From b88f37457b5be90add250e98f42e0e9398a730bb Mon Sep 17 00:00:00 2001 From: nativerv Date: Fri, 16 Feb 2024 03:49:36 +0300 Subject: [PATCH] style: run `cargo fmt` --- crate/bevy_controls/src/contract.rs | 493 +++++++++++----------- crate/bevy_controls/src/lib.rs | 4 +- crate/bevy_controls/src/plugin.rs | 507 +++++++++++------------ crate/bevy_controls/src/resource.rs | 622 ++++++++++++++-------------- crate/bevy_controls/src/util.rs | 154 +++---- rustfmt.toml | 1 + 6 files changed, 889 insertions(+), 892 deletions(-) create mode 100644 rustfmt.toml diff --git a/crate/bevy_controls/src/contract.rs b/crate/bevy_controls/src/contract.rs index 0c925b6..7d6e32d 100644 --- a/crate/bevy_controls/src/contract.rs +++ b/crate/bevy_controls/src/contract.rs @@ -1,245 +1,248 @@ -use std::hash::Hash; - -use bevy_ecs::{schedule::States, system::Resource}; -#[cfg(feature = "inspector-egui")] -use bevy_inspector_egui::inspector_options::InspectorOptionsType; -use strum::IntoEnumIterator; -// #[cfg(all(feature = "reflect", feature = "serialize"))] -// use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; -#[cfg(feature = "reflect")] -use bevy_reflect::{FromReflect, Reflect, TypePath}; -#[cfg(feature = "serialize")] -use serde::{de::DeserializeOwned, Serialize}; - -use crate::resource::PlayerInputs; - -pub trait ActionInner: - 'static - + std::marker::Sync - + std::marker::Send - + PartialEq - + Eq - + Hash - + IntoEnumIterator - + Clone - + Copy - + std::fmt::Debug -{ -} - -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 + 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. - fn iter_inputs<'a>(&'a self) -> Box> + 'a>; - /// The method returning an player inputs of this client. - fn me<'a>(&'a self) -> Option<&'a PlayerInputs>; - /// The method returning an mutable player inputs of this client. - fn me_mut<'a>(&'a mut self) -> Option<&'a mut PlayerInputs>; -} - -#[cfg(feature = "serialize")] -pub trait SerializeImpl: Serialize + DeserializeOwned {} - -#[cfg(feature = "reflect")] -pub trait ReflectImpl: Reflect + TypePath + FromReflect {} - -#[cfg(feature = "inspector-egui")] -pub trait InspectorEguiImpl: InspectorOptionsType {} - -// ===== Action ===== -// SAFETY: inspector-egui includes reflect -#[cfg(all( - not(feature = "serialize"), - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait Action: ActionInner {} - -#[cfg(all( - feature = "serialize", - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait Action: ActionInner + SerializeImpl {} - -#[cfg(all( - not(feature = "serialize"), - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait Action: ActionInner + ReflectImpl {} - -#[cfg(all( - feature = "serialize", - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait Action: ActionInner + SerializeImpl + ReflectImpl {} - -#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] -pub trait Action: ActionInner + ReflectImpl + InspectorEguiImpl {} - -#[cfg(all(feature = "serialize", feature = "inspector-egui"))] -pub trait Action: ActionInner + SerializeImpl + ReflectImpl + InspectorEguiImpl {} - -// ===== GameState ===== -// SAFETY: inspector-egui includes reflect -#[cfg(all( - not(feature = "serialize"), - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait GameState: GameStateInner {} - -#[cfg(all( - feature = "serialize", - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait GameState: GameStateInner + SerializeImpl {} - -#[cfg(all( - not(feature = "serialize"), - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait GameState: GameStateInner + ReflectImpl {} - -#[cfg(all( - feature = "serialize", - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait GameState: GameStateInner + SerializeImpl + ReflectImpl {} - -#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] -pub trait GameState: GameStateInner + ReflectImpl + InspectorEguiImpl {} - -#[cfg(all(feature = "serialize", feature = "inspector-egui"))] -pub trait GameState: GameStateInner + SerializeImpl + ReflectImpl + InspectorEguiImpl {} - -// ===== InputsContainer ===== -// SAFETY: inspector-egui includes reflect -#[cfg(all( - not(feature = "serialize"), - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait InputsContainer: InputsContainerInner {} - -#[cfg(all( - feature = "serialize", - not(feature = "reflect"), - not(feature = "inspector-egui") -))] -pub trait InputsContainer: InputsContainerInner + SerializeImpl {} - -#[cfg(all( - not(feature = "serialize"), - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait InputsContainer: InputsContainerInner + ReflectImpl {} - -#[cfg(all( - feature = "serialize", - feature = "reflect", - not(feature = "inspector-egui") -))] -pub trait InputsContainer: - InputsContainerInner + SerializeImpl + ReflectImpl -{ -} - -#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] -pub trait InputsContainer: - InputsContainerInner + ReflectImpl + InspectorEguiImpl -{ -} - -#[cfg(all(feature = "serialize", feature = "inspector-egui"))] -pub trait InputsContainer: - InputsContainerInner + SerializeImpl + ReflectImpl + InspectorEguiImpl -{ -} - -// #[cfg(test)] -// mod test { -// use bevy_ecs::{entity::Entity, schedule::States}; -// use bevy_utils::{HashMap, prelude::default}; -// use strum_macros::EnumIter; - -// #[cfg(feature = "serialize")] -// use serde::{Serialize, Deserialize}; - -// use crate::{hashmap, resource::PlayerInputs, common_traits_conditions}; - -// common_traits_conditions! { -// #[derive(Debug, Clone, PartialEq)] -// #[cfg_attr(feature = "reflect", reflect(Resource))] -// pub struct Lobby { -// pub me: PlayerId, -// pub players: HashMap, -// } -// } - -// impl Default for Lobby { -// fn default() -> Self { -// Self { -// me: PlayerId::Host, -// players: hashmap! { -// PlayerId::Host => Player::default() -// }, -// } -// } -// } - -// common_traits_conditions! { -// #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -// pub enum PlayerId { -// /// Host or alone -// Host, -// /// Client -// Client(()), -// } - -// #[derive(Default, Debug, PartialEq, Clone)] -// pub struct Player { -// /// Client do not need to know about other clients -// #[cfg_attr(feature = "serialize", serde(skip))] -// pub inputs: PlayerInputs, -// #[cfg_attr(feature = "serialize", serde(skip))] -// pub entity: Option, -// } -// } - -// #[derive(Debug, PartialEq, Clone, States, Default, Hash, Eq)] -// pub enum GameState { -// #[default] -// LevelEditor, -// InGame, -// } - -// impl super::GameState for GameState {} - -// // TODO: it is just plug, it must be a trait -// /// Actions that can be performed by player -// #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, EnumIter)] -// pub enum Action { -// /// Move forward -// LeverEditorForward, -// /// Move backward -// LevelEditorBackward, -// /// Move left -// LevelEditorLeft, -// /// Move right -// LevelEditorRight, -// LevelEditorFly, -// } - -// impl super::Action for Action {} -// } +use std::hash::Hash; + +use bevy_ecs::{schedule::States, system::Resource}; +#[cfg(feature = "inspector-egui")] +use bevy_inspector_egui::inspector_options::InspectorOptionsType; +use strum::IntoEnumIterator; +// #[cfg(all(feature = "reflect", feature = "serialize"))] +// use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; +#[cfg(feature = "reflect")] +use bevy_reflect::{FromReflect, Reflect, TypePath}; +#[cfg(feature = "serialize")] +use serde::{de::DeserializeOwned, Serialize}; + +use crate::resource::PlayerInputs; + +pub trait ActionInner: + 'static + + std::marker::Sync + + std::marker::Send + + PartialEq + + Eq + + Hash + + IntoEnumIterator + + Clone + + Copy + + std::fmt::Debug +{ +} + +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 + 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. + fn iter_inputs<'a>(&'a self) -> Box> + 'a>; + /// The method returning an player inputs of this client. + fn me<'a>(&'a self) -> Option<&'a PlayerInputs>; + /// The method returning an mutable player inputs of this client. + fn me_mut<'a>(&'a mut self) -> Option<&'a mut PlayerInputs>; +} + +#[cfg(feature = "serialize")] +pub trait SerializeImpl: Serialize + DeserializeOwned {} + +#[cfg(feature = "reflect")] +pub trait ReflectImpl: Reflect + TypePath + FromReflect {} + +#[cfg(feature = "inspector-egui")] +pub trait InspectorEguiImpl: InspectorOptionsType {} + +// ===== Action ===== +// SAFETY: inspector-egui includes reflect +#[cfg(all( + not(feature = "serialize"), + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait Action: ActionInner {} + +#[cfg(all( + feature = "serialize", + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait Action: ActionInner + SerializeImpl {} + +#[cfg(all( + not(feature = "serialize"), + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait Action: ActionInner + ReflectImpl {} + +#[cfg(all( + feature = "serialize", + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait Action: ActionInner + SerializeImpl + ReflectImpl {} + +#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] +pub trait Action: ActionInner + ReflectImpl + InspectorEguiImpl {} + +#[cfg(all(feature = "serialize", feature = "inspector-egui"))] +pub trait Action: ActionInner + SerializeImpl + ReflectImpl + InspectorEguiImpl {} + +// ===== GameState ===== +// SAFETY: inspector-egui includes reflect +#[cfg(all( + not(feature = "serialize"), + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait GameState: GameStateInner {} + +#[cfg(all( + feature = "serialize", + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait GameState: GameStateInner + SerializeImpl {} + +#[cfg(all( + not(feature = "serialize"), + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait GameState: GameStateInner + ReflectImpl {} + +#[cfg(all( + feature = "serialize", + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait GameState: GameStateInner + SerializeImpl + ReflectImpl {} + +#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] +pub trait GameState: GameStateInner + ReflectImpl + InspectorEguiImpl {} + +#[cfg(all(feature = "serialize", feature = "inspector-egui"))] +pub trait GameState: GameStateInner + SerializeImpl + ReflectImpl + InspectorEguiImpl {} + +// ===== InputsContainer ===== +// SAFETY: inspector-egui includes reflect +#[cfg(all( + not(feature = "serialize"), + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait InputsContainer: InputsContainerInner {} + +#[cfg(all( + feature = "serialize", + not(feature = "reflect"), + not(feature = "inspector-egui") +))] +pub trait InputsContainer: InputsContainerInner + SerializeImpl {} + +#[cfg(all( + not(feature = "serialize"), + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait InputsContainer: InputsContainerInner + ReflectImpl {} + +#[cfg(all( + feature = "serialize", + feature = "reflect", + not(feature = "inspector-egui") +))] +pub trait InputsContainer: + InputsContainerInner + SerializeImpl + ReflectImpl +{ +} + +#[cfg(all(not(feature = "serialize"), feature = "inspector-egui"))] +pub trait InputsContainer: + InputsContainerInner + ReflectImpl + InspectorEguiImpl +{ +} + +#[cfg(all(feature = "serialize", feature = "inspector-egui"))] +pub trait InputsContainer: + InputsContainerInner + SerializeImpl + ReflectImpl + InspectorEguiImpl +{ +} + +// #[cfg(test)] +// mod test { +// use bevy_ecs::{entity::Entity, schedule::States}; +// use bevy_utils::{HashMap, prelude::default}; +// use strum_macros::EnumIter; + +// #[cfg(feature = "serialize")] +// use serde::{Serialize, Deserialize}; + +// use crate::{hashmap, resource::PlayerInputs, common_traits_conditions}; + +// common_traits_conditions! { +// #[derive(Debug, Clone, PartialEq)] +// #[cfg_attr(feature = "reflect", reflect(Resource))] +// pub struct Lobby { +// pub me: PlayerId, +// pub players: HashMap, +// } +// } + +// impl Default for Lobby { +// fn default() -> Self { +// Self { +// me: PlayerId::Host, +// players: hashmap! { +// PlayerId::Host => Player::default() +// }, +// } +// } +// } + +// common_traits_conditions! { +// #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +// pub enum PlayerId { +// /// Host or alone +// Host, +// /// Client +// Client(()), +// } + +// #[derive(Default, Debug, PartialEq, Clone)] +// pub struct Player { +// /// Client do not need to know about other clients +// #[cfg_attr(feature = "serialize", serde(skip))] +// pub inputs: PlayerInputs, +// #[cfg_attr(feature = "serialize", serde(skip))] +// pub entity: Option, +// } +// } + +// #[derive(Debug, PartialEq, Clone, States, Default, Hash, Eq)] +// pub enum GameState { +// #[default] +// LevelEditor, +// InGame, +// } + +// impl super::GameState for GameState {} + +// // TODO: it is just plug, it must be a trait +// /// Actions that can be performed by player +// #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, EnumIter)] +// pub enum Action { +// /// Move forward +// LeverEditorForward, +// /// Move backward +// LevelEditorBackward, +// /// Move left +// LevelEditorLeft, +// /// Move right +// LevelEditorRight, +// LevelEditorFly, +// } + +// impl super::Action for Action {} +// } diff --git a/crate/bevy_controls/src/lib.rs b/crate/bevy_controls/src/lib.rs index 40bb6de..cbd2b56 100644 --- a/crate/bevy_controls/src/lib.rs +++ b/crate/bevy_controls/src/lib.rs @@ -1,6 +1,6 @@ -pub mod resource; -pub mod plugin; pub mod contract; +pub mod plugin; +pub mod resource; mod util; pub use util::*; diff --git a/crate/bevy_controls/src/plugin.rs b/crate/bevy_controls/src/plugin.rs index 34c4530..261c1e1 100644 --- a/crate/bevy_controls/src/plugin.rs +++ b/crate/bevy_controls/src/plugin.rs @@ -1,260 +1,247 @@ -use bevy_app::{Plugin, App, Update}; -use bevy_ecs::{system::{Res, ResMut}, schedule::State}; -use bevy_input::{Input, keyboard::KeyCode, mouse::MouseButton}; - -use crate::{resource::*, contract::{Action, GameState, InputsContainer}}; - -pub struct ControlsPlugin { - _action: std::marker::PhantomData, - _inputs_container: std::marker::PhantomData, - _game_state: std::marker::PhantomData, -} - -impl Default for ControlsPlugin { - fn default() -> Self { - Self { - _action: std::marker::PhantomData, - _inputs_container: std::marker::PhantomData, - _game_state: std::marker::PhantomData, - } - } -} - -impl< - A: Action, - Ic: InputsContainer, - Gs: GameState -> Plugin for ControlsPlugin { - fn build(&self, app: &mut App) { - app.init_resource::>() - .init_resource::() - .add_state::() - .add_systems(Update, Self::save_input); - - #[cfg(feature = "reflect")] - app.register_type::>(); - } - -} - -impl< - A: Action, - Ic: InputsContainer, - Gs: GameState -> ControlsPlugin { - /// Process all hard inputs and bindings to update [`PlayerInputs`] - fn save_input( - keyboard_input: Res>, - mouse_input: Res>, - mut inputs_container: ResMut, - controls: Res>, - game_state: Res>, - ) { - if let Some(inputs) = inputs_container.me_mut() { - for (action, config) in controls.iter() { - 'bindings_loop: for binding in config.bindings.iter() { - for condition in &binding.conditions { - match condition { - BindingCondition::InGameState(state) => { - if *state != *game_state.get() { - continue 'bindings_loop; - } - } - } - } - - log::trace!("action binding {:?} {:?} in condition", action, binding); - - match &binding.input { - ButtonCombination::Single(button) => match button { - InputType::Keyboard(key) => { - log::trace!("presed?: {:?}", keyboard_input.pressed(*key)); - log::trace!("active"); - if keyboard_input.pressed(*key) { - inputs.forced_set(*action, true); - break; // when on binding trigered no sence check another - } - inputs.forced_set(*action, false); // FIXME: this is happening on every pass so too frequently - } - InputType::Mouse(input) => { - match input { - MouseInput::Axis(_axis) => { - todo!(); - } - MouseInput::Button(button) => { - if !mouse_input - .get_pressed() - .any(|b| b == button) - { - continue 'bindings_loop; - } - } - MouseInput::Wheel(_axis) => { - todo!(); - } - } - } - }, - ButtonCombination::Chord(buttons) => { - // If any button in chord is not pressed we skip this `binding` - for button in buttons { - match button { - InputType::Keyboard(key) => { - if !keyboard_input.pressed(*key) { - continue 'bindings_loop; - } - } - InputType::Mouse(input) => { - match input { - MouseInput::Axis(_axis) => { - todo!(); - } - MouseInput::Button(button) => { - if !mouse_input - .get_pressed() - .any(|b| b == button) - { - continue 'bindings_loop; - } - } - MouseInput::Wheel(_axis) => { - todo!(); - } - } - } - } - } - - log::trace!("active"); - // TODO: should be [`Chord`](ButtonCombination::Chord) only [`Boolean`](InputValue::Boolean) type - inputs.forced_set(*action, true); - break; // when on binding trigered no sence check another - } - } - } - } - } else { - log::error!("cannot find me in inputs container") - } - } -} - - -// #[cfg(test)] -// mod performance_test { -// use crate::{ util::test::{enable_loggings, measure_time, Times}, resource::PlayerInputs}; - -// use super::Controls; -// use std::time::Duration; - -// /// Test for execution time for [`Controls`] get -// /// -// /// Example: -// /// ``` -// /// cargo test --package pih-pah-app --lib --features "dev, ui_egui" -- controls::test::controls_get --exact --nocapture -// /// ``` -// #[test] -// fn controls_get() { -// enable_loggings(); - -// let controls = Controls::default(); - -// let duration = measure_time( -// || { -// controls.get(Action::LeverEditorForward); -// controls.get(Action::LevelEditorBackward); -// controls.get(Action::LevelEditorLeft); -// controls.get(Action::LevelEditorRight); -// }, -// Times::default(), -// ); - -// log::info!("time: {:?}", duration); -// } - -// /// Test for execution speed for [`PlayerInputs`] get -// fn player_inputs_get() -> Duration { -// enable_loggings(); - -// let inputs = PlayerInputs::default(); - -// let duration = measure_time( -// || { -// inputs.get(Action::LeverEditorForward); -// inputs.get(Action::LevelEditorBackward); -// inputs.get(Action::LevelEditorLeft); -// inputs.get(Action::LevelEditorRight); -// }, -// Times::default(), -// ); - -// duration -// } - -// /// Test for execution speed for [`PlayerInputs`] get_many -// fn player_inputs_get_many() -> Duration { -// enable_loggings(); - -// let inputs = PlayerInputs::default(); - -// let duration = measure_time( -// || { -// inputs.get_many(vec![ -// Action::LeverEditorForward, -// Action::LevelEditorBackward, -// Action::LevelEditorLeft, -// Action::LevelEditorRight, -// ]); -// }, -// Times::default(), -// ); - -// duration -// } - -// /// Test for execution speed for [`PlayerInputs`] get and get_many -// /// -// /// Example: -// /// ``` -// /// cargo test --package pih-pah-app --lib --features "dev, ui_egui" -- controls::test::compare_player_inputs_get_and_get_many --exact --nocapture -// /// ``` -// #[test] -// fn compare_player_inputs_get_and_get_many() { -// let get = player_inputs_get(); -// let get_many = player_inputs_get_many(); - -// log::info!("get: {:?}", get); -// log::info!("get_many: {:?}", get_many); -// } - -// /// Test for execution speed for [`InputValue`] casting -// #[test] -// fn action_casting() { -// enable_loggings(); - -// let inputs = PlayerInputs::default(); - -// let duration = measure_time( -// || { -// let _ = (inputs.get(Action::LeverEditorForward).as_boolean() as i8 -// - inputs.get(Action::LevelEditorBackward).as_boolean() as i8) -// as f32; -// }, -// 10000000.into(), -// ); - -// log::info!("with casting: {:?}", duration); - -// let inputs = PlayerInputs::default(); - -// let duration = measure_time( -// || { -// let _ = inputs.get(Action::LeverEditorForward); -// let _ = inputs.get(Action::LevelEditorBackward); -// }, -// 10000000.into(), -// ); - -// log::info!("without casting: {:?}", duration); -// } -// } +use bevy_app::{App, Plugin, Update}; +use bevy_ecs::{ + schedule::State, + system::{Res, ResMut}, +}; +use bevy_input::{keyboard::KeyCode, mouse::MouseButton, Input}; + +use crate::{ + contract::{Action, GameState, InputsContainer}, + resource::*, +}; + +pub struct ControlsPlugin { + _action: std::marker::PhantomData, + _inputs_container: std::marker::PhantomData, + _game_state: std::marker::PhantomData, +} + +impl Default for ControlsPlugin { + fn default() -> Self { + Self { + _action: std::marker::PhantomData, + _inputs_container: std::marker::PhantomData, + _game_state: std::marker::PhantomData, + } + } +} + +impl, Gs: GameState> Plugin for ControlsPlugin { + fn build(&self, app: &mut App) { + app + .init_resource::>() + .init_resource::() + .add_state::() + .add_systems(Update, Self::save_input); + + #[cfg(feature = "reflect")] + app.register_type::>(); + } +} + +impl, Gs: GameState> ControlsPlugin { + /// Process all hard inputs and bindings to update [`PlayerInputs`] + fn save_input( + keyboard_input: Res>, + mouse_input: Res>, + mut inputs_container: ResMut, + controls: Res>, + game_state: Res>, + ) { + if let Some(inputs) = inputs_container.me_mut() { + for (action, config) in controls.iter() { + 'bindings_loop: for binding in config.bindings.iter() { + for condition in &binding.conditions { + match condition { + BindingCondition::InGameState(state) => { + if *state != *game_state.get() { + continue 'bindings_loop; + } + } + } + } + + log::trace!("action binding {:?} {:?} in condition", action, binding); + + match &binding.input { + ButtonCombination::Single(button) => match button { + InputType::Keyboard(key) => { + log::trace!("presed?: {:?}", keyboard_input.pressed(*key)); + log::trace!("active"); + if keyboard_input.pressed(*key) { + inputs.forced_set(*action, true); + break; // when on binding trigered no sence check another + } + inputs.forced_set(*action, false); // FIXME: this is happening on every pass so too frequently + } + InputType::Mouse(input) => match input { + MouseInput::Axis(_axis) => { + todo!(); + } + MouseInput::Button(button) => { + if !mouse_input.get_pressed().any(|b| b == button) { + continue 'bindings_loop; + } + } + MouseInput::Wheel(_axis) => { + todo!(); + } + }, + }, + ButtonCombination::Chord(buttons) => { + // If any button in chord is not pressed we skip this `binding` + for button in buttons { + match button { + InputType::Keyboard(key) => { + if !keyboard_input.pressed(*key) { + continue 'bindings_loop; + } + } + InputType::Mouse(input) => match input { + MouseInput::Axis(_axis) => { + todo!(); + } + MouseInput::Button(button) => { + if !mouse_input.get_pressed().any(|b| b == button) { + continue 'bindings_loop; + } + } + MouseInput::Wheel(_axis) => { + todo!(); + } + }, + } + } + + log::trace!("active"); + // TODO: should be [`Chord`](ButtonCombination::Chord) only [`Boolean`](InputValue::Boolean) type + inputs.forced_set(*action, true); + break; // when on binding trigered no sence check another + } + } + } + } + } else { + log::error!("cannot find me in inputs container") + } + } +} + +// #[cfg(test)] +// mod performance_test { +// use crate::{ util::test::{enable_loggings, measure_time, Times}, resource::PlayerInputs}; + +// use super::Controls; +// use std::time::Duration; + +// /// Test for execution time for [`Controls`] get +// /// +// /// Example: +// /// ``` +// /// cargo test --package pih-pah-app --lib --features "dev, ui_egui" -- controls::test::controls_get --exact --nocapture +// /// ``` +// #[test] +// fn controls_get() { +// enable_loggings(); + +// let controls = Controls::default(); + +// let duration = measure_time( +// || { +// controls.get(Action::LeverEditorForward); +// controls.get(Action::LevelEditorBackward); +// controls.get(Action::LevelEditorLeft); +// controls.get(Action::LevelEditorRight); +// }, +// Times::default(), +// ); + +// log::info!("time: {:?}", duration); +// } + +// /// Test for execution speed for [`PlayerInputs`] get +// fn player_inputs_get() -> Duration { +// enable_loggings(); + +// let inputs = PlayerInputs::default(); + +// let duration = measure_time( +// || { +// inputs.get(Action::LeverEditorForward); +// inputs.get(Action::LevelEditorBackward); +// inputs.get(Action::LevelEditorLeft); +// inputs.get(Action::LevelEditorRight); +// }, +// Times::default(), +// ); + +// duration +// } + +// /// Test for execution speed for [`PlayerInputs`] get_many +// fn player_inputs_get_many() -> Duration { +// enable_loggings(); + +// let inputs = PlayerInputs::default(); + +// let duration = measure_time( +// || { +// inputs.get_many(vec![ +// Action::LeverEditorForward, +// Action::LevelEditorBackward, +// Action::LevelEditorLeft, +// Action::LevelEditorRight, +// ]); +// }, +// Times::default(), +// ); + +// duration +// } + +// /// Test for execution speed for [`PlayerInputs`] get and get_many +// /// +// /// Example: +// /// ``` +// /// cargo test --package pih-pah-app --lib --features "dev, ui_egui" -- controls::test::compare_player_inputs_get_and_get_many --exact --nocapture +// /// ``` +// #[test] +// fn compare_player_inputs_get_and_get_many() { +// let get = player_inputs_get(); +// let get_many = player_inputs_get_many(); + +// log::info!("get: {:?}", get); +// log::info!("get_many: {:?}", get_many); +// } + +// /// Test for execution speed for [`InputValue`] casting +// #[test] +// fn action_casting() { +// enable_loggings(); + +// let inputs = PlayerInputs::default(); + +// let duration = measure_time( +// || { +// let _ = (inputs.get(Action::LeverEditorForward).as_boolean() as i8 +// - inputs.get(Action::LevelEditorBackward).as_boolean() as i8) +// as f32; +// }, +// 10000000.into(), +// ); + +// log::info!("with casting: {:?}", duration); + +// let inputs = PlayerInputs::default(); + +// let duration = measure_time( +// || { +// let _ = inputs.get(Action::LeverEditorForward); +// let _ = inputs.get(Action::LevelEditorBackward); +// }, +// 10000000.into(), +// ); + +// log::info!("without casting: {:?}", duration); +// } +// } diff --git a/crate/bevy_controls/src/resource.rs b/crate/bevy_controls/src/resource.rs index 1215dad..434f660 100644 --- a/crate/bevy_controls/src/resource.rs +++ b/crate/bevy_controls/src/resource.rs @@ -10,32 +10,35 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; use bevy_utils::HashMap; use log::warn; #[cfg(feature = "serialize")] -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use std::mem::discriminant; use strum::IntoEnumIterator; #[cfg(feature = "reflect")] use {bevy_ecs::prelude::ReflectResource, bevy_reflect::Reflect}; -use crate::{common_traits_conditions, contract::{Action, GameState}}; +use crate::{ + common_traits_conditions, + contract::{Action, GameState}, +}; /// Validate that all enum variants are in the hash map pub fn validate_hash_map(hash_map: &HashMap) -> bool where - K: Eq + std::hash::Hash + Copy + IntoEnumIterator, - K::Iterator: Iterator, + K: Eq + std::hash::Hash + Copy + IntoEnumIterator, + K::Iterator: Iterator, { - let all_keys = K::iter().collect::>(); - if hash_map.len() != all_keys.len() { - return false; - } + let all_keys = K::iter().collect::>(); + if hash_map.len() != all_keys.len() { + return false; + } - for key in all_keys { - if !hash_map.contains_key(&key) { - return false; - } + for key in all_keys { + if !hash_map.contains_key(&key) { + return false; } + } - true + true } common_traits_conditions! { @@ -54,143 +57,143 @@ common_traits_conditions! { } impl Default for PlayerInputs { - fn default() -> Self { - PlayerInputs { - current: Inputs( - A::iter() - .map(|action| (action, InputValue::Empty)) - .collect(), - ), - previous: Inputs( - A::iter() - .map(|action| (action, InputValue::Empty)) - .collect(), - ), - } + fn default() -> Self { + PlayerInputs { + current: Inputs( + A::iter() + .map(|action| (action, InputValue::Empty)) + .collect(), + ), + previous: Inputs( + A::iter() + .map(|action| (action, InputValue::Empty)) + .collect(), + ), } + } } impl PlayerInputs { - /// Returns current input value for action - /// - /// in any case faster that `get_many` method - pub fn get(&self, action: A) -> InputValue { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - *self.current.get(&action).unwrap() + /// Returns current input value for action + /// + /// in any case faster that `get_many` method + pub fn get(&self, action: A) -> InputValue { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + *self.current.get(&action).unwrap() + } + + // TODO + // /// Returns current input value for action + // /// + // /// in any case faster that `get_many` method + // pub fn all_active(&self) -> InputValue { + // *self.current.iter().filter(|a| {a.}) + // } + + /// Returns current input values for actions + pub fn get_many(&self, actions: Vec) -> Vec { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + actions + .iter() + .map(|action| *self.current.get(action).unwrap()) + .collect() + } + + /// Returns `true` if current `InputValue` has become `InputValue::Boolean(true)` in this frame + /// If input has not same type as `InputValue` on previous frame call `panic` + pub fn just_pressed(&self, action: A) -> bool { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + if let InputValue::Boolean(current) = *self.current.get(&action).unwrap() { + if let InputValue::Boolean(previous) = *self.previous.get(&action).unwrap() { + return current && !previous; + } + panic!("Previous input is not boolean"); } + panic!("This input is not boolean") + } - // TODO - // /// Returns current input value for action - // /// - // /// in any case faster that `get_many` method - // pub fn all_active(&self) -> InputValue { - // *self.current.iter().filter(|a| {a.}) - // } - - /// Returns current input values for actions - pub fn get_many(&self, actions: Vec) -> Vec { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - actions - .iter() - .map(|action| *self.current.get(action).unwrap()) - .collect() + // 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> { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + if let InputValue::Boolean(current) = *self.current.get(&action).unwrap() { + if let InputValue::Boolean(previous) = *self.previous.get(&action).unwrap() { + return Ok(current && !previous); + } + return Err("Previous input is not boolean".into()); } + Err("This input is not boolean".into()) + } - /// Returns `true` if current `InputValue` has become `InputValue::Boolean(true)` in this frame - /// If input has not same type as `InputValue` on previous frame call `panic` - pub fn just_pressed(&self, action: A) -> bool { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - if let InputValue::Boolean(current) = *self.current.get(&action).unwrap() { - if let InputValue::Boolean(previous) = *self.previous.get(&action).unwrap() { - return current && !previous; - } - panic!("Previous input is not boolean"); - } - panic!("This input is not boolean") + /// Set input value to new + /// + /// notice: not recomended to use if you do not know what do you do + pub fn forced_set(&mut self, action: A, value: impl Into) { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + let current_input = self.current.get_mut(&action).unwrap(); + *self.previous.get_mut(&action).unwrap() = *current_input; + *current_input = value.into(); + } + + /// Set input value to new + /// if it is not the same InputValue type return `Error()` + /// + /// notice: not recomended to use if you do not know what do you do + pub fn set( + &mut self, + action: A, + value: impl Into, + ) -> Result<(), Box> { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + let current_input = self.current.get_mut(&action).unwrap(); + let previos_input = self.previous.get_mut(&action).unwrap(); + + // check if enum type is the same ignoring value + if discriminant(current_input) == discriminant(previos_input) { + *previos_input = *current_input; + *current_input = value.into(); + Ok(()) + } else { + Err("Input type is not the same".into()) } + } - // 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> { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - if let InputValue::Boolean(current) = *self.current.get(&action).unwrap() { - if let InputValue::Boolean(previous) = *self.previous.get(&action).unwrap() { - return Ok(current && !previous); - } - return Err("Previous input is not boolean".into()); - } - Err("This input is not boolean".into()) - } - - /// Set input value to new - /// - /// notice: not recomended to use if you do not know what do you do - pub fn forced_set(&mut self, action: A, value: impl Into) { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - let current_input = self.current.get_mut(&action).unwrap(); - *self.previous.get_mut(&action).unwrap() = *current_input; - *current_input = value.into(); - } - - /// Set input value to new - /// if it is not the same InputValue type return `Error()` - /// - /// notice: not recomended to use if you do not know what do you do - pub fn set( - &mut self, - action: A, - value: impl Into, - ) -> Result<(), Box> { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - let current_input = self.current.get_mut(&action).unwrap(); - let previos_input = self.previous.get_mut(&action).unwrap(); - - // check if enum type is the same ignoring value - if discriminant(current_input) == discriminant(previos_input) { - *previos_input = *current_input; - *current_input = value.into(); - Ok(()) - } else { - Err("Input type is not the same".into()) - } - } - - /// Update current inputs - /// - /// notice: not recomended to use if you do not know what do you do - pub fn forced_update(&mut self, inputs: Inputs) { - *self.previous = self.current.clone().0; - *self.current = inputs.0; - } - - /// Update current inputs - /// if any input is not the same InputValue type return `Error()` - /// ! remember that it work safely but slow - /// - /// notice: not recomended to use if you do not know what do you do - pub fn update(&mut self, inputs: Inputs) -> Result<(), Box> { - // SAFETY: action is always valid - // because we iterate over all actions in `default` method - for (action, value) in inputs.0.iter() { - let current_input = self.current.get_mut(action).unwrap(); - let previos_input = self.previous.get_mut(action).unwrap(); - - // check if enum type is not the same ignoring value - if discriminant(current_input) != discriminant(previos_input) { - return Err("Input type is not the same".into()); - } - *previos_input = *current_input; - *current_input = *value; - } - Ok(()) + /// Update current inputs + /// + /// notice: not recomended to use if you do not know what do you do + pub fn forced_update(&mut self, inputs: Inputs) { + *self.previous = self.current.clone().0; + *self.current = inputs.0; + } + + /// Update current inputs + /// if any input is not the same InputValue type return `Error()` + /// ! remember that it work safely but slow + /// + /// notice: not recomended to use if you do not know what do you do + pub fn update(&mut self, inputs: Inputs) -> Result<(), Box> { + // SAFETY: action is always valid + // because we iterate over all actions in `default` method + for (action, value) in inputs.0.iter() { + let current_input = self.current.get_mut(action).unwrap(); + let previos_input = self.previous.get_mut(action).unwrap(); + + // check if enum type is not the same ignoring value + if discriminant(current_input) != discriminant(previos_input) { + return Err("Input type is not the same".into()); + } + *previos_input = *current_input; + *current_input = *value; } + Ok(()) + } } common_traits_conditions! { @@ -251,28 +254,28 @@ common_traits_conditions! { } impl Default for ActivationOptions { - fn default() -> Self { - Self { - mode: ActivationMode::Tap, // Because it is more safe - option: OptionsMode::Immutable, - delay: 0.05, // 20 times per second; 14 - world record? - } + fn default() -> Self { + Self { + mode: ActivationMode::Tap, // Because it is more safe + option: OptionsMode::Immutable, + delay: 0.05, // 20 times per second; 14 - world record? } + } } impl ActivationOptions { - pub fn new(mode: ActivationMode, option: OptionsMode) -> Self { - Self { - mode, - option, - ..Default::default() - } + pub fn new(mode: ActivationMode, option: OptionsMode) -> Self { + Self { + mode, + option, + ..Default::default() } + } - pub fn with_delay(mut self, delay: f32) -> Self { - self.delay = delay; - self - } + pub fn with_delay(mut self, delay: f32) -> Self { + self.delay = delay; + self + } } common_traits_conditions! { @@ -303,26 +306,26 @@ common_traits_conditions! { } impl From for Binding { - fn from(input: ButtonCombination) -> Self { - Binding { - input, - conditions: Vec::new(), - } + fn from(input: ButtonCombination) -> Self { + Binding { + input, + conditions: Vec::new(), } + } } impl Binding { - pub fn new(input: ButtonCombination) -> Self { - Self { - input, - conditions: Vec::new(), - } + pub fn new(input: ButtonCombination) -> Self { + Self { + input, + conditions: Vec::new(), } + } - pub fn with_condition(mut self, condition: BindingCondition) -> Self { - self.conditions.push(condition); - self - } + pub fn with_condition(mut self, condition: BindingCondition) -> Self { + self.conditions.push(condition); + self + } } common_traits_conditions! { @@ -337,55 +340,55 @@ common_traits_conditions! { } impl From for InputValue { - fn from(value: bool) -> Self { - InputValue::Boolean(value) - } + fn from(value: bool) -> Self { + InputValue::Boolean(value) + } } impl From for InputValue { - fn from(value: f32) -> Self { - InputValue::Float(value) - } + fn from(value: f32) -> Self { + InputValue::Float(value) + } } impl From for bool { - fn from(value: InputValue) -> Self { - match value { - InputValue::Boolean(value) => value, - _ => panic!("InputValue is not boolean"), - } + fn from(value: InputValue) -> Self { + match value { + InputValue::Boolean(value) => value, + _ => panic!("InputValue is not boolean"), } + } } impl From for f32 { - fn from(value: InputValue) -> Self { - match value { - InputValue::Float(value) => value, - _ => panic!("InputValue is not float"), - } + fn from(value: InputValue) -> Self { + match value { + InputValue::Float(value) => value, + _ => panic!("InputValue is not float"), } + } } impl InputValue { - pub fn is_empty(&self) -> bool { - matches!(self, InputValue::Empty) - } + pub fn is_empty(&self) -> bool { + matches!(self, InputValue::Empty) + } - pub fn is_boolean(&self) -> bool { - matches!(self, InputValue::Boolean(_)) - } + pub fn is_boolean(&self) -> bool { + matches!(self, InputValue::Boolean(_)) + } - pub fn is_float(&self) -> bool { - matches!(self, InputValue::Float(_)) - } + pub fn is_float(&self) -> bool { + matches!(self, InputValue::Float(_)) + } - pub fn to_boolean(&self) -> bool { - match self { - InputValue::Boolean(value) => *value, - InputValue::Float(value) => *value > 0.0, - InputValue::Empty => false, - } + pub fn to_boolean(&self) -> bool { + match self { + InputValue::Boolean(value) => *value, + InputValue::Float(value) => *value > 0.0, + InputValue::Empty => false, } + } } common_traits_conditions! { @@ -400,74 +403,74 @@ common_traits_conditions! { } impl Default for Bindings { - fn default() -> Self { - Self { - list: Vec::new(), - options: OptionsMode::Immutable, - } + fn default() -> Self { + Self { + list: Vec::new(), + options: OptionsMode::Immutable, } + } } impl Bindings { - pub fn new(bindings: Vec>, options: OptionsMode) -> Self { - Self { - list: bindings, - options, - } + pub fn new(bindings: Vec>, options: OptionsMode) -> Self { + Self { + list: bindings, + options, } + } - pub fn force_push(&mut self, binding: Binding) { - self.list.push(binding); - } + 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"); - return; - } - 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"); + return; } + self.list.push(binding); + } - pub fn clear(&mut self) { - if self.options == OptionsMode::Immutable { - warn!("You try to clear immutable bindings"); - return; - } - self.list.clear(); + pub fn clear(&mut self) { + if self.options == OptionsMode::Immutable { + warn!("You try to clear immutable bindings"); + return; } + self.list.clear(); + } - pub fn retain(&mut self, f: F) - where - F: FnMut(&Binding) -> bool, - { - if self.options == OptionsMode::Immutable { - warn!("You try to retain immutable bindings"); - return; - } - self.list.retain(f); + pub fn retain(&mut self, f: F) + where + F: FnMut(&Binding) -> bool, + { + if self.options == OptionsMode::Immutable { + warn!("You try to retain immutable bindings"); + return; } + self.list.retain(f); + } - pub fn iter(&self) -> impl Iterator> { - self.list.iter() - } + pub fn iter(&self) -> impl Iterator> { + self.list.iter() + } - pub fn iter_mut( - &mut self, - ) -> Result>, Box> { - if self.options == OptionsMode::Immutable { - warn!("You try to iterate over immutable bindings"); - return Err("You try to iterate over immutable bindings".into()); - } - Ok(self.list.iter_mut()) + pub fn iter_mut( + &mut self, + ) -> Result>, Box> { + if self.options == OptionsMode::Immutable { + warn!("You try to iterate over immutable bindings"); + return Err("You try to iterate over immutable bindings".into()); } + Ok(self.list.iter_mut()) + } - pub fn is_customizable(&self) -> bool { - self.options == OptionsMode::Customizable - } + pub fn is_customizable(&self) -> bool { + self.options == OptionsMode::Customizable + } - pub fn is_immutable(&self) -> bool { - self.options == OptionsMode::Immutable - } + pub fn is_immutable(&self) -> bool { + self.options == OptionsMode::Immutable + } } common_traits_conditions! { @@ -483,12 +486,12 @@ common_traits_conditions! { } impl BindingConfig { - pub fn new(bindings: Bindings, activation: ActivationOptions) -> Self { - Self { - bindings, - activation, - } + pub fn new(bindings: Bindings, activation: ActivationOptions) -> Self { + Self { + bindings, + activation, } + } } common_traits_conditions! { @@ -504,67 +507,70 @@ common_traits_conditions! { } impl Default for Controls { - fn default() -> Self { - // TODO: default must create empty controls or fill empty / default BindingConfig on any actions - let mut controls = HashMap::new(); + fn default() -> Self { + // TODO: default must create empty controls or fill empty / default BindingConfig on any actions + let mut controls = HashMap::new(); - for key in A::iter() { - controls.insert(key, BindingConfig::default()); - } - - // If you see this error, you may add new action in menu_actions - // or make sure that you have only one Menufor<'a> Action<'a> with the same name in the Menufor<'a> Action<'a>s - assert!(validate_hash_map(&controls)); - - Self(controls) + for key in A::iter() { + controls.insert(key, BindingConfig::default()); } + + // If you see this error, you may add new action in menu_actions + // or make sure that you have only one Menufor<'a> Action<'a> with the same name in the Menufor<'a> Action<'a>s + assert!(validate_hash_map(&controls)); + + Self(controls) + } } impl Controls { - /// Returns bindings for action - pub fn get(&self, action: A) -> Option<&BindingConfig> { - self.0.get(&action) - } + /// Returns bindings for action + pub fn get(&self, action: A) -> Option<&BindingConfig> { + 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); - } + /// 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 - // TODO: interface for [`ActivationOptions`] - self.0 - .entry(action) - .or_insert_with(BindingConfig::default) - .bindings - .push(binding); - } + /// Push new binding for action + pub fn 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 + .push(binding); + } - /// Remove all bindings for action - pub fn remove(&mut self, action: A) { - // TODO: warning if config is not exist yet - self.0 - .entry(action) - .or_insert_with(BindingConfig::default) - .bindings - .clear(); - } + /// Remove all bindings for action + pub fn remove(&mut self, action: A) { + // TODO: warning if config is not exist yet + self + .0 + .entry(action) + .or_insert_with(BindingConfig::default) + .bindings + .clear(); + } - pub fn remove_binding(&mut self, action: A, binding: Binding) { - if let Some(config) = self.0.get_mut(&action) { - config.bindings.retain(|b| *b == binding); - } + pub fn remove_binding(&mut self, action: A, binding: Binding) { + if let Some(config) = self.0.get_mut(&action) { + config.bindings.retain(|b| *b == binding); } + } - pub fn iter(&self) -> impl Iterator)> { - self.0.iter() - } + pub fn iter(&self) -> impl Iterator)> { + self.0.iter() + } } diff --git a/crate/bevy_controls/src/util.rs b/crate/bevy_controls/src/util.rs index eddacfb..dbd79c1 100644 --- a/crate/bevy_controls/src/util.rs +++ b/crate/bevy_controls/src/util.rs @@ -75,105 +75,105 @@ macro_rules! common_traits_conditions { #[cfg(test)] pub mod test { - use std::time::{Duration, Instant}; + use std::time::{Duration, Instant}; - use bevy_derive::{Deref, DerefMut}; - use log::Level; + use bevy_derive::{Deref, DerefMut}; + use log::Level; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, DerefMut)] - pub struct Times(u64); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, DerefMut)] + pub struct Times(u64); - impl Into for Times { - fn into(self) -> u64 { - self.0 - } + impl Into for Times { + fn into(self) -> u64 { + self.0 } + } - impl Into for Times { - fn into(self) -> usize { - self.0 as usize - } + impl Into for Times { + fn into(self) -> usize { + self.0 as usize } + } - impl Into for Times { - fn into(self) -> u32 { - self.0 as u32 - } + impl Into for Times { + fn into(self) -> u32 { + self.0 as u32 } + } - impl Into for Times { - fn into(self) -> i32 { - self.0 as i32 - } + impl Into for Times { + fn into(self) -> i32 { + self.0 as i32 } + } - impl From for Times { - fn from(times: u64) -> Self { - Self(times) - } + impl From for Times { + fn from(times: u64) -> Self { + Self(times) } + } - impl From for Times { - fn from(times: usize) -> Self { - Self(times as u64) - } + impl From for Times { + fn from(times: usize) -> Self { + Self(times as u64) } + } - impl From for Times { - fn from(times: u32) -> Self { - Self(times as u64) - } + impl From for Times { + fn from(times: u32) -> Self { + Self(times as u64) } + } - impl From for Times { - fn from(times: i32) -> Self { - Self(times as u64) - } + impl From for Times { + fn from(times: i32) -> Self { + Self(times as u64) } + } - impl Default for Times { - /// Value that may be enough for most cases - fn default() -> Self { - Self(100000) - } + impl Default for Times { + /// Value that may be enough for most cases + fn default() -> Self { + Self(100000) } + } - /// Enable logging for debug - pub fn enable_loggings() { - use std::env; - use std::io::Write; + /// Enable logging for debug + pub fn enable_loggings() { + use std::env; + use std::io::Write; - let _ = env::set_var("RUST_LOG", "debug"); - // FIXME: colorize logs - // TODO: colorize thorwed args - let _ = env_logger::builder() - .is_test(true) - .format(|buf, record| { - let mut style = buf.style(); - let level = record.level(); - match level { - Level::Trace => style.set_color(env_logger::fmt::Color::Magenta), - Level::Debug => style.set_color(env_logger::fmt::Color::Blue), - Level::Info => style.set_color(env_logger::fmt::Color::Green), - Level::Warn => style.set_color(env_logger::fmt::Color::Yellow), - Level::Error => style.set_color(env_logger::fmt::Color::Red), - }; + let _ = env::set_var("RUST_LOG", "debug"); + // FIXME: colorize logs + // TODO: colorize thorwed args + let _ = env_logger::builder() + .is_test(true) + .format(|buf, record| { + let mut style = buf.style(); + let level = record.level(); + match level { + Level::Trace => style.set_color(env_logger::fmt::Color::Magenta), + Level::Debug => style.set_color(env_logger::fmt::Color::Blue), + Level::Info => style.set_color(env_logger::fmt::Color::Green), + Level::Warn => style.set_color(env_logger::fmt::Color::Yellow), + Level::Error => style.set_color(env_logger::fmt::Color::Red), + }; - writeln!(buf, "{}: {}", style.value(level), record.args()) - }) - .try_init(); - } - - /// Measure time of predicate - pub fn measure_time(predicate: F, times: Times) -> Duration - where - F: FnOnce() -> (), - { - let start = Instant::now(); - for _ in 0..times.clone().into() { - predicate(); - } - let global_duration = start.elapsed(); - global_duration / times.into() + writeln!(buf, "{}: {}", style.value(level), record.args()) + }) + .try_init(); + } + + /// Measure time of predicate + pub fn measure_time(predicate: F, times: Times) -> Duration + where + F: FnOnce() -> (), + { + let start = Instant::now(); + for _ in 0..times.clone().into() { + predicate(); } + let global_duration = start.elapsed(); + global_duration / times.into() + } } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..b196eaa --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +tab_spaces = 2