moonshine_behavior/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4/// Common elements for [`Behavior`] query and management.
5pub mod prelude {
6    pub use crate::{Behavior, BehaviorIndex, BehaviorMut, BehaviorRef};
7    pub use moonshine_kind::{Instance, InstanceCommands};
8
9    pub use crate::transition::{
10        transition, Interrupt, Interruption, Next, Previous, Transition, TransitionSequence,
11    };
12
13    pub use crate::events::{OnActivate, OnPause, OnResume, OnStart, OnStop};
14    pub use crate::plugin::BehaviorPlugin;
15
16    pub use crate::match_next;
17}
18
19pub mod events;
20pub mod transition;
21
22mod plugin;
23
24#[cfg(test)]
25mod tests;
26
27use std::fmt::Debug;
28use std::mem::{replace, swap};
29use std::ops::{Deref, DerefMut, Index, IndexMut};
30
31use bevy_derive::{Deref, DerefMut};
32use bevy_ecs::change_detection::MaybeLocation;
33use bevy_ecs::component::{Components, Mutable, Tick};
34use bevy_ecs::{prelude::*, query::QueryData};
35use bevy_log::prelude::*;
36use bevy_reflect::prelude::*;
37use moonshine_kind::prelude::*;
38
39pub use plugin::BehaviorPlugin;
40
41use crate::events::{OnActivate, OnError, OnPause, OnResume, OnStart, OnStop};
42
43use self::transition::*;
44
45/// Any [`Component`] which may be used as a [`Behavior`].
46///
47/// # Usage
48///
49/// A [`Behavior`] is a component which represents a set of finite states. This makes `enum` the ideal data structure
50/// to implement this trait, however this is not a strict requirement.
51pub trait Behavior: Component<Mutability = Mutable> + Debug + Sized {
52    /// Called when an interrupt is requested.
53    ///
54    /// If this returns `true`, the current behavior will stop to allow the next behavior to start.
55    /// The initial behavior is never allowed to yield.
56    fn filter_yield(&self, next: &Self) -> bool {
57        match_next! {
58            self => next,
59            _ => _,
60        }
61    }
62
63    /// Called before a new behavior is started.
64    ///
65    /// If this returns `false`, the transition fails.
66    /// See [`Error`](crate::events::BehaviorEvent) for details on how to handle transition failures.
67    fn filter_next(&self, next: &Self) -> bool {
68        match_next! {
69            self => next,
70            _ => _,
71        }
72    }
73
74    /// Called after a behavior is paused.
75    ///
76    /// If this returns `false`, the paused behavior will be stopped immediatedly and discarded.
77    /// No [`Pause`](crate::events::BehaviorEvent) event will be sent in this case.
78    fn is_resumable(&self) -> bool {
79        match self {
80            _ => true,
81        }
82    }
83
84    /// Called during [`transition`](transition::transition) just after the behavior is started.
85    fn on_start(&self, _previous: Option<&Self>, _commands: InstanceCommands<Self>) {}
86
87    /// Called during [`transition`](transition::transition) just after the behavior is paused.
88    fn on_pause(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
89
90    /// Called during [`transition`](transition::transition) just after the behavior is resumed.
91    fn on_resume(&self, _previous: &Self, _commands: InstanceCommands<Self>) {}
92
93    /// Called during [`transition`](transition::transition) just after the behavior is stopped.
94    fn on_stop(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
95
96    /// Called during [`transition`](transition::transition) just after the behavior is started *or* resumed.
97    fn on_activate(&self, _previous: Option<&Self>, _commands: InstanceCommands<Self>) {}
98
99    /// Called during [`transition`](transition::transition) just after the behavior is paused *or* stopped.
100    fn on_suspend(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
101}
102
103#[doc(hidden)]
104trait BehaviorHooks: Behavior {
105    fn invoke_start(&self, previous: Option<&Self>, mut commands: InstanceCommands<Self>) {
106        self.on_start(previous, commands.reborrow());
107        self.on_activate(previous, commands);
108    }
109
110    fn invoke_pause(&self, current: &Self, mut commands: InstanceCommands<Self>) {
111        self.on_suspend(current, commands.reborrow());
112        self.on_pause(current, commands);
113    }
114
115    fn invoke_resume(&self, previous: &Self, mut commands: InstanceCommands<Self>) {
116        self.on_resume(previous, commands.reborrow());
117        self.on_activate(Some(previous), commands);
118    }
119
120    fn invoke_stop(&self, current: &Self, mut commands: InstanceCommands<Self>) {
121        self.on_suspend(current, commands.reborrow());
122        self.on_stop(current, commands);
123    }
124}
125
126impl<T: Behavior> BehaviorHooks for T {}
127
128/// Query data for a [`Behavior`].
129///
130/// # Usage
131///
132/// This provides a read-only reference to the current behavior state and all previous states in the stack.
133///
134/// Additionally, it provides methods to check for pending transitions ([`has_transition`](BehaviorRefItem::has_transition)),
135/// active transition sequences ([`has_sequence`](BehaviorRefItem::has_sequence)) and the current
136/// behavior index ([`index`](BehaviorRefItem::index)).
137#[derive(QueryData)]
138pub struct BehaviorRef<T: Behavior> {
139    current: Ref<'static, T>,
140    memory: &'static Memory<T>,
141    transition: &'static Transition<T>,
142    sequence: Has<TransitionSequence<T>>,
143}
144
145impl<T: Behavior> BehaviorRef<T> {
146    /// Creates a new [`BehaviorRef`] item from an [`EntityRef`].
147    pub fn from_entity(entity: EntityRef) -> Option<BehaviorRefItem<T>> {
148        Some(BehaviorRefItem {
149            current: entity.get_ref::<T>()?,
150            memory: entity.get::<Memory<T>>()?,
151            transition: entity.get::<Transition<T>>()?,
152            sequence: entity.contains::<TransitionSequence<T>>(),
153        })
154    }
155}
156
157impl<T: Behavior> BehaviorRefItem<'_, T> {
158    /// Returns the current [`Behavior`] state.
159    pub fn current(&self) -> &T {
160        &self.current
161    }
162
163    /// Returns the [`BehaviorIndex`] associated with the current [`Behavior`] state.
164    pub fn index(&self) -> BehaviorIndex {
165        BehaviorIndex(self.memory.len())
166    }
167
168    /// Returns `true` if the given [`BehaviorIndex`] matches a state in this [`Behavior`] stack.
169    pub fn has_index(&self, index: BehaviorIndex) -> bool {
170        index <= self.index()
171    }
172
173    /// Returns the previous [`Behavior`] state in the stack.
174    ///
175    /// # Usage
176    ///
177    /// Note that this is **NOT** the previously active state.
178    /// Instead, this is the previous state which was active before the current one was started.
179    ///
180    /// To access the previously active state, handle [`Stop`](crate::events::BehaviorEvent::Stop) instead.
181    pub fn previous(&self) -> Option<&T> {
182        self.memory.last()
183    }
184
185    /// Returns an iterator over all [`Behavior`] states in the stack, including the current one.
186    ///
187    /// The iterator is ordered from the initial behavior (index = 0) to the current one.
188    pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
189        self.memory.iter().chain(std::iter::once(self.current()))
190    }
191
192    /// Returns `true` if there is any pending [`Transition`] for this [`Behavior`].
193    ///
194    /// # Usage
195    ///
196    /// By design, only one transition is allowed per [`transition`](crate::transition::transition) cycle.
197    ///
198    /// The only exception to this rule is if the behavior is interrupted or reset where multiple states
199    /// may be stopped within a single cycle.
200    ///
201    /// If a transition is requested while another is pending, it would be overriden.
202    /// The transition helper methods [`start`](BehaviorMutItem::start), [`interrupt_start`](BehaviorMutItem::interrupt_start),
203    /// [`stop`](BehaviorMutItem::stop) and [`reset`](BehaviorMutItem::reset) all trigger a warning in this case.
204    ///
205    /// Because of this, this method is useful to avoid unintentional transition overrides.
206    pub fn has_transition(&self) -> bool {
207        !self.transition.is_none()
208    }
209
210    /// Returns `true` if there is any [`TransitionSequence`] running on this [`Behavior`].
211    ///
212    /// This is useful to allow transition sequences to finish before starting a new behavior.
213    pub fn has_sequence(&self) -> bool {
214        self.sequence
215    }
216}
217
218impl<T: Behavior> Deref for BehaviorRefItem<'_, T> {
219    type Target = T;
220
221    fn deref(&self) -> &Self::Target {
222        self.current()
223    }
224}
225
226impl<T: Behavior> AsRef<T> for BehaviorRefItem<'_, T> {
227    fn as_ref(&self) -> &T {
228        &self.current
229    }
230}
231
232impl<T: Behavior> DetectChanges for BehaviorRefItem<'_, T> {
233    fn is_added(&self) -> bool {
234        self.current.is_added()
235    }
236
237    fn is_changed(&self) -> bool {
238        self.current.is_changed()
239    }
240
241    fn last_changed(&self) -> Tick {
242        self.current.last_changed()
243    }
244
245    fn added(&self) -> Tick {
246        self.current.added()
247    }
248
249    fn changed_by(&self) -> MaybeLocation {
250        self.current.changed_by()
251    }
252}
253
254impl<T: Behavior> Index<BehaviorIndex> for BehaviorRefItem<'_, T> {
255    type Output = T;
256
257    fn index(&self, BehaviorIndex(index): BehaviorIndex) -> &Self::Output {
258        if index == self.memory.stack.len() {
259            self.current()
260        } else {
261            &self.memory[index]
262        }
263    }
264}
265
266/// Query data for a [`Behavior`] with mutable access.
267///
268/// # Usage
269///
270/// This provides a mutable reference to the current behavior state and all previous states in the stack.
271///
272/// See [`BehaviorRef`] for more details.
273#[derive(QueryData)]
274#[query_data(mutable)]
275pub struct BehaviorMut<T: Behavior> {
276    current: Mut<'static, T>,
277    memory: &'static mut Memory<T>,
278    transition: &'static mut Transition<T>,
279    sequence: Has<TransitionSequence<T>>,
280}
281
282impl<T: Behavior> BehaviorMutReadOnlyItem<'_, T> {
283    /// See [`BehaviorRefItem::current`].
284    pub fn current(&self) -> &T {
285        &self.current
286    }
287
288    /// See [`BehaviorRefItem::previous`].
289    pub fn previous(&self) -> Option<&T> {
290        self.memory.last()
291    }
292
293    /// See [`BehaviorRefItem::iter`].
294    pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
295        self.memory.iter().chain(std::iter::once(self.current()))
296    }
297
298    /// See [`BehaviorRefItem::index`].
299    pub fn index(&self) -> BehaviorIndex {
300        BehaviorIndex(self.memory.len())
301    }
302
303    /// See [`BehaviorRefItem::has_transition`].
304    pub fn has_transition(&self) -> bool {
305        !self.transition.is_none()
306    }
307
308    /// See [`BehaviorRefItem::has_sequence`].
309    pub fn has_sequence(&self) -> bool {
310        self.sequence
311    }
312}
313
314impl<T: Behavior> Deref for BehaviorMutReadOnlyItem<'_, T> {
315    type Target = T;
316
317    fn deref(&self) -> &Self::Target {
318        self.current()
319    }
320}
321
322impl<T: Behavior> AsRef<T> for BehaviorMutReadOnlyItem<'_, T> {
323    fn as_ref(&self) -> &T {
324        self.current.as_ref()
325    }
326}
327
328impl<T: Behavior> DetectChanges for BehaviorMutReadOnlyItem<'_, T> {
329    fn is_added(&self) -> bool {
330        self.current.is_added()
331    }
332
333    fn is_changed(&self) -> bool {
334        self.current.is_changed()
335    }
336
337    fn last_changed(&self) -> Tick {
338        self.current.last_changed()
339    }
340
341    fn added(&self) -> Tick {
342        self.current.added()
343    }
344
345    fn changed_by(&self) -> MaybeLocation {
346        self.current.changed_by()
347    }
348}
349
350impl<T: Behavior> Index<BehaviorIndex> for BehaviorMutReadOnlyItem<'_, T> {
351    type Output = T;
352
353    fn index(&self, BehaviorIndex(index): BehaviorIndex) -> &Self::Output {
354        if index == self.memory.stack.len() {
355            self.current()
356        } else {
357            &self.memory[index]
358        }
359    }
360}
361
362impl<T: Behavior> BehaviorMutItem<'_, T> {
363    /// Returns the current [`Behavior`] state.
364    pub fn current(&self) -> &T {
365        &self.current
366    }
367
368    /// Returns the current [`Behavior`] state as a mutable.
369    pub fn current_mut(&mut self) -> &mut T {
370        self.current.as_mut()
371    }
372
373    /// See [`BehaviorRefItem::previous`].
374    pub fn previous(&self) -> Option<&T> {
375        self.memory.last()
376    }
377
378    /// Returns the previous [`Behavior`] state as a mutable.
379    ///
380    /// See [`BehaviorRefItem::previous`] for more details.
381    pub fn previous_mut(&mut self) -> Option<&mut T> {
382        self.memory.last_mut()
383    }
384
385    /// See [`BehaviorRefItem::iter`].
386    pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
387        self.memory.iter().chain(std::iter::once(self.current()))
388    }
389
390    /// Returns a mutable iterator over all [`Behavior`] states in the stack, including the current one.
391    ///
392    /// See [`BehaviorRefItem::iter`] for more details.
393    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> + '_ {
394        self.memory
395            .iter_mut()
396            .chain(std::iter::once(self.current.as_mut()))
397    }
398
399    /// See [`BehaviorRefItem::index`].
400    pub fn index(&self) -> BehaviorIndex {
401        BehaviorIndex(self.memory.len())
402    }
403
404    /// See [`BehaviorRefItem::has_index`].
405    pub fn has_index(&self, index: BehaviorIndex) -> bool {
406        index <= self.index()
407    }
408
409    /// See [`BehaviorRefItem::has_transition`].
410    pub fn has_transition(&self) -> bool {
411        !self.transition.is_none()
412    }
413
414    /// See [`BehaviorRefItem::has_sequence`].
415    pub fn has_sequence(&self) -> bool {
416        self.sequence
417    }
418
419    /// Starts the given `next` behavior.
420    ///
421    /// This operation pushes the current behavior onto the stack and inserts the new behavior.
422    ///
423    /// Note that this will fail if the current behavior rejects `next` through [`Behavior::filter_next`].
424    /// See [`Error`](crate::events::BehaviorEvent) for details on how to handle transition failures.
425    #[track_caller]
426    pub fn start(&mut self, next: T) {
427        self.start_with_caller(next, MaybeLocation::caller());
428    }
429
430    /// Attempts to start the given `next` behavior if there are no pending transitions and the
431    /// current behavior allows it.
432    ///
433    /// Note that it's still possible for the transition to fail if the current behavior mutates
434    /// in such a way as to no longer allow the transition between the time this function is called
435    /// and when the [`transition`](crate::transition::transition) system runs.
436    ///
437    /// Do **NOT** use this method to react to transition failures.
438    /// See [`Error`](crate::events::BehaviorEvent) for details on how to correctly handle transition failures.
439    ///
440    /// # Usage
441    ///
442    /// This is similar to [`start`](BehaviorMutItem::start) but will return an error containing
443    /// the given `next` behavior if it fails.
444    ///
445    /// This is useful for fire-and-forget transitions where you don't want to override a
446    /// pending transition or may expect a transition failure.
447    ///
448    /// If multiple systems call this method before transition, only the first one will succeed.
449    #[track_caller]
450    pub fn try_start(&mut self, next: T) -> Result<(), T> {
451        if self.has_transition() || !self.filter_next(&next) {
452            return Err(next);
453        }
454
455        self.start_with_caller(next, MaybeLocation::caller());
456        Ok(())
457    }
458
459    fn start_with_caller(&mut self, next: T, caller: MaybeLocation) {
460        self.set_transition(Next(next), caller);
461    }
462
463    /// Interrupts the current behavior and starts the given `next` behavior.
464    ///
465    /// This operation stops all behaviors which yield to the new behavior and pushes it onto the stack.
466    /// See [`Behavior::filter_yield`] for details on how to define how states yield to each other.
467    ///
468    /// This also removes any remaining [`TransitionSequence`] steps.
469    ///
470    /// The initial behavior is never allowed to yield.
471    ///
472    /// Note that this will fail if the first non-yielding behavior rejects `next` through [`Behavior::filter_next`].
473    /// See [`Error`](crate::events::BehaviorEvent) for details on how to handle transition failures.
474    #[track_caller]
475    pub fn interrupt_start(&mut self, next: T) {
476        self.interrupt_start_with_caller(next, MaybeLocation::caller());
477    }
478
479    /// Attempts to interrupt the current behavior and start the given `next` behavior.
480    ///
481    /// This is similar to [`interrupt_start`](BehaviorMutItem::interrupt_start) but will fail if there is a pending transition.
482    #[track_caller]
483    pub fn try_interrupt_start(&mut self, next: T) -> Result<(), T> {
484        if self.has_transition() {
485            return Err(next);
486        }
487
488        self.interrupt_start_with_caller(next, MaybeLocation::caller());
489        Ok(())
490    }
491
492    fn interrupt_start_with_caller(&mut self, next: T, caller: MaybeLocation) {
493        self.set_transition(Interrupt(Interruption::Start(next)), caller);
494    }
495
496    /// Stops all behaviors above and including the given [`BehaviorIndex`].
497    ///
498    /// This also removes any remaining [`TransitionSequence`] steps.
499    ///
500    /// The initial behavior is never allowed to yield.
501    #[track_caller]
502    pub fn interrupt_stop(&mut self, index: BehaviorIndex) {
503        self.interrupt_resume_with_caller(index.previous(), MaybeLocation::caller());
504    }
505
506    /// Attempts to stop all behaviors above and including the given [`BehaviorIndex`].
507    ///
508    /// This is similar to [`interrupt_stop`](BehaviorMutItem::interrupt_stop) but will fail if:
509    /// - There is a pending transition
510    /// - The given `index` is the initial behavior
511    /// - The given `index` is not in the stack
512    #[track_caller]
513    pub fn try_interrupt_stop(&mut self, index: BehaviorIndex) -> Result<(), BehaviorIndex> {
514        if self.has_transition() || !self.has_index(index) || index == BehaviorIndex::initial() {
515            return Err(index);
516        }
517
518        self.interrupt_resume_with_caller(index.previous(), MaybeLocation::caller());
519        Ok(())
520    }
521
522    /// Stops all behaviors above the given [`BehaviorIndex`] and resume the behavior at that index.
523    ///
524    /// This also removes any remaining [`TransitionSequence`] steps.
525    #[track_caller]
526    pub fn interrupt_resume(&mut self, index: BehaviorIndex) {
527        self.interrupt_resume_with_caller(index, MaybeLocation::caller());
528    }
529
530    /// Attempts to stop all behaviors above the given [`BehaviorIndex`] and resume the behavior at that index.
531    ///
532    /// This is similar to [`interrupt_resume`](BehaviorMutItem::interrupt_resume) but will fail if:
533    /// - There is a pending transition
534    /// - The given `index` is not in the stack
535    #[track_caller]
536    pub fn try_interrupt_resume(&mut self, index: BehaviorIndex) -> Result<(), BehaviorIndex> {
537        if self.has_transition() || !self.has_index(index) {
538            return Err(index);
539        }
540
541        self.interrupt_resume_with_caller(index, MaybeLocation::caller());
542        Ok(())
543    }
544
545    fn interrupt_resume_with_caller(&mut self, index: BehaviorIndex, caller: MaybeLocation) {
546        self.set_transition(Interrupt(Interruption::Resume(index)), caller);
547    }
548
549    /// Stops the current behavior.
550    ///
551    /// This operation pops the current behavior off the stack and resumes the previous behavior.
552    ///
553    /// Note that this will fail if the current behavior is the initial behavior.
554    /// See [`Error`](crate::events::BehaviorEvent) for details on how to handle transition failures.
555    #[track_caller]
556    pub fn stop(&mut self) {
557        self.stop_with_caller(MaybeLocation::caller());
558    }
559
560    /// Attempts to stop the current behavior.
561    ///
562    /// This is similar to [`stop`](BehaviorMutItem::stop) but will fail if:
563    /// - There is a pending transition
564    /// - The current behavior is the initial behavior
565    #[track_caller]
566    pub fn try_stop(&mut self) -> bool {
567        if self.has_transition() || self.memory.is_empty() {
568            return false;
569        }
570
571        self.stop_with_caller(MaybeLocation::caller());
572        true
573    }
574
575    fn stop_with_caller(&mut self, caller: MaybeLocation) {
576        self.set_transition(Previous, caller);
577    }
578
579    /// Stops the current and all previous behaviors and resumes the initial behavior.
580    ///
581    /// This operation clears the stack and resumes the initial behavior. It can never fail.
582    /// If the stack is empty (i.e. initial behavior), it does nothing.
583    #[track_caller]
584    pub fn reset(&mut self) {
585        self.interrupt_resume_with_caller(BehaviorIndex::initial(), MaybeLocation::caller());
586    }
587
588    /// Attempts to reset the current behavior.
589    ///
590    /// This is similar to [`reset`](BehaviorMutItem::reset) but will fail if there is a pending transition.
591    #[track_caller]
592    pub fn try_reset(&mut self) -> bool {
593        if self.has_transition() {
594            return false;
595        }
596
597        self.interrupt_resume_with_caller(BehaviorIndex::initial(), MaybeLocation::caller());
598        true
599    }
600
601    fn set_transition(&mut self, transition: Transition<T>, caller: MaybeLocation) {
602        let previous = replace(self.transition.as_mut(), transition);
603        if !previous.is_none() {
604            warn!(
605                "transition override ({caller})): {previous:?} -> {:?}",
606                *self.transition
607            );
608        }
609    }
610
611    fn push(
612        &mut self,
613        instance: Instance<T>,
614        mut next: T,
615        components: &Components,
616        commands: &mut Commands,
617    ) -> bool {
618        let id = components.valid_component_id::<T>().unwrap();
619
620        if self.filter_next(&next) {
621            let previous = {
622                swap(self.current.as_mut(), &mut next);
623                next
624            };
625            self.invoke_start(Some(&previous), commands.instance(instance));
626            let index = self.memory.len();
627            if previous.is_resumable() {
628                let next_index = index + 1;
629                debug!(
630                    "{instance:?}: {previous:?} (#{index}) -> {:?} (#{next_index})",
631                    *self.current
632                );
633
634                previous.invoke_pause(&self.current, commands.instance(instance));
635
636                commands.trigger_targets(
637                    OnPause {
638                        index: BehaviorIndex(index),
639                    },
640                    (*instance, id),
641                );
642                commands.trigger_targets(
643                    OnStart {
644                        index: BehaviorIndex(next_index),
645                    },
646                    (*instance, id),
647                );
648                commands.trigger_targets(
649                    OnActivate {
650                        index: BehaviorIndex(next_index),
651                        resume: false,
652                    },
653                    (*instance, id),
654                );
655
656                self.memory.push(previous);
657            } else {
658                debug!(
659                    "{instance:?}: {previous:?} (#{index}) -> {:?} (#{index})",
660                    *self.current
661                );
662
663                previous.invoke_stop(&self.current, commands.instance(instance));
664
665                commands.trigger_targets(OnStop { behavior: previous }, (*instance, id));
666                commands.trigger_targets(
667                    OnStart {
668                        index: BehaviorIndex(index),
669                    },
670                    (*instance, id),
671                );
672                commands.trigger_targets(
673                    OnActivate {
674                        index: BehaviorIndex(index),
675                        resume: false,
676                    },
677                    (*instance, id),
678                );
679            }
680            true
681        } else {
682            warn!(
683                "{instance:?}: transition {:?} -> {next:?} is not allowed",
684                *self.current
685            );
686
687            commands.trigger_targets(
688                OnError(TransitionError::RejectedNext(next)),
689                (*instance, id),
690            );
691            false
692        }
693    }
694
695    fn interrupt(
696        &mut self,
697        instance: Instance<T>,
698        next: T,
699        components: &Components,
700        commands: &mut Commands,
701    ) {
702        let id = components.valid_component_id::<T>().unwrap();
703
704        while self.filter_yield(&next) && !self.memory.is_empty() {
705            let index = self.memory.len();
706            if let Some(mut next) = self.memory.pop() {
707                let previous = {
708                    swap(self.current.as_mut(), &mut next);
709                    next
710                };
711                debug!("{instance:?}: {:?} (#{index}) -> Interrupt", previous);
712                previous.invoke_stop(&self.current, commands.instance(instance));
713                commands.trigger_targets(OnStop { behavior: previous }, (*instance, id));
714            }
715        }
716
717        self.push(instance, next, components, commands);
718    }
719
720    fn pop(
721        &mut self,
722        instance: Instance<T>,
723        components: &Components,
724        commands: &mut Commands,
725    ) -> bool {
726        let id = components.valid_component_id::<T>().unwrap();
727        let index = self.memory.len();
728        if let Some(mut next) = self.memory.pop() {
729            let next_index = self.memory.len();
730            debug!(
731                "{instance:?}: {:?} (#{index}) -> {next:?} (#{next_index})",
732                *self.current
733            );
734            let previous = {
735                swap(self.current.as_mut(), &mut next);
736                next
737            };
738            self.invoke_resume(&previous, commands.instance(instance));
739            previous.invoke_stop(&self.current, commands.instance(instance));
740            commands.trigger_targets(
741                OnResume {
742                    index: BehaviorIndex(next_index),
743                },
744                (*instance, id),
745            );
746            commands.trigger_targets(
747                OnActivate {
748                    index: BehaviorIndex(next_index),
749                    resume: true,
750                },
751                (*instance, id),
752            );
753            commands.trigger_targets(OnStop { behavior: previous }, (*instance, id));
754            true
755        } else {
756            warn!(
757                "{instance:?}: transition {:?} -> None is not allowed",
758                *self.current
759            );
760            commands.trigger_targets(OnError::<T>(TransitionError::NoPrevious), (*instance, id));
761            false
762        }
763    }
764
765    fn clear(
766        &mut self,
767        instance: Instance<T>,
768        index: BehaviorIndex,
769        components: &Components,
770        commands: &mut Commands,
771    ) {
772        let id = components.valid_component_id::<T>().unwrap();
773
774        // Stop all states except the one above the given index
775        while self.index() > index.next() {
776            let index = self.memory.len();
777            let previous = self.memory.pop().unwrap();
778            let next = self.memory.last().unwrap();
779            debug!("{instance:?}: {:?} (#{index}) -> Interrupt", previous);
780            previous.invoke_stop(next, commands.instance(instance));
781            commands.trigger_targets(OnStop { behavior: previous }, (*instance, id));
782        }
783
784        // Pop the state above the given index
785        self.pop(instance, components, commands);
786    }
787}
788
789impl<T: Behavior> Deref for BehaviorMutItem<'_, T> {
790    type Target = T;
791
792    fn deref(&self) -> &Self::Target {
793        self.current()
794    }
795}
796
797impl<T: Behavior> DerefMut for BehaviorMutItem<'_, T> {
798    fn deref_mut(&mut self) -> &mut Self::Target {
799        self.current_mut()
800    }
801}
802
803impl<T: Behavior> DetectChanges for BehaviorMutItem<'_, T> {
804    fn is_added(&self) -> bool {
805        self.current.is_added()
806    }
807
808    fn is_changed(&self) -> bool {
809        self.current.is_changed()
810    }
811
812    fn last_changed(&self) -> Tick {
813        self.current.last_changed()
814    }
815
816    fn added(&self) -> Tick {
817        self.current.added()
818    }
819
820    fn changed_by(&self) -> MaybeLocation {
821        self.current.changed_by()
822    }
823}
824
825impl<T: Behavior> DetectChangesMut for BehaviorMutItem<'_, T> {
826    type Inner = T;
827
828    fn set_changed(&mut self) {
829        self.current.set_changed()
830    }
831
832    fn set_last_changed(&mut self, last_changed: Tick) {
833        self.current.set_last_changed(last_changed)
834    }
835
836    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
837        self.current.bypass_change_detection()
838    }
839
840    fn set_added(&mut self) {
841        self.current.set_added()
842    }
843
844    fn set_last_added(&mut self, last_added: Tick) {
845        self.current.set_last_added(last_added)
846    }
847}
848
849impl<T: Behavior> AsRef<T> for BehaviorMutItem<'_, T> {
850    fn as_ref(&self) -> &T {
851        self.current.as_ref()
852    }
853}
854
855impl<T: Behavior> AsMut<T> for BehaviorMutItem<'_, T> {
856    fn as_mut(&mut self) -> &mut T {
857        self.current.as_mut()
858    }
859}
860
861impl<T: Behavior> Index<BehaviorIndex> for BehaviorMutItem<'_, T> {
862    type Output = T;
863
864    fn index(&self, BehaviorIndex(index): BehaviorIndex) -> &Self::Output {
865        if index == self.memory.stack.len() {
866            self.current()
867        } else {
868            &self.memory[index]
869        }
870    }
871}
872
873impl<T: Behavior> IndexMut<BehaviorIndex> for BehaviorMutItem<'_, T> {
874    fn index_mut(&mut self, BehaviorIndex(index): BehaviorIndex) -> &mut Self::Output {
875        if index == self.memory.stack.len() {
876            self.current_mut()
877        } else {
878            &mut self.memory[index]
879        }
880    }
881}
882
883/// A numeric index which represents the position of a [`Behavior`] in the stack.
884///
885/// This index may be used to uniquely identify each behavior state.
886/// The initial behavior always has the index of `0`, and the current behavior always has the highest index (length of the stack).
887#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Reflect)]
888pub struct BehaviorIndex(usize);
889
890impl BehaviorIndex {
891    /// Returns the index of the initial behavior. This is always `0`.
892    pub fn initial() -> Self {
893        Self(0)
894    }
895
896    fn next(self) -> Self {
897        Self(self.0.saturating_add(1))
898    }
899
900    fn previous(self) -> Self {
901        Self(self.0.saturating_sub(1))
902    }
903}
904
905#[derive(Component, Deref, DerefMut, Reflect)]
906#[reflect(Component)]
907struct Memory<T: Behavior> {
908    stack: Vec<T>,
909}
910
911impl<T: Behavior> Default for Memory<T> {
912    fn default() -> Self {
913        Self {
914            stack: Vec::default(),
915        }
916    }
917}
918
919/// A convenient macro for implementation of [`Behavior::filter_next`].
920///
921/// # Usage
922/// For any given pair of states `curr` and `next`, this match expands into a match arm such that:
923/// ```rust,ignore
924/// match curr {
925///     From => matches!(next, To)
926/// }
927/// ```
928/// where `From` is the current possible state, and `To` is the next allowed state.
929///
930/// # Example
931///
932/// ```rust
933/// # use bevy::prelude::*;
934/// # use moonshine_behavior::prelude::*;
935/// #[derive(Component, Debug)]
936/// enum Soldier {
937///     Idle,
938///     Crouch,
939///     Fire,
940///     Sprint,
941///     Jump,
942/// }
943///
944/// impl Behavior for Soldier {
945///     fn filter_next(&self, next: &Self) -> bool {
946///         use Soldier::*;
947///         match_next! {
948///             self => next,
949///             Idle => Crouch | Sprint | Fire | Jump,
950///             Crouch => Sprint | Fire,
951///             Sprint => Jump,
952///         }
953///     }
954/// }
955///
956/// # assert!(Soldier::Idle.filter_next(&Soldier::Crouch));
957/// # assert!(!Soldier::Sprint.filter_next(&Soldier::Fire));
958/// ```
959#[macro_export]
960macro_rules! match_next {
961    { $curr:ident => $next:ident, $($from:pat => $to:pat),* $(,)? } => {
962        match $curr {
963            $(
964                $from => matches!($next, $to),
965            )*
966            #[allow(unreachable_patterns)]
967            _ => false,
968        }
969    };
970}