Skip to content

Commit

Permalink
Fix InputMap::merge (#621)
Browse files Browse the repository at this point in the history
* Fix `InputMap::merge`

* Remove unnecessary swizzle

* minor

* minor

* RELEASES.md
  • Loading branch information
Shute052 authored Sep 10, 2024
1 parent a123723 commit 7d500aa
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 48 deletions.
3 changes: 2 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- added `TripleAxislikeChord` that groups a `Buttonlike` and a `TripleAxislike` together.
- added related variants such as:
- `InputControlType::TripleAxis`
- `ActionDiff::TripleAxisChanged`
- `ActionDiff::TripleAxisChanged`

### Usability (0.15.1)

Expand All @@ -32,6 +32,7 @@
### Bugs (0.15.1)

- `InputMap::get_pressed` and siblings now check if the action kind is buttonlike before checking if they are pressed or released, avoiding a debug-mode panic
- `InputMap::merge` is now compatible with all input kinds, previously limited to buttons

## Version 0.15.0

Expand Down
5 changes: 2 additions & 3 deletions examples/twin_stick_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,13 @@ fn control_player(
if action_state.axis_pair(&PlayerAction::Move) != Vec2::ZERO {
// Note: In a real game we'd feed this into an actual player controller
// and respects the camera extrinsics to ensure the direction is correct
let move_delta =
time.delta_seconds() * action_state.clamped_axis_pair(&PlayerAction::Move).xy();
let move_delta = time.delta_seconds() * action_state.clamped_axis_pair(&PlayerAction::Move);
player_transform.translation += Vec3::new(move_delta.x, 0.0, move_delta.y);
println!("Player moved to: {}", player_transform.translation.xz());
}

if action_state.axis_pair(&PlayerAction::Look) != Vec2::ZERO {
let look = action_state.axis_pair(&PlayerAction::Look).xy().normalize();
let look = action_state.axis_pair(&PlayerAction::Look).normalize();
println!("Player looking in direction: {}", look);
}

Expand Down
84 changes: 40 additions & 44 deletions src/input_map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! This module contains [`InputMap`] and its supporting methods and impls.

use std::fmt::Debug;
use std::hash::Hash;

#[cfg(feature = "asset")]
use bevy::asset::Asset;
Expand Down Expand Up @@ -222,26 +223,23 @@ impl<A: Actionlike> InputMap<A> {
}
}

// Insertion
impl<A: Actionlike> InputMap<A> {
/// Inserts a binding between an `action` and a specific boxed dyn [`Buttonlike`].
/// Multiple inputs can be bound to the same action.
///
/// This method ensures idempotence, meaning that adding the same input
/// for the same action multiple times will only result in a single binding being created.
#[inline(always)]
fn insert_boxed(&mut self, action: A, button: Box<dyn Buttonlike>) -> &mut Self {
if let Some(bindings) = self.buttonlike_map.get_mut(&action) {
if !bindings.contains(&button) {
bindings.push(button);
}
} else {
self.buttonlike_map.insert(action, vec![button]);
#[inline(always)]
fn insert_unique<K, V>(map: &mut HashMap<K, Vec<V>>, key: &K, value: V)
where
K: Clone + Eq + Hash,
V: PartialEq,
{
if let Some(list) = map.get_mut(key) {
if !list.contains(&value) {
list.push(value);
}

self
} else {
map.insert(key.clone(), vec![value]);
}
}

// Insertion
impl<A: Actionlike> InputMap<A> {
/// Inserts a binding between an `action` and a specific [`Buttonlike`] `input`.
/// Multiple inputs can be bound to the same action.
///
Expand All @@ -267,7 +265,7 @@ impl<A: Actionlike> InputMap<A> {
return self;
}

self.insert_boxed(action, Box::new(button));
insert_unique(&mut self.buttonlike_map, &action, Box::new(button));
self
}

Expand Down Expand Up @@ -296,14 +294,7 @@ impl<A: Actionlike> InputMap<A> {
return self;
}

let axis = Box::new(axis) as Box<dyn Axislike>;
if let Some(bindings) = self.axislike_map.get_mut(&action) {
if !bindings.contains(&axis) {
bindings.push(axis);
}
} else {
self.axislike_map.insert(action, vec![axis]);
}
insert_unique(&mut self.axislike_map, &action, Box::new(axis));
self
}

Expand Down Expand Up @@ -332,14 +323,7 @@ impl<A: Actionlike> InputMap<A> {
return self;
}

let dual_axis = Box::new(dual_axis) as Box<dyn DualAxislike>;
if let Some(bindings) = self.dual_axislike_map.get_mut(&action) {
if !bindings.contains(&dual_axis) {
bindings.push(dual_axis);
}
} else {
self.dual_axislike_map.insert(action, vec![dual_axis]);
}
insert_unique(&mut self.dual_axislike_map, &action, Box::new(dual_axis));
self
}

Expand Down Expand Up @@ -368,14 +352,8 @@ impl<A: Actionlike> InputMap<A> {
return self;
}

let triple_axis = Box::new(triple_axis) as Box<dyn TripleAxislike>;
if let Some(bindings) = self.triple_axislike_map.get_mut(&action) {
if !bindings.contains(&triple_axis) {
bindings.push(triple_axis);
}
} else {
self.triple_axislike_map.insert(action, vec![triple_axis]);
}
let boxed = Box::new(triple_axis);
insert_unique(&mut self.triple_axislike_map, &action, boxed);
self
}

Expand Down Expand Up @@ -433,9 +411,27 @@ impl<A: Actionlike> InputMap<A> {
self.clear_gamepad();
}

for (other_action, other_inputs) in other.buttonlike_map.iter() {
for (other_action, other_inputs) in other.iter_buttonlike() {
for other_input in other_inputs.iter().cloned() {
insert_unique(&mut self.buttonlike_map, other_action, other_input);
}
}

for (other_action, other_inputs) in other.iter_axislike() {
for other_input in other_inputs.iter().cloned() {
insert_unique(&mut self.axislike_map, other_action, other_input);
}
}

for (other_action, other_inputs) in other.iter_dual_axislike() {
for other_input in other_inputs.iter().cloned() {
insert_unique(&mut self.dual_axislike_map, other_action, other_input);
}
}

for (other_action, other_inputs) in other.iter_triple_axislike() {
for other_input in other_inputs.iter().cloned() {
self.insert_boxed(other_action.clone(), other_input);
insert_unique(&mut self.triple_axislike_map, other_action, other_input);
}
}

Expand Down

0 comments on commit 7d500aa

Please sign in to comment.