diff --git a/lyra-ecs/README.md b/lyra-ecs/README.md
index 2859881..7a42101 100644
--- a/lyra-ecs/README.md
+++ b/lyra-ecs/README.md
@@ -5,7 +5,7 @@ An ECS for the Lyra game engine.
I couldn't find anything that fulfilled my needs, specifically an ECS that can store arbitrary components without knowing about the types. This makes it easier to implement into a scripting engine that has the ability to create its own components.
## Features
-- [ ] Archetypes
+- [x] Archetypes
- [x] Spawning entities
- [x] Despawning entities
- [x] Delete entities from archetypes
@@ -14,19 +14,15 @@ I couldn't find anything that fulfilled my needs, specifically an ECS that can s
- [x] Grow archetype as it fills up
- [x] Borrow safety of components inside Archetypes
- [x] Return `Ref` and `RefMut` from borrow queries
-- [ ] Querying components from archetypes
+- [x] Querying components from archetypes
- [x] Views
- - [ ] Mutable views
- - [ ] Make it possible so that ONLY `ViewMut` can borrow mutably
+ - [x] Mutable views
- [x] Resources
- [x] Get resources in views somehow
- [ ] Relationships (maybe this can be done through queries, idk)
-- [ ] Dynamic queries
+- [x] Dynamic queries
* Needed for scripting engines that can create their own components that Rust does not know the types of.
-- [ ] Systems
- - [ ] Dispatchers/Executors
- - [ ] Execution graph that follows dependencies
-
-
-
-To be honest, the name may change at some point
\ No newline at end of file
+- [x] Systems
+ - [x] Dispatchers/Executors
+ - [x] Execution graph that follows dependencies
+- [ ] Track when components on entities are changed
\ No newline at end of file
diff --git a/lyra-ecs/src/archetype.rs b/lyra-ecs/src/archetype.rs
index a63ea7a..d676dd4 100644
--- a/lyra-ecs/src/archetype.rs
+++ b/lyra-ecs/src/archetype.rs
@@ -2,6 +2,7 @@ use std::{ptr::{NonNull, self}, alloc::{self, Layout, alloc, dealloc}, mem, coll
use crate::{world::{Entity, ArchetypeEntityId}, bundle::Bundle, component_info::ComponentInfo, DynTypeId};
+#[derive(Clone)]
pub struct ComponentColumn {
pub data: RefCell>,
pub len: usize,
@@ -187,7 +188,7 @@ impl ComponentColumn {
}
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
pub struct ArchetypeId(pub u64);
impl ArchetypeId {
@@ -200,6 +201,7 @@ impl ArchetypeId {
}
}
+#[derive(Clone, Default)]
pub struct Archetype {
pub id: ArchetypeId,
pub(crate) entities: HashMap,
diff --git a/lyra-ecs/src/world.rs b/lyra-ecs/src/world.rs
index 36b5515..f8d472f 100644
--- a/lyra-ecs/src/world.rs
+++ b/lyra-ecs/src/world.rs
@@ -31,8 +31,8 @@ pub struct World {
resources: HashMap,
}
-impl World {
- pub fn new() -> Self {
+impl Default for World {
+ fn default() -> Self {
Self {
archetypes: HashMap::new(),
next_archetype_id: ArchetypeId(0),
@@ -42,6 +42,12 @@ impl World {
resources: HashMap::new(),
}
}
+}
+
+impl World {
+ pub fn new() -> Self {
+ Self::default()
+ }
fn get_new_entity(&mut self) -> Entity {
match self.dead_entities.pop_front() {
@@ -201,6 +207,17 @@ impl World {
self.resources.insert(TypeId::of::(), ResourceData::new(data));
}
+ /// Get a resource from the world, or insert it into the world with the provided
+ /// `fn` and return it.
+ pub fn get_resource_or_else(&mut self, f: F) -> RefMut
+ where
+ F: Fn() -> T + 'static
+ {
+ self.resources.entry(TypeId::of::())
+ .or_insert_with(|| ResourceData::new(f()))
+ .get_mut()
+ }
+
/// Gets a resource from the World.
///
/// Will panic if the resource is not in the world. See [`try_get_resource`] for