diff --git a/CHANGELOG.md b/CHANGELOG.md
index f57a5be..cf1bf97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rename `Pressed` into `Press`.
- Rename `BlockedBy` into `BlockBy`.
- Rename `Scalar` into `Scale`.
+- Split `ActionData::update` into `ActionData::update_time`, `ActionData::trigger_events` and `ActionData::set_state`.
- Use `isize` for `InputContext::PRIORITY`.
- Replace `SmoothDelta` with `LerpDelta` that does only linear interpolation. Using easing functions for inputs doesn't make much sense.
- Modifiers are now allowed to change passed value dimensions.
@@ -35,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `ignore_incompatible!` since no longer needed.
- `SwizzleAxis::XXX`, `SwizzleAxis::YYY` and `SwizzleAxis::ZZZ`. They encourage a bad pattern of defining actions with duplicate data. Duplicate axes inside the trigger if needed.
+- `ActionData::trigger_removed`, use `ActionData::trigger_events` instead.
## [0.1.0] - 2024-10-20
diff --git a/src/input_context/context_instance.rs b/src/input_context/context_instance.rs
index f68d6bc..8747127 100644
--- a/src/input_context/context_instance.rs
+++ b/src/input_context/context_instance.rs
@@ -11,6 +11,7 @@ use super::{
use crate::{
action_value::{ActionValue, ActionValueDim},
input::{input_reader::InputReader, GamepadDevice, Input},
+ ActionState,
};
/// Instance for [`InputContext`](super::InputContext).
@@ -95,7 +96,13 @@ impl ContextInstance {
.actions
.get(&binding.type_id)
.expect("actions and bindings should have matching type IDs");
- action.trigger_removed(commands, entities, binding.dim);
+
+ action.trigger_events(
+ commands,
+ entities,
+ ActionState::None,
+ ActionValue::zero(binding.dim),
+ );
}
}
}
@@ -298,7 +305,9 @@ impl ActionBind {
let state = tracker.state();
let value = tracker.value().convert(self.dim);
- action.update(commands, time, entities, state, value);
+ action.update_time(time);
+ action.trigger_events(commands, entities, state, value);
+ action.set_state(state);
}
}
diff --git a/src/input_context/input_action.rs b/src/input_context/input_action.rs
index 7c83a65..45a946f 100644
--- a/src/input_context/input_action.rs
+++ b/src/input_context/input_action.rs
@@ -47,21 +47,14 @@ impl ActionData {
state: Default::default(),
elapsed_secs: 0.0,
fired_secs: 0.0,
- trigger_events: Self::trigger::,
+ trigger_events: Self::trigger_events_typed::,
}
}
- /// Updates internal state and triggers corresponding events.
- pub fn update(
- &mut self,
- commands: &mut Commands,
- time: &Time,
- entities: &[Entity],
- state: ActionState,
- value: impl Into,
- ) {
- // Add time from the previous frame if needed
- // before triggering events.
+ /// Adds time from the previous frame if needed
+ ///
+ /// Should be called before [`Self::trigger_events`].
+ pub fn update_time(&mut self, time: &Time) {
match self.state {
ActionState::None => (),
ActionState::Ongoing => {
@@ -72,11 +65,27 @@ impl ActionData {
self.fired_secs += time.delta_seconds();
}
}
+ }
+ /// Triggers events for transitioning from the current state to the specified `state`.
+ ///
+ /// Should be called after [`Self::update_time`] and before [`Self::set_state`].
+ pub fn trigger_events(
+ &self,
+ commands: &mut Commands,
+ entities: &[Entity],
+ state: ActionState,
+ value: impl Into,
+ ) {
(self.trigger_events)(self, commands, entities, state, value.into());
- self.state = state;
+ }
+ /// Sets state and resets time if necessary.
+ ///
+ /// Should be called after [`Self::trigger_events`].
+ pub fn set_state(&mut self, state: ActionState) {
// Reset time for updated state.
+ self.state = state;
match self.state {
ActionState::None => {
self.elapsed_secs = 0.0;
@@ -89,29 +98,7 @@ impl ActionData {
}
}
- /// Trigger events for removed entities.
- ///
- /// This will trigger transition from the current state to [`ActionState::None`]
- /// simulating releasing the input.
- ///
- /// Internal state won't be updated.
- /// Called for removed entities for shared contexts or for context removals.
- pub fn trigger_removed(
- &self,
- commands: &mut Commands,
- entities: &[Entity],
- dim: ActionValueDim,
- ) {
- (self.trigger_events)(
- self,
- commands,
- entities,
- ActionState::None,
- ActionValue::zero(dim),
- );
- }
-
- fn trigger(
+ fn trigger_events_typed(
&self,
commands: &mut Commands,
entities: &[Entity],
diff --git a/src/input_context/input_condition/block_by.rs b/src/input_context/input_condition/block_by.rs
index bf88ade..2ec5beb 100644
--- a/src/input_context/input_condition/block_by.rs
+++ b/src/input_context/input_condition/block_by.rs
@@ -70,11 +70,10 @@ mod tests {
fn block() {
let mut condition = BlockBy::::default();
let mut action = ActionData::new::();
- let mut world = World::new();
- let time = Time::default();
- action.update(&mut world.commands(), &time, &[], ActionState::Fired, true);
+ action.set_state(ActionState::Fired);
let mut actions = ActionsData::default();
actions.insert_action::(action);
+ let time = Time::default();
assert_eq!(
condition.evaluate(&actions, &time, true.into()),
diff --git a/src/input_context/input_condition/chord.rs b/src/input_context/input_condition/chord.rs
index d6de95e..b2b9f23 100644
--- a/src/input_context/input_condition/chord.rs
+++ b/src/input_context/input_condition/chord.rs
@@ -71,11 +71,10 @@ mod tests {
fn chord() {
let mut condition = Chord::::default();
let mut action = ActionData::new::();
- let mut world = World::new();
- let time = Time::default();
- action.update(&mut world.commands(), &time, &[], ActionState::Fired, true);
+ action.set_state(ActionState::Fired);
let mut actions = ActionsData::default();
actions.insert_action::(action);
+ let time = Time::default();
assert_eq!(
condition.evaluate(&actions, &time, true.into()),