use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; pub use bevy_ecs_macros::{ScheduleLabel, SystemSet}; use bevy_utils::define_boxed_label; use bevy_utils::label::DynHash; use crate::system::{ ExclusiveSystemParamFunction, IsExclusiveFunctionSystem, IsFunctionSystem, SystemParamFunction, }; define_boxed_label!(ScheduleLabel); pub type BoxedSystemSet = Box; pub type BoxedScheduleLabel = Box; /// Types that identify logical groups of systems. pub trait SystemSet: DynHash + Debug + Send + Sync + 'static { /// Returns `true` if this system set is a [`SystemTypeSet`]. fn is_system_type(&self) -> bool { false } /// Returns `true` if this set is a "base system set". Systems /// can only belong to one base set at a time. Systems and Sets /// can only be added to base sets using specialized `in_base_set` /// APIs. This enables "mutually exclusive" behaviors. It also /// enables schedules to have a "default base set", which can be used /// to apply default configuration to systems. fn is_base(&self) -> bool { false } /// Creates a boxed clone of the label corresponding to this system set. fn dyn_clone(&self) -> Box; } impl PartialEq for dyn SystemSet { fn eq(&self, other: &Self) -> bool { self.dyn_eq(other.as_dyn_eq()) } } impl Eq for dyn SystemSet {} impl Hash for dyn SystemSet { fn hash(&self, state: &mut H) { self.dyn_hash(state); } } impl Clone for Box { fn clone(&self) -> Self { self.dyn_clone() } } /// A [`SystemSet`] grouping instances of the same function. /// /// This kind of set is automatically populated and thus has some special rules: /// - You cannot manually add members. /// - You cannot configure them. /// - You cannot order something relative to one if it has more than one member. pub struct SystemTypeSet(PhantomData T>); impl SystemTypeSet { pub(crate) fn new() -> Self { Self(PhantomData) } } impl Debug for SystemTypeSet { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("SystemTypeSet") .field(&std::any::type_name::()) .finish() } } impl Hash for SystemTypeSet { fn hash(&self, _state: &mut H) { // all systems of a given type are the same } } impl Clone for SystemTypeSet { fn clone(&self) -> Self { Self(PhantomData) } } impl Copy for SystemTypeSet {} impl PartialEq for SystemTypeSet { #[inline] fn eq(&self, _other: &Self) -> bool { // all systems of a given type are the same true } } impl Eq for SystemTypeSet {} impl SystemSet for SystemTypeSet { fn is_system_type(&self) -> bool { true } fn dyn_clone(&self) -> Box { Box::new(*self) } } /// Types that can be converted into a [`SystemSet`]. pub trait IntoSystemSet: Sized { type Set: SystemSet; fn into_system_set(self) -> Self::Set; } // systems sets impl IntoSystemSet<()> for S { type Set = Self; #[inline] fn into_system_set(self) -> Self::Set { self } } // systems impl IntoSystemSet<(IsFunctionSystem, Marker)> for F where F: SystemParamFunction, { type Set = SystemTypeSet; #[inline] fn into_system_set(self) -> Self::Set { SystemTypeSet::new() } } // exclusive systems impl IntoSystemSet<(IsExclusiveFunctionSystem, Marker)> for F where F: ExclusiveSystemParamFunction, { type Set = SystemTypeSet; #[inline] fn into_system_set(self) -> Self::Set { SystemTypeSet::new() } }