1pub mod prelude {
2 pub use crate::{Behavior, BehaviorMut, BehaviorRef};
3 pub use moonshine_kind::{Instance, InstanceCommands};
4
5 pub use crate::transition::{
6 transition, Next, Previous, Reset, Transition, TransitionSequence,
7 };
8
9 pub use crate::events::{BehaviorEvent, BehaviorEvents};
10 pub use crate::plugin::BehaviorPlugin;
11
12 pub use crate::match_next;
13}
14
15pub mod events;
16pub mod plugin;
17pub mod transition;
18
19#[cfg(test)]
20mod tests;
21
22use std::fmt::Debug;
23use std::mem::{replace, swap};
24use std::ops::{Deref, DerefMut, Index, IndexMut};
25
26use bevy_derive::{Deref, DerefMut};
27use bevy_ecs::change_detection::MaybeLocation;
28use bevy_ecs::component::{Mutable, Tick};
29use bevy_ecs::{prelude::*, query::QueryData};
30use bevy_log::prelude::*;
31use bevy_reflect::prelude::*;
32use events::BehaviorEventsMut;
33use moonshine_kind::prelude::*;
34
35use crate::events::BehaviorEvent;
36
37use self::transition::*;
38
39pub trait Behavior: Component<Mutability = Mutable> + Debug + Sized {
40 fn filter_yield(&self, next: &Self) -> bool {
45 match_next! {
46 self => next,
47 _ => _,
48 }
49 }
50
51 fn filter_next(&self, next: &Self) -> bool {
56 match_next! {
57 self => next,
58 _ => _,
59 }
60 }
61
62 fn is_resumable(&self) -> bool {
67 match self {
68 _ => true,
69 }
70 }
71
72 fn on_start(&self, _previous: Option<&Self>, _commands: InstanceCommands<Self>) {}
74
75 fn on_pause(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
77
78 fn on_resume(&self, _previous: &Self, _commands: InstanceCommands<Self>) {}
80
81 fn on_stop(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
83
84 fn on_activate(&self, _previous: Option<&Self>, _commands: InstanceCommands<Self>) {}
86
87 fn on_suspend(&self, _current: &Self, _commands: InstanceCommands<Self>) {}
89}
90
91#[doc(hidden)]
92trait BehaviorHooks: Behavior {
93 fn invoke_start(&self, previous: Option<&Self>, mut commands: InstanceCommands<Self>) {
94 self.on_start(previous, commands.reborrow());
95 self.on_activate(previous, commands);
96 }
97
98 fn invoke_pause(&self, current: &Self, mut commands: InstanceCommands<Self>) {
99 self.on_suspend(current, commands.reborrow());
100 self.on_pause(current, commands);
101 }
102
103 fn invoke_resume(&self, previous: &Self, mut commands: InstanceCommands<Self>) {
104 self.on_resume(previous, commands.reborrow());
105 self.on_activate(Some(previous), commands);
106 }
107
108 fn invoke_stop(&self, current: &Self, mut commands: InstanceCommands<Self>) {
109 self.on_suspend(current, commands.reborrow());
110 self.on_stop(current, commands);
111 }
112}
113
114impl<T: Behavior> BehaviorHooks for T {}
115
116#[derive(QueryData)]
126pub struct BehaviorRef<T: Behavior> {
127 current: Ref<'static, T>,
128 memory: &'static Memory<T>,
129 transition: &'static Transition<T>,
130 sequence: Has<TransitionSequence<T>>,
131}
132
133impl<T: Behavior> BehaviorRef<T> {
134 pub fn from_entity(entity: EntityRef) -> Option<BehaviorRefItem<T>> {
136 Some(BehaviorRefItem {
137 current: entity.get_ref::<T>()?,
138 memory: entity.get::<Memory<T>>()?,
139 transition: entity.get::<Transition<T>>()?,
140 sequence: entity.contains::<TransitionSequence<T>>(),
141 })
142 }
143}
144
145impl<T: Behavior> BehaviorRefItem<'_, T> {
146 pub fn current(&self) -> &T {
148 &self.current
149 }
150
151 pub fn index(&self) -> usize {
162 self.memory.len()
163 }
164
165 pub fn previous(&self) -> Option<&T> {
174 self.memory.last()
175 }
176
177 pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
181 self.memory.iter().chain(std::iter::once(self.current()))
182 }
183
184 pub fn has_transition(&self) -> bool {
199 !self.transition.is_none()
200 }
201
202 pub fn has_sequence(&self) -> bool {
206 self.sequence
207 }
208}
209
210impl<T: Behavior> Deref for BehaviorRefItem<'_, T> {
211 type Target = T;
212
213 fn deref(&self) -> &Self::Target {
214 self.current()
215 }
216}
217
218impl<T: Behavior> AsRef<T> for BehaviorRefItem<'_, T> {
219 fn as_ref(&self) -> &T {
220 &self.current
221 }
222}
223
224impl<T: Behavior> DetectChanges for BehaviorRefItem<'_, T> {
225 fn is_added(&self) -> bool {
226 self.current.is_added()
227 }
228
229 fn is_changed(&self) -> bool {
230 self.current.is_changed()
231 }
232
233 fn last_changed(&self) -> Tick {
234 self.current.last_changed()
235 }
236
237 fn added(&self) -> Tick {
238 self.current.added()
239 }
240
241 fn changed_by(&self) -> MaybeLocation {
242 self.current.changed_by()
243 }
244}
245
246impl<T: Behavior> Index<usize> for BehaviorRefItem<'_, T> {
247 type Output = T;
248
249 fn index(&self, index: usize) -> &Self::Output {
250 if index == self.memory.stack.len() {
251 self.current()
252 } else {
253 &self.memory[index]
254 }
255 }
256}
257
258#[derive(QueryData)]
266#[query_data(mutable)]
267pub struct BehaviorMut<T: Behavior> {
268 current: Mut<'static, T>,
269 memory: &'static mut Memory<T>,
270 transition: &'static mut Transition<T>,
271 sequence: Has<TransitionSequence<T>>,
272}
273
274impl<T: Behavior> BehaviorMutReadOnlyItem<'_, T> {
275 pub fn current(&self) -> &T {
277 &self.current
278 }
279
280 pub fn previous(&self) -> Option<&T> {
282 self.memory.last()
283 }
284
285 pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
287 self.memory.iter().chain(std::iter::once(self.current()))
288 }
289
290 pub fn index(&self) -> usize {
292 self.memory.len()
293 }
294
295 pub fn has_transition(&self) -> bool {
297 !self.transition.is_none()
298 }
299
300 pub fn has_sequence(&self) -> bool {
302 self.sequence
303 }
304}
305
306impl<T: Behavior> Deref for BehaviorMutReadOnlyItem<'_, T> {
307 type Target = T;
308
309 fn deref(&self) -> &Self::Target {
310 self.current()
311 }
312}
313
314impl<T: Behavior> AsRef<T> for BehaviorMutReadOnlyItem<'_, T> {
315 fn as_ref(&self) -> &T {
316 self.current.as_ref()
317 }
318}
319
320impl<T: Behavior> DetectChanges for BehaviorMutReadOnlyItem<'_, T> {
321 fn is_added(&self) -> bool {
322 self.current.is_added()
323 }
324
325 fn is_changed(&self) -> bool {
326 self.current.is_changed()
327 }
328
329 fn last_changed(&self) -> Tick {
330 self.current.last_changed()
331 }
332
333 fn added(&self) -> Tick {
334 self.current.added()
335 }
336
337 fn changed_by(&self) -> MaybeLocation {
338 self.current.changed_by()
339 }
340}
341
342impl<T: Behavior> Index<usize> for BehaviorMutReadOnlyItem<'_, T> {
343 type Output = T;
344
345 fn index(&self, index: usize) -> &Self::Output {
346 if index == self.memory.stack.len() {
347 self.current()
348 } else {
349 &self.memory[index]
350 }
351 }
352}
353
354impl<T: Behavior> BehaviorMutItem<'_, T> {
355 pub fn current(&self) -> &T {
357 &self.current
358 }
359
360 pub fn current_mut(&mut self) -> &mut T {
362 self.current.as_mut()
363 }
364
365 pub fn previous(&self) -> Option<&T> {
367 self.memory.last()
368 }
369
370 pub fn previous_mut(&mut self) -> Option<&mut T> {
374 self.memory.last_mut()
375 }
376
377 pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
379 self.memory.iter().chain(std::iter::once(self.current()))
380 }
381
382 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> + '_ {
386 self.memory
387 .iter_mut()
388 .chain(std::iter::once(self.current.as_mut()))
389 }
390
391 pub fn index(&self) -> usize {
393 self.memory.len()
394 }
395
396 pub fn has_transition(&self) -> bool {
398 !self.transition.is_none()
399 }
400
401 pub fn has_sequence(&self) -> bool {
403 self.sequence
404 }
405
406 pub fn start(&mut self, next: T) {
413 self.set_transition(Next(next));
414 }
415
416 pub fn try_start(&mut self, next: T) -> Result<(), T> {
436 if self.has_transition() || !self.filter_next(&next) {
437 return Err(next);
438 }
439
440 self.start(next);
441 Ok(())
442 }
443
444 pub fn interrupt_start(&mut self, next: T) {
456 self.set_transition(Interrupt(next));
457 }
458
459 pub fn stop(&mut self) {
466 self.set_transition(Previous);
467 }
468
469 pub fn reset(&mut self) {
474 self.set_transition(Reset);
475 }
476
477 fn set_transition(&mut self, transition: Transition<T>) {
478 let previous = replace(self.transition.as_mut(), transition);
479 if !previous.is_none() {
480 warn!(
481 "transition override: {previous:?} -> {:?}",
482 *self.transition
483 );
484 }
485 }
486
487 fn push(
488 &mut self,
489 instance: Instance<T>,
490 mut next: T,
491 events: &mut BehaviorEventsMut<T>,
492 commands: &mut Commands,
493 ) -> bool {
494 if self.filter_next(&next) {
495 let previous = {
496 swap(self.current.as_mut(), &mut next);
497 next
498 };
499 self.invoke_start(Some(&previous), commands.instance(instance));
500 let index = self.memory.len();
501 if previous.is_resumable() {
502 let new_index = index + 1;
503 debug!(
504 "{instance:?}: {previous:?} (#{index}) -> {:?} (#{new_index})",
505 *self.current
506 );
507 previous.invoke_pause(&self.current, commands.instance(instance));
508 events.write(BehaviorEvent::Pause { instance, index });
509 events.write(BehaviorEvent::Start {
510 instance,
511 index: new_index,
512 });
513 self.memory.push(previous);
514 } else {
515 debug!(
516 "{instance:?}: {previous:?} (#{index}) -> {:?} (#{index})",
517 *self.current
518 );
519 previous.invoke_stop(&self.current, commands.instance(instance));
520 events.write(BehaviorEvent::Start { instance, index });
521 events.write(BehaviorEvent::Stop {
522 instance,
523 behavior: previous,
524 });
525 }
526 true
527 } else {
528 warn!(
529 "{instance:?}: transition {:?} -> {next:?} is not allowed",
530 *self.current
531 );
532 events.write(BehaviorEvent::Error {
533 instance,
534 error: TransitionError::RejectedNext(next),
535 });
536 false
537 }
538 }
539
540 fn interrupt(
541 &mut self,
542 instance: Instance<T>,
543 next: T,
544 events: &mut BehaviorEventsMut<T>,
545 commands: &mut Commands,
546 ) {
547 while self.filter_yield(&next) && !self.memory.is_empty() {
548 let index = self.memory.len();
549 if let Some(mut next) = self.memory.pop() {
550 let next_index = self.memory.len();
551 debug!(
552 "{instance:?}: {:?} (#{index}) -> {next:?} (#{next_index})",
553 *self.current
554 );
555 let previous = {
556 swap(self.current.as_mut(), &mut next);
557 next
558 };
559 previous.invoke_stop(&self.current, commands.instance(instance));
560 events.write(BehaviorEvent::Stop {
561 instance,
562 behavior: previous,
563 });
564 }
565 }
566
567 self.push(instance, next, events, commands);
568 }
569
570 fn pop(
571 &mut self,
572 instance: Instance<T>,
573 events: &mut BehaviorEventsMut<T>,
574 commands: &mut Commands,
575 ) -> bool {
576 let index = self.memory.len();
577 if let Some(mut next) = self.memory.pop() {
578 let next_index = self.memory.len();
579 debug!(
580 "{instance:?}: {:?} (#{index}) -> {next:?} (#{next_index})",
581 *self.current
582 );
583 let previous = {
584 swap(self.current.as_mut(), &mut next);
585 next
586 };
587 self.invoke_resume(&previous, commands.instance(instance));
588 previous.invoke_stop(&self.current, commands.instance(instance));
589 events.write(BehaviorEvent::Resume {
590 instance,
591 index: next_index,
592 });
593 events.write(BehaviorEvent::Stop {
594 instance,
595 behavior: previous,
596 });
597 true
598 } else {
599 warn!(
600 "{instance:?}: transition {:?} -> None is not allowed",
601 *self.current
602 );
603 events.write(BehaviorEvent::Error {
604 instance,
605 error: TransitionError::NoPrevious,
606 });
607 false
608 }
609 }
610
611 fn clear(
612 &mut self,
613 instance: Instance<T>,
614 events: &mut BehaviorEventsMut<T>,
615 commands: &mut Commands,
616 ) {
617 while self.memory.len() > 1 {
618 let index = self.memory.len();
619 let previous = self.memory.pop().unwrap();
620 let next_index = self.memory.len();
621 let next = self.memory.last().unwrap();
622 debug!(
623 "{instance:?}: {:?} (#{index}) -> {next:?} (#{next_index})",
624 *self.current
625 );
626 previous.invoke_stop(next, commands.instance(instance));
627 events.write(BehaviorEvent::Stop {
628 instance,
629 behavior: previous,
630 });
631 }
632
633 self.pop(instance, events, commands);
634 }
635}
636
637impl<T: Behavior> Deref for BehaviorMutItem<'_, T> {
638 type Target = T;
639
640 fn deref(&self) -> &Self::Target {
641 self.current()
642 }
643}
644
645impl<T: Behavior> DerefMut for BehaviorMutItem<'_, T> {
646 fn deref_mut(&mut self) -> &mut Self::Target {
647 self.current_mut()
648 }
649}
650
651impl<T: Behavior> DetectChanges for BehaviorMutItem<'_, T> {
652 fn is_added(&self) -> bool {
653 self.current.is_added()
654 }
655
656 fn is_changed(&self) -> bool {
657 self.current.is_changed()
658 }
659
660 fn last_changed(&self) -> Tick {
661 self.current.last_changed()
662 }
663
664 fn added(&self) -> Tick {
665 self.current.added()
666 }
667
668 fn changed_by(&self) -> MaybeLocation {
669 self.current.changed_by()
670 }
671}
672
673impl<T: Behavior> DetectChangesMut for BehaviorMutItem<'_, T> {
674 type Inner = T;
675
676 fn set_changed(&mut self) {
677 self.current.set_changed()
678 }
679
680 fn set_last_changed(&mut self, last_changed: Tick) {
681 self.current.set_last_changed(last_changed)
682 }
683
684 fn bypass_change_detection(&mut self) -> &mut Self::Inner {
685 self.current.bypass_change_detection()
686 }
687
688 fn set_added(&mut self) {
689 self.current.set_added()
690 }
691
692 fn set_last_added(&mut self, last_added: Tick) {
693 self.current.set_last_added(last_added)
694 }
695}
696
697impl<T: Behavior> AsRef<T> for BehaviorMutItem<'_, T> {
698 fn as_ref(&self) -> &T {
699 self.current.as_ref()
700 }
701}
702
703impl<T: Behavior> AsMut<T> for BehaviorMutItem<'_, T> {
704 fn as_mut(&mut self) -> &mut T {
705 self.current.as_mut()
706 }
707}
708
709impl<T: Behavior> Index<usize> for BehaviorMutItem<'_, T> {
710 type Output = T;
711
712 fn index(&self, index: usize) -> &Self::Output {
713 if index == self.memory.stack.len() {
714 self.current()
715 } else {
716 &self.memory[index]
717 }
718 }
719}
720
721impl<T: Behavior> IndexMut<usize> for BehaviorMutItem<'_, T> {
722 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
723 if index == self.memory.stack.len() {
724 self.current_mut()
725 } else {
726 &mut self.memory[index]
727 }
728 }
729}
730
731#[derive(Component, Deref, DerefMut, Reflect)]
732#[reflect(Component)]
733struct Memory<T: Behavior> {
734 stack: Vec<T>,
735}
736
737impl<T: Behavior> Default for Memory<T> {
738 fn default() -> Self {
739 Self {
740 stack: Vec::default(),
741 }
742 }
743}
744
745#[macro_export]
786macro_rules! match_next {
787 { $curr:ident => $next:ident, $($from:pat => $to:pat),* $(,)? } => {
788 match $curr {
789 $(
790 $from => matches!($next, $to),
791 )*
792 #[allow(unreachable_patterns)]
793 _ => false,
794 }
795 };
796}