use bevy::prelude::*;
use log::warn;
use smallvec::{SmallVec, smallvec};
use crate::prelude::*;
#[derive(Component, Reflect, Debug, Clone)]
pub struct BlockBy {
pub actions: SmallVec<[Entity; 2]>,
}
impl BlockBy {
#[must_use]
pub fn single(action: Entity) -> Self {
Self::new(smallvec![action])
}
#[must_use]
pub fn new(actions: impl Into<SmallVec<[Entity; 2]>>) -> Self {
Self {
actions: actions.into(),
}
}
}
impl InputCondition for BlockBy {
fn evaluate(
&mut self,
actions: &ActionsQuery,
_time: &ContextTime,
_value: ActionValue,
) -> ActionState {
for &action in &self.actions {
let Ok((_, &state, ..)) = actions.get(action) else {
warn!("`{action}` is not a valid action");
continue;
};
if state == ActionState::Fired {
return ActionState::None;
}
}
ActionState::Fired
}
fn kind(&self) -> ConditionKind {
ConditionKind::Blocker
}
}
#[cfg(test)]
mod tests {
use bevy_enhanced_input_macros::InputAction;
use super::*;
use crate::context;
#[test]
fn block() {
let (mut world, mut state) = context::init_world();
let action = world
.spawn((Action::<Test>::new(), ActionState::Fired))
.id();
let (time, actions) = state.get(&world);
let mut condition = BlockBy::single(action);
assert_eq!(
condition.evaluate(&actions, &time, true.into()),
ActionState::None,
);
}
#[test]
fn missing_action() {
let (world, mut state) = context::init_world();
let (time, actions) = state.get(&world);
let mut condition = BlockBy::single(Entity::PLACEHOLDER);
assert_eq!(
condition.evaluate(&actions, &time, true.into()),
ActionState::Fired,
);
}
#[derive(InputAction)]
#[action_output(bool)]
struct Test;
}