Update 2024 & move ecs out of engine

This commit is contained in:
Michael Hübner 2025-02-26 08:39:19 +01:00
parent b773002bdd
commit 22662557ba
35 changed files with 428 additions and 436 deletions

View file

@ -21,7 +21,7 @@ members = [
"map", "map",
"rpg_components", "rpg_components",
"entity_manager", "entity_manager",
"character_window", "character_window", "ecs",
] ]
[workspace.dependencies] [workspace.dependencies]

View file

@ -2,7 +2,7 @@
name = "config_handler" name = "config_handler"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -2,7 +2,7 @@
name = "networking" name = "networking"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -19,5 +19,5 @@ trust-dns-resolver = { workspace = true, optional = true }
[features] [features]
local_ip = ["if-addrs"] local_ip = ["if-addrs"]
public_ip = ["public-ip", "async-std"] public_ip = ["async-std", "public-ip"]
resolve_dns = ["trust-dns-resolver"] resolve_dns = ["trust-dns-resolver"]

View file

@ -1,7 +1,7 @@
[package] [package]
name = "asset" name = "asset"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,7 +1,7 @@
[package] [package]
name = "character_window" name = "character_window"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "context" name = "context"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <superschneider@t-online.de>"] authors = ["hodasemi <superschneider@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
utilities = { workspace = true } utilities = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "controllable_thread" name = "controllable_thread"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

18
ecs/Cargo.toml Normal file
View file

@ -0,0 +1,18 @@
[package]
name = "ecs"
version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2024"
[dependencies]
anyhow.workspace = true
destructure_traitobject.workspace = true
indexmap.workspace = true
serde = { workspace = true, features = ["derive"] }
paste.workspace = true
ron.workspace = true
scene_update_macros = { path = "../scene_update_macros" }
[features]
timings = []

View file

@ -1,24 +1,14 @@
use crate::prelude::*;
use core::fmt; use core::fmt;
use std::any::TypeId; use std::any::TypeId;
use std::cmp::Ordering;
use std::{num::ParseIntError, str::FromStr}; use std::{num::ParseIntError, str::FromStr};
use anyhow::Result; use anyhow::Result;
use serde::{Deserialize, Serialize};
use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap};
pub const COMPONENT_SEPARATOR: char = '§'; pub const COMPONENT_SEPARATOR: char = '§';
// Used for serialisation over network
#[derive(Serialize, Deserialize)]
pub struct EntityCreateInfo {
gltf_file: Option<String>,
network_id: Option<NetworkID>,
ignore_transactions: bool,
}
impl ComponentCreateInfo<'_> for EntityCreateInfo {}
#[derive(Default)] #[derive(Default)]
pub struct ActivationState { pub struct ActivationState {
activated: bool, activated: bool,
@ -34,7 +24,7 @@ impl ActivationState {
} }
} }
pub struct EntityObject { pub struct EntityObject<S> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub debug_name: Option<String>, pub debug_name: Option<String>,
@ -48,16 +38,16 @@ pub struct EntityObject {
pub entity_id: u32, pub entity_id: u32,
// component map // component map
pub(crate) components: TypeMap, pub(crate) components: TypeMap<S>,
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
component_names: Vec<String>, component_names: Vec<String>,
} }
unsafe impl Send for EntityObject {} unsafe impl<S> Send for EntityObject<S> {}
unsafe impl Sync for EntityObject {} unsafe impl<S> Sync for EntityObject<S> {}
impl EntityObject { impl<S> EntityObject<S> {
pub(crate) fn new(id: u32) -> Self { pub(crate) fn new(id: u32) -> Self {
Self { Self {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -80,11 +70,11 @@ impl EntityObject {
self.gltf_file.as_ref() self.gltf_file.as_ref()
} }
pub fn multi_mut(&mut self) -> MultiMut<'_> { pub fn multi_mut(&mut self) -> MultiMut<'_, S> {
self.components.multi_mut() self.components.multi_mut()
} }
pub fn insert_component<T: EntityComponent + ComponentDebug>( pub fn insert_component<T: EntityComponent<S> + ComponentDebug>(
&mut self, &mut self,
component: T, component: T,
) -> Option<T> { ) -> Option<T> {
@ -108,8 +98,11 @@ impl EntityObject {
pub(crate) fn insert_component_by_id( pub(crate) fn insert_component_by_id(
&mut self, &mut self,
type_id: TypeId, type_id: TypeId,
component: Box<dyn EntityComponent>, component: Box<dyn EntityComponent<S>>,
) -> Option<Box<dyn EntityComponent>> { ) -> Option<Box<dyn EntityComponent<S>>>
where
S: 'static,
{
assert!( assert!(
!self.activation_state.is_active(), !self.activation_state.is_active(),
"inserting components while the entity is activated is not allowed" "inserting components while the entity is activated is not allowed"
@ -127,7 +120,7 @@ impl EntityObject {
self.components.insert_type(type_id, component) self.components.insert_type(type_id, component)
} }
pub fn remove_component<T: EntityComponent>(&mut self) -> Option<T> { pub fn remove_component<T: EntityComponent<S>>(&mut self) -> Option<T> {
assert!( assert!(
!self.activation_state.is_active(), !self.activation_state.is_active(),
"removing components while the entity is activated is not allowed" "removing components while the entity is activated is not allowed"
@ -152,7 +145,10 @@ impl EntityObject {
pub(crate) fn remove_component_by_id( pub(crate) fn remove_component_by_id(
&mut self, &mut self,
type_id: TypeId, type_id: TypeId,
) -> Option<Box<dyn EntityComponent>> { ) -> Option<Box<dyn EntityComponent<S>>>
where
S: 'static,
{
assert!( assert!(
!self.activation_state.is_active(), !self.activation_state.is_active(),
"removing components while the entity is activated is not allowed" "removing components while the entity is activated is not allowed"
@ -179,19 +175,19 @@ impl EntityObject {
&self.component_names &self.component_names
} }
pub fn get_component<T: EntityComponent + ComponentDebug>( pub fn get_component<T: EntityComponent<S> + ComponentDebug>(
&self, &self,
) -> std::result::Result<&T, ComponentNotFoundError> { ) -> std::result::Result<&T, ComponentNotFoundError> {
self.components.get() self.components.get()
} }
pub fn get_component_mut<T: EntityComponent + ComponentDebug>( pub fn get_component_mut<T: EntityComponent<S> + ComponentDebug>(
&mut self, &mut self,
) -> std::result::Result<&mut T, ComponentNotFoundError> { ) -> std::result::Result<&mut T, ComponentNotFoundError> {
self.components.get_mut() self.components.get_mut()
} }
pub fn contains_component<T: EntityComponent>(&self) -> bool { pub fn contains_component<T: EntityComponent<S>>(&self) -> bool {
self.components.contains::<T>() self.components.contains::<T>()
} }
@ -203,7 +199,7 @@ impl EntityObject {
Entity { id: self.entity_id } Entity { id: self.entity_id }
} }
pub fn clone_without_components(&self, engine: &Engine) -> EntityObject { pub(crate) fn clone_without_components(&self, id: u32) -> EntityObject<S> {
EntityObject { EntityObject {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
debug_name: self.debug_name.clone(), debug_name: self.debug_name.clone(),
@ -213,17 +209,17 @@ impl EntityObject {
activation_state: Default::default(), activation_state: Default::default(),
entity_id: engine.assets().get_entity_id(), entity_id: id,
// component map // component map
components: TypeMap::new(), components: TypeMap::default(),
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
component_names: Vec::new(), component_names: Vec::new(),
} }
} }
pub fn clone_component_from<T: EntityComponent + ComponentDebug + Clone>( pub fn clone_component_from<T: EntityComponent<S> + ComponentDebug + Clone>(
&mut self, &mut self,
other: &Self, other: &Self,
) -> Result<()> { ) -> Result<()> {
@ -240,8 +236,8 @@ pub struct Entity {
pub(crate) id: u32, pub(crate) id: u32,
} }
impl PartialEq<EntityObject> for Entity { impl<S> PartialEq<EntityObject<S>> for Entity {
fn eq(&self, entity: &EntityObject) -> bool { fn eq(&self, entity: &EntityObject<S>) -> bool {
self.id == entity.entity_id self.id == entity.entity_id
} }
} }
@ -265,77 +261,3 @@ impl FromStr for Entity {
Ok(Self { id: s.parse()? }) Ok(Self { id: s.parse()? })
} }
} }
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct NetworkID {
pub(crate) id: u32,
}
impl NetworkID {
pub fn display_vector(v: &Vec<Self>) -> String {
// add starting bracket
let mut s = String::from("[");
for id in v {
s += &format!("{},", id.id);
}
// remove last comma
s.pop();
// add closing bracket
s += "]";
s
}
pub fn from_opt(me: Option<Self>) -> String {
match me {
Some(nid) => format!("Some({})", nid),
None => "None".to_string(),
}
}
pub fn try_opt(s: &str) -> Result<Option<Self>> {
Ok(if s == "None" {
None
} else {
if !s.starts_with("Some") {
panic!("unexpected string when parsing Option<NetworkID>: {}", s);
}
let tmp = s
.trim_start_matches("Some")
.trim_start_matches('(')
.trim_end_matches(')');
Some(tmp.parse()?)
})
}
}
impl fmt::Display for NetworkID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.id)
}
}
impl FromStr for NetworkID {
type Err = ParseIntError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(Self { id: s.parse()? })
}
}
impl Ord for NetworkID {
fn cmp(&self, other: &Self) -> Ordering {
self.id.cmp(&other.id)
}
}
impl PartialOrd for NetworkID {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

View file

@ -5,20 +5,25 @@ use std::{
ops::DerefMut, ops::DerefMut,
}; };
use crate::prelude::SceneContents; pub struct Events<C> {
#[derive(Default)]
pub struct Events {
events: HashMap< events: HashMap<
TypeId, TypeId,
( (
Vec<Box<dyn Any + Send + Sync>>, Vec<Box<dyn Any + Send + Sync>>,
Vec<Box<dyn Fn(&mut SceneContents<'_>, &dyn Any) -> anyhow::Result<()> + Send + Sync>>, Vec<Box<dyn Fn(&mut C, &dyn Any) -> anyhow::Result<()> + Send + Sync>>,
), ),
>, >,
} }
impl Events { impl<C> Default for Events<C> {
fn default() -> Self {
Self {
events: HashMap::new(),
}
}
}
impl<C> Events<C> {
pub(crate) fn clone_from_register(&self) -> Self { pub(crate) fn clone_from_register(&self) -> Self {
Self { Self {
events: self events: self
@ -54,13 +59,13 @@ impl Events {
pub fn add_reader<T: Any + Send + Sync, F>(&mut self, f: F) pub fn add_reader<T: Any + Send + Sync, F>(&mut self, f: F)
where where
F: Fn(&mut SceneContents<'_>, &T) -> anyhow::Result<()> + Send + Sync + 'static, F: Fn(&mut C, &T) -> anyhow::Result<()> + Send + Sync + 'static,
{ {
match self.events.get_mut(&TypeId::of::<T>()) { match self.events.get_mut(&TypeId::of::<T>()) {
Some((_, listener)) => listener.push(Box::new(move |scene, payload| { Some((_, listener)) => listener.push(Box::new(move |c, payload| {
let typed_payload: &T = payload.downcast_ref().unwrap(); let typed_payload: &T = payload.downcast_ref().unwrap();
f(scene, typed_payload) f(c, typed_payload)
})), })),
None => panic!("register event type first!"), None => panic!("register event type first!"),
} }
@ -73,11 +78,11 @@ impl Events {
} }
} }
pub(crate) fn fire_events(&mut self, scene: &mut SceneContents<'_>) -> anyhow::Result<()> { pub(crate) fn fire_events(&mut self, c: &mut C) -> anyhow::Result<()> {
for (payloads, listeners) in self.events.values_mut() { for (payloads, listeners) in self.events.values_mut() {
for payload in payloads.iter_mut() { for payload in payloads.iter_mut() {
for listener in listeners.iter_mut() { for listener in listeners.iter_mut() {
(listener)(scene, payload.deref_mut())?; (listener)(c, payload.deref_mut())?;
} }
} }

17
ecs/src/lib.rs Normal file
View file

@ -0,0 +1,17 @@
mod entity;
mod events;
mod resources;
mod type_map;
mod unsafe_component_store;
mod updates;
mod world;
pub use crate::entity::{Entity, EntityObject};
pub use crate::events::Events;
pub use crate::resources::{ResourceMultiMut, Resources};
pub use crate::type_map::{
ComponentCreateInfo, ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap,
};
pub use crate::unsafe_component_store::UnsafeComponentStore;
pub use crate::updates::*;
pub use crate::world::World;

View file

@ -2,8 +2,8 @@ use std::mem::transmute;
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
collections::{ collections::{
hash_map::{Iter, IterMut},
HashMap, HashMap,
hash_map::{Iter, IterMut},
}, },
fmt::Display, fmt::Display,
}; };
@ -12,14 +12,12 @@ use anyhow::Result;
use destructure_traitobject; use destructure_traitobject;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::prelude::*; pub trait EntityComponent<S>: Any + Send + Sync {
fn enable(&mut self, _scene: &mut S) -> Result<()> {
pub trait EntityComponent: Any + Send + Sync {
fn enable(&mut self, _scene: &mut Scene) -> Result<()> {
Ok(()) Ok(())
} }
fn disable(&mut self, _scene: &mut Scene) -> Result<()> { fn disable(&mut self, _scene: &mut S) -> Result<()> {
Ok(()) Ok(())
} }
@ -47,19 +45,20 @@ pub trait ComponentCreateInfo<'de>: Serialize + Deserialize<'de> {
} }
} }
#[derive(Default)] pub struct TypeMap<S> {
pub struct TypeMap { map: HashMap<TypeId, Box<dyn EntityComponent<S>>>,
map: HashMap<TypeId, Box<dyn EntityComponent>>,
} }
impl TypeMap { impl<S> Default for TypeMap<S> {
pub fn new() -> Self { fn default() -> Self {
TypeMap { Self {
map: HashMap::new(), map: HashMap::new(),
} }
} }
}
pub fn insert<T: EntityComponent + ComponentDebug>(&mut self, value: T) -> Option<T> { impl<S> TypeMap<S> {
pub fn insert<T: EntityComponent<S> + ComponentDebug>(&mut self, value: T) -> Option<T> {
self.map self.map
.insert(TypeId::of::<T>(), Box::new(value)) .insert(TypeId::of::<T>(), Box::new(value))
.map(|any| *Self::downcast_unchecked(any)) .map(|any| *Self::downcast_unchecked(any))
@ -68,21 +67,21 @@ impl TypeMap {
pub fn insert_type( pub fn insert_type(
&mut self, &mut self,
type_id: TypeId, type_id: TypeId,
component: Box<dyn EntityComponent>, component: Box<dyn EntityComponent<S>>,
) -> Option<Box<dyn EntityComponent>> { ) -> Option<Box<dyn EntityComponent<S>>> {
self.map.insert(type_id, component) self.map.insert(type_id, component)
} }
pub fn remove<T: EntityComponent>(&mut self) -> Option<T> { pub fn remove<T: EntityComponent<S>>(&mut self) -> Option<T> {
self.remove_by_type_id(&TypeId::of::<T>()) self.remove_by_type_id(&TypeId::of::<T>())
.map(|any| *Self::downcast_unchecked(any)) .map(|any| *Self::downcast_unchecked(any))
} }
pub fn remove_by_type_id(&mut self, type_id: &TypeId) -> Option<Box<dyn EntityComponent>> { pub fn remove_by_type_id(&mut self, type_id: &TypeId) -> Option<Box<dyn EntityComponent<S>>> {
self.map.remove(type_id) self.map.remove(type_id)
} }
pub fn get<T: EntityComponent + ComponentDebug>( pub fn get<T: EntityComponent<S> + ComponentDebug>(
&self, &self,
) -> std::result::Result<&T, ComponentNotFoundError> { ) -> std::result::Result<&T, ComponentNotFoundError> {
self.map self.map
@ -94,13 +93,13 @@ impl TypeMap {
pub fn get_by_type_id( pub fn get_by_type_id(
&self, &self,
type_id: &TypeId, type_id: &TypeId,
) -> std::result::Result<&Box<dyn EntityComponent>, ComponentNotFoundError> { ) -> std::result::Result<&Box<dyn EntityComponent<S>>, ComponentNotFoundError> {
self.map self.map
.get(type_id) .get(type_id)
.ok_or_else(|| ComponentNotFoundError::type_id(*type_id)) .ok_or_else(|| ComponentNotFoundError::type_id(*type_id))
} }
pub fn get_mut<T: EntityComponent + ComponentDebug>( pub fn get_mut<T: EntityComponent<S> + ComponentDebug>(
&mut self, &mut self,
) -> std::result::Result<&mut T, ComponentNotFoundError> { ) -> std::result::Result<&mut T, ComponentNotFoundError> {
self.map self.map
@ -112,13 +111,13 @@ impl TypeMap {
pub fn get_mut_by_type_id( pub fn get_mut_by_type_id(
&mut self, &mut self,
type_id: &TypeId, type_id: &TypeId,
) -> std::result::Result<&mut Box<dyn EntityComponent>, ComponentNotFoundError> { ) -> std::result::Result<&mut Box<dyn EntityComponent<S>>, ComponentNotFoundError> {
self.map self.map
.get_mut(type_id) .get_mut(type_id)
.ok_or_else(|| ComponentNotFoundError::type_id(*type_id)) .ok_or_else(|| ComponentNotFoundError::type_id(*type_id))
} }
pub fn contains<T: EntityComponent>(&self) -> bool { pub fn contains<T: EntityComponent<S>>(&self) -> bool {
self.contains_type_id(&TypeId::of::<T>()) self.contains_type_id(&TypeId::of::<T>())
} }
@ -126,24 +125,24 @@ impl TypeMap {
self.map.contains_key(type_id) self.map.contains_key(type_id)
} }
pub fn multi_mut(&mut self) -> MultiMut<'_> { pub fn multi_mut(&mut self) -> MultiMut<'_, S> {
MultiMut::new(&mut self.map) MultiMut::new(&mut self.map)
} }
pub fn iter(&self) -> Iter<'_, TypeId, Box<dyn EntityComponent>> { pub fn iter(&self) -> Iter<'_, TypeId, Box<dyn EntityComponent<S>>> {
self.map.iter() self.map.iter()
} }
pub fn iter_mut(&mut self) -> IterMut<'_, TypeId, Box<dyn EntityComponent>> { pub fn iter_mut(&mut self) -> IterMut<'_, TypeId, Box<dyn EntityComponent<S>>> {
self.map.iter_mut() self.map.iter_mut()
} }
fn downcast_unchecked<T: EntityComponent>(boxed: Box<dyn EntityComponent>) -> Box<T> { fn downcast_unchecked<T: EntityComponent<S>>(boxed: Box<dyn EntityComponent<S>>) -> Box<T> {
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut T) } unsafe { Box::from_raw(Box::into_raw(boxed) as *mut T) }
} }
pub(crate) fn downcast_ref_unchecked<T: EntityComponent>( pub fn downcast_ref_unchecked<T: EntityComponent<S>>(
boxed_ref: &Box<dyn EntityComponent>, boxed_ref: &Box<dyn EntityComponent<S>>,
) -> &T { ) -> &T {
unsafe { unsafe {
let ptr_to_ptr: *const *const T = let ptr_to_ptr: *const *const T =
@ -153,8 +152,8 @@ impl TypeMap {
} }
} }
pub(crate) fn downcast_mut_unchecked<T: EntityComponent>( pub fn downcast_mut_unchecked<T: EntityComponent<S>>(
boxed_ref: &mut Box<dyn EntityComponent>, boxed_ref: &mut Box<dyn EntityComponent<S>>,
) -> &mut T { ) -> &mut T {
unsafe { unsafe {
let ptr_to_ptr: *mut *mut T = let ptr_to_ptr: *mut *mut T =
@ -166,13 +165,13 @@ impl TypeMap {
} }
/// Allows mutable access to multiple components at once /// Allows mutable access to multiple components at once
pub struct MultiMut<'a> { pub struct MultiMut<'a, S> {
map: &'a mut HashMap<TypeId, Box<dyn EntityComponent>>, map: &'a mut HashMap<TypeId, Box<dyn EntityComponent<S>>>,
buffer: Vec<*mut Box<dyn EntityComponent>>, buffer: Vec<*mut Box<dyn EntityComponent<S>>>,
} }
impl<'a> MultiMut<'a> { impl<'a, S> MultiMut<'a, S> {
fn new(map: &'a mut HashMap<TypeId, Box<dyn EntityComponent>>) -> Self { fn new(map: &'a mut HashMap<TypeId, Box<dyn EntityComponent<S>>>) -> Self {
MultiMut { MultiMut {
map, map,
buffer: Vec::new(), buffer: Vec::new(),
@ -180,7 +179,7 @@ impl<'a> MultiMut<'a> {
} }
/// Returns requested type on success /// Returns requested type on success
pub fn get<T: EntityComponent + ComponentDebug>( pub fn get<T: EntityComponent<S> + ComponentDebug>(
&mut self, &mut self,
) -> std::result::Result<&'a mut T, ComponentNotFoundError> { ) -> std::result::Result<&'a mut T, ComponentNotFoundError> {
self.get_by_type_id(&TypeId::of::<T>()) self.get_by_type_id(&TypeId::of::<T>())
@ -192,7 +191,7 @@ impl<'a> MultiMut<'a> {
pub fn get_by_type_id( pub fn get_by_type_id(
&mut self, &mut self,
type_id: &TypeId, type_id: &TypeId,
) -> std::result::Result<&'a mut Box<dyn EntityComponent>, ComponentNotFoundError> { ) -> std::result::Result<&'a mut Box<dyn EntityComponent<S>>, ComponentNotFoundError> {
match self.map.get_mut(type_id) { match self.map.get_mut(type_id) {
Some(v) => { Some(v) => {
let ptr = v as *mut _; let ptr = v as *mut _;
@ -206,7 +205,7 @@ impl<'a> MultiMut<'a> {
} }
} }
let t: Option<&'a mut Box<dyn EntityComponent>> = unsafe { transmute(ptr) }; let t: Option<&'a mut Box<dyn EntityComponent<S>>> = unsafe { transmute(ptr) };
t.ok_or_else(|| ComponentNotFoundError::type_id(*type_id)) t.ok_or_else(|| ComponentNotFoundError::type_id(*type_id))
} }
@ -262,7 +261,7 @@ struct Test {
z: u32, z: u32,
} }
impl EntityComponent for Test { impl<S> EntityComponent<S> for Test {
fn name(&self) -> &str { fn name(&self) -> &str {
"Test" "Test"
} }
@ -282,7 +281,7 @@ impl PartialEq for Test {
#[test] #[test]
fn verify_multi_mut() { fn verify_multi_mut() {
let mut map = TypeMap::new(); let mut map = TypeMap::<()>::default();
map.insert(Test::default()); map.insert(Test::default());
@ -300,7 +299,7 @@ fn verify_multi_mut() {
#[test] #[test]
fn verify_insert() { fn verify_insert() {
let mut map = TypeMap::new(); let mut map = TypeMap::<()>::default();
let reference = Test { x: 5, y: 20, z: 30 }; let reference = Test { x: 5, y: 20, z: 30 };
@ -312,7 +311,7 @@ fn verify_insert() {
#[test] #[test]
fn verify_get() { fn verify_get() {
let mut map = TypeMap::new(); let mut map = TypeMap::<()>::default();
let reference = Test { x: 5, y: 20, z: 30 }; let reference = Test { x: 5, y: 20, z: 30 };
@ -323,7 +322,7 @@ fn verify_get() {
#[test] #[test]
fn verify_get_mut() { fn verify_get_mut() {
let mut map = TypeMap::new(); let mut map = TypeMap::<()>::default();
let reference = Test { x: 5, y: 20, z: 30 }; let reference = Test { x: 5, y: 20, z: 30 };

View file

@ -27,7 +27,7 @@ impl<T> UnsafeComponentStore<T> {
"Called UnsafeComponentStore while being empty" "Called UnsafeComponentStore while being empty"
); );
self.ptr.as_mut().unwrap() unsafe { self.ptr.as_mut().unwrap() }
} }
pub fn is_init(&self) -> bool { pub fn is_init(&self) -> bool {

View file

@ -1,7 +1,6 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use std::any::TypeId; use std::any::TypeId;
use std::collections::HashMap;
use std::marker::PhantomData; use std::marker::PhantomData;
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
@ -13,19 +12,19 @@ use indexmap::IndexMap;
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
use super::super::timings::Timings; use super::super::timings::Timings;
use crate::prelude::*; use crate::*;
use scene_update_macros::implement_pair_update; use scene_update_macros::implement_pair_update;
macro_rules! impl_singleton_update { macro_rules! impl_singleton_update {
( $name: ident, $([$var: ident]$(,)?)+ ) => { ( $name: ident, $([$var: ident]$(,)?)+ ) => {
impl Archetype { impl<C> Archetype<C> {
paste::item! { paste::item! {
pub fn [<create_ $name>]<F, Filter, $($var,)+>(f: F, filter: Filter) -> Self pub fn [<create_ $name>]<F, Filter, $($var,)+>(f: F, filter: Filter) -> Self
where where
F: Fn(&mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static, F: Fn(&mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static, Filter: CheckFilter<C> + 'static,
$( $(
$var: EntityComponent + ComponentDebug, $var: EntityComponent<C> + ComponentDebug,
)+ )+
{ {
$( $(
@ -69,13 +68,13 @@ macro_rules! impl_singleton_update {
} }
} }
impl<Func, Filter, $( $var, )+> AddUpdates2<( $( $var, )+ ), Func, Filter> for Updates impl<C, Func, Filter, $( $var, )+> AddUpdates2<C, ( $( $var, )+ ), Func, Filter> for Updates<C>
where where
$( $(
$var: EntityComponent + ComponentDebug, $var: EntityComponent<C> + ComponentDebug,
)+ )+
Func: Fn(& mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static Filter: CheckFilter<C> + 'static
{ {
fn add_update( fn add_update(
&mut self, &mut self,
@ -83,7 +82,7 @@ macro_rules! impl_singleton_update {
priority: u32, priority: u32,
func: Func, func: Func,
filter: Filter, filter: Filter,
entities: &IndexMap<Entity, EntityObject> entities: &IndexMap<Entity, EntityObject<C>>
) -> Result<()> { ) -> Result<()> {
paste::item! { paste::item! {
self.add(name, priority, Update::Single(Archetype::[<create_ $name>](func, filter)), entities) self.add(name, priority, Update::Single(Archetype::[<create_ $name>](func, filter)), entities)
@ -91,13 +90,14 @@ macro_rules! impl_singleton_update {
} }
} }
impl<Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for Scene impl<C, Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for World<C>
where where
$( $(
$var: EntityComponent + ComponentDebug, $var: EntityComponent<C> + ComponentDebug,
)+ )+
Func: Fn(& mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static Filter: CheckFilter<C> + 'static,
C: Send + Sync
{ {
fn add_update( fn add_update(
&mut self, &mut self,
@ -110,25 +110,25 @@ macro_rules! impl_singleton_update {
} }
} }
impl Scene { // impl Scene {
paste::item! { // paste::item! {
pub fn [<add_ $name _archetype>]<F, Filter, $($var,)+>(&mut self, name: impl ToString, f: F, filter: Filter) -> Result<()> // pub fn [<add_ $name _archetype>]<F, Filter, $($var,)+>(&mut self, name: impl ToString, f: F, filter: Filter) -> Result<()>
where // where
F: Fn(&mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static, // F: Fn(&mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static, // Filter: CheckFilter + 'static,
$( // $(
$var: EntityComponent + ComponentDebug, // $var: EntityComponent + ComponentDebug,
)+ // )+
{ // {
let mut archetype = Archetype::[<create_ $name>](f, filter); // let mut archetype = Archetype::[<create_ $name>](f, filter);
archetype.setup(&self.entities)?; // archetype.setup(&self.entities)?;
self.archetypes.insert(name.to_string(), archetype); // self.archetypes.insert(name.to_string(), archetype);
Ok(()) // Ok(())
} // }
} // }
} // }
}; };
} }
@ -139,19 +139,19 @@ macro_rules! impl_pair_update {
$rhs_id: expr, $rhs_id: expr,
( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ ) ( $([$rhs_little: ident: $rhs_big: ident]$(,)?)+ )
) => { ) => {
impl ArchetypePair { impl<C> ArchetypePair<C> {
paste::item! { paste::item! {
pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+> pub fn [<create_lhs_ $lhs_id _rhs_ $rhs_id>] <F, LeftFilter, RightFilter, $($lhs_big,)+ $($rhs_big,)+>
(f: F, left_filter: LeftFilter, right_filter: RightFilter) -> Self (f: F, left_filter: LeftFilter, right_filter: RightFilter) -> Self
where where
F: Fn(&mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static, F: Fn(&mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
LeftFilter: CheckFilter + 'static, LeftFilter: CheckFilter<C> + 'static,
RightFilter: CheckFilter + 'static, RightFilter: CheckFilter<C> + 'static,
$( $(
$rhs_big: EntityComponent + ComponentDebug, $rhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
$( $(
$lhs_big: EntityComponent + ComponentDebug, $lhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
{ {
$( $(
@ -220,17 +220,17 @@ macro_rules! impl_pair_update {
} }
} }
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<C, ( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates<C>
where where
$( $(
$rhs_big: EntityComponent + ComponentDebug, $rhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
$( $(
$lhs_big: EntityComponent + ComponentDebug, $lhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static, LhsFilter: CheckFilter<C> + 'static,
RhsFilter: CheckFilter + 'static RhsFilter: CheckFilter<C> + 'static
{ {
fn add_update( fn add_update(
&mut self, &mut self,
@ -238,7 +238,7 @@ macro_rules! impl_pair_update {
priority: u32, priority: u32,
func: Func, func: Func,
filter: (LhsFilter, RhsFilter), filter: (LhsFilter, RhsFilter),
entities: &IndexMap<Entity, EntityObject> entities: &IndexMap<Entity, EntityObject<C>>
) -> Result<()> { ) -> Result<()> {
paste::item! { paste::item! {
self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func, filter.0, filter.1)), entities)?; self.add(name, priority, Update::Pair(ArchetypePair::[<create_lhs_ $lhs_id _rhs_ $rhs_id>](func, filter.0, filter.1)), entities)?;
@ -248,17 +248,18 @@ macro_rules! impl_pair_update {
} }
} }
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Scene impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for World<C>
where where
$( $(
$rhs_big: EntityComponent + ComponentDebug, $rhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
$( $(
$lhs_big: EntityComponent + ComponentDebug, $lhs_big: EntityComponent<C> + ComponentDebug,
)+ )+
Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static, Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
LhsFilter: CheckFilter + 'static, LhsFilter: CheckFilter<C> + 'static,
RhsFilter: CheckFilter + 'static RhsFilter: CheckFilter<C> + 'static,
C: Send + Sync
{ {
fn add_update( fn add_update(
&mut self, &mut self,
@ -271,47 +272,56 @@ macro_rules! impl_pair_update {
} }
} }
impl<Func, Filter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, Filter> for Scene // impl<Func, Filter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, Filter> for Scene
where // where
$( // $(
$rhs_big: EntityComponent + ComponentDebug, // $rhs_big: EntityComponent + ComponentDebug,
)+ // )+
$( // $(
$lhs_big: EntityComponent + ComponentDebug, // $lhs_big: EntityComponent + ComponentDebug,
)+ // )+
Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static, // Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
Filter: CheckFilter + 'static, // Filter: CheckFilter + 'static,
{ // {
fn add_update( // fn add_update(
&mut self, // &mut self,
name: &str, // name: &str,
priority: u32, // priority: u32,
func: Func, // func: Func,
filter: Filter, // filter: Filter,
) -> Result<()> { // ) -> Result<()> {
paste::item! { // paste::item! {
self.updates.add_update(name, priority, func, (filter.clone(), filter), &self.entities)?; // self.updates.add_update(name, priority, func, (filter.clone(), filter), &self.entities)?;
} // }
Ok(()) // Ok(())
} // }
} // }
}; };
} }
macro_rules! impl_update_filter { macro_rules! impl_update_filter {
( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => { ( $name: ident, $([$big: ident, $little: ident]$(,)?)+ ) => {
paste::item! { paste::item! {
pub struct [<$name Filter>]<$($big: EntityComponent,)+> pub struct [<$name Filter>]<C, $($big: EntityComponent<C>,)+>
where
C: Send + Sync
{ {
c: std::marker::PhantomData<C>,
$( $(
$little: std::marker::PhantomData<$big>, $little: std::marker::PhantomData<$big>,
)+ )+
} }
impl<$($big: EntityComponent,)+> Default for [<$name Filter>]<$($big,)+> { impl<C, $($big: EntityComponent<C>,)+> Default for [<$name Filter>]<C, $($big,)+>
where
C: Send + Sync
{
fn default() -> Self { fn default() -> Self {
Self { Self {
c: std::marker::PhantomData,
$( $(
$little: std::marker::PhantomData, $little: std::marker::PhantomData,
)+ )+
@ -319,8 +329,11 @@ macro_rules! impl_update_filter {
} }
} }
impl<$($big: EntityComponent,)+> CheckFilter for [<$name Filter>]<$($big,)+> { impl<C, $($big: EntityComponent<C>,)+> CheckFilter<C> for [<$name Filter>]<C, $($big,)+>
fn check(&self, entity: &EntityObject) -> bool { where
C: Send + Sync
{
fn check(&self, entity: &EntityObject<C>) -> bool {
$( $(
if entity.contains_component::<$big>() { if entity.contains_component::<$big>() {
return false; return false;
@ -330,7 +343,7 @@ macro_rules! impl_update_filter {
true true
} }
fn verify_dedup<O: EntityComponent>(&self) { fn verify_dedup<O: EntityComponent<C>>(&self) {
$( $(
if TypeId::of::<O>() == TypeId::of::<$big>() { if TypeId::of::<O>() == TypeId::of::<$big>() {
panic!("Type is used as input and filter at the same time"); panic!("Type is used as input and filter at the same time");
@ -339,9 +352,14 @@ macro_rules! impl_update_filter {
} }
} }
impl<$($big: EntityComponent,)+> Clone for [<$name Filter>]<$($big,)+> { impl<C, $($big: EntityComponent<C>,)+> Clone for [<$name Filter>]<C, $($big,)+>
where
C: Send + Sync
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
c: self.c.clone(),
$( $(
$little: self.$little.clone(), $little: self.$little.clone(),
)+ )+
@ -352,39 +370,41 @@ macro_rules! impl_update_filter {
}; };
} }
pub struct Query<T, F = EmptyFilter> pub struct Query<C, T, F = EmptyFilter>
where where
F: CheckFilter, F: CheckFilter<C>,
{ {
pub components: T, pub components: T,
d: PhantomData<F>, d: PhantomData<F>,
c: PhantomData<C>,
} }
pub trait AddUpdates<T, Func, Filter> { pub trait AddUpdates<T, Func, Filter> {
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>; fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
} }
trait AddUpdates2<T, Func, Filter> { trait AddUpdates2<C, T, Func, Filter> {
fn add_update( fn add_update(
&mut self, &mut self,
name: &str, name: &str,
priority: u32, priority: u32,
func: Func, func: Func,
filter: Filter, filter: Filter,
entities: &IndexMap<Entity, EntityObject>, entities: &IndexMap<Entity, EntityObject<C>>,
) -> Result<()>; ) -> Result<()>;
} }
pub trait CheckFilter: Send + Sync + Default + Clone { pub trait CheckFilter<C>: Send + Sync + Default + Clone {
fn check(&self, entity: &EntityObject) -> bool; fn check(&self, entity: &EntityObject<C>) -> bool;
fn verify_dedup<O: EntityComponent>(&self); fn verify_dedup<O: EntityComponent<C>>(&self);
} }
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct EmptyFilter; pub struct EmptyFilter;
impl CheckFilter for EmptyFilter { impl<C> CheckFilter<C> for EmptyFilter {
fn check(&self, _entity: &EntityObject) -> bool { fn check(&self, _entity: &EntityObject<C>) -> bool {
true true
} }
@ -410,23 +430,19 @@ impl ArchetypeInfo {
} }
} }
pub struct Archetype { pub struct Archetype<C> {
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>, check_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
create_callback: Box< create_callback: Box<
dyn Fn( dyn Fn(&EntityObject<C>) -> Result<Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>
&EntityObject,
)
-> Result<Box<dyn Fn(Entity, &mut SceneContents<'_>) -> Result<()> + Send + Sync>>
+ Send + Send
+ Sync, + Sync,
>, >,
entities: entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>,
IndexMap<Entity, Box<dyn Fn(Entity, &mut SceneContents<'_>) -> Result<()> + Send + Sync>>,
} }
impl Archetype { impl<C> Archetype<C> {
pub fn add_entity(&mut self, entity_object: &EntityObject) -> Result<()> { pub fn add_entity(&mut self, entity_object: &EntityObject<C>) -> Result<()> {
if (self.check_entity)(entity_object) { if (self.check_entity)(entity_object) {
let cb = (self.create_callback)(entity_object)?; let cb = (self.create_callback)(entity_object)?;
@ -440,7 +456,7 @@ impl Archetype {
self.entities.swap_remove(&entity); self.entities.swap_remove(&entity);
} }
pub fn execute(&self, scene_contents: &mut SceneContents<'_>) -> Result<()> { pub fn execute(&self, scene_contents: &mut C) -> Result<()> {
for (entity, callback) in self.entities.iter() { for (entity, callback) in self.entities.iter() {
callback(*entity, scene_contents)?; callback(*entity, scene_contents)?;
} }
@ -448,7 +464,7 @@ impl Archetype {
Ok(()) Ok(())
} }
pub fn setup(&mut self, entities: &IndexMap<Entity, EntityObject>) -> Result<()> { pub fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
for (entity, entity_object) in entities.iter() { for (entity, entity_object) in entities.iter() {
if (self.check_entity)(entity_object) { if (self.check_entity)(entity_object) {
let cb = (self.create_callback)(entity_object)?; let cb = (self.create_callback)(entity_object)?;
@ -462,37 +478,34 @@ impl Archetype {
pub(crate) fn entities( pub(crate) fn entities(
&self, &self,
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut SceneContents<'_>) -> Result<()> + Send + Sync>> ) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>> {
{
&self.entities &self.entities
} }
} }
pub struct ArchetypePair { pub struct ArchetypePair<C> {
check_left_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>, check_left_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
check_right_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>, check_right_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
create_callback: Box< create_callback: Box<
dyn Fn( dyn Fn(
&EntityObject, &EntityObject<C>,
&EntityObject, &EntityObject<C>,
) -> Result< )
Box<dyn Fn(Entity, Entity, &mut SceneContents<'_>) -> Result<()> + Send + Sync>, -> Result<Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>
> + Send + Send
+ Sync, + Sync,
>, >,
entities: IndexMap< entities:
(Entity, Entity), IndexMap<(Entity, Entity), Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>,
Box<dyn Fn(Entity, Entity, &mut SceneContents<'_>) -> Result<()> + Send + Sync>,
>,
} }
impl ArchetypePair { impl<C> ArchetypePair<C> {
pub(crate) fn add_entity( pub(crate) fn add_entity(
&mut self, &mut self,
entity_object: &EntityObject, entity_object: &EntityObject<C>,
entities: &IndexMap<Entity, EntityObject>, entities: &IndexMap<Entity, EntityObject<C>>,
) -> Result<()> { ) -> Result<()> {
for (other_entity, other_entity_object) in entities.iter() { for (other_entity, other_entity_object) in entities.iter() {
if entity_object.as_entity() == *other_entity { if entity_object.as_entity() == *other_entity {
@ -533,7 +546,7 @@ impl ArchetypePair {
} }
} }
pub(crate) fn execute(&self, scene_contents: &mut SceneContents<'_>) -> Result<()> { pub(crate) fn execute(&self, scene_contents: &mut C) -> Result<()> {
for ((left_entity, right_entity), callback) in self.entities.iter() { for ((left_entity, right_entity), callback) in self.entities.iter() {
callback(*left_entity, *right_entity, scene_contents)?; callback(*left_entity, *right_entity, scene_contents)?;
} }
@ -541,7 +554,7 @@ impl ArchetypePair {
Ok(()) Ok(())
} }
pub(crate) fn setup(&mut self, entities: &IndexMap<Entity, EntityObject>) -> Result<()> { pub(crate) fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
for (lhs_entity, lhs_entity_object) in entities.iter() { for (lhs_entity, lhs_entity_object) in entities.iter() {
for (rhs_entity, rhs_entity_object) in entities.iter() { for (rhs_entity, rhs_entity_object) in entities.iter() {
if lhs_entity != rhs_entity if lhs_entity != rhs_entity
@ -559,33 +572,43 @@ impl ArchetypePair {
} }
} }
pub enum Update { pub enum Update<C> {
Single(Archetype), Single(Archetype<C>),
Pair(ArchetypePair), Pair(ArchetypePair<C>),
} }
impl From<Archetype> for Update { impl<C> From<Archetype<C>> for Update<C> {
fn from(archetype: Archetype) -> Self { fn from(archetype: Archetype<C>) -> Self {
Self::Single(archetype) Self::Single(archetype)
} }
} }
impl From<ArchetypePair> for Update { impl<C> From<ArchetypePair<C>> for Update<C> {
fn from(pair: ArchetypePair) -> Self { fn from(pair: ArchetypePair<C>) -> Self {
Self::Pair(pair) Self::Pair(pair)
} }
} }
#[derive(Default)] pub struct Updates<C> {
pub struct Updates {
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
timings: Timings, timings: Timings,
updates: Vec<(String, u32, Update)>, updates: Vec<(String, u32, Update<C>)>,
} }
impl Updates { impl<C> Default for Updates<C> {
pub(crate) fn update(&mut self, scene_contents: &mut SceneContents<'_>) -> Result<()> { fn default() -> Self {
Self {
#[cfg(feature = "timings")]
timings: Timings::default,
updates: Vec::new(),
}
}
}
impl<C> Updates<C> {
pub(crate) fn update(&mut self, scene_contents: &mut C) -> Result<()> {
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
if let Some(timings) = self.timings.check_timing(scene_contents.now(), None) { if let Some(timings) = self.timings.check_timing(scene_contents.now(), None) {
if !timings.is_empty() { if !timings.is_empty() {
@ -622,8 +645,8 @@ impl Updates {
pub(crate) fn add_entity( pub(crate) fn add_entity(
&mut self, &mut self,
entity_object: &EntityObject, entity_object: &EntityObject<C>,
entities: &IndexMap<Entity, EntityObject>, entities: &IndexMap<Entity, EntityObject<C>>,
) -> Result<()> { ) -> Result<()> {
for (_, _, update) in self.updates.iter_mut() { for (_, _, update) in self.updates.iter_mut() {
match update { match update {
@ -663,8 +686,8 @@ impl Updates {
&mut self, &mut self,
name: &str, name: &str,
priority: u32, priority: u32,
mut update: Update, mut update: Update<C>,
entities: &IndexMap<Entity, EntityObject>, entities: &IndexMap<Entity, EntityObject<C>>,
) -> Result<()> { ) -> Result<()> {
match &mut update { match &mut update {
Update::Single(archetype) => archetype.setup(entities)?, Update::Single(archetype) => archetype.setup(entities)?,
@ -682,46 +705,46 @@ impl Updates {
} }
} }
#[derive(Default)] // #[derive(Default)]
pub struct Archetypes { // pub struct Archetypes {
archetypes: HashMap<String, Archetype>, // archetypes: HashMap<String, Archetype>,
} // }
impl Archetypes { // impl Archetypes {
pub(crate) fn add_entity(&mut self, entity_object: &EntityObject) -> Result<()> { // pub(crate) fn add_entity(&mut self, entity_object: &EntityObject) -> Result<()> {
for archetype in self.archetypes.values_mut() { // for archetype in self.archetypes.values_mut() {
archetype.add_entity(entity_object)?; // archetype.add_entity(entity_object)?;
} // }
Ok(()) // Ok(())
} // }
pub(crate) fn remove_entity(&mut self, entity: Entity) { // pub(crate) fn remove_entity(&mut self, entity: Entity) {
for archetype in self.archetypes.values_mut() { // for archetype in self.archetypes.values_mut() {
archetype.remove_entity(entity); // archetype.remove_entity(entity);
} // }
} // }
pub(crate) fn clear(&mut self) { // pub(crate) fn clear(&mut self) {
self.archetypes.clear(); // self.archetypes.clear();
} // }
pub(crate) fn insert(&mut self, name: String, archetype: Archetype) { // pub(crate) fn insert(&mut self, name: String, archetype: Archetype) {
assert!(self.archetypes.insert(name, archetype).is_none()); // assert!(self.archetypes.insert(name, archetype).is_none());
} // }
pub(crate) fn get(&self, name: &String) -> Option<&Archetype> { // pub(crate) fn get(&self, name: &String) -> Option<&Archetype> {
self.archetypes.get(name) // self.archetypes.get(name)
} // }
pub(crate) fn execute( // pub(crate) fn execute(
&self, // &self,
name: &String, // name: &String,
scene_contents: &mut SceneContents<'_>, // scene_contents: &mut SceneContents<'_>,
) -> Result<()> { // ) -> Result<()> {
self.archetypes[name].execute(scene_contents) // self.archetypes[name].execute(scene_contents)
} // }
} // }
#[rustfmt::skip] #[rustfmt::skip]
impl_singleton_update!(single, [R]); impl_singleton_update!(single, [R]);

21
ecs/src/world.rs Normal file
View file

@ -0,0 +1,21 @@
use indexmap::IndexMap;
use crate::*;
pub struct World<SCENE: Send + Sync> {
pub(crate) updates: Updates<SCENE>,
pub(crate) events: Events<SCENE>,
pub(crate) resources: Resources,
pub(crate) entities: IndexMap<Entity, EntityObject<SCENE>>,
}
impl<SCENE: Send + Sync> Default for World<SCENE> {
fn default() -> Self {
Self {
updates: Updates::default(),
events: Events::default(),
resources: Resources::default(),
entities: IndexMap::default(),
}
}
}

View file

@ -2,7 +2,7 @@
name = "engine" name = "engine"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
# needed # needed
@ -24,8 +24,7 @@ lua-wrapper = { path = "../lua-wrapper" }
scene_update_macros = { path = "../scene_update_macros" } scene_update_macros = { path = "../scene_update_macros" }
asset = { path = "../asset" } asset = { path = "../asset" }
loading_screen = { path = "../loading-screen" } loading_screen = { path = "../loading-screen" }
context = { path = "../context", features = ["sound", "bundle_sdl2"] } context = { path = "../context", features = ["bundle_sdl2", "sound"] }
[features] [features]
timings = [] timings = []

View file

@ -7,7 +7,7 @@ use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle}; // use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle};
#[derive(Debug)] #[derive(Debug)]
pub enum EngineEvent { pub enum EngineEvent {
@ -29,68 +29,71 @@ pub enum EngineEvent {
FileDrop(String), FileDrop(String),
} }
pub trait EngineObjectHelper: Any { // pub trait EngineObjectHelper: Any {
type Payload: Send + Sync; // type Payload: Send + Sync;
fn access(&self) -> EngineObjectAccess<'_, Self::Payload>; // fn access(&self) -> EngineObjectAccess<'_, Self::Payload>;
fn payload(&self) -> EngineObjectDataHandle<Self::Payload>; // fn payload(&self) -> EngineObjectDataHandle<Self::Payload>;
fn ui(&self) -> &States; // fn ui(&self) -> &States;
fn ui_mut(&mut self) -> &mut States; // fn ui_mut(&mut self) -> &mut States;
fn access_callback_mut<F>(&self, f: F) -> impl FnMut() -> Result<()> + Send + Sync + 'static // fn access_callback_mut<'a, F>(
where // &'a self,
F: FnMut(EngineObjectAccess<'_, Self::Payload>) -> Result<()> + Send + Sync + 'static, // f: F,
{ // ) -> impl FnMut() -> Result<()> + Send + Sync + 'static
self.payload().access_callback_mut(f) // where
} // F: FnMut(EngineObjectAccess<'a, Self::Payload>) -> Result<()> + Send + Sync + 'static,
// {
// self.payload().access_callback_mut(f)
// }
fn access_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static // fn access_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static
where // where
F: Fn(EngineObjectAccess<'_, Self::Payload>) -> Result<()> + Send + Sync + 'static, // F: Fn(EngineObjectAccess<'_, Self::Payload>) -> Result<()> + Send + Sync + 'static,
{ // {
self.payload().access_callback(f) // self.payload().access_callback(f)
} // }
fn handle_callback_mut<F>(&self, mut f: F) -> impl FnMut() -> Result<()> + Send + Sync + 'static // fn handle_callback_mut<F>(&self, mut f: F) -> impl FnMut() -> Result<()> + Send + Sync + 'static
where // where
F: FnMut( // F: FnMut(
EngineObjectDataHandle<Self::Payload>, // EngineObjectDataHandle<Self::Payload>,
EngineObjectAccess<'_, Self::Payload>, // EngineObjectAccess<'_, Self::Payload>,
) -> Result<()> // ) -> Result<()>
+ Send // + Send
+ Sync // + Sync
+ 'static, // + 'static,
{ // {
let handle = self.payload(); // let handle = self.payload();
move || { // move || {
let data = handle.as_data(); // let data = handle.as_data();
let access = data.access(); // let access = data.access();
f(handle.copy(), access) // f(handle.copy(), access)
} // }
} // }
fn handle_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static // fn handle_callback<F>(&self, f: F) -> impl Fn() -> Result<()> + Send + Sync + 'static
where // where
F: Fn( // F: Fn(
EngineObjectDataHandle<Self::Payload>, // EngineObjectDataHandle<Self::Payload>,
EngineObjectAccess<'_, Self::Payload>, // EngineObjectAccess<'_, Self::Payload>,
) -> Result<()> // ) -> Result<()>
+ Send // + Send
+ Sync // + Sync
+ 'static, // + 'static,
{ // {
let handle = self.payload(); // let handle = self.payload();
move || { // move || {
let data = handle.as_data(); // let data = handle.as_data();
let access = data.access(); // let access = data.access();
f(handle.copy(), access) // f(handle.copy(), access)
} // }
} // }
} // }
pub trait EngineObject: Any { pub trait EngineObject: Any {
fn name(&self) -> &str; fn name(&self) -> &str;

View file

@ -4,4 +4,4 @@ pub mod enginesettings;
pub mod engineobject; pub mod engineobject;
pub mod asset_handler; pub mod asset_handler;
pub mod engine_object_data; // pub mod engine_object_data;

View file

@ -7,8 +7,11 @@ pub use loading_screen::*;
pub use crate::scene::prelude::*; pub use crate::scene::prelude::*;
pub use crate::engine::{ pub use crate::engine::{
engine_object_data::*, // engine_object_data::*,
engineobject::{EngineObject, EngineObjectHelper}, engineobject::{
EngineObject,
// EngineObjectHelper
},
}; };
pub use crate::engine::asset_handler::{AssetHandler, AssetLoader}; pub use crate::engine::asset_handler::{AssetHandler, AssetLoader};
@ -17,8 +20,8 @@ pub use crate::engine::{engine::*, enginesettings::*};
pub use crate::engine::engineobject::EngineEvent; pub use crate::engine::engineobject::EngineEvent;
pub use serde::{ pub use serde::{
ser::{SerializeMap, SerializeSeq, SerializeStruct},
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
ser::{SerializeMap, SerializeSeq, SerializeStruct},
}; };
pub use ron; pub use ron;

View file

@ -1,12 +1,5 @@
pub mod components; pub mod components;
pub mod entity;
pub mod map; pub mod map;
pub mod unsafe_component_store;
pub mod updates;
pub mod events;
pub mod prelude; pub mod prelude;
pub mod query; mod query;
mod resources;
pub mod type_map;

View file

@ -1,7 +1,5 @@
pub use super::map::Map; pub use super::map::Map;
pub use super::entity::{Entity, EntityObject, NetworkID};
pub use super::components::{animation::Animation, audio::Audio, draw::Draw}; pub use super::components::{animation::Animation, audio::Audio, draw::Draw};
pub use super::components::{ pub use super::components::{
@ -12,11 +10,3 @@ pub use super::components::{
}; };
pub use super::query::SceneQuery; pub use super::query::SceneQuery;
pub use super::unsafe_component_store::UnsafeComponentStore;
pub use super::updates::*;
pub use super::type_map::{
ComponentCreateInfo, ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap,
};
pub use super::resources::{ResourceMultiMut, Resources};

View file

@ -1,7 +1,7 @@
[package] [package]
name = "entity_manager" name = "entity_manager"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -3,7 +3,7 @@ name = "gavania-core"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <superschneider@t-online.de>"] authors = ["hodasemi <superschneider@t-online.de>"]
build = "src/osbuild.rs" build = "src/osbuild.rs"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
rusqlite = { workspace = true } rusqlite = { workspace = true }
@ -27,4 +27,3 @@ entity_manager = { path = "../entity_manager" }
[features] [features]
wayland = [] wayland = []

View file

@ -2,7 +2,7 @@
name = "gltf-loader" name = "gltf-loader"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <superschneider@t-online.de>"] authors = ["hodasemi <superschneider@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
gltf = { workspace = true } gltf = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "loading_screen" name = "loading_screen"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
context = { path = "../context" } context = { path = "../context" }

View file

@ -2,7 +2,7 @@
name = "lua-wrapper" name = "lua-wrapper"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
mlua = { workspace = true } mlua = { workspace = true }

View file

@ -1,7 +1,7 @@
[package] [package]
name = "map" name = "map"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "math" name = "math"
version = "0.1.0" version = "0.1.0"
authors = ["shnie <hagen.m42ller@gmail.com>"] authors = ["shnie <hagen.m42ller@gmail.com>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -2,7 +2,7 @@
name = "presentation" name = "presentation"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <superschneider@t-online.de>"] authors = ["hodasemi <superschneider@t-online.de>"]
edition = "2021" edition = "2024"
[dependencies] [dependencies]
vulkan-rs = { workspace = true } vulkan-rs = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "promise" name = "promise"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,7 +1,7 @@
[package] [package]
name = "ring_buffer" name = "ring_buffer"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,7 +1,7 @@
[package] [package]
name = "rpg_components" name = "rpg_components"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "scene_update_macros" name = "scene_update_macros"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
[lib] [lib]
proc-macro = true proc-macro = true

View file

@ -2,7 +2,7 @@
name = "transaction_derive" name = "transaction_derive"
version = "0.1.0" version = "0.1.0"
authors = ["hodasemi <michaelh.95@t-online.de>"] authors = ["hodasemi <michaelh.95@t-online.de>"]
edition = "2021" edition = "2024"
[lib] [lib]
proc-macro = true proc-macro = true