Skip to content

Commit

Permalink
Split ActionData::update into multiple methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Shatur committed Oct 28, 2024
1 parent 0d5dffe commit 670f18b
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 44 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
13 changes: 11 additions & 2 deletions src/input_context/context_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use super::{
use crate::{
action_value::{ActionValue, ActionValueDim},
input::{input_reader::InputReader, GamepadDevice, Input},
ActionState,
};

/// Instance for [`InputContext`](super::InputContext).
Expand Down Expand Up @@ -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),
);
}
}
}
Expand Down Expand Up @@ -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);
}
}

Expand Down
59 changes: 23 additions & 36 deletions src/input_context/input_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,14 @@ impl ActionData {
state: Default::default(),
elapsed_secs: 0.0,
fired_secs: 0.0,
trigger_events: Self::trigger::<A>,
trigger_events: Self::trigger_events_typed::<A>,
}
}

/// Updates internal state and triggers corresponding events.
pub fn update(
&mut self,
commands: &mut Commands,
time: &Time<Virtual>,
entities: &[Entity],
state: ActionState,
value: impl Into<ActionValue>,
) {
// 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<Virtual>) {
match self.state {
ActionState::None => (),
ActionState::Ongoing => {
Expand All @@ -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<ActionValue>,
) {
(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;
Expand All @@ -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<A: InputAction>(
fn trigger_events_typed<A: InputAction>(
&self,
commands: &mut Commands,
entities: &[Entity],
Expand Down
5 changes: 2 additions & 3 deletions src/input_context/input_condition/block_by.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,10 @@ mod tests {
fn block() {
let mut condition = BlockBy::<DummyAction>::default();
let mut action = ActionData::new::<DummyAction>();
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::<DummyAction>(action);
let time = Time::default();

assert_eq!(
condition.evaluate(&actions, &time, true.into()),
Expand Down
5 changes: 2 additions & 3 deletions src/input_context/input_condition/chord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,10 @@ mod tests {
fn chord() {
let mut condition = Chord::<DummyAction>::default();
let mut action = ActionData::new::<DummyAction>();
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::<DummyAction>(action);
let time = Time::default();

assert_eq!(
condition.evaluate(&actions, &time, true.into()),
Expand Down

0 comments on commit 670f18b

Please sign in to comment.