Skip to content

Commit

Permalink
feat: Make relevant PrefabData impls use the derive
Browse files Browse the repository at this point in the history
  • Loading branch information
Rhuagh committed Oct 29, 2018
1 parent f8f9495 commit 6cc2aab
Show file tree
Hide file tree
Showing 18 changed files with 233 additions and 331 deletions.
2 changes: 1 addition & 1 deletion amethyst_animation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ travis-ci = { repository = "amethyst/amethyst" }
[dependencies]
amethyst_assets = { path = "../amethyst_assets/", version = "0.5.0" }
amethyst_core = { path = "../amethyst_core/", version = "0.4.0" }
amethyst_derive = { path = "../amethyst_derive", version = "0.1.0" }
amethyst_derive = { path = "../amethyst_derive", version = "0.2.0" }
amethyst_renderer = { path = "../amethyst_renderer/", version = "0.9.0" }
derivative = "1.0"
fnv = "1"
Expand Down
68 changes: 3 additions & 65 deletions amethyst_animation/src/prefab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,23 +181,6 @@ where
}
}

impl<'a, T> PrefabData<'a> for RestState<T>
where
T: AnimationSampling + Clone,
{
type SystemData = WriteStorage<'a, RestState<T>>;
type Result = ();

fn add_to_entity(
&self,
entity: Entity,
storage: &mut Self::SystemData,
_: &[Entity],
) -> Result<(), PrefabError> {
storage.insert(entity, self.clone()).map(|_| ())
}
}

/// `PrefabData` for loading `AnimationHierarchy`.
///
/// ### Type parameters
Expand Down Expand Up @@ -242,13 +225,14 @@ where
///
/// - `I`: Id type of `Animation`s in `AnimationSet`s
/// - `T`: The animatable `Component`
#[derive(Default, Clone, Debug, Deserialize, Serialize)]
#[derive(Default, Clone, Debug, Deserialize, Serialize, PrefabData)]
#[serde(default)]
pub struct AnimatablePrefab<I, T>
where
T: AnimationSampling,
T: AnimationSampling + Clone,
T::Channel: for<'a> Deserialize<'a> + Serialize,
T::Primitive: Debug + for<'a> Deserialize<'a> + Serialize,
I: Clone + Hash + Eq + Send + Sync + 'static,
{
/// Place an `AnimationSet` on the `Entity`
pub animation_set: Option<AnimationSetPrefab<I, T>>,
Expand All @@ -257,49 +241,3 @@ where
/// Place a `RestState` on the `Entity`
pub rest_state: Option<RestState<T>>,
}

// TODO: derive PrefabData for AnimatablePrefab, require generics support in derive macro
impl<'a, I, T> PrefabData<'a> for AnimatablePrefab<I, T>
where
T: AnimationSampling + Clone,
T::Channel: for<'b> Deserialize<'b> + Serialize,
T::Primitive: Debug + for<'b> Deserialize<'b> + Serialize,
I: Clone + Hash + Eq + Send + Sync + 'static,
{
type SystemData = (
<AnimationSetPrefab<I, T> as PrefabData<'a>>::SystemData,
<AnimationHierarchyPrefab<T> as PrefabData<'a>>::SystemData,
<RestState<T> as PrefabData<'a>>::SystemData,
);
type Result = ();

fn add_to_entity(
&self,
entity: Entity,
system_data: &mut <Self as PrefabData>::SystemData,
entities: &[Entity],
) -> Result<<Self as PrefabData>::Result, PrefabError> {
if let Some(ref prefab) = self.animation_set {
prefab.add_to_entity(entity, &mut system_data.0, entities)?;
}
if let Some(ref prefab) = self.hierarchy {
prefab.add_to_entity(entity, &mut system_data.1, entities)?;
}
if let Some(ref prefab) = self.rest_state {
prefab.add_to_entity(entity, &mut system_data.2, entities)?;
}
Ok(())
}

fn load_sub_assets(
&mut self,
progress: &mut ProgressCounter,
system_data: &mut Self::SystemData,
) -> Result<bool, PrefabError> {
if let Some(ref mut prefab) = self.animation_set {
prefab.load_sub_assets(progress, &mut system_data.0)
} else {
Ok(false)
}
}
}
21 changes: 15 additions & 6 deletions amethyst_animation/src/resources.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use amethyst_assets::{Asset, AssetStorage, Handle, ProcessingState, Result};
use amethyst_assets::{
Asset, AssetStorage, Handle, PrefabData, PrefabError, ProcessingState, Result,
};
use amethyst_core::shred::SystemData;
use amethyst_core::specs::prelude::{Component, DenseVecStorage, Entity, VecStorage, WriteStorage};
use amethyst_core::timing::{duration_to_secs, secs_to_duration};
Expand Down Expand Up @@ -107,12 +109,19 @@ where
}

/// Define the rest state for a component on an entity
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RestState<T> {
#[derive(Debug, Clone, Deserialize, Serialize, PrefabData)]
#[prefab(Component)]
pub struct RestState<T>
where
T: AnimationSampling + Clone,
{
state: T,
}

impl<T> RestState<T> {
impl<T> RestState<T>
where
T: AnimationSampling + Clone,
{
/// Create new rest state
pub fn new(t: T) -> Self {
RestState { state: t }
Expand All @@ -126,7 +135,7 @@ impl<T> RestState<T> {

impl<T> Component for RestState<T>
where
T: AnimationSampling,
T: AnimationSampling + Clone,
{
type Storage = DenseVecStorage<Self>;
}
Expand Down Expand Up @@ -179,7 +188,7 @@ where
/// entity in the hierarchy.
pub fn rest_state<F>(&self, get_component: F, states: &mut WriteStorage<RestState<T>>)
where
T: AnimationSampling,
T: AnimationSampling + Clone,
F: Fn(Entity) -> Option<T>,
{
for entity in self.nodes.values() {
Expand Down
2 changes: 1 addition & 1 deletion amethyst_assets/src/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::Deserialize;
use {Asset, SimpleFormat};

/// Format for loading from Ron files.
#[derive(Default, Clone, Debug)]
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct RonFormat;

impl<T> SimpleFormat<T> for RonFormat
Expand Down
4 changes: 2 additions & 2 deletions amethyst_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ quote = "0.6"
proc-macro2 = "0.4"

[dev-dependencies]
amethyst_core = { path = "../amethyst_core", version = "0.3.0" }
amethyst_assets = { path = "../amethyst_assets", version = "0.4.0" }
amethyst_core = { path = "../amethyst_core", version = "0.4.0" }
amethyst_assets = { path = "../amethyst_assets", version = "0.5.0" }

[lib]
name = "amethyst_derive"
Expand Down
133 changes: 70 additions & 63 deletions amethyst_derive/src/prefab_data.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,8 @@
use proc_macro2::TokenStream;
use syn::{Data, DeriveInput, Generics, Ident, Meta, NestedMeta, Type};
use syn::{Attribute, Data, DeriveInput, Generics, Ident, Meta, NestedMeta, Type};

pub fn impl_prefab_data(ast: &DeriveInput) -> TokenStream {
let mut component = false;
for meta in ast
.attrs
.iter()
.filter(|attr| attr.path.segments[0].ident == "prefab")
.map(|attr| {
attr.interpret_meta()
.expect("reader attribute incorrectly defined")
}) {
match meta {
Meta::List(l) => {
for nested_meta in l.nested.iter() {
match *nested_meta {
NestedMeta::Meta(Meta::Word(ref word)) => {
if word == "Component" {
component = true;
}
}
_ => panic!("reader attribute does not contain a single name"),
}
}
}
_ => (),
};
}

if component {
if have_component_attribute(&ast.attrs[..]) {
impl_prefab_data_component(ast)
} else {
impl_prefab_data_aggregate(ast)
Expand All @@ -49,7 +23,7 @@ fn impl_prefab_data_component(ast: &DeriveInput) -> TokenStream {
fn add_to_entity(&self,
entity: Entity,
system_data: &mut Self::SystemData,
_: &[Entity]) -> Result<(), PrefabError> {
_: &[Entity]) -> ::std::result::Result<(), PrefabError> {
system_data.insert(entity, self.clone()).map(|_| ())
}
}
Expand All @@ -58,34 +32,43 @@ fn impl_prefab_data_component(ast: &DeriveInput) -> TokenStream {

fn impl_prefab_data_aggregate(ast: &DeriveInput) -> TokenStream {
let base = &ast.ident;
let tys = collect_field_types(&ast.data);
let tys = &tys;
let names = collect_field_names(&ast.data);
let names = &names;

let system_datas: Vec<_> = (0..tys.len())
.map(|n| {
let ty = &tys[n];
let data = collect_field_data(&ast.data);

let system_datas = data.iter().map(|(ty, _, is_component)| {
if *is_component {
quote! {
WriteStorage<'pfd, #ty>
}
} else {
quote! {
<#ty as PrefabData<'pfd>>::SystemData
}
}).collect();
let adds: Vec<_> = (0..tys.len())
.map(|n| {
let name = &names[n];
}
});
let adds = (0..data.len()).map(|n| {
let (_, name, is_component) = &data[n];
if *is_component {
quote! {
self.#name.add_to_entity(entity, &mut system_data.#n, entities)?;
system_data.#n.insert(entity, self.#name.clone())?;
}
}).collect();
let subs: Vec<_> = (0..tys.len())
.map(|n| {
let name = &names[n];
} else {
quote! {
self.#name.add_to_entity(entity, &mut system_data.#n, entities)?;
}
}
});
let subs = (0..data.len()).filter_map(|n| {
let (_, name, is_component) = &data[n];
if *is_component {
None
} else {
Some(quote! {
if self.#name.load_sub_assets(progress, &mut system_data.#n)? {
ret = true;
}
}
}).collect();
})
}
});

let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
let lf_tokens = gen_def_lt_tokens(&ast.generics);
Expand All @@ -101,14 +84,14 @@ fn impl_prefab_data_aggregate(ast: &DeriveInput) -> TokenStream {
fn add_to_entity(&self,
entity: Entity,
system_data: &mut Self::SystemData,
entities: &[Entity]) -> Result<(), PrefabError> {
entities: &[Entity]) -> ::std::result::Result<(), PrefabError> {
#(#adds)*
Ok(())
}

fn load_sub_assets(&mut self,
progress: &mut ProgressCounter,
system_data: &mut Self::SystemData) -> Result<bool, PrefabError> {
system_data: &mut Self::SystemData) -> ::std::result::Result<bool, PrefabError> {
let mut ret = false;
#(#subs)*
Ok(ret)
Expand All @@ -117,25 +100,22 @@ fn impl_prefab_data_aggregate(ast: &DeriveInput) -> TokenStream {
}
}

fn collect_field_types(ast: &Data) -> Vec<Type> {
match *ast {
Data::Struct(ref s) => s.fields.iter().map(|f| f.ty.clone()).collect(),
_ => panic!("PrefabData derive only support structs"),
}
}

fn collect_field_names(ast: &Data) -> Vec<Ident> {
fn collect_field_data(ast: &Data) -> Vec<(Type, Ident, bool)> {
match *ast {
Data::Struct(ref s) => s
.fields
.iter()
.map(|f| {
f.ident
.as_ref()
.expect("PrefabData derive only support named fieldds")
.clone()
(
f.ty.clone(),
f.ident
.as_ref()
.expect("PrefabData derive only support named fields")
.clone(),
have_component_attribute(&f.attrs[..]),
)
}).collect(),
_ => panic!("PrefabData derive only support structs"),
_ => panic!("PrefabData aggregate derive only support structs"),
}
}

Expand Down Expand Up @@ -168,3 +148,30 @@ fn gen_def_ty_params(generics: &Generics) -> TokenStream {

quote! { #( #ty_params ),* }
}

fn have_component_attribute(attrs: &[Attribute]) -> bool {
for meta in attrs
.iter()
.filter(|attr| attr.path.segments[0].ident == "prefab")
.map(|attr| {
attr.interpret_meta()
.expect("prefab attribute incorrectly defined")
}) {
match meta {
Meta::List(l) => {
for nested_meta in l.nested.iter() {
match *nested_meta {
NestedMeta::Meta(Meta::Word(ref word)) => {
if word == "Component" {
return true;
}
}
_ => panic!("prefab attribute does not contain a single word value"),
}
}
}
_ => (),
};
}
false
}
15 changes: 15 additions & 0 deletions amethyst_derive/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,18 @@ where
{
inner: Stuff<T>,
}

#[derive(Clone)]
pub struct External {
inner: u64,
}

impl Component for External {
type Storage = DenseVecStorage<Self>;
}

#[derive(PrefabData, Clone)]
pub struct Outer {
#[prefab(Component)]
external: External,
}
1 change: 1 addition & 0 deletions amethyst_renderer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ nightly = [ "amethyst_core/nightly" ]
[dependencies]
amethyst_assets = { path = "../amethyst_assets", version = "0.5.0" }
amethyst_core = { path = "../amethyst_core", version = "0.4.0" }
amethyst_derive = { path = "../amethyst_derive", version = "0.2.0" }
derivative = "1.0"
error-chain = "0.12"
fnv = "1.0"
Expand Down
2 changes: 2 additions & 0 deletions amethyst_renderer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
extern crate amethyst_assets;
extern crate amethyst_core;
#[macro_use]
extern crate amethyst_derive;
#[macro_use]
extern crate derivative;
#[macro_use]
extern crate error_chain;
Expand Down
Loading

0 comments on commit 6cc2aab

Please sign in to comment.