Split to ecs (almost complete)
This commit is contained in:
parent
22662557ba
commit
d6469c9181
31 changed files with 743 additions and 892 deletions
20
Cargo.toml
20
Cargo.toml
|
@ -2,26 +2,28 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"asset",
|
|
||||||
"ConfigHandler",
|
"ConfigHandler",
|
||||||
|
"Networking",
|
||||||
|
"asset",
|
||||||
|
"character_window",
|
||||||
"context",
|
"context",
|
||||||
"controllable_thread",
|
"controllable_thread",
|
||||||
|
"ecs",
|
||||||
"engine",
|
"engine",
|
||||||
|
"entity_manager",
|
||||||
|
"examples/simple_window",
|
||||||
"gavania-core",
|
"gavania-core",
|
||||||
"gltf-loader",
|
"gltf-loader",
|
||||||
"loading-screen",
|
"loading-screen",
|
||||||
"lua-wrapper",
|
"lua-wrapper",
|
||||||
|
"map",
|
||||||
"math",
|
"math",
|
||||||
"Networking",
|
|
||||||
"presentation",
|
"presentation",
|
||||||
"promise",
|
"promise",
|
||||||
"ring_buffer",
|
"ring_buffer",
|
||||||
|
"rpg_components",
|
||||||
"scene_update_macros",
|
"scene_update_macros",
|
||||||
"transaction_derive",
|
"transaction_derive",
|
||||||
"map",
|
|
||||||
"rpg_components",
|
|
||||||
"entity_manager",
|
|
||||||
"character_window", "ecs",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
@ -43,7 +45,7 @@ reqwest = { version = "0.12.5", features = ["blocking"] }
|
||||||
shared_library = "0.1.9"
|
shared_library = "0.1.9"
|
||||||
gltf = { version = "1.4.1", features = ["extras", "names"] }
|
gltf = { version = "1.4.1", features = ["extras", "names"] }
|
||||||
mlua = { version = "0.9.9", features = ["lua54", "send", "vendored"] }
|
mlua = { version = "0.9.9", features = ["lua54", "send", "vendored"] }
|
||||||
public-ip = { version = "0.2.2", default-features = false, features = ["tokio-dns-resolver", "all-providers"] }
|
public-ip = { version = "0.2.2", default-features = false, features = ["all-providers", "tokio-dns-resolver"] }
|
||||||
async-std = { version = "1.12.0" }
|
async-std = { version = "1.12.0" }
|
||||||
if-addrs = { version = "0.13.0" }
|
if-addrs = { version = "0.13.0" }
|
||||||
hostname = { version = "0.3.1" }
|
hostname = { version = "0.3.1" }
|
||||||
|
@ -51,7 +53,7 @@ trust-dns-resolver = { version = "0.23.2" }
|
||||||
openxr = { version = "0.19.0", default-features = false, features = ["static"] }
|
openxr = { version = "0.19.0", default-features = false, features = ["static"] }
|
||||||
openvr = { version = "0.6.0" }
|
openvr = { version = "0.6.0" }
|
||||||
sdl2 = { version = "0.37.0" }
|
sdl2 = { version = "0.37.0" }
|
||||||
syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
||||||
quote = "1.0.35"
|
quote = "1.0.35"
|
||||||
proc-macro2 = "1.0.86"
|
proc-macro2 = "1.0.86"
|
||||||
downcast-rs = "1.2.1"
|
downcast-rs = "1.2.1"
|
||||||
|
@ -61,7 +63,7 @@ vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||||
assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||||
audio = { git = "https://gavania.de/hodasemi/audio.git" }
|
audio = { git = "https://gavania.de/hodasemi/audio.git" }
|
||||||
library_loader = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
library_loader = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||||
ui = { git= "https://gavania.de/hodasemi/ui.git" }
|
ui = { git = "https://gavania.de/hodasemi/ui.git" }
|
||||||
|
|
||||||
[profile.release-lto]
|
[profile.release-lto]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
|
|
|
@ -11,6 +11,7 @@ indexmap.workspace = true
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
paste.workspace = true
|
paste.workspace = true
|
||||||
ron.workspace = true
|
ron.workspace = true
|
||||||
|
utilities.workspace = true
|
||||||
|
|
||||||
scene_update_macros = { path = "../scene_update_macros" }
|
scene_update_macros = { path = "../scene_update_macros" }
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,35 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::{num::ParseIntError, str::FromStr};
|
use std::{num::ParseIntError, str::FromStr};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use indexmap::IndexMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap};
|
use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap};
|
||||||
|
|
||||||
pub const COMPONENT_SEPARATOR: char = '§';
|
pub const COMPONENT_SEPARATOR: char = '§';
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EntityNotFoundError {
|
||||||
|
entity: Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityNotFoundError {
|
||||||
|
pub(crate) fn new(entity: Entity) -> Self {
|
||||||
|
Self { entity }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for EntityNotFoundError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Entity (ID: {}) not found!", self.entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for EntityNotFoundError {}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ActivationState {
|
pub struct ActivationState {
|
||||||
activated: bool,
|
activated: bool,
|
||||||
|
@ -24,7 +45,7 @@ impl ActivationState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EntityObject<S> {
|
pub struct EntityObject {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub debug_name: Option<String>,
|
pub debug_name: Option<String>,
|
||||||
|
|
||||||
|
@ -38,16 +59,16 @@ pub struct EntityObject<S> {
|
||||||
pub entity_id: u32,
|
pub entity_id: u32,
|
||||||
|
|
||||||
// component map
|
// component map
|
||||||
pub(crate) components: TypeMap<S>,
|
pub components: TypeMap,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
component_names: Vec<String>,
|
component_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<S> Send for EntityObject<S> {}
|
unsafe impl Send for EntityObject {}
|
||||||
unsafe impl<S> Sync for EntityObject<S> {}
|
unsafe impl Sync for EntityObject {}
|
||||||
|
|
||||||
impl<S> EntityObject<S> {
|
impl EntityObject {
|
||||||
pub(crate) fn new(id: u32) -> Self {
|
pub(crate) fn new(id: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -70,11 +91,11 @@ impl<S> EntityObject<S> {
|
||||||
self.gltf_file.as_ref()
|
self.gltf_file.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multi_mut(&mut self) -> MultiMut<'_, S> {
|
pub fn multi_mut(&mut self) -> MultiMut<'_> {
|
||||||
self.components.multi_mut()
|
self.components.multi_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_component<T: EntityComponent<S> + ComponentDebug>(
|
pub fn insert_component<T: EntityComponent + ComponentDebug>(
|
||||||
&mut self,
|
&mut self,
|
||||||
component: T,
|
component: T,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
|
@ -98,11 +119,8 @@ impl<S> EntityObject<S> {
|
||||||
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<S>>,
|
component: Box<dyn EntityComponent>,
|
||||||
) -> Option<Box<dyn EntityComponent<S>>>
|
) -> Option<Box<dyn EntityComponent>> {
|
||||||
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"
|
||||||
|
@ -120,7 +138,7 @@ impl<S> EntityObject<S> {
|
||||||
self.components.insert_type(type_id, component)
|
self.components.insert_type(type_id, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_component<T: EntityComponent<S>>(&mut self) -> Option<T> {
|
pub fn remove_component<T: EntityComponent>(&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"
|
||||||
|
@ -145,10 +163,7 @@ impl<S> EntityObject<S> {
|
||||||
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<S>>>
|
) -> Option<Box<dyn EntityComponent>> {
|
||||||
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"
|
||||||
|
@ -175,19 +190,19 @@ impl<S> EntityObject<S> {
|
||||||
&self.component_names
|
&self.component_names
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_component<T: EntityComponent<S> + ComponentDebug>(
|
pub fn get_component<T: EntityComponent + 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<S> + ComponentDebug>(
|
pub fn get_component_mut<T: EntityComponent + 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<S>>(&self) -> bool {
|
pub fn contains_component<T: EntityComponent>(&self) -> bool {
|
||||||
self.components.contains::<T>()
|
self.components.contains::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +214,7 @@ impl<S> EntityObject<S> {
|
||||||
Entity { id: self.entity_id }
|
Entity { id: self.entity_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_without_components(&self, id: u32) -> EntityObject<S> {
|
pub(crate) fn clone_without_components(&self, id: u32) -> EntityObject {
|
||||||
EntityObject {
|
EntityObject {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
debug_name: self.debug_name.clone(),
|
debug_name: self.debug_name.clone(),
|
||||||
|
@ -219,7 +234,7 @@ impl<S> EntityObject<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_component_from<T: EntityComponent<S> + ComponentDebug + Clone>(
|
pub fn clone_component_from<T: EntityComponent + ComponentDebug + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -236,8 +251,8 @@ pub struct Entity {
|
||||||
pub(crate) id: u32,
|
pub(crate) id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> PartialEq<EntityObject<S>> for Entity {
|
impl PartialEq<EntityObject> for Entity {
|
||||||
fn eq(&self, entity: &EntityObject<S>) -> bool {
|
fn eq(&self, entity: &EntityObject) -> bool {
|
||||||
self.id == entity.entity_id
|
self.id == entity.entity_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,3 +276,40 @@ impl FromStr for Entity {
|
||||||
Ok(Self { id: s.parse()? })
|
Ok(Self { id: s.parse()? })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EntityMultiMut<'a> {
|
||||||
|
entities: &'a mut IndexMap<Entity, EntityObject>,
|
||||||
|
buffer: HashSet<Entity>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EntityMultiMut<'a> {
|
||||||
|
pub(crate) fn new(entities: &'a mut IndexMap<Entity, EntityObject>) -> Self {
|
||||||
|
Self {
|
||||||
|
entities,
|
||||||
|
buffer: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> std::result::Result<&'a mut EntityObject, EntityNotFoundError> {
|
||||||
|
match self.entities.get_mut(&entity) {
|
||||||
|
Some(v) => {
|
||||||
|
let ptr = v as *mut EntityObject;
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
self.buffer.get(&entity).is_none(),
|
||||||
|
"Entity ({}) already borrowed",
|
||||||
|
entity.id
|
||||||
|
);
|
||||||
|
self.buffer.insert(entity);
|
||||||
|
|
||||||
|
let e: Option<&'a mut EntityObject> = Some(unsafe { &mut *ptr });
|
||||||
|
|
||||||
|
e.ok_or_else(|| EntityNotFoundError::new(entity))
|
||||||
|
}
|
||||||
|
None => Err(EntityNotFoundError::new(entity)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
ecs/src/entity_object_manager.rs
Normal file
19
ecs/src/entity_object_manager.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::EntityObject;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EntityObjectManager {
|
||||||
|
current_entity_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityObjectManager {
|
||||||
|
pub(crate) fn fetch_add_entity_id(&mut self) -> u32 {
|
||||||
|
let id = self.current_entity_id;
|
||||||
|
self.current_entity_id += 1;
|
||||||
|
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_entity(&mut self) -> EntityObject {
|
||||||
|
EntityObject::new(self.fetch_add_entity_id())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,23 @@
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
mem,
|
|
||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Events<C> {
|
use crate::World;
|
||||||
|
|
||||||
|
pub struct Events {
|
||||||
events: HashMap<
|
events: HashMap<
|
||||||
TypeId,
|
TypeId, // TypeId of Payload
|
||||||
(
|
(
|
||||||
Vec<Box<dyn Any + Send + Sync>>,
|
Vec<Box<dyn Any + Send + Sync>>, // Payload
|
||||||
Vec<Box<dyn Fn(&mut C, &dyn Any) -> anyhow::Result<()> + Send + Sync>>,
|
Vec<Arc<dyn Fn(&mut World, &dyn Any) -> anyhow::Result<()> + Send + Sync>>, // Listener on Payload
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Default for Events<C> {
|
impl Default for Events {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
events: HashMap::new(),
|
events: HashMap::new(),
|
||||||
|
@ -23,28 +25,20 @@ impl<C> Default for Events<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Events<C> {
|
impl Events {
|
||||||
pub(crate) fn clone_from_register(&self) -> Self {
|
pub(crate) fn take_events(&mut self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
events: self
|
events: self
|
||||||
.events
|
.events
|
||||||
.keys()
|
.iter_mut()
|
||||||
.map(|type_id| (*type_id, (Vec::new(), Vec::new())))
|
.filter_map(|(type_id, (payload, listener))| {
|
||||||
|
(!payload.is_empty())
|
||||||
|
.then(|| (*type_id, (std::mem::take(payload), listener.clone())))
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn move_events(&mut self, other: &mut Self) {
|
|
||||||
for (type_id, (payloads, _)) in other.events.iter_mut() {
|
|
||||||
if !payloads.is_empty() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
mem::swap(payloads, &mut tmp);
|
|
||||||
|
|
||||||
self.events.get_mut(type_id).unwrap().0.extend(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
for (payloads, listener) in self.events.values_mut() {
|
for (payloads, listener) in self.events.values_mut() {
|
||||||
payloads.clear();
|
payloads.clear();
|
||||||
|
@ -59,13 +53,13 @@ impl<C> Events<C> {
|
||||||
|
|
||||||
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 C, &T) -> anyhow::Result<()> + Send + Sync + 'static,
|
F: Fn(&mut World, &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 |c, payload| {
|
Some((_, listener)) => listener.push(Arc::new(move |world, payload| {
|
||||||
let typed_payload: &T = payload.downcast_ref().unwrap();
|
let typed_payload: &T = payload.downcast_ref().unwrap();
|
||||||
|
|
||||||
f(c, typed_payload)
|
f(world, typed_payload)
|
||||||
})),
|
})),
|
||||||
None => panic!("register event type first!"),
|
None => panic!("register event type first!"),
|
||||||
}
|
}
|
||||||
|
@ -78,11 +72,11 @@ impl<C> Events<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fire_events(&mut self, c: &mut C) -> anyhow::Result<()> {
|
pub(crate) fn fire_events(&mut self, world: &mut World) -> 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)(c, payload.deref_mut())?;
|
(listener)(world, payload.deref_mut())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
mod entity;
|
mod entity;
|
||||||
|
mod entity_object_manager;
|
||||||
mod events;
|
mod events;
|
||||||
mod resources;
|
mod resources;
|
||||||
mod type_map;
|
mod type_map;
|
||||||
|
@ -6,7 +7,7 @@ mod unsafe_component_store;
|
||||||
mod updates;
|
mod updates;
|
||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
pub use crate::entity::{Entity, EntityObject};
|
pub use crate::entity::{Entity, EntityMultiMut, EntityNotFoundError, EntityObject};
|
||||||
pub use crate::events::Events;
|
pub use crate::events::Events;
|
||||||
pub use crate::resources::{ResourceMultiMut, Resources};
|
pub use crate::resources::{ResourceMultiMut, Resources};
|
||||||
pub use crate::type_map::{
|
pub use crate::type_map::{
|
||||||
|
@ -14,4 +15,4 @@ pub use crate::type_map::{
|
||||||
};
|
};
|
||||||
pub use crate::unsafe_component_store::UnsafeComponentStore;
|
pub use crate::unsafe_component_store::UnsafeComponentStore;
|
||||||
pub use crate::updates::*;
|
pub use crate::updates::*;
|
||||||
pub use crate::world::World;
|
pub use crate::world::{World, WorldBuilder};
|
||||||
|
|
|
@ -12,12 +12,14 @@ use anyhow::Result;
|
||||||
use destructure_traitobject;
|
use destructure_traitobject;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub trait EntityComponent<S>: Any + Send + Sync {
|
use crate::World;
|
||||||
fn enable(&mut self, _scene: &mut S) -> Result<()> {
|
|
||||||
|
pub trait EntityComponent: Any + Send + Sync {
|
||||||
|
fn enable(&mut self, _world: &mut World) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(&mut self, _scene: &mut S) -> Result<()> {
|
fn disable(&mut self, _world: &mut World) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +47,11 @@ pub trait ComponentCreateInfo<'de>: Serialize + Deserialize<'de> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeMap<S> {
|
pub struct TypeMap {
|
||||||
map: HashMap<TypeId, Box<dyn EntityComponent<S>>>,
|
map: HashMap<TypeId, Box<dyn EntityComponent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Default for TypeMap<S> {
|
impl Default for TypeMap {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
|
@ -57,8 +59,8 @@ impl<S> Default for TypeMap<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> TypeMap<S> {
|
impl TypeMap {
|
||||||
pub fn insert<T: EntityComponent<S> + ComponentDebug>(&mut self, value: T) -> Option<T> {
|
pub fn insert<T: EntityComponent + 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))
|
||||||
|
@ -67,21 +69,21 @@ impl<S> TypeMap<S> {
|
||||||
pub fn insert_type(
|
pub fn insert_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
component: Box<dyn EntityComponent<S>>,
|
component: Box<dyn EntityComponent>,
|
||||||
) -> Option<Box<dyn EntityComponent<S>>> {
|
) -> Option<Box<dyn EntityComponent>> {
|
||||||
self.map.insert(type_id, component)
|
self.map.insert(type_id, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove<T: EntityComponent<S>>(&mut self) -> Option<T> {
|
pub fn remove<T: EntityComponent>(&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<S>>> {
|
pub fn remove_by_type_id(&mut self, type_id: &TypeId) -> Option<Box<dyn EntityComponent>> {
|
||||||
self.map.remove(type_id)
|
self.map.remove(type_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<T: EntityComponent<S> + ComponentDebug>(
|
pub fn get<T: EntityComponent + ComponentDebug>(
|
||||||
&self,
|
&self,
|
||||||
) -> std::result::Result<&T, ComponentNotFoundError> {
|
) -> std::result::Result<&T, ComponentNotFoundError> {
|
||||||
self.map
|
self.map
|
||||||
|
@ -93,13 +95,13 @@ impl<S> TypeMap<S> {
|
||||||
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<S>>, ComponentNotFoundError> {
|
) -> std::result::Result<&Box<dyn EntityComponent>, 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<S> + ComponentDebug>(
|
pub fn get_mut<T: EntityComponent + ComponentDebug>(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> std::result::Result<&mut T, ComponentNotFoundError> {
|
) -> std::result::Result<&mut T, ComponentNotFoundError> {
|
||||||
self.map
|
self.map
|
||||||
|
@ -111,13 +113,13 @@ impl<S> TypeMap<S> {
|
||||||
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<S>>, ComponentNotFoundError> {
|
) -> std::result::Result<&mut Box<dyn EntityComponent>, 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<S>>(&self) -> bool {
|
pub fn contains<T: EntityComponent>(&self) -> bool {
|
||||||
self.contains_type_id(&TypeId::of::<T>())
|
self.contains_type_id(&TypeId::of::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,25 +127,23 @@ impl<S> TypeMap<S> {
|
||||||
self.map.contains_key(type_id)
|
self.map.contains_key(type_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multi_mut(&mut self) -> MultiMut<'_, S> {
|
pub fn multi_mut(&mut self) -> MultiMut<'_> {
|
||||||
MultiMut::new(&mut self.map)
|
MultiMut::new(&mut self.map)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> Iter<'_, TypeId, Box<dyn EntityComponent<S>>> {
|
pub fn iter(&self) -> Iter<'_, TypeId, Box<dyn EntityComponent>> {
|
||||||
self.map.iter()
|
self.map.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> IterMut<'_, TypeId, Box<dyn EntityComponent<S>>> {
|
pub fn iter_mut(&mut self) -> IterMut<'_, TypeId, Box<dyn EntityComponent>> {
|
||||||
self.map.iter_mut()
|
self.map.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downcast_unchecked<T: EntityComponent<S>>(boxed: Box<dyn EntityComponent<S>>) -> Box<T> {
|
fn downcast_unchecked<T: EntityComponent>(boxed: Box<dyn EntityComponent>) -> 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 fn downcast_ref_unchecked<T: EntityComponent<S>>(
|
pub fn downcast_ref_unchecked<T: EntityComponent>(boxed_ref: &Box<dyn EntityComponent>) -> &T {
|
||||||
boxed_ref: &Box<dyn EntityComponent<S>>,
|
|
||||||
) -> &T {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr_to_ptr: *const *const T =
|
let ptr_to_ptr: *const *const T =
|
||||||
transmute(destructure_traitobject::data(boxed_ref as *const _));
|
transmute(destructure_traitobject::data(boxed_ref as *const _));
|
||||||
|
@ -152,8 +152,8 @@ impl<S> TypeMap<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downcast_mut_unchecked<T: EntityComponent<S>>(
|
pub fn downcast_mut_unchecked<T: EntityComponent>(
|
||||||
boxed_ref: &mut Box<dyn EntityComponent<S>>,
|
boxed_ref: &mut Box<dyn EntityComponent>,
|
||||||
) -> &mut T {
|
) -> &mut T {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr_to_ptr: *mut *mut T =
|
let ptr_to_ptr: *mut *mut T =
|
||||||
|
@ -165,13 +165,13 @@ impl<S> TypeMap<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows mutable access to multiple components at once
|
/// Allows mutable access to multiple components at once
|
||||||
pub struct MultiMut<'a, S> {
|
pub struct MultiMut<'a> {
|
||||||
map: &'a mut HashMap<TypeId, Box<dyn EntityComponent<S>>>,
|
map: &'a mut HashMap<TypeId, Box<dyn EntityComponent>>,
|
||||||
buffer: Vec<*mut Box<dyn EntityComponent<S>>>,
|
buffer: Vec<*mut Box<dyn EntityComponent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> MultiMut<'a, S> {
|
impl<'a> MultiMut<'a> {
|
||||||
fn new(map: &'a mut HashMap<TypeId, Box<dyn EntityComponent<S>>>) -> Self {
|
fn new(map: &'a mut HashMap<TypeId, Box<dyn EntityComponent>>) -> Self {
|
||||||
MultiMut {
|
MultiMut {
|
||||||
map,
|
map,
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
|
@ -179,7 +179,7 @@ impl<'a, S> MultiMut<'a, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns requested type on success
|
/// Returns requested type on success
|
||||||
pub fn get<T: EntityComponent<S> + ComponentDebug>(
|
pub fn get<T: EntityComponent + 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>())
|
||||||
|
@ -191,7 +191,7 @@ impl<'a, S> MultiMut<'a, S> {
|
||||||
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<S>>, ComponentNotFoundError> {
|
) -> std::result::Result<&'a mut Box<dyn EntityComponent>, 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 _;
|
||||||
|
@ -205,7 +205,7 @@ impl<'a, S> MultiMut<'a, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let t: Option<&'a mut Box<dyn EntityComponent<S>>> = unsafe { transmute(ptr) };
|
let t: Option<&'a mut Box<dyn EntityComponent>> = unsafe { transmute(ptr) };
|
||||||
|
|
||||||
t.ok_or_else(|| ComponentNotFoundError::type_id(*type_id))
|
t.ok_or_else(|| ComponentNotFoundError::type_id(*type_id))
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ struct Test {
|
||||||
z: u32,
|
z: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> EntityComponent<S> for Test {
|
impl EntityComponent for Test {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"Test"
|
"Test"
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ impl PartialEq for Test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_multi_mut() {
|
fn verify_multi_mut() {
|
||||||
let mut map = TypeMap::<()>::default();
|
let mut map = TypeMap::default();
|
||||||
|
|
||||||
map.insert(Test::default());
|
map.insert(Test::default());
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ fn verify_multi_mut() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_insert() {
|
fn verify_insert() {
|
||||||
let mut map = TypeMap::<()>::default();
|
let mut map = TypeMap::default();
|
||||||
|
|
||||||
let reference = Test { x: 5, y: 20, z: 30 };
|
let reference = Test { x: 5, y: 20, z: 30 };
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ fn verify_insert() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_get() {
|
fn verify_get() {
|
||||||
let mut map = TypeMap::<()>::default();
|
let mut map = TypeMap::default();
|
||||||
|
|
||||||
let reference = Test { x: 5, y: 20, z: 30 };
|
let reference = Test { x: 5, y: 20, z: 30 };
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ fn verify_get() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_get_mut() {
|
fn verify_get_mut() {
|
||||||
let mut map = TypeMap::<()>::default();
|
let mut map = TypeMap::default();
|
||||||
|
|
||||||
let reference = Test { x: 5, y: 20, z: 30 };
|
let reference = Test { x: 5, y: 20, z: 30 };
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@ 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<C> Archetype<C> {
|
impl Archetype {
|
||||||
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 C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
F: Fn(&mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter<C> + 'static,
|
Filter: CheckFilter + 'static,
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent<C> + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
{
|
{
|
||||||
$(
|
$(
|
||||||
|
@ -68,36 +68,34 @@ macro_rules! impl_singleton_update {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, Func, Filter, $( $var, )+> AddUpdates2<C, ( $( $var, )+ ), Func, Filter> for Updates<C>
|
impl<Func, Filter, $( $var, )+> AddUpdates2<( $( $var, )+ ), Func, Filter> for Updates
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent<C> + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter<C> + '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
|
||||||
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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for World<C>
|
impl<Func, Filter, $( $var, )+> AddUpdates<( $( $var, )+ ), Func, Filter> for WorldBuilder
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$var: EntityComponent<C> + ComponentDebug,
|
$var: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut C, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut World, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
Filter: CheckFilter<C> + 'static,
|
Filter: CheckFilter + 'static
|
||||||
C: Send + Sync
|
|
||||||
{
|
{
|
||||||
fn add_update(
|
fn add_update(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -106,29 +104,9 @@ macro_rules! impl_singleton_update {
|
||||||
func: Func,
|
func: Func,
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.updates.add_update(name, priority, func, filter, &self.entities)
|
self.updates.add_update(name, priority, func, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl Scene {
|
|
||||||
// paste::item! {
|
|
||||||
// pub fn [<add_ $name _archetype>]<F, Filter, $($var,)+>(&mut self, name: impl ToString, f: F, filter: Filter) -> Result<()>
|
|
||||||
// where
|
|
||||||
// F: Fn(&mut SceneContents<'_>, Entity, $(&mut $var,)+) -> Result<()> + Send + Sync + Clone + 'static,
|
|
||||||
// Filter: CheckFilter + 'static,
|
|
||||||
// $(
|
|
||||||
// $var: EntityComponent + ComponentDebug,
|
|
||||||
// )+
|
|
||||||
// {
|
|
||||||
// let mut archetype = Archetype::[<create_ $name>](f, filter);
|
|
||||||
// archetype.setup(&self.entities)?;
|
|
||||||
|
|
||||||
// self.archetypes.insert(name.to_string(), archetype);
|
|
||||||
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,19 +117,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<C> ArchetypePair<C> {
|
impl ArchetypePair {
|
||||||
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 C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
F: Fn(&mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LeftFilter: CheckFilter<C> + 'static,
|
LeftFilter: CheckFilter + 'static,
|
||||||
RightFilter: CheckFilter<C> + 'static,
|
RightFilter: CheckFilter + 'static,
|
||||||
$(
|
$(
|
||||||
$rhs_big: EntityComponent<C> + ComponentDebug,
|
$rhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
$(
|
$(
|
||||||
$lhs_big: EntityComponent<C> + ComponentDebug,
|
$lhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
{
|
{
|
||||||
$(
|
$(
|
||||||
|
@ -220,46 +198,44 @@ macro_rules! impl_pair_update {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<C, ( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates<C>
|
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates2<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for Updates
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$rhs_big: EntityComponent<C> + ComponentDebug,
|
$rhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
$(
|
$(
|
||||||
$lhs_big: EntityComponent<C> + ComponentDebug,
|
$lhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LhsFilter: CheckFilter<C> + 'static,
|
LhsFilter: CheckFilter + 'static,
|
||||||
RhsFilter: CheckFilter<C> + 'static
|
RhsFilter: 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: (LhsFilter, RhsFilter),
|
filter: (LhsFilter, RhsFilter)
|
||||||
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)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for World<C>
|
impl<Func, LhsFilter, RhsFilter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, (LhsFilter, RhsFilter)> for WorldBuilder
|
||||||
where
|
where
|
||||||
$(
|
$(
|
||||||
$rhs_big: EntityComponent<C> + ComponentDebug,
|
$rhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
$(
|
$(
|
||||||
$lhs_big: EntityComponent<C> + ComponentDebug,
|
$lhs_big: EntityComponent + ComponentDebug,
|
||||||
)+
|
)+
|
||||||
Func: Fn(& mut C, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
Func: Fn(& mut World, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
||||||
LhsFilter: CheckFilter<C> + 'static,
|
LhsFilter: CheckFilter + 'static,
|
||||||
RhsFilter: CheckFilter<C> + 'static,
|
RhsFilter: CheckFilter + 'static
|
||||||
C: Send + Sync
|
|
||||||
{
|
{
|
||||||
fn add_update(
|
fn add_update(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -268,60 +244,24 @@ macro_rules! impl_pair_update {
|
||||||
func: Func,
|
func: Func,
|
||||||
filter: (LhsFilter, RhsFilter),
|
filter: (LhsFilter, RhsFilter),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.updates.add_update(name, priority, func, filter, &self.entities)
|
self.updates.add_update(name, priority, func, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl<Func, Filter, $( $lhs_big, )+ $($rhs_big,)+> AddUpdates<( ($( $lhs_big, )+), ($($rhs_big,)+) ), Func, Filter> for Scene
|
|
||||||
// where
|
|
||||||
// $(
|
|
||||||
// $rhs_big: EntityComponent + ComponentDebug,
|
|
||||||
// )+
|
|
||||||
// $(
|
|
||||||
// $lhs_big: EntityComponent + ComponentDebug,
|
|
||||||
// )+
|
|
||||||
// Func: Fn(& mut SceneContents<'_>, (Entity, $(&mut $lhs_big,)+), (Entity, $(&mut $rhs_big,)+)) -> Result<()> + Send + Sync + Clone + 'static,
|
|
||||||
// Filter: CheckFilter + 'static,
|
|
||||||
// {
|
|
||||||
// fn add_update(
|
|
||||||
// &mut self,
|
|
||||||
// name: &str,
|
|
||||||
// priority: u32,
|
|
||||||
// func: Func,
|
|
||||||
// filter: Filter,
|
|
||||||
// ) -> Result<()> {
|
|
||||||
// paste::item! {
|
|
||||||
// self.updates.add_update(name, priority, func, (filter.clone(), filter), &self.entities)?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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>]<C, $($big: EntityComponent<C>,)+>
|
pub struct [<$name Filter>]<$($big: EntityComponent,)+> {
|
||||||
where
|
|
||||||
C: Send + Sync
|
|
||||||
{
|
|
||||||
c: std::marker::PhantomData<C>,
|
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$little: std::marker::PhantomData<$big>,
|
$little: std::marker::PhantomData<$big>,
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, $($big: EntityComponent<C>,)+> Default for [<$name Filter>]<C, $($big,)+>
|
impl<$($big: EntityComponent,)+> Default for [<$name Filter>]<$($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,
|
||||||
)+
|
)+
|
||||||
|
@ -329,11 +269,8 @@ macro_rules! impl_update_filter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, $($big: EntityComponent<C>,)+> CheckFilter<C> for [<$name Filter>]<C, $($big,)+>
|
impl<$($big: EntityComponent,)+> CheckFilter for [<$name Filter>]<$($big,)+> {
|
||||||
where
|
fn check(&self, entity: &EntityObject) -> bool {
|
||||||
C: Send + Sync
|
|
||||||
{
|
|
||||||
fn check(&self, entity: &EntityObject<C>) -> bool {
|
|
||||||
$(
|
$(
|
||||||
if entity.contains_component::<$big>() {
|
if entity.contains_component::<$big>() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -343,7 +280,7 @@ macro_rules! impl_update_filter {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_dedup<O: EntityComponent<C>>(&self) {
|
fn verify_dedup<O: EntityComponent>(&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");
|
||||||
|
@ -352,14 +289,9 @@ macro_rules! impl_update_filter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, $($big: EntityComponent<C>,)+> Clone for [<$name Filter>]<C, $($big,)+>
|
impl<$($big: EntityComponent,)+> Clone for [<$name Filter>]<$($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(),
|
||||||
)+
|
)+
|
||||||
|
@ -370,41 +302,33 @@ macro_rules! impl_update_filter {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Query<C, T, F = EmptyFilter>
|
pub struct Query<T, F = EmptyFilter>
|
||||||
where
|
where
|
||||||
F: CheckFilter<C>,
|
F: CheckFilter,
|
||||||
{
|
{
|
||||||
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<C, T, Func, Filter> {
|
trait AddUpdates2<T, Func, Filter> {
|
||||||
fn add_update(
|
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
priority: u32,
|
|
||||||
func: Func,
|
|
||||||
filter: Filter,
|
|
||||||
entities: &IndexMap<Entity, EntityObject<C>>,
|
|
||||||
) -> Result<()>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CheckFilter<C>: Send + Sync + Default + Clone {
|
pub trait CheckFilter: Send + Sync + Default + Clone {
|
||||||
fn check(&self, entity: &EntityObject<C>) -> bool;
|
fn check(&self, entity: &EntityObject) -> bool;
|
||||||
fn verify_dedup<O: EntityComponent<C>>(&self);
|
fn verify_dedup<O: EntityComponent>(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct EmptyFilter;
|
pub struct EmptyFilter;
|
||||||
|
|
||||||
impl<C> CheckFilter<C> for EmptyFilter {
|
impl CheckFilter for EmptyFilter {
|
||||||
fn check(&self, _entity: &EntityObject<C>) -> bool {
|
fn check(&self, _entity: &EntityObject) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,19 +354,19 @@ impl ArchetypeInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Archetype<C> {
|
pub struct Archetype {
|
||||||
check_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
|
||||||
create_callback: Box<
|
create_callback: Box<
|
||||||
dyn Fn(&EntityObject<C>) -> Result<Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>
|
dyn Fn(&EntityObject) -> Result<Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>>,
|
entities: IndexMap<Entity, Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Archetype<C> {
|
impl Archetype {
|
||||||
pub fn add_entity(&mut self, entity_object: &EntityObject<C>) -> Result<()> {
|
pub fn add_entity(&mut self, entity_object: &EntityObject) -> 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)?;
|
||||||
|
|
||||||
|
@ -456,7 +380,7 @@ impl<C> Archetype<C> {
|
||||||
self.entities.swap_remove(&entity);
|
self.entities.swap_remove(&entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&self, scene_contents: &mut C) -> Result<()> {
|
pub fn execute(&self, scene_contents: &mut World) -> Result<()> {
|
||||||
for (entity, callback) in self.entities.iter() {
|
for (entity, callback) in self.entities.iter() {
|
||||||
callback(*entity, scene_contents)?;
|
callback(*entity, scene_contents)?;
|
||||||
}
|
}
|
||||||
|
@ -464,48 +388,38 @@ impl<C> Archetype<C> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
|
|
||||||
for (entity, entity_object) in entities.iter() {
|
|
||||||
if (self.check_entity)(entity_object) {
|
|
||||||
let cb = (self.create_callback)(entity_object)?;
|
|
||||||
|
|
||||||
self.entities.insert(entity.clone(), cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn entities(
|
pub(crate) fn entities(
|
||||||
&self,
|
&self,
|
||||||
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut C) -> Result<()> + Send + Sync>> {
|
) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>> {
|
||||||
&self.entities
|
&self.entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ArchetypePair<C> {
|
pub struct ArchetypePair {
|
||||||
check_left_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
check_left_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
|
||||||
check_right_entity: Box<dyn Fn(&EntityObject<C>) -> bool + Send + Sync>,
|
check_right_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
|
||||||
|
|
||||||
create_callback: Box<
|
create_callback: Box<
|
||||||
dyn Fn(
|
dyn Fn(
|
||||||
&EntityObject<C>,
|
&EntityObject,
|
||||||
&EntityObject<C>,
|
&EntityObject,
|
||||||
)
|
)
|
||||||
-> Result<Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>
|
-> Result<Box<dyn Fn(Entity, Entity, &mut World) -> Result<()> + Send + Sync>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
entities:
|
entities: IndexMap<
|
||||||
IndexMap<(Entity, Entity), Box<dyn Fn(Entity, Entity, &mut C) -> Result<()> + Send + Sync>>,
|
(Entity, Entity),
|
||||||
|
Box<dyn Fn(Entity, Entity, &mut World) -> Result<()> + Send + Sync>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> ArchetypePair<C> {
|
impl ArchetypePair {
|
||||||
pub(crate) fn add_entity(
|
pub(crate) fn add_entity(
|
||||||
&mut self,
|
&mut self,
|
||||||
entity_object: &EntityObject<C>,
|
entity_object: &EntityObject,
|
||||||
entities: &IndexMap<Entity, EntityObject<C>>,
|
entities: &IndexMap<Entity, EntityObject>,
|
||||||
) -> 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 {
|
||||||
|
@ -546,57 +460,40 @@ impl<C> ArchetypePair<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn execute(&self, scene_contents: &mut C) -> Result<()> {
|
pub(crate) fn execute(&self, scene_contents: &mut World) -> 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)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn setup(&mut self, entities: &IndexMap<Entity, EntityObject<C>>) -> Result<()> {
|
|
||||||
for (lhs_entity, lhs_entity_object) in entities.iter() {
|
|
||||||
for (rhs_entity, rhs_entity_object) in entities.iter() {
|
|
||||||
if lhs_entity != rhs_entity
|
|
||||||
&& (self.check_left_entity)(lhs_entity_object)
|
|
||||||
&& (self.check_right_entity)(rhs_entity_object)
|
|
||||||
{
|
|
||||||
let cb = (self.create_callback)(lhs_entity_object, rhs_entity_object)?;
|
|
||||||
|
|
||||||
self.entities.insert((*lhs_entity, *rhs_entity), cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Update<C> {
|
pub enum Update {
|
||||||
Single(Archetype<C>),
|
Single(Archetype),
|
||||||
Pair(ArchetypePair<C>),
|
Pair(ArchetypePair),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> From<Archetype<C>> for Update<C> {
|
impl From<Archetype> for Update {
|
||||||
fn from(archetype: Archetype<C>) -> Self {
|
fn from(archetype: Archetype) -> Self {
|
||||||
Self::Single(archetype)
|
Self::Single(archetype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> From<ArchetypePair<C>> for Update<C> {
|
impl From<ArchetypePair> for Update {
|
||||||
fn from(pair: ArchetypePair<C>) -> Self {
|
fn from(pair: ArchetypePair) -> Self {
|
||||||
Self::Pair(pair)
|
Self::Pair(pair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Updates<C> {
|
pub struct Updates {
|
||||||
#[cfg(feature = "timings")]
|
#[cfg(feature = "timings")]
|
||||||
timings: Timings,
|
timings: Timings,
|
||||||
|
|
||||||
updates: Vec<(String, u32, Update<C>)>,
|
updates: Vec<(String, u32, Update)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Default for Updates<C> {
|
impl Default for Updates {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(feature = "timings")]
|
#[cfg(feature = "timings")]
|
||||||
|
@ -607,10 +504,10 @@ impl<C> Default for Updates<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> Updates<C> {
|
impl Updates {
|
||||||
pub(crate) fn update(&mut self, scene_contents: &mut C) -> Result<()> {
|
pub(crate) fn update(&mut self, world: &mut World) -> 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(world.now(), None) {
|
||||||
if !timings.is_empty() {
|
if !timings.is_empty() {
|
||||||
println!("timings: {:#?}", timings);
|
println!("timings: {:#?}", timings);
|
||||||
}
|
}
|
||||||
|
@ -627,10 +524,10 @@ impl<C> Updates<C> {
|
||||||
|
|
||||||
match update {
|
match update {
|
||||||
Update::Single(archetype) => {
|
Update::Single(archetype) => {
|
||||||
archetype.execute(scene_contents)?;
|
archetype.execute(world)?;
|
||||||
}
|
}
|
||||||
Update::Pair(archetype_pair) => {
|
Update::Pair(archetype_pair) => {
|
||||||
archetype_pair.execute(scene_contents)?;
|
archetype_pair.execute(world)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,8 +542,8 @@ impl<C> Updates<C> {
|
||||||
|
|
||||||
pub(crate) fn add_entity(
|
pub(crate) fn add_entity(
|
||||||
&mut self,
|
&mut self,
|
||||||
entity_object: &EntityObject<C>,
|
entity_object: &EntityObject,
|
||||||
entities: &IndexMap<Entity, EntityObject<C>>,
|
entities: &IndexMap<Entity, EntityObject>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (_, _, update) in self.updates.iter_mut() {
|
for (_, _, update) in self.updates.iter_mut() {
|
||||||
match update {
|
match update {
|
||||||
|
@ -682,18 +579,7 @@ impl<C> Updates<C> {
|
||||||
self.timings.clear();
|
self.timings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add(
|
pub(crate) fn add(&mut self, name: &str, priority: u32, update: Update) -> Result<()> {
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
priority: u32,
|
|
||||||
mut update: Update<C>,
|
|
||||||
entities: &IndexMap<Entity, EntityObject<C>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
match &mut update {
|
|
||||||
Update::Single(archetype) => archetype.setup(entities)?,
|
|
||||||
Update::Pair(archetype_pair) => archetype_pair.setup(entities)?,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
#[cfg(feature = "timings")]
|
||||||
self.timings.add_timing_afterwards(name);
|
self.timings.add_timing_afterwards(name);
|
||||||
|
|
||||||
|
|
335
ecs/src/world.rs
335
ecs/src/world.rs
|
@ -1,21 +1,330 @@
|
||||||
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
collections::HashMap,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{Result, bail};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use utilities::prelude::{remove_life_time, remove_life_time_mut};
|
||||||
|
|
||||||
use crate::*;
|
use crate::{entity_object_manager::EntityObjectManager, *};
|
||||||
|
|
||||||
pub struct World<SCENE: Send + Sync> {
|
pub struct WorldBuilder {
|
||||||
pub(crate) updates: Updates<SCENE>,
|
pub(crate) updates: Updates,
|
||||||
pub(crate) events: Events<SCENE>,
|
pub events: Events,
|
||||||
pub(crate) resources: Resources,
|
pub resources: Resources,
|
||||||
pub(crate) entities: IndexMap<Entity, EntityObject<SCENE>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SCENE: Send + Sync> Default for World<SCENE> {
|
impl WorldBuilder {
|
||||||
fn default() -> Self {
|
pub fn build(self) -> World {
|
||||||
Self {
|
World {
|
||||||
updates: Updates::default(),
|
updates: self.updates,
|
||||||
events: Events::default(),
|
events: self.events,
|
||||||
resources: Resources::default(),
|
resources: self.resources,
|
||||||
entities: IndexMap::default(),
|
entities: Default::default(),
|
||||||
|
|
||||||
|
entities_to_remove: Default::default(),
|
||||||
|
entities_to_add: Default::default(),
|
||||||
|
entities_updates: Default::default(),
|
||||||
|
|
||||||
|
entity_object_manager: Default::default(),
|
||||||
|
|
||||||
|
start_time: Instant::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ComponentChange {
|
||||||
|
Added(TypeId, Box<dyn EntityComponent>),
|
||||||
|
Removed(TypeId),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct World {
|
||||||
|
pub(crate) updates: Updates,
|
||||||
|
pub events: Events,
|
||||||
|
pub resources: Resources,
|
||||||
|
pub(crate) entities: IndexMap<Entity, EntityObject>,
|
||||||
|
|
||||||
|
entities_to_remove: Vec<Entity>,
|
||||||
|
entities_to_add: Vec<EntityObject>,
|
||||||
|
entities_updates: HashMap<Entity, Vec<ComponentChange>>,
|
||||||
|
|
||||||
|
entity_object_manager: EntityObjectManager,
|
||||||
|
|
||||||
|
start_time: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
pub fn builder() -> WorldBuilder {
|
||||||
|
WorldBuilder {
|
||||||
|
updates: Default::default(),
|
||||||
|
events: Default::default(),
|
||||||
|
resources: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_entity(&mut self) -> EntityObject {
|
||||||
|
self.entity_object_manager.create_entity()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn now(&self) -> Duration {
|
||||||
|
self.start_time.elapsed()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entity(
|
||||||
|
&self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> std::result::Result<&EntityObject, EntityNotFoundError> {
|
||||||
|
self.entities
|
||||||
|
.get(&entity)
|
||||||
|
.ok_or_else(|| EntityNotFoundError::new(entity))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn entity_unchecked<'a>(
|
||||||
|
&self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> std::result::Result<&'a EntityObject, EntityNotFoundError> {
|
||||||
|
self.entity(entity).map(|e| unsafe { remove_life_time(e) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entity_mut(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> std::result::Result<&mut EntityObject, EntityNotFoundError> {
|
||||||
|
self.entities
|
||||||
|
.get_mut(&entity)
|
||||||
|
.ok_or_else(|| EntityNotFoundError::new(entity))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn entity_mut_unchecked<'a>(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> std::result::Result<&'a mut EntityObject, EntityNotFoundError> {
|
||||||
|
self.entity_mut(entity)
|
||||||
|
.map(|e| unsafe { remove_life_time_mut(e) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entities_multi_mut(&mut self) -> EntityMultiMut<'_> {
|
||||||
|
EntityMultiMut::new(&mut self.entities)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_entity(&mut self, entity_object: EntityObject) -> Result<Entity> {
|
||||||
|
let entity = entity_object.as_entity();
|
||||||
|
self.entities_to_add.push(entity_object);
|
||||||
|
|
||||||
|
Ok(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_component<T: EntityComponent + ComponentDebug>(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
component: T,
|
||||||
|
) -> Result<()> {
|
||||||
|
println!("insert component {}", T::debug_name());
|
||||||
|
|
||||||
|
let change = ComponentChange::Added(TypeId::of::<T>(), Box::new(component));
|
||||||
|
|
||||||
|
match self.entities_updates.get_mut(&entity) {
|
||||||
|
Some(changes) => {
|
||||||
|
changes.push(change);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.entities_updates.insert(entity, vec![change]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_component<T: EntityComponent + ComponentDebug>(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> Result<()> {
|
||||||
|
println!("remove component {}", T::debug_name());
|
||||||
|
|
||||||
|
let change = ComponentChange::Removed(TypeId::of::<T>());
|
||||||
|
|
||||||
|
match self.entities_updates.get_mut(&entity) {
|
||||||
|
Some(changes) => {
|
||||||
|
changes.push(change);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.entities_updates.insert(entity, vec![change]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_entity(&mut self, entity: Entity) -> Result<Option<EntityObject>> {
|
||||||
|
self.entities_to_remove.push(entity);
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async application of changes
|
||||||
|
impl World {
|
||||||
|
fn _add_entity(&mut self, mut entity: EntityObject) -> Result<Entity> {
|
||||||
|
// call enable event for all components
|
||||||
|
for (_, component) in entity.components.iter_mut() {
|
||||||
|
component.enable(self)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.activation_state.apply_change();
|
||||||
|
|
||||||
|
let e = entity.as_entity();
|
||||||
|
|
||||||
|
self.updates.add_entity(&mut entity, &self.entities)?;
|
||||||
|
assert!(self.entities.insert(e, entity).is_none());
|
||||||
|
|
||||||
|
Ok(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _remove_entity(&mut self, entity: Entity) -> Result<Option<EntityObject>> {
|
||||||
|
if let Some(mut entity_object) = self.entities.swap_remove(&entity) {
|
||||||
|
for (_, component) in entity_object.components.iter_mut() {
|
||||||
|
component.disable(self)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
self.updates.remove_entity(entity);
|
||||||
|
|
||||||
|
return Ok(Some(entity_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _insert_component<T: EntityComponent + ComponentDebug>(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
mut component: T,
|
||||||
|
) -> Result<()> {
|
||||||
|
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
|
||||||
|
|
||||||
|
let entity_object = entities
|
||||||
|
.get_mut(&entity)
|
||||||
|
.ok_or_else(|| EntityNotFoundError::new(entity))?;
|
||||||
|
|
||||||
|
self.updates.remove_entity(entity);
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
component.enable(self)?;
|
||||||
|
if entity_object.insert_component(component).is_some() {
|
||||||
|
bail!("component {} already present", T::debug_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
self.updates.add_entity(entity_object, &self.entities)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _remove_component<T: EntityComponent + ComponentDebug>(
|
||||||
|
&mut self,
|
||||||
|
entity: Entity,
|
||||||
|
) -> Result<()> {
|
||||||
|
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
|
||||||
|
|
||||||
|
let entity_object = entities
|
||||||
|
.get_mut(&entity)
|
||||||
|
.ok_or_else(|| EntityNotFoundError::new(entity))?;
|
||||||
|
|
||||||
|
self.updates.remove_entity(entity);
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
if let Some(mut component) = entity_object.remove_component_by_id(TypeId::of::<T>()) {
|
||||||
|
component.disable(self)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
self.updates.add_entity(entity_object, &self.entities)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit_entity_changes(&mut self) -> Result<()> {
|
||||||
|
if !self.entities_to_remove.is_empty() {
|
||||||
|
println!("entities to remove {}", self.entities_to_remove.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity in core::mem::take(&mut self.entities_to_remove) {
|
||||||
|
self._remove_entity(entity)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.entities_to_add.is_empty() {
|
||||||
|
println!("entities to add {}", self.entities_to_add.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity_object in core::mem::take(&mut self.entities_to_add) {
|
||||||
|
self._add_entity(entity_object)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.entities_updates.is_empty() {
|
||||||
|
println!("entities to update {}", self.entities_updates.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, changes) in core::mem::take(&mut self.entities_updates) {
|
||||||
|
self.updates.remove_entity(entity);
|
||||||
|
|
||||||
|
if let Some(entity_object) = unsafe { self.entity_mut_unchecked(entity).ok() } {
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
for change in changes {
|
||||||
|
match change {
|
||||||
|
ComponentChange::Added(type_id, mut component) => {
|
||||||
|
component.enable(self)?;
|
||||||
|
let name = component.name().to_string();
|
||||||
|
|
||||||
|
if entity_object
|
||||||
|
.insert_component_by_id(type_id, component)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
bail!("component {name} already present");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ComponentChange::Removed(type_id) => {
|
||||||
|
if let Some(mut component) =
|
||||||
|
entity_object.remove_component_by_id(type_id)
|
||||||
|
{
|
||||||
|
component.disable(self)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_object.activation_state.apply_change();
|
||||||
|
|
||||||
|
self.updates.add_entity(entity_object, &self.entities)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
pub fn run(&mut self) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
let mut events = self.events.take_events();
|
||||||
|
events.fire_events(self)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
// actually safe:
|
||||||
|
// - updates can't be altered on a running world
|
||||||
|
// - entity changes are processed afterwards
|
||||||
|
let w = unsafe { remove_life_time_mut(self) };
|
||||||
|
|
||||||
|
self.updates.update(w)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.commit_entity_changes()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ 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 = ["bundle_sdl2", "sound"] }
|
context = { path = "../context", features = ["bundle_sdl2", "sound"] }
|
||||||
|
ecs = { path = "../ecs" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
timings = []
|
timings = []
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use super::entity_object_manager::EntityObjectManager;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
|
|
||||||
|
|
||||||
use crate::prelude::EntityObject;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct EntityObjectManager {
|
|
||||||
current_entity_id: AtomicU32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EntityObjectManager {
|
|
||||||
pub(crate) fn fetch_add_entity_id(&self) -> u32 {
|
|
||||||
self.current_entity_id.fetch_add(1, SeqCst)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn create_entity(&self) -> EntityObject {
|
|
||||||
EntityObject::new(self.fetch_add_entity_id())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,6 @@
|
||||||
pub mod assetcache;
|
pub mod assetcache;
|
||||||
|
|
||||||
pub mod assetmanager;
|
pub mod assetmanager;
|
||||||
|
|
||||||
pub mod entity_object_manager;
|
|
||||||
|
|
||||||
use std::{collections::HashMap, path::Path};
|
use std::{collections::HashMap, path::Path};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::assets::assetmanager::AssetManager;
|
use crate::assets::assetmanager::AssetManager;
|
||||||
|
|
||||||
use crate::{assets::entity_object_manager::EntityObjectManager, prelude::*};
|
use crate::prelude::*;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ use context::prelude::cgmath::vec3;
|
||||||
use loading_screen::LoadingScreen;
|
use loading_screen::LoadingScreen;
|
||||||
|
|
||||||
use crate::assets::assetmanager::AssetManager;
|
use crate::assets::assetmanager::AssetManager;
|
||||||
use crate::assets::entity_object_manager::EntityObjectManager;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub use serde::{
|
||||||
ser::{SerializeMap, SerializeSeq, SerializeStruct},
|
ser::{SerializeMap, SerializeSeq, SerializeStruct},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use ecs::*;
|
||||||
pub use ron;
|
pub use ron;
|
||||||
|
|
||||||
pub use crate::assets::assetcache::AssetCache;
|
pub use crate::assets::assetcache::AssetCache;
|
||||||
|
|
|
@ -175,7 +175,7 @@ impl Clone for Animation {
|
||||||
|
|
||||||
impl EntityComponent for Animation {
|
impl EntityComponent for Animation {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"Animation"
|
Self::debug_name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,11 +164,11 @@ impl EntityComponent for Audio {
|
||||||
Self::debug_name()
|
Self::debug_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(&mut self, _scene: &mut Scene) -> Result<()> {
|
fn enable(&mut self, _world: &mut World) -> Result<()> {
|
||||||
self.play(ON_ENABLE_SOUND, false)
|
self.play(ON_ENABLE_SOUND, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(&mut self, _scene: &mut Scene) -> Result<()> {
|
fn disable(&mut self, _world: &mut World) -> Result<()> {
|
||||||
self.play(ON_DISABLE_SOUND, false)
|
self.play(ON_DISABLE_SOUND, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl From<GltfBB> for BoundingBox {
|
||||||
|
|
||||||
impl EntityComponent for BoundingBox {
|
impl EntityComponent for BoundingBox {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"BoundingBox"
|
Self::debug_name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl Index<usize> for Draw {
|
||||||
|
|
||||||
impl EntityComponent for Draw {
|
impl EntityComponent for Draw {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"Draw"
|
Self::debug_name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
use asset::*;
|
use asset::*;
|
||||||
|
|
||||||
use utilities::prelude::cgmath::{vec3, Deg, InnerSpace, Matrix4};
|
use utilities::prelude::cgmath::{Deg, InnerSpace, Matrix4, vec3};
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ impl ParticleSystemInfoBuffer {
|
||||||
|
|
||||||
pub struct ParticleSystemVulkanObjects {
|
pub struct ParticleSystemVulkanObjects {
|
||||||
descriptor_set_layout: Arc<DescriptorSetLayout>,
|
descriptor_set_layout: Arc<DescriptorSetLayout>,
|
||||||
pipeline: Arc<Pipeline>,
|
pub(crate) pipeline: Arc<Pipeline>,
|
||||||
|
|
||||||
command_buffer: Arc<CommandBuffer>,
|
command_buffer: Arc<CommandBuffer>,
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ impl ParticleSystem {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
info: ParticleSystemInfo,
|
info: ParticleSystemInfo,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
scene: &impl SceneEntities,
|
scene: &Scene,
|
||||||
draw: &mut Draw,
|
draw: &mut Draw,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Self::_new(
|
Self::_new(
|
||||||
|
@ -410,12 +410,12 @@ impl ParticleSystem {
|
||||||
pub(crate) fn animate(
|
pub(crate) fn animate(
|
||||||
&self,
|
&self,
|
||||||
recorder: &mut CommandBufferRecorder<'_>,
|
recorder: &mut CommandBufferRecorder<'_>,
|
||||||
scene: &SceneContents<'_>,
|
pipeline: &Arc<Pipeline>,
|
||||||
time: Duration,
|
world: &World,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
recorder.bind_pipeline(&scene.particle_system_vulkan_objects().pipeline)?;
|
recorder.bind_pipeline(pipeline)?;
|
||||||
recorder.bind_descriptor_sets_minimal(&[&self.descriptor_set]);
|
recorder.bind_descriptor_sets_minimal(&[&self.descriptor_set]);
|
||||||
recorder.push_constants(VK_SHADER_STAGE_COMPUTE_BIT, &time.as_secs_f32());
|
recorder.push_constants(VK_SHADER_STAGE_COMPUTE_BIT, &world.now().as_secs_f32());
|
||||||
recorder.dispatch(self.particle_buffer.size() as u32, 1, 1);
|
recorder.dispatch(self.particle_buffer.size() as u32, 1, 1);
|
||||||
|
|
||||||
recorder.buffer_barrier(
|
recorder.buffer_barrier(
|
||||||
|
@ -565,8 +565,8 @@ impl ParticleSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntityComponent for ParticleSystem {
|
impl EntityComponent for ParticleSystem {
|
||||||
fn enable(&mut self, scene: &mut Scene) -> Result<()> {
|
fn enable(&mut self, world: &mut World) -> Result<()> {
|
||||||
let now = scene.now();
|
let now = world.now();
|
||||||
self.start = now;
|
self.start = now;
|
||||||
|
|
||||||
// Copy gpu only buffer into temporary cpu buffer to modify starting time
|
// Copy gpu only buffer into temporary cpu buffer to modify starting time
|
||||||
|
@ -574,15 +574,15 @@ impl EntityComponent for ParticleSystem {
|
||||||
{
|
{
|
||||||
let now_f32 = now.as_secs_f32();
|
let now_f32 = now.as_secs_f32();
|
||||||
|
|
||||||
let fence = Fence::builder().build(scene.device().clone())?;
|
let fence = Fence::builder().build(world.device().clone())?;
|
||||||
let command_buffer = CommandBuffer::new_primary()
|
let command_buffer = CommandBuffer::new_primary()
|
||||||
.build(scene.device().clone(), scene.queue().clone())?;
|
.build(world.device().clone(), world.queue().clone())?;
|
||||||
|
|
||||||
let cpu_buffer: Arc<Buffer<ParticleInfoBuffer>> = Buffer::builder()
|
let cpu_buffer: Arc<Buffer<ParticleInfoBuffer>> = Buffer::builder()
|
||||||
.set_memory_usage(MemoryUsage::GpuToCpu)
|
.set_memory_usage(MemoryUsage::GpuToCpu)
|
||||||
.set_usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
.set_usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
||||||
.set_size(self.particle_buffer.size())
|
.set_size(self.particle_buffer.size())
|
||||||
.build(scene.device().clone())?;
|
.build(world.device().clone())?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
||||||
|
@ -602,12 +602,12 @@ impl EntityComponent for ParticleSystem {
|
||||||
|
|
||||||
// submit
|
// submit
|
||||||
let submit = SubmitInfo::default().add_command_buffer(&command_buffer);
|
let submit = SubmitInfo::default().add_command_buffer(&command_buffer);
|
||||||
scene
|
world
|
||||||
.queue()
|
.queue()
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.submit(Some(&fence), &[submit])?;
|
.submit(Some(&fence), &[submit])?;
|
||||||
scene
|
world
|
||||||
.device()
|
.device()
|
||||||
.wait_for_fences(&[&fence], true, Duration::from_secs(1))?;
|
.wait_for_fences(&[&fence], true, Duration::from_secs(1))?;
|
||||||
|
|
||||||
|
@ -653,12 +653,12 @@ impl EntityComponent for ParticleSystem {
|
||||||
|
|
||||||
// submit
|
// submit
|
||||||
let submit = SubmitInfo::default().add_command_buffer(&command_buffer);
|
let submit = SubmitInfo::default().add_command_buffer(&command_buffer);
|
||||||
scene
|
world
|
||||||
.queue()
|
.queue()
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.submit(Some(&fence), &[submit])?;
|
.submit(Some(&fence), &[submit])?;
|
||||||
scene
|
world
|
||||||
.device()
|
.device()
|
||||||
.wait_for_fences(&[&fence], true, Duration::from_secs(1))?;
|
.wait_for_fences(&[&fence], true, Duration::from_secs(1))?;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +667,7 @@ impl EntityComponent for ParticleSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"ParticleSystem"
|
Self::debug_name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@ pub mod components;
|
||||||
|
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
mod query;
|
// mod query;
|
||||||
|
|
|
@ -9,4 +9,4 @@ pub use super::components::{
|
||||||
particle_system::*,
|
particle_system::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use super::query::SceneQuery;
|
// pub use super::query::SceneQuery;
|
||||||
|
|
|
@ -87,64 +87,64 @@ macro_rules! impl_add_query {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl< 'a, $( $var, )+ > CheckEntity< ( $( $var, )+ ) > for Entities<'a>
|
// impl< 'a, $( $var, )+ > CheckEntity< ( $( $var, )+ ) > for Entities<'a>
|
||||||
where
|
// where
|
||||||
$(
|
// $(
|
||||||
$var: EntityComponent + ComponentDebug,
|
// $var: EntityComponent + ComponentDebug,
|
||||||
)+
|
// )+
|
||||||
{
|
// {
|
||||||
fn check_entity<Filter>(entity: &EntityObject) -> bool
|
// fn check_entity<Filter>(entity: &EntityObject) -> bool
|
||||||
where
|
// where
|
||||||
Filter: CheckFilter,
|
// Filter: CheckFilter,
|
||||||
{
|
// {
|
||||||
let filter = Filter::default();
|
// let filter = Filter::default();
|
||||||
|
|
||||||
$(
|
// $(
|
||||||
filter.verify_dedup::<$var>();
|
// filter.verify_dedup::<$var>();
|
||||||
)+
|
// )+
|
||||||
|
|
||||||
$(
|
// $(
|
||||||
if !entity.components.contains::<$var>() {
|
// if !entity.components.contains::<$var>() {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
)+
|
// )+
|
||||||
|
|
||||||
if !filter.check(entity) {
|
// if !filter.check(entity) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<'a, $( $var, )+ F > SceneQuery<'a, ( $( &'a $var, )+ ), F > for Entities<'a>
|
// impl<'a, $( $var, )+ F > SceneQuery<'a, ( $( &'a $var, )+ ), F > for Entities<'a>
|
||||||
where
|
// where
|
||||||
$(
|
// $(
|
||||||
$var: EntityComponent + ComponentDebug,
|
// $var: EntityComponent + ComponentDebug,
|
||||||
)+
|
// )+
|
||||||
Self: CheckEntity<( $( $var, )+ )>,
|
// Self: CheckEntity<( $( $var, )+ )>,
|
||||||
F: FnMut(Entity, $( &'a $var, )+) -> Result<()>,
|
// F: FnMut(Entity, $( &'a $var, )+) -> Result<()>,
|
||||||
{
|
// {
|
||||||
fn query<Filter>(&'a self, mut f: F) -> Result<()>
|
// fn query<Filter>(&'a self, mut f: F) -> Result<()>
|
||||||
where
|
// where
|
||||||
Filter: CheckFilter,
|
// Filter: CheckFilter,
|
||||||
{
|
// {
|
||||||
paste::paste! {
|
// paste::paste! {
|
||||||
self.entities.iter().filter_map(|(entity, object)| {
|
// self.entities.iter().filter_map(|(entity, object)| {
|
||||||
if Self::check_entity::<Filter>(object) {
|
// if Self::check_entity::<Filter>(object) {
|
||||||
$(
|
// $(
|
||||||
let [< $var:lower >] = object.get_component::<$var>().unwrap();
|
// let [< $var:lower >] = object.get_component::<$var>().unwrap();
|
||||||
)+
|
// )+
|
||||||
|
|
||||||
Some(( entity, $( [< $var:lower >], )+ ))
|
// Some(( entity, $( [< $var:lower >], )+ ))
|
||||||
} else {
|
// } else {
|
||||||
None
|
// None
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.try_for_each(|( entity, $( [< $var:lower >], )+ )| f( *entity, $( [< $var:lower >], )+ ))
|
// .try_for_each(|( entity, $( [< $var:lower >], )+ )| f( *entity, $( [< $var:lower >], )+ ))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,20 @@ use std::sync::Arc;
|
||||||
|
|
||||||
pub const SHADER_OPTION_COUNT: usize = 9;
|
pub const SHADER_OPTION_COUNT: usize = 9;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! include_shader {
|
||||||
|
($path: expr) => {{
|
||||||
|
let shader = include_str!($path);
|
||||||
|
let file_name = std::path::Path::new($path)
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(shader, file_name)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
pub enum ShadersType {
|
pub enum ShadersType {
|
||||||
Graphics(
|
Graphics(
|
||||||
Arc<ShaderModule<shader_type::Vertex>>,
|
Arc<ShaderModule<shader_type::Vertex>>,
|
||||||
|
@ -56,10 +70,10 @@ pub struct ShaderCompiler<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ShaderCompiler<'a> {
|
impl<'a> ShaderCompiler<'a> {
|
||||||
pub fn new(files: Vec<(&'a str, &'a str)>) -> Result<ShaderCompiler<'a>> {
|
pub fn new(files: impl IntoIterator<Item = (&'a str, &'a str)>) -> Result<ShaderCompiler<'a>> {
|
||||||
Ok(ShaderCompiler {
|
Ok(ShaderCompiler {
|
||||||
compiler: Self::create_compiler()?,
|
compiler: Self::create_compiler()?,
|
||||||
files,
|
files: files.into_iter().collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
mod scene_base;
|
mod scene_base;
|
||||||
mod scene_content;
|
// mod scene_content;
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pub use super::scene_base::Scene;
|
pub use super::scene_base::Scene;
|
||||||
pub use super::scene_content::{ContentEvents, Entities, SceneContents, SceneEntities};
|
// pub use super::scene_content::{ContentEvents, Entities, SceneContents, SceneEntities};
|
||||||
|
|
|
@ -1,74 +1,29 @@
|
||||||
use crate::scene::content::events::Events;
|
use crate::scene::rendering::{
|
||||||
use crate::scene::rendering::rasterizer::deferred::Rasterizer;
|
ExtensionCheck, RenderingFrontEnd,
|
||||||
use crate::scene::rendering::rasterizer::traditional::TraditionalRasterizer;
|
rasterizer::{deferred::Rasterizer, traditional::TraditionalRasterizer},
|
||||||
use crate::scene::rendering::raytracer::hardwareraytracer::HardwareRayTracer;
|
raytracer::{
|
||||||
use crate::scene::rendering::raytracer::raytracer::RayTracer;
|
hardwareraytracer::HardwareRayTracer, raytracer::RayTracer,
|
||||||
use crate::scene::rendering::raytracer::softwareraytracer::SoftwareRayTracer;
|
softwareraytracer::SoftwareRayTracer,
|
||||||
use crate::scene::rendering::shared::shadercompiler::{ShaderCompiler, ShaderTypeConverter};
|
},
|
||||||
use crate::{prelude::*, scene::content::updates::Updates};
|
shared::shadercompiler::{ShaderCompiler, ShaderTypeConverter},
|
||||||
|
};
|
||||||
use crate::scene::content::entity::EntityObject;
|
use crate::{include_shader, prelude::*};
|
||||||
|
|
||||||
use crate::scene::rendering::{ExtensionCheck, RenderingFrontEnd};
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
#[cfg(feature = "timings")]
|
||||||
use super::super::timings::Timings;
|
use super::super::timings::Timings;
|
||||||
|
|
||||||
use super::scene_content::EntityNotFoundError;
|
use anyhow::Result;
|
||||||
|
use ecs::*;
|
||||||
use utilities::prelude::cgmath::{vec3, Matrix4, Vector3};
|
|
||||||
|
|
||||||
use anyhow::{bail, Error, Result};
|
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use utilities::prelude::cgmath::{Matrix4, Vector3, vec3};
|
||||||
use std::any::{Any, TypeId};
|
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
#[cfg(feature = "timings")]
|
#[cfg(feature = "timings")]
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use std::{collections::HashSet, mem, time::Duration};
|
use std::sync::Arc;
|
||||||
use std::{ptr::NonNull, sync::Arc};
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct EntityMultiMut<'a> {
|
|
||||||
entities: &'a mut IndexMap<Entity, EntityObject>,
|
|
||||||
buffer: HashSet<Entity>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> EntityMultiMut<'a> {
|
|
||||||
pub(crate) fn new(entities: &'a mut IndexMap<Entity, EntityObject>) -> Self {
|
|
||||||
Self {
|
|
||||||
entities,
|
|
||||||
buffer: HashSet::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(
|
|
||||||
&mut self,
|
|
||||||
entity: Entity,
|
|
||||||
) -> std::result::Result<&'a mut EntityObject, EntityNotFoundError> {
|
|
||||||
match self.entities.get_mut(&entity) {
|
|
||||||
Some(v) => {
|
|
||||||
let ptr = v as *mut EntityObject;
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
self.buffer.get(&entity).is_none(),
|
|
||||||
"Entity ({}) already borrowed",
|
|
||||||
entity.id
|
|
||||||
);
|
|
||||||
self.buffer.insert(entity);
|
|
||||||
|
|
||||||
let e: Option<&'a mut EntityObject> = Some(unsafe { &mut *ptr });
|
|
||||||
|
|
||||||
e.ok_or_else(|| EntityNotFoundError::new(entity))
|
|
||||||
}
|
|
||||||
None => Err(EntityNotFoundError::new(entity)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
screen_width: f32,
|
screen_width: f32,
|
||||||
|
@ -79,12 +34,6 @@ pub struct Scene {
|
||||||
|
|
||||||
pub(crate) render_type: SceneType,
|
pub(crate) render_type: SceneType,
|
||||||
|
|
||||||
pub(crate) updates: Updates,
|
|
||||||
pub(crate) archetypes: Archetypes,
|
|
||||||
pub(crate) events: Events,
|
|
||||||
pub resources: Resources,
|
|
||||||
|
|
||||||
pub(crate) entities: IndexMap<Entity, EntityObject>,
|
|
||||||
pub(crate) map: Option<Box<dyn Map>>,
|
pub(crate) map: Option<Box<dyn Map>>,
|
||||||
|
|
||||||
pub(crate) start_time: Instant,
|
pub(crate) start_time: Instant,
|
||||||
|
@ -117,7 +66,8 @@ impl Scene {
|
||||||
rasterizer_info: RasterizerInfo,
|
rasterizer_info: RasterizerInfo,
|
||||||
raytracer_info: RaytracingInfo,
|
raytracer_info: RaytracingInfo,
|
||||||
graphics_info: GraphicsInfo,
|
graphics_info: GraphicsInfo,
|
||||||
) -> Result<Self> {
|
world: &mut WorldBuilder,
|
||||||
|
) -> Result<()> {
|
||||||
let (renderer, render_type): (Box<dyn RenderingFrontEnd + Send + Sync>, SceneType) =
|
let (renderer, render_type): (Box<dyn RenderingFrontEnd + Send + Sync>, SceneType) =
|
||||||
Self::create_rendering_front_end(
|
Self::create_rendering_front_end(
|
||||||
device,
|
device,
|
||||||
|
@ -129,9 +79,8 @@ impl Scene {
|
||||||
graphics_info,
|
graphics_info,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let compiler = ShaderCompiler::new(vec![(
|
let compiler = ShaderCompiler::new([include_shader!(
|
||||||
include_str!("../content/components/particle_system.comp"),
|
"../content/components/particle_system.comp"
|
||||||
"particle_system.comp",
|
|
||||||
)])?;
|
)])?;
|
||||||
|
|
||||||
let cs = compiler.compile::<_, 0>(device, &[], |_| {})?;
|
let cs = compiler.compile::<_, 0>(device, &[], |_| {})?;
|
||||||
|
@ -146,12 +95,6 @@ impl Scene {
|
||||||
|
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
queue: queue.clone(),
|
queue: queue.clone(),
|
||||||
|
|
||||||
updates: Updates::default(),
|
|
||||||
archetypes: Archetypes::default(),
|
|
||||||
events: Events::default(),
|
|
||||||
resources: Resources::default(),
|
|
||||||
entities: IndexMap::new(),
|
|
||||||
map: None,
|
map: None,
|
||||||
|
|
||||||
frustum_check: None,
|
frustum_check: None,
|
||||||
|
@ -174,22 +117,15 @@ impl Scene {
|
||||||
.add_timing("renderer"),
|
.add_timing("renderer"),
|
||||||
};
|
};
|
||||||
|
|
||||||
scene.insert_default_updates()?;
|
Self::insert_default_updates(world)?;
|
||||||
|
world.resources.insert(scene);
|
||||||
|
|
||||||
Ok(scene)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// object handling
|
// object handling
|
||||||
impl Scene {
|
impl Scene {
|
||||||
#[inline]
|
|
||||||
fn _entity_mut(
|
|
||||||
entities: &mut IndexMap<Entity, EntityObject>,
|
|
||||||
entity: Entity,
|
|
||||||
) -> Option<&mut EntityObject> {
|
|
||||||
entities.get_mut(&entity)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_map(&mut self, map_opt: Option<Box<dyn Map>>) -> Result<()> {
|
pub fn set_map(&mut self, map_opt: Option<Box<dyn Map>>) -> Result<()> {
|
||||||
if let Some(old_map) = self.map.take() {
|
if let Some(old_map) = self.map.take() {
|
||||||
old_map.disable(self)?;
|
old_map.disable(self)?;
|
||||||
|
@ -199,150 +135,6 @@ impl Scene {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_content(&mut self) -> Result<()> {
|
|
||||||
let mut entities = IndexMap::new();
|
|
||||||
mem::swap(&mut self.entities, &mut entities);
|
|
||||||
|
|
||||||
for (_, entity) in entities.iter_mut() {
|
|
||||||
for (_, component) in entity.components.iter_mut() {
|
|
||||||
component.disable(self)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.map = None;
|
|
||||||
self.updates.clear();
|
|
||||||
self.archetypes.clear();
|
|
||||||
self.events.clear();
|
|
||||||
|
|
||||||
self.insert_default_updates()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_resource(&mut self) -> (&mut View, &mut Resources) {
|
|
||||||
(self.renderer.view_mut(), &mut self.resources)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scene {
|
|
||||||
pub fn add_archetype(&mut self, id: impl ToString, mut archetype: Archetype) -> Result<()> {
|
|
||||||
archetype.setup(&self.entities)?;
|
|
||||||
self.archetypes.insert(id.to_string(), archetype);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_event<T: Any + Send + Sync>(&mut self) {
|
|
||||||
self.events.register_event::<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_event_reader<T: Any + Send + Sync, F>(&mut self, f: F)
|
|
||||||
where
|
|
||||||
F: Fn(&mut SceneContents<'_>, &T) -> anyhow::Result<()> + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
self.events.add_reader(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
|
|
||||||
self.events.write_event(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_scene_contents(&mut self) -> SceneContents<'_> {
|
|
||||||
SceneContents::new(
|
|
||||||
&self.device,
|
|
||||||
&self.queue,
|
|
||||||
self.render_type,
|
|
||||||
self.frame_time,
|
|
||||||
self.start_time,
|
|
||||||
(self.screen_width, self.screen_height),
|
|
||||||
&mut self.entities,
|
|
||||||
&self.map,
|
|
||||||
(&mut self.renderer, &mut self.particle_system_vulkan_objects),
|
|
||||||
&self.archetypes,
|
|
||||||
&mut self.events,
|
|
||||||
&mut self.resources,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn update(&mut self) -> Result<()> {
|
|
||||||
let mut temp_events = self.events.clone_from_register();
|
|
||||||
|
|
||||||
let mut scene_content = SceneContents::new(
|
|
||||||
&self.device,
|
|
||||||
&self.queue,
|
|
||||||
self.render_type,
|
|
||||||
self.frame_time,
|
|
||||||
self.start_time,
|
|
||||||
(self.screen_width, self.screen_height),
|
|
||||||
&mut self.entities,
|
|
||||||
&self.map,
|
|
||||||
(&mut self.renderer, &mut self.particle_system_vulkan_objects),
|
|
||||||
&self.archetypes,
|
|
||||||
&mut temp_events,
|
|
||||||
&mut self.resources,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
let before = Instant::now();
|
|
||||||
|
|
||||||
self.events.fire_events(&mut scene_content)?;
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
self.timings
|
|
||||||
.add("fire events", Instant::now().duration_since(before));
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
let before = Instant::now();
|
|
||||||
|
|
||||||
self.updates.update(&mut scene_content)?;
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
self.timings
|
|
||||||
.add("updates", Instant::now().duration_since(before));
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
let before = Instant::now();
|
|
||||||
|
|
||||||
self.events.move_events(scene_content.events.events);
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
self.timings
|
|
||||||
.add("move events", Instant::now().duration_since(before));
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
let before = Instant::now();
|
|
||||||
|
|
||||||
scene_content.entity_changes().commit(self)?;
|
|
||||||
|
|
||||||
#[cfg(feature = "timings")]
|
|
||||||
self.timings
|
|
||||||
.add("entity changes", Instant::now().duration_since(before));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn execute_archetype(&mut self, name: impl ToString) -> Result<()> {
|
|
||||||
let mut scene_content = SceneContents::new(
|
|
||||||
&self.device,
|
|
||||||
&self.queue,
|
|
||||||
self.render_type,
|
|
||||||
self.frame_time,
|
|
||||||
self.start_time,
|
|
||||||
(self.screen_width, self.screen_height),
|
|
||||||
&mut self.entities,
|
|
||||||
&self.map,
|
|
||||||
(&mut self.renderer, &mut self.particle_system_vulkan_objects),
|
|
||||||
&self.archetypes,
|
|
||||||
&mut self.events,
|
|
||||||
&mut self.resources,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.archetypes
|
|
||||||
.execute(&name.to_string(), &mut scene_content)?;
|
|
||||||
|
|
||||||
scene_content.entity_changes().commit(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
|
@ -368,31 +160,26 @@ impl Scene {
|
||||||
Ok((x, y))
|
Ok((x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn insert_default_updates(&mut self) -> Result<()> {
|
pub(crate) fn insert_default_updates(world: &mut WorldBuilder) -> Result<()> {
|
||||||
self.add_update(
|
world.add_update(
|
||||||
"animate",
|
"animate",
|
||||||
5_500_000,
|
5_500_000,
|
||||||
|scene_contents: &mut SceneContents<'_>,
|
|world: &mut World, _entity, draw: &mut Draw, animation: &mut Animation| {
|
||||||
_entity,
|
animation.animate(world.now(), draw)?;
|
||||||
draw: &mut Draw,
|
|
||||||
animation: &mut Animation| {
|
|
||||||
animation.animate(scene_contents.now(), draw)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
EmptyFilter,
|
EmptyFilter,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.add_update(
|
world.add_update(
|
||||||
"particle_system",
|
"particle_system",
|
||||||
5_000_000,
|
5_000_000,
|
||||||
|scene_contents: &mut SceneContents<'_>,
|
|world: &mut World, entity, particle_system: &mut ParticleSystem| {
|
||||||
entity,
|
let now = world.now();
|
||||||
particle_system: &mut ParticleSystem| {
|
|
||||||
let now = scene_contents.now();
|
|
||||||
|
|
||||||
if !particle_system.update(now) {
|
if !particle_system.update(now) {
|
||||||
scene_contents.remove_entity(entity)?;
|
world.remove_entity(entity)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,13 +189,12 @@ impl Scene {
|
||||||
VkCommandBufferBeginInfo::new(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
VkCommandBufferBeginInfo::new(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||||
begin_info.set_inheritance_info(&inheritance_info);
|
begin_info.set_inheritance_info(&inheritance_info);
|
||||||
|
|
||||||
let unsafe_scene = unsafe { remove_life_time_mut(scene_contents) };
|
let scene = world.resources.get_mut::<Scene>();
|
||||||
|
|
||||||
let mut recorder = scene_contents
|
let particle_handles = scene.particle_system_vulkan_objects_mut();
|
||||||
.particle_system_vulkan_objects_mut()
|
let mut recorder = particle_handles.begin(begin_info)?;
|
||||||
.begin(begin_info)?;
|
|
||||||
|
|
||||||
particle_system.animate(&mut recorder, unsafe_scene, now)?;
|
particle_system.animate(&mut recorder, &particle_handles.pipeline, world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -616,7 +402,7 @@ impl Scene {
|
||||||
let frustum = view.frustum();
|
let frustum = view.frustum();
|
||||||
let planes = frustum.planes();
|
let planes = frustum.planes();
|
||||||
|
|
||||||
let content: Vec<Option<&EntityObject>> = self
|
let content: Vec<Option<&EntityObject<Self>>> = self
|
||||||
.entities
|
.entities
|
||||||
.par_values()
|
.par_values()
|
||||||
.map(|entity_object| {
|
.map(|entity_object| {
|
||||||
|
@ -652,199 +438,8 @@ impl Scene {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SceneEntities for Scene {
|
pub fn world_to_screen_space(&self, world_space: Vector3<f32>) -> Result<(i32, i32)> {
|
||||||
fn device(&self) -> &Arc<Device> {
|
|
||||||
&self.device
|
|
||||||
}
|
|
||||||
|
|
||||||
fn queue(&self) -> &Arc<Mutex<Queue>> {
|
|
||||||
&self.queue
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entity(&self, entity: Entity) -> std::result::Result<&EntityObject, EntityNotFoundError> {
|
|
||||||
self.entities
|
|
||||||
.get(&entity)
|
|
||||||
.ok_or_else(|| EntityNotFoundError::new(entity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entity_mut(
|
|
||||||
&mut self,
|
|
||||||
entity: Entity,
|
|
||||||
) -> std::result::Result<&mut EntityObject, EntityNotFoundError> {
|
|
||||||
self.entities
|
|
||||||
.get_mut(&entity)
|
|
||||||
.ok_or_else(|| EntityNotFoundError::new(entity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entities_multi_mut(&mut self) -> EntityMultiMut<'_> {
|
|
||||||
EntityMultiMut::new(&mut self.entities)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_entity(&mut self, mut entity: EntityObject) -> Result<Entity> {
|
|
||||||
// call enable event for all components
|
|
||||||
for (_, component) in entity.components.iter_mut() {
|
|
||||||
component.enable(self)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.activation_state.apply_change();
|
|
||||||
|
|
||||||
let e = entity.as_entity();
|
|
||||||
|
|
||||||
self.updates.add_entity(&mut entity, &self.entities)?;
|
|
||||||
self.archetypes.add_entity(&mut entity)?;
|
|
||||||
assert!(self.entities.insert(e, entity).is_none());
|
|
||||||
|
|
||||||
Ok(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entity_resource(&mut self, entity: Entity) -> Result<(&mut Resources, &mut EntityObject)> {
|
|
||||||
Ok((
|
|
||||||
unsafe { remove_life_time_mut(&mut self.resources) },
|
|
||||||
self.entity_mut(entity)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn archetype_info(&self, name: impl ToString) -> Result<ArchetypeInfo> {
|
|
||||||
let name = name.to_string();
|
|
||||||
let archetype = self
|
|
||||||
.archetypes
|
|
||||||
.get(&name)
|
|
||||||
.ok_or_else(|| Error::msg(format!("requested archetype ({}) not found", name)))?;
|
|
||||||
|
|
||||||
let mut entities = Vec::new();
|
|
||||||
|
|
||||||
for entity in archetype.entities().keys() {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
let debug_name = self.entity(*entity)?.debug_name.clone();
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
let debug_name = None;
|
|
||||||
|
|
||||||
entities.push((*entity, debug_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ArchetypeInfo::new(entities))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_component<T: EntityComponent + ComponentDebug>(
|
|
||||||
&mut self,
|
|
||||||
entity: Entity,
|
|
||||||
mut component: T,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
|
|
||||||
|
|
||||||
let entity_object = entities
|
|
||||||
.get_mut(&entity)
|
|
||||||
.ok_or_else(|| EntityNotFoundError::new(entity))?;
|
|
||||||
|
|
||||||
self.updates.remove_entity(entity);
|
|
||||||
self.archetypes.remove_entity(entity);
|
|
||||||
|
|
||||||
entity_object.activation_state.apply_change();
|
|
||||||
|
|
||||||
component.enable(self)?;
|
|
||||||
if entity_object.insert_component(component).is_some() {
|
|
||||||
bail!("component {} already present", T::debug_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_object.activation_state.apply_change();
|
|
||||||
|
|
||||||
self.updates.add_entity(entity_object, &self.entities)?;
|
|
||||||
self.archetypes.add_entity(entity_object)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_component<T: EntityComponent + ComponentDebug>(
|
|
||||||
&mut self,
|
|
||||||
entity: Entity,
|
|
||||||
) -> Result<()> {
|
|
||||||
let entities = unsafe { remove_life_time_mut(&mut self.entities) };
|
|
||||||
|
|
||||||
let entity_object = entities
|
|
||||||
.get_mut(&entity)
|
|
||||||
.ok_or_else(|| EntityNotFoundError::new(entity))?;
|
|
||||||
|
|
||||||
self.updates.remove_entity(entity);
|
|
||||||
self.archetypes.remove_entity(entity);
|
|
||||||
|
|
||||||
entity_object.activation_state.apply_change();
|
|
||||||
|
|
||||||
if let Some(mut component) = entity_object.remove_component_by_id(TypeId::of::<T>()) {
|
|
||||||
component.disable(self)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_object.activation_state.apply_change();
|
|
||||||
|
|
||||||
self.updates.add_entity(entity_object, &self.entities)?;
|
|
||||||
self.archetypes.add_entity(entity_object)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
|
|
||||||
self.write_event(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_entity(&mut self, entity: Entity) -> Result<Option<EntityObject>> {
|
|
||||||
if let Some(mut entity_object) = self.entities.swap_remove(&entity) {
|
|
||||||
for (_, component) in entity_object.components.iter_mut() {
|
|
||||||
component.disable(self)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_object.activation_state.apply_change();
|
|
||||||
self.updates.remove_entity(entity);
|
|
||||||
self.archetypes.remove_entity(entity);
|
|
||||||
|
|
||||||
return Ok(Some(entity_object));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function will panic if map is not set!
|
|
||||||
fn map<F, T>(&mut self, f: F) -> Result<T>
|
|
||||||
where
|
|
||||||
F: FnOnce(&Box<dyn Map>, &mut SceneContents<'_>) -> Result<T>,
|
|
||||||
{
|
|
||||||
let map = self
|
|
||||||
.map
|
|
||||||
.as_ref()
|
|
||||||
.expect("Map is not set while trying to call map");
|
|
||||||
let p = map as *const Box<dyn Map> as *mut Box<dyn Map>;
|
|
||||||
|
|
||||||
let mut scene_content = SceneContents::new(
|
|
||||||
&self.device,
|
|
||||||
&self.queue,
|
|
||||||
self.render_type,
|
|
||||||
self.frame_time,
|
|
||||||
self.start_time,
|
|
||||||
(self.screen_width, self.screen_height),
|
|
||||||
&mut self.entities,
|
|
||||||
&self.map,
|
|
||||||
(&mut self.renderer, &mut self.particle_system_vulkan_objects),
|
|
||||||
&self.archetypes,
|
|
||||||
&mut self.events,
|
|
||||||
&mut self.resources,
|
|
||||||
);
|
|
||||||
|
|
||||||
let result = f(
|
|
||||||
unsafe { NonNull::new_unchecked(p).as_ref() },
|
|
||||||
&mut scene_content,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
scene_content.entity_changes().commit(self)?;
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn now(&self) -> Duration {
|
|
||||||
Instant::now().duration_since(self.start_time)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn world_to_screen_space(&self, world_space: Vector3<f32>) -> Result<(i32, i32)> {
|
|
||||||
Self::_world_to_screen_space(
|
Self::_world_to_screen_space(
|
||||||
(self.screen_width, self.screen_height),
|
(self.screen_width, self.screen_height),
|
||||||
world_space,
|
world_space,
|
||||||
|
@ -852,48 +447,48 @@ impl SceneEntities for Scene {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn screen_space_to_world(&self, x: u32, y: u32) -> Result<Option<Vector3<f32>>> {
|
pub fn screen_space_to_world(&self, x: u32, y: u32) -> Result<Option<Vector3<f32>>> {
|
||||||
let scale = self.renderer.render_scale();
|
let scale = self.renderer.render_scale();
|
||||||
|
|
||||||
self.renderer
|
self.renderer
|
||||||
.screen_to_world((x as f32 * scale) as u32, (y as f32 * scale) as u32)
|
.screen_to_world((x as f32 * scale) as u32, (y as f32 * scale) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn particle_system_vulkan_objects_mut(&mut self) -> &mut ParticleSystemVulkanObjects {
|
pub fn particle_system_vulkan_objects_mut(&mut self) -> &mut ParticleSystemVulkanObjects {
|
||||||
&mut self.particle_system_vulkan_objects
|
&mut self.particle_system_vulkan_objects
|
||||||
}
|
}
|
||||||
|
|
||||||
fn particle_system_vulkan_objects(&self) -> &ParticleSystemVulkanObjects {
|
pub fn particle_system_vulkan_objects(&self) -> &ParticleSystemVulkanObjects {
|
||||||
&self.particle_system_vulkan_objects
|
&self.particle_system_vulkan_objects
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_light(&mut self, light: Light) -> Result<()> {
|
pub fn add_light(&mut self, light: Light) -> Result<()> {
|
||||||
self.renderer.add_light(light)?;
|
self.renderer.add_light(light)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_light(&mut self, light: Light) -> Result<()> {
|
pub fn remove_light(&mut self, light: Light) -> Result<()> {
|
||||||
self.renderer.remove_light(light)?;
|
self.renderer.remove_light(light)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_lights(&mut self) -> Result<()> {
|
pub fn clear_lights(&mut self) -> Result<()> {
|
||||||
self.renderer.clear_lights()?;
|
self.renderer.clear_lights()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_mut(&mut self) -> &mut View {
|
pub fn view_mut(&mut self) -> &mut View {
|
||||||
self.renderer.view_mut()
|
self.renderer.view_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_type(&self) -> SceneType {
|
pub fn render_type(&self) -> SceneType {
|
||||||
self.render_type
|
self.render_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_time(&self) -> Duration {
|
pub fn frame_time(&self) -> Duration {
|
||||||
self.frame_time
|
self.frame_time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
||||||
|
|
||||||
use utilities::prelude::cgmath::Vector3;
|
use utilities::prelude::cgmath::Vector3;
|
||||||
|
|
||||||
use anyhow::{bail, Error, Result};
|
use anyhow::{Error, Result, bail};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use crate::scene::{content::events::Events, rendering::RenderingFrontEnd};
|
use crate::scene::{content::events::Events, rendering::RenderingFrontEnd};
|
||||||
|
@ -17,25 +17,6 @@ use crate::prelude::*;
|
||||||
|
|
||||||
use super::scene_base::EntityMultiMut;
|
use super::scene_base::EntityMultiMut;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct EntityNotFoundError {
|
|
||||||
entity: Entity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EntityNotFoundError {
|
|
||||||
pub(crate) fn new(entity: Entity) -> Self {
|
|
||||||
Self { entity }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for EntityNotFoundError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "Entity (ID: {}) not found!", self.entity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for EntityNotFoundError {}
|
|
||||||
|
|
||||||
pub trait SceneEntities {
|
pub trait SceneEntities {
|
||||||
fn device(&self) -> &Arc<Device>;
|
fn device(&self) -> &Arc<Device>;
|
||||||
fn queue(&self) -> &Arc<Mutex<Queue>>;
|
fn queue(&self) -> &Arc<Mutex<Queue>>;
|
||||||
|
|
9
examples/simple_window/Cargo.toml
Normal file
9
examples/simple_window/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "simple_window"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
|
||||||
|
ecs = { path = "../../ecs" }
|
9
examples/simple_window/src/main.rs
Normal file
9
examples/simple_window/src/main.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use ecs::*;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let mut world_builder = World::builder();
|
||||||
|
// world_builder.
|
||||||
|
|
||||||
|
world_builder.build().run()
|
||||||
|
}
|
Loading…
Reference in a new issue