2020-08-22 14:41:36 +00:00
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
use std::iter::Iterator;
|
|
|
|
|
2020-12-10 00:10:45 +00:00
|
|
|
use crate::componentmap::{
|
2021-03-21 20:34:53 +00:00
|
|
|
AccessError,
|
|
|
|
Ref as ComponentMapRef,
|
|
|
|
RefMut as ComponentMapRefMut,
|
2020-12-10 00:10:45 +00:00
|
|
|
ComponentMap,
|
|
|
|
ComponentMapIter,
|
|
|
|
ComponentMapIterMut,
|
|
|
|
};
|
2021-03-21 16:12:58 +00:00
|
|
|
use crate::globalmap::{
|
|
|
|
GlobalMap,
|
|
|
|
GlobalRef,
|
|
|
|
GlobalRefMut,
|
2021-01-13 23:10:48 +00:00
|
|
|
};
|
2020-08-22 14:41:36 +00:00
|
|
|
use crate::entity;
|
|
|
|
use crate::component;
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub struct ReadComponent<'a, T: component::Component> {
|
2020-12-10 00:10:45 +00:00
|
|
|
world: &'a World,
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData<&'a T>,
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> ReadComponent<'a, T> {
|
|
|
|
pub fn iter(&self) -> ReadComponentIter<'a, T> {
|
2021-01-13 23:10:48 +00:00
|
|
|
let cm = self.world.components.get(&component::component_id::<T>());
|
2021-03-21 16:03:15 +00:00
|
|
|
ReadComponentIter {
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData,
|
2020-12-10 00:10:45 +00:00
|
|
|
iter: cm.map(|e| e.try_iter().unwrap() ),
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-21 20:34:53 +00:00
|
|
|
|
|
|
|
pub fn get(&self, e: entity::ID) -> Result<ComponentMapRef<'a, T>, AccessError> {
|
|
|
|
// TODO(q3k): fix the unwrap
|
|
|
|
let cm = self.world.components.get(&component::component_id::<T>()).unwrap();
|
|
|
|
unsafe {
|
|
|
|
cm.get(e)
|
|
|
|
}
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub struct ReadComponentIter<'a, T: component::Component> {
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData<&'a T>,
|
2020-12-10 00:10:45 +00:00
|
|
|
iter: Option<ComponentMapIter<'a>>,
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl <'a, T: component::Component> Iterator for ReadComponentIter<'a, T> {
|
2020-12-10 00:10:45 +00:00
|
|
|
type Item = (entity::ID, &'a T);
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2020-12-10 00:10:45 +00:00
|
|
|
if self.iter.is_none() {
|
2020-08-22 14:41:36 +00:00
|
|
|
return None;
|
|
|
|
}
|
2020-12-10 00:10:45 +00:00
|
|
|
match self.iter.as_mut().unwrap().iter.next() {
|
|
|
|
None => None,
|
|
|
|
Some((eid, component)) => {
|
|
|
|
let component = component.as_ref();
|
|
|
|
let component = unsafe { & *(component as *const (dyn component::Component) as *const T) };
|
|
|
|
Some((*eid, component))
|
|
|
|
},
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub struct ReadWriteComponent<'a, T: component::Component> {
|
2020-12-10 00:10:45 +00:00
|
|
|
world: &'a World,
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData<&'a T>,
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl<'a, T: component::Component> ReadWriteComponent<'a, T> {
|
|
|
|
pub fn iter_mut(&self) -> ReadWriteComponentIter<'a, T> {
|
2021-01-13 23:10:48 +00:00
|
|
|
let cm = self.world.components.get(&component::component_id::<T>());
|
2021-03-21 16:03:15 +00:00
|
|
|
ReadWriteComponentIter {
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData,
|
2020-12-10 00:10:45 +00:00
|
|
|
iter: cm.map(|e| e.try_iter_mut().unwrap() ),
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-21 20:34:53 +00:00
|
|
|
|
|
|
|
pub fn get_mut(&self, e: entity::ID) -> Result<ComponentMapRefMut<'a, T>, AccessError> {
|
|
|
|
// TODO(q3k): fix the unwrap
|
|
|
|
let cm = self.world.components.get(&component::component_id::<T>()).unwrap();
|
|
|
|
unsafe {
|
|
|
|
cm.get_mut(e)
|
|
|
|
}
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub struct ReadWriteComponentIter<'a, T: component::Component> {
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData<&'a T>,
|
2020-12-10 00:10:45 +00:00
|
|
|
iter: Option<ComponentMapIterMut<'a>>,
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
impl <'a, T: component::Component> Iterator for ReadWriteComponentIter<'a, T> {
|
2020-12-10 00:10:45 +00:00
|
|
|
type Item = (entity::ID, &'a mut T);
|
2020-08-22 14:41:36 +00:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2020-12-10 00:10:45 +00:00
|
|
|
if self.iter.is_none() {
|
2020-08-22 14:41:36 +00:00
|
|
|
return None;
|
|
|
|
}
|
2020-12-10 00:10:45 +00:00
|
|
|
match self.iter.as_mut().unwrap().iter.next() {
|
|
|
|
None => None,
|
|
|
|
Some((eid, component)) => {
|
|
|
|
let component = component.as_mut();
|
|
|
|
let component = unsafe { &mut *(component as *mut (dyn component::Component) as *mut T) };
|
|
|
|
Some((*eid, component))
|
|
|
|
},
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
pub struct ReadGlobal<'a, T: component::Global> {
|
2021-01-13 23:10:48 +00:00
|
|
|
world: &'a World,
|
|
|
|
phantom: PhantomData<&'a T>,
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
impl<'a, T: component::Global> ReadGlobal<'a, T> {
|
|
|
|
pub fn get(&self) -> GlobalRef<'a, T> {
|
|
|
|
self.world.globals.get::<T>().unwrap()
|
2021-03-21 15:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
pub struct ReadWriteGlobal<'a, T: component::Global> {
|
2021-03-21 15:45:43 +00:00
|
|
|
world: &'a World,
|
|
|
|
phantom: PhantomData<&'a T>,
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
impl<'a, T: component::Global> ReadWriteGlobal<'a, T> {
|
|
|
|
pub fn get(&self) -> GlobalRefMut<'a, T> {
|
|
|
|
self.world.globals.get_mut::<T>().unwrap()
|
2021-01-13 23:10:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-05 16:34:12 +00:00
|
|
|
/// ReadWriteAll gives access to all components/entities/globals within a world. Using it in a
|
|
|
|
/// system means that no other system can run in parallel, and limits performance. This should only
|
|
|
|
/// be used when absolutely necessary (eg. for scripting systems).
|
|
|
|
pub struct ReadWriteAll<'a> {
|
|
|
|
world: &'a World,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ReadWriteAll<'a> {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-22 14:41:36 +00:00
|
|
|
pub struct World {
|
2020-12-10 00:10:45 +00:00
|
|
|
components: BTreeMap<component::ID, ComponentMap>,
|
2021-04-05 16:34:12 +00:00
|
|
|
component_by_idstr: BTreeMap<&'static str, component::ID>,
|
|
|
|
component_lua_bindings: BTreeMap<component::ID, Box<dyn component::LuaBindings>>,
|
2021-03-21 16:12:58 +00:00
|
|
|
globals: GlobalMap,
|
2020-08-22 14:41:36 +00:00
|
|
|
next_id: entity::ID,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl World {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
2020-12-10 00:10:45 +00:00
|
|
|
components: BTreeMap::new(),
|
2021-04-05 16:34:12 +00:00
|
|
|
component_by_idstr: BTreeMap::new(),
|
|
|
|
component_lua_bindings: BTreeMap::new(),
|
2021-03-21 16:12:58 +00:00
|
|
|
globals: GlobalMap::new(),
|
2020-08-22 14:41:36 +00:00
|
|
|
next_id: 1u64,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_entity(&mut self) -> entity::EntityBuilder {
|
|
|
|
let id = self.next_id;
|
|
|
|
self.next_id += 1;
|
|
|
|
entity::EntityBuilder::new(self, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn register_component_entity(
|
|
|
|
&mut self,
|
|
|
|
cid: component::ID,
|
|
|
|
c: Box<dyn component::Component>,
|
|
|
|
e: entity::Entity
|
|
|
|
) {
|
2021-04-05 16:34:12 +00:00
|
|
|
if let Some(bindings) = c.lua_bindings() {
|
|
|
|
// TODO(q3k): optimize this to not happen on every registration.
|
|
|
|
self.component_by_idstr.insert(bindings.id(), cid);
|
|
|
|
self.component_lua_bindings.insert(cid, bindings);
|
|
|
|
}
|
2021-04-04 20:35:03 +00:00
|
|
|
let map = self.components.entry(cid).or_insert_with(|| {
|
2021-04-05 16:34:12 +00:00
|
|
|
if let Some(bindings) = c.lua_bindings() {
|
|
|
|
log::info!("Registered component {}", bindings.id());
|
|
|
|
} else {
|
|
|
|
log::warn!("Component {:?} has no .lua_bindings() defined, will not be accessible from scripting.", cid);
|
2021-04-04 20:35:03 +00:00
|
|
|
}
|
|
|
|
ComponentMap::new()
|
|
|
|
});
|
2020-12-10 00:10:45 +00:00
|
|
|
map.insert(e.id(), c).unwrap();
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub fn components<'a, T: component::Component>(&'a self) -> ReadComponent<'a, T> {
|
|
|
|
ReadComponent {
|
2020-12-10 00:10:45 +00:00
|
|
|
world: self,
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:03:15 +00:00
|
|
|
pub fn components_mut<'a, T: component::Component>(&'a self) -> ReadWriteComponent<'a, T> {
|
|
|
|
ReadWriteComponent {
|
2020-12-10 00:10:45 +00:00
|
|
|
world: self,
|
2020-08-22 14:41:36 +00:00
|
|
|
phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
2021-01-13 23:10:48 +00:00
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
pub fn global<'a, T: component::Global>(&'a self) -> ReadGlobal<'a, T> {
|
|
|
|
ReadGlobal {
|
2021-01-13 23:10:48 +00:00
|
|
|
world: self,
|
|
|
|
phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
pub fn global_mut<'a, T: component::Global>(&'a self) -> ReadWriteGlobal<'a, T> {
|
|
|
|
ReadWriteGlobal {
|
2021-03-21 15:45:43 +00:00
|
|
|
world: self,
|
|
|
|
phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-05 16:34:12 +00:00
|
|
|
pub fn all<'a>(&'a self) -> ReadWriteAll<'a> {
|
|
|
|
ReadWriteAll {
|
|
|
|
world: self,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:12:58 +00:00
|
|
|
pub fn set_global<T: component::Global>(&self, r: T) {
|
|
|
|
self.globals.set(r).unwrap();
|
2021-01-13 23:10:48 +00:00
|
|
|
}
|
2021-04-05 16:34:12 +00:00
|
|
|
|
|
|
|
pub fn lua_components(&self) -> &BTreeMap<component::ID, Box<dyn component::LuaBindings>> {
|
|
|
|
&self.component_lua_bindings
|
|
|
|
}
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::component;
|
|
|
|
use crate::world;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Position {
|
|
|
|
x: u32,
|
|
|
|
y: u32,
|
|
|
|
z: u32,
|
|
|
|
}
|
|
|
|
impl component::Component for Position {}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Name(String);
|
|
|
|
impl component::Component for Name {}
|
|
|
|
impl Name {
|
|
|
|
fn new(s: &str) -> Name {
|
|
|
|
Name(String::from(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn new_list() {
|
|
|
|
let mut world = world::World::new();
|
|
|
|
world.new_entity().with(Name::new("foo")).with(Position { x: 1, y: 2, z: 3 }).build();
|
|
|
|
world.new_entity().with(Name::new("bar")).with(Position { x: 4, y: 5, z: 6 }).build();
|
|
|
|
|
|
|
|
let mut named = world.components::<Name>().iter();
|
|
|
|
let mut named2 = world.components::<Name>().iter();
|
2020-10-16 21:20:08 +00:00
|
|
|
assert_eq!(String::from("foo"), (named.next().unwrap().1).0);
|
|
|
|
assert_eq!(String::from("foo"), (named2.next().unwrap().1).0);
|
|
|
|
assert_eq!(String::from("bar"), (named.next().unwrap().1).0);
|
|
|
|
assert_eq!(String::from("bar"), (named2.next().unwrap().1).0);
|
2020-08-22 14:41:36 +00:00
|
|
|
}
|
|
|
|
}
|