From e6c9e65417eb8c47a8fffde57f393e87a8bdc9ea Mon Sep 17 00:00:00 2001 From: yukkop Date: Fri, 13 Sep 2024 08:01:38 +0000 Subject: [PATCH] refactor: more coments --- 1 | 173 ------------------------------ crate/bevy_controls/src/plugin.rs | 39 +++++-- 2 files changed, 32 insertions(+), 180 deletions(-) delete mode 100644 1 diff --git a/1 b/1 deleted file mode 100644 index 792e8fe..0000000 --- a/1 +++ /dev/null @@ -1,173 +0,0 @@ -use bevy_app::{App, Plugin, PreUpdate}; -use bevy_derive::{Deref, DerefMut}; -use bevy_ecs::system::{In, IntoSystem}; -use bevy_ecs::{ - event::EventReader, - system::{Res, ResMut, Resource}, -}; -use bevy_input::{ - keyboard::KeyCode, - mouse::{MouseButton, MouseMotion, MouseScrollUnit, MouseWheel}, - ButtonInput, -}; -use bevy_utils::HashMap; - -use crate::{ - contract::{Action, GameState, InputsContainer}, - resource::*, -}; - -pub struct ControlsPlugin, Gs: GameState> { - _action: std::marker::PhantomData, - _inputs_container: std::marker::PhantomData, - _game_state: std::marker::PhantomData, - controls: Controls, -} - -impl, Gs: GameState> Default for ControlsPlugin { - fn default() -> Self { - Self { - _action: std::marker::PhantomData, - _inputs_container: std::marker::PhantomData, - _game_state: std::marker::PhantomData, - controls: Controls::::default(), - } - } -} - -impl, Gs: GameState> ControlsPlugin { - pub fn new(controls: Controls) -> Self { - Self { - _action: std::marker::PhantomData, - _inputs_container: std::marker::PhantomData, - _game_state: std::marker::PhantomData, - controls, - } - } -} - -#[derive(Resource, Default, Debug, Deref, DerefMut)] -struct TrigeredInputs(HashMap); - -impl, Gs: GameState> Plugin for ControlsPlugin { - fn build(&self, app: &mut App) { - app - .insert_resource(self.controls.clone()) - .init_resource::() - .init_resource::() - .insert_state::(Gs::default()) - .add_systems( - PreUpdate, - Self::collect_inputs.pipe(Self::fill_players_inputs), - ); - - #[cfg(feature = "reflect")] - app.register_type::>(); - } -} - -impl, Gs: GameState> ControlsPlugin { - // Separate collecting and filling is necessary becouse order of complicate imputs in future - fn collect_inputs( - keyboard_button: Res>, - mouse_buttons: Res>, - mut scroll_evr: EventReader, - mut motion_evr: EventReader, - // mut collected_inputs: ResMut, - ) -> TrigeredInputs { - let mut collected_inputs = TrigeredInputs(HashMap::new()); - for key in keyboard_button.get_pressed() { - collected_inputs.insert(InputType::Keyboard(*key), InputValue::Boolean(true)); - } - - // buttons.get_just_released() - - for button in mouse_buttons.get_pressed() { - collected_inputs.insert( - InputType::Mouse(MouseInput::Button(*button)), - InputValue::Boolean(true), - ); - } - - for ev in motion_evr.read() { - collected_inputs.insert( - InputType::Mouse(MouseInput::Axis(AxisName::Horizontal)), - InputValue::Float(ev.delta.x), - ); - collected_inputs.insert( - InputType::Mouse(MouseInput::Axis(AxisName::Vertical)), - InputValue::Float(ev.delta.y), - ); - } - - for ev in scroll_evr.read() { - match ev.unit { - MouseScrollUnit::Line => { - collected_inputs.insert( - InputType::Mouse(MouseInput::Wheel(AxisName::Horizontal)), - InputValue::Float(ev.x), - ); - collected_inputs.insert( - InputType::Mouse(MouseInput::Wheel(AxisName::Vertical)), - InputValue::Float(ev.y), - ); - } - MouseScrollUnit::Pixel => { - panic!("I'm do not accept you to use touch pad in my game"); - } - } - } - - collected_inputs - } - - // TODO: ! Zero out values that did not arrive - fn fill_players_inputs( - In(collected_inputs): In, - mut inputs_container: ResMut, - controls: Res>, - game_state: Res>, - ) { - if let Some(inputs) = inputs_container.me_mut() { - // TODO: only on controls change - let mut action_binding_pairs: Vec<(&A, &BindingConfig, &Binding)> = Vec::new(); - for (action, config) in controls.iter() { - for binding in config.bindings.iter() { - action_binding_pairs.push((action, config, binding)); - } - } - - action_binding_pairs.sort_by(|a, b| b.2.input.len().cmp(&a.2.input.len())); - - 'bindings_loop: for (action, _config, binding) in action_binding_pairs.iter() { - // check binding conditions - for condition in &binding.conditions { - match condition { - BindingCondition::InGameState(state) => { - if *state != *game_state.get() { - continue 'bindings_loop; - } - } - } - } - - //log::info!("{:#?}", collected_inputs); - //log::info!("{:#?}", action_binding_pairs[0]); - - match &binding.input { - ButtonCombination::Single(input_type) => { - // TODO: exclude if used - if let Some(value) = collected_inputs.get(&*input_type) { - inputs.forced_set(**action, *value); - } else { - inputs.forced_set(**action, InputValue::Empty); - } - } - } - } - } else { - // TODO: print onece - log::warn!("cannot find me in inputs container"); - } - } -} diff --git a/crate/bevy_controls/src/plugin.rs b/crate/bevy_controls/src/plugin.rs index 1b205e6..52be6d8 100644 --- a/crate/bevy_controls/src/plugin.rs +++ b/crate/bevy_controls/src/plugin.rs @@ -69,7 +69,13 @@ impl, Gs: GameState> Plugin for ControlsPlugin } impl, Gs: GameState> ControlsPlugin { - // Separate collecting and filling is necessary becouse order of complicate imputs in future + /// Collects input events from various input devices + /// (keyboard, mouse buttons, mouse motion, and scroll) + /// and stores them in a `TrigeredInputs` structure. + /// + /// This function is separated from filling inputs to allow for more complex input handling + /// in the future, particularly in scenarios where the order of input events becomes significant. + /// fn collect_inputs( keyboard_button: Res>, mouse_buttons: Res>, @@ -78,12 +84,15 @@ impl, Gs: GameState> ControlsPlugin // mut collected_inputs: ResMut, ) -> TrigeredInputs { let mut collected_inputs = TrigeredInputs(HashMap::new()); + + // Collect pressed keyboard buttons for key in keyboard_button.get_pressed() { collected_inputs.insert(InputType::Keyboard(*key), InputValue::Boolean(true)); } // buttons.get_just_released() + // Collect pressed mouse buttons for button in mouse_buttons.get_pressed() { collected_inputs.insert( InputType::Mouse(MouseInput::Button(*button)), @@ -91,6 +100,7 @@ impl, Gs: GameState> ControlsPlugin ); } + // Collect mouse motion events for ev in motion_evr.read() { collected_inputs.insert( InputType::Mouse(MouseInput::Axis(AxisName::Horizontal)), @@ -102,8 +112,10 @@ impl, Gs: GameState> ControlsPlugin ); } + // Collect mouse scroll events for ev in scroll_evr.read() { match ev.unit { + // Handle scroll in line units MouseScrollUnit::Line => { collected_inputs.insert( InputType::Mouse(MouseInput::Wheel(AxisName::Horizontal)), @@ -114,6 +126,7 @@ impl, Gs: GameState> ControlsPlugin InputValue::Float(ev.y), ); } + // Handle scroll in pixel units (not accepted in this game) MouseScrollUnit::Pixel => { panic!("I'm do not accept you to use touch pad in my game"); } @@ -124,27 +137,40 @@ impl, Gs: GameState> ControlsPlugin } // TODO: ! Zero out values that did not arrive + /// Fills the player's inputs based on the collected inputs and the current control bindings. + /// + /// This function takes in the current inputs, updates them according to the specified control + /// bindings, and then stores the updated inputs in the input container. It only updates the + /// inputs if they satisfy the binding conditions, such as being in a specific game state. + /// fn fill_players_inputs( In(collected_inputs): In, mut inputs_container: ResMut, controls: Res>, game_state: Res>, ) { + // Check if the input container is accessible if let Some(inputs) = inputs_container.me_mut() { + // Initialize a vector to hold tuples of actions and their corresponding bindings // TODO: only on controls change let mut action_binding_pairs: Vec<(&A, &BindingConfig, &Binding)> = Vec::new(); + + // Iterate over the control bindings and collect all action-binding pairs for (action, config) in controls.iter() { for binding in config.bindings.iter() { action_binding_pairs.push((action, config, binding)); } } + // Sort the action-binding pairs by the length of the input sequence, in descending order action_binding_pairs.sort_by(|a, b| b.2.input.len().cmp(&a.2.input.len())); + // Loop over each binding to apply the corresponding input actions 'bindings_loop: for (action, _config, binding) in action_binding_pairs.iter() { - // check binding conditions + // Check the binding conditions before applying for condition in &binding.conditions { match condition { + // Skip this binding if the game state does not match the condition BindingCondition::InGameState(state) => { if *state != *game_state.get() { continue 'bindings_loop; @@ -153,12 +179,10 @@ impl, Gs: GameState> ControlsPlugin } } - //log::info!("{:#?}", collected_inputs); - //log::info!("{:#?}", action_binding_pairs[0]); - + // Match the binding input type to update the player's inputs match &binding.input { ButtonCombination::Single(input_type) => { - // TODO: exclude if used + // TODO: Exclude this input if it has already been used if let Some(value) = collected_inputs.get(&*input_type) { inputs.forced_set(**action, *value); } else { @@ -168,7 +192,8 @@ impl, Gs: GameState> ControlsPlugin } } } else { - // TODO: print onece + // Log a warning if the inputs container cannot be accessed + // TODO: Ensure this warning is only printed once log::warn!("cannot find me in inputs container"); } }