feat!: serialize feature without errors now

This commit is contained in:
2024-01-11 05:02:53 +01:00
parent 987dccaf76
commit 2f7bb64147
2 changed files with 148 additions and 86 deletions
+135 -80
View File
@@ -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 {}
// }
+13 -6
View File
@@ -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