From 627f63211d737291f08dcd16f4a11f940e63bf48 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 2 Aug 2022 17:15:22 -0500 Subject: [PATCH] Refactor to leafwing-input-manager. --- Cargo.toml | 2 +- src/exploration.rs | 335 ++++++++++++++++++++------------------------- src/lib.rs | 2 +- src/navigation.rs | 306 ++++++++++++++++------------------------- 4 files changed, 267 insertions(+), 378 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d052bad..3b38421 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ features = [ [dependencies] backtrace = "0.3" -bevy_input_actionmap = { git = "https://github.com/lightsoutgames/bevy_input_actionmap", branch = "bevy-0.8" } bevy_rapier2d = { version = "0.16", features = ["serde-serialize"] } bevy_synthizer = { git = "https://labs.lightsout.games/projects/bevy_synthizer", branch = "bevy-0.8" } bevy_tts = { git = "https://github.com/lightsoutgames/bevy_tts", default-features = false, features = ["tolk"], branch = "bevy-0.8" } @@ -32,6 +31,7 @@ coord_2d = "0.3" futures-lite = "1" gilrs = "0.9" here_be_dragons = "0.1" +leafwing_input_manager = { git = "https://github.com/ndarilek/leafwing-input-manager", branch = "dev" } maze_generator = "2" once_cell = "1" pathfinding = "3" diff --git a/src/exploration.rs b/src/exploration.rs index 09c9ce4..9e9d6ba 100644 --- a/src/exploration.rs +++ b/src/exploration.rs @@ -1,9 +1,9 @@ use std::{error::Error, fmt::Debug, hash::Hash, marker::PhantomData}; use bevy::prelude::*; -use bevy_input_actionmap::InputMap; use bevy_rapier2d::prelude::*; use bevy_tts::Tts; +use leafwing_input_manager::prelude::*; use crate::{ core::{Player, PointLike}, @@ -13,6 +13,19 @@ use crate::{ visibility::{RevealedTiles, Viewshed, Visible, VisibleEntities}, }; +#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug)] +pub enum ExplorationAction { + Forward, + Backward, + Left, + Right, + FocusNext, + FocusPrev, + SelectNextType, + SelectPrevType, + NavigateTo, +} + #[derive(Component, Clone, Copy, Debug, Default, PartialEq, Reflect)] #[reflect(Component)] pub struct Explorable; @@ -34,85 +47,75 @@ pub struct FocusedExplorationType(pub Option); #[reflect(Component)] pub struct Mappable; -fn exploration_type_change( - config: Res>, +fn exploration_type_change( mut tts: ResMut, - input: Res>, - mut explorers: Query<(&VisibleEntities, &mut FocusedExplorationType)>, + mut explorers: Query<( + &ActionState, + &VisibleEntities, + &mut FocusedExplorationType, + )>, features: Query<&T>, ) -> Result<(), Box> where T: Component + Copy + Ord, S: 'static + Clone + Debug + Eq + Hash + Send + Sync, - A: Hash + Eq + Clone + Send + Sync, { - if let (Some(select_next_type), Some(select_prev_type)) = ( - config.action_explore_select_next_type.clone(), - config.action_explore_select_prev_type.clone(), - ) { - let changed = input.just_active(select_next_type.clone()) - || input.just_active(select_prev_type.clone()); - if !changed { - return Ok(()); - } - for (visible, mut focused) in explorers.iter_mut() { - let mut types: Vec = vec![]; - for e in visible.iter() { - if let Ok(t) = features.get(*e) { - types.push(*t); - } + for (actions, visible, mut focused) in explorers.iter_mut() { + let mut types: Vec = vec![]; + for e in visible.iter() { + if let Ok(t) = features.get(*e) { + types.push(*t); } - types.sort(); - types.dedup(); - if types.is_empty() { - tts.speak("Nothing visible.", true)?; - } else if input.just_active(select_prev_type.clone()) { - if let Some(t) = &focused.0 { - if let Some(i) = types.iter().position(|v| *v == *t) { - if i == 0 { - focused.0 = None; - } else { - let t = &types[i - 1]; - focused.0 = Some(*t); - } + } + types.sort(); + types.dedup(); + if types.is_empty() { + tts.speak("Nothing visible.", true)?; + } else if actions.just_pressed(ExplorationAction::SelectPrevType) { + if let Some(t) = &focused.0 { + if let Some(i) = types.iter().position(|v| *v == *t) { + if i == 0 { + focused.0 = None; } else { - let t = types.last().unwrap(); + let t = &types[i - 1]; focused.0 = Some(*t); } } else { let t = types.last().unwrap(); focused.0 = Some(*t); } - } else if input.just_active(select_next_type.clone()) { - if let Some(t) = &focused.0 { - if let Some(i) = types.iter().position(|v| *v == *t) { - if i == types.len() - 1 { - focused.0 = None; - } else { - let t = &types[i + 1]; - focused.0 = Some(*t); - } + } else { + let t = types.last().unwrap(); + focused.0 = Some(*t); + } + } else if actions.just_pressed(ExplorationAction::SelectNextType) { + if let Some(t) = &focused.0 { + if let Some(i) = types.iter().position(|v| *v == *t) { + if i == types.len() - 1 { + focused.0 = None; } else { - let t = types.first().unwrap(); + let t = &types[i + 1]; focused.0 = Some(*t); } } else { let t = types.first().unwrap(); - focused.0 = Some(*t) + focused.0 = Some(*t); } + } else { + let t = types.first().unwrap(); + focused.0 = Some(*t) } } } Ok(()) } -fn exploration_type_focus( +fn exploration_type_focus( mut commands: Commands, - config: Res>, - input: Res>, mut tts: ResMut, explorers: Query<( Entity, + &ActionState, &VisibleEntities, &FocusedExplorationType, Option<&Exploring>, @@ -122,57 +125,46 @@ fn exploration_type_focus( where T: Component + PartialEq, S: 'static + Clone + Debug + Eq + Hash + Send + Sync, - A: 'static + Hash + Eq + Clone + Send + Sync, { - if let (Some(explore_focus_next), Some(explore_focus_prev)) = ( - config.action_explore_focus_next.clone(), - config.action_explore_focus_prev.clone(), - ) { - let changed = input.just_active(explore_focus_next.clone()) - || input.just_active(explore_focus_prev.clone()); - if !changed { + for (entity, actions, visible_entities, focused_type, exploring) in explorers.iter() { + let mut features = features + .iter() + .filter(|v| visible_entities.contains(&v.0)) + .map(|v| (v.1.floor(), v.2)) + .collect::>(); + if features.is_empty() { + tts.speak("Nothing visible.", true)?; return Ok(()); } - for (entity, visible_entities, focused_type, exploring) in explorers.iter() { - let mut features = features - .iter() - .filter(|v| visible_entities.contains(&v.0)) - .map(|v| (v.1.floor(), v.2)) - .collect::>(); - if features.is_empty() { - tts.speak("Nothing visible.", true)?; - return Ok(()); - } - features.sort_by(|(c1, _), (c2, _)| c1.partial_cmp(c2).unwrap()); - if let Some(focused) = &focused_type.0 { - features.retain(|(_, t)| **t == *focused); - } - let mut target: Option<&((f32, f32), &T)> = None; - if input.just_active(explore_focus_next.clone()) { - if let Some(exploring) = exploring { - target = features.iter().find(|(c, _)| *c > **exploring); - if target.is_none() { - target = features.first(); - } - } else { + features.sort_by(|(c1, _), (c2, _)| c1.partial_cmp(c2).unwrap()); + if let Some(focused) = &focused_type.0 { + features.retain(|(_, t)| **t == *focused); + } + let mut target: Option<&((f32, f32), &T)> = None; + if actions.just_pressed(ExplorationAction::FocusNext) { + if let Some(exploring) = exploring { + target = features.iter().find(|(c, _)| *c > **exploring); + if target.is_none() { target = features.first(); } - } else if input.just_active(explore_focus_prev.clone()) { - if let Some(exploring) = exploring { - features.reverse(); - target = features.iter().find(|(c, _)| *c < **exploring); - if target.is_none() { - target = features.first(); - } - } else { - target = features.last(); + } else { + target = features.first(); + } + } else if actions.just_pressed(ExplorationAction::FocusPrev) { + if let Some(exploring) = exploring { + features.reverse(); + target = features.iter().find(|(c, _)| *c < **exploring); + if target.is_none() { + target = features.first(); } + } else { + target = features.last(); } - if let Some((coordinates, _)) = target { - commands - .entity(entity) - .insert(Exploring(coordinates.floor())); - } + } + if let Some((coordinates, _)) = target { + commands + .entity(entity) + .insert(Exploring(coordinates.floor())); } } Ok(()) @@ -208,83 +200,71 @@ where Ok(()) } -fn exploration_focus( +fn exploration_focus( mut commands: Commands, - config: Res>, - input: Res>, map: Query<&Map>, - explorers: Query<(Entity, &Transform, Option<&Exploring>), With>, + explorers: Query< + ( + Entity, + &ActionState, + &Transform, + Option<&Exploring>, + ), + With, + >, ) where S: 'static + Clone + Debug + Eq + Hash + Send + Sync, - A: Hash + Eq + Clone + Send + Sync, { - if let ( - Some(explore_forward), - Some(explore_backward), - Some(explore_left), - Some(explore_right), - ) = ( - config.action_explore_forward.clone(), - config.action_explore_backward.clone(), - config.action_explore_left.clone(), - config.action_explore_right.clone(), - ) { - if let Ok((entity, transform, exploring)) = explorers.get_single() { - let coordinates = transform.translation; - let mut exploring = if let Some(exploring) = exploring { - **exploring - } else { - let floor = coordinates.floor(); - (floor.x, floor.y) - }; - let orig = exploring; - if input.just_active(explore_forward) { - exploring.1 += 1.; - } else if input.just_active(explore_backward) { - exploring.1 -= 1.; - } else if input.just_active(explore_left) { - exploring.0 -= 1.; - } else if input.just_active(explore_right) { - exploring.0 += 1.; - } - let dimensions = if let Ok(map) = map.get_single() { - Some((map.width as f32, map.height as f32)) - } else { - None - }; - if let Some((width, height)) = dimensions { - if exploring.0 >= width || exploring.1 >= height { - return; - } - } - if orig != exploring && exploring.0 >= 0. && exploring.1 >= 0. { - commands.entity(entity).insert(Exploring(exploring)); + for (entity, actions, transform, exploring) in explorers.iter() { + let coordinates = transform.translation; + let mut exploring = if let Some(exploring) = exploring { + **exploring + } else { + let floor = coordinates.floor(); + (floor.x, floor.y) + }; + let orig = exploring; + if actions.just_pressed(ExplorationAction::Forward) { + exploring.1 += 1.; + } else if actions.just_pressed(ExplorationAction::Backward) { + exploring.1 -= 1.; + } else if actions.just_pressed(ExplorationAction::Left) { + exploring.0 -= 1.; + } else if actions.just_pressed(ExplorationAction::Right) { + exploring.0 += 1.; + } + let dimensions = if let Ok(map) = map.get_single() { + Some((map.width as f32, map.height as f32)) + } else { + None + }; + if let Some((width, height)) = dimensions { + if exploring.0 >= width || exploring.1 >= height { + return; } } + if orig != exploring && exploring.0 >= 0. && exploring.1 >= 0. { + commands.entity(entity).insert(Exploring(exploring)); + } } } -fn navigate_to_explored( +fn navigate_to_explored( mut commands: Commands, - config: Res>, - input: Res>, map: Query<(&Map, &RevealedTiles)>, - explorers: Query<(Entity, &Exploring)>, + explorers: Query<(Entity, &ActionState, &Exploring)>, ) where S: 'static + Clone + Debug + Eq + Hash + Send + Sync, - A: Hash + Eq + Clone + Send + Sync, { - if let Some(navigate_to_explored) = config.action_navigate_to_explored.clone() { - for (entity, exploring) in explorers.iter() { - for (map, revealed_tiles) in map.iter() { - let point = **exploring; - let idx = point.to_index(map.width); - let known = revealed_tiles[idx]; - if input.just_active(navigate_to_explored.clone()) && known { - commands - .entity(entity) - .insert(Destination((point.x_i32(), point.y_i32()))); - } + for (entity, actions, exploring) in explorers.iter() { + for (map, revealed_tiles) in map.iter() { + let point = **exploring; + let idx = point.to_index(map.width); + let known = revealed_tiles[idx]; + if actions.just_pressed(ExplorationAction::NavigateTo) && known { + commands + .entity(entity) + .insert(Destination((point.x_i32(), point.y_i32()))); } } } @@ -388,32 +368,14 @@ fn cleanup( } #[derive(Clone, Debug)] -pub struct ExplorationConfig { +pub struct ExplorationConfig { pub exploration_control_states: Vec, - pub action_explore_forward: Option, - pub action_explore_backward: Option, - pub action_explore_left: Option, - pub action_explore_right: Option, - pub action_explore_focus_next: Option, - pub action_explore_focus_prev: Option, - pub action_explore_select_next_type: Option, - pub action_explore_select_prev_type: Option, - pub action_navigate_to_explored: Option, } -impl Default for ExplorationConfig { +impl Default for ExplorationConfig { fn default() -> Self { Self { exploration_control_states: vec![], - action_explore_forward: None, - action_explore_backward: None, - action_explore_left: None, - action_explore_right: None, - action_explore_focus_next: None, - action_explore_focus_prev: None, - action_explore_select_next_type: None, - action_explore_select_prev_type: None, - action_navigate_to_explored: None, } } } @@ -439,22 +401,23 @@ where D: 'static + Clone + Default + Send + Sync, { fn build(&self, app: &mut App) { - if !app.world.contains_resource::>() { - app.insert_resource(ExplorationConfig::::default()); + if !app.world.contains_resource::>() { + app.insert_resource(ExplorationConfig::::default()); } let config = app .world - .get_resource::>() + .get_resource::>() .unwrap() .clone(); app.register_type::() .register_type::() + .add_plugin(InputManagerPlugin::::default()) .add_system(exploration_changed_announcement::.chain(error_handler)); if config.exploration_control_states.is_empty() { - app.add_system(exploration_focus::) - .add_system(exploration_type_focus::.chain(error_handler)) - .add_system(exploration_type_change::.chain(error_handler)) - .add_system(navigate_to_explored::) + app.add_system(exploration_focus::) + .add_system(exploration_type_focus::.chain(error_handler)) + .add_system(exploration_type_change::.chain(error_handler)) + .add_system(navigate_to_explored::) .add_system_to_stage( CoreStage::PostUpdate, exploration_type_changed_announcement::.chain(error_handler), @@ -464,10 +427,10 @@ where for state in states { app.add_system_set( SystemSet::on_update(state.clone()) - .with_system(exploration_focus::) - .with_system(exploration_type_focus::.chain(error_handler)) - .with_system(exploration_type_change::.chain(error_handler)) - .with_system(navigate_to_explored::) + .with_system(exploration_focus::) + .with_system(exploration_type_focus::.chain(error_handler)) + .with_system(exploration_type_change::.chain(error_handler)) + .with_system(navigate_to_explored::) .with_system( exploration_type_changed_announcement::.chain(error_handler), ), diff --git a/src/lib.rs b/src/lib.rs index a9f5f62..f872d94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ #![allow(clippy::too_many_arguments)] #![allow(clippy::type_complexity)] -pub use bevy_input_actionmap; pub use bevy_rapier2d; pub use bevy_synthizer; pub use bevy_tts; @@ -15,6 +14,7 @@ pub mod exploration; pub use futures_lite; pub use gilrs; pub use here_be_dragons as mapgen; +pub use leafwing_input_manager; pub mod log; pub mod map; pub mod navigation; diff --git a/src/navigation.rs b/src/navigation.rs index 5730251..df45027 100644 --- a/src/navigation.rs +++ b/src/navigation.rs @@ -1,9 +1,9 @@ use std::{error::Error, f32::consts::PI, fmt::Debug, hash::Hash, marker::PhantomData}; use bevy::prelude::*; -use bevy_input_actionmap::InputMap; use bevy_rapier2d::prelude::*; use bevy_tts::Tts; +use leafwing_input_manager::prelude::*; use crate::{ commands::RunIfExistsExt, @@ -15,6 +15,17 @@ use crate::{ utils::target_and_other, }; +#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug)] +pub enum NavigationAction { + Move, + Rotate, + SnapLeft, + SnapRight, + SnapCardinal, + SnapReverse, + Sprint, +} + #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct MaxSpeed(pub f32); @@ -46,15 +57,15 @@ pub struct Sprinting; #[derive(Default, Deref, DerefMut)] struct Snapping(bool); -fn movement_controls( +fn movement_controls( mut commands: Commands, - config: Res>, - input: Res>, + config: Res>, time: Res, - pub action_forward: Option, - pub action_left: Option, - pub action_right: Option, - pub action_rotate_left: Option, - pub action_rotate_right: Option, - pub action_snap_left: Option, - pub action_snap_right: Option, - pub action_snap_reverse: Option, - pub action_snap_cardinal: Option, - pub action_sprint: Option, +pub struct NavigationConfig { pub forward_movement_factor: f32, pub backward_movement_factor: f32, pub strafe_movement_factor: f32, @@ -390,20 +326,9 @@ pub struct NavigationConfig { pub log_area_descriptions: bool, } -impl Default for NavigationConfig { +impl Default for NavigationConfig { fn default() -> Self { Self { - action_backward: None, - action_forward: None, - action_left: None, - action_right: None, - action_rotate_left: None, - action_rotate_right: None, - action_snap_left: None, - action_snap_right: None, - action_snap_reverse: None, - action_snap_cardinal: None, - action_sprint: None, forward_movement_factor: 1., backward_movement_factor: 1., strafe_movement_factor: 1., @@ -429,12 +354,12 @@ where A: Hash + Eq + Copy + Send + Sync, { fn build(&self, app: &mut App) { - if !app.world.contains_resource::>() { - app.insert_resource(NavigationConfig::::default()); + if !app.world.contains_resource::>() { + app.insert_resource(NavigationConfig::::default()); } let config = app .world - .get_resource::>() + .get_resource::>() .unwrap() .clone(); const SNAP: &str = "SNAP"; @@ -442,6 +367,7 @@ where .register_type::() .register_type::() .register_type::() + .add_plugin(InputManagerPlugin::::default()) .add_system_to_stage(CoreStage::PostUpdate, update_direction) .add_system_to_stage(CoreStage::PostUpdate, remove_direction) .add_system(speak_direction.chain(error_handler)) @@ -450,9 +376,9 @@ where .add_system_to_stage(CoreStage::PostUpdate, log_area_descriptions::); const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS"; if config.movement_control_states.is_empty() { - app.add_system(movement_controls::.label(MOVEMENT_CONTROLS)) + app.add_system(movement_controls::.label(MOVEMENT_CONTROLS)) .add_system( - snap:: + snap:: .chain(error_handler) .label(SNAP) .before(MOVEMENT_CONTROLS), @@ -462,9 +388,9 @@ where for state in states { app.add_system_set( SystemSet::on_update(state) - .with_system(movement_controls::.label(MOVEMENT_CONTROLS)) + .with_system(movement_controls::.label(MOVEMENT_CONTROLS)) .with_system( - snap:: + snap:: .chain(error_handler) .label(SNAP) .before(MOVEMENT_CONTROLS),