mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
ecs: refactor resources
fixes unintialized global resource memory
This commit is contained in:
parent
2ec530da8c
commit
946d5d1024
7 changed files with 209 additions and 261 deletions
|
@ -45,7 +45,7 @@ impl AppPlugin for ScheduleRunnerPlugin {
|
|||
app.schedule.run(&mut app.world, &mut app.resources);
|
||||
}
|
||||
RunMode::Loop { wait } => loop {
|
||||
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||
break;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl AppPlugin for ScheduleRunnerPlugin {
|
|||
|
||||
app.schedule.run(&mut app.world, &mut app.resources);
|
||||
|
||||
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,26 @@
|
|||
use super::{FromResources, Resources};
|
||||
use crate::{
|
||||
system::{SystemId, TypeAccess},
|
||||
ResourceIndex,
|
||||
};
|
||||
use core::{
|
||||
any::TypeId,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::NonNull,
|
||||
};
|
||||
use hecs::{smaller_tuples_too, MissingComponent, Component, Archetype};
|
||||
use std::collections::HashMap;
|
||||
use super::{Resources, FromResources};
|
||||
use hecs::{smaller_tuples_too, Component};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Shared borrow of an entity's component
|
||||
pub struct Res<'a, T: Component> {
|
||||
archetype: &'a Archetype,
|
||||
target: NonNull<T>,
|
||||
value: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T: Component> Res<'a, T> {
|
||||
#[allow(missing_docs)]
|
||||
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
|
||||
let target = NonNull::new_unchecked(
|
||||
archetype
|
||||
.get::<T>()
|
||||
.ok_or_else(MissingComponent::new::<T>)?
|
||||
.as_ptr()
|
||||
.add(index as usize),
|
||||
);
|
||||
Ok(Self { archetype, target })
|
||||
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||
Self {
|
||||
value: &*value.as_ptr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,22 +28,9 @@ pub trait UnsafeClone {
|
|||
unsafe fn unsafe_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
// TODO: this is unsafe. lets think of a better solution that allows us to clone internally
|
||||
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
archetype: self.archetype,
|
||||
target: self.target,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> UnsafeClone for Res<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
archetype: self.archetype,
|
||||
target: self.target,
|
||||
}
|
||||
Self { value: self.value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,27 +40,22 @@ unsafe impl<T: Component> Sync for Res<'_, T> {}
|
|||
impl<'a, T: Component> Deref for Res<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { self.target.as_ref() }
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique borrow of a resource
|
||||
pub struct ResMut<'a, T: Component> {
|
||||
archetype: &'a Archetype,
|
||||
target: NonNull<T>,
|
||||
_marker: PhantomData<&'a T>,
|
||||
value: *mut T,
|
||||
}
|
||||
|
||||
impl<'a, T: Component> ResMut<'a, T> {
|
||||
#[allow(missing_docs)]
|
||||
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
|
||||
let target = NonNull::new_unchecked(
|
||||
archetype
|
||||
.get::<T>()
|
||||
.ok_or_else(MissingComponent::new::<T>)?
|
||||
.as_ptr()
|
||||
.add(index as usize),
|
||||
);
|
||||
Ok(Self { archetype, target })
|
||||
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||
Self {
|
||||
value: value.as_ptr(),
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,40 +65,35 @@ unsafe impl<T: Component> Sync for ResMut<'_, T> {}
|
|||
impl<'a, T: Component> Deref for ResMut<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { self.target.as_ref() }
|
||||
unsafe { &*self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> DerefMut for ResMut<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { self.target.as_mut() }
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
value: self.value,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Local<'a, T: Component + FromResources> {
|
||||
archetype: &'a Archetype,
|
||||
target: NonNull<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> Local<'a, T> {
|
||||
#[allow(missing_docs)]
|
||||
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
|
||||
let target = NonNull::new_unchecked(
|
||||
archetype
|
||||
.get::<T>()
|
||||
.ok_or_else(MissingComponent::new::<T>)?
|
||||
.as_ptr()
|
||||
.add(index as usize),
|
||||
);
|
||||
Ok(Self { archetype, target })
|
||||
}
|
||||
value: *mut T,
|
||||
_marker: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
archetype: self.archetype,
|
||||
target: self.target,
|
||||
value: self.value,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,13 +101,13 @@ impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
|||
impl<'a, T: Component + FromResources> Deref for Local<'a, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { self.target.as_ref() }
|
||||
unsafe { &*self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> DerefMut for Local<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { self.target.as_mut() }
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,8 +124,8 @@ pub trait FetchResource<'a>: Sized {
|
|||
type Item: UnsafeClone;
|
||||
|
||||
fn access() -> TypeAccess;
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>);
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>);
|
||||
fn borrow(resources: &Resources);
|
||||
fn release(resources: &Resources);
|
||||
|
||||
/// Construct a `Fetch` for `archetype` if it should be traversed
|
||||
///
|
||||
|
@ -171,19 +143,17 @@ pub struct FetchResourceRead<T>(NonNull<T>);
|
|||
impl<'a, T: Component> FetchResource<'a> for FetchResourceRead<T> {
|
||||
type Item = Res<'a, T>;
|
||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||
resources.get_res::<T>()
|
||||
Res::new(resources.get_unsafe_ref::<T>(ResourceIndex::Global))
|
||||
}
|
||||
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.borrow::<T>();
|
||||
}
|
||||
fn borrow(resources: &Resources) {
|
||||
resources.borrow::<T>();
|
||||
}
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.release::<T>();
|
||||
}
|
||||
|
||||
fn release(resources: &Resources) {
|
||||
resources.release::<T>();
|
||||
}
|
||||
|
||||
fn access() -> TypeAccess {
|
||||
let mut access = TypeAccess::default();
|
||||
access.immutable.insert(TypeId::of::<T>());
|
||||
|
@ -200,19 +170,17 @@ pub struct FetchResourceWrite<T>(NonNull<T>);
|
|||
impl<'a, T: Component> FetchResource<'a> for FetchResourceWrite<T> {
|
||||
type Item = ResMut<'a, T>;
|
||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||
resources.get_res_mut::<T>()
|
||||
ResMut::new(resources.get_unsafe_ref::<T>(ResourceIndex::Global))
|
||||
}
|
||||
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.borrow_mut::<T>();
|
||||
}
|
||||
fn borrow(resources: &Resources) {
|
||||
resources.borrow_mut::<T>();
|
||||
}
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.release_mut::<T>();
|
||||
}
|
||||
|
||||
fn release(resources: &Resources) {
|
||||
resources.release_mut::<T>();
|
||||
}
|
||||
|
||||
fn access() -> TypeAccess {
|
||||
let mut access = TypeAccess::default();
|
||||
access.mutable.insert(TypeId::of::<T>());
|
||||
|
@ -235,33 +203,23 @@ pub struct FetchResourceLocalMut<T>(NonNull<T>);
|
|||
impl<'a, T: Component + FromResources> FetchResource<'a> for FetchResourceLocalMut<T> {
|
||||
type Item = Local<'a, T>;
|
||||
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
|
||||
if let Some(system_id) = system_id {
|
||||
let archetype = resources
|
||||
.resource_archetypes
|
||||
.get(&TypeId::of::<T>())
|
||||
.unwrap_or_else(|| {
|
||||
panic!("Resource does not exist {}", std::any::type_name::<T>())
|
||||
});
|
||||
let index = resources
|
||||
.system_id_to_archetype_index
|
||||
.get(&system_id.0)
|
||||
.expect("System does not have this resource");
|
||||
Local::new(archetype, *index).expect("Resource does not exist")
|
||||
} else {
|
||||
panic!("Only Systems can use Local<T> resources");
|
||||
let id = system_id.expect("Local<T> resources can only be used by systems");
|
||||
Local {
|
||||
value: resources
|
||||
.get_unsafe_ref::<T>(ResourceIndex::System(id))
|
||||
.as_ptr(),
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.borrow_mut::<T>();
|
||||
}
|
||||
fn borrow(resources: &Resources) {
|
||||
resources.borrow_mut::<T>();
|
||||
}
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
||||
archetype.release_mut::<T>();
|
||||
}
|
||||
|
||||
fn release(resources: &Resources) {
|
||||
resources.release_mut::<T>();
|
||||
}
|
||||
|
||||
fn access() -> TypeAccess {
|
||||
let mut access = TypeAccess::default();
|
||||
access.mutable.insert(TypeId::of::<T>());
|
||||
|
@ -275,13 +233,13 @@ macro_rules! tuple_impl {
|
|||
type Item = ($($name::Item,)*);
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
$($name::borrow(resource_archetypes);)*
|
||||
fn borrow(resources: &Resources) {
|
||||
$($name::borrow(resources);)*
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
$($name::release(resource_archetypes);)*
|
||||
fn release(resources: &Resources) {
|
||||
$($name::release(resources);)*
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
|
|
|
@ -1,78 +1,79 @@
|
|||
use super::{FetchResource, Res, ResMut, ResourceQuery};
|
||||
use super::{FetchResource, ResourceQuery};
|
||||
use crate::system::SystemId;
|
||||
use core::any::TypeId;
|
||||
use hecs::{Archetype, ComponentError, Ref, RefMut, TypeInfo};
|
||||
use std::collections::HashMap;
|
||||
use hecs::{Archetype, Ref, RefMut, TypeInfo};
|
||||
use std::{collections::HashMap, ptr::NonNull};
|
||||
|
||||
pub trait Resource: Send + Sync + 'static {}
|
||||
impl<T: Send + Sync + 'static> Resource for T {}
|
||||
|
||||
pub struct ResourceData {
|
||||
archetype: Archetype,
|
||||
default_index: Option<u32>,
|
||||
system_id_to_archetype_index: HashMap<u32, u32>,
|
||||
}
|
||||
|
||||
pub enum ResourceIndex {
|
||||
Global,
|
||||
System(SystemId),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Resources {
|
||||
pub(crate) resource_archetypes: HashMap<TypeId, Archetype>,
|
||||
pub(crate) system_id_to_archetype_index: HashMap<u32, u32>,
|
||||
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
||||
}
|
||||
|
||||
impl Resources {
|
||||
pub fn insert<T: Resource>(&mut self, resource: T) {
|
||||
self.insert_index(resource, 0);
|
||||
self.insert_resource(resource, ResourceIndex::Global);
|
||||
}
|
||||
|
||||
pub fn contains<T: Resource>(&self) -> bool {
|
||||
self.get_index::<T>(0).is_ok()
|
||||
self.get_resource::<T>(ResourceIndex::Global).is_some()
|
||||
}
|
||||
|
||||
pub fn get<T: Resource>(&self) -> Result<Ref<'_, T>, ComponentError> {
|
||||
self.get_index(0)
|
||||
pub fn get<T: Resource>(&self) -> Option<Ref<'_, T>> {
|
||||
self.get_resource(ResourceIndex::Global)
|
||||
}
|
||||
|
||||
pub fn get_mut<T: Resource>(&self) -> Result<RefMut<'_, T>, ComponentError> {
|
||||
self.get_index_mut(0)
|
||||
pub fn get_mut<T: Resource>(&self) -> Option<RefMut<'_, T>> {
|
||||
self.get_resource_mut(ResourceIndex::Global)
|
||||
}
|
||||
|
||||
pub fn get_local<'a, T: Resource>(
|
||||
&'a self,
|
||||
id: SystemId,
|
||||
) -> Result<Ref<'a, T>, ComponentError> {
|
||||
self.system_id_to_archetype_index
|
||||
.get(&id.0)
|
||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
||||
.and_then(|index| self.get_index(*index))
|
||||
pub fn get_local<'a, T: Resource>(&'a self, id: SystemId) -> Option<Ref<'a, T>> {
|
||||
self.get_resource(ResourceIndex::System(id))
|
||||
}
|
||||
|
||||
pub fn get_local_mut<'a, T: Resource>(
|
||||
&'a self,
|
||||
id: SystemId,
|
||||
) -> Result<RefMut<'a, T>, ComponentError> {
|
||||
self.system_id_to_archetype_index
|
||||
.get(&id.0)
|
||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
||||
.and_then(|index| self.get_index_mut(*index))
|
||||
pub fn get_local_mut<'a, T: Resource>(&'a self, id: SystemId) -> Option<RefMut<'a, T>> {
|
||||
self.get_resource_mut(ResourceIndex::System(id))
|
||||
}
|
||||
|
||||
pub fn insert_local<T: Resource>(&mut self, id: SystemId, resource: T) {
|
||||
if let Some(index) = self.system_id_to_archetype_index.get(&id.0).cloned() {
|
||||
self.insert_index(resource, index);
|
||||
} else {
|
||||
let mut index = self.archetype_len::<T>();
|
||||
// index 0 is reserved for the global non-system resource
|
||||
if index == 0 {
|
||||
self.allocate_next::<T>();
|
||||
index += 1;
|
||||
}
|
||||
self.insert_index(resource, index);
|
||||
self.system_id_to_archetype_index.insert(id.0, index);
|
||||
}
|
||||
self.insert_resource(resource, ResourceIndex::System(id))
|
||||
}
|
||||
|
||||
fn insert_index<T: Resource>(&mut self, mut resource: T, index: u32) {
|
||||
fn insert_resource<T: Resource>(&mut self, mut resource: T, resource_index: ResourceIndex) {
|
||||
let type_id = TypeId::of::<T>();
|
||||
let archetype = self.resource_archetypes.entry(type_id).or_insert_with(|| {
|
||||
let data = self.resource_data.entry(type_id).or_insert_with(|| {
|
||||
let mut types = Vec::new();
|
||||
types.push(TypeInfo::of::<T>());
|
||||
Archetype::new(types)
|
||||
ResourceData {
|
||||
archetype: Archetype::new(types),
|
||||
default_index: None,
|
||||
system_id_to_archetype_index: HashMap::new(),
|
||||
}
|
||||
});
|
||||
|
||||
let archetype = &mut data.archetype;
|
||||
|
||||
let index = match resource_index {
|
||||
ResourceIndex::Global => *data.default_index.get_or_insert_with(|| archetype.len()),
|
||||
ResourceIndex::System(id) => *data
|
||||
.system_id_to_archetype_index
|
||||
.entry(id.0)
|
||||
.or_insert_with(|| archetype.len()),
|
||||
};
|
||||
|
||||
if index == archetype.len() {
|
||||
unsafe { archetype.allocate(index) };
|
||||
} else if index > archetype.len() {
|
||||
|
@ -86,42 +87,33 @@ impl Resources {
|
|||
}
|
||||
}
|
||||
|
||||
fn allocate_next<T: Resource>(&mut self) {
|
||||
let type_id = TypeId::of::<T>();
|
||||
let archetype = self.resource_archetypes.entry(type_id).or_insert_with(|| {
|
||||
let mut types = Vec::new();
|
||||
types.push(TypeInfo::of::<T>());
|
||||
Archetype::new(types)
|
||||
});
|
||||
|
||||
let index = archetype.len();
|
||||
unsafe { archetype.allocate(index) };
|
||||
}
|
||||
|
||||
fn get_index<T: Resource>(&self, index: u32) -> Result<Ref<'_, T>, ComponentError> {
|
||||
self.resource_archetypes
|
||||
fn get_resource<T: Resource>(&self, resource_index: ResourceIndex) -> Option<Ref<'_, T>> {
|
||||
self.resource_data
|
||||
.get(&TypeId::of::<T>())
|
||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
||||
.and_then(|archetype| unsafe {
|
||||
Ref::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
|
||||
.and_then(|data| unsafe {
|
||||
let index = match resource_index {
|
||||
ResourceIndex::Global => data.default_index?,
|
||||
ResourceIndex::System(id) => *data.system_id_to_archetype_index.get(&id.0)?,
|
||||
};
|
||||
Ref::new(&data.archetype, index).ok()
|
||||
})
|
||||
}
|
||||
|
||||
fn get_index_mut<T: Resource>(&self, index: u32) -> Result<RefMut<'_, T>, ComponentError> {
|
||||
self.resource_archetypes
|
||||
fn get_resource_mut<T: Resource>(
|
||||
&self,
|
||||
resource_index: ResourceIndex,
|
||||
) -> Option<RefMut<'_, T>> {
|
||||
self.resource_data
|
||||
.get(&TypeId::of::<T>())
|
||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
||||
.and_then(|archetype| unsafe {
|
||||
RefMut::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
|
||||
.and_then(|data| unsafe {
|
||||
let index = match resource_index {
|
||||
ResourceIndex::Global => data.default_index?,
|
||||
ResourceIndex::System(id) => *data.system_id_to_archetype_index.get(&id.0)?,
|
||||
};
|
||||
RefMut::new(&data.archetype, index).ok()
|
||||
})
|
||||
}
|
||||
|
||||
fn archetype_len<T: Resource>(&self) -> u32 {
|
||||
self.resource_archetypes
|
||||
.get(&TypeId::of::<T>())
|
||||
.map_or(0, |a| a.len())
|
||||
}
|
||||
|
||||
pub fn query<Q: ResourceQuery>(&self) -> <Q::Fetch as FetchResource>::Item {
|
||||
unsafe { Q::Fetch::get(&self, None) }
|
||||
}
|
||||
|
@ -134,21 +126,45 @@ impl Resources {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get_res<T: Resource>(&self) -> Res<'_, T> {
|
||||
let archetype = self
|
||||
.resource_archetypes
|
||||
pub unsafe fn get_unsafe_ref<T: Resource>(&self, resource_index: ResourceIndex) -> NonNull<T> {
|
||||
self.resource_data
|
||||
.get(&TypeId::of::<T>())
|
||||
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()));
|
||||
Res::new(archetype, 0).expect("Resource does not exist")
|
||||
.and_then(|data| {
|
||||
let index = match resource_index {
|
||||
ResourceIndex::Global => data.default_index?,
|
||||
ResourceIndex::System(id) => {
|
||||
data.system_id_to_archetype_index.get(&id.0).cloned()?
|
||||
}
|
||||
};
|
||||
Some(NonNull::new_unchecked(
|
||||
data.archetype.get::<T>()?.as_ptr().add(index as usize),
|
||||
))
|
||||
})
|
||||
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get_res_mut<T: Resource>(&self) -> ResMut<'_, T> {
|
||||
let archetype = self
|
||||
.resource_archetypes
|
||||
.get(&TypeId::of::<T>())
|
||||
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()));
|
||||
ResMut::new(archetype, 0).expect("Resource does not exist")
|
||||
pub fn borrow<T: Resource>(&self) {
|
||||
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
|
||||
data.archetype.borrow::<T>();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn release<T: Resource>(&self) {
|
||||
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
|
||||
data.archetype.release::<T>();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_mut<T: Resource>(&self) {
|
||||
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
|
||||
data.archetype.borrow_mut::<T>();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn release_mut<T: Resource>(&self) {
|
||||
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
|
||||
data.archetype.release_mut::<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +192,7 @@ mod tests {
|
|||
#[test]
|
||||
fn resource() {
|
||||
let mut resources = Resources::default();
|
||||
assert!(resources.get::<i32>().is_err());
|
||||
assert!(resources.get::<i32>().is_none());
|
||||
|
||||
resources.insert(123);
|
||||
assert_eq!(*resources.get::<i32>().expect("resource exists"), 123);
|
||||
|
@ -195,7 +211,7 @@ mod tests {
|
|||
|
||||
assert_eq!(*resources.get::<f64>().expect("resource exists"), -1.0);
|
||||
|
||||
assert!(resources.get_local::<i32>(SystemId(0)).is_err());
|
||||
assert!(resources.get_local::<i32>(SystemId(0)).is_none());
|
||||
resources.insert_local(SystemId(0), 111);
|
||||
assert_eq!(
|
||||
*resources
|
||||
|
|
|
@ -105,14 +105,14 @@ macro_rules! impl_into_foreach_system {
|
|||
name: core::any::type_name::<Self>().into(),
|
||||
id,
|
||||
func: move |world, resources, _archetype_access, state| {
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources.resource_archetypes);
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources);
|
||||
{
|
||||
let ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
|
||||
for ($($component,)*) in world.query::<($($component,)*)>().iter() {
|
||||
fn_call!(self, ($($commands, state)*), ($($resource),*), ($($component),*))
|
||||
}
|
||||
}
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources.resource_archetypes);
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources);
|
||||
},
|
||||
thread_local_func: move |world, resources, state| {
|
||||
state.apply(world, resources);
|
||||
|
@ -251,7 +251,7 @@ macro_rules! impl_into_query_system {
|
|||
id,
|
||||
name: core::any::type_name::<Self>().into(),
|
||||
func: move |world, resources, archetype_access, state| {
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources.resource_archetypes);
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources);
|
||||
{
|
||||
let ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
|
||||
let mut i = 0;
|
||||
|
@ -267,7 +267,7 @@ macro_rules! impl_into_query_system {
|
|||
let commands = &state.commands;
|
||||
fn_call!(self, ($($commands, commands)*), ($($resource),*), ($($query),*))
|
||||
}
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources.resource_archetypes);
|
||||
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources);
|
||||
},
|
||||
thread_local_func: move |world, resources, state| {
|
||||
state.commands.apply(world, resources);
|
||||
|
|
|
@ -11,11 +11,11 @@ use crate::{
|
|||
};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_ecs::{
|
||||
Archetype, FetchResource, Query, Res, ResMut, ResourceQuery, Resources, SystemId, TypeAccess,
|
||||
UnsafeClone,
|
||||
FetchResource, Query, Res, ResMut, ResourceIndex, ResourceQuery, Resources, SystemId,
|
||||
TypeAccess, UnsafeClone,
|
||||
};
|
||||
use bevy_property::Properties;
|
||||
use std::{any::TypeId, collections::HashMap, ops::Range, sync::Arc};
|
||||
use std::{any::TypeId, ops::Range, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -150,66 +150,40 @@ pub struct FetchDrawContext;
|
|||
// TODO: derive this impl
|
||||
impl<'a> FetchResource<'a> for FetchDrawContext {
|
||||
type Item = DrawContext<'a>;
|
||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
|
||||
.unwrap()
|
||||
.borrow_mut::<Assets<PipelineDescriptor>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Assets<Shader>>())
|
||||
.unwrap()
|
||||
.borrow_mut::<Assets<Shader>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<PipelineCompiler>())
|
||||
.unwrap()
|
||||
.borrow_mut::<PipelineCompiler>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Box<dyn RenderResourceContext>>())
|
||||
.unwrap()
|
||||
.borrow::<Box<dyn RenderResourceContext>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<VertexBufferDescriptors>())
|
||||
.unwrap()
|
||||
.borrow::<VertexBufferDescriptors>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<SharedBuffers>())
|
||||
.unwrap()
|
||||
.borrow::<SharedBuffers>();
|
||||
fn borrow(resources: &Resources) {
|
||||
resources.borrow_mut::<Assets<PipelineDescriptor>>();
|
||||
resources.borrow_mut::<Assets<Shader>>();
|
||||
resources.borrow_mut::<PipelineCompiler>();
|
||||
resources.borrow::<Box<dyn RenderResourceContext>>();
|
||||
resources.borrow::<VertexBufferDescriptors>();
|
||||
resources.borrow::<SharedBuffers>();
|
||||
}
|
||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
|
||||
.unwrap()
|
||||
.release_mut::<Assets<PipelineDescriptor>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Assets<Shader>>())
|
||||
.unwrap()
|
||||
.release_mut::<Assets<Shader>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<PipelineCompiler>())
|
||||
.unwrap()
|
||||
.release_mut::<PipelineCompiler>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<Box<dyn RenderResourceContext>>())
|
||||
.unwrap()
|
||||
.release::<Box<dyn RenderResourceContext>>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<VertexBufferDescriptors>())
|
||||
.unwrap()
|
||||
.release::<VertexBufferDescriptors>();
|
||||
resource_archetypes
|
||||
.get(&TypeId::of::<SharedBuffers>())
|
||||
.unwrap()
|
||||
.release::<SharedBuffers>();
|
||||
fn release(resources: &Resources) {
|
||||
resources.release_mut::<Assets<PipelineDescriptor>>();
|
||||
resources.release_mut::<Assets<Shader>>();
|
||||
resources.release_mut::<PipelineCompiler>();
|
||||
resources.release::<Box<dyn RenderResourceContext>>();
|
||||
resources.release::<VertexBufferDescriptors>();
|
||||
resources.release::<SharedBuffers>();
|
||||
}
|
||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||
DrawContext {
|
||||
pipelines: resources.get_res_mut::<Assets<PipelineDescriptor>>(),
|
||||
shaders: resources.get_res_mut::<Assets<Shader>>(),
|
||||
pipeline_compiler: resources.get_res_mut::<PipelineCompiler>(),
|
||||
render_resource_context: resources.get_res::<Box<dyn RenderResourceContext>>(),
|
||||
vertex_buffer_descriptors: resources.get_res::<VertexBufferDescriptors>(),
|
||||
shared_buffers: resources.get_res::<SharedBuffers>(),
|
||||
pipelines: ResMut::new(
|
||||
resources.get_unsafe_ref::<Assets<PipelineDescriptor>>(ResourceIndex::Global),
|
||||
),
|
||||
shaders: ResMut::new(resources.get_unsafe_ref::<Assets<Shader>>(ResourceIndex::Global)),
|
||||
pipeline_compiler: ResMut::new(
|
||||
resources.get_unsafe_ref::<PipelineCompiler>(ResourceIndex::Global),
|
||||
),
|
||||
render_resource_context: Res::new(
|
||||
resources.get_unsafe_ref::<Box<dyn RenderResourceContext>>(ResourceIndex::Global),
|
||||
),
|
||||
vertex_buffer_descriptors: Res::new(
|
||||
resources.get_unsafe_ref::<VertexBufferDescriptors>(ResourceIndex::Global),
|
||||
),
|
||||
shared_buffers: Res::new(
|
||||
resources.get_unsafe_ref::<SharedBuffers>(ResourceIndex::Global),
|
||||
),
|
||||
current_pipeline: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ impl Node for PassNode {
|
|||
|
||||
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
|
||||
if self.default_clear_color_inputs.contains(&i) {
|
||||
if let Ok(default_clear_color) = resources.get::<ClearColor>() {
|
||||
if let Some(default_clear_color) = resources.get::<ClearColor>() {
|
||||
color_attachment.ops.load = LoadOp::Clear(default_clear_color.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ pub fn winit_runner(mut app: App) {
|
|||
ControlFlow::Poll
|
||||
};
|
||||
|
||||
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
|
||||
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue