refactor: hardcoded proc macro for GameState supertraits
This commit is contained in:
Generated
+10
@@ -448,6 +448,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy-inspector-egui",
|
"bevy-inspector-egui",
|
||||||
"bevy_app",
|
"bevy_app",
|
||||||
|
"bevy_controls_macros",
|
||||||
"bevy_derive",
|
"bevy_derive",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"bevy_input",
|
"bevy_input",
|
||||||
@@ -470,6 +471,15 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_controls_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_core"
|
name = "bevy_core"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ log = "0.4.20"
|
|||||||
serde = { version = "1.0.194", optional = true }
|
serde = { version = "1.0.194", optional = true }
|
||||||
strum = "0.25.0"
|
strum = "0.25.0"
|
||||||
strum_macros = "0.25.3"
|
strum_macros = "0.25.3"
|
||||||
|
bevy_controls_macros = { path = "macros", version = "0.1.0" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.10.1"
|
env_logger = "0.10.1"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "bevy_controls_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
#bevy_controls = { path = "./../bevy_controls" }
|
||||||
|
syn = { version = "1.0", features = [ "full", "extra-traits" ] }
|
||||||
|
quote = "1.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
env_logger = "0.10.1"
|
||||||
|
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
//use quote::quote;
|
||||||
|
use syn::{
|
||||||
|
parse::{Parse, ParseStream, Result},
|
||||||
|
parse_macro_input,
|
||||||
|
punctuated::Punctuated,
|
||||||
|
token::{Bracket, Add},
|
||||||
|
Expr, Ident, ItemTrait, Token, TypeParamBound, LitStr,
|
||||||
|
};
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
// #[cfg_feature_trait_bounds {
|
||||||
|
// "serialize" => Serialize + DeserializeOwned,
|
||||||
|
// "reflect" => Reflect + TypePath + FromReflect,
|
||||||
|
// "inspector-egui" => InspectorOptionsType,
|
||||||
|
// }]
|
||||||
|
|
||||||
|
type RuleKey = LitStr;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct FeatureTraitBoundMap(HashMap<RuleKey, Punctuated<TypeParamBound, Token![+]>>);
|
||||||
|
|
||||||
|
impl Parse for FeatureTraitBoundMap {
|
||||||
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
|
let mut rules = HashMap::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let condition: RuleKey = input.parse()?;
|
||||||
|
|
||||||
|
let _arrow = input.parse::<Token![=>]>()?;
|
||||||
|
|
||||||
|
let supertraits = {
|
||||||
|
let mut supertraits = Punctuated::new();
|
||||||
|
loop {
|
||||||
|
supertraits.push_value(input.parse()?);
|
||||||
|
if !input.peek(Token![+]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
supertraits.push_punct(input.parse()?);
|
||||||
|
|
||||||
|
if input.peek(Token![,]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
supertraits
|
||||||
|
};
|
||||||
|
let _comma = input.parse::<Token![,]>();
|
||||||
|
|
||||||
|
rules.insert(condition, supertraits);
|
||||||
|
|
||||||
|
if input.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(FeatureTraitBoundMap(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn cfg_feature_trait_bounds(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let rules = parse_macro_input!(attr as FeatureTraitBoundMap);
|
||||||
|
let input = parse_macro_input!(input as ItemTrait);
|
||||||
|
|
||||||
|
dbg!(std::env::vars().map(|(key, _)| key).collect::<Vec<_>>());
|
||||||
|
|
||||||
|
|
||||||
|
// let code = quote! {
|
||||||
|
// trait #name: #rules {}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// dbg!(code);
|
||||||
|
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn game_state_supertraits(_attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as ItemTrait);
|
||||||
|
|
||||||
|
let mut bounds = Vec::new();
|
||||||
|
if cfg!(feature = "serialize") {
|
||||||
|
bounds.push(quote! { serde::Serialize });
|
||||||
|
bounds.push(quote! { serde::de::DeserializeOwned });
|
||||||
|
};
|
||||||
|
if cfg!(feature = "reflect") {
|
||||||
|
bounds.push(quote! { bevy_reflect::Reflect });
|
||||||
|
bounds.push(quote! { bevy_reflect::TypePath });
|
||||||
|
bounds.push(quote! { bevy_reflect::FromReflect });
|
||||||
|
};
|
||||||
|
if cfg!(feature = "inspector-egui") {
|
||||||
|
bounds.push(quote! { bevy_inspector_egui::inspector_options::InspectorOptionsType });
|
||||||
|
};
|
||||||
|
|
||||||
|
let ItemTrait {
|
||||||
|
ident,
|
||||||
|
vis,
|
||||||
|
items,
|
||||||
|
supertraits: bounds_old,
|
||||||
|
..
|
||||||
|
} = input;
|
||||||
|
|
||||||
|
let bounds_old = bounds_old.iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let out = quote! {
|
||||||
|
#vis trait #ident: #(#bounds_old)+* + #(#bounds)+* { #(#items)* }
|
||||||
|
};
|
||||||
|
|
||||||
|
// dbg!(&out);
|
||||||
|
// dbg!(out.to_string());
|
||||||
|
|
||||||
|
TokenStream::from(out)
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ use strum::IntoEnumIterator;
|
|||||||
use bevy_reflect::{FromReflect, Reflect, TypePath};
|
use bevy_reflect::{FromReflect, Reflect, TypePath};
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
use bevy_controls_macros::{cfg_feature_trait_bounds, game_state_supertraits};
|
||||||
|
|
||||||
use crate::resource::PlayerInputs;
|
use crate::resource::PlayerInputs;
|
||||||
|
|
||||||
@@ -27,11 +28,6 @@ pub trait ActionInner:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GameStateInner:
|
|
||||||
'static + std::marker::Sync + std::marker::Send + States + Default + std::fmt::Debug
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait InputsContainerInner<A: Action>:
|
pub trait InputsContainerInner<A: Action>:
|
||||||
'static + std::marker::Sync + std::marker::Send + Resource + Default + std::fmt::Debug
|
'static + std::marker::Sync + std::marker::Send + Resource + Default + std::fmt::Debug
|
||||||
{
|
{
|
||||||
@@ -91,39 +87,16 @@ pub trait Action: ActionInner + SerializeImpl + ReflectImpl + InspectorEguiImpl
|
|||||||
|
|
||||||
// ===== GameState =====
|
// ===== GameState =====
|
||||||
// SAFETY: inspector-egui includes reflect
|
// SAFETY: inspector-egui includes reflect
|
||||||
#[cfg(all(
|
#[game_state_supertraits]
|
||||||
not(feature = "serialize"),
|
pub trait GameState:
|
||||||
not(feature = "reflect"),
|
'static
|
||||||
not(feature = "inspector-egui")
|
+ std::marker::Sync
|
||||||
))]
|
+ std::marker::Send
|
||||||
pub trait GameState: GameStateInner {}
|
+ States
|
||||||
|
+ Default
|
||||||
#[cfg(all(
|
+ std::fmt::Debug
|
||||||
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 =====
|
// ===== InputsContainer =====
|
||||||
// SAFETY: inspector-egui includes reflect
|
// SAFETY: inspector-egui includes reflect
|
||||||
|
|||||||
@@ -6,24 +6,7 @@ edition = "2021"
|
|||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
# [features]
|
|
||||||
# default = []
|
|
||||||
# serialize = ["bevy_input/serialize", "serde"]
|
|
||||||
# reflect = ["dep:bevy_reflect"]
|
|
||||||
# inspector-egui = ["reflect", "dep:bevy-inspector-egui"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy-inspector-egui = { version = "0.22.1", optional = true }
|
|
||||||
# bevy_app = "0.12.1"
|
|
||||||
# bevy_derive = "0.12.1"
|
|
||||||
# bevy_ecs = "0.12.1"
|
|
||||||
# bevy_input = "0.12.1"
|
|
||||||
# bevy_reflect = { version = "0.12.1", optional = true }
|
|
||||||
# bevy_utils = "0.12.1"
|
|
||||||
# log = "0.4.20"
|
|
||||||
# serde = { version = "1.0.194", optional = true }
|
|
||||||
# strum = "0.25.0"
|
|
||||||
# strum_macros = "0.25.3"
|
|
||||||
bevy_controls = { path = "./../bevy_controls" }
|
bevy_controls = { path = "./../bevy_controls" }
|
||||||
syn = "1.0"
|
syn = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user