You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Change ChildOf to Childof { parent: Entity} and support deriving Relationship and RelationshipTarget with named structs (#17905)
# Objective
fixes#17896
## Solution
Change ChildOf ( Entity ) to ChildOf { parent: Entity }
by doing this we also allow users to use named structs for relationship
derives, When you have more than 1 field in a struct with named fields
the macro will look for a field with the attribute #[relationship] and
all of the other fields should implement the Default trait. Unnamed
fields are still supported.
When u have a unnamed struct with more than one field the macro will
fail.
Do we want to support something like this ?
```rust
#[derive(Component)]
#[relationship_target(relationship = ChildOf)]
pub struct Children (#[relationship] Entity, u8);
```
I could add this, it but doesn't seem nice.
## Testing
crates/bevy_ecs - cargo test
## Showcase
```rust
use bevy_ecs::component::Component;
use bevy_ecs::entity::Entity;
#[derive(Component)]
#[relationship(relationship_target = Children)]
pub struct ChildOf {
#[relationship]
pub parent: Entity,
internal: u8,
};
#[derive(Component)]
#[relationship_target(relationship = ChildOf)]
pub struct Children {
children: Vec<Entity>
};
```
---------
Co-authored-by: Tim Overbeek <[email protected]>
Co-authored-by: Tim Overbeek <[email protected]>
Co-authored-by: Tim Overbeek <[email protected]>
Co-authored-by: Tim Overbeek <[email protected]>
Co-authored-by: Tim Overbeek <[email protected]>
if visited_fields.is_empty() && visited_indices.is_empty(){
294
303
TokenStream2::new()
295
304
}else{
@@ -651,25 +660,24 @@ fn derive_relationship(
651
660
letSome(relationship) = &attrs.relationshipelse{
652
661
returnOk(None);
653
662
};
654
-
constRELATIONSHIP_FORMAT_MESSAGE:&str = "Relationship derives must be a tuple struct with the only element being an EntityTargets type (ex: ChildOf(Entity))";
constRELATIONSHIP_TARGET_FORMAT_MESSAGE:&str = "RelationshipTarget derives must be a tuple struct with the first element being a private RelationshipSourceCollection (ex: Children(Vec<Entity>))";
returnErr(syn::Error::new(first.span(),"The collection in RelationshipTarget must be private to prevent users from directly mutating it, which could invalidate the correctness of relationships."));
715
-
}
716
-
first.ty.clone()
717
-
}else{
718
-
returnErr(syn::Error::new(
719
-
struct_token.span(),
720
-
RELATIONSHIP_TARGET_FORMAT_MESSAGE,
721
-
));
722
-
}
723
-
}else{
721
+
else{
724
722
returnErr(syn::Error::new(
725
723
ast.span(),
726
-
RELATIONSHIP_TARGET_FORMAT_MESSAGE,
724
+
"RelationshipTarget can only be derived for structs.",
727
725
));
728
726
};
727
+
let field = relationship_field(fields,"RelationshipTarget", struct_token.span())?;
728
+
729
+
if field.vis != Visibility::Inherited{
730
+
returnErr(syn::Error::new(field.span(),"The collection in RelationshipTarget must be private to prevent users from directly mutating it, which could invalidate the correctness of relationships."));
731
+
}
732
+
let collection = &field.ty;
733
+
734
+
let relationship_member = field.ident.clone().map_or(Member::from(0),Member::Named);
735
+
736
+
let members = fields
737
+
.members()
738
+
.filter(|member| member != &relationship_member);
729
739
730
740
let relationship = &relationship_target.relationship;
0 commit comments