use crate::prelude::*;
use beet_core::prelude::*;
use beet_flow::prelude::*;
#[derive(Debug, Default, Clone, PartialEq, Component, Reflect)]
#[reflect(Default, Component)]
#[require(ContinueRun)]
pub struct Seek {
pub on_not_found: OnTargetNotFound,
}
impl Seek {
pub fn new(on_not_found: OnTargetNotFound) -> Self { Self { on_not_found } }
}
#[derive(Debug, Default, Clone, PartialEq, Reflect)]
pub enum OnTargetNotFound {
#[default]
Warn,
Clear,
Fail,
Succeed,
Ignore,
}
pub(crate) fn seek(
mut commands: Commands,
transforms: Query<&GlobalTransform>,
mut agents: AgentQuery<(
Entity,
&GlobalTransform,
&Velocity,
&SteerTarget,
&MaxSpeed,
&mut Impulse,
Option<&ArriveRadius>,
)>,
query: Query<(Entity, &Seek), With<Running>>,
) -> Result {
for (action, seek) in query.iter() {
let (
agent_entity,
transform,
velocity,
steer_target,
max_speed,
mut impulse,
arrive_radius,
) = agents.get_mut(action)?;
match (&seek.on_not_found, steer_target.get_position(&transforms)) {
(_, Ok(target_position)) => {
*impulse = seek_impulse(
&transform.translation(),
&velocity,
&target_position,
*max_speed,
arrive_radius.copied(),
);
}
(OnTargetNotFound::Clear, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
}
(OnTargetNotFound::Fail, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
commands.entity(action).trigger_target(Outcome::Fail);
}
(OnTargetNotFound::Succeed, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
commands.entity(action).trigger_target(Outcome::Pass);
}
(OnTargetNotFound::Ignore, Err(_)) => {}
(OnTargetNotFound::Warn, Err(msg)) => {
log::warn!("{}", msg);
}
}
}
Ok(())
}
#[cfg(test)]
mod test {
use crate::prelude::*;
use beet_core::prelude::*;
use beet_flow::prelude::*;
#[test]
fn works() {
let mut app = App::new();
app.add_plugins((ControlFlowPlugin::default(), BeetSpatialPlugins))
.insert_time();
let agent = app
.world_mut()
.spawn((
Transform::default(),
ForceBundle::default(),
SteerBundle::default(),
SteerTarget::Position(Vec3::new(1.0, 0., 0.)),
Seek::default(),
))
.trigger_target(GetOutcome)
.id();
app.update_with_secs(1);
app.world()
.get::<Transform>(agent)
.unwrap()
.translation
.xpect_eq(Vec3::new(0.01, 0., 0.));
}
}