Skip to content

Commit

Permalink
Merge pull request #38 from MrGVSV/fix-expected-asset-path
Browse files Browse the repository at this point in the history
Correctly handle `ProtoAsset::HandleId`
  • Loading branch information
MrGVSV authored May 3, 2023
2 parents 97a4695 + 1f0d316 commit b5e643b
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 59 deletions.
20 changes: 14 additions & 6 deletions bevy_proto_derive/src/schematic/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl DeriveSchematic {

/// Generates the logic for `Schematic::preload`.
pub fn preload_def(&self) -> Option<TokenStream> {
let proto_crate = &self.proto_crate;
match &self.data {
SchematicData::Struct(SchematicStruct::Unit) => None,
SchematicData::Struct(
Expand All @@ -110,19 +111,26 @@ impl DeriveSchematic {
ReplacementType::Asset(config) if config.is_preload() => {
let ty = field.defined_ty();
let member = field.member();
let name_str = field.member().to_token_stream().to_string();

Some(if let Some(path) = config.path() {
quote!(
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(#path);
)
} else {
quote!(
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(
#INPUT_IDENT.#member
.to_asset_path()
.expect("ProtoAsset should contain an asset path")
.to_owned()
);
match #INPUT_IDENT.#member {
#proto_crate::proto::ProtoAsset::AssetPath(ref path) => {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(path.to_owned());
}
#proto_crate::proto::ProtoAsset::HandleId(handle_id) => {
panic!(
"expected `ProtoAsset::AssetPath` in field `{}` of `{}`, but found `ProtoAsset::HandleId`",
#name_str,
::core::any::type_name::<Self::Input>()
);
}
}
)
})
}
Expand Down
23 changes: 14 additions & 9 deletions bevy_proto_derive/src/schematic/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,20 @@ impl SchematicField {
)
} else {
quote!(
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.load(
#INPUT_IDENT
.#member
.to_asset_path()
.expect("ProtoAsset should contain an asset path")
)
match #INPUT_IDENT.#member {
#proto_crate::proto::ProtoAsset::AssetPath(ref path) => {
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.load(path)
}
#proto_crate::proto::ProtoAsset::HandleId(handle_id) => {
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.get_handle(handle_id)
}
}
)
}
}
Expand Down
106 changes: 66 additions & 40 deletions bevy_proto_derive/src/schematic/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,40 +53,51 @@ impl SchematicVariant {

pub fn generate_preload_arm(&self, input_ty: &InputType) -> TokenStream {
let ident = &self.ident;
let ident_str = ident.to_string();
match &self.data {
SchematicStruct::Unit => quote! {
#input_ty::#ident => {}
},
SchematicStruct::Unnamed(fields) => {
let (pat, stmt): (Vec<_>, Vec<_>) = fields
.iter()
.filter_map(|field| {
match field.attrs().replacement_ty() {
ReplacementType::Asset(config) if config.is_preload() => {
let ty = field.defined_ty();
let member = field.member();
let name = format_ident!("field_{}", member);

Some(if let Some(path) = config.path() {
(
None,
quote! {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(#path);
},
)
} else {
(
Some(quote!(#member: #name,)),
quote! {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(
#name.to_asset_path().expect("ProtoAsset should contain an asset path")
);
},
)
})
},
_ => None
.filter_map(|field| match field.attrs().replacement_ty() {
ReplacementType::Asset(config) if config.is_preload() => {
let proto_crate = field.proto_crate();
let ty = field.defined_ty();
let member = field.member();
let name = format_ident!("field_{}", member);
let name_str = member.to_token_stream().to_string();

Some(if let Some(path) = config.path() {
(
None,
quote! {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(#path);
},
)
} else {
(
Some(quote!(#member: #name,)),
quote! {
match #name {
#proto_crate::proto::ProtoAsset::AssetPath(ref path) => {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(path.to_owned());
}
#proto_crate::proto::ProtoAsset::HandleId(handle_id) => {
panic!(
"expected `ProtoAsset::AssetPath` in field `{}` of `{}::{}`, but found `ProtoAsset::HandleId`",
#name_str,
::core::any::type_name::<Self::Input>(),
#ident_str
);
}
}
},
)
})
}
_ => None,
})
.unzip();

Expand All @@ -99,8 +110,10 @@ impl SchematicVariant {
.iter()
.filter_map(|field| match field.attrs().replacement_ty() {
ReplacementType::Asset(config) if config.is_preload() => {
let proto_crate = field.proto_crate();
let ty = field.defined_ty();
let member = field.member();
let name_str = member.to_token_stream().to_string();

Some(if let Some(path) = config.path() {
(
Expand All @@ -113,12 +126,19 @@ impl SchematicVariant {
(
Some(quote!(#member,)),
quote! {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(
#member
.to_asset_path()
.expect("ProtoAsset should contain an asset path")
.to_owned()
);
match #member {
#proto_crate::proto::ProtoAsset::AssetPath(ref path) => {
let _: #ty = #DEPENDENCIES_IDENT.add_dependency(path.to_owned());
}
#proto_crate::proto::ProtoAsset::HandleId(handle_id) => {
panic!(
"expected `ProtoAsset::AssetPath` in field `{}` of `{}::{}`, but found `ProtoAsset::HandleId`",
#name_str,
::core::any::type_name::<Self::Input>(),
#ident_str
);
}
}
},
)
})
Expand Down Expand Up @@ -152,14 +172,20 @@ impl SchematicVariant {
)
} else {
quote!(
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.load(
#member
.to_asset_path()
.expect("ProtoAsset should contain an asset path")
)
match #member {
#proto_crate::proto::ProtoAsset::AssetPath(ref path) => {
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.load(path)
}
#proto_crate::proto::ProtoAsset::HandleId(handle_id) => {
#CONTEXT_IDENT
.world()
.resource::<#bevy_crate::asset::AssetServer>()
.get_handle(handle_id)
}
}
)
}
}
Expand Down
10 changes: 10 additions & 0 deletions examples/derive_schematic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ struct Foo<T: Reflect> {
_phantom: PhantomData<T>,
}

#[derive(Component, Schematic, Reflect)]
#[reflect(Schematic)]
enum Foob {
Bar(#[schematic(asset(preload))] Handle<Image>),
Baz {
#[schematic(asset(preload))]
image: Handle<Image>,
},
}

#[derive(Reflect, FromReflect)]
struct EntityGroup(Vec<Entity>);

Expand Down
12 changes: 8 additions & 4 deletions tests/compile_tests/generics.pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ use std::borrow::Cow;
#[derive(Component, Schematic, Reflect)]
#[reflect(Schematic)]
struct TupleStructWithGenerics<'a: 'static, T: Asset, const N: usize>(
#[schematic(asset)] Handle<T>,
#[schematic(asset(preload))] Handle<T>,
Cow<'a, str>,
[i32; N],
);

#[derive(Component, Schematic, Reflect)]
#[reflect(Schematic)]
struct StructWithGenerics<'a: 'static, T: Asset, const N: usize> {
#[schematic(asset)]
#[schematic(asset(preload))]
asset: Handle<T>,
string: Cow<'a, str>,
array: [i32; N],
Expand All @@ -24,9 +24,13 @@ struct StructWithGenerics<'a: 'static, T: Asset, const N: usize> {
#[reflect(Schematic)]
enum EnumWithGenerics<'a: 'static, T: Asset, const N: usize> {
Unit,
Tuple(#[schematic(asset)] Handle<T>, Cow<'a, str>, [i32; N]),
Tuple(
#[schematic(asset(preload))] Handle<T>,
Cow<'a, str>,
[i32; N],
),
Struct {
#[schematic(asset)]
#[schematic(asset(preload))]
asset: Handle<T>,
string: Cow<'a, str>,
array: [i32; N],
Expand Down

0 comments on commit b5e643b

Please sign in to comment.