Skip to content

Commit

Permalink
Store a HashMap in ActionState (#450)
Browse files Browse the repository at this point in the history
* Remove methods on Actionlike

* Revert "Remove methods on Actionlike"

This reverts commit dd9394a.

* Use a HashMap in ActionState

* Update release notes

* Remove unhelpful test

* Pass around a Hashmap when dealing with which_pressed

* Remove unhelpful doc tests

* Fix doc test

* Clippy

---------

Co-authored-by: Alice Cecile <[email protected]>
  • Loading branch information
alice-i-cecile and Alice Cecile authored Jan 23, 2024
1 parent 0e8e7bf commit a81caef
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 279 deletions.
5 changes: 5 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
- all non-insertion methods now take `&A: Actionlike` rather than `A: Actionlike` to avoid pointless cloning
- removed `multimap` dependency in favor of regular `HashMap` which allowed to derive `Reflect` for `InputMap`
- removed widely unused and untested dynamic actions functionality: this should be more feasible to implement directly with the changed architecture
- `ActionState` now stores a `HashMap` internally
- `ActionState::update` now takes a `HashMap<A, ActionState>` rather than relying on ordering
- `InputMap::which_pressed` now returns a `HashMap<A, ActionState>`
- `handle_clashes` now takes a `HashMap<A, ActionState>`
- `ClashStrategy::UseActionOrder` has been removed

## Version 0.11.2

Expand Down
23 changes: 14 additions & 9 deletions benches/action_state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bevy::prelude::Reflect;
use bevy::{prelude::Reflect, utils::HashMap};
use criterion::{criterion_group, criterion_main, Criterion};
use leafwing_input_manager::{
action_state::{ActionData, Timing},
Expand Down Expand Up @@ -37,7 +37,7 @@ fn just_released(action_state: &ActionState<TestAction>) -> bool {
action_state.just_released(&TestAction::A)
}

fn update(mut action_state: ActionState<TestAction>, action_data: Vec<ActionData>) {
fn update(mut action_state: ActionState<TestAction>, action_data: HashMap<TestAction, ActionData>) {
action_state.update(action_data);
}

Expand All @@ -52,13 +52,18 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("released", |b| b.iter(|| released(&action_state)));
c.bench_function("just_released", |b| b.iter(|| just_released(&action_state)));

let action_data: Vec<ActionData> = TestAction::variants()
.map(|_action| ActionData {
state: ButtonState::JustPressed,
value: 0.0,
axis_pair: None,
timing: Timing::default(),
consumed: false,
let action_data: HashMap<TestAction, ActionData> = TestAction::variants()
.map(|action| {
(
action,
ActionData {
state: ButtonState::JustPressed,
value: 0.0,
axis_pair: None,
timing: Timing::default(),
consumed: false,
},
)
})
.collect();

Expand Down
6 changes: 5 additions & 1 deletion benches/input_map.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::Reflect;
use bevy::utils::HashMap;
use bevy::{
input::InputPlugin,
prelude::{App, KeyCode},
Expand Down Expand Up @@ -57,7 +58,10 @@ fn construct_input_map_from_chained_calls() -> InputMap<TestAction> {
)
}

fn which_pressed(input_streams: &InputStreams, clash_strategy: ClashStrategy) -> Vec<ActionData> {
fn which_pressed(
input_streams: &InputStreams,
clash_strategy: ClashStrategy,
) -> HashMap<TestAction, ActionData> {
let input_map = construct_input_map_from_iter();
input_map.which_pressed(input_streams, clash_strategy)
}
Expand Down
6 changes: 4 additions & 2 deletions examples/arpg_indirection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ fn copy_action_state(
if let Some(matching_ability) = ability_slot_map.get(&slot) {
// This copies the `ActionData` between the ActionStates,
// including information about how long the buttons have been pressed or released
ability_state
.set_action_data(matching_ability, slot_state.action_data(&slot).clone());
ability_state.set_action_data(
matching_ability.clone(),
slot_state.action_data(&slot).unwrap().clone(),
);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions examples/mouse_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ fn update_cursor_state_from_window(
.expect("Entity does not exist, or does not have an `ActionState` component");

if let Some(val) = window.cursor_position() {
action_state.action_data_mut(&driver.action).axis_pair =
Some(DualAxisData::from_xy(val));
action_state
.action_data_mut(&driver.action)
.unwrap()
.axis_pair = Some(DualAxisData::from_xy(val));
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion examples/twin_stick_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ fn player_mouse_look(
// Press the look action, so we can check that it is active
action_state.press(&PlayerAction::Look);
// Modify the action data to set the axis
let action_data = action_state.action_data_mut(&PlayerAction::Look);
let Some(action_data) = action_state.action_data_mut(&PlayerAction::Look) else {
return;
};
// Flipping y sign here to be consistent with gamepad input. We could also invert the gamepad y axis
action_data.axis_pair = Some(DualAxisData::from_xy(Vec2::new(diff.x, -diff.y)));
}
Expand Down
Loading

0 comments on commit a81caef

Please sign in to comment.