added ability to get Res<T>
from World
with World::get_resource_ref
(#11561)
# Objective It's sometimes desirable to get a `Res<T>` rather than `&T` from `World::get_resource`. Alternative to #9940, partly adresses #9926 ## Solution added additional methods to `World` and `UnsafeWorldCell` to retrieve a resource wrapped in a `Res`. - `UnsafeWorldCell::get_resource_ref` - `World::get_resource_ref` - `World::resource_ref` I can change it so `World::resource_mut` returns `ResMut` instead of `Mut` as well if that's desired, but that could also be added later in a seperate pr. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Mike <mike.hsu@gmail.com> Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
This commit is contained in:
parent
56c3079586
commit
2391e44fa0
@ -28,7 +28,7 @@ use crate::{
|
|||||||
removal_detection::RemovedComponentEvents,
|
removal_detection::RemovedComponentEvents,
|
||||||
schedule::{Schedule, ScheduleLabel, Schedules},
|
schedule::{Schedule, ScheduleLabel, Schedules},
|
||||||
storage::{ResourceData, Storages},
|
storage::{ResourceData, Storages},
|
||||||
system::Resource,
|
system::{Res, Resource},
|
||||||
world::error::TryRunScheduleError,
|
world::error::TryRunScheduleError,
|
||||||
};
|
};
|
||||||
use bevy_ptr::{OwningPtr, Ptr};
|
use bevy_ptr::{OwningPtr, Ptr};
|
||||||
@ -1302,6 +1302,30 @@ impl World {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference to the resource of the given type
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the resource does not exist.
|
||||||
|
/// Use [`get_resource_ref`](World::get_resource_ref) instead if you want to handle this case.
|
||||||
|
///
|
||||||
|
/// If you want to instead insert a value if the resource does not exist,
|
||||||
|
/// use [`get_resource_or_insert_with`](World::get_resource_or_insert_with).
|
||||||
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn resource_ref<R: Resource>(&self) -> Res<R> {
|
||||||
|
match self.get_resource_ref() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => panic!(
|
||||||
|
"Requested resource {} does not exist in the `World`.
|
||||||
|
Did you forget to add it using `app.insert_resource` / `app.init_resource`?
|
||||||
|
Resources are also implicitly added via `app.add_event`,
|
||||||
|
and can be added by plugins.",
|
||||||
|
std::any::type_name::<R>()
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the resource of the given type
|
/// Gets a mutable reference to the resource of the given type
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
@ -1335,6 +1359,15 @@ impl World {
|
|||||||
unsafe { self.as_unsafe_world_cell_readonly().get_resource() }
|
unsafe { self.as_unsafe_world_cell_readonly().get_resource() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference including change detection to the resource of the given type if it exists.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_resource_ref<R: Resource>(&self) -> Option<Res<R>> {
|
||||||
|
// SAFETY:
|
||||||
|
// - `as_unsafe_world_cell_readonly` gives permission to access everything immutably
|
||||||
|
// - `&self` ensures nothing in world is borrowed mutably
|
||||||
|
unsafe { self.as_unsafe_world_cell_readonly().get_resource_ref() }
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the resource of the given type if it exists
|
/// Gets a mutable reference to the resource of the given type if it exists
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
|
pub fn get_resource_mut<R: Resource>(&mut self) -> Option<Mut<'_, R>> {
|
||||||
@ -1875,7 +1908,7 @@ impl World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Runs both [`clear_entities`](Self::clear_entities) and [`clear_resources`](Self::clear_resources),
|
/// Runs both [`clear_entities`](Self::clear_entities) and [`clear_resources`](Self::clear_resources),
|
||||||
/// invalidating all [`Entity`] and resource fetches such as [`Res`](crate::system::Res), [`ResMut`](crate::system::ResMut)
|
/// invalidating all [`Entity`] and resource fetches such as [`Res`], [`ResMut`](crate::system::ResMut)
|
||||||
pub fn clear_all(&mut self) {
|
pub fn clear_all(&mut self) {
|
||||||
self.clear_entities();
|
self.clear_entities();
|
||||||
self.clear_resources();
|
self.clear_resources();
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
prelude::Component,
|
prelude::Component,
|
||||||
removal_detection::RemovedComponentEvents,
|
removal_detection::RemovedComponentEvents,
|
||||||
storage::{Column, ComponentSparseSet, Storages},
|
storage::{Column, ComponentSparseSet, Storages},
|
||||||
system::Resource,
|
system::{Res, Resource},
|
||||||
};
|
};
|
||||||
use bevy_ptr::Ptr;
|
use bevy_ptr::Ptr;
|
||||||
use std::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData};
|
use std::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData};
|
||||||
@ -342,6 +342,30 @@ impl<'w> UnsafeWorldCell<'w> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference including change detection to the resource of the given type if it exists.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// It is the callers responsibility to ensure that
|
||||||
|
/// - the [`UnsafeWorldCell`] has permission to access the resource
|
||||||
|
/// - no mutable reference to the resource exists at the same time
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn get_resource_ref<R: Resource>(self) -> Option<Res<'w, R>> {
|
||||||
|
let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
|
||||||
|
|
||||||
|
// SAFETY: caller ensures `self` has permission to access the resource
|
||||||
|
// caller also ensure that no mutable reference to the resource exists
|
||||||
|
let (ptr, ticks) = unsafe { self.get_resource_with_ticks(component_id)? };
|
||||||
|
|
||||||
|
// SAFETY: `component_id` was obtained from the type ID of `R`
|
||||||
|
let value = unsafe { ptr.deref::<R>() };
|
||||||
|
|
||||||
|
// SAFETY: caller ensures that no mutable reference to the resource exists
|
||||||
|
let ticks =
|
||||||
|
unsafe { Ticks::from_tick_cells(ticks, self.last_change_tick(), self.change_tick()) };
|
||||||
|
|
||||||
|
Some(Res { value, ticks })
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
|
/// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
|
||||||
/// The returned pointer must not be used to modify the resource, and must not be
|
/// The returned pointer must not be used to modify the resource, and must not be
|
||||||
/// dereferenced after the borrow of the [`World`] ends.
|
/// dereferenced after the borrow of the [`World`] ends.
|
||||||
|
Loading…
Reference in New Issue
Block a user