lib/ecs: implement ReadWriteResource
parent
517db87c62
commit
d8062733e9
|
@ -7,7 +7,12 @@ pub mod system;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
pub use component::Component as Component;
|
pub use component::Component as Component;
|
||||||
|
pub use component::Resource as Resource;
|
||||||
pub use world::World as World;
|
pub use world::World as World;
|
||||||
pub use world::ReadData as ReadData;
|
pub use world::ReadData as ReadData;
|
||||||
|
pub use world::ReadWriteData as ReadWriteData;
|
||||||
|
pub use world::ReadResource as ReadResource;
|
||||||
|
pub use world::ReadWriteResource as ReadWriteResource;
|
||||||
pub use system::System as System;
|
pub use system::System as System;
|
||||||
pub use system::Join as Join;
|
pub use system::Join as Join;
|
||||||
|
pub use system::Processor as Processor;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Deref;
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use crate::component;
|
use crate::component;
|
||||||
use crate::borrow;
|
use crate::borrow;
|
||||||
|
@ -45,9 +45,35 @@ impl ResourceMap {
|
||||||
None => Err(AccessError::concurrent()),
|
None => Err(AccessError::concurrent()),
|
||||||
Some(b2) => {
|
Some(b2) => {
|
||||||
let val = val.as_ref();
|
let val = val.as_ref();
|
||||||
let val = unsafe { & *(val as *const (dyn component::Resource) as *const T) };
|
let val = & *(val as *const (dyn component::Resource) as *const T);
|
||||||
drop(b);
|
drop(b);
|
||||||
Ok(ResourceRef { val, borrow: b2 })
|
Ok(ResourceRef { val, borrow: Some(b2) })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => Err(AccessError("resource absent from world".to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut<'a, T: component::Resource>(&'a self) -> Result<ResourceRefMut<'a, T>, AccessError> {
|
||||||
|
match borrow::RefMut::new(&self.borrow) {
|
||||||
|
None => Err(AccessError::concurrent()),
|
||||||
|
Some(b) => {
|
||||||
|
let map = self.value.get();
|
||||||
|
unsafe {
|
||||||
|
match (*map).get_mut(&component::resource_id::<T>()) {
|
||||||
|
Some(entry) => {
|
||||||
|
let val = &mut entry.resource;
|
||||||
|
match borrow::RefMut::new(&entry.borrow) {
|
||||||
|
None => Err(AccessError::concurrent()),
|
||||||
|
Some(b2) => {
|
||||||
|
let val = val.as_mut();
|
||||||
|
let val = &mut *(val as *mut (dyn component::Resource) as *mut T);
|
||||||
|
drop(b);
|
||||||
|
Ok(ResourceRefMut { val, borrow: Some(b2) })
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -92,7 +118,7 @@ impl ResourceMap {
|
||||||
|
|
||||||
pub struct ResourceRef<'a, T: component::Resource> {
|
pub struct ResourceRef<'a, T: component::Resource> {
|
||||||
val: *const T,
|
val: *const T,
|
||||||
borrow: borrow::Ref<'a>,
|
borrow: Option<borrow::Ref<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: component::Resource> Deref for ResourceRef<'a, T> {
|
impl<'a, T: component::Resource> Deref for ResourceRef<'a, T> {
|
||||||
|
@ -104,3 +130,37 @@ impl<'a, T: component::Resource> Deref for ResourceRef<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'a, T: component::Resource> Drop for ResourceRef<'a, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.borrow = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ResourceRefMut<'a, T: component::Resource> {
|
||||||
|
val: *mut T,
|
||||||
|
borrow: Option<borrow::RefMut<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, T: component::Resource> Drop for ResourceRefMut<'a, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.borrow = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, T: component::Resource> Deref for ResourceRefMut<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
unsafe {
|
||||||
|
&(*self.val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, T: component::Resource> DerefMut for ResourceRefMut<'a, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
unsafe {
|
||||||
|
&mut(*self.val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
world::{
|
world::{
|
||||||
ReadData, ReadDataIter,
|
ReadData, ReadDataIter,
|
||||||
ReadWriteData, ReadWriteDataIter,
|
ReadWriteData, ReadWriteDataIter,
|
||||||
ReadResource,
|
ReadResource, ReadWriteResource,
|
||||||
World,
|
World,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -75,6 +75,12 @@ impl<'a, T: component::Resource> Access<'a> for ReadResource<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: component::Resource> Access<'a> for ReadWriteResource<'a, T> {
|
||||||
|
fn fetch(world: &'a World) -> Self {
|
||||||
|
world.resource_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl <'a,
|
impl <'a,
|
||||||
T: Access<'a>,
|
T: Access<'a>,
|
||||||
U: Access<'a>,
|
U: Access<'a>,
|
||||||
|
@ -101,12 +107,34 @@ impl <'a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'a,
|
||||||
|
T: Access<'a>,
|
||||||
|
U: Access<'a>,
|
||||||
|
V: Access<'a>,
|
||||||
|
W: Access<'a>,
|
||||||
|
> Access<'a> for (T, U, V, W) {
|
||||||
|
fn fetch(world: &'a World) -> Self {
|
||||||
|
(
|
||||||
|
T::fetch(world),
|
||||||
|
U::fetch(world),
|
||||||
|
V::fetch(world),
|
||||||
|
W::fetch(world),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Processor<'a> {
|
pub struct Processor<'a> {
|
||||||
world: &'a World,
|
world: &'a World,
|
||||||
runners: Vec<Box<dyn WorldRunner<'a>>>,
|
runners: Vec<Box<dyn WorldRunner<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Processor<'a> {
|
impl<'a> Processor<'a> {
|
||||||
|
pub fn new(world: &'a World) -> Self {
|
||||||
|
Self {
|
||||||
|
world,
|
||||||
|
runners: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn add_system<T: System<'a> + 'static>(&mut self, system: T) {
|
pub fn add_system<T: System<'a> + 'static>(&mut self, system: T) {
|
||||||
self.runners.push(Box::new(system));
|
self.runners.push(Box::new(system));
|
||||||
}
|
}
|
||||||
|
@ -172,13 +200,19 @@ mod test {
|
||||||
component::Resource,
|
component::Resource,
|
||||||
system,
|
system,
|
||||||
system::Join,
|
system::Join,
|
||||||
world::{ReadData, ReadWriteData, ReadResource, World},
|
world::{ReadData, ReadWriteData, ReadResource, ReadWriteResource, World},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone,Debug,Default)]
|
#[derive(Clone,Debug,Default)]
|
||||||
struct Delta(f32);
|
struct Delta(f32);
|
||||||
impl Resource for Delta {}
|
impl Resource for Delta {}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
struct PhysicsStatus {
|
||||||
|
object_count: u64,
|
||||||
|
}
|
||||||
|
impl Resource for PhysicsStatus {}
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
struct Position {
|
struct Position {
|
||||||
x: f32,
|
x: f32,
|
||||||
|
@ -199,15 +233,19 @@ mod test {
|
||||||
impl<'a> system::System<'a> for Physics {
|
impl<'a> system::System<'a> for Physics {
|
||||||
type SystemData = ( ReadWriteData<'a, Position>
|
type SystemData = ( ReadWriteData<'a, Position>
|
||||||
, ReadData<'a, Velocity>
|
, ReadData<'a, Velocity>
|
||||||
, ReadResource<'a, Delta>);
|
, ReadResource<'a, Delta>
|
||||||
|
, ReadWriteResource<'a, PhysicsStatus>);
|
||||||
|
|
||||||
fn run(&mut self, (pos, vel, delta): Self::SystemData) {
|
fn run(&mut self, (pos, vel, delta, status): Self::SystemData) {
|
||||||
let d = delta.get();
|
let d = delta.get();
|
||||||
|
let mut count = 0u64;
|
||||||
for (mut p, v) in (pos, vel).join_all() {
|
for (mut p, v) in (pos, vel).join_all() {
|
||||||
p.x += v.x * d.0;
|
p.x += v.x * d.0;
|
||||||
p.y += v.y * d.0;
|
p.y += v.y * d.0;
|
||||||
p.z += v.z * d.0;
|
p.z += v.z * d.0;
|
||||||
|
count += 1;
|
||||||
}
|
}
|
||||||
|
status.get().object_count = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +255,7 @@ mod test {
|
||||||
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 1.0 }).with(Position { x: 1.0, y: 2.0, z: 3.0 }).build();
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 1.0 }).with(Position { x: 1.0, y: 2.0, z: 3.0 }).build();
|
||||||
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 2.0 }).with(Position { x: 4.0, y: 5.0, z: 6.0 }).build();
|
world.new_entity().with(Velocity { x: 0.0, y: 0.0, z: 2.0 }).with(Position { x: 4.0, y: 5.0, z: 6.0 }).build();
|
||||||
world.set_resource(Delta(1.0));
|
world.set_resource(Delta(1.0));
|
||||||
|
world.set_resource(PhysicsStatus { object_count: 0u64 });
|
||||||
|
|
||||||
let mut p = system::Processor {
|
let mut p = system::Processor {
|
||||||
world: &world,
|
world: &world,
|
||||||
|
@ -231,5 +270,6 @@ mod test {
|
||||||
world.set_resource(Delta(2.0));
|
world.set_resource(Delta(2.0));
|
||||||
p.run();
|
p.run();
|
||||||
assert_eq!(vec![6.0, 12.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
assert_eq!(vec![6.0, 12.0], positions.iter().map(|(_, el)| el.z).collect::<Vec<f32>>());
|
||||||
|
assert_eq!(2, world.resource::<PhysicsStatus>().get().object_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
use std::cell::{Ref, RefMut, RefCell};
|
|
||||||
|
|
||||||
use crate::componentmap::{
|
use crate::componentmap::{
|
||||||
ComponentMap,
|
ComponentMap,
|
||||||
|
@ -11,6 +10,7 @@ use crate::componentmap::{
|
||||||
use crate::resourcemap::{
|
use crate::resourcemap::{
|
||||||
ResourceMap,
|
ResourceMap,
|
||||||
ResourceRef,
|
ResourceRef,
|
||||||
|
ResourceRefMut,
|
||||||
};
|
};
|
||||||
use crate::entity;
|
use crate::entity;
|
||||||
use crate::component;
|
use crate::component;
|
||||||
|
@ -98,7 +98,18 @@ pub struct ReadResource<'a, T: component::Resource> {
|
||||||
|
|
||||||
impl<'a, T: component::Resource> ReadResource<'a, T> {
|
impl<'a, T: component::Resource> ReadResource<'a, T> {
|
||||||
pub fn get(&self) -> ResourceRef<'a, T> {
|
pub fn get(&self) -> ResourceRef<'a, T> {
|
||||||
self.world.resources.get::<'a, T>().unwrap()
|
self.world.resources.get::<T>().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ReadWriteResource<'a, T: component::Resource> {
|
||||||
|
world: &'a World,
|
||||||
|
phantom: PhantomData<&'a T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: component::Resource> ReadWriteResource<'a, T> {
|
||||||
|
pub fn get(&self) -> ResourceRefMut<'a, T> {
|
||||||
|
self.world.resources.get_mut::<T>().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +165,13 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resource_mut<'a, T: component::Resource>(&'a self) -> ReadWriteResource<'a, T> {
|
||||||
|
ReadWriteResource {
|
||||||
|
world: self,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_resource<T: component::Resource>(&self, r: T) {
|
pub fn set_resource<T: component::Resource>(&self, r: T) {
|
||||||
self.resources.set(r).unwrap();
|
self.resources.set(r).unwrap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue