Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions crates/bevy_ecs/src/reflect/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl<B: Bundle + Reflect + TypePath + BundleFromComponents> FromType<B> for Refl
match reflected_bundle.reflect_ref() {
ReflectRef::Struct(bundle) => bundle
.iter_fields()
.for_each(|field| apply_field(&mut entity, field, registry)),
.for_each(|(_, field)| apply_field(&mut entity, field, registry)),
ReflectRef::Tuple(bundle) => bundle
.iter_fields()
.for_each(|field| apply_field(&mut entity, field, registry)),
Expand Down Expand Up @@ -195,15 +195,17 @@ impl<B: Bundle + Reflect + TypePath + BundleFromComponents> FromType<B> for Refl
);
} else {
match reflected_bundle.reflect_ref() {
ReflectRef::Struct(bundle) => bundle.iter_fields().for_each(|field| {
apply_or_insert_field_mapped(
entity,
field,
registry,
mapper,
relationship_hook_mode,
);
}),
ReflectRef::Struct(bundle) => {
bundle.iter_fields().for_each(|(_, field)| {
apply_or_insert_field_mapped(
entity,
field,
registry,
mapper,
relationship_hook_mode,
);
});
}
ReflectRef::Tuple(bundle) => bundle.iter_fields().for_each(|field| {
apply_or_insert_field_mapped(
entity,
Expand Down
20 changes: 18 additions & 2 deletions crates/bevy_reflect/derive/src/impls/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
}
}

fn name_of(&self, field: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<&str> {
#(if #bevy_reflect_path::PartialReflect::reflect_partial_eq(#fields_ref, field).unwrap_or(false) { return #fqoption::Some(#field_names) })*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you can probably clean this up by using ? out of the reflect_partial_eq.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in this comment, I'm still not fully sold on this behavior.

To summarize my thoughts, I believe this behavior (i.e. where a field from one struct returns None on a field of another struct of the same type) may be too unintuitive.

I'm on board with index_by_name (though I think it should be renamed to index_of) and name_at, but index_of (in its current form) and name_of seem too situational and easy to mess up.

I'm willing to change my mind if people feel strongly that this is useful/necessary, though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One idea for getting around the limitations I mention here, is to instead make name_of and friends return a Result with a potential error of like NameOfError::NonUniqueFieldType. And then return that error if the struct contains two of the same type field.

But I don't love that idea as it still is super limiting (just not as much).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option that I think would work better is to provide a low-level API for working with struct field pointers and addresses directly. Then you could do something like:

let api = TheApi::from(&my_struct);
let field: NamedField = api.field_at_addr(&my_struct.field).unwrap();
let name = field.name();

In fact, renaming Struct::name_of to Struct::name_at_addr or something would probably be an okay compromise. But I still also don't know if this sort of low level API belongs in Struct (of course, the benefit is that we don't have to go through get_represented_type_info).

#FQOption::None
}

fn index_of(&self, field: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<usize> {
#(if #bevy_reflect_path::PartialReflect::reflect_partial_eq(#fields_ref, field).unwrap_or(false) { return #fqoption::Some(#field_indices) })*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

#FQOption::None
}

fn index_of_name(&self, name: &str) -> #FQOption<usize> {
match name {
#(#field_names => #fqoption::Some(#field_indices),)*
_ => #FQOption::None,
}
}

fn field_len(&self) -> usize {
#field_count
}
Expand Down Expand Up @@ -144,8 +161,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
if let #bevy_reflect_path::ReflectRef::Struct(struct_value)
= #bevy_reflect_path::PartialReflect::reflect_ref(value) {
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::structs::Struct::iter_fields(struct_value)) {
let name = #bevy_reflect_path::structs::Struct::name_at(struct_value, i).unwrap();
for (name, value) in #bevy_reflect_path::structs::Struct::iter_fields(struct_value) {
if let #FQOption::Some(v) = #bevy_reflect_path::structs::Struct::field_mut(self, name) {
#bevy_reflect_path::PartialReflect::try_apply(v, value)?;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/enums/dynamic_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl Enum for DynamicEnum {

fn index_of(&self, name: &str) -> Option<usize> {
if let DynamicVariant::Struct(data) = &self.variant {
data.index_of(name)
data.index_of_name(name)
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ mod tests {

let values: Vec<u32> = foo
.iter_fields()
.map(|value| *value.try_downcast_ref::<u32>().unwrap())
.map(|(_, value)| *value.try_downcast_ref::<u32>().unwrap())
.collect();
assert_eq!(values, vec![1]);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/serde/ser/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<P: ReflectSerializerProcessor> Serialize for StructSerializer<'_, P> {
self.struct_value.field_len() - ignored_len,
)?;

for (index, value) in self.struct_value.iter_fields().enumerate() {
for (index, (_, value)) in self.struct_value.iter_fields().enumerate() {
if serialization_data.is_some_and(|data| data.is_field_skipped(index)) {
continue;
}
Expand Down
Loading
Loading