bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.14k stars 3.56k forks source link

Easy reflection type traversal utils #14847

Open DasLixou opened 2 months ago

DasLixou commented 2 months ago

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

Currently, it is non-trivial to search for and patch a specific type nested deep inside a dyn Reflect.

What solution would you like?

Add an iter_children (name bikesheddable) iterator function on Reflect that returns a ChildrenIter (name bikesheddable) over all direct children. ChildrenIter will be an enum with the same same variants as ReflectKind, but it also holds a reference to the iterator of the erased data trait. e.g. Struct(IterFields<'a>) This is needed for Reflect to still be object-safe. It should also exist an iter_children_mut, which is blocked on #14846

What alternative(s) have you considered?

Writing that myself.

DasLixou commented 2 months ago

Thinking about it, might it not be just easier to put that whole "get by index" stuff directly into Reflect? EDIT: won't work directly for maps, because key-value pairs (but we could do values directly?) and enums, because they have a weird wrapper struct which also tells a name if it's there (but we could also just use the value here)

MrGVSV commented 2 months ago

Personally, I don't think this should be on Reflect itself. This sounds like it would be best done as either an extension trait or utility function. We could potentially take inspiration from syn's visit module for how we could implement it (i.e. with a VisitReflect trait or something).

However, we could also go with a simple visit_reflect function to start with that just takes a FnMut(&dyn Reflect) -> Option<&dyn Reflect> closure and navigates through each item depth-first.