diff --git a/lyra-ecs/src/main.rs b/lyra-ecs/src/main.rs index 9762d55..5fb0381 100644 --- a/lyra-ecs/src/main.rs +++ b/lyra-ecs/src/main.rs @@ -8,6 +8,9 @@ mod component; mod query; mod component_info; +#[cfg(test)] +mod tests; + #[derive(Debug)] pub struct Position2d(i32, i32); @@ -28,10 +31,6 @@ fn main() { println!("\nstart of querying!\n"); - /* for pos in world.query::() { - println!("Queried Position2d: {:?}", pos); - } */ - let mut q = world.query_better(); q.with_component::(); diff --git a/lyra-ecs/src/query/borrow.rs b/lyra-ecs/src/query/borrow.rs index f5c33e8..522d3ed 100644 --- a/lyra-ecs/src/query/borrow.rs +++ b/lyra-ecs/src/query/borrow.rs @@ -1,6 +1,8 @@ use std::{marker::PhantomData, any::TypeId, ptr::NonNull}; -use super::{Fetch, Query}; +use crate::component::Component; + +use super::{Fetch, Query, AsQuery, IntoQuery, DefaultQuery}; pub struct FetchBorrow<'a, T> { ptr: NonNull, @@ -35,6 +37,15 @@ pub struct QueryBorrow { _phantom: PhantomData } +impl QueryBorrow { + pub fn new() -> Self { + Self { + type_id: TypeId::of::(), + _phantom: PhantomData, + } + } +} + impl Query for QueryBorrow where T: 'static @@ -60,6 +71,26 @@ where } } +impl AsQuery for QueryBorrow { + type Query = Self; +} + +impl DefaultQuery for QueryBorrow { + fn default_query() -> Self { + QueryBorrow::::new() + } +} + +impl AsQuery for &T { + type Query = QueryBorrow; +} + +impl DefaultQuery for &T { + fn default_query() -> QueryBorrow { + QueryBorrow::::new() + } +} + pub struct FetchBorrowMut<'a, T> { ptr: NonNull, size: usize, @@ -93,6 +124,15 @@ pub struct QueryBorrowMut { _phantom: PhantomData } +impl QueryBorrowMut { + pub fn new() -> Self { + Self { + type_id: TypeId::of::(), + _phantom: PhantomData, + } + } +} + impl Query for QueryBorrowMut where T: 'static @@ -118,29 +158,34 @@ where } } +impl AsQuery for QueryBorrowMut { + type Query = Self; +} + +impl DefaultQuery for QueryBorrowMut { + fn default_query() -> Self { + QueryBorrowMut::::new() + } +} + +impl AsQuery for &mut T { + type Query = QueryBorrowMut; +} + +impl DefaultQuery for &mut T { + fn default_query() -> QueryBorrowMut { + QueryBorrowMut::::new() + } +} + #[cfg(test)] mod tests { use std::any::TypeId; - use crate::{world::World, archetype::Archetype, query::View}; + use crate::{world::World, archetype::Archetype, query::View, tests::Vec2}; use super::{QueryBorrow, QueryBorrowMut}; - #[derive(Clone, Copy, Debug, Default)] - struct Vec2 { - x: f32, - y: f32, - } - - impl Vec2 { - pub fn new(x: f32, y: f32) -> Self { - Self { - x, - y, - } - } - } - /// Creates a world with two entities, one at Vec(10, 50) and /// the other at Vec2(25, 30). fn prepare_world() -> World { diff --git a/lyra-ecs/src/query/entities.rs b/lyra-ecs/src/query/entities.rs index 064ca8b..a8bcb8e 100644 --- a/lyra-ecs/src/query/entities.rs +++ b/lyra-ecs/src/query/entities.rs @@ -1,6 +1,6 @@ use crate::{world::Entity, archetype::{Archetype, ArchetypeId}}; -use super::{Fetch, Query}; +use super::{Fetch, Query, DefaultQuery, AsQuery}; pub struct EntitiesFetch<'a> { entities: &'a [Entity], @@ -37,4 +37,14 @@ impl Query for Entities { entities: &archetype.entities, } } -} \ No newline at end of file +} + +/* impl AsQuery for Entities { + type Query = Entities; +} + +impl DefaultQuery for Entities { + fn default_query() -> Self { + Entities + } +} */ \ No newline at end of file diff --git a/lyra-ecs/src/query/mod.rs b/lyra-ecs/src/query/mod.rs index 9685e59..cdd4e2e 100644 --- a/lyra-ecs/src/query/mod.rs +++ b/lyra-ecs/src/query/mod.rs @@ -111,27 +111,26 @@ pub trait Query { unsafe fn fetch<'a>(&self, arch_id: ArchetypeId, archetype: &'a Archetype) -> Self::Fetch<'a>; } +/// A trait for getting the query of a type. +pub trait AsQuery { + /// The query for this type + type Query: Query; +} + +pub trait IntoQuery { + fn into_query(self) -> Self; +} + +pub trait DefaultQuery: AsQuery { + fn default_query() -> Self::Query; +} + #[cfg(test)] mod tests { - use crate::{world::World, archetype::Archetype}; + use crate::{world::World, archetype::Archetype, tests::Vec2}; use super::{View, Entities}; - #[derive(Clone, Copy, Debug, Default)] - struct Vec2 { - x: f32, - y: f32, - } - - impl Vec2 { - pub fn new(x: f32, y: f32) -> Self { - Self { - x, - y, - } - } - } - #[test] fn simple_view() { let mut world = World::new(); diff --git a/lyra-ecs/src/tests.rs b/lyra-ecs/src/tests.rs new file mode 100644 index 0000000..d8d87e7 --- /dev/null +++ b/lyra-ecs/src/tests.rs @@ -0,0 +1,16 @@ +/// This source file includes some common things that tests are using. + +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] +pub struct Vec2 { + pub x: f32, + pub y: f32, +} + +impl Vec2 { + pub fn new(x: f32, y: f32) -> Self { + Self { + x, + y, + } + } +} \ No newline at end of file diff --git a/lyra-ecs/src/world.rs b/lyra-ecs/src/world.rs index 6830261..7de0e57 100644 --- a/lyra-ecs/src/world.rs +++ b/lyra-ecs/src/world.rs @@ -1,7 +1,7 @@ use std::{collections::{HashMap, VecDeque}, any::{Any, TypeId}}; use std::slice::Iter; -use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::QuerySimple}; +use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{QuerySimple, ViewIter, IntoQuery, View, AsQuery, DefaultQuery}}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct EntityId(pub u64); @@ -109,11 +109,10 @@ impl World { archetype.get_entity_component(record.index) } - pub fn query(&self) -> impl Iterator { - self.archetypes - .iter() - .filter_map(|(_, a)| a.get_component_column::()) - .flatten() + pub fn view<'a, T: 'static + Component + DefaultQuery>(&'a self) -> ViewIter<'a, T::Query> { + let archetypes = self.archetypes.values().collect(); + let v = View::new(T::default_query(), archetypes); + v.into_iter() } pub fn query_better(&self) -> QuerySimple { @@ -131,12 +130,9 @@ impl World { #[cfg(test)] mod tests { - use super::World; + use crate::tests::Vec2; - struct Vec2 { - x: f32, - y: f32, - } + use super::World; #[test] fn spawning_entity() { @@ -146,4 +142,28 @@ mod tests { y: 15.0, }, )); } + + #[test] + fn query_entities() { + let mut world = World::new(); + world.spawn((Vec2 { + x: 10.0, + y: 15.0, + }, )); + world.spawn((Vec2 { + x: 152.0, + y: 3585.0, + }, )); + world.spawn((Vec2 { + x: 235.0, + y: 734.0, + }, )); + + let mut count = 0; + for pos in world.view::<&Vec2>() { + println!("Found entity at {:?}", pos); + count += 1; + } + assert!(count == 3); + } } \ No newline at end of file