Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace axis-like input configuration with new input processors #494

Merged
merged 64 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6b5b344
Add input processors and input settings
Shute052 Feb 27, 2024
88f7a7a
Merge branch 'main' into input-processors
Shute052 Feb 28, 2024
fd18dcb
Replace all usage
Shute052 Feb 28, 2024
91f6e4e
RELEASES.md
Shute052 Feb 28, 2024
08a6acf
Document
Shute052 Feb 28, 2024
d7ac626
Document
Shute052 Feb 28, 2024
03e54fa
Document
Shute052 Feb 28, 2024
714c296
Document
Shute052 Feb 28, 2024
09579bb
Add more test cases
Shute052 Feb 28, 2024
f58953d
Split out deadzones into another module
Shute052 Feb 29, 2024
491c38f
Fix CI and examples
Shute052 Feb 29, 2024
789017c
add `with_settings`
Shute052 Feb 29, 2024
cfd4afd
Update comment
Shute052 Feb 29, 2024
4c44577
Split axis settings into separate modules
Shute052 Feb 29, 2024
a3ccf29
Update the documentation
Shute052 Mar 1, 2024
f8a3d4d
typo
Shute052 Mar 1, 2024
f4468cc
RELEASES.md
Shute052 Mar 1, 2024
324e76e
fix ci
Shute052 Mar 1, 2024
ed9b72e
fix RELEASES.md
Shute052 Mar 2, 2024
6b8d445
fix documentation
Shute052 Mar 2, 2024
1eb50b2
fix documentation
Shute052 Mar 2, 2024
34de561
Use new implementation
Shute052 Mar 22, 2024
9066278
Add comments
Shute052 Mar 28, 2024
cf860d7
Merge branch 'main' into input-processors
Shute052 Mar 28, 2024
fed7811
Add an example
Shute052 Mar 28, 2024
e9810ef
Fix warnings in examples
Shute052 Mar 28, 2024
f572244
Remove compilation configuration
Shute052 Mar 28, 2024
3513305
Doc typo
Shute052 Mar 28, 2024
b181a30
Doc typo
Shute052 Mar 28, 2024
d4a4f35
Fix hashing
Shute052 Mar 28, 2024
070e815
Simplify
Shute052 Mar 30, 2024
a191dd4
Fix macros
Shute052 Apr 4, 2024
3623571
Merge branch 'main' into input-processors
Shute052 Apr 4, 2024
3d8d7ad
Improve docs
Shute052 Apr 4, 2024
84ad6ef
Improve docs
Shute052 Apr 4, 2024
ee10149
Improve
Shute052 Apr 4, 2024
b130c8a
Rename macros.rs
Shute052 Apr 4, 2024
64f23ce
Prefer import from bevy::prelude
Shute052 Apr 4, 2024
feefdf1
Improve macro
Shute052 Apr 4, 2024
25011c8
Improve docs
Shute052 Apr 5, 2024
f7808aa
Improve docs
Shute052 Apr 5, 2024
6b08029
Improve docs and fix CI
Shute052 Apr 5, 2024
bc63f18
Rename Square* to DualAxis*
Shute052 Apr 5, 2024
729948f
Split dual_axis.rs
Shute052 Apr 5, 2024
a10d675
Update module docs
Shute052 Apr 5, 2024
c700dae
Rename `with_processor` to `replace_processor`, add `with_processor`
Shute052 Apr 5, 2024
e79f5d2
Improve docs
Shute052 Apr 5, 2024
48a8929
Improve docs
Shute052 Apr 5, 2024
5a9dc5a
Rearrange the order of match arms
Shute052 Apr 5, 2024
2bacf98
Improve docs
Shute052 Apr 5, 2024
953a935
Typo
Shute052 Apr 5, 2024
f2d8cd3
Expand macros and refine the results
Shute052 Apr 9, 2024
a444164
Rearrange dual-axis input processors
Shute052 Apr 9, 2024
4a8afa0
Rearrange processors
Shute052 Apr 12, 2024
de7ca2b
Remove macros.rs
Shute052 Apr 12, 2024
531cf51
Switch to `serde_flexitos`
Shute052 Apr 12, 2024
ff18aa4
Add tests
Shute052 Apr 12, 2024
d614f7c
Minor
Shute052 Apr 12, 2024
5c1821c
Improve docs
Shute052 Apr 12, 2024
5a4d4de
Inline doc alias
Shute052 Apr 12, 2024
1f35022
Typo
Shute052 Apr 12, 2024
c846c38
Add missing tests
Shute052 Apr 12, 2024
8a9c864
Cleanup
Shute052 Apr 12, 2024
9fe0a6d
Cleanup
Shute052 Apr 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ derive_more = { version = "0.99", default-features = false, features = [
] }
itertools = "0.12"
serde = { version = "1.0", features = ["derive"] }
typetag = "0.2"
Shute052 marked this conversation as resolved.
Show resolved Hide resolved
dyn-clone = "1.0"
dyn-eq = "0.1"
dyn-hash = "0.2"

[dev-dependencies]
bevy = { version = "0.13", default-features = false, features = [
Expand Down
34 changes: 33 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,39 @@

### Breaking Changes

- Removed `Direction` type. Use `bevy::math::primitives::Direction2d`.
- removed `Direction` type in favor of `bevy::math::primitives::Direction2d`.
- removed `DualAxisShape`.
- added input processors for `SingleAxis`, `DualAxis`, `VirtualAxis`, and `VirtualDpad` to refine input values:
- Traits:
- `AxisProcessor`: Handles single-axis values.
- `DualAxisProcessor`: Handles dual-axis values.
- Built-in processors:
- Composite Processors: Combine multiple processors function as a pipeline.
- `AxisProcessingPipeline`: Chain processors for single-axis values.
- `define_axis_processing_pipeline` macro: Inlined processor chaining for single-axis values with fixed steps.
- `DualAxisProcessingPipeline`: Chain processors for dual-axis values.
- `define_dual_axis_processing_pipeline` macro: Inlined processor chaining for dual-axis values with fixed steps.
- Inversion: Reverses control (positive becomes negative, etc.)
- `AxisInverted`: Single-axis inversion.
- `DualAxisInverted`: Dual-axis inversion.
- Sensitivity: Adjusts control responsiveness (doubling, halving, etc.).
- `AxisSensitivity`: Single-axis scaling.
- `DualAxisSensitivity`: Dual-axis scaling.
- Value Bounds: Define the boundaries for constraining input values.
- `AxisBounds`: Restricts single-axis values to a range.
- `DualAxisBounds`: Restricts single-axis values to a range along each axis.
- `CircleBounds`: Limits dual-axis values to a maximum magnitude.
- Deadzone: Ignores near-zero values, treating them as zero.
- Unscaled Deadzone:
- `AxisExclusion`: Excludes small single-axis values.
- `DualAxisExclusion`: Excludes small dual-axis values along each axis.
- `CircleExclusion`: Excludes dual-axis values below a specified magnitude threshold.
- Scaled Deadzone:
- `AxisDeadzone`: Normalizes single-axis values based on `AxisExclusion` and `AxisBounds::default`.
- `DualAxisDeadzone`: Normalizes dual-axis values based on `DualAxisExclusion` and `DualAxisBounds::default`.
- `CircleDeadzone`: Normalizes dual-axis values based on `CircleExclusion` and `CircleBounds::default`.
- removed functions for inverting, adjusting sensitivity, and creating deadzones from `SingleAxis` and `DualAxis`.
- added `with_processor`, `replace_processor`, and `no_processor` to manage processors for `SingleAxis`, `DualAxis`, `VirtualAxis`, and `VirtualDpad`.

### Bugs

Expand Down
2 changes: 1 addition & 1 deletion examples/action_state_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! and include it as a resource in a bevy app.

use bevy::prelude::*;
use leafwing_input_manager::{prelude::*, user_input::InputKind};
use leafwing_input_manager::prelude::*;

fn main() {
App::new()
Expand Down
6 changes: 3 additions & 3 deletions examples/arpg_indirection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,19 @@ fn spawn_player(mut commands: Commands) {

fn copy_action_state(
mut query: Query<(
&ActionState<Slot>,
&mut ActionState<Slot>,
&mut ActionState<Ability>,
&AbilitySlotMap,
)>,
) {
for (slot_state, mut ability_state, ability_slot_map) in query.iter_mut() {
for (mut slot_state, mut ability_state, ability_slot_map) in query.iter_mut() {
for slot in Slot::variants() {
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).unwrap().clone(),
slot_state.action_data_mut_or_default(&slot).clone(),
);
}
}
Expand Down
3 changes: 2 additions & 1 deletion examples/axis_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ fn spawn_player(mut commands: Commands) {
.insert(Action::Throttle, GamepadButtonType::RightTrigger2)
// And we'll use the right stick's x-axis as a rudder control
.insert(
// Add an AxisDeadzone to process horizontal values of the right stick.
// This will trigger if the axis is moved 10% or more in either direction.
Action::Rudder,
SingleAxis::symmetric(GamepadAxisType::RightStickX, 0.1),
SingleAxis::new(GamepadAxisType::RightStickX).with_processor(AxisDeadzone::default()),
Shute052 marked this conversation as resolved.
Show resolved Hide resolved
)
.build();
commands
Expand Down
1 change: 0 additions & 1 deletion examples/clash_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//! See [`ClashStrategy`] for more details.

use bevy::prelude::*;
use leafwing_input_manager::clashing_inputs::ClashStrategy;
use leafwing_input_manager::prelude::*;

fn main() {
Expand Down
1 change: 0 additions & 1 deletion examples/consuming_actions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Demonstrates how to "consume" actions, so they can only be responded to by a single system

use bevy::ecs::system::Resource;
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;

Expand Down
2 changes: 1 addition & 1 deletion examples/default_controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum PlayerAction {
}

impl PlayerAction {
/// Define the default binding to the input
/// Define the default bindings to the input
fn default_input_map() -> InputMap<Self> {
let mut input_map = InputMap::default();

Expand Down
70 changes: 70 additions & 0 deletions examples/input_processing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(InputManagerPlugin::<Action>::default())
.add_systems(Startup, spawn_player)
.add_systems(Update, check_data)
.run();
}

#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
enum Action {
Move,
LookAround,
}

#[derive(Component)]
struct Player;

fn spawn_player(mut commands: Commands) {
let mut input_map = InputMap::default();
input_map
.insert(
Action::Move,
VirtualDPad::wasd()
// You can add a processor to handle axis-like user inputs by using the `with_processor`.
//
// This processor is a circular deadzone that normalizes input values
// by clamping their magnitude to a maximum of 1.0,
// excluding those with a magnitude less than 0.1,
// and scaling other values linearly in between.
.with_processor(CircleDeadzone::default())
// Followed by appending another processor for the next processing step.
.with_processor(AxisSensitivity(2.0).extend_dual()),
Shute052 marked this conversation as resolved.
Show resolved Hide resolved
)
.insert(
Action::Move,
DualAxis::left_stick()
// You can replace the currently used processor with another processor.
.replace_processor(CircleDeadzone::default())
// Or remove the processor directly, leaving no processor applied.
.no_processor(),
)
.insert(
Action::LookAround,
// You can also add a pipeline to handle axis-like user inputs.
DualAxis::mouse_motion().with_processor(
DualAxisProcessingPipeline::default()
// The first processor is a circular deadzone.
.with(CircleDeadzone::default())
// The next processor doubles inputs normalized by the deadzone.
.with(AxisSensitivity(2.0).extend_dual()),
),
);
commands
.spawn(InputManagerBundle::with_map(input_map))
.insert(Player);
}

fn check_data(query: Query<&ActionState<Action>, With<Player>>) {
let action_state = query.single();
for action in action_state.get_pressed() {
println!(
"Pressed {action:?}! Its data: {:?}",
action_state.axis_pair(&action)
);
}
}
3 changes: 1 addition & 2 deletions examples/mouse_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ fn update_cursor_state_from_window(

if let Some(val) = window.cursor_position() {
action_state
.action_data_mut(&driver.action)
.unwrap()
.action_data_mut_or_default(&driver.action)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make action_data and action_data_mut infallible again, and remove this. Seperate PR though; I don't care whether it's before or after this PR is merged.

.axis_pair = Some(DualAxisData::from_xy(val));
}
}
Expand Down
6 changes: 1 addition & 5 deletions examples/send_actions_over_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Note that [`ActionState`] can also be serialized and sent directly.
//! This approach will be less bandwidth efficient, but involve less complexity and CPU work.

use bevy::ecs::event::{Events, ManualEventReader};
use bevy::ecs::event::ManualEventReader;
use bevy::input::InputPlugin;
use bevy::prelude::*;
use leafwing_input_manager::action_diff::ActionDiffEvent;
Expand All @@ -23,10 +23,6 @@ enum FpsAction {
Shoot,
}

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cleanup is good, but not particularly related. Whatever, it can stay.


/// Processes an [`Events`] stream of [`ActionDiff`] to update an [`ActionState`]
///
/// In a real scenario, you would have to map the entities between the server and client world.
Expand Down
2 changes: 1 addition & 1 deletion examples/twin_stick_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub enum PlayerAction {
}

impl PlayerAction {
/// Define the default binding to the input
/// Define the default bindings to the input
fn default_input_map() -> InputMap<Self> {
let mut input_map = InputMap::default();

Expand Down
1 change: 1 addition & 0 deletions examples/virtual_dpad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn spawn_player(mut commands: Commands) {
down: KeyCode::KeyS.into(),
left: KeyCode::KeyA.into(),
right: KeyCode::KeyD.into(),
processor: None,
},
)]);
commands
Expand Down
Loading
Loading