Skip to content

Commit bb54563

Browse files
committed
refactor: Move World::get_reflect{_mut} to new module world::reflect
Feedback from PR
1 parent 242c5ea commit bb54563

File tree

3 files changed

+257
-251
lines changed

3 files changed

+257
-251
lines changed

crates/bevy_ecs/src/world/error.rs

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,13 @@
22
//!
33
//! [`World`]: crate::world::World
44
5-
use std::any::TypeId;
6-
75
use thiserror::Error;
86

9-
use crate::{component::ComponentId, prelude::*, schedule::InternedScheduleLabel};
7+
use crate::schedule::InternedScheduleLabel;
108

119
/// The error type returned by [`World::try_run_schedule`] if the provided schedule does not exist.
1210
///
1311
/// [`World::try_run_schedule`]: crate::world::World::try_run_schedule
1412
#[derive(Error, Debug)]
1513
#[error("The schedule with the label {0:?} was not found.")]
1614
pub struct TryRunScheduleError(pub InternedScheduleLabel);
17-
18-
/// The error type returned by [`World::get_reflect`] and [`World::get_reflect_mut`].
19-
#[cfg(feature = "bevy_reflect")]
20-
#[derive(Error, Debug)]
21-
pub enum GetComponentReflectError {
22-
/// There is no [`ComponentId`] corresponding to the given [`TypeId`].
23-
///
24-
/// This is usually handled by calling [`App::register_type`] for the type corresponding to
25-
/// the given [`TypeId`].
26-
///
27-
/// See the documentation for [`bevy_reflect`] for more information.
28-
///
29-
/// [`App::register_type`]: ../../../bevy_app/struct.App.html#method.register_type
30-
#[error("No `ComponentId` corresponding to {0:?} found (did you call App::register_type()?)")]
31-
NoCorrespondingComponentId(TypeId),
32-
33-
/// The given [`Entity`] does not have a [`Component`] corresponding to the given [`TypeId`].
34-
#[error("The given `Entity` {entity:?} does not have a `{component_name:?}` component ({component_id:?}, which corresponds to {type_id:?})")]
35-
EntityDoesNotHaveComponent {
36-
/// The given [`Entity`].
37-
entity: Entity,
38-
/// The given [`TypeId`].
39-
type_id: TypeId,
40-
/// The [`ComponentId`] corresponding to the given [`TypeId`].
41-
component_id: ComponentId,
42-
/// The name corresponding to the [`Component`] with the given [`TypeId`], or `None`
43-
/// if not available.
44-
component_name: Option<String>,
45-
},
46-
47-
/// The [`World`] was missing the [`AppTypeRegistry`] resource.
48-
#[error("The `World` was missing the `AppTypeRegistry` resource")]
49-
MissingAppTypeRegistry,
50-
51-
/// The [`World`]'s [`TypeRegistry`] did not contain [`TypeData`] for [`ReflectFromPtr`] for the given [`TypeId`].
52-
///
53-
/// This is usually handled by calling [`App::register_type`] for the type corresponding to
54-
/// the given [`TypeId`].
55-
///
56-
/// See the documentation for [`bevy_reflect`] for more information.
57-
///
58-
/// [`TypeData`]: bevy_reflect::TypeData
59-
/// [`TypeRegistry`]: bevy_reflect::TypeRegistry
60-
/// [`ReflectFromPtr`]: bevy_reflect::ReflectFromPtr
61-
/// [`App::register_type`]: ../../../bevy_app/struct.App.html#method.register_type
62-
#[error("The `World`'s `TypeRegistry` did not contain `TypeData` for `ReflectFromPtr` for the given {0:?} (did you call `App::register_type()`?)")]
63-
MissingReflectFromPtrTypeData(TypeId),
64-
}

crates/bevy_ecs/src/world/mod.rs

Lines changed: 3 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ mod identifier;
99
mod spawn_batch;
1010
pub mod unsafe_world_cell;
1111

12+
#[cfg(feature = "bevy_reflect")]
13+
pub mod reflect;
14+
1215
pub use crate::{
1316
change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD},
1417
world::command_queue::CommandQueue,
@@ -2635,206 +2638,6 @@ impl World {
26352638
.get_mut_by_id(component_id)
26362639
}
26372640
}
2638-
2639-
/// Retrieves a reference to the given `entity`'s [`Component`] of the given `type_id` using
2640-
/// reflection.
2641-
///
2642-
/// Requires implementing [`Reflect`] for the [`Component`] (e.g., using [`#[derive(Reflect)`](derive@bevy_reflect::Reflect))
2643-
/// and `app.register_type::<TheComponent>()` to have been called[^note-reflect-impl].
2644-
///
2645-
/// If you want to call this with a [`ComponentId`], see [`World::components`] and [`Components::get_id`] to get
2646-
/// the corresponding [`TypeId`].
2647-
///
2648-
/// Also see the crate documentation for [`bevy_reflect`] for more information on
2649-
/// [`Reflect`] and bevy's reflection capabilities.
2650-
///
2651-
/// # Errors
2652-
///
2653-
/// See [`GetComponentReflectError`](error::GetComponentReflectError) for the possible errors and their descriptions.
2654-
///
2655-
/// # Example
2656-
///
2657-
/// ```
2658-
/// use bevy_ecs::prelude::*;
2659-
/// use bevy_reflect::Reflect;
2660-
/// use std::any::TypeId;
2661-
///
2662-
/// // define a `Component` and derive `Reflect` for it
2663-
/// #[derive(Component, Reflect)]
2664-
/// struct MyComponent;
2665-
///
2666-
/// // create a `World` for this example
2667-
/// let mut world = World::new();
2668-
///
2669-
/// // Note: This is usually handled by `App::register_type()`, but this example cannot use `App`.
2670-
/// world.init_resource::<AppTypeRegistry>();
2671-
/// world.get_resource_mut::<AppTypeRegistry>().unwrap().write().register::<MyComponent>();
2672-
///
2673-
/// // spawn an entity with a `MyComponent`
2674-
/// let entity = world.spawn(MyComponent).id();
2675-
///
2676-
/// // retrieve a reflected reference to the entity's `MyComponent`
2677-
/// let comp_reflected: &dyn Reflect = world.get_reflect(entity, TypeId::of::<MyComponent>()).unwrap();
2678-
///
2679-
/// // make sure we got the expected type
2680-
/// assert!(comp_reflected.is::<MyComponent>());
2681-
/// ```
2682-
///
2683-
/// # Note
2684-
/// Requires the `bevy_reflect` feature (included in the default features).
2685-
///
2686-
/// [`ReflectFromPtr`]: bevy_reflect::ReflectFromPtr
2687-
/// [`TypeData`]: bevy_reflect::TypeData
2688-
/// [`Reflect`]: bevy_reflect::Reflect
2689-
/// [`App::register_type`]: ../../bevy_app/struct.App.html#method.register_type
2690-
/// [^note-reflect-impl]: More specifically: Requires [`TypeData`] for [`ReflectFromPtr`] to be registered for the given `type_id`,
2691-
/// which is automatically handled when deriving [`Reflect`] and calling [`App::register_type`].
2692-
#[inline]
2693-
#[cfg(feature = "bevy_reflect")]
2694-
pub fn get_reflect(
2695-
&self,
2696-
entity: Entity,
2697-
type_id: TypeId,
2698-
) -> Result<&dyn bevy_reflect::Reflect, error::GetComponentReflectError> {
2699-
use bevy_reflect::ReflectFromPtr;
2700-
2701-
use crate::prelude::AppTypeRegistry;
2702-
2703-
use error::GetComponentReflectError;
2704-
2705-
let Some(component_id) = self.components().get_id(type_id) else {
2706-
return Err(GetComponentReflectError::NoCorrespondingComponentId(
2707-
type_id,
2708-
));
2709-
};
2710-
2711-
let Some(comp_ptr) = self.get_by_id(entity, component_id) else {
2712-
let component_name = self
2713-
.components()
2714-
.get_name(component_id)
2715-
.map(ToString::to_string);
2716-
2717-
return Err(GetComponentReflectError::EntityDoesNotHaveComponent {
2718-
entity,
2719-
type_id,
2720-
component_id,
2721-
component_name,
2722-
});
2723-
};
2724-
2725-
let Some(type_registry) = self.get_resource::<AppTypeRegistry>().map(|atr| atr.read())
2726-
else {
2727-
return Err(GetComponentReflectError::MissingAppTypeRegistry);
2728-
};
2729-
2730-
let Some(reflect_from_ptr) = type_registry.get_type_data::<ReflectFromPtr>(type_id) else {
2731-
return Err(GetComponentReflectError::MissingReflectFromPtrTypeData(
2732-
type_id,
2733-
));
2734-
};
2735-
2736-
// SAFETY:
2737-
// - `comp_ptr` is guaranteed to point to an object of type `type_id`
2738-
// - `reflect_from_ptr` was constructed for type `type_id`
2739-
// - Assertion that checks this equality is present
2740-
unsafe {
2741-
assert_eq!(
2742-
reflect_from_ptr.type_id(),
2743-
type_id,
2744-
"Mismatch between Ptr's type_id and ReflectFromPtr's type_id",
2745-
);
2746-
2747-
Ok(reflect_from_ptr.as_reflect(comp_ptr))
2748-
}
2749-
}
2750-
2751-
/// Retrieves a mutable reference to the given `entity`'s [`Component`] of the given `type_id` using
2752-
/// reflection.
2753-
///
2754-
/// Requires implementing [`Reflect`] for the [`Component`] (e.g., using [`#[derive(Reflect)`](derive@bevy_reflect::Reflect))
2755-
/// and `app.register_type::<TheComponent>()` to have been called.
2756-
///
2757-
/// This is the mutable version of [`World::get_reflect`], see its docs for more information
2758-
/// and an example.
2759-
///
2760-
/// Just calling this method does not trigger [change detection](crate::change_detection).
2761-
///
2762-
/// # Errors
2763-
///
2764-
/// See [`GetComponentReflectError`](error::GetComponentReflectError) for the possible errors and their descriptions.
2765-
///
2766-
/// # Example
2767-
///
2768-
/// See the documentation for [`World::get_reflect`].
2769-
///
2770-
/// # Note
2771-
/// Requires the feature `bevy_reflect` (included in the default features).
2772-
///
2773-
/// [`Reflect`]: bevy_reflect::Reflect
2774-
#[inline]
2775-
#[cfg(feature = "bevy_reflect")]
2776-
pub fn get_reflect_mut(
2777-
&mut self,
2778-
entity: Entity,
2779-
type_id: TypeId,
2780-
) -> Result<Mut<'_, dyn bevy_reflect::Reflect>, error::GetComponentReflectError> {
2781-
use bevy_reflect::ReflectFromPtr;
2782-
2783-
use crate::prelude::AppTypeRegistry;
2784-
2785-
use error::GetComponentReflectError;
2786-
2787-
// little clone() + read() dance so we a) don't keep a borrow of `self` and b) don't drop a
2788-
// temporary (from read()) too early.
2789-
let Some(app_type_registry) = self.get_resource::<AppTypeRegistry>().cloned() else {
2790-
return Err(GetComponentReflectError::MissingAppTypeRegistry);
2791-
};
2792-
let type_registry = app_type_registry.read();
2793-
2794-
let Some(reflect_from_ptr) = type_registry.get_type_data::<ReflectFromPtr>(type_id) else {
2795-
return Err(GetComponentReflectError::MissingReflectFromPtrTypeData(
2796-
type_id,
2797-
));
2798-
};
2799-
2800-
let Some(component_id) = self.components().get_id(type_id) else {
2801-
return Err(GetComponentReflectError::NoCorrespondingComponentId(
2802-
type_id,
2803-
));
2804-
};
2805-
2806-
// HACK: Only required for the `None`-case/`else`-branch, but it borrows `self`, which will
2807-
// already be mutablyy borrowed by `self.get_mut_by_id()`, and I didn't find a way around it.
2808-
let component_name = self
2809-
.components()
2810-
.get_name(component_id)
2811-
.map(ToString::to_string);
2812-
2813-
let Some(comp_mut_untyped) = self.get_mut_by_id(entity, component_id) else {
2814-
return Err(GetComponentReflectError::EntityDoesNotHaveComponent {
2815-
entity,
2816-
type_id,
2817-
component_id,
2818-
component_name,
2819-
});
2820-
};
2821-
2822-
// SAFETY:
2823-
// - `comp_mut_untyped` is guaranteed to point to an object of type `type_id`
2824-
// - `reflect_from_ptr` was constructed for type `type_id`
2825-
// - Assertion that checks this equality is present
2826-
let comp_mut_typed = comp_mut_untyped.map_unchanged(|ptr_mut| unsafe {
2827-
assert_eq!(
2828-
reflect_from_ptr.type_id(),
2829-
type_id,
2830-
"Mismatch between PtrMut's type_id and ReflectFromPtr's type_id",
2831-
);
2832-
2833-
reflect_from_ptr.as_reflect_mut(ptr_mut)
2834-
});
2835-
2836-
Ok(comp_mut_typed)
2837-
}
28382641
}
28392642

28402643
// Schedule-related methods

0 commit comments

Comments
 (0)