diff --git a/crates/bevy_scene/macros/src/bsn/codegen.rs b/crates/bevy_scene/macros/src/bsn/codegen.rs index 8a4974ae31a90..e8c7af79a938e 100644 --- a/crates/bevy_scene/macros/src/bsn/codegen.rs +++ b/crates/bevy_scene/macros/src/bsn/codegen.rs @@ -580,8 +580,8 @@ impl BsnType { #(#base_path.)*#member = #bevy_ecs::template::EntityTemplate::from_reference(#invocation, #index, _call_id); }); } - Some(BsnValue::Type(ty)) if ty.enum_variant.is_some() => { - assignments.push(quote! {#(#base_path.)*#member = #ty;}); + Some(value @ BsnValue::Type(ty)) if ty.enum_variant.is_some() => { + assignments.push(quote! {#(#base_path.)*#member = #value;}); } Some(BsnValue::Type(ty)) => { let mut new_path = base_path.to_vec(); @@ -730,7 +730,7 @@ impl ToTokens for BsnValue { let inner = t.0.iter(); quote! {(#(#inner),*)}.to_tokens(tokens); } - BsnValue::Type(ty) => ty.to_tokens(tokens), + BsnValue::Type(ty) => quote! {(#ty).into()}.to_tokens(tokens), BsnValue::Name(_) => { // Name requires additional context to convert to tokens unreachable!() @@ -908,6 +908,47 @@ mod tests { .contains("Field `x` is missing a value")); } + #[test] + fn enum_variant_field_values_use_implicit_into() { + let mut refs = EntityRefs::default(); + let paths = TestPaths::new(); + let mut exprs = HoistedExpressions::default(); + let mut ctx = paths.ctx(&mut refs, &mut exprs); + let mut assignments = Vec::new(); + let font = BsnType { + path: parse_quote!(TextFont), + enum_variant: None, + fields: BsnFields::Named(vec![BsnNamedField { + is_prop: false, + is_name_shorthand: false, + name: parse_quote!(font_size), + value: Some(BsnValue::Type(BsnType { + path: parse_quote!(TextSize), + enum_variant: Some(parse_quote!(Large)), + fields: BsnFields::Named(Vec::new()), + })), + }]), + }; + + let res = font.push_struct_patch( + &mut ctx, + &mut assignments, + false, + false, + PatchTarget { + path: &[Member::Named(parse_quote!(value))], + is_ref: false, + }, + ); + + assert!(res.is_ok()); + assert!(ctx.errors.is_empty()); + assert_eq!( + assignments[0].to_string(), + "value . font_size = (TextSize :: Large { }) . into () ;" + ); + } + #[test] fn enum_duplicate_field() { // Arrange diff --git a/crates/bevy_scene/src/lib.rs b/crates/bevy_scene/src/lib.rs index 25f2642fecc14..2cb66f942d51a 100644 --- a/crates/bevy_scene/src/lib.rs +++ b/crates/bevy_scene/src/lib.rs @@ -2845,6 +2845,42 @@ mod tests { assert_eq!(entity.get::().unwrap().value, vec![10]); } + #[test] + fn enum_variant_field_values_use_implicit_into() { + let mut app = test_app(); + let world = app.world_mut(); + + #[derive(Component, Default, Clone)] + struct TextFont { + font_size: FontSize, + } + + #[derive(Default, Clone, Debug, PartialEq, Eq)] + struct FontSize(u32); + + enum TextSize { + Large, + } + + impl From for FontSize { + fn from(value: TextSize) -> Self { + match value { + TextSize::Large => FontSize(24), + } + } + } + + let entity = world + .spawn_scene(bsn! { + TextFont { + font_size: TextSize::Large, + } + }) + .unwrap(); + + assert_eq!(entity.get::().unwrap().font_size, FontSize(24)); + } + #[test] fn field_name_shorthand() { let mut app = test_app();