Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Custom Implementations of ReflectComponent #6206

Closed
zicklag opened this issue Oct 8, 2022 · 4 comments
Closed

Allow Custom Implementations of ReflectComponent #6206

zicklag opened this issue Oct 8, 2022 · 4 comments
Labels
A-Reflection Runtime information about types C-Usability A targeted quality-of-life change that makes Bevy easier to use

Comments

@zicklag
Copy link
Member

zicklag commented Oct 8, 2022

What problem does this solve or what need does it fill?

While working on a scripting interface to Bevy I've run into the use-case to provide a custom implementation of ReflectComponent for a custom Reflect type.

Essentially the custom Reflect type is a JsComponent type that could represent any number of different ComponentIds, though they are all backed by the same Rust type. The JsComponent type stores the ComponentId of the component that it represents internally, and this requires a custom implementation of ReflectComponent to allow the component to be inserted with the proper component ID when adding it to the Bevy world.

Unfortunately, I can't make a custom implementation of ReflectComponent, because it's fields are private.

What solution would you like?

This is largely a question, but do you think it would make sense to make the fields of ReflectComponent public, to allow custom implementations?

What alternative(s) have you considered?

The alternative I can imagine is that I just create a CustomReflectComponent type data that I check for instead of ReflectComponent, but that is more intrusive. In my current use-case, that requires hard-coding support for my custom component type into the bevy_mod_js_scripting scripting interface, instead of having my custom component transparently supported along with all the other components, simply by overriding the ReflectComponent implementation.

Additional context

None.

@zicklag zicklag added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled A-Reflection Runtime information about types labels Oct 8, 2022
@zicklag
Copy link
Member Author

zicklag commented Oct 8, 2022

@MrGVSV and @jakobhellermann, pinging you just in case you have thoughts.

@alice-i-cecile alice-i-cecile added C-Usability A targeted quality-of-life change that makes Bevy easier to use and removed C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Oct 9, 2022
@alice-i-cecile
Copy link
Member

I'd be fine to either make these fields public, or add a constructor method. I suspect the latter will be safer, as it avoids accidentally mutating the fields of pre-existing ReflectComponent in ways that can cause UB.

@MrGVSV
Copy link
Member

MrGVSV commented Oct 9, 2022

I think your use case makes sense and it feels like reflection should allow doing dangerous things like overwriting a ReflectComponent. (And I don't have enough context on bevy_scene + scripting to really suggest anything better haha.)

I agree with @alice-i-cecile that it would be best to protect those fields from unsuspecting users. A constructor would be good but there's a lot of fields to set. Maybe we should use a builder pattern? Or pass a config object?

Also would you need to do the same sort of thing for ReflectResource?

@zicklag
Copy link
Member Author

zicklag commented Oct 9, 2022

I suspect the latter will be safer, as it avoids accidentally mutating the fields of pre-existing ReflectComponent in ways that can cause UB.

I can't tell immediately whether assigning to those fields could cause undefined behavior, unless of course it was the reflect_mut function which is itself unsafe. It seems like it might be fine.

Also, users of ReflectComponent will almost never have a mutable ReflectComponent anyway, because you'll almost always just call TypeRegistry::get_type_data(), which returns an immutable reference.

In other words I think it'd be highly unlikely to modify one on accident, but I'm not really against a constructor either way.

Maybe we should use a builder pattern? Or pass a config object?

If we did it, I think I'd prefer a config object. There aren't a lot of builders in the Bevy API so far, at least as far as I've used.

I guess the config object would literally be an identical struct, but with all the fields public. Then you'd pass that into a ReflectComponent::new() function, maybe.

Also would you need to do the same sort of thing for ReflectResource?

Yes, actually. I hadn't thought of resources yet, but its the same scenario.

@MrGVSV MrGVSV moved this to Open in Reflection Oct 15, 2022
@MrGVSV MrGVSV moved this from Open to In Progress in Reflection Oct 15, 2022
@bors bors bot closed this as completed in f9c56b3 Oct 17, 2022
@MrGVSV MrGVSV moved this from In Progress to Done in Reflection Oct 17, 2022
james7132 pushed a commit to james7132/bevy that referenced this issue Oct 19, 2022
# Objective

- Fixes bevyengine#6206

## Solution

- Create a constructor for creating `ReflectComponent` and `ReflectResource`

---

## Changelog

> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.

### Added

- Created constructors for `ReflectComponent` and `ReflectResource`, allowing for advanced scripting use-cases.
james7132 pushed a commit to james7132/bevy that referenced this issue Oct 28, 2022
# Objective

- Fixes bevyengine#6206

## Solution

- Create a constructor for creating `ReflectComponent` and `ReflectResource`

---

## Changelog

> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.

### Added

- Created constructors for `ReflectComponent` and `ReflectResource`, allowing for advanced scripting use-cases.
Pietrek14 pushed a commit to Pietrek14/bevy that referenced this issue Dec 17, 2022
# Objective

- Fixes bevyengine#6206

## Solution

- Create a constructor for creating `ReflectComponent` and `ReflectResource`

---

## Changelog

> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.

### Added

- Created constructors for `ReflectComponent` and `ReflectResource`, allowing for advanced scripting use-cases.
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

- Fixes bevyengine#6206

## Solution

- Create a constructor for creating `ReflectComponent` and `ReflectResource`

---

## Changelog

> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.

### Added

- Created constructors for `ReflectComponent` and `ReflectResource`, allowing for advanced scripting use-cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Reflection Runtime information about types C-Usability A targeted quality-of-life change that makes Bevy easier to use
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants