use std::any::Any; use std::marker::PhantomData; use std::sync::{Arc, Weak}; use crate::component::{Component, Sequence as ComponentSequence}; use crate::lock::{Lock, WriteGuard}; use crate::system::{NoInitParamFlag, Param as SystemParam, System}; use crate::{ActionQueue, WorldData}; /// Used to to queue up actions for a [`World`] to perform. #[derive(Debug)] pub struct Actions<'world> { action_queue: WriteGuard<'world, ActionQueue>, action_queue_weak: Weak>, } impl<'world> Actions<'world> { /// Adds a spawning a new entity to the action queue. pub fn spawn(&mut self, components: Comps) { self.action_queue.push(Action::Spawn(components.into_vec())); } /// Adds stopping the loop in [`Engine::event_loop`] at the next opportune time to the /// action queue. pub fn stop(&mut self) { self.action_queue.push(Action::Stop); } /// Returns a struct which holds a weak reference to the [`World`] that `Actions` /// references and that can be used to aquire a new `Actions` instance if the /// referenced [`World`] is still alive. #[must_use] pub fn to_weak_ref(&self) -> WeakRef { WeakRef { action_queue: self.action_queue_weak.clone(), } } fn new(action_queue: &'world Arc>) -> Self { Self { action_queue: action_queue .write_nonblock() .expect("Failed to aquire read-write action queue lock"), action_queue_weak: Arc::downgrade(action_queue), } } } unsafe impl<'world> SystemParam<'world> for Actions<'world> { type Flags = NoInitParamFlag; type Input = (); fn initialize( _system: &mut impl System<'world, SystemImpl>, _input: Self::Input, ) { } fn new( _system: &'world impl System<'world, SystemImpl>, world_data: &'world WorldData, ) -> Self { Self::new(&world_data.action_queue) } fn is_compatible>() -> bool { let other_comparable = Other::get_comparable(); other_comparable.downcast_ref::().is_none() } fn get_comparable() -> Box { Box::new(()) } } #[derive(Debug, Clone)] pub struct WeakRef { action_queue: Weak>, } impl WeakRef { /// Returns a struct which can be used to retrieve a [`Actions`]. /// /// Returns [`None`] if the referenced [`World`] has been dropped. #[must_use] pub fn access(&self) -> Option> { Some(Ref { action_queue: self.action_queue.upgrade()?, _pd: PhantomData, }) } } /// Intermediate between [`Actions`] and [`WeakRef`]. Contains a strong reference to /// a world which is not allowed direct access to. #[derive(Debug, Clone)] pub struct Ref<'weak_ref> { action_queue: Arc>, _pd: PhantomData<&'weak_ref ()>, } impl<'weak_ref> Ref<'weak_ref> { #[must_use] pub fn to_actions(&self) -> Actions<'_> { Actions::new(&self.action_queue) } } /// A action for a [`System`] to perform. #[derive(Debug)] pub(crate) enum Action { Spawn(Vec>), Stop, } struct Comparable;