feat!: serialize feature without errors now
This commit is contained in:
@@ -1,13 +1,77 @@
|
||||
use std::hash::Hash;
|
||||
|
||||
use bevy_ecs::{system::Resource, schedule::States};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::de;
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
#[cfg(feature = "inspector-egui")]
|
||||
use bevy_inspector_egui::prelude::*;
|
||||
#[cfg(all(feature = "reflect", feature = "serialize"))]
|
||||
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Deserialize, de::DeserializeOwned};
|
||||
#[cfg(feature = "reflect")]
|
||||
use {bevy_ecs::prelude::ReflectResource, bevy_reflect::Reflect};
|
||||
|
||||
use crate::resource::PlayerInputs;
|
||||
|
||||
pub trait InputsContainer<A: Action>: 'static + std::marker::Sync + std::marker::Send + Resource {
|
||||
macro_rules! define_common_trait {
|
||||
($trait_name:ident, $trait_inner:ident) => {
|
||||
#[cfg(all(not(feature = "serialize"), not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name: $trait_inner {}
|
||||
|
||||
#[cfg(all(feature = "serialize", not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name: $trait_inner + Serialize + DeserializeOwned {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), feature = "reflect", not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name: $trait_inner + bevy_reflect::Reflect {}
|
||||
|
||||
#[cfg(all(feature = "serialize", feature = "reflect", not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name: $trait_inner + bevy_reflect::Reflect + Serialize + DeserializeOwned {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), not(feature = "reflect"), feature = "inspector-egui"))]
|
||||
pub trait $trait_name: $trait_inner + bevy_inspector_egui::Inspectable + InspectorOptions {}
|
||||
|
||||
#[cfg(all(feature = "serialize", not(feature = "reflect"), feature = "inspector-egui"))]
|
||||
pub trait $trait_name: $trait_inner + bevy_inspector_egui::Inspectable + Serialize + DeserializeOwned + InspectorOptions {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), feature = "reflect", feature = "inspector-egui"))]
|
||||
pub trait $trait_name: $trait_inner + bevy_inspector_egui::Inspectable + bevy_reflect::Reflect + InspectorOptions {}
|
||||
|
||||
#[cfg(all(feature = "serialize", feature = "reflect", feature = "inspector-egui"))]
|
||||
pub trait $trait_name: $trait_inner + bevy_inspector_egui::Inspectable + bevy_reflect::Reflect + Serialize + DeserializeOwned + InspectorOptions {}
|
||||
};
|
||||
($trait_name:ident<$generic:ident : $bound:path>, $trait_inner:ident<$trait_inner_generic:ident>) => {
|
||||
#[cfg(all(not(feature = "serialize"), not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> {}
|
||||
|
||||
#[cfg(all(feature = "serialize", not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + Serialize + DeserializeOwned {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), feature = "reflect", not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_reflect::Reflect {}
|
||||
|
||||
#[cfg(all(feature = "serialize", feature = "reflect", not(feature = "inspector-egui")))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_reflect::Reflect + Serialize + DeserializeOwned {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), not(feature = "reflect"), feature = "inspector-egui"))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_inspector_egui::Inspectable + InspectorOptions {}
|
||||
|
||||
#[cfg(all(feature = "serialize", not(feature = "reflect"), feature = "inspector-egui"))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_inspector_egui::Inspectable + Serialize + DeserializeOwned + InspectorOptions {}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), feature = "reflect", feature = "inspector-egui"))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_inspector_egui::Inspectable + bevy_reflect::Reflect + InspectorOptions {}
|
||||
|
||||
#[cfg(all(feature = "serialize", feature = "reflect", feature = "inspector-egui"))]
|
||||
pub trait $trait_name<$generic: $bound>: $trait_inner<$trait_inner_generic> + bevy_inspector_egui::Inspectable + bevy_reflect::Reflect + Serialize + DeserializeOwned + InspectorOptions {}
|
||||
};
|
||||
}
|
||||
pub trait ActionInner: 'static + std::marker::Sync + std::marker::Send + PartialEq + Eq + Hash + IntoEnumIterator + Clone + Copy { }
|
||||
|
||||
pub trait GameStateInner: 'static + std::marker::Sync + std::marker::Send + States { }
|
||||
|
||||
pub trait InputsContainerInner<A: Action>: 'static + std::marker::Sync + std::marker::Send + Resource {
|
||||
/// 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<dyn Iterator<Item = &'a PlayerInputs<A>> + 'a>;
|
||||
@@ -17,93 +81,84 @@ pub trait InputsContainer<A: Action>: 'static + std::marker::Sync + std::marker:
|
||||
fn me_mut<'a>(&self) -> Option<&'a mut PlayerInputs<A>>;
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait Action: 'static + std::marker::Sync + std::marker::Send + PartialEq + Eq + Hash + IntoEnumIterator + Clone + Copy { }
|
||||
|
||||
#[cfg(all(feature = "serialize", not(feature = "reflect"), not(feature = "inspector-egui")))]
|
||||
pub trait Action<'a>: 'static + std::marker::Sync + std::marker::Send + PartialEq + Eq + Hash + IntoEnumIterator + Clone + Copy + Serialize + Deserialize<'a> { }
|
||||
|
||||
#[cfg(all(not(feature = "serialize"), feature = "reflect", not(feature = "inspector-egui")))]
|
||||
pub trait Action: 'static + std::marker::Sync + std::marker::Send + PartialEq + Eq + Hash + IntoEnumIterator + Clone + Copy + Serialize + Deserialize + Reflect { }
|
||||
define_common_trait!(Action, ActionInner);
|
||||
define_common_trait!(GameState, GameStateInner);
|
||||
define_common_trait!(InputsContainer<A: Action>, InputsContainerInner<A>);
|
||||
|
||||
|
||||
pub trait GameState: 'static + std::marker::Sync + std::marker::Send + States {
|
||||
// #[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};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use bevy_ecs::{entity::Entity, schedule::States};
|
||||
use bevy_utils::{HashMap, prelude::default};
|
||||
use strum_macros::EnumIter;
|
||||
// use crate::{hashmap, resource::PlayerInputs, common_traits_conditions};
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
// common_traits_conditions! {
|
||||
// #[derive(Debug, Clone, PartialEq)]
|
||||
// #[cfg_attr(feature = "reflect", reflect(Resource))]
|
||||
// pub struct Lobby {
|
||||
// pub me: PlayerId,
|
||||
// pub players: HashMap<PlayerId, Player>,
|
||||
// }
|
||||
// }
|
||||
|
||||
use crate::{hashmap, resource::PlayerInputs, common_traits_conditions};
|
||||
// impl Default for Lobby {
|
||||
// fn default() -> Self {
|
||||
// Self {
|
||||
// me: PlayerId::Host,
|
||||
// players: hashmap! {
|
||||
// PlayerId::Host => Player::default()
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
common_traits_conditions! {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "reflect", reflect(Resource))]
|
||||
pub struct Lobby {
|
||||
pub me: PlayerId,
|
||||
pub players: HashMap<PlayerId, Player>,
|
||||
}
|
||||
}
|
||||
// common_traits_conditions! {
|
||||
// #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
// pub enum PlayerId {
|
||||
// /// Host or alone
|
||||
// Host,
|
||||
// /// Client
|
||||
// Client(()),
|
||||
// }
|
||||
|
||||
impl Default for Lobby {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
me: PlayerId::Host,
|
||||
players: hashmap! {
|
||||
PlayerId::Host => Player::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
// #[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<Action>,
|
||||
// #[cfg_attr(feature = "serialize", serde(skip))]
|
||||
// pub entity: Option<Entity>,
|
||||
// }
|
||||
// }
|
||||
|
||||
common_traits_conditions! {
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum PlayerId {
|
||||
/// Host or alone
|
||||
Host,
|
||||
/// Client
|
||||
Client(()),
|
||||
}
|
||||
// #[derive(Debug, PartialEq, Clone, States, Default, Hash, Eq)]
|
||||
// pub enum GameState {
|
||||
// #[default]
|
||||
// LevelEditor,
|
||||
// InGame,
|
||||
// }
|
||||
|
||||
#[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<Action>,
|
||||
#[cfg_attr(feature = "serialize", serde(skip))]
|
||||
pub entity: Option<Entity>,
|
||||
}
|
||||
}
|
||||
// impl super::GameState for GameState {}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, States, Default, Hash, Eq)]
|
||||
pub enum GameState {
|
||||
#[default]
|
||||
LevelEditor,
|
||||
InGame,
|
||||
}
|
||||
// // 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::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 {}
|
||||
}
|
||||
// impl super::Action for Action {}
|
||||
// }
|
||||
|
||||
@@ -10,7 +10,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_utils::HashMap;
|
||||
use log::warn;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, de::DeserializeOwned, Serialize};
|
||||
use std::mem::discriminant;
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
@@ -39,15 +39,18 @@ where
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
common_traits_conditions! {
|
||||
/// Struct that contains user's inputs corresponding to actions
|
||||
#[derive(Debug, PartialEq, Clone, Deref, DerefMut)]
|
||||
pub struct Inputs<A: Action>(HashMap<A, InputValue>);
|
||||
pub struct Inputs<A: Action>(#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))] HashMap<A, InputValue>);
|
||||
|
||||
/// Resource that contains current user inputs
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct PlayerInputs<A: Action> {
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
current: Inputs<A>,
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
previous: Inputs<A>,
|
||||
}
|
||||
}
|
||||
@@ -212,9 +215,9 @@ common_traits_conditions! {
|
||||
/// Represents the manner in which input is registered
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum ActivationMode {
|
||||
/// Action is triggered when the button is pressed
|
||||
/// for<'a> Action<'a> is triggered when the button is pressed
|
||||
Hold,
|
||||
/// Action is triggered when the button is pressed
|
||||
/// for<'a> Action<'a> is triggered when the button is pressed
|
||||
/// and cannot be triggered again until the button is released
|
||||
/// you don't need to release all buttons in chord
|
||||
/// you can release only last pressed button
|
||||
@@ -269,6 +272,7 @@ common_traits_conditions! {
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum BindingCondition<Gs: GameState> {
|
||||
/// During specific game state
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
InGameState(Gs),
|
||||
/// Binding is active only if player is in pause menu
|
||||
DuringPauseMenu(bool),
|
||||
@@ -280,6 +284,7 @@ common_traits_conditions! {
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Binding<Gs: GameState> {
|
||||
pub input: ButtonCombination,
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
pub conditions: Vec<BindingCondition<Gs>>,
|
||||
}
|
||||
}
|
||||
@@ -373,6 +378,7 @@ impl InputValue {
|
||||
common_traits_conditions! {
|
||||
pub struct Bindings<Gs: GameState> {
|
||||
/// List of bindings for action
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
list: Vec<Binding<Gs>>,
|
||||
/// Possibility to change this binding
|
||||
options: OptionsMode,
|
||||
@@ -451,6 +457,7 @@ common_traits_conditions! {
|
||||
/// and different activation options
|
||||
#[derive(Default)]
|
||||
pub struct BindingConfig<Gs: GameState> {
|
||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))]
|
||||
pub bindings: Bindings<Gs>,
|
||||
#[cfg_attr(feature = "serialize", serde(skip))]
|
||||
pub activation: ActivationOptions,
|
||||
@@ -471,7 +478,7 @@ common_traits_conditions! {
|
||||
#[derive(Resource)]
|
||||
#[cfg_attr(feature = "reflect", reflect(Resource))]
|
||||
// TODO: Add delay for input
|
||||
pub struct Controls<A: Action, Gs: GameState>(HashMap<A, BindingConfig<Gs>>); // TODO: change HashMap to Vec for faster iteration
|
||||
pub struct Controls<A: Action, Gs: GameState>(#[cfg_attr(feature = "serialize", serde(bound(deserialize = "")))] HashMap<A, BindingConfig<Gs>>); // TODO: change HashMap to Vec for faster iteration
|
||||
}
|
||||
|
||||
impl<A: Action, Gs: GameState> Default for Controls<A, Gs> {
|
||||
@@ -480,7 +487,7 @@ impl<A: Action, Gs: GameState> Default for Controls<A, Gs> {
|
||||
let controls = Self(HashMap::new());
|
||||
|
||||
// If you see this error, you may add new action in menu_actions
|
||||
// or make sure that you have only one MenuAction with the same name in the MenuActions
|
||||
// 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.0));
|
||||
|
||||
controls
|
||||
|
||||
Reference in New Issue
Block a user