diff --git a/crates/beet_flow/src/actions/global/end_continued_run.rs b/crates/beet_flow/src/actions/global/end_continued_run.rs index b88e0225..2ea78694 100644 --- a/crates/beet_flow/src/actions/global/end_continued_run.rs +++ b/crates/beet_flow/src/actions/global/end_continued_run.rs @@ -9,7 +9,10 @@ pub fn end_continued_run( mut commands: Commands, running: Populated>, children: Query<&Children>, - children_should_remove: Populated<(), (With, Without)>, + children_should_remove: Populated< + (), + (With, Without), + >, ) { if let Some(entity) = running.get(trigger.entity()).ok() { commands.entity(entity).remove::(); diff --git a/crates/beet_flow/src/actions/misc/repeat.rs b/crates/beet_flow/src/actions/misc/repeat.rs index 6d9bd102..ddb71234 100644 --- a/crates/beet_flow/src/actions/misc/repeat.rs +++ b/crates/beet_flow/src/actions/misc/repeat.rs @@ -1,6 +1,28 @@ use crate::prelude::*; +use bevy::prelude::*; -/// This does **not** trigger observers, making it safe from infinite loops -/// Reattaches the [`RunOnSpawn`] component whenever [`OnRunResult`] is called. -pub type Repeat = InsertOnRunResult; + + +// /// This does **not** trigger observers, making it safe from infinite loops +// /// Reattaches the [`RunOnSpawn`] component whenever [`OnRunResult`] is called. +#[derive(Debug, Clone, PartialEq, Component, Action, Reflect)] +#[reflect(Default, Component, ActionMeta)] +#[category(ActionCategory::Behavior)] +#[observers(repeat)] +pub struct Repeat { + // TODO times + // pub times: RepeatAnimation, +} + +impl Default for Repeat { + fn default() -> Self { + Self { + // times: RepeatAnimation::Forever, + } + } +} + +fn repeat(trigger: Trigger, mut commands: Commands) { + commands.entity(trigger.entity()).insert(RunOnSpawn); +} diff --git a/crates/beet_flow/src/lifecycle/lifecycle_plugin.rs b/crates/beet_flow/src/lifecycle/lifecycle_plugin.rs index 3a374813..9064f178 100644 --- a/crates/beet_flow/src/lifecycle/lifecycle_plugin.rs +++ b/crates/beet_flow/src/lifecycle/lifecycle_plugin.rs @@ -25,6 +25,10 @@ impl Plugin for LifecyclePlugin { RunTimer, LogOnRun, Repeat, + InsertOnRun, + RemoveOnRun, + InsertOnRunResult, + RemoveOnRunResult, SequenceFlow, FallbackFlow, ParallelFlow, diff --git a/crates/emby/examples/emote_arm.rs b/crates/emby/examples/emote_arm.rs index fe57ebc1..a9f1c7dc 100644 --- a/crates/emby/examples/emote_arm.rs +++ b/crates/emby/examples/emote_arm.rs @@ -4,14 +4,15 @@ use emby::prelude::*; pub fn main() { App::new() - .add_plugins((crate_test_beet_example_plugin, EmbyPlugin)) + .add_plugins((crate_test_beet_example_plugin, plugin_ml, EmbyPlugin)) .add_systems( Startup, ( beetmash::core::scenes::lighting_3d, beetmash::core::scenes::ground_3d, - beet_examples::scenes::flow::beet_debug_start_and_stop, - beet_examples::scenes::spatial::spawn_ik_camera, + beetmash::core::scenes::ui_terminal_input, + // beet_examples::scenes::flow::beet_debug_start_and_stop, + emby::scenes::emote_arm_camera, emby::scenes::emote_arm, emby::scenes::spawn_barbarian, emby::scenes::phone_texture_camera_3d, diff --git a/crates/emby/examples/interaction.rs b/crates/emby/examples/interaction.rs index 68204ecd..648de4e2 100644 --- a/crates/emby/examples/interaction.rs +++ b/crates/emby/examples/interaction.rs @@ -1,6 +1,7 @@ use beet::prelude::*; use beet_examples::prelude::*; use bevy::prelude::*; +use bevy::render::view::RenderLayers; use emby::prelude::*; fn main() { @@ -23,6 +24,7 @@ fn main() { fn setup(mut commands: Commands) { commands.spawn(( Camera3d::default(), - Transform::from_xyz(0., 1.6, 5.) + RenderLayers::layer(0).with(RENDER_TEXTURE_LAYER), + Transform::from_xyz(0., 1.6, 5.), )); } diff --git a/crates/emby/src/scenes/emote_arm.rs b/crates/emby/src/scenes/emote_arm.rs index 897859f0..cbcb1f6f 100644 --- a/crates/emby/src/scenes/emote_arm.rs +++ b/crates/emby/src/scenes/emote_arm.rs @@ -1,14 +1,26 @@ use beet::prelude::*; use beetmash::prelude::*; -use bevy::color::palettes::tailwind; use bevy::prelude::*; use forky::prelude::TransformExt; +use std::f32::consts::TAU; use std::time::Duration; + + +pub fn emote_arm_camera(mut commands: Commands) { + commands.spawn(( + Name::new("Camera"), + BundlePlaceholder::Camera3d, + Transform::from_xyz(0., 2., 5.) + .looking_at(Vec3::new(0., 2., 0.), Vec3::Y), + )); +} + + pub fn emote_arm(mut commands: Commands) { let mut target = Entity::PLACEHOLDER; - let pos_happy = Vec3::new(0., 3., 0.); + let pos_happy = Vec3::new(0., 2.5, 0.); let pos_idle = Vec3::new(0., 2., 0.); let transform_idle = Transform::from_translation(pos_idle) @@ -22,10 +34,14 @@ pub fn emote_arm(mut commands: Commands) { .spawn((Name::new("Target Parent"), transform_idle)) .with_children(|parent| { target = parent - .spawn((Name::new("Target"), BundlePlaceholder::Pbr { - mesh: Sphere::new(0.2).into(), - material: MaterialPlaceholder::unlit(tailwind::BLUE_500), - })) + .spawn(( + Name::new("Target"), + Transform::default(), + // BundlePlaceholder::Pbr { + // mesh: Sphere::new(0.2).into(), + // material: MaterialPlaceholder::unlit(tailwind::BLUE_500), + // } + )) .id(); }) .id(); @@ -39,9 +55,9 @@ pub fn emote_arm(mut commands: Commands) { IkSpawner::default(), )); - commands + let idle_behavior = commands .spawn(( - Name::new("Behavior"), + Name::new("Idle Behavior"), RunOnSpawn, Repeat::default(), SequenceFlow, @@ -51,7 +67,10 @@ pub fn emote_arm(mut commands: Commands) { Name::new("New Pos"), InsertOnRun::new(transform_idle).with_target(target_parent), TargetAgent(target), - SetCurveOnRun::default(), + SetCurveOnRun::EaseRangeDir2 { + range: -TAU * 0.1..TAU * 0.1, + func: EaseFunction::CubicInOut, + }, PlayProceduralAnimation::default() // .with_meter_per_second(1.), .with_duration_secs(2.), @@ -63,15 +82,23 @@ pub fn emote_arm(mut commands: Commands) { Duration::from_secs(1)..Duration::from_secs(4), ), )); - parent.spawn(( - Name::new("Happy"), - TargetAgent(target_parent), - SetCurveOnRun::PingPongPause { - target: pos_happy, - pause: 1., - func: EaseFunction::CubicInOut, - }, - PlayProceduralAnimation::default().with_duration_secs(4.), - )); - }); + }) + .id(); + + commands.spawn(( + Name::new("Happy"), + RemoveOnRun::::default().with_target(idle_behavior), + EndOnRun::success().with_target(idle_behavior), + TargetAgent(target_parent), + InsertSentenceOnUserInput::default(), + RunOnInsertSentence::default(), + SetCurveOnRun::PingPongPause { + target: pos_happy, + pause: 0.1, + func: EaseFunction::CubicInOut, + }, + PlayProceduralAnimation::default().with_duration_secs(2.), + RunOnRunResult::new_with_target(idle_behavior), + InsertOnRunResult::::default().with_target(idle_behavior), + )); }