Skip to content

Document ReflectComponent#3385

Closed
alice-i-cecile wants to merge 6 commits intobevyengine:mainfrom
alice-i-cecile:reflectcomponent-docs
Closed

Document ReflectComponent#3385
alice-i-cecile wants to merge 6 commits intobevyengine:mainfrom
alice-i-cecile:reflectcomponent-docs

Conversation

@alice-i-cecile
Copy link
Member

@alice-i-cecile alice-i-cecile commented Dec 19, 2021

Objective

  • ReflectComponent is undocumented and very complex to use.

Solution

  • Document it!

Migration Guide

ReflectComponent::add_component has been renamed to ReflectComponent::insert_component for consistency with other insertion APIs.

@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Dec 19, 2021
Probably out of scope for this PR
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Docs An addition or correction to our documentation and removed S-Needs-Triage This issue needs to be labelled labels Dec 19, 2021
@alice-i-cecile
Copy link
Member Author

I'm considering documenting more of the reflect machinery in this PR, but I'm unsure if that will make it harder or easier to review.

@alice-i-cecile alice-i-cecile added A-Reflection Runtime information about types S-Needs-Migration-Guide labels Dec 19, 2021
@alice-i-cecile alice-i-cecile added M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide and removed S-Needs-Migration-Guide labels Jan 20, 2022
};
use bevy_reflect::{impl_reflect_value, FromType, Reflect, ReflectDeserialize};

/// A runtime type-reflectable component
Copy link
Member

Choose a reason for hiding this comment

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

Not entirely correct. ReflectComponent is a type-erased collection of operations on a given component type. By itself, it doesn't contain any reference to a given component. It's meant to be used as metadata that is fetched Res<TypeRegistryArc>.

It can be used to get a dyn Reflect reference given a World reference and Entity, but by itself it does not hold nor refer to component data at all.

This isn't too intuitive at all, so an explicit example is probably best here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, that's a very useful explanation! I was muddling through based on my first pass examining the raw code.

alice-i-cecile and others added 2 commits March 7, 2022 21:58
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: James Liu <contact@jamessliu.com>
@alice-i-cecile alice-i-cecile marked this pull request as draft March 8, 2022 03:05
Copy link
Contributor

@oddfacade oddfacade left a comment

Choose a reason for hiding this comment

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

hope this isn't too pedantic. left some comments based on the things i struggled to understand while trying to figure out how this thing works.

/// Inserts the non-erased value of `component` (with type `C`) into the `entity`
///
/// # Panics
/// `component` must have the same type `C` as the type used to create this struct
Copy link
Contributor

Choose a reason for hiding this comment

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

afaik component only needs to be applicable to C, but need not actually be of type C. for instance, on this line, component may be a DynamicStruct.

Comment on lines +14 to +17
/// a [`ReflectComponent`] is a type-erased version of a component's data,
/// can be transformed into ['dyn Reflect'](Reflect) trait objects,
/// which can be worked with generically
/// and loaded from disk in a type-safe fashion.
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps it would be more accurate to say something like "a ReflectComponent exposes type-erased methods for interacting with components of a certain type." IMO what you have here makes it sound like the ReflectComponent actually stores the component instance's data or something, when in reality it's essentially a virtual method table associated with the component's type. It doesn't so much "transform into" a dyn reflect as fetch the component from the world and then cast it to a dyn reflect.

Comment on lines +23 to +24
/// Once a [`ReflectComponent`] object has been created, you can use that concrete struct
/// to use the methods on this type, which always implicitly affect only the component type originally used to create this struct.
Copy link
Contributor

Choose a reason for hiding this comment

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

This could really use an example. The interaction between ReflectComponent and any given &dyn Reflect is profoundly unintuitive.

Also, nit: "always implicitly affects only..." to me sounds like it's suggesting you can use these methods without worrying about types, because they handle the checking for you. In actual fact the situation is a bit more dire; some of these methods panic if the reference you give them is of the wrong type.

impl ReflectComponent {
pub fn add_component(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
(self.add_component)(world, entity, component);
/// Inserts the non-erased value of `component` (with type `C`) into the `entity`
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if the entity already has a component of type C?

@alice-i-cecile
Copy link
Member Author

Those are excellent comments; thank you @oddfacade.

@alice-i-cecile
Copy link
Member Author

Closing; I'm not confident in my understanding here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events A-Reflection Runtime information about types C-Docs An addition or correction to our documentation M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants