Skip to content

Commit

Permalink
Add ValueChange and AxisPairChange variants to ActionDiff (#422)
Browse files Browse the repository at this point in the history
* Add axis change event to ActionDiff

* Removed unneeded axis mutation

* Add support for value and axis_pair changes in
ActionDiff

* Fix action data value and axis pair reset

* added tests for ActionDiff systems
  • Loading branch information
WesleyClements authored Dec 13, 2023
1 parent 42e2fed commit 7a92892
Show file tree
Hide file tree
Showing 5 changed files with 532 additions and 10 deletions.
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- added support in `ActionDiff` for value and axis_pair changes
- Added `InputMap::Clear`.

## Version 0.11.2
Expand Down
2 changes: 1 addition & 1 deletion examples/send_actions_over_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ enum FpsAction {
}

/// This identifier uniquely identifies entities across the network
#[derive(Component, Clone, PartialEq, Eq, Debug)]
#[derive(Component, Clone, PartialEq, Eq, Hash, Debug)]
struct StableId(u64);

fn main() {
Expand Down
21 changes: 20 additions & 1 deletion src/action_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::Actionlike;
use crate::{axislike::DualAxisData, buttonlike::ButtonState};

use bevy::ecs::{component::Component, entity::Entity};
use bevy::math::Vec2;
use bevy::prelude::{Event, Resource};
use bevy::reflect::Reflect;
use bevy::utils::hashbrown::hash_set::Iter;
Expand Down Expand Up @@ -758,7 +759,7 @@ impl Timing {
///
/// `ID` should be a component type that stores a unique stable identifier for the entity
/// that stores the corresponding [`ActionState`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Event)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Event)]
pub enum ActionDiff<A: Actionlike, ID: Eq + Clone + Component> {
/// The action was pressed
Pressed {
Expand All @@ -774,6 +775,24 @@ pub enum ActionDiff<A: Actionlike, ID: Eq + Clone + Component> {
/// The stable identifier of the entity
id: ID,
},
/// The value of the action changed
ValueChanged {
/// The value of the action
action: A,
/// The stable identifier of the entity
id: ID,
/// The new value of the action
value: f32,
},
/// The axis pair of the action changed
AxisPairChanged {
/// The value of the action
action: A,
/// The stable identifier of the entity
id: ID,
/// The new value of the axis
axis_pair: Vec2,
},
}

#[cfg(test)]
Expand Down
123 changes: 115 additions & 8 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::action_state::ActionStateDriver;
use crate::{
action_state::{ActionDiff, ActionState},
axislike::DualAxisData,
clashing_inputs::ClashStrategy,
input_map::InputMap,
input_streams::InputStreams,
Expand All @@ -12,8 +13,6 @@ use crate::{
Actionlike,
};

use bevy::time::Time;
use bevy::utils::Instant;
use bevy::{ecs::prelude::*, prelude::ScanCode};
use bevy::{
input::{
Expand All @@ -22,8 +21,11 @@ use bevy::{
mouse::{MouseButton, MouseMotion, MouseWheel},
Axis, Input,
},
time::Real,
math::Vec2,
time::{Real, Time},
utils::{HashMap, Instant},
};
use core::hash::Hash;

#[cfg(feature = "ui")]
use bevy::ui::Interaction;
Expand Down Expand Up @@ -187,23 +189,100 @@ pub fn update_action_state_from_interaction<A: Actionlike>(
/// suitable to be sent across a network.
///
/// This system is not part of the [`InputManagerPlugin`](crate::plugin::InputManagerPlugin) and must be added manually.
pub fn generate_action_diffs<A: Actionlike, ID: Eq + Clone + Component>(
pub fn generate_action_diffs<A: Actionlike, ID: Eq + Clone + Component + Hash>(
action_state_query: Query<(&ActionState<A>, &ID)>,
mut action_diffs: EventWriter<ActionDiff<A, ID>>,
mut previous_values: Local<HashMap<A, HashMap<ID, f32>>>,
mut previous_axis_pairs: Local<HashMap<A, HashMap<ID, Vec2>>>,
) {
for (action_state, id) in action_state_query.iter() {
for action in action_state.get_just_pressed() {
action_diffs.send(ActionDiff::Pressed {
action: action.clone(),
id: id.clone(),
});
match action_state.action_data(action.clone()).axis_pair {
Some(axis_pair) => {
action_diffs.send(ActionDiff::AxisPairChanged {
action: action.clone(),
id: id.clone(),
axis_pair: axis_pair.into(),
});
previous_axis_pairs
.raw_entry_mut()
.from_key(&action)
.or_insert_with(|| (action.clone(), HashMap::default()))
.1
.insert(id.clone(), axis_pair.xy());
}
None => {
let value = action_state.value(action.clone());
action_diffs.send(if value == 1. {
ActionDiff::Pressed {
action: action.clone(),
id: id.clone(),
}
} else {
ActionDiff::ValueChanged {
action: action.clone(),
id: id.clone(),
value,
}
});
previous_values
.raw_entry_mut()
.from_key(&action)
.or_insert_with(|| (action.clone(), HashMap::default()))
.1
.insert(id.clone(), value);
}
}
}
for action in action_state.get_pressed() {
if action_state.just_pressed(action.clone()) {
continue;
}
match action_state.action_data(action.clone()).axis_pair {
Some(axis_pair) => {
let previous_axis_pairs = previous_axis_pairs.get_mut(&action).unwrap();

if let Some(previous_axis_pair) = previous_axis_pairs.get(&id.clone()) {
if *previous_axis_pair == axis_pair.xy() {
continue;
}
}
action_diffs.send(ActionDiff::AxisPairChanged {
action: action.clone(),
id: id.clone(),
axis_pair: axis_pair.into(),
});
previous_axis_pairs.insert(id.clone(), axis_pair.xy());
}
None => {
let value = action_state.value(action.clone());
let previous_values = previous_values.get_mut(&action).unwrap();

if let Some(previous_value) = previous_values.get(&id.clone()) {
if *previous_value == value {
continue;
}
}
action_diffs.send(ActionDiff::ValueChanged {
action: action.clone(),
id: id.clone(),
value,
});
previous_values.insert(id.clone(), value);
}
}
}
for action in action_state.get_just_released() {
action_diffs.send(ActionDiff::Released {
action: action.clone(),
id: id.clone(),
});
if let Some(previous_axes) = previous_axis_pairs.get_mut(&action) {
previous_axes.remove(&id.clone());
}
if let Some(previous_values) = previous_values.get_mut(&action) {
previous_values.remove(&id.clone());
}
}
}
}
Expand All @@ -228,6 +307,7 @@ pub fn process_action_diffs<A: Actionlike, ID: Eq + Component + Clone>(
} => {
if event_id == id {
action_state.press(action.clone());
action_state.action_data_mut(action.clone()).value = 1.;
continue;
}
}
Expand All @@ -237,6 +317,33 @@ pub fn process_action_diffs<A: Actionlike, ID: Eq + Component + Clone>(
} => {
if event_id == id {
action_state.release(action.clone());
let action_data = action_state.action_data_mut(action.clone());
action_data.value = 0.;
action_data.axis_pair = None;
continue;
}
}
ActionDiff::ValueChanged {
action,
id: event_id,
value,
} => {
if event_id == id {
action_state.press(action.clone());
action_state.action_data_mut(action.clone()).value = *value;
continue;
}
}
ActionDiff::AxisPairChanged {
action,
id: event_id,
axis_pair,
} => {
if event_id == id {
action_state.press(action.clone());
let action_data = action_state.action_data_mut(action.clone());
action_data.axis_pair = Some(DualAxisData::from_xy(*axis_pair));
action_data.value = axis_pair.length();
continue;
}
}
Expand Down
Loading

0 comments on commit 7a92892

Please sign in to comment.