1#![doc = include_str!("../readme.inc.md")]
3#![deny(missing_docs)]
4use std::{borrow::Cow, ops::RangeInclusive};
5
6use bevy::prelude::*;
7use ego_tree::*;
8
9mod behave_trigger;
10mod ctx;
11mod dyn_bundle;
12mod plugin;
13
14use behave_trigger::*;
15use ctx::*;
16use dyn_bundle::prelude::*;
17
18pub use ego_tree;
20
21pub mod prelude {
24 pub use super::behave;
25 pub use super::behave_trigger::BehaveTrigger;
26 pub use super::ctx::*;
27 pub use super::plugin::*;
28 pub use super::{Behave, BehaveFinished};
29 pub use ego_tree::*;
30}
31
32#[derive(Copy, Clone, PartialEq, Eq, Debug)]
34enum BehaveNodeStatus {
35 Success,
37 Failure,
39 Running,
41 RunningTimer,
43 AwaitingTrigger,
45 PendingReset,
47}
48
49#[derive(Component, Reflect, Debug)]
52pub struct BehaveFinished(pub bool);
53
54#[derive(Clone)]
60pub enum Behave {
61 Wait(f32),
63 DynamicEntity {
66 name: Cow<'static, str>,
68 dynamic_bundel: DynamicBundel,
70 },
71 Sequence,
73 Fallback,
75 Invert,
77 AlwaysSucceed,
79 AlwaysFail,
81 TriggerReq(DynamicTrigger),
84 Forever,
86 While,
88 IfThen,
91}
92
93impl std::fmt::Display for Behave {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 match self {
96 Behave::While => write!(f, "While"),
97 Behave::Wait(secs) => write!(f, "Wait({secs}s)"),
98 Behave::DynamicEntity { name, .. } => write!(f, "Spawn({name})"),
99 Behave::Sequence => write!(f, "Sequence"),
100 Behave::Fallback => write!(f, "Fallback"),
101 Behave::Invert => write!(f, "Invert"),
102 Behave::AlwaysSucceed => write!(f, "AlwaysSucceed"),
103 Behave::AlwaysFail => write!(f, "AlwaysFail"),
104 Behave::TriggerReq(t) => write!(f, "Trigger({})", t.type_name()),
105 Behave::Forever => write!(f, "Forever"),
106 Behave::IfThen => write!(f, "IfThen"),
107 }
108 }
109}
110
111impl Behave {
112 pub fn spawn<T: Bundle + Clone>(bundle: T) -> Behave {
115 Behave::DynamicEntity {
116 name: "unnamed".into(),
117 dynamic_bundel: DynamicBundel::new(bundle),
118 }
119 }
120 pub fn spawn_named<T: Bundle + Clone>(name: impl Into<Cow<'static, str>>, bundle: T) -> Behave {
128 let name = name.into();
129 Behave::DynamicEntity {
130 name: name.clone(),
131 dynamic_bundel: DynamicBundel::new((Name::new(name), bundle)),
132 }
133 }
134 pub fn trigger<T: Clone + Send + Sync + 'static>(value: T) -> Self {
137 Behave::TriggerReq(DynamicTrigger::new(value))
138 }
139 pub(crate) fn permitted_children(&self) -> RangeInclusive<usize> {
141 match self {
142 Behave::Sequence => 1..=usize::MAX,
143 Behave::Fallback => 1..=usize::MAX,
144 Behave::Forever => 1..=usize::MAX,
145 Behave::While => 1..=2,
146 Behave::IfThen => 2..=3,
147 Behave::Invert => 1..=1,
148 Behave::Wait(_) => 0..=0,
150 Behave::TriggerReq(_) => 0..=0,
151 Behave::DynamicEntity { .. } => 0..=0,
152 Behave::AlwaysSucceed => 0..=0,
154 Behave::AlwaysFail => 0..=0,
155 }
156 }
157}
158
159pub(crate) enum BehaveNode {
163 Forever {
164 status: Option<BehaveNodeStatus>,
165 },
166 Wait {
167 start_time: Option<f32>,
168 secs_to_wait: f32,
169 status: Option<BehaveNodeStatus>,
170 },
171 DynamicEntity {
172 task_status: EntityTaskStatus,
174 status: Option<BehaveNodeStatus>,
175 bundle: DynamicBundel,
176 name: Cow<'static, str>,
177 },
178 SequenceFlow {
179 status: Option<BehaveNodeStatus>,
180 },
181 FallbackFlow {
182 status: Option<BehaveNodeStatus>,
183 },
184 Invert {
185 status: Option<BehaveNodeStatus>,
186 },
187 AlwaysSucceed {
188 status: Option<BehaveNodeStatus>,
189 },
190 AlwaysFail {
191 status: Option<BehaveNodeStatus>,
192 },
193 TriggerReq {
194 status: Option<BehaveNodeStatus>,
195 task_status: TriggerTaskStatus,
196 trigger: DynamicTrigger,
197 },
198 While {
199 status: Option<BehaveNodeStatus>,
200 },
201 IfThen {
202 status: Option<BehaveNodeStatus>,
203 },
204}
205
206#[derive(Clone, Debug)]
207enum EntityTaskStatus {
208 NotStarted,
209 Started(Entity),
210 Complete(bool),
211}
212
213#[derive(Clone, Debug)]
214enum TriggerTaskStatus {
215 NotTriggered,
216 Triggered,
217 Complete(bool),
218}
219
220impl BehaveNode {
221 fn status(&self) -> &Option<BehaveNodeStatus> {
222 match self {
223 BehaveNode::Forever { status } => status,
224 BehaveNode::TriggerReq { status, .. } => status,
225 BehaveNode::Wait { status, .. } => status,
226 BehaveNode::DynamicEntity { status, .. } => status,
227 BehaveNode::SequenceFlow { status } => status,
228 BehaveNode::FallbackFlow { status } => status,
229 BehaveNode::Invert { status } => status,
230 BehaveNode::AlwaysSucceed { status } => status,
231 BehaveNode::AlwaysFail { status } => status,
232 BehaveNode::While { status } => status,
233 BehaveNode::IfThen { status } => status,
234 }
235 }
236 fn status_mut(&mut self) -> &mut Option<BehaveNodeStatus> {
237 match self {
238 BehaveNode::Forever { status } => status,
239 BehaveNode::TriggerReq { status, .. } => status,
240 BehaveNode::Wait { status, .. } => status,
241 BehaveNode::DynamicEntity { status, .. } => status,
242 BehaveNode::SequenceFlow { status } => status,
243 BehaveNode::FallbackFlow { status } => status,
244 BehaveNode::Invert { status } => status,
245 BehaveNode::AlwaysSucceed { status } => status,
246 BehaveNode::AlwaysFail { status } => status,
247 BehaveNode::While { status } => status,
248 BehaveNode::IfThen { status } => status,
249 }
250 }
251}
252
253impl std::fmt::Display for BehaveNode {
254 #[rustfmt::skip]
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 match self {
257 BehaveNode::Forever { .. } => write!(f, "Forever")?,
258 BehaveNode::TriggerReq { trigger, .. } => write!(f, "TriggerReq({})", trigger.type_name())?,
259 BehaveNode::Wait { secs_to_wait, .. } => write!(f, "Wait({secs_to_wait})")?,
260 BehaveNode::DynamicEntity {name, .. } => write!(f, "DynamicEntity({name})")?,
261 BehaveNode::SequenceFlow { .. } => write!(f, "SequenceFlow")?,
262 BehaveNode::FallbackFlow { .. } => write!(f, "FallbackFlow")?,
263 BehaveNode::Invert { .. } => write!(f, "Invert")?,
264 BehaveNode::AlwaysSucceed { .. } => write!(f, "AlwaysSucceed")?,
265 BehaveNode::AlwaysFail { .. } => write!(f, "AlwaysFail")?,
266 BehaveNode::While { .. } => write!(f, "While")?,
267 BehaveNode::IfThen { .. } => write!(f, "IfThen")?,
268 }
269 match self.status() {
270 Some(BehaveNodeStatus::Success) => write!(f, " --> ✅"),
271 Some(BehaveNodeStatus::Failure) => write!(f, " --> ❌"),
272 Some(BehaveNodeStatus::Running) => write!(f, " --> ⏳"),
273 Some(BehaveNodeStatus::RunningTimer) => write!(f, " --> ⏳"),
274 Some(BehaveNodeStatus::AwaitingTrigger) => write!(f, " --> ⏳"),
275 Some(BehaveNodeStatus::PendingReset) => write!(f, " --> 🔄"),
276 _ => Ok(()),
277 }
278 }
279}
280
281impl BehaveNode {
282 pub(crate) fn reset(&mut self) {
283 match self {
284 BehaveNode::Forever { status } => {
285 *status = None;
286 }
287 BehaveNode::TriggerReq {
288 status,
289 task_status,
290 ..
291 } => {
292 *status = None;
293 *task_status = TriggerTaskStatus::NotTriggered;
294 }
295 BehaveNode::Wait {
296 status, start_time, ..
297 } => {
298 *status = None;
299 *start_time = None;
300 }
301 BehaveNode::DynamicEntity {
302 status,
303 task_status,
304 ..
305 } => {
306 *status = None;
307 *task_status = EntityTaskStatus::NotStarted;
308 }
309 BehaveNode::SequenceFlow { status } => {
310 *status = None;
311 }
312 BehaveNode::FallbackFlow { status } => {
313 *status = None;
314 }
315 BehaveNode::Invert { status } => {
316 *status = None;
317 }
318 BehaveNode::AlwaysSucceed { status } => {
319 *status = None;
320 }
321 BehaveNode::AlwaysFail { status } => {
322 *status = None;
323 }
324 BehaveNode::While { status } => {
325 *status = None;
326 }
327 BehaveNode::IfThen { status } => {
328 *status = None;
329 }
330 }
331 }
332 pub(crate) fn new(behave: Behave) -> Self {
333 match behave {
334 Behave::Forever => Self::Forever { status: None },
335 Behave::TriggerReq(trig_fn) => Self::TriggerReq {
336 status: None,
337 task_status: TriggerTaskStatus::NotTriggered,
338 trigger: trig_fn,
339 },
340 Behave::Wait(secs_to_wait) => Self::Wait {
341 start_time: None,
342 secs_to_wait,
343 status: None,
344 },
345 Behave::DynamicEntity {
346 name,
347 dynamic_bundel: bundle,
348 } => Self::DynamicEntity {
349 task_status: EntityTaskStatus::NotStarted,
350 status: None,
351 bundle,
352 name,
353 },
354 Behave::While => Self::While { status: None },
355 Behave::Sequence => Self::SequenceFlow { status: None },
356 Behave::Fallback => Self::FallbackFlow { status: None },
357 Behave::Invert => Self::Invert { status: None },
358 Behave::AlwaysSucceed => Self::AlwaysSucceed { status: None },
359 Behave::AlwaysFail => Self::AlwaysFail { status: None },
360 Behave::IfThen => Self::IfThen { status: None },
361 }
362 }
363}
364
365fn reset_descendants(n: &mut NodeMut<BehaveNode>) {
367 n.value().reset();
369 if let Some(mut sibling) = n.next_sibling() {
370 reset_descendants(&mut sibling);
371 }
372 if let Some(mut child) = n.first_child() {
373 reset_descendants(&mut child);
374 }
375}
376
377fn tick_node(
378 n: &mut NodeMut<BehaveNode>,
379 time: &Res<Time>,
380 commands: &mut Commands,
381 bt_entity: Entity,
382 target_entity: Entity,
383 logging: bool,
384) -> BehaveNodeStatus {
385 use BehaveNode::*;
386 let reset_needed = match n.value().status() {
391 Some(BehaveNodeStatus::Success) => return BehaveNodeStatus::Success,
392 Some(BehaveNodeStatus::Failure) => return BehaveNodeStatus::Failure,
393 Some(BehaveNodeStatus::PendingReset) => true,
394 _ => false,
395 };
396 if reset_needed {
397 *n.value().status_mut() = Some(BehaveNodeStatus::Running);
398 reset_descendants(n);
399 }
400 let task_node = n.id();
401 match n.value() {
402 While { .. } => {
403 *n.value().status_mut() = Some(BehaveNodeStatus::Running);
404 let mut first_child = n
405 .first_child()
406 .expect("While node first child must exist (the conditional)");
407 match tick_node(
408 &mut first_child,
409 time,
410 commands,
411 bt_entity,
412 target_entity,
413 logging,
414 ) {
415 BehaveNodeStatus::Success => {
416 *first_child.value().status_mut() = Some(BehaveNodeStatus::Success);
417 if let Some(mut second_child) = first_child.next_sibling() {
421 match tick_node(
422 &mut second_child,
423 time,
424 commands,
425 bt_entity,
426 target_entity,
427 logging,
428 ) {
429 BehaveNodeStatus::Success => {
430 *second_child.value().status_mut() =
431 Some(BehaveNodeStatus::Success);
432 *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
434 BehaveNodeStatus::PendingReset
435 }
436 other => {
437 *n.value().status_mut() = Some(other);
438 other
439 }
440 }
441 } else {
442 *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
443 BehaveNodeStatus::PendingReset
444 }
445 }
446 other => {
447 *first_child.value().status_mut() = Some(other);
448 *n.value().status_mut() = Some(other);
449 other
450 }
451 }
452 }
453 IfThen { .. } => {
454 *n.value().status_mut() = Some(BehaveNodeStatus::Running);
455 let mut conditional_child = n
456 .first_child()
457 .expect("IfThen node first child must exist (the 'if condition' child)");
458 match tick_node(
460 &mut conditional_child,
461 time,
462 commands,
463 bt_entity,
464 target_entity,
465 logging,
466 ) {
467 BehaveNodeStatus::Success => {
468 *conditional_child.value().status_mut() = Some(BehaveNodeStatus::Success);
470 let mut then_child = conditional_child
471 .next_sibling()
472 .expect("IfThen node second child must exist (the 'then' child)");
473 let then_result = tick_node(
474 &mut then_child,
475 time,
476 commands,
477 bt_entity,
478 target_entity,
479 logging,
480 );
481 *n.value().status_mut() = Some(then_result);
482 then_result
483 }
484 BehaveNodeStatus::Failure => {
485 *conditional_child.value().status_mut() = Some(BehaveNodeStatus::Failure);
487 if let Some(mut else_child) = conditional_child
488 .next_sibling()
489 .expect("If nodes must have exactly two or three children")
490 .next_sibling()
491 {
492 let else_result = tick_node(
494 &mut else_child,
495 time,
496 commands,
497 bt_entity,
498 target_entity,
499 logging,
500 );
501 *n.value().status_mut() = Some(else_result);
502 else_result
503 } else {
504 *n.value().status_mut() = Some(BehaveNodeStatus::Failure);
506 BehaveNodeStatus::Failure
507 }
508 }
509 other => {
510 *n.value().status_mut() = Some(other);
511 other
512 }
513 }
514 }
515 Forever { .. } => {
516 *n.value().status_mut() = Some(BehaveNodeStatus::Running);
517 let mut only_child = n.first_child().expect("Forever nodes must have a child");
518 if only_child.has_siblings() {
519 panic!("Forever nodes must have a single child, not multiple children");
520 }
521 match tick_node(
522 &mut only_child,
523 time,
524 commands,
525 bt_entity,
526 target_entity,
527 logging,
528 ) {
529 BehaveNodeStatus::Success | BehaveNodeStatus::Failure => {
531 *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
532 BehaveNodeStatus::PendingReset
533 }
534 other => other,
535 }
536 }
537 TriggerReq {
538 task_status: task_status @ TriggerTaskStatus::NotTriggered,
539 status,
540 trigger,
541 } => {
542 let ctx = BehaveCtx::new_for_trigger(bt_entity, task_node, target_entity);
543 commands.dyn_trigger(trigger.clone(), ctx);
544 *task_status = TriggerTaskStatus::Triggered;
548 *status = Some(BehaveNodeStatus::Running);
549 BehaveNodeStatus::Running
550 }
551 #[rustfmt::skip]
552 TriggerReq {task_status: TriggerTaskStatus::Complete(true), status, ..} => {
553 *status = Some(BehaveNodeStatus::Success);
554 BehaveNodeStatus::Success
555 }
556 #[rustfmt::skip]
557 TriggerReq {task_status: TriggerTaskStatus::Complete(false), status, ..} => {
558 *status = Some(BehaveNodeStatus::Failure);
559 BehaveNodeStatus::Failure
560 }
561 #[rustfmt::skip]
564 TriggerReq {task_status: TriggerTaskStatus::Triggered, status, .. } => {
565 *status = Some(BehaveNodeStatus::AwaitingTrigger);
566 BehaveNodeStatus::AwaitingTrigger
567 }
568 Invert { .. } => {
569 let mut only_child = n.first_child().expect("Invert nodes must have a child");
570 if only_child.has_siblings() {
571 panic!("Invert nodes must have a single child, not multiple children");
572 }
573 let res = match tick_node(
574 &mut only_child,
575 time,
576 commands,
577 bt_entity,
578 target_entity,
579 logging,
580 ) {
581 BehaveNodeStatus::Success => BehaveNodeStatus::Failure, BehaveNodeStatus::Failure => BehaveNodeStatus::Success, other => other,
584 };
585 let Invert { status } = n.value() else {
586 unreachable!("Must be an Invert");
587 };
588 *status = Some(res);
589 res
590 }
591 AlwaysSucceed { status } => {
592 *status = Some(BehaveNodeStatus::Success);
593 BehaveNodeStatus::Success
594 }
595 AlwaysFail { status } => {
596 *status = Some(BehaveNodeStatus::Failure);
597 BehaveNodeStatus::Failure
598 }
599 Wait {
601 start_time: start_time @ None,
602 status,
603 ..
604 } => {
605 *start_time = Some(time.elapsed_secs());
607 *status = Some(BehaveNodeStatus::Running);
608 BehaveNodeStatus::Running
609 }
610 Wait {
612 start_time: Some(start_time),
613 secs_to_wait,
614 status,
615 } => {
616 let elapsed = time.elapsed_secs() - *start_time;
618 if elapsed > *secs_to_wait {
619 *status = Some(BehaveNodeStatus::Success);
620 return BehaveNodeStatus::Success;
621 }
622 BehaveNodeStatus::RunningTimer
623 }
624 DynamicEntity {
626 task_status: task_status @ EntityTaskStatus::NotStarted,
627 status,
628 bundle,
629 name: _,
630 } => {
631 let mut e = commands.spawn(());
632 e.set_parent(bt_entity);
633 let ctx = BehaveCtx::new_for_entity(bt_entity, task_node, target_entity);
634 let id = e.dyn_insert(bundle.clone(), Some(ctx)).id();
639 *task_status = EntityTaskStatus::Started(id);
641 *status = Some(BehaveNodeStatus::Running);
646 BehaveNodeStatus::Running
647 }
648 #[rustfmt::skip]
649 DynamicEntity { task_status: EntityTaskStatus::Started(_), status: status @ Some(BehaveNodeStatus::Running), .. } => {
650 *status = Some(BehaveNodeStatus::AwaitingTrigger);
653 BehaveNodeStatus::AwaitingTrigger
654 }
655 #[rustfmt::skip]
656 DynamicEntity{ task_status: EntityTaskStatus::Started(_), .. } => unreachable!("Short circuit should prevent this while AwaitingTrigger"),
657 #[rustfmt::skip]
659 DynamicEntity {task_status: EntityTaskStatus::Complete(true), status, ..} => {
660 *status = Some(BehaveNodeStatus::Success);
661 BehaveNodeStatus::Success
662 }
663 #[rustfmt::skip]
664 DynamicEntity {task_status: EntityTaskStatus::Complete(false), status, ..} => {
665 *status = Some(BehaveNodeStatus::Failure);
666 BehaveNodeStatus::Failure
667 }
668 SequenceFlow { .. } => {
670 let Some(mut child) = n.first_child() else {
672 warn!("SequenceFlow with no children, returning success anyway");
673 return BehaveNodeStatus::Success;
674 };
675
676 let mut final_status;
677 loop {
678 match tick_node(
679 &mut child,
680 time,
681 commands,
682 bt_entity,
683 target_entity,
684 logging,
685 ) {
686 BehaveNodeStatus::Success => {
687 final_status = BehaveNodeStatus::Success;
688 if let Ok(next_child) = child.into_next_sibling() {
689 child = next_child;
690 continue;
691 } else {
692 break;
693 }
694 }
695 other => {
697 final_status = other;
698 break;
699 }
700 }
701 }
702 let SequenceFlow { status, .. } = n.value() else {
703 unreachable!("Must be a SequenceFlow");
704 };
705 *status = Some(final_status);
706 final_status
707 }
708
709 FallbackFlow { .. } => {
710 let Some(mut child) = n.first_child() else {
711 warn!("FallbackFlow with no children, returning success anyway");
712 return BehaveNodeStatus::Success;
713 };
714
715 let mut final_status;
716 loop {
717 match tick_node(
718 &mut child,
719 time,
720 commands,
721 bt_entity,
722 target_entity,
723 logging,
724 ) {
725 BehaveNodeStatus::Failure => {
726 final_status = BehaveNodeStatus::Failure;
728 if let Ok(next_child) = child.into_next_sibling() {
729 child = next_child;
730 continue;
731 } else {
732 break;
733 }
734 }
735 other => {
737 final_status = other;
738 break;
739 }
740 }
741 }
742 let FallbackFlow { status, .. } = n.value() else {
743 unreachable!("Must be a FallbackFlow");
744 };
745 *status = Some(final_status);
746 final_status
747 }
748 }
749}
750
751#[macro_export]
770macro_rules! behave {
771 (@ $n:ident { @[ $children:expr ] $(, $($tail:tt)*)? }) => {{
773 for child in $children {
774 $n.append(child);
775 }
776 $( behave!(@ $n { $($tail)* }); )?
777 }};
778
779 (@ $n:ident { @ $subtree:expr $(, $($tail:tt)*)? }) => {{
781 $n.append_subtree($subtree);
782 $( behave!(@ $n { $($tail)* }); )?
783 }};
784
785 (@ $n:ident { $(,)? }) => { };
787
788 (@ $n:ident { $value:expr $(,)? }) => {{
790 $n.append($value);
791 }};
792
793 (@ $n:ident { $value:expr, $($tail:tt)* }) => {{
795 $n.append($value);
796 behave!(@ $n { $($tail)* });
797 }};
798
799 (@ $n:ident { $value:expr => $children:tt $(,)? }) => {{
801 let mut node = $n.append($value);
802 behave!(@ node $children);
803 }};
804
805 (@ $n:ident { $value:expr => $children:tt, $($tail:tt)* }) => {{
807 let mut node = $n.append($value);
808 behave!(@ node $children);
809 behave!(@ $n { $($tail)* });
810 }};
811
812 ($root:expr $(,)?) => { $crate::ego_tree::Tree::new($root) };
814
815 ($root:expr => $children:tt $(,)?) => {{
817 let mut tree = $crate::ego_tree::Tree::new($root);
818 {
819 let mut node = tree.root_mut();
820 behave!(@ node $children);
821 }
822 tree
823 }};
824}