1use bevy_app::{App, Plugin};
4use bevy_ecs::prelude::*;
5use bevy_ecs::system::IntoObserverSystem;
6use std::marker::PhantomData;
7use std::sync::Mutex;
8
9use crate::Static;
10
11pub trait SingleEvent: Static {}
28
29pub trait AddSingleObserver {
31 fn has_single_observer<E: SingleEvent>(&self) -> bool;
33
34 fn add_single_observer<E: SingleEvent, B: Bundle, M>(
39 self,
40 observer: impl IntoSingleObserverSystem<E, B, M>,
41 ) -> Self;
42}
43
44impl AddSingleObserver for &mut App {
45 fn has_single_observer<E: SingleEvent>(&self) -> bool {
46 self.is_plugin_added::<SingleEventObserverPlugin<E>>()
47 }
48
49 fn add_single_observer<E: SingleEvent, B: Bundle, M>(
50 self,
51 observer: impl IntoSingleObserverSystem<E, B, M>,
52 ) -> Self {
53 if !self.is_plugin_added::<SingleEventObserverPlugin<E>>() {
54 self.add_plugins(SingleEventObserverPlugin::<E>::new());
55 } else {
56 panic!(
57 "a single observer is already registered for event: {}",
58 std::any::type_name::<E>()
59 );
60 }
61
62 self.add_observer(observer)
63 }
64}
65
66pub trait TriggerSingle {
68 fn trigger_single<E: SingleEvent>(self, event: E);
72}
73
74impl TriggerSingle for &mut Commands<'_, '_> {
75 fn trigger_single<E: SingleEvent>(self, event: E) {
76 self.trigger(SingleEventWrapper::new(event));
77 }
78}
79
80impl TriggerSingle for &mut World {
81 fn trigger_single<E: SingleEvent>(self, event: E) {
82 self.trigger(SingleEventWrapper::new(event));
83 }
84}
85
86#[doc(hidden)]
87pub trait IntoSingleObserverSystem<E: SingleEvent, B: Bundle, M>:
88 IntoObserverSystem<SingleEventWrapper<E>, B, M>
89{
90}
91
92impl<E: SingleEvent, B: Bundle, M, S> IntoSingleObserverSystem<E, B, M> for S where
93 S: IntoObserverSystem<SingleEventWrapper<E>, B, M>
94{
95}
96
97#[derive(Event)]
101pub struct SingleEventWrapper<E: SingleEvent>(Mutex<Option<E>>);
102
103impl<E: SingleEvent> SingleEventWrapper<E> {
104 fn new(event: E) -> Self {
105 Self(Mutex::new(Some(event)))
106 }
107
108 pub fn consume(&self) -> Option<E> {
112 self.0.lock().unwrap().take()
113 }
114}
115
116pub type OnSingle<'w, 't, E, B = ()> = On<'w, 't, SingleEventWrapper<E>, B>;
120
121#[doc(hidden)]
122pub struct SingleEventObserverPlugin<E: SingleEvent>(PhantomData<E>);
123
124impl<E: SingleEvent> SingleEventObserverPlugin<E> {
125 fn new() -> Self {
126 Self(PhantomData)
127 }
128}
129
130impl<E: SingleEvent> Plugin for SingleEventObserverPlugin<E> {
131 fn build(&self, _: &mut App) {}
132}