mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +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);
|
app.schedule.run(&mut app.world, &mut app.resources);
|
||||||
}
|
}
|
||||||
RunMode::Loop { wait } => loop {
|
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() {
|
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl AppPlugin for ScheduleRunnerPlugin {
|
||||||
|
|
||||||
app.schedule.run(&mut app.world, &mut app.resources);
|
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() {
|
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,26 @@
|
||||||
|
use super::{FromResources, Resources};
|
||||||
use crate::{
|
use crate::{
|
||||||
system::{SystemId, TypeAccess},
|
system::{SystemId, TypeAccess},
|
||||||
|
ResourceIndex,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
use hecs::{smaller_tuples_too, MissingComponent, Component, Archetype};
|
use hecs::{smaller_tuples_too, Component};
|
||||||
use std::collections::HashMap;
|
use std::marker::PhantomData;
|
||||||
use super::{Resources, FromResources};
|
|
||||||
/// Shared borrow of an entity's component
|
/// Shared borrow of an entity's component
|
||||||
pub struct Res<'a, T: Component> {
|
pub struct Res<'a, T: Component> {
|
||||||
archetype: &'a Archetype,
|
value: &'a T,
|
||||||
target: NonNull<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Component> Res<'a, T> {
|
impl<'a, T: Component> Res<'a, T> {
|
||||||
#[allow(missing_docs)]
|
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||||
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
|
Self {
|
||||||
let target = NonNull::new_unchecked(
|
value: &*value.as_ptr(),
|
||||||
archetype
|
}
|
||||||
.get::<T>()
|
|
||||||
.ok_or_else(MissingComponent::new::<T>)?
|
|
||||||
.as_ptr()
|
|
||||||
.add(index as usize),
|
|
||||||
);
|
|
||||||
Ok(Self { archetype, target })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,22 +28,9 @@ pub trait UnsafeClone {
|
||||||
unsafe fn unsafe_clone(&self) -> Self;
|
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> {
|
impl<'a, T: Component> UnsafeClone for Res<'a, T> {
|
||||||
unsafe fn unsafe_clone(&self) -> Self {
|
unsafe fn unsafe_clone(&self) -> Self {
|
||||||
Self {
|
Self { value: self.value }
|
||||||
archetype: self.archetype,
|
|
||||||
target: self.target,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,27 +40,22 @@ unsafe impl<T: Component> Sync for Res<'_, T> {}
|
||||||
impl<'a, T: Component> Deref for Res<'a, T> {
|
impl<'a, T: Component> Deref for Res<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
unsafe { self.target.as_ref() }
|
self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unique borrow of a resource
|
/// Unique borrow of a resource
|
||||||
pub struct ResMut<'a, T: Component> {
|
pub struct ResMut<'a, T: Component> {
|
||||||
archetype: &'a Archetype,
|
_marker: PhantomData<&'a T>,
|
||||||
target: NonNull<T>,
|
value: *mut T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Component> ResMut<'a, T> {
|
impl<'a, T: Component> ResMut<'a, T> {
|
||||||
#[allow(missing_docs)]
|
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||||
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
|
Self {
|
||||||
let target = NonNull::new_unchecked(
|
value: value.as_ptr(),
|
||||||
archetype
|
_marker: Default::default(),
|
||||||
.get::<T>()
|
}
|
||||||
.ok_or_else(MissingComponent::new::<T>)?
|
|
||||||
.as_ptr()
|
|
||||||
.add(index as usize),
|
|
||||||
);
|
|
||||||
Ok(Self { archetype, target })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,40 +65,35 @@ unsafe impl<T: Component> Sync for ResMut<'_, T> {}
|
||||||
impl<'a, T: Component> Deref for ResMut<'a, T> {
|
impl<'a, T: Component> Deref for ResMut<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
unsafe { self.target.as_ref() }
|
unsafe { &*self.value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Component> DerefMut for ResMut<'a, T> {
|
impl<'a, T: Component> DerefMut for ResMut<'a, T> {
|
||||||
fn deref_mut(&mut self) -> &mut 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> {
|
pub struct Local<'a, T: Component + FromResources> {
|
||||||
archetype: &'a Archetype,
|
value: *mut T,
|
||||||
target: NonNull<T>,
|
_marker: PhantomData<&'a 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 })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
||||||
unsafe fn unsafe_clone(&self) -> Self {
|
unsafe fn unsafe_clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
archetype: self.archetype,
|
value: self.value,
|
||||||
target: self.target,
|
_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> {
|
impl<'a, T: Component + FromResources> Deref for Local<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
unsafe { self.target.as_ref() }
|
unsafe { &*self.value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Component + FromResources> DerefMut for Local<'a, T> {
|
impl<'a, T: Component + FromResources> DerefMut for Local<'a, T> {
|
||||||
fn deref_mut(&mut self) -> &mut 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;
|
type Item: UnsafeClone;
|
||||||
|
|
||||||
fn access() -> TypeAccess;
|
fn access() -> TypeAccess;
|
||||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>);
|
fn borrow(resources: &Resources);
|
||||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>);
|
fn release(resources: &Resources);
|
||||||
|
|
||||||
/// Construct a `Fetch` for `archetype` if it should be traversed
|
/// 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> {
|
impl<'a, T: Component> FetchResource<'a> for FetchResourceRead<T> {
|
||||||
type Item = Res<'a, T>;
|
type Item = Res<'a, T>;
|
||||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
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>) {
|
fn borrow(resources: &Resources) {
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
resources.borrow::<T>();
|
||||||
archetype.borrow::<T>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
fn release(resources: &Resources) {
|
||||||
archetype.release::<T>();
|
resources.release::<T>();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access() -> TypeAccess {
|
fn access() -> TypeAccess {
|
||||||
let mut access = TypeAccess::default();
|
let mut access = TypeAccess::default();
|
||||||
access.immutable.insert(TypeId::of::<T>());
|
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> {
|
impl<'a, T: Component> FetchResource<'a> for FetchResourceWrite<T> {
|
||||||
type Item = ResMut<'a, T>;
|
type Item = ResMut<'a, T>;
|
||||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
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>) {
|
fn borrow(resources: &Resources) {
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
resources.borrow_mut::<T>();
|
||||||
archetype.borrow_mut::<T>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
fn release(resources: &Resources) {
|
||||||
archetype.release_mut::<T>();
|
resources.release_mut::<T>();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access() -> TypeAccess {
|
fn access() -> TypeAccess {
|
||||||
let mut access = TypeAccess::default();
|
let mut access = TypeAccess::default();
|
||||||
access.mutable.insert(TypeId::of::<T>());
|
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> {
|
impl<'a, T: Component + FromResources> FetchResource<'a> for FetchResourceLocalMut<T> {
|
||||||
type Item = Local<'a, T>;
|
type Item = Local<'a, T>;
|
||||||
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
|
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
|
||||||
if let Some(system_id) = system_id {
|
let id = system_id.expect("Local<T> resources can only be used by systems");
|
||||||
let archetype = resources
|
Local {
|
||||||
.resource_archetypes
|
value: resources
|
||||||
.get(&TypeId::of::<T>())
|
.get_unsafe_ref::<T>(ResourceIndex::System(id))
|
||||||
.unwrap_or_else(|| {
|
.as_ptr(),
|
||||||
panic!("Resource does not exist {}", std::any::type_name::<T>())
|
_marker: Default::default(),
|
||||||
});
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
fn borrow(resources: &Resources) {
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
resources.borrow_mut::<T>();
|
||||||
archetype.borrow_mut::<T>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
|
||||||
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
|
fn release(resources: &Resources) {
|
||||||
archetype.release_mut::<T>();
|
resources.release_mut::<T>();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access() -> TypeAccess {
|
fn access() -> TypeAccess {
|
||||||
let mut access = TypeAccess::default();
|
let mut access = TypeAccess::default();
|
||||||
access.mutable.insert(TypeId::of::<T>());
|
access.mutable.insert(TypeId::of::<T>());
|
||||||
|
@ -275,13 +233,13 @@ macro_rules! tuple_impl {
|
||||||
type Item = ($($name::Item,)*);
|
type Item = ($($name::Item,)*);
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
fn borrow(resources: &Resources) {
|
||||||
$($name::borrow(resource_archetypes);)*
|
$($name::borrow(resources);)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
fn release(resources: &Resources) {
|
||||||
$($name::release(resource_archetypes);)*
|
$($name::release(resources);)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
|
|
|
@ -1,78 +1,79 @@
|
||||||
use super::{FetchResource, Res, ResMut, ResourceQuery};
|
use super::{FetchResource, ResourceQuery};
|
||||||
use crate::system::SystemId;
|
use crate::system::SystemId;
|
||||||
use core::any::TypeId;
|
use core::any::TypeId;
|
||||||
use hecs::{Archetype, ComponentError, Ref, RefMut, TypeInfo};
|
use hecs::{Archetype, Ref, RefMut, TypeInfo};
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ptr::NonNull};
|
||||||
|
|
||||||
pub trait Resource: Send + Sync + 'static {}
|
pub trait Resource: Send + Sync + 'static {}
|
||||||
impl<T: Send + Sync + 'static> Resource for T {}
|
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)]
|
#[derive(Default)]
|
||||||
pub struct Resources {
|
pub struct Resources {
|
||||||
pub(crate) resource_archetypes: HashMap<TypeId, Archetype>,
|
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
||||||
pub(crate) system_id_to_archetype_index: HashMap<u32, u32>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resources {
|
impl Resources {
|
||||||
pub fn insert<T: Resource>(&mut self, resource: T) {
|
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 {
|
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> {
|
pub fn get<T: Resource>(&self) -> Option<Ref<'_, T>> {
|
||||||
self.get_index(0)
|
self.get_resource(ResourceIndex::Global)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<T: Resource>(&self) -> Result<RefMut<'_, T>, ComponentError> {
|
pub fn get_mut<T: Resource>(&self) -> Option<RefMut<'_, T>> {
|
||||||
self.get_index_mut(0)
|
self.get_resource_mut(ResourceIndex::Global)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_local<'a, T: Resource>(
|
pub fn get_local<'a, T: Resource>(&'a self, id: SystemId) -> Option<Ref<'a, T>> {
|
||||||
&'a self,
|
self.get_resource(ResourceIndex::System(id))
|
||||||
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_mut<'a, T: Resource>(
|
pub fn get_local_mut<'a, T: Resource>(&'a self, id: SystemId) -> Option<RefMut<'a, T>> {
|
||||||
&'a self,
|
self.get_resource_mut(ResourceIndex::System(id))
|
||||||
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 insert_local<T: Resource>(&mut self, id: SystemId, resource: T) {
|
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_resource(resource, ResourceIndex::System(id))
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 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();
|
let mut types = Vec::new();
|
||||||
types.push(TypeInfo::of::<T>());
|
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() {
|
if index == archetype.len() {
|
||||||
unsafe { archetype.allocate(index) };
|
unsafe { archetype.allocate(index) };
|
||||||
} else if index > archetype.len() {
|
} else if index > archetype.len() {
|
||||||
|
@ -86,42 +87,33 @@ impl Resources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_next<T: Resource>(&mut self) {
|
fn get_resource<T: Resource>(&self, resource_index: ResourceIndex) -> Option<Ref<'_, T>> {
|
||||||
let type_id = TypeId::of::<T>();
|
self.resource_data
|
||||||
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
|
|
||||||
.get(&TypeId::of::<T>())
|
.get(&TypeId::of::<T>())
|
||||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
.and_then(|data| unsafe {
|
||||||
.and_then(|archetype| unsafe {
|
let index = match resource_index {
|
||||||
Ref::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
|
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> {
|
fn get_resource_mut<T: Resource>(
|
||||||
self.resource_archetypes
|
&self,
|
||||||
|
resource_index: ResourceIndex,
|
||||||
|
) -> Option<RefMut<'_, T>> {
|
||||||
|
self.resource_data
|
||||||
.get(&TypeId::of::<T>())
|
.get(&TypeId::of::<T>())
|
||||||
.ok_or_else(|| ComponentError::NoSuchEntity)
|
.and_then(|data| unsafe {
|
||||||
.and_then(|archetype| unsafe {
|
let index = match resource_index {
|
||||||
RefMut::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
|
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 {
|
pub fn query<Q: ResourceQuery>(&self) -> <Q::Fetch as FetchResource>::Item {
|
||||||
unsafe { Q::Fetch::get(&self, None) }
|
unsafe { Q::Fetch::get(&self, None) }
|
||||||
}
|
}
|
||||||
|
@ -134,21 +126,45 @@ impl Resources {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn get_res<T: Resource>(&self) -> Res<'_, T> {
|
pub unsafe fn get_unsafe_ref<T: Resource>(&self, resource_index: ResourceIndex) -> NonNull<T> {
|
||||||
let archetype = self
|
self.resource_data
|
||||||
.resource_archetypes
|
|
||||||
.get(&TypeId::of::<T>())
|
.get(&TypeId::of::<T>())
|
||||||
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()));
|
.and_then(|data| {
|
||||||
Res::new(archetype, 0).expect("Resource does not exist")
|
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 fn borrow<T: Resource>(&self) {
|
||||||
pub unsafe fn get_res_mut<T: Resource>(&self) -> ResMut<'_, T> {
|
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
|
||||||
let archetype = self
|
data.archetype.borrow::<T>();
|
||||||
.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 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]
|
#[test]
|
||||||
fn resource() {
|
fn resource() {
|
||||||
let mut resources = Resources::default();
|
let mut resources = Resources::default();
|
||||||
assert!(resources.get::<i32>().is_err());
|
assert!(resources.get::<i32>().is_none());
|
||||||
|
|
||||||
resources.insert(123);
|
resources.insert(123);
|
||||||
assert_eq!(*resources.get::<i32>().expect("resource exists"), 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_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);
|
resources.insert_local(SystemId(0), 111);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*resources
|
*resources
|
||||||
|
|
|
@ -105,14 +105,14 @@ macro_rules! impl_into_foreach_system {
|
||||||
name: core::any::type_name::<Self>().into(),
|
name: core::any::type_name::<Self>().into(),
|
||||||
id,
|
id,
|
||||||
func: move |world, resources, _archetype_access, state| {
|
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 ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
|
||||||
for ($($component,)*) in world.query::<($($component,)*)>().iter() {
|
for ($($component,)*) in world.query::<($($component,)*)>().iter() {
|
||||||
fn_call!(self, ($($commands, state)*), ($($resource),*), ($($component),*))
|
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| {
|
thread_local_func: move |world, resources, state| {
|
||||||
state.apply(world, resources);
|
state.apply(world, resources);
|
||||||
|
@ -251,7 +251,7 @@ macro_rules! impl_into_query_system {
|
||||||
id,
|
id,
|
||||||
name: core::any::type_name::<Self>().into(),
|
name: core::any::type_name::<Self>().into(),
|
||||||
func: move |world, resources, archetype_access, state| {
|
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 ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -267,7 +267,7 @@ macro_rules! impl_into_query_system {
|
||||||
let commands = &state.commands;
|
let commands = &state.commands;
|
||||||
fn_call!(self, ($($commands, commands)*), ($($resource),*), ($($query),*))
|
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| {
|
thread_local_func: move |world, resources, state| {
|
||||||
state.commands.apply(world, resources);
|
state.commands.apply(world, resources);
|
||||||
|
|
|
@ -11,11 +11,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
Archetype, FetchResource, Query, Res, ResMut, ResourceQuery, Resources, SystemId, TypeAccess,
|
FetchResource, Query, Res, ResMut, ResourceIndex, ResourceQuery, Resources, SystemId,
|
||||||
UnsafeClone,
|
TypeAccess, UnsafeClone,
|
||||||
};
|
};
|
||||||
use bevy_property::Properties;
|
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;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -150,66 +150,40 @@ pub struct FetchDrawContext;
|
||||||
// TODO: derive this impl
|
// TODO: derive this impl
|
||||||
impl<'a> FetchResource<'a> for FetchDrawContext {
|
impl<'a> FetchResource<'a> for FetchDrawContext {
|
||||||
type Item = DrawContext<'a>;
|
type Item = DrawContext<'a>;
|
||||||
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
fn borrow(resources: &Resources) {
|
||||||
resource_archetypes
|
resources.borrow_mut::<Assets<PipelineDescriptor>>();
|
||||||
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
|
resources.borrow_mut::<Assets<Shader>>();
|
||||||
.unwrap()
|
resources.borrow_mut::<PipelineCompiler>();
|
||||||
.borrow_mut::<Assets<PipelineDescriptor>>();
|
resources.borrow::<Box<dyn RenderResourceContext>>();
|
||||||
resource_archetypes
|
resources.borrow::<VertexBufferDescriptors>();
|
||||||
.get(&TypeId::of::<Assets<Shader>>())
|
resources.borrow::<SharedBuffers>();
|
||||||
.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 release(resource_archetypes: &HashMap<TypeId, Archetype>) {
|
fn release(resources: &Resources) {
|
||||||
resource_archetypes
|
resources.release_mut::<Assets<PipelineDescriptor>>();
|
||||||
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
|
resources.release_mut::<Assets<Shader>>();
|
||||||
.unwrap()
|
resources.release_mut::<PipelineCompiler>();
|
||||||
.release_mut::<Assets<PipelineDescriptor>>();
|
resources.release::<Box<dyn RenderResourceContext>>();
|
||||||
resource_archetypes
|
resources.release::<VertexBufferDescriptors>();
|
||||||
.get(&TypeId::of::<Assets<Shader>>())
|
resources.release::<SharedBuffers>();
|
||||||
.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>();
|
|
||||||
}
|
}
|
||||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||||
DrawContext {
|
DrawContext {
|
||||||
pipelines: resources.get_res_mut::<Assets<PipelineDescriptor>>(),
|
pipelines: ResMut::new(
|
||||||
shaders: resources.get_res_mut::<Assets<Shader>>(),
|
resources.get_unsafe_ref::<Assets<PipelineDescriptor>>(ResourceIndex::Global),
|
||||||
pipeline_compiler: resources.get_res_mut::<PipelineCompiler>(),
|
),
|
||||||
render_resource_context: resources.get_res::<Box<dyn RenderResourceContext>>(),
|
shaders: ResMut::new(resources.get_unsafe_ref::<Assets<Shader>>(ResourceIndex::Global)),
|
||||||
vertex_buffer_descriptors: resources.get_res::<VertexBufferDescriptors>(),
|
pipeline_compiler: ResMut::new(
|
||||||
shared_buffers: resources.get_res::<SharedBuffers>(),
|
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,
|
current_pipeline: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ impl Node for PassNode {
|
||||||
|
|
||||||
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
|
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
|
||||||
if self.default_clear_color_inputs.contains(&i) {
|
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);
|
color_attachment.ops.load = LoadOp::Clear(default_clear_color.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn winit_runner(mut app: App) {
|
||||||
ControlFlow::Poll
|
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() {
|
if app_exit_event_reader.latest(&app_exit_events).is_some() {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue