Compare commits

..

2 commits

Author SHA1 Message Date
540be64f6a Merge branch 'main' of ssh://gavania.de:62/hodasemi/ecs 2025-04-08 18:00:17 +02:00
a073f8e520 Start query testing 2025-04-08 17:58:14 +02:00
5 changed files with 185 additions and 22 deletions

View file

@ -4,18 +4,20 @@ use std::{
time::Duration,
};
use crate::{world::ComponentChange, *};
use crate::{resources::Resource, world::ComponentChange, *};
enum CommandsTypes {
enum CommandTypes {
InsertEntity(EntityObject),
RemoveEntity(Entity),
UpdateEntity(Entity, ComponentChange),
Event(TypeId, Box<dyn Any + Send + Sync>),
InsertResource(TypeId, Box<dyn Resource>),
}
pub struct Commands {
commands: Vec<CommandsTypes>,
commands: Vec<CommandTypes>,
now: Duration,
}
@ -35,24 +37,24 @@ impl Commands {
let entity = entity_object.as_entity();
self.commands
.push(CommandsTypes::InsertEntity(entity_object));
.push(CommandTypes::InsertEntity(entity_object));
entity
}
pub fn remove_entity(&mut self, entity: Entity) {
self.commands.push(CommandsTypes::RemoveEntity(entity));
self.commands.push(CommandTypes::RemoveEntity(entity));
}
pub fn insert_component<T: EntityComponent>(&mut self, entity: Entity, component: T) {
self.commands.push(CommandsTypes::UpdateEntity(
self.commands.push(CommandTypes::UpdateEntity(
entity,
ComponentChange::Added(TypeId::of::<T>(), Box::new(component)),
));
}
pub fn remove_component<T: EntityComponent>(&mut self, entity: Entity) {
self.commands.push(CommandsTypes::UpdateEntity(
self.commands.push(CommandTypes::UpdateEntity(
entity,
ComponentChange::Removed(TypeId::of::<T>()),
));
@ -60,20 +62,32 @@ impl Commands {
pub fn write_event<T: Any + Send + Sync>(&mut self, payload: T) {
self.commands
.push(CommandsTypes::Event(TypeId::of::<T>(), Box::new(payload)));
.push(CommandTypes::Event(TypeId::of::<T>(), Box::new(payload)));
}
pub fn insert_resource<T: Resource>(&mut self, resource: T) {
self.commands.push(CommandTypes::InsertResource(
TypeId::of::<T>(),
Box::new(resource),
));
}
pub(crate) fn apply_deferred(self, world: &mut World) -> Result<()> {
for command in self.commands {
match command {
CommandsTypes::InsertEntity(entity_object) => {
CommandTypes::InsertEntity(entity_object) => {
world.add_entity(entity_object)?;
}
CommandsTypes::RemoveEntity(entity) => world.remove_entity(entity),
CommandsTypes::UpdateEntity(entity, component_change) => {
CommandTypes::RemoveEntity(entity) => world.remove_entity(entity),
CommandTypes::UpdateEntity(entity, component_change) => {
world.component_change(entity, component_change)
}
CommandsTypes::Event(type_id, any) => world.events.write_payload(type_id, any),
CommandTypes::Event(type_id, payload) => {
world.events.write_payload(type_id, payload)
}
CommandTypes::InsertResource(type_id, resource) => {
world.resources.insert_resource(type_id, resource)
}
}
}

View file

@ -6,6 +6,7 @@ pub mod get_disjoint_mut;
pub mod resources;
mod type_map;
mod unsafe_component_store;
mod update_testing;
mod updates;
mod world;

View file

@ -38,6 +38,10 @@ impl Resources {
.flatten()
}
pub(crate) fn insert_resource(&mut self, type_id: TypeId, resource: Box<dyn Resource>) {
self.map.insert(type_id, resource);
}
pub fn insert_if_not_exists<T: Resource + Default>(&mut self) {
if !self.contains::<T>() {
self.insert(T::default());

154
ecs/src/update_testing.rs Normal file
View file

@ -0,0 +1,154 @@
#![allow(unused)]
use anyhow::Result;
use std::marker::PhantomData;
use std::{ops::Deref, ops::DerefMut};
use crate::*;
#[derive(Copy, Clone)]
pub struct Query<C, F = EmptyFilter>
where
F: StaticCheckFilter,
{
entity: Entity,
c: C,
filter: PhantomData<F>,
}
impl<C, F: StaticCheckFilter> Query<C, F> {
pub fn entity(&self) -> Entity {
self.entity
}
}
impl<C, F: StaticCheckFilter> Deref for Query<C, F> {
type Target = C;
fn deref(&self) -> &Self::Target {
&self.c
}
}
impl<C, F: StaticCheckFilter> DerefMut for Query<C, F> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.c
}
}
trait CreateQueryArchetype<T, R, Func, Filter> {
fn create(f: Func) -> Self;
}
pub trait StaticCheckFilter: Send + Sync + Default + Clone {
fn check(entity: &EntityObject) -> bool;
fn verify_dedup<O: EntityComponent>();
}
impl StaticCheckFilter for EmptyFilter {
fn check(_entity: &EntityObject) -> bool {
true
}
fn verify_dedup<O>() {}
}
pub struct QueryArchetype {
check_entity: Box<dyn Fn(&EntityObject) -> bool + Send + Sync>,
create_callback: Box<
dyn Fn(
&EntityObject,
)
-> Result<Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>
+ Send
+ Sync,
>,
entities: Vec<Box<dyn Fn(&mut Commands, &mut World) -> Result<()> + Send + Sync>>,
}
macro_rules! impl_query_singleton_update {
( $($var:ident $(,)?)+ ) => {
impl<Func, Filter, $( $var, )+> CreateQueryArchetype<( $( $var, )+ ), (), Func, Filter> for QueryArchetype
where
Func: Fn(&mut Commands, Query<( $( &mut $var, )+ ), Filter>) -> Result<()> + Send + Sync + Clone + 'static,
Filter: StaticCheckFilter,
$(
$var: EntityComponent + ComponentDebug,
)+
{
paste::item! {
fn create(f: Func) -> Self {
$(
Filter::verify_dedup::<$var>();
)+
Self {
check_entity: Box::new({
move |entity| {
$(
if !entity.components.contains::<$var>() {
return false;
}
)+
if !Filter::check(entity) {
return false;
}
true
}
}),
create_callback: Box::new(move |entity| {
$(
let [< $var:lower >] = UnsafeComponentStore::from(
entity.get_component::<$var>()?
);
)+
let e = entity.as_entity();
let f = f.clone();
Ok(Box::new(move |commands, _world| {
let q = Query {
entity: e,
c: unsafe { ($([< $var:lower >].as_mut(),)+) },
filter: PhantomData,
};
f(commands, q)
}))
}),
entities: Vec::new(),
}
}
}
}
};
}
impl_query_singleton_update!(R);
struct T {}
impl EntityComponent for T {
fn name(&self) -> &str {
Self::debug_name()
}
}
impl ComponentDebug for T {
fn debug_name() -> &'static str {
"T"
}
}
fn system(_commands: &mut Commands, mut _query: Query<&mut T>) -> Result<()> {
Ok(())
}
fn test() {
// let q = QueryArchetype::create(system);
}

View file

@ -3,7 +3,6 @@
use std::any::TypeId;
use std::collections::HashMap;
use std::marker::PhantomData;
#[cfg(feature = "timings")]
use std::time::Instant;
@ -418,15 +417,6 @@ macro_rules! impl_update_filter {
};
}
pub struct Query<T, F = EmptyFilter>
where
F: CheckFilter,
{
pub components: T,
d: PhantomData<F>,
}
pub trait AddUpdates<T, R, Func, Filter> {
fn add_update(&mut self, name: &str, priority: u32, func: Func, filter: Filter) -> Result<()>;
}