moonshine_behavior/
transition.rs1use std::collections::VecDeque;
2use std::fmt::Debug;
3
4use bevy_ecs::prelude::*;
5use bevy_log::prelude::*;
6use bevy_reflect::prelude::*;
7use moonshine_kind::prelude::*;
8
9use crate::events::BehaviorEvent;
10use crate::{Behavior, BehaviorEventsMut, BehaviorHooks, BehaviorMut, BehaviorMutItem, Memory};
11
12pub use self::Transition::{Interrupt, Next, Previous, Reset};
13
14#[derive(Component, Debug, Reflect)]
15#[require(Memory<T>)]
16#[reflect(Component)]
17pub enum Transition<T: Behavior> {
18 None,
19 Next(T),
20 Interrupt(T),
21 Previous,
22 Reset,
23}
24
25impl<T: Behavior> Transition<T> {
26 pub fn is_none(&self) -> bool {
27 matches!(self, Self::None)
28 }
29
30 fn take(&mut self) -> Self {
31 std::mem::replace(self, Transition::None)
32 }
33}
34
35impl<T: Behavior> Default for Transition<T> {
36 fn default() -> Self {
37 Self::None
38 }
39}
40
41impl<T: Behavior + Clone> Clone for Transition<T> {
42 fn clone(&self) -> Self {
43 match self {
44 Self::None => Self::None,
45 Next(next) => Next(next.clone()),
46 Interrupt(next) => Interrupt(next.clone()),
47 Previous => Previous,
48 Reset => Reset,
49 }
50 }
51}
52
53pub fn transition<T: Behavior>(
54 mut events: BehaviorEventsMut<T>,
55 mut query: Query<
56 (
57 Instance<T>,
58 BehaviorMut<T>,
59 Option<&mut TransitionSequence<T>>,
60 ),
61 TransitionChanged<T>,
62 >,
63 mut commands: Commands,
64) {
65 for (instance, mut behavior, sequence_opt) in &mut query {
66 if behavior.current.is_added() {
67 debug_assert!(behavior.memory.is_empty());
69
70 behavior.invoke_start(None, commands.instance(instance));
72 events.write(BehaviorEvent::Start { instance, index: 0 });
73 }
74
75 let mut stop_index = None;
77
78 let mut interrupt_sequence = false;
79
80 match behavior.transition.take() {
81 Next(next) => {
82 interrupt_sequence = !behavior.push(instance, next, &mut events, &mut commands);
83 }
84 Previous => {
85 stop_index = Some(behavior.index());
86 interrupt_sequence = !behavior.pop(instance, &mut events, &mut commands);
87 }
88 Interrupt(next) => {
89 behavior.interrupt(instance, next, &mut events, &mut commands);
90 interrupt_sequence = true;
91 }
92 Reset => {
93 behavior.clear(instance, &mut events, &mut commands);
94 interrupt_sequence = true;
95 }
96 _ => {}
97 }
98
99 let Some(sequence) = sequence_opt else {
100 continue;
101 };
102
103 if interrupt_sequence {
104 debug!("{instance:?}: sequence interrupted");
105 commands.entity(*instance).remove::<TransitionSequence<T>>();
106 } else if sequence.is_empty() {
107 debug!("{instance:?}: sequence finished");
108 commands.entity(*instance).remove::<TransitionSequence<T>>();
109 } else {
110 TransitionSequence::update(sequence, instance, behavior, stop_index);
111 }
112 }
113}
114
115pub type TransitionChanged<T> = Or<(Changed<Transition<T>>, With<TransitionSequence<T>>)>;
117
118#[derive(Debug, PartialEq, Reflect)]
119pub enum TransitionError<T: Behavior> {
120 RejectedNext(T),
121 NoPrevious,
122}
123
124#[derive(Component, Reflect)]
125#[reflect(Component)]
126pub struct TransitionSequence<T: Behavior> {
127 queue: VecDeque<TransitionSequenceElement<T>>,
128 wait_index: Option<usize>,
129}
130
131impl<T: Behavior> TransitionSequence<T> {
132 pub fn new(items: impl IntoIterator<Item = T>) -> Self {
133 Self {
134 queue: VecDeque::from_iter(items.into_iter().map(TransitionSequenceElement::Start)),
135 wait_index: None,
136 }
137 }
138
139 pub fn empty() -> Self {
140 Self {
141 queue: VecDeque::new(),
142 wait_index: None,
143 }
144 }
145
146 pub fn is_empty(&self) -> bool {
147 self.queue.is_empty()
148 }
149
150 pub fn len(&self) -> usize {
151 self.queue.len()
152 }
153
154 pub fn start(next: T) -> Self {
155 let mut sequence = Self::empty();
156 sequence.push(TransitionSequenceElement::Start(next));
157 sequence
158 }
159
160 pub fn wait_for(next: T) -> Self {
161 Self::empty().then_wait_for(next)
162 }
163
164 pub fn then(mut self, next: T) -> Self {
165 self.push(TransitionSequenceElement::Start(next));
166 self
167 }
168
169 pub fn then_wait_for(mut self, next: T) -> Self {
170 self.push(TransitionSequenceElement::StartWait(next));
171 self
172 }
173
174 pub fn then_stop(mut self) -> Self {
175 self.push(TransitionSequenceElement::Stop);
176 self
177 }
178
179 fn push(&mut self, next: TransitionSequenceElement<T>) {
180 self.queue.push_back(next);
181 }
182}
183
184impl<T: Behavior> TransitionSequence<T> {
185 pub(crate) fn update(
186 mut this: Mut<Self>,
187 instance: Instance<T>,
188 mut behavior: BehaviorMutItem<T>,
189 stop_index: Option<usize>,
190 ) {
191 debug_assert!(!this.queue.is_empty());
192
193 if let Some(wait_index) = this.wait_index {
194 if let Some(stop_index) = stop_index {
195 if wait_index != stop_index {
196 return;
197 }
198 } else {
199 return;
200 }
201 }
202
203 debug!("{instance:?}: sequence steps = {:?}", this.queue.len());
204
205 if let Some(element) = this.queue.pop_front() {
206 use TransitionSequenceElement::*;
207 match element {
208 Start(next) => {
209 this.wait_index = None;
210 behavior.start(next);
211 }
212 StartWait(next) => {
213 this.wait_index = Some(behavior.index() + 1);
214 behavior.start(next);
215 }
216 Stop => {
217 this.wait_index = None;
218 behavior.stop();
219 }
220 }
221 }
222 }
223}
224
225#[derive(Debug, Reflect)]
226enum TransitionSequenceElement<T: Behavior> {
227 Start(T),
228 StartWait(T),
229 Stop,
230}