bevy_enhanced_input/input_condition/
block_by.rs1use core::{any, marker::PhantomData};
2
3use bevy::prelude::*;
4
5use super::{ConditionKind, InputCondition};
6use crate::{
7 action_map::{ActionMap, ActionState},
8 action_value::ActionValue,
9 input_action::InputAction,
10};
11
12#[derive(Debug)]
14pub struct BlockBy<A: InputAction> {
15 marker: PhantomData<A>,
17
18 pub events_only: bool,
22}
23
24impl<A: InputAction> BlockBy<A> {
25 pub fn events_only() -> Self {
32 Self {
33 marker: PhantomData,
34 events_only: true,
35 }
36 }
37}
38
39impl<A: InputAction> Default for BlockBy<A> {
40 fn default() -> Self {
41 Self {
42 marker: PhantomData,
43 events_only: false,
44 }
45 }
46}
47
48impl<A: InputAction> Clone for BlockBy<A> {
49 fn clone(&self) -> Self {
50 *self
51 }
52}
53
54impl<A: InputAction> Copy for BlockBy<A> {}
55
56impl<A: InputAction> InputCondition for BlockBy<A> {
57 fn evaluate(
58 &mut self,
59 action_map: &ActionMap,
60 _time: &Time<Virtual>,
61 _value: ActionValue,
62 ) -> ActionState {
63 if let Some(action) = action_map.action::<A>() {
64 if action.state() == ActionState::Fired {
65 return ActionState::None;
66 }
67 } else {
68 warn_once!(
69 "action `{}` is not present in context",
70 any::type_name::<A>()
71 );
72 }
73
74 ActionState::Fired
75 }
76
77 fn kind(&self) -> ConditionKind {
78 ConditionKind::Blocker {
79 events_only: self.events_only,
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use bevy_enhanced_input_macros::InputAction;
87
88 use super::*;
89 use crate::action_map::Action;
90
91 #[test]
92 fn block() {
93 let mut condition = BlockBy::<DummyAction>::default();
94 let mut action = Action::new::<DummyAction>();
95 let time = Time::default();
96 action.update(&time, ActionState::Fired, true);
97 let mut action_map = ActionMap::default();
98 action_map.insert_action::<DummyAction>(action);
99
100 assert_eq!(
101 condition.evaluate(&action_map, &time, true.into()),
102 ActionState::None,
103 );
104 }
105
106 #[test]
107 fn missing_action() {
108 let mut condition = BlockBy::<DummyAction>::default();
109 let action_map = ActionMap::default();
110 let time = Time::default();
111
112 assert_eq!(
113 condition.evaluate(&action_map, &time, true.into()),
114 ActionState::Fired,
115 );
116 }
117
118 #[derive(Debug, InputAction)]
119 #[input_action(output = bool)]
120 struct DummyAction;
121}