1use crate::{
3 Completion, CompletionStatus, Frame, Motion, MotionState, Target, Transition, Variants,
4};
5
6use std::{fmt, time::Duration};
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10pub enum ChildrenOrder {
11 #[default]
13 Together,
14 BeforeChildren,
16 AfterChildren,
18}
19
20#[derive(Clone, Copy, Debug, Default)]
23pub struct MotionConfig {
24 transition: Transition,
25 stagger: Duration,
26}
27
28impl MotionConfig {
29 pub fn transition(mut self, transition: Transition) -> Self {
31 self.transition = transition;
32
33 self
34 }
35
36 pub fn stagger(mut self, interval: Duration) -> Self {
38 self.stagger = interval;
39
40 self
41 }
42
43 pub fn motion(self, target: Target) -> Motion {
45 Motion::new(target).transition(self.transition)
46 }
47}
48
49#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51pub enum TreeError {
52 Identity,
54 Variant,
56 Depth,
58}
59
60impl fmt::Display for TreeError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(f, "invalid motion tree operation: {self:?}")
63 }
64}
65
66impl std::error::Error for TreeError {}
67
68#[derive(Debug)]
70pub struct MotionNode<K, V> {
71 key: K,
72 parent: Option<K>,
73 initial: Target,
74 variants: Variants<V>,
75 order: ChildrenOrder,
76 exit_order: Option<ChildrenOrder>,
77 inherit: bool,
78}
79
80impl<K, V> MotionNode<K, V> {
81 pub fn new(key: K, initial: Target, variants: Variants<V>) -> Self {
83 Self {
84 key,
85 parent: None,
86 initial,
87 variants,
88 order: ChildrenOrder::Together,
89 exit_order: None,
90 inherit: true,
91 }
92 }
93
94 pub fn parent(mut self, parent: K) -> Self {
96 self.parent = Some(parent);
97
98 self
99 }
100
101 pub fn when(mut self, order: ChildrenOrder) -> Self {
103 self.order = order;
104
105 self
106 }
107
108 pub fn exit_when(mut self, order: ChildrenOrder) -> Self {
111 self.exit_order = Some(order);
112
113 self
114 }
115
116 pub fn inherit(mut self, inherit: bool) -> Self {
118 self.inherit = inherit;
119
120 self
121 }
122}
123
124#[derive(Debug)]
125struct Node<K, V> {
126 declaration: MotionNode<K, V>,
127 parent: Option<usize>,
128 children: Vec<usize>,
129 rank: usize,
130 state: MotionState,
131 current: Motion,
132 desired: Motion,
133 pending: Option<Motion>,
134 clock: Duration,
135 eligible: Option<Duration>,
136 running: bool,
137 done: bool,
138 frame: Frame,
139}
140
141#[derive(Debug)]
147pub struct MotionTree<K, V> {
148 nodes: Vec<Node<K, V>>,
149 config: MotionConfig,
150 last: Duration,
151 active: bool,
152 observers: crate::completion::CompletionSource,
153}
154
155impl<K, V> Default for MotionTree<K, V> {
156 fn default() -> Self {
157 Self {
158 nodes: Vec::new(),
159 config: MotionConfig::default(),
160 last: Duration::ZERO,
161 active: false,
162 observers: Default::default(),
163 }
164 }
165}
166
167impl<K: PartialEq, V: PartialEq> MotionTree<K, V> {
168 pub fn config(mut self, config: MotionConfig) -> Self {
170 self.config = config;
171
172 self
173 }
174
175 pub fn add(&mut self, declaration: MotionNode<K, V>) -> Result<(), TreeError> {
177 if self
178 .nodes
179 .iter()
180 .any(|node| node.declaration.key == declaration.key)
181 {
182 return Err(TreeError::Identity);
183 }
184
185 let parent = declaration
186 .parent
187 .as_ref()
188 .map(|key| self.index(key))
189 .transpose()?;
190
191 let mut ancestor = parent;
192 let mut depth = 0;
193
194 while let Some(index) = ancestor {
195 depth += 1;
196 ancestor = self.nodes[index].parent;
197 }
198
199 if depth >= 256 {
200 return Err(TreeError::Depth);
201 }
202
203 let rank = parent.map_or(0, |index| self.nodes[index].children.len());
204 let current = Motion::new(declaration.initial).transition(Transition::Instant);
205 let mut state = MotionState::default();
206 let frame = state.sample(current, Duration::ZERO, false);
207 let index = self.nodes.len();
208
209 self.nodes.push(Node {
210 declaration,
211 parent,
212 rank,
213 children: Vec::new(),
214 state,
215 current,
216 desired: current,
217 pending: None,
218 clock: Duration::ZERO,
219 eligible: None,
220 running: false,
221 done: true,
222 frame,
223 });
224
225 if let Some(parent) = parent {
226 self.nodes[parent].children.push(index);
227 }
228
229 Ok(())
230 }
231
232 fn index(&self, key: &K) -> Result<usize, TreeError> {
233 self.nodes
234 .iter()
235 .position(|node| node.declaration.key == *key)
236 .ok_or(TreeError::Identity)
237 }
238
239 fn inherits(&self, mut index: usize, root: Option<usize>) -> bool {
240 loop {
241 if Some(index) == root {
242 return true;
243 }
244
245 if !self.nodes[index].declaration.inherit {
246 return false;
247 }
248
249 match self.nodes[index].parent {
250 Some(parent) => index = parent,
251 None => return root.is_none(),
252 }
253 }
254 }
255
256 pub fn set_variant(
259 &mut self,
260 variant: &V,
261 now: Duration,
262 reduced: bool,
263 ) -> Result<(), TreeError> {
264 self.change(None, variant, now, reduced)
265 }
266
267 pub fn set_node_variant(
269 &mut self,
270 key: &K,
271 variant: &V,
272 now: Duration,
273 reduced: bool,
274 ) -> Result<(), TreeError> {
275 let root = self.index(key)?;
276
277 self.change(Some(root), variant, now, reduced)
278 }
279
280 pub fn set_motion(
284 &mut self,
285 key: &K,
286 motion: Motion,
287 now: Duration,
288 reduced: bool,
289 ) -> Result<(), TreeError> {
290 let index = self.index(key)?;
291
292 if self.nodes[index].desired == motion {
293 return Ok(());
294 }
295
296 self.sample(now, reduced);
297 self.observers.resolve(CompletionStatus::Cancelled);
298 let node = &mut self.nodes[index];
299
300 node.desired = motion;
301 node.pending = Some(motion);
302 node.running = false;
303 node.done = false;
304 node.eligible = None;
305 self.active = true;
306
307 Ok(())
308 }
309
310 fn change(
311 &mut self,
312 root: Option<usize>,
313 variant: &V,
314 now: Duration,
315 reduced: bool,
316 ) -> Result<(), TreeError> {
317 for (index, node) in self.nodes.iter().enumerate() {
318 if self.inherits(index, root) && node.declaration.variants.get(variant).is_none() {
319 return Err(TreeError::Variant);
320 }
321 }
322
323 if !self.nodes.iter().enumerate().any(|(index, node)| {
324 self.inherits(index, root)
325 && node.declaration.variants.get(variant) != Some(node.desired)
326 }) {
327 return Ok(());
328 }
329
330 self.sample(now, reduced);
331 self.observers.resolve(CompletionStatus::Cancelled);
332
333 for index in 0..self.nodes.len() {
334 if self.inherits(index, root)
335 && self.nodes[index].declaration.variants.get(variant)
336 != Some(self.nodes[index].desired)
337 {
338 let node = &mut self.nodes[index];
339
340 node.pending = node.declaration.variants.get(variant);
341 node.desired = node.pending.expect("validated variant");
342 node.running = false;
343 node.done = false;
344 node.eligible = None;
345 }
346 }
347
348 self.active = self.nodes.iter().any(|node| !node.done);
349
350 Ok(())
351 }
352
353 fn own(&mut self, index: usize, allowed: bool, delta: Duration, now: Duration, reduced: bool) {
354 let delay = self
355 .config
356 .stagger
357 .saturating_mul(self.nodes[index].rank.min(u32::MAX as usize) as u32);
358
359 let node = &mut self.nodes[index];
360
361 if node.done {
362 return;
363 }
364
365 if !allowed && !reduced {
366 return;
367 }
368
369 let due = *node.eligible.get_or_insert(now.saturating_add(delay));
370
371 if now < due && !reduced {
372 return;
373 }
374
375 if let Some(motion) = node.pending.take() {
376 node.current = motion;
377 } else if node.running {
378 node.clock = node.clock.saturating_add(delta);
379 }
380
381 node.frame = node.state.sample(node.current, node.clock, reduced);
382 node.running = true;
383 node.done = !node.frame.is_animating();
384 }
385
386 fn subtree(
387 &mut self,
388 index: usize,
389 allowed: bool,
390 delta: Duration,
391 now: Duration,
392 reduced: bool,
393 ) -> bool {
394 let node = &self.nodes[index];
395
396 let order = if node.desired.is_present() {
397 node.declaration.order
398 } else {
399 node.declaration
400 .exit_order
401 .unwrap_or(node.declaration.order)
402 };
403
404 if order != ChildrenOrder::AfterChildren {
405 self.own(index, allowed, delta, now, reduced);
406 }
407
408 let children_allowed =
409 allowed && (order != ChildrenOrder::BeforeChildren || self.nodes[index].done);
410
411 let mut children_done = true;
412
413 for i in 0..self.nodes[index].children.len() {
414 let child = self.nodes[index].children[i];
415
416 children_done &= self.subtree(child, children_allowed || reduced, delta, now, reduced);
417 }
418
419 if order == ChildrenOrder::AfterChildren {
420 self.own(index, allowed && children_done, delta, now, reduced);
421 }
422
423 self.nodes[index].done && children_done
424 }
425
426 pub fn sample(&mut self, now: Duration, reduced: bool) {
428 let now = now.max(self.last);
429 let delta = now.saturating_sub(self.last);
430 let mut done = true;
431
432 for index in 0..self.nodes.len() {
433 if self.nodes[index].parent.is_none() {
434 done &= self.subtree(index, true, delta, now, reduced);
435 }
436 }
437
438 if done && self.active {
439 self.observers.resolve(CompletionStatus::Completed);
440 }
441
442 self.active = !done;
443 self.last = now;
444 }
445
446 pub fn get(&self, key: &K) -> Option<Frame> {
448 self.index(key).ok().map(|index| self.nodes[index].frame)
449 }
450
451 pub fn is_mounted(&self, key: &K) -> bool {
454 let Ok(root) = self.index(key) else {
455 return false;
456 };
457
458 self.nodes.iter().enumerate().any(|(mut index, node)| {
459 if !node.frame.is_mounted() {
460 return false;
461 }
462
463 loop {
464 if index == root {
465 return true;
466 }
467
468 match self.nodes[index].parent {
469 Some(parent) => index = parent,
470 None => return false,
471 }
472 }
473 })
474 }
475
476 pub fn is_animating(&self) -> bool {
478 self.active
479 }
480
481 pub fn completion(&mut self) -> Completion {
483 self.observers.subscribe(!self.active)
484 }
485}