mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
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
2 changed files with 60 additions and 3 deletions
|
@ -28,7 +28,7 @@ use crate::{
|
|||
removal_detection::RemovedComponentEvents,
|
||||
schedule::{Schedule, ScheduleLabel, Schedules},
|
||||
storage::{ResourceData, Storages},
|
||||
system::Resource,
|
||||
system::{Res, Resource},
|
||||
world::error::TryRunScheduleError,
|
||||
};
|
||||
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
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -1335,6 +1359,15 @@ impl World {
|
|||
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
|
||||
#[inline]
|
||||
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),
|
||||
/// 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) {
|
||||
self.clear_entities();
|
||||
self.clear_resources();
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
prelude::Component,
|
||||
removal_detection::RemovedComponentEvents,
|
||||
storage::{Column, ComponentSparseSet, Storages},
|
||||
system::Resource,
|
||||
system::{Res, Resource},
|
||||
};
|
||||
use bevy_ptr::Ptr;
|
||||
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.
|
||||
/// The returned pointer must not be used to modify the resource, and must not be
|
||||
/// dereferenced after the borrow of the [`World`] ends.
|
||||
|
|
Loading…
Add table
Reference in a new issue