#![doc = include_str!("../README.md")]
#![cfg_attr(
feature = "document-features",
doc = document_features::document_features!()
)]
#![cfg_attr(not(any(test, feature = "std")), no_std)]
extern crate alloc;
use bevy_app::prelude::*;
use bevy_ecs::{
prelude::*,
schedule::{InternedScheduleLabel, ScheduleLabel},
};
use bevy_platform::prelude::*;
pub mod graph;
pub mod signal;
pub mod signal_map;
pub mod signal_vec;
pub mod utils;
cfg_if::cfg_if! {
if #[cfg(feature = "builder")] {
pub mod builder;
#[doc(inline)]
pub use builder::Builder;
}
}
pub struct JonmoPlugin {
schedules: Vec<InternedScheduleLabel>,
registration_recursion_limit: usize,
on_recursion_limit_exceeded: graph::RecursionLimitBehavior,
}
impl Default for JonmoPlugin {
fn default() -> Self {
Self::new::<Last>()
}
}
impl JonmoPlugin {
pub fn new<S: ScheduleLabel + Default>() -> Self {
Self {
schedules: vec![S::default().intern()],
registration_recursion_limit: graph::DEFAULT_REGISTRATION_RECURSION_LIMIT,
on_recursion_limit_exceeded: graph::RecursionLimitBehavior::default(),
}
}
pub fn with_schedule<S: ScheduleLabel + Default>(mut self) -> Self {
let interned = S::default().intern();
if !self.schedules.contains(&interned) {
self.schedules.push(interned);
}
self
}
pub fn registration_recursion_limit(mut self, limit: usize) -> Self {
self.registration_recursion_limit = limit;
self
}
pub fn on_recursion_limit_exceeded(mut self, behavior: graph::RecursionLimitBehavior) -> Self {
self.on_recursion_limit_exceeded = behavior;
self
}
}
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct SignalProcessing;
impl Plugin for JonmoPlugin {
fn build(&self, app: &mut App) {
let default_schedule = self.schedules[0];
app.insert_resource(graph::SignalGraphState::with_options(
default_schedule,
self.registration_recursion_limit,
self.on_recursion_limit_exceeded,
));
let mut state = app.world_mut().resource_mut::<graph::SignalGraphState>();
for &schedule in &self.schedules {
state.register_schedule(schedule);
}
for &schedule in &self.schedules {
app.add_systems(
schedule,
(
(
signal_vec::trigger_replays::<signal_vec::VecReplayTrigger>,
signal_vec::trigger_replays::<signal_map::MapReplayTrigger>,
),
graph::process_signal_graph_for_schedule(schedule),
(
graph::despawn_stale_signals,
signal_vec::despawn_stale_mutable_vecs,
signal_map::despawn_stale_mutable_btree_maps,
),
)
.chain()
.in_set(SignalProcessing),
);
}
app.add_systems(Last, graph::clear_signal_inputs.after(SignalProcessing));
}
}
pub mod prelude {
#[cfg(feature = "builder")]
pub use crate::builder::{SignalMapTaskExt, SignalTask, SignalTaskExt, SignalVecTaskExt};
pub use crate::{
JonmoPlugin,
graph::SignalHandles,
signal::{self, BoxedSignal, IntoSignalEither, Signal, SignalEither, SignalExt},
signal_map::{
IntoSignalMapEither, MutableBTreeMap, MutableBTreeMapData, SignalMap, SignalMapEither, SignalMapExt,
},
signal_vec::{IntoSignalVecEither, MutableVec, MutableVecData, SignalVec, SignalVecEither, SignalVecExt},
utils::{LazyEntity, clone, deref_cloned, deref_copied},
};
#[doc(no_inline)]
pub use apply::{Also, Apply};
}