engine/ecs/src/entity.rs

264 lines
6.3 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
use core::fmt;
use std::any::TypeId;
use std::{num::ParseIntError, str::FromStr};
use anyhow::Result;
2025-02-26 07:39:19 +00:00
use serde::{Deserialize, Serialize};
2024-08-23 11:22:09 +00:00
2025-02-26 07:39:19 +00:00
use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap};
2024-08-23 11:22:09 +00:00
2025-02-26 07:39:19 +00:00
pub const COMPONENT_SEPARATOR: char = '§';
2024-08-23 11:22:09 +00:00
#[derive(Default)]
pub struct ActivationState {
activated: bool,
}
impl ActivationState {
pub fn is_active(&self) -> bool {
self.activated
}
pub(crate) fn apply_change(&mut self) {
self.activated = !self.activated;
}
}
2025-02-26 07:39:19 +00:00
pub struct EntityObject<S> {
2024-08-23 11:22:09 +00:00
#[cfg(debug_assertions)]
pub debug_name: Option<String>,
// gltf file name
pub(crate) gltf_file: Option<String>,
// activation state of Entity
pub(crate) activation_state: ActivationState,
// program local ID
pub entity_id: u32,
// component map
2025-02-26 07:39:19 +00:00
pub(crate) components: TypeMap<S>,
2024-08-23 11:22:09 +00:00
#[cfg(debug_assertions)]
component_names: Vec<String>,
}
2025-02-26 07:39:19 +00:00
unsafe impl<S> Send for EntityObject<S> {}
unsafe impl<S> Sync for EntityObject<S> {}
2024-08-23 11:22:09 +00:00
2025-02-26 07:39:19 +00:00
impl<S> EntityObject<S> {
2024-08-23 11:22:09 +00:00
pub(crate) fn new(id: u32) -> Self {
Self {
#[cfg(debug_assertions)]
debug_name: None,
gltf_file: None,
activation_state: ActivationState::default(),
entity_id: id,
components: TypeMap::default(),
#[cfg(debug_assertions)]
component_names: Vec::new(),
}
}
pub fn gltf_file(&self) -> Option<&String> {
self.gltf_file.as_ref()
}
2025-02-26 07:39:19 +00:00
pub fn multi_mut(&mut self) -> MultiMut<'_, S> {
2024-08-23 11:22:09 +00:00
self.components.multi_mut()
}
2025-02-26 07:39:19 +00:00
pub fn insert_component<T: EntityComponent<S> + ComponentDebug>(
2024-08-23 11:22:09 +00:00
&mut self,
component: T,
) -> Option<T> {
assert!(
!self.activation_state.is_active(),
"inserting components while the entity is activated is not allowed"
);
#[cfg(debug_assertions)]
{
let name = component.name().to_string();
if !self.component_names.contains(&name) {
self.component_names.push(name);
}
}
self.components.insert(component)
}
pub(crate) fn insert_component_by_id(
&mut self,
type_id: TypeId,
2025-02-26 07:39:19 +00:00
component: Box<dyn EntityComponent<S>>,
) -> Option<Box<dyn EntityComponent<S>>>
where
S: 'static,
{
2024-08-23 11:22:09 +00:00
assert!(
!self.activation_state.is_active(),
"inserting components while the entity is activated is not allowed"
);
#[cfg(debug_assertions)]
{
let name = component.name().to_string();
if !self.component_names.contains(&name) {
self.component_names.push(name);
}
}
self.components.insert_type(type_id, component)
}
2025-02-26 07:39:19 +00:00
pub fn remove_component<T: EntityComponent<S>>(&mut self) -> Option<T> {
2024-08-23 11:22:09 +00:00
assert!(
!self.activation_state.is_active(),
"removing components while the entity is activated is not allowed"
);
let t: Option<T> = self.components.remove();
#[cfg(debug_assertions)]
if let Some(t) = &t {
if let Some(index) = self
.component_names
.iter()
.position(|name| name == t.name())
{
self.component_names.remove(index);
}
}
t
}
pub(crate) fn remove_component_by_id(
&mut self,
type_id: TypeId,
2025-02-26 07:39:19 +00:00
) -> Option<Box<dyn EntityComponent<S>>>
where
S: 'static,
{
2024-08-23 11:22:09 +00:00
assert!(
!self.activation_state.is_active(),
"removing components while the entity is activated is not allowed"
);
let t = self.components.remove_by_type_id(&type_id);
#[cfg(debug_assertions)]
if let Some(t) = &t {
if let Some(index) = self
.component_names
.iter()
.position(|name| name == t.name())
{
self.component_names.remove(index);
}
}
t
}
#[cfg(debug_assertions)]
pub fn component_names(&self) -> &[String] {
&self.component_names
}
2025-02-26 07:39:19 +00:00
pub fn get_component<T: EntityComponent<S> + ComponentDebug>(
2024-08-23 11:22:09 +00:00
&self,
) -> std::result::Result<&T, ComponentNotFoundError> {
self.components.get()
}
2025-02-26 07:39:19 +00:00
pub fn get_component_mut<T: EntityComponent<S> + ComponentDebug>(
2024-08-23 11:22:09 +00:00
&mut self,
) -> std::result::Result<&mut T, ComponentNotFoundError> {
self.components.get_mut()
}
2025-02-26 07:39:19 +00:00
pub fn contains_component<T: EntityComponent<S>>(&self) -> bool {
2024-08-23 11:22:09 +00:00
self.components.contains::<T>()
}
pub fn is_activated(&self) -> bool {
self.activation_state.is_active()
}
pub fn as_entity(&self) -> Entity {
Entity { id: self.entity_id }
}
2025-02-26 07:39:19 +00:00
pub(crate) fn clone_without_components(&self, id: u32) -> EntityObject<S> {
2024-08-23 11:22:09 +00:00
EntityObject {
#[cfg(debug_assertions)]
debug_name: self.debug_name.clone(),
// gltf file name
gltf_file: self.gltf_file.clone(),
activation_state: Default::default(),
2025-02-26 07:39:19 +00:00
entity_id: id,
2024-08-23 11:22:09 +00:00
// component map
2025-02-26 07:39:19 +00:00
components: TypeMap::default(),
2024-08-23 11:22:09 +00:00
#[cfg(debug_assertions)]
component_names: Vec::new(),
}
}
2025-02-26 07:39:19 +00:00
pub fn clone_component_from<T: EntityComponent<S> + ComponentDebug + Clone>(
2024-08-23 11:22:09 +00:00
&mut self,
other: &Self,
) -> Result<()> {
let component = other.get_component::<T>()?;
self.insert_component(component.clone());
Ok(())
}
}
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Debug, Clone, Copy, Hash, Eq, Serialize, Deserialize)]
pub struct Entity {
pub(crate) id: u32,
}
2025-02-26 07:39:19 +00:00
impl<S> PartialEq<EntityObject<S>> for Entity {
fn eq(&self, entity: &EntityObject<S>) -> bool {
2024-08-23 11:22:09 +00:00
self.id == entity.entity_id
}
}
impl PartialEq<Entity> for Entity {
fn eq(&self, entity: &Entity) -> bool {
self.id == entity.id
}
}
impl fmt::Display for Entity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.id)
}
}
impl FromStr for Entity {
type Err = ParseIntError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(Self { id: s.parse()? })
}
}