Path: blob/main/crates/bevy_ecs/src/reflect/resource.rs
6600 views
//! Definitions for [`Resource`] reflection.1//!2//! # Architecture3//!4//! See the module doc for [`crate::reflect::component`].56use crate::{7change_detection::Mut,8component::ComponentId,9resource::Resource,10world::{11error::ResourceFetchError, unsafe_world_cell::UnsafeWorldCell, FilteredResources,12FilteredResourcesMut, World,13},14};15use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry};1617use super::from_reflect_with_fallback;1819/// A struct used to operate on reflected [`Resource`] of a type.20///21/// A [`ReflectResource`] for type `T` can be obtained via22/// [`bevy_reflect::TypeRegistration::data`].23#[derive(Clone)]24pub struct ReflectResource(ReflectResourceFns);2526/// The raw function pointers needed to make up a [`ReflectResource`].27///28/// This is used when creating custom implementations of [`ReflectResource`] with29/// [`ReflectResource::new()`].30///31/// > **Note:**32/// > Creating custom implementations of [`ReflectResource`] is an advanced feature that most users33/// > will not need.34/// > Usually a [`ReflectResource`] is created for a type by deriving [`Reflect`]35/// > and adding the `#[reflect(Resource)]` attribute.36/// > After adding the component to the [`TypeRegistry`],37/// > its [`ReflectResource`] can then be retrieved when needed.38///39/// Creating a custom [`ReflectResource`] may be useful if you need to create new resource types at40/// runtime, for example, for scripting implementations.41///42/// By creating a custom [`ReflectResource`] and inserting it into a type's43/// [`TypeRegistration`][bevy_reflect::TypeRegistration],44/// you can modify the way that reflected resources of that type will be inserted into the bevy45/// world.46#[derive(Clone)]47pub struct ReflectResourceFns {48/// Function pointer implementing [`ReflectResource::insert()`].49pub insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry),50/// Function pointer implementing [`ReflectResource::apply()`].51pub apply: fn(&mut World, &dyn PartialReflect),52/// Function pointer implementing [`ReflectResource::apply_or_insert()`].53pub apply_or_insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry),54/// Function pointer implementing [`ReflectResource::remove()`].55pub remove: fn(&mut World),56/// Function pointer implementing [`ReflectResource::reflect()`].57pub reflect:58for<'w> fn(FilteredResources<'w, '_>) -> Result<&'w dyn Reflect, ResourceFetchError>,59/// Function pointer implementing [`ReflectResource::reflect_mut()`].60pub reflect_mut: for<'w> fn(61FilteredResourcesMut<'w, '_>,62) -> Result<Mut<'w, dyn Reflect>, ResourceFetchError>,63/// Function pointer implementing [`ReflectResource::reflect_unchecked_mut()`].64///65/// # Safety66/// The function may only be called with an [`UnsafeWorldCell`] that can be used to mutably access the relevant resource.67pub reflect_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>) -> Option<Mut<'_, dyn Reflect>>,68/// Function pointer implementing [`ReflectResource::copy()`].69pub copy: fn(&World, &mut World, &TypeRegistry),70/// Function pointer implementing [`ReflectResource::register_resource()`].71pub register_resource: fn(&mut World) -> ComponentId,72}7374impl ReflectResourceFns {75/// Get the default set of [`ReflectResourceFns`] for a specific resource type using its76/// [`FromType`] implementation.77///78/// This is useful if you want to start with the default implementation before overriding some79/// of the functions to create a custom implementation.80pub fn new<T: Resource + FromReflect + TypePath>() -> Self {81<ReflectResource as FromType<T>>::from_type().082}83}8485impl ReflectResource {86/// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource).87pub fn insert(88&self,89world: &mut World,90resource: &dyn PartialReflect,91registry: &TypeRegistry,92) {93(self.0.insert)(world, resource, registry);94}9596/// Uses reflection to set the value of this [`Resource`] type in the world to the given value.97///98/// # Panics99///100/// Panics if there is no [`Resource`] of the given type.101pub fn apply(&self, world: &mut World, resource: &dyn PartialReflect) {102(self.0.apply)(world, resource);103}104105/// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist.106pub fn apply_or_insert(107&self,108world: &mut World,109resource: &dyn PartialReflect,110registry: &TypeRegistry,111) {112(self.0.apply_or_insert)(world, resource, registry);113}114115/// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist.116pub fn remove(&self, world: &mut World) {117(self.0.remove)(world);118}119120/// Gets the value of this [`Resource`] type from the world as a reflected reference.121///122/// Note that [`&World`](World) is a valid type for `resources`.123pub fn reflect<'w, 's>(124&self,125resources: impl Into<FilteredResources<'w, 's>>,126) -> Result<&'w dyn Reflect, ResourceFetchError> {127(self.0.reflect)(resources.into())128}129130/// Gets the value of this [`Resource`] type from the world as a mutable reflected reference.131///132/// Note that [`&mut World`](World) is a valid type for `resources`.133pub fn reflect_mut<'w, 's>(134&self,135resources: impl Into<FilteredResourcesMut<'w, 's>>,136) -> Result<Mut<'w, dyn Reflect>, ResourceFetchError> {137(self.0.reflect_mut)(resources.into())138}139140/// # Safety141/// This method does not prevent you from having two mutable pointers to the same data,142/// violating Rust's aliasing rules. To avoid this:143/// * Only call this method with an [`UnsafeWorldCell`] which can be used to mutably access the resource.144/// * Don't call this method more than once in the same scope for a given [`Resource`].145pub unsafe fn reflect_unchecked_mut<'w>(146&self,147world: UnsafeWorldCell<'w>,148) -> Option<Mut<'w, dyn Reflect>> {149// SAFETY: caller promises to uphold uniqueness guarantees150unsafe { (self.0.reflect_unchecked_mut)(world) }151}152153/// Gets the value of this [`Resource`] type from `source_world` and [applies](Self::apply()) it to the value of this [`Resource`] type in `destination_world`.154///155/// # Panics156///157/// Panics if there is no [`Resource`] of the given type.158pub fn copy(159&self,160source_world: &World,161destination_world: &mut World,162registry: &TypeRegistry,163) {164(self.0.copy)(source_world, destination_world, registry);165}166167/// Register the type of this [`Resource`] in [`World`], returning the [`ComponentId`]168pub fn register_resource(&self, world: &mut World) -> ComponentId {169(self.0.register_resource)(world)170}171172/// Create a custom implementation of [`ReflectResource`].173///174/// This is an advanced feature,175/// useful for scripting implementations,176/// that should not be used by most users177/// unless you know what you are doing.178///179/// Usually you should derive [`Reflect`] and add the `#[reflect(Resource)]` component180/// to generate a [`ReflectResource`] implementation automatically.181///182/// See [`ReflectResourceFns`] for more information.183pub fn new(&self, fns: ReflectResourceFns) -> Self {184Self(fns)185}186187/// The underlying function pointers implementing methods on `ReflectResource`.188///189/// This is useful when you want to keep track locally of an individual190/// function pointer.191///192/// Calling [`TypeRegistry::get`] followed by193/// [`TypeRegistration::data::<ReflectResource>`] can be costly if done several194/// times per frame. Consider cloning [`ReflectResource`] and keeping it195/// between frames, cloning a `ReflectResource` is very cheap.196///197/// If you only need a subset of the methods on `ReflectResource`,198/// use `fn_pointers` to get the underlying [`ReflectResourceFns`]199/// and copy the subset of function pointers you care about.200///201/// [`TypeRegistration::data::<ReflectResource>`]: bevy_reflect::TypeRegistration::data202/// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get203pub fn fn_pointers(&self) -> &ReflectResourceFns {204&self.0205}206}207208impl<R: Resource + FromReflect + TypePath> FromType<R> for ReflectResource {209fn from_type() -> Self {210ReflectResource(ReflectResourceFns {211insert: |world, reflected_resource, registry| {212let resource = from_reflect_with_fallback::<R>(reflected_resource, world, registry);213world.insert_resource(resource);214},215apply: |world, reflected_resource| {216let mut resource = world.resource_mut::<R>();217resource.apply(reflected_resource);218},219apply_or_insert: |world, reflected_resource, registry| {220if let Some(mut resource) = world.get_resource_mut::<R>() {221resource.apply(reflected_resource);222} else {223let resource =224from_reflect_with_fallback::<R>(reflected_resource, world, registry);225world.insert_resource(resource);226}227},228remove: |world| {229world.remove_resource::<R>();230},231reflect: |world| world.get::<R>().map(|res| res.into_inner() as &dyn Reflect),232reflect_mut: |world| {233world234.into_mut::<R>()235.map(|res| res.map_unchanged(|value| value as &mut dyn Reflect))236},237reflect_unchecked_mut: |world| {238// SAFETY: all usages of `reflect_unchecked_mut` guarantee that there is either a single mutable239// reference or multiple immutable ones alive at any given point240let res = unsafe { world.get_resource_mut::<R>() };241res.map(|res| res.map_unchanged(|value| value as &mut dyn Reflect))242},243copy: |source_world, destination_world, registry| {244let source_resource = source_world.resource::<R>();245let destination_resource =246from_reflect_with_fallback::<R>(source_resource, destination_world, registry);247destination_world.insert_resource(destination_resource);248},249250register_resource: |world: &mut World| -> ComponentId {251world.register_resource::<R>()252},253})254}255}256257258