mirror of
https://github.com/lisk77/comet.git
synced 2025-12-12 09:08:49 +00:00
refactor(ecs)!: reworked the entity id system
This commit is contained in:
parent
eced6ddf3f
commit
607bf94f1e
7 changed files with 198 additions and 95 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
use comet_colors::{Color as ColorTrait, LinearRgba};
|
use comet_colors::{Color as ColorTrait, LinearRgba};
|
||||||
use comet_ecs::{Camera2D, Component, Entity, Render2D, Scene, Text, Transform2D, Transform3D};
|
use comet_ecs::{
|
||||||
|
Camera2D, Component, Entity, EntityId, Render2D, Scene, Text, Transform2D, Transform3D,
|
||||||
|
};
|
||||||
use comet_input::keyboard::Key;
|
use comet_input::keyboard::Key;
|
||||||
use comet_log::*;
|
use comet_log::*;
|
||||||
use comet_renderer::renderer::Renderer;
|
use comet_renderer::renderer::Renderer;
|
||||||
|
|
@ -163,22 +165,22 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new entity and returns its ID.
|
/// Creates a new entity and returns its ID.
|
||||||
pub fn new_entity(&mut self) -> usize {
|
pub fn new_entity(&mut self) -> EntityId {
|
||||||
self.scene.new_entity() as usize
|
self.scene.new_entity()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes an entity by its ID.
|
/// Deletes an entity by its ID.
|
||||||
pub fn delete_entity(&mut self, entity_id: usize) {
|
pub fn delete_entity(&mut self, entity_id: EntityId) {
|
||||||
self.scene.delete_entity(entity_id)
|
self.scene.delete_entity(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an immutable reference to an entity by its ID.
|
/// Gets an immutable reference to an entity by its ID.
|
||||||
pub fn get_entity(&self, entity_id: usize) -> Option<&Entity> {
|
pub fn get_entity(&self, entity_id: EntityId) -> Option<&Entity> {
|
||||||
self.scene.get_entity(entity_id)
|
self.scene.get_entity(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to an entity by its ID.
|
/// Gets a mutable reference to an entity by its ID.
|
||||||
pub fn get_entity_mut(&mut self, entity_id: usize) -> Option<&mut Entity> {
|
pub fn get_entity_mut(&mut self, entity_id: EntityId) -> Option<&mut Entity> {
|
||||||
self.scene.get_entity_mut(entity_id)
|
self.scene.get_entity_mut(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,29 +196,29 @@ impl App {
|
||||||
|
|
||||||
/// Adds a component to an entity by its ID and an instance of the component.
|
/// Adds a component to an entity by its ID and an instance of the component.
|
||||||
/// Overwrites the previous component if another component of the same type is added.
|
/// Overwrites the previous component if another component of the same type is added.
|
||||||
pub fn add_component<C: Component>(&mut self, entity_id: usize, component: C) {
|
pub fn add_component<C: Component>(&mut self, entity_id: EntityId, component: C) {
|
||||||
self.scene.add_component(entity_id, component)
|
self.scene.add_component(entity_id, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a component from an entity by its ID.
|
/// Removes a component from an entity by its ID.
|
||||||
pub fn remove_component<C: Component>(&mut self, entity_id: usize) {
|
pub fn remove_component<C: Component>(&mut self, entity_id: EntityId) {
|
||||||
self.scene.remove_component::<C>(entity_id)
|
self.scene.remove_component::<C>(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to a component of an entity by its ID.
|
/// Returns a reference to a component of an entity by its ID.
|
||||||
pub fn get_component<C: Component>(&self, entity_id: usize) -> Option<&C> {
|
pub fn get_component<C: Component>(&self, entity_id: EntityId) -> Option<&C> {
|
||||||
self.scene.get_component::<C>(entity_id)
|
self.scene.get_component::<C>(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to a component of an entity by its ID.
|
/// Returns a mutable reference to a component of an entity by its ID.
|
||||||
pub fn get_component_mut<C: Component>(&mut self, entity_id: usize) -> Option<&mut C> {
|
pub fn get_component_mut<C: Component>(&mut self, entity_id: EntityId) -> Option<&mut C> {
|
||||||
self.scene.get_component_mut::<C>(entity_id)
|
self.scene.get_component_mut::<C>(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of entities that have the given components.
|
/// Returns a list of entities that have the given components.
|
||||||
/// The amount of queriable components is limited to 3 such that the `Archetype` creation is more efficient.
|
/// The amount of queriable components is limited to 3 such that the `Archetype` creation is more efficient.
|
||||||
/// Otherwise it would be a factorial complexity chaos.
|
/// Otherwise it would be a factorial complexity chaos.
|
||||||
pub fn get_entities_with(&self, components: Vec<TypeId>) -> Vec<usize> {
|
pub fn get_entities_with(&self, components: Vec<TypeId>) -> Vec<EntityId> {
|
||||||
self.scene.get_entities_with(components)
|
self.scene.get_entities_with(components)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +235,7 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether an entity has the given component.
|
/// Returns whether an entity has the given component.
|
||||||
pub fn has<C: Component>(&self, entity_id: usize) -> bool {
|
pub fn has<C: Component>(&self, entity_id: EntityId) -> bool {
|
||||||
self.scene.has::<C>(entity_id)
|
self.scene.has::<C>(entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +245,7 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns a prefab with the given name.
|
/// Spawns a prefab with the given name.
|
||||||
pub fn spawn_prefab(&mut self, name: &str) -> Option<usize> {
|
pub fn spawn_prefab(&mut self, name: &str) -> Option<EntityId> {
|
||||||
self.scene.spawn_prefab(name)
|
self.scene.spawn_prefab(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -436,13 +436,15 @@ impl Camera for Camera2D {
|
||||||
let entities = scene.entities();
|
let entities = scene.entities();
|
||||||
let mut visible_entities = Vec::new();
|
let mut visible_entities = Vec::new();
|
||||||
for entity in entities {
|
for entity in entities {
|
||||||
let id = *entity.clone().unwrap().id() as usize;
|
if let Some(ent) = entity.clone() {
|
||||||
|
let id = ent.id();
|
||||||
if let Some(transform) = scene.get_component::<Transform2D>(id) {
|
if let Some(transform) = scene.get_component::<Transform2D>(id) {
|
||||||
if self.in_view_frustum(camera_position, transform.position()) {
|
if self.in_view_frustum(camera_position, transform.position()) {
|
||||||
visible_entities.push(entity.clone().unwrap());
|
visible_entities.push(ent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("Entity {} missing Transform2D", id);
|
error!("Entity {} missing Transform2D", id.index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visible_entities
|
visible_entities
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,35 @@
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
|
||||||
|
/// Handle used to reference entities safely. Contains an index into the entity
|
||||||
|
/// storage and a generation counter to detect stale handles.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
pub struct EntityId {
|
||||||
|
pub index: u32,
|
||||||
|
pub gen: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EntityId {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { index: 0, gen: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
id: u32,
|
id: EntityId,
|
||||||
components: BitSet
|
components: BitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity {
|
impl Entity {
|
||||||
pub(crate) fn new(id: u32) -> Self {
|
pub(crate) fn new(index: u32, gen: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id: EntityId { index, gen },
|
||||||
components: BitSet::new()
|
components: BitSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> &u32 {
|
pub fn id(&self) -> EntityId {
|
||||||
&self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_component(&mut self, component_index: usize) {
|
pub(crate) fn add_component(&mut self, component_index: usize) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use comet_structs::FlatMap;
|
use comet_structs::FlatMap;
|
||||||
|
|
||||||
pub type PrefabFactory = fn(&mut crate::Scene) -> usize;
|
pub type PrefabFactory = fn(&mut crate::Scene) -> crate::EntityId;
|
||||||
|
|
||||||
pub(crate) struct PrefabManager {
|
pub(crate) struct PrefabManager {
|
||||||
pub(crate) prefabs: FlatMap<String, PrefabFactory>,
|
pub(crate) prefabs: FlatMap<String, PrefabFactory>,
|
||||||
|
|
@ -26,8 +26,8 @@ impl PrefabManager {
|
||||||
macro_rules! register_prefab {
|
macro_rules! register_prefab {
|
||||||
($scene:expr, $name:expr, $($component:expr),* $(,)?) => {
|
($scene:expr, $name:expr, $($component:expr),* $(,)?) => {
|
||||||
{
|
{
|
||||||
fn prefab_factory(scene: &mut $crate::Scene) -> usize {
|
fn prefab_factory(scene: &mut $crate::Scene) -> $crate::EntityId {
|
||||||
let entity = scene.new_entity() as usize;
|
let entity = scene.new_entity();
|
||||||
$(
|
$(
|
||||||
scene.add_component(entity, $component);
|
scene.add_component(entity, $component);
|
||||||
)*
|
)*
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::archetypes::Archetypes;
|
use crate::archetypes::Archetypes;
|
||||||
use crate::prefabs::PrefabManager;
|
use crate::prefabs::PrefabManager;
|
||||||
use crate::{Component, Entity, IdQueue};
|
use crate::{Component, Entity, EntityId, IdQueue};
|
||||||
use comet_log::*;
|
use comet_log::*;
|
||||||
use comet_structs::*;
|
use comet_structs::*;
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
@ -8,6 +8,7 @@ use std::any::TypeId;
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
id_queue: IdQueue,
|
id_queue: IdQueue,
|
||||||
next_id: u32,
|
next_id: u32,
|
||||||
|
generations: Vec<u32>,
|
||||||
entities: Vec<Option<Entity>>,
|
entities: Vec<Option<Entity>>,
|
||||||
components: ComponentStorage,
|
components: ComponentStorage,
|
||||||
archetypes: Archetypes,
|
archetypes: Archetypes,
|
||||||
|
|
@ -19,6 +20,7 @@ impl Scene {
|
||||||
Self {
|
Self {
|
||||||
id_queue: IdQueue::new(),
|
id_queue: IdQueue::new(),
|
||||||
next_id: 0,
|
next_id: 0,
|
||||||
|
generations: Vec::new(),
|
||||||
entities: Vec::new(),
|
entities: Vec::new(),
|
||||||
components: ComponentStorage::new(),
|
components: ComponentStorage::new(),
|
||||||
archetypes: Archetypes::new(),
|
archetypes: Archetypes::new(),
|
||||||
|
|
@ -43,45 +45,80 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_alive(&self, id: EntityId) -> bool {
|
||||||
|
self.generations
|
||||||
|
.get(id.index as usize)
|
||||||
|
.is_some_and(|g| *g == id.gen)
|
||||||
|
&& self
|
||||||
|
.entities
|
||||||
|
.get(id.index as usize)
|
||||||
|
.is_some_and(|e| e.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
/// Retuns the `Vec` of `Option<Entity>` which contains all the entities in the current Scene.
|
/// Retuns the `Vec` of `Option<Entity>` which contains all the entities in the current Scene.
|
||||||
pub fn entities(&self) -> &Vec<Option<Entity>> {
|
pub fn entities(&self) -> &Vec<Option<Entity>> {
|
||||||
&self.entities
|
&self.entities
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new entity and returns its ID.
|
/// Creates a new entity and returns its ID.
|
||||||
pub fn new_entity(&mut self) -> u32 {
|
pub fn new_entity(&mut self) -> EntityId {
|
||||||
let id = self.next_id;
|
let index = self.next_id;
|
||||||
if (self.next_id as usize) >= self.entities.len() {
|
let gen = if (index as usize) >= self.generations.len() {
|
||||||
self.entities.push(Some(Entity::new(self.next_id)));
|
self.generations.push(0);
|
||||||
self.get_next_id();
|
0
|
||||||
info!("Created entity! ID: {}", id);
|
} else {
|
||||||
return id;
|
self.generations[index as usize]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (index as usize) >= self.entities.len() {
|
||||||
|
self.entities.push(Some(Entity::new(index, gen)));
|
||||||
|
} else {
|
||||||
|
self.entities[index as usize] = Some(Entity::new(index, gen));
|
||||||
}
|
}
|
||||||
self.entities[self.next_id as usize] = Some(Entity::new(self.next_id));
|
|
||||||
|
let id = EntityId { index, gen };
|
||||||
self.get_next_id();
|
self.get_next_id();
|
||||||
info!("Created entity! ID: {}", id);
|
info!("Created entity! ID: {} (gen {})", id.index, id.gen);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an immutable reference to an entity by its ID.
|
/// Gets an immutable reference to an entity by its ID.
|
||||||
pub fn get_entity(&self, entity_id: usize) -> Option<&Entity> {
|
pub fn get_entity(&self, entity_id: EntityId) -> Option<&Entity> {
|
||||||
self.entities.get(entity_id).and_then(|e| e.as_ref())
|
if !self.is_alive(entity_id) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.entities
|
||||||
|
.get(entity_id.index as usize)
|
||||||
|
.and_then(|e| e.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to an entity by its ID.
|
/// Gets a mutable reference to an entity by its ID.
|
||||||
pub fn get_entity_mut(&mut self, entity_id: usize) -> Option<&mut Entity> {
|
pub fn get_entity_mut(&mut self, entity_id: EntityId) -> Option<&mut Entity> {
|
||||||
self.entities.get_mut(entity_id).and_then(|e| e.as_mut())
|
if !self.is_alive(entity_id) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.entities
|
||||||
|
.get_mut(entity_id.index as usize)
|
||||||
|
.and_then(|e| e.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes an entity by its ID.
|
/// Deletes an entity by its ID.
|
||||||
pub fn delete_entity(&mut self, entity_id: usize) {
|
pub fn delete_entity(&mut self, entity_id: EntityId) {
|
||||||
self.remove_entity_from_archetype(entity_id as u32, self.get_component_set(entity_id));
|
if !self.is_alive(entity_id) {
|
||||||
self.entities[entity_id] = None;
|
return;
|
||||||
info!("Deleted entity! ID: {}", entity_id);
|
|
||||||
for (_, value) in self.components.iter_mut() {
|
|
||||||
value.remove::<u8>(entity_id);
|
|
||||||
}
|
}
|
||||||
self.id_queue.sorted_enqueue(entity_id as u32);
|
|
||||||
|
let idx = entity_id.index as usize;
|
||||||
|
self.remove_entity_from_archetype(entity_id.index, self.get_component_set(idx));
|
||||||
|
self.entities[idx] = None;
|
||||||
|
info!("Deleted entity! ID: {}", entity_id.index);
|
||||||
|
for (_, value) in self.components.iter_mut() {
|
||||||
|
value.remove::<u8>(idx);
|
||||||
|
}
|
||||||
|
if let Some(gen) = self.generations.get_mut(idx) {
|
||||||
|
*gen = gen.wrapping_add(1);
|
||||||
|
}
|
||||||
|
self.id_queue.sorted_enqueue(entity_id.index);
|
||||||
self.get_next_id();
|
self.get_next_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,13 +196,23 @@ impl Scene {
|
||||||
|
|
||||||
/// Adds a component to an entity by its ID and an instance of the component.
|
/// Adds a component to an entity by its ID and an instance of the component.
|
||||||
/// Overwrites the previous component if another component of the same type is added.
|
/// Overwrites the previous component if another component of the same type is added.
|
||||||
pub fn add_component<C: Component + 'static>(&mut self, entity_id: usize, component: C) {
|
pub fn add_component<C: Component + 'static>(&mut self, entity_id: EntityId, component: C) {
|
||||||
let old_component_set = self.get_component_set(entity_id);
|
if !self.is_alive(entity_id) {
|
||||||
if !old_component_set.to_vec().is_empty() {
|
error!(
|
||||||
self.remove_entity_from_archetype(entity_id as u32, old_component_set);
|
"Attempted to add component {} to dead entity {}",
|
||||||
|
C::type_name(),
|
||||||
|
entity_id.index
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.components.set_component(entity_id, component);
|
let old_component_set = self.get_component_set(entity_id.index as usize);
|
||||||
|
if !old_component_set.to_vec().is_empty() {
|
||||||
|
self.remove_entity_from_archetype(entity_id.index, old_component_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.components
|
||||||
|
.set_component(entity_id.index as usize, component);
|
||||||
if let Some(component_index) = self
|
if let Some(component_index) = self
|
||||||
.components
|
.components
|
||||||
.keys()
|
.keys()
|
||||||
|
|
@ -175,36 +222,43 @@ impl Scene {
|
||||||
if let Some(entity) = self.get_entity_mut(entity_id) {
|
if let Some(entity) = self.get_entity_mut(entity_id) {
|
||||||
entity.add_component(component_index);
|
entity.add_component(component_index);
|
||||||
} else {
|
} else {
|
||||||
error!("Attempted to add component to non-existent entity {}", entity_id);
|
error!(
|
||||||
|
"Attempted to add component to non-existent entity {}",
|
||||||
|
entity_id.index
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"Component {} not registered, cannot add to entity {}",
|
"Component {} not registered, cannot add to entity {}",
|
||||||
C::type_name(),
|
C::type_name(),
|
||||||
entity_id
|
entity_id.index
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_component_set = self.get_component_set(entity_id);
|
let new_component_set = self.get_component_set(entity_id.index as usize);
|
||||||
|
|
||||||
if !self.archetypes.contains_archetype(&new_component_set) {
|
if !self.archetypes.contains_archetype(&new_component_set) {
|
||||||
self.create_archetype(new_component_set.clone());
|
self.create_archetype(new_component_set.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_entity_to_archetype(entity_id as u32, new_component_set);
|
self.add_entity_to_archetype(entity_id.index, new_component_set);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Added component {} to entity {}!",
|
"Added component {} to entity {}!",
|
||||||
C::type_name(),
|
C::type_name(),
|
||||||
entity_id
|
entity_id.index
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_component<C: Component + 'static>(&mut self, entity_id: usize) {
|
pub fn remove_component<C: Component + 'static>(&mut self, entity_id: EntityId) {
|
||||||
let old_component_set = self.get_component_set(entity_id);
|
if !self.is_alive(entity_id) {
|
||||||
self.remove_entity_from_archetype(entity_id as u32, old_component_set);
|
return;
|
||||||
|
}
|
||||||
|
let old_component_set = self.get_component_set(entity_id.index as usize);
|
||||||
|
self.remove_entity_from_archetype(entity_id.index, old_component_set);
|
||||||
|
|
||||||
self.components.remove_component::<C>(entity_id);
|
self.components
|
||||||
|
.remove_component::<C>(entity_id.index as usize);
|
||||||
if let Some(component_index) = self
|
if let Some(component_index) = self
|
||||||
.components
|
.components
|
||||||
.keys()
|
.keys()
|
||||||
|
|
@ -216,48 +270,73 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_component_set = self.get_component_set(entity_id);
|
let new_component_set = self.get_component_set(entity_id.index as usize);
|
||||||
|
|
||||||
if !new_component_set.to_vec().is_empty() {
|
if !new_component_set.to_vec().is_empty() {
|
||||||
if !self.archetypes.contains_archetype(&new_component_set) {
|
if !self.archetypes.contains_archetype(&new_component_set) {
|
||||||
self.create_archetype(new_component_set.clone());
|
self.create_archetype(new_component_set.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_entity_to_archetype(entity_id as u32, new_component_set);
|
self.add_entity_to_archetype(entity_id.index, new_component_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Removed component {} from entity {}!",
|
"Removed component {} from entity {}!",
|
||||||
C::type_name(),
|
C::type_name(),
|
||||||
entity_id
|
entity_id.index
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to a component of an entity by its ID.
|
/// Returns a reference to a component of an entity by its ID.
|
||||||
pub fn get_component<C: Component + 'static>(&self, entity_id: usize) -> Option<&C> {
|
pub fn get_component<C: Component + 'static>(&self, entity_id: EntityId) -> Option<&C> {
|
||||||
self.components.get_component::<C>(entity_id)
|
if !self.is_alive(entity_id) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.components
|
||||||
|
.get_component::<C>(entity_id.index as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_component_mut<C: Component + 'static>(
|
pub fn get_component_mut<C: Component + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
entity_id: usize,
|
entity_id: EntityId,
|
||||||
) -> Option<&mut C> {
|
) -> Option<&mut C> {
|
||||||
self.components.get_component_mut::<C>(entity_id)
|
if !self.is_alive(entity_id) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.components
|
||||||
|
.get_component_mut::<C>(entity_id.index as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has<C: Component + 'static>(&self, entity_id: usize) -> bool {
|
pub fn has<C: Component + 'static>(&self, entity_id: EntityId) -> bool {
|
||||||
self.components.get_component::<C>(entity_id).is_some()
|
self.is_alive(entity_id)
|
||||||
|
&& self
|
||||||
|
.components
|
||||||
|
.get_component::<C>(entity_id.index as usize)
|
||||||
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of entities that have the given components.
|
/// Returns a list of entities that have the given components.
|
||||||
pub fn get_entities_with(&self, components: Vec<TypeId>) -> Vec<usize> {
|
pub fn get_entities_with(&self, components: Vec<TypeId>) -> Vec<EntityId> {
|
||||||
let component_set = ComponentSet::from_ids(components);
|
let component_set = ComponentSet::from_ids(components);
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
for archetype_set in self.archetypes.component_sets() {
|
for archetype_set in self.archetypes.component_sets() {
|
||||||
if component_set.is_subset(&archetype_set) {
|
if component_set.is_subset(&archetype_set) {
|
||||||
if let Some(entities) = self.archetypes.get_archetype(&archetype_set) {
|
if let Some(entities) = self.archetypes.get_archetype(&archetype_set) {
|
||||||
result.extend(entities.iter().map(|x| *x as usize));
|
for index in entities.iter() {
|
||||||
|
if let Some(gen) = self.generations.get(*index as usize) {
|
||||||
|
if self
|
||||||
|
.entities
|
||||||
|
.get(*index as usize)
|
||||||
|
.is_some_and(|e| e.is_some())
|
||||||
|
{
|
||||||
|
result.push(EntityId {
|
||||||
|
index: *index,
|
||||||
|
gen: *gen,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -286,8 +365,9 @@ impl Scene {
|
||||||
.components
|
.components
|
||||||
.get_two_mut(&C::type_id(), &K::type_id());
|
.get_two_mut(&C::type_id(), &K::type_id());
|
||||||
|
|
||||||
let c_opt = c_set.and_then(|set| set.get_mut::<C>(entity));
|
let idx = entity.index as usize;
|
||||||
let k_opt = k_set.and_then(|set| set.get_mut::<K>(entity));
|
let c_opt = c_set.and_then(|set| set.get_mut::<C>(idx));
|
||||||
|
let k_opt = k_set.and_then(|set| set.get_mut::<K>(idx));
|
||||||
|
|
||||||
if let (Some(c), Some(k)) = (c_opt, k_opt) {
|
if let (Some(c), Some(k)) = (c_opt, k_opt) {
|
||||||
func(c, k);
|
func(c, k);
|
||||||
|
|
@ -301,7 +381,7 @@ impl Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns a prefab with the given name.
|
/// Spawns a prefab with the given name.
|
||||||
pub fn spawn_prefab(&mut self, name: &str) -> Option<usize> {
|
pub fn spawn_prefab(&mut self, name: &str) -> Option<EntityId> {
|
||||||
if self.prefabs.has_prefab(name) {
|
if self.prefabs.has_prefab(name) {
|
||||||
if let Some(factory) = self.prefabs.prefabs.get(&name.to_string()) {
|
if let Some(factory) = self.prefabs.prefabs.get(&name.to_string()) {
|
||||||
let factory = *factory; // Copy the function pointer
|
let factory = *factory; // Copy the function pointer
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,11 @@ impl CameraManager {
|
||||||
self.cameras.get(self.active_camera).unwrap()
|
self.cameras.get(self.active_camera).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_from_scene(&mut self, scene: &comet_ecs::Scene, camera_entities: Vec<usize>) {
|
pub fn update_from_scene(
|
||||||
|
&mut self,
|
||||||
|
scene: &comet_ecs::Scene,
|
||||||
|
camera_entities: Vec<comet_ecs::EntityId>,
|
||||||
|
) {
|
||||||
self.cameras.clear();
|
self.cameras.clear();
|
||||||
|
|
||||||
let mut cameras_with_priority: Vec<(RenderCamera, u8)> = Vec::new();
|
let mut cameras_with_priority: Vec<(RenderCamera, u8)> = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ pub struct Renderer2D<'a> {
|
||||||
resource_manager: GraphicResourceManager,
|
resource_manager: GraphicResourceManager,
|
||||||
camera_manager: CameraManager,
|
camera_manager: CameraManager,
|
||||||
render_passes: Vec<RenderPass>,
|
render_passes: Vec<RenderPass>,
|
||||||
cached_render_entities: Vec<usize>,
|
cached_render_entities: Vec<comet_ecs::EntityId>,
|
||||||
last_frame_time: std::time::Instant,
|
last_frame_time: std::time::Instant,
|
||||||
delta_time: f32,
|
delta_time: f32,
|
||||||
}
|
}
|
||||||
|
|
@ -754,7 +754,8 @@ impl<'a> Renderer2D<'a> {
|
||||||
let mut dirty_sort = self.cached_render_entities.len() != unsorted_entities.len();
|
let mut dirty_sort = self.cached_render_entities.len() != unsorted_entities.len();
|
||||||
|
|
||||||
if !dirty_sort {
|
if !dirty_sort {
|
||||||
let unsorted_set: HashSet<usize> = unsorted_entities.iter().copied().collect();
|
let unsorted_set: HashSet<comet_ecs::EntityId> =
|
||||||
|
unsorted_entities.iter().copied().collect();
|
||||||
dirty_sort = self
|
dirty_sort = self
|
||||||
.cached_render_entities
|
.cached_render_entities
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -952,7 +953,7 @@ impl<'a> Renderer2D<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_camera(&mut self, scene: &comet_ecs::Scene, cameras: Vec<usize>) {
|
fn setup_camera(&mut self, scene: &comet_ecs::Scene, cameras: Vec<comet_ecs::EntityId>) {
|
||||||
if cameras.is_empty() {
|
if cameras.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue