From 2ecced8496958d926d520678bd55996582d78f49 Mon Sep 17 00:00:00 2001 From: yukkop Date: Sun, 11 Feb 2024 13:54:49 +0100 Subject: [PATCH] docs: simplest example --- example/basic/src/main.rs | 142 +++++++++++++++++++++----------------- src/contract.rs | 5 +- src/plugin.rs | 5 ++ src/resource.rs | 22 +++++- 4 files changed, 106 insertions(+), 68 deletions(-) diff --git a/example/basic/src/main.rs b/example/basic/src/main.rs index cea81cb..c6f8ce3 100644 --- a/example/basic/src/main.rs +++ b/example/basic/src/main.rs @@ -14,22 +14,19 @@ use bevy_controls::{ Action, ActionInner, GameState, GameStateInner, InputsContainer, InputsContainerInner, }, plugin::ControlsPlugin, - resource::{Binding, ButtonCombination, Controls, InputType, Inputs, PlayerInputs}, + resource::{Binding, ButtonCombination, Controls, InputType, InputValue, Inputs, PlayerInputs}, }; use strum::IntoEnumIterator; use strum_macros::EnumIter; const FIRA_CODE_PATH: &str = "font/FiraCode/FiraCode-VariableFont_wght.ttf"; -#[derive(PartialEq, Eq, Hash, EnumIter, Clone, Copy)] +#[derive(PartialEq, Eq, Hash, EnumIter, Clone, Copy, Debug)] enum MyAction { MoveForward, MoveBack, MoveLeft, MoveRight, Jump, - Interact, - Shoot, - Scope, } impl Action for MyAction {} @@ -46,7 +43,7 @@ impl GameState for MyGameState {} impl GameStateInner for MyGameState {} -#[derive(Resource, Default, Clone)] +#[derive(Resource, Default, Clone, Debug)] struct MyInputsContainer { // When the game does not provide multiplayer, one field is enough player_inputs: PlayerInputs, @@ -78,58 +75,49 @@ fn main() { ControlsPlugin::::default(), )) .add_systems(Startup, (add_bindings, setup)) + .add_systems(Update, text_update_system) .run(); } // TODO: default bingings... fn add_bindings(mut controls: ResMut>) { - controls.push( + controls.force_push( + MyAction::MoveLeft, + Binding::new(ButtonCombination::Single(InputType::Keyboard(KeyCode::A))), + ); + controls.force_push( + MyAction::MoveBack, + Binding::new(ButtonCombination::Single(InputType::Keyboard(KeyCode::S))), + ); + controls.force_push( MyAction::MoveForward, Binding::new(ButtonCombination::Single(InputType::Keyboard(KeyCode::W))), ); + controls.force_push( + MyAction::MoveRight, + Binding::new(ButtonCombination::Single(InputType::Keyboard(KeyCode::D))), + ); + controls.force_push( + MyAction::Jump, + Binding::new(ButtonCombination::Single(InputType::Keyboard(KeyCode::Space))), + ); } #[derive(Component)] struct TextBlock; +const TEXT_SIZE: f32 = 30.; + fn setup(mut commands: Commands, asset_server: Res) { commands.spawn(Camera2dBundle::default()); commands.spawn(( TextBundle::from_sections([ TextSection::new( - "Input: ", + "Inputs: A S W D Space", TextStyle { font: asset_server.load(FIRA_CODE_PATH), - font_size: 60.0, - ..default() - }, - ), - TextSection::new( - "A ", - TextStyle { - font_size: 60.0, - ..default() - }, - ), - TextSection::new( - "S ", - TextStyle { - font_size: 60.0, - ..default() - }, - ), - TextSection::new( - "W ", - TextStyle { - font_size: 60.0, - ..default() - }, - ), - TextSection::new( - "D ", - TextStyle { - font_size: 60.0, + font_size: TEXT_SIZE, ..default() }, ), @@ -137,35 +125,42 @@ fn setup(mut commands: Commands, asset_server: Res) { "\nAction: ", TextStyle { font: asset_server.load(FIRA_CODE_PATH), - font_size: 60.0, + font_size: TEXT_SIZE, ..default() }, ), TextSection::new( - "MoveLeft", + "MoveLeft ", TextStyle { - font_size: 60.0, + font_size: TEXT_SIZE, ..default() }, ), TextSection::new( - "MoveBack", + "MoveBack ", TextStyle { - font_size: 60.0, + font_size: TEXT_SIZE, ..default() }, ), TextSection::new( - "MoveForward", + "MoveForward ", TextStyle { - font_size: 60.0, + font_size: TEXT_SIZE, ..default() }, ), TextSection::new( - "MoveRight", + "MoveRight ", TextStyle { - font_size: 60.0, + font_size: TEXT_SIZE, + ..default() + }, + ), + TextSection::new( + "Jump", + TextStyle { + font_size: TEXT_SIZE, ..default() }, ), @@ -175,31 +170,52 @@ fn setup(mut commands: Commands, asset_server: Res) { } // text sections indexes -const A_INDEX: usize = 2; -const S_INDEX: usize = 3; -const W_INDEX: usize = 4; -const D_INDEX: usize = 5; - -const MOVE_LEFT_INDEX: usize = 6; -const MOVE_BACK_INDEX: usize = 7; -const MOVE_FORWARD_INDEX: usize = 8; -const MOVE_RIGHT_INDEX: usize = 9; +const MOVE_LEFT_INDEX: usize = 2; +const MOVE_BACK_INDEX: usize = 3; +const MOVE_FORWARD_INDEX: usize = 4; +const MOVE_RIGHT_INDEX: usize = 5; +const JUMP_INDEX: usize = 6; fn text_update_system( mut query: Query<&mut Text, With>, - inputs_container: MyInputsContainer, + inputs_container: Res, ) { - for mut text in &mut query { + for text in query.iter_mut() { - let input_value = inputs_container.me().expect("This is bad").get(MyAction::MoveLeft); - if input_value.is_boolean() && input_value.to_boolean() { - text.sections[MOVE_LEFT_INDEX].style.color = Color::GOLD; - } else { - text.sections[MOVE_LEFT_INDEX].style.color = Color::GOLD; - } + let player_inputs = inputs_container.me().expect("This is bad"); + let mut text = update_text( + text, + player_inputs.get(MyAction::MoveLeft), + MOVE_LEFT_INDEX); + text = update_text( + text, + player_inputs.get(MyAction::MoveBack), + MOVE_BACK_INDEX); + text = update_text( + text, + player_inputs.get(MyAction::MoveForward), + MOVE_FORWARD_INDEX); + text = update_text( + text, + player_inputs.get(MyAction::MoveRight), + MOVE_RIGHT_INDEX); + _ = update_text( + text, + InputValue::Boolean(player_inputs.get_just_pressed(MyAction::Jump).unwrap_or(false)), + JUMP_INDEX); } } +fn update_text(mut text: Mut, input_value: InputValue, index: usize) -> Mut{ + if input_value.is_boolean() && input_value.to_boolean() { + text.sections[index].style.color = Color::GOLD; + } else { + text.sections[index].style.color = Color::WHITE; + } + + text +} + // fn text_update_system( // diagnostics: Res, // mut query: Query<&mut Text, With>, diff --git a/src/contract.rs b/src/contract.rs index 7b04253..3f3df21 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -23,13 +23,14 @@ pub trait ActionInner: + IntoEnumIterator + Clone + Copy + + std::fmt::Debug { } -pub trait GameStateInner: 'static + std::marker::Sync + std::marker::Send + States + Default {} +pub trait GameStateInner: 'static + std::marker::Sync + std::marker::Send + States + Default + std::fmt::Debug {} pub trait InputsContainerInner: - 'static + std::marker::Sync + std::marker::Send + Resource + Default + 'static + std::marker::Sync + std::marker::Send + Resource + Default + std::fmt::Debug { /// The method returning an iterator over references to the PlayerInputs. /// Note: the use of 'a for both the method's lifetime and the returned Iterator's lifetime. diff --git a/src/plugin.rs b/src/plugin.rs index c2d3432..d8ded05 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -63,9 +63,13 @@ impl< } } + log::trace!("action {:?} in condition", action); + match &binding.input { ButtonCombination::Single(button) => match button { InputType::Keyboard(key) => { + log::trace!("presed?: {:?}", keyboard_input.pressed(*key)); + log::trace!("active"); inputs.forced_set(*action, keyboard_input.pressed(*key)); } InputType::Mouse(input) => { @@ -117,6 +121,7 @@ impl< } } + log::trace!("active"); // TODO: should be [`Chord`](ButtonCombination::Chord) only [`Boolean`](InputValue::Boolean) type inputs.forced_set(*action, true); } diff --git a/src/resource.rs b/src/resource.rs index 822843c..dc437b0 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -112,6 +112,7 @@ impl PlayerInputs { panic!("This input is not boolean") } + // TODO this is must be binding option for non axis inputs /// Returns `true` if current `InputValue` has become `InputValue::Boolean(true)` in this frame /// If input has not same type as `InputValue` on previous frame return `Error()` pub fn get_just_pressed(&self, action: A) -> Result> { @@ -238,7 +239,7 @@ common_traits_conditions! { Tap, } - #[derive(Clone)] + #[derive(Clone, Debug)] pub struct ActivationOptions { /// Manner in which input is registered pub mode: ActivationMode, @@ -388,7 +389,7 @@ impl InputValue { } common_traits_conditions! { - #[derive(Clone)] + #[derive(Clone, Debug)] pub struct Bindings { /// List of bindings for action #[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))] @@ -415,6 +416,10 @@ impl Bindings { } } + pub fn force_push(&mut self, binding: Binding) { + self.list.push(binding); + } + pub fn push(&mut self, binding: Binding) { if self.options == OptionsMode::Immutable { warn!("You try to push binding to immutable bindings"); @@ -468,7 +473,7 @@ impl Bindings { common_traits_conditions! { /// Contains all bindings for action /// and different activation options - #[derive(Default, Clone)] + #[derive(Default, Clone, Debug)] pub struct BindingConfig { #[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))] pub bindings: Bindings, @@ -517,6 +522,17 @@ impl Controls { self.0.get(&action) } + /// Forced push new binding for action + pub fn force_push(&mut self, action: A, binding: Binding) { + // TODO: warning if config is not exist yet + // TODO: interface for [`ActivationOptions`] + self.0 + .entry(action) + .or_insert_with(BindingConfig::default) + .bindings + .force_push(binding); + } + /// Push new binding for action pub fn push(&mut self, action: A, binding: Binding) { // TODO: warning if config is not exist yet