bevy icon indicating copy to clipboard operation
bevy copied to clipboard

add `ReflectAsset` and `ReflectHandle`

Open jakobhellermann opened this issue 3 years ago • 1 comments

Objective

image

^ enable this

Concretely, I need to

  • list all handle ids for an asset type
  • fetch the asset as dyn Reflect, given a HandleUntyped
  • when encountering a Handle<T>, find out what asset type that handle refers to (T's type id) and turn the handle into a HandleUntyped

Solution

  • add ReflectAsset type containing function pointers for working with assets
pub struct ReflectAsset {
    type_uuid: Uuid,
    assets_resource_type_id: TypeId, // TypeId of the `Assets<T>` resource

    get: fn(&World, HandleUntyped) -> Option<&dyn Reflect>,
    get_mut: fn(&mut World, HandleUntyped) -> Option<&mut dyn Reflect>,
    get_unchecked_mut: unsafe fn(&World, HandleUntyped) -> Option<&mut dyn Reflect>,
    add: fn(&mut World, &dyn Reflect) -> HandleUntyped,
    set: fn(&mut World, HandleUntyped, &dyn Reflect) -> HandleUntyped,
    len: fn(&World) -> usize,
    ids: for<'w> fn(&'w World) -> Box<dyn Iterator<Item = HandleId> + 'w>,
    remove: fn(&mut World, HandleUntyped) -> Option<Box<dyn Reflect>>,
}
  • add ReflectHandle type relating the handle back to the asset type and providing a way to create a HandleUntyped
pub struct ReflectHandle {
    type_uuid: Uuid,
    asset_type_id: TypeId,
    downcast_handle_untyped: fn(&dyn Any) -> Option<HandleUntyped>,
}
  • add the corresponding FromType impls
  • add a function app.register_asset_reflect which is supposed to be called after .add_asset and registers ReflectAsset and ReflectHandle in the type registry

Changelog

  • add ReflectAsset and ReflectHandle types, which allow code to use reflection to manipulate arbitrary assets without knowing their types at compile time

jakobhellermann avatar Sep 09 '22 12:09 jakobhellermann

I'm in favor of this! Just some small comments around ergonomics and docs.

alice-i-cecile avatar Sep 09 '22 13:09 alice-i-cecile

One question I just thought of is if we want to represent owned values in these kinds of APIs as &Reflect with the expectation that we will just call FromReflect on it, or as Box<dyn Reflect> which we assume to be containing exactly the wanted type. If the later, we probably need ReflectFromReflect for people who want to use FromReflect dynamically (part of https://github.com/bevyengine/bevy/pull/6056).

jakobhellermann avatar Oct 06 '22 20:10 jakobhellermann

Big :+1: to this! This is exactly what I was needing for asset management in scripts.

zicklag avatar Oct 06 '22 21:10 zicklag

One question I just thought of is if we want to represent owned values in these kinds of APIs as &Reflect with the expectation that we will just call FromReflect on it, or as Box<dyn Reflect> which we assume to be containing exactly the wanted type.

My instinct is that I should have a Box<dyn Reflect> for owned values, and ReflectFromReflect was another thing I ran into the need for earlier.

To work around not having ReflectFromReflect I ended up trying to combine ReflectDefault to create the value and Reflect.apply() to patch the value.

zicklag avatar Oct 06 '22 21:10 zicklag

@jakobhellermann I think this PR needs to be rebased

MrGVSV avatar Oct 25 '22 20:10 MrGVSV

bors r+

cart avatar Oct 28 '22 20:10 cart