From 256ad876cbb48a06f0d4aa6e4d9fd2638327a369 Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Tue, 18 Jan 2022 21:40:03 -0800 Subject: [PATCH 1/6] Add `gamepad_stick_input` example --- Cargo.toml | 4 ++ assets/textures/crosshair.png | Bin 0 -> 345 bytes examples/README.md | 3 +- examples/input/gamepad_stick_input.rs | 58 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 assets/textures/crosshair.png create mode 100644 examples/input/gamepad_stick_input.rs diff --git a/Cargo.toml b/Cargo.toml index 812bcd4adf157..ccb9318dd7683 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -376,6 +376,10 @@ path = "examples/input/gamepad_input.rs" name = "gamepad_input_events" path = "examples/input/gamepad_input_events.rs" +[[example]] +name = "gamepad_stick_input" +path = "examples/input/gamepad_stick_input.rs" + [[example]] name = "keyboard_input" path = "examples/input/keyboard_input.rs" diff --git a/assets/textures/crosshair.png b/assets/textures/crosshair.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d6770aeeec5df7ce254be12071bf32e471dff4 GIT binary patch literal 345 zcmV-f0jBPx$6G=otR5(v{Q%RDht15vYkiF5K0g9X8J_LH>aDwo=q>vL;BR0Z5 zVtr}Q;JW}bfL0fc%LT6JP2z1JO`^nE#5N7xqxmg9G6Y=FWpsZ~u=tUSy@VT5bq@cZ z=NS?DURb38nv$$xYc^GJj)woqMG9T|3ClA)U&MmFgB00000NkvXXu0mjfpnsXf literal 0 HcmV?d00001 diff --git a/examples/README.md b/examples/README.md index 1ddbd01a583fa..52325db766617 100644 --- a/examples/README.md +++ b/examples/README.md @@ -188,9 +188,10 @@ Example | File | Description Example | File | Description --- | --- | --- -`char_input_events` | [`input/char_input_events.rs`](./input/char_input_events.rs) | Prints out all chars as they are inputted. +`char_input_events` | [`input/char_input_events.rs`](./input/char_input_events.rs) | Prints out all chars as they are input `gamepad_input` | [`input/gamepad_input.rs`](./input/gamepad_input.rs) | Shows handling of gamepad input, connections, and disconnections `gamepad_input_events` | [`input/gamepad_input_events.rs`](./input/gamepad_input_events.rs) | Iterates and prints gamepad input and connection events +`gamepad_stick_input` | [`input/gamepad_stick_input.rs`](./input/gamepad_stick_input.rs) | Shows gamepad stick input graphically `keyboard_input` | [`input/keyboard_input.rs`](./input/keyboard_input.rs) | Demonstrates handling a key press/release `keyboard_input_events` | [`input/keyboard_input_events.rs`](./input/keyboard_input_events.rs) | Prints out all keyboard events `keyboard_modifiers` | [`input/keyboard_modifiers.rs`](./input/keyboard_modifiers.rs) | Demonstrates using key modifiers (ctrl, shift) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs new file mode 100644 index 0000000000000..a9c1ae9486c45 --- /dev/null +++ b/examples/input/gamepad_stick_input.rs @@ -0,0 +1,58 @@ +use bevy::prelude::*; + +const WINDOW_SIZE: f32 = 300.0; +const CROSSHAIR_SIZE: f32 = 32.0; + +#[derive(Component)] +struct Crosshair; + +fn main() { + App::new() + .insert_resource(WindowDescriptor { + title: "Gamepad Stick Input".to_owned(), + width: WINDOW_SIZE, + height: WINDOW_SIZE, + ..Default::default() + }) + .insert_resource(ClearColor(Color::GRAY)) + .add_plugins(DefaultPlugins) + .add_startup_system(setup) + .add_system(move_crosshair) + .run(); +} + +fn move_crosshair( + mut query: Query<&mut Transform, With>, + gamepads: Res, + axes: Res>, +) { + let mut xform = query.single_mut(); + for gamepad in gamepads.iter() { + let left_stick_x = axes + .get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickX)) + .unwrap(); + let left_stick_y = axes + .get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickY)) + .unwrap(); + xform.translation.x = left_stick_x * WINDOW_SIZE / 2.0; + xform.translation.y = left_stick_y * WINDOW_SIZE / 2.0; + } +} + +fn setup(mut commands: Commands, asset_server: Res) { + // Spawn camera + commands.spawn_bundle(OrthographicCameraBundle::new_2d()); + + // Spawn crosshair + let texture = asset_server.load("textures/crosshair.png"); + commands + .spawn_bundle(SpriteBundle { + texture, + sprite: Sprite { + custom_size: Some(Vec2::new(CROSSHAIR_SIZE, CROSSHAIR_SIZE)), + ..Default::default() + }, + ..Default::default() + }) + .insert(Crosshair); +} From fe53252f988afe46a9c7ad3a1997db36c8340cc2 Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Tue, 18 Jan 2022 22:34:52 -0800 Subject: [PATCH 2/6] Add coordinate text to `gamepad_stick_input` example --- examples/input/gamepad_stick_input.rs | 49 +++++++++++++++++++++------ 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs index a9c1ae9486c45..188dfc642f9ab 100644 --- a/examples/input/gamepad_stick_input.rs +++ b/examples/input/gamepad_stick_input.rs @@ -1,11 +1,16 @@ use bevy::prelude::*; const WINDOW_SIZE: f32 = 300.0; -const CROSSHAIR_SIZE: f32 = 32.0; +const CROSSHAIR_SIZE: f32 = 24.0; +const FONT: &str = "fonts/FiraMono-Medium.ttf"; +const FONT_SIZE: f32 = 18.0; #[derive(Component)] struct Crosshair; +#[derive(Component)] +struct CoordinateText; + fn main() { App::new() .insert_resource(WindowDescriptor { @@ -17,30 +22,35 @@ fn main() { .insert_resource(ClearColor(Color::GRAY)) .add_plugins(DefaultPlugins) .add_startup_system(setup) - .add_system(move_crosshair) + .add_system(update_position) .run(); } -fn move_crosshair( - mut query: Query<&mut Transform, With>, +fn update_position( + mut xform_query: Query<&mut Transform, With>, + mut text_query: Query<&mut Text, With>, gamepads: Res, axes: Res>, ) { - let mut xform = query.single_mut(); + let mut xform = xform_query.single_mut(); + let mut text = text_query.single_mut(); for gamepad in gamepads.iter() { - let left_stick_x = axes + // We only use input from the left stick. + let x = axes .get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickX)) .unwrap(); - let left_stick_y = axes + let y = axes .get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickY)) .unwrap(); - xform.translation.x = left_stick_x * WINDOW_SIZE / 2.0; - xform.translation.y = left_stick_y * WINDOW_SIZE / 2.0; + xform.translation.x = x * WINDOW_SIZE / 2.0; + xform.translation.y = y * WINDOW_SIZE / 2.0; + text.sections[0].value = format!("({:6.3}, {:6.3})", x, y); } } fn setup(mut commands: Commands, asset_server: Res) { - // Spawn camera + // Spawn cameras + commands.spawn_bundle(OrthographicCameraBundle::new_2d()); commands.spawn_bundle(OrthographicCameraBundle::new_2d()); // Spawn crosshair @@ -55,4 +65,23 @@ fn setup(mut commands: Commands, asset_server: Res) { ..Default::default() }) .insert(Crosshair); + + // Spawn text + let font = asset_server.load(FONT); + let text_style = TextStyle { + font, + font_size: FONT_SIZE, + color: Color::BLACK, + }; + let text_alignment = TextAlignment { + vertical: VerticalAlign::Bottom, + horizontal: HorizontalAlign::Left, + }; + commands + .spawn_bundle(Text2dBundle { + text: Text::with_section("(0.000, 0.000)", text_style, text_alignment), + transform: Transform::from_xyz(-WINDOW_SIZE / 2.0, -WINDOW_SIZE / 2.0, 0.0), + ..Default::default() + }) + .insert(CoordinateText); } From 70e3f1c5ea35b8f4124e8f4763d4a3c8031dc3d2 Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Wed, 19 Jan 2022 00:39:40 -0800 Subject: [PATCH 3/6] Add deadzone indicator --- examples/input/gamepad_stick_input.rs | 43 ++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs index 188dfc642f9ab..82102cf97a50e 100644 --- a/examples/input/gamepad_stick_input.rs +++ b/examples/input/gamepad_stick_input.rs @@ -1,7 +1,7 @@ -use bevy::prelude::*; +use bevy::{input::gamepad::GamepadSettings, prelude::*}; const WINDOW_SIZE: f32 = 300.0; -const CROSSHAIR_SIZE: f32 = 24.0; +const CROSSHAIR_SIZE: f32 = 16.0; const FONT: &str = "fonts/FiraMono-Medium.ttf"; const FONT_SIZE: f32 = 18.0; @@ -11,6 +11,9 @@ struct Crosshair; #[derive(Component)] struct CoordinateText; +#[derive(Component)] +struct DeadzoneBox; + fn main() { App::new() .insert_resource(WindowDescriptor { @@ -48,9 +51,12 @@ fn update_position( } } -fn setup(mut commands: Commands, asset_server: Res) { - // Spawn cameras - commands.spawn_bundle(OrthographicCameraBundle::new_2d()); +fn setup( + mut commands: Commands, + asset_server: Res, + gamepad_settings: Res, +) { + // Spawn camera commands.spawn_bundle(OrthographicCameraBundle::new_2d()); // Spawn crosshair @@ -62,6 +68,8 @@ fn setup(mut commands: Commands, asset_server: Res) { custom_size: Some(Vec2::new(CROSSHAIR_SIZE, CROSSHAIR_SIZE)), ..Default::default() }, + // Make sure it is in the foreground with a Z value > 0.0 + transform: Transform::from_xyz(0.0, 0.0, 1.0), ..Default::default() }) .insert(Crosshair); @@ -79,9 +87,30 @@ fn setup(mut commands: Commands, asset_server: Res) { }; commands .spawn_bundle(Text2dBundle { - text: Text::with_section("(0.000, 0.000)", text_style, text_alignment), - transform: Transform::from_xyz(-WINDOW_SIZE / 2.0, -WINDOW_SIZE / 2.0, 0.0), + text: Text::with_section("( 0.000, 0.000)", text_style, text_alignment), + transform: Transform::from_xyz(-WINDOW_SIZE / 2.0, -WINDOW_SIZE / 2.0, 1.0), ..Default::default() }) .insert(CoordinateText); + + // Get deadzone info + let deadzone_upperbound = gamepad_settings.default_axis_settings.positive_low; + let deadzone_lowerbound = gamepad_settings.default_axis_settings.negative_low; + let deadzone_midpoint = (deadzone_lowerbound + deadzone_upperbound) / 2.0; + let deadzone_size = deadzone_upperbound - deadzone_lowerbound; + let deadzone_box_midpoint = deadzone_midpoint * WINDOW_SIZE / 2.0; + let deadzone_box_size = deadzone_size * WINDOW_SIZE / 2.0; + + // Spawn deadzone box + commands + .spawn_bundle(SpriteBundle { + sprite: Sprite { + custom_size: Some(Vec2::new(deadzone_box_size, deadzone_box_size)), + color: Color::rgb(0.4, 0.4, 0.4), + ..Default::default() + }, + transform: Transform::from_xyz(deadzone_box_midpoint, deadzone_box_midpoint, 0.0), + ..Default::default() + }) + .insert(DeadzoneBox); } From 67ed76081e616161f408ac36c2a778c1d2dd181e Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Wed, 19 Jan 2022 01:02:14 -0800 Subject: [PATCH 4/6] Add outer deadzone --- examples/input/gamepad_stick_input.rs | 70 ++++++++++++++++++--------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs index 82102cf97a50e..352e8371a4400 100644 --- a/examples/input/gamepad_stick_input.rs +++ b/examples/input/gamepad_stick_input.rs @@ -4,6 +4,8 @@ const WINDOW_SIZE: f32 = 300.0; const CROSSHAIR_SIZE: f32 = 16.0; const FONT: &str = "fonts/FiraMono-Medium.ttf"; const FONT_SIZE: f32 = 18.0; +const LIVEZONE_COLOR: Color = Color::GRAY; +const DEADZONE_COLOR: Color = Color::rgb(0.4, 0.4, 0.4); #[derive(Component)] struct Crosshair; @@ -22,7 +24,7 @@ fn main() { height: WINDOW_SIZE, ..Default::default() }) - .insert_resource(ClearColor(Color::GRAY)) + .insert_resource(ClearColor(DEADZONE_COLOR)) .add_plugins(DefaultPlugins) .add_startup_system(setup) .add_system(update_position) @@ -74,43 +76,65 @@ fn setup( }) .insert(Crosshair); - // Spawn text - let font = asset_server.load(FONT); - let text_style = TextStyle { - font, - font_size: FONT_SIZE, - color: Color::BLACK, - }; - let text_alignment = TextAlignment { - vertical: VerticalAlign::Bottom, - horizontal: HorizontalAlign::Left, - }; - commands - .spawn_bundle(Text2dBundle { - text: Text::with_section("( 0.000, 0.000)", text_style, text_alignment), - transform: Transform::from_xyz(-WINDOW_SIZE / 2.0, -WINDOW_SIZE / 2.0, 1.0), - ..Default::default() - }) - .insert(CoordinateText); - - // Get deadzone info + // Get live/deadzone info + let livezone_upperbound = gamepad_settings.default_axis_settings.positive_high; + let livezone_lowerbound = gamepad_settings.default_axis_settings.negative_high; let deadzone_upperbound = gamepad_settings.default_axis_settings.positive_low; let deadzone_lowerbound = gamepad_settings.default_axis_settings.negative_low; + let livezone_midpoint = (livezone_lowerbound + livezone_upperbound) / 2.0; let deadzone_midpoint = (deadzone_lowerbound + deadzone_upperbound) / 2.0; + let livezone_size = livezone_upperbound - livezone_lowerbound; let deadzone_size = deadzone_upperbound - deadzone_lowerbound; + let livezone_box_midpoint = livezone_midpoint * WINDOW_SIZE / 2.0; let deadzone_box_midpoint = deadzone_midpoint * WINDOW_SIZE / 2.0; + let livezone_box_size = livezone_size * WINDOW_SIZE / 2.0; let deadzone_box_size = deadzone_size * WINDOW_SIZE / 2.0; + // For text placement + let livezone_lower_left_corner = (livezone_box_midpoint - livezone_box_size) / 2.0; + // Spawn livezone box + commands.spawn_bundle(SpriteBundle { + sprite: Sprite { + custom_size: Some(Vec2::new(livezone_box_size, livezone_box_size)), + color: LIVEZONE_COLOR, + ..Default::default() + }, + transform: Transform::from_xyz(livezone_box_midpoint, livezone_box_midpoint, 0.0), + ..Default::default() + }); // Spawn deadzone box commands .spawn_bundle(SpriteBundle { sprite: Sprite { custom_size: Some(Vec2::new(deadzone_box_size, deadzone_box_size)), - color: Color::rgb(0.4, 0.4, 0.4), + color: DEADZONE_COLOR, ..Default::default() }, - transform: Transform::from_xyz(deadzone_box_midpoint, deadzone_box_midpoint, 0.0), + transform: Transform::from_xyz(deadzone_box_midpoint, deadzone_box_midpoint, 0.1), ..Default::default() }) .insert(DeadzoneBox); + + // Spawn text + let font = asset_server.load(FONT); + let text_style = TextStyle { + font, + font_size: FONT_SIZE, + color: Color::BLACK, + }; + let text_alignment = TextAlignment { + vertical: VerticalAlign::Bottom, + horizontal: HorizontalAlign::Left, + }; + commands + .spawn_bundle(Text2dBundle { + text: Text::with_section("( 0.000, 0.000)", text_style, text_alignment), + transform: Transform::from_xyz( + livezone_lower_left_corner, + livezone_lower_left_corner, + 1.0, + ), + ..Default::default() + }) + .insert(CoordinateText); } From 8c1043f508185ed3abdaee0286352b753c3101df Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Wed, 19 Jan 2022 01:22:41 -0800 Subject: [PATCH 5/6] Remove unnecessary `DeadzoneBox` struct --- examples/input/gamepad_stick_input.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs index 352e8371a4400..89539e7d7bccf 100644 --- a/examples/input/gamepad_stick_input.rs +++ b/examples/input/gamepad_stick_input.rs @@ -13,9 +13,6 @@ struct Crosshair; #[derive(Component)] struct CoordinateText; -#[derive(Component)] -struct DeadzoneBox; - fn main() { App::new() .insert_resource(WindowDescriptor { @@ -103,17 +100,15 @@ fn setup( ..Default::default() }); // Spawn deadzone box - commands - .spawn_bundle(SpriteBundle { - sprite: Sprite { - custom_size: Some(Vec2::new(deadzone_box_size, deadzone_box_size)), - color: DEADZONE_COLOR, - ..Default::default() - }, - transform: Transform::from_xyz(deadzone_box_midpoint, deadzone_box_midpoint, 0.1), + commands.spawn_bundle(SpriteBundle { + sprite: Sprite { + custom_size: Some(Vec2::new(deadzone_box_size, deadzone_box_size)), + color: DEADZONE_COLOR, ..Default::default() - }) - .insert(DeadzoneBox); + }, + transform: Transform::from_xyz(deadzone_box_midpoint, deadzone_box_midpoint, 0.1), + ..Default::default() + }); // Spawn text let font = asset_server.load(FONT); From 9924167331d635dcd77bd08c8b437409bcbdd458 Mon Sep 17 00:00:00 2001 From: Michael Dorst Date: Wed, 19 Jan 2022 19:19:05 -0800 Subject: [PATCH 6/6] Implement suggestions from rparrett --- examples/input/gamepad_stick_input.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/input/gamepad_stick_input.rs b/examples/input/gamepad_stick_input.rs index 89539e7d7bccf..8f9e2cfedef5f 100644 --- a/examples/input/gamepad_stick_input.rs +++ b/examples/input/gamepad_stick_input.rs @@ -29,12 +29,12 @@ fn main() { } fn update_position( - mut xform_query: Query<&mut Transform, With>, + mut crosshair_query: Query<&mut Transform, With>, mut text_query: Query<&mut Text, With>, gamepads: Res, axes: Res>, ) { - let mut xform = xform_query.single_mut(); + let mut transform = crosshair_query.single_mut(); let mut text = text_query.single_mut(); for gamepad in gamepads.iter() { // We only use input from the left stick. @@ -44,8 +44,8 @@ fn update_position( let y = axes .get(GamepadAxis(*gamepad, GamepadAxisType::LeftStickY)) .unwrap(); - xform.translation.x = x * WINDOW_SIZE / 2.0; - xform.translation.y = y * WINDOW_SIZE / 2.0; + transform.translation.x = x * WINDOW_SIZE / 2.0; + transform.translation.y = y * WINDOW_SIZE / 2.0; text.sections[0].value = format!("({:6.3}, {:6.3})", x, y); } } @@ -64,7 +64,7 @@ fn setup( .spawn_bundle(SpriteBundle { texture, sprite: Sprite { - custom_size: Some(Vec2::new(CROSSHAIR_SIZE, CROSSHAIR_SIZE)), + custom_size: Some(Vec2::splat(CROSSHAIR_SIZE)), ..Default::default() }, // Make sure it is in the foreground with a Z value > 0.0 @@ -92,7 +92,7 @@ fn setup( // Spawn livezone box commands.spawn_bundle(SpriteBundle { sprite: Sprite { - custom_size: Some(Vec2::new(livezone_box_size, livezone_box_size)), + custom_size: Some(Vec2::splat(livezone_box_size)), color: LIVEZONE_COLOR, ..Default::default() }, @@ -102,7 +102,7 @@ fn setup( // Spawn deadzone box commands.spawn_bundle(SpriteBundle { sprite: Sprite { - custom_size: Some(Vec2::new(deadzone_box_size, deadzone_box_size)), + custom_size: Some(Vec2::splat(deadzone_box_size)), color: DEADZONE_COLOR, ..Default::default() },