use bevy::{ecs::component::ComponentId, prelude::*};
use crate::{
ecs::TargetedAction,
event::{ActionEndReason, OnActionEnded, OnActionInitiated, RequestAction},
picking::Picker,
};
pub struct ActionPlugin;
impl Plugin for ActionPlugin {
fn build(&self, app: &mut App) {
app.observe(Self::on_request_cancel_and_initiate)
.observe(Self::on_ended_request_again);
}
}
impl ActionPlugin {
pub fn on_request_cancel_and_initiate(
trigger: Trigger<RequestAction>,
mut commands: Commands,
mut actors: Query<(&Picker, Option<&CurrentAction>)>,
) {
let actor = trigger.entity();
let requested = trigger.event().action;
if let Ok((picker, current_action)) = actors.get_mut(actor) {
let current_action = current_action.map(|ca| ca.0);
let next_action = requested.unwrap_or(picker.picked);
if let Some(current_action) = current_action {
if next_action == current_action {
return;
}
commands.trigger_targets(
OnActionEnded::cancelled(current_action),
TargetedAction(actor, current_action),
);
}
commands.entity(actor).insert(CurrentAction(next_action));
commands.trigger_targets(
OnActionInitiated { action: next_action },
TargetedAction(actor, next_action),
);
}
}
pub fn on_ended_request_again(trigger: Trigger<OnActionEnded>, mut commands: Commands) {
let actor = trigger.entity();
match trigger.event().reason {
ActionEndReason::Completed => {
commands.trigger_targets(RequestAction { action: None }, actor);
}
ActionEndReason::Cancelled => {
}
}
}
}
#[derive(Component, Reflect)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[reflect(Component)]
pub struct CurrentAction(pub ComponentId);
pub fn on_action_initiated_insert_default<Action: Component + Default>(
trigger: Trigger<OnActionInitiated, Action>,
mut commands: Commands,
) {
let actor = trigger.entity();
commands.entity(actor).insert(Action::default());
}
pub fn on_action_initiated_insert_from_resource<Action: Component + Resource + Clone>(
trigger: Trigger<OnActionInitiated, Action>,
mut commands: Commands,
resource: Res<Action>,
) {
let actor = trigger.entity();
commands.entity(actor).insert(resource.clone());
}
pub fn on_action_ended_remove<Action: Component>(trigger: Trigger<OnActionEnded, Action>, mut commands: Commands) {
let actor = trigger.entity();
commands.entity(actor).remove::<Action>();
}