Skip to main content

gizmo_core/
component.rs

1use std::any::Any;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum StorageType {
5    Table,
6    SparseSet,
7}
8
9pub trait Component: 'static + Any + Send + Sync + Clone {
10    fn storage_type() -> StorageType {
11        StorageType::Table
12    }
13}
14
15#[macro_export]
16macro_rules! impl_component {
17    ($($t:ty),+ $(,)?) => {
18        $(
19            impl $crate::Component for $t {}
20        )+
21    };
22    ($($t:ty),+ ; $storage:expr) => {
23        $(
24            impl $crate::Component for $t {
25                fn storage_type() -> $crate::component::StorageType {
26                    $storage
27                }
28            }
29        )+
30    };
31}
32
33// --- Hiyerarşi (Scene Graph) Bileşenleri ---
34#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
35pub struct Parent(pub u32);
36
37#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
38pub struct Children(pub Vec<u32>);
39
40#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
41pub struct EntityName(pub String);
42
43impl EntityName {
44    pub fn new(name: &str) -> Self {
45        Self(name.to_string())
46    }
47}
48
49#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
50pub struct IsHidden;
51
52#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
53pub struct IsDeleted;
54
55#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
56pub struct PrefabRequest(pub String);
57
58impl PrefabRequest {
59    pub fn new(name: &str) -> Self {
60        Self(name.to_string())
61    }
62    pub fn name(&self) -> &str {
63        &self.0
64    }
65}
66
67impl std::fmt::Display for EntityName {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        write!(f, "{}", self.0)
70    }
71}
72
73#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
74pub struct MeshSource(pub String);
75
76#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
77pub struct MaterialSource {
78    pub albedo: [f32; 4],
79    pub roughness: f32,
80    pub metallic: f32,
81    pub unlit: f32,
82    pub texture_source: Option<String>,
83}
84
85impl_component!(Parent, Children, EntityName, IsHidden, PrefabRequest, IsDeleted, MeshSource, MaterialSource);
86
87// ============================================================
88//  Bundle Trait
89// ============================================================
90
91pub trait Bundle {
92    fn get_infos() -> Vec<crate::archetype::ComponentInfo>;
93    unsafe fn write_to_archetype(self, arch: &mut crate::archetype::Archetype, _row: usize, tick: u32);
94    fn apply(self, _world: &mut crate::world::World, _entity: crate::entity::Entity) where Self: Sized {}
95}
96
97pub struct DynamicBundle<B: Bundle, C: Component> {
98    pub bundle: B,
99    pub component: C,
100}
101
102impl<B: Bundle, C: Component> Bundle for DynamicBundle<B, C> {
103    fn get_infos() -> Vec<crate::archetype::ComponentInfo> {
104        let mut infos = B::get_infos();
105        infos.push(crate::archetype::ComponentInfo::of::<C>());
106        infos
107    }
108
109    unsafe fn write_to_archetype(self, arch: &mut crate::archetype::Archetype, row: usize, tick: u32) {
110        self.bundle.write_to_archetype(arch, row, tick);
111        let col = arch.get_column_mut(std::any::TypeId::of::<C>()).unwrap();
112        if col.len() <= row {
113            col.push_raw(&self.component as *const _ as *const u8, tick);
114            std::mem::forget(self.component);
115        } else {
116            let ptr = col.get_mut_ptr(row) as *mut C;
117            std::ptr::write(ptr, self.component);
118            *col.ticks_ptr_mut().add(row) = crate::archetype::ComponentTicks::new(tick);
119        }
120    }
121}
122
123pub trait BundleExt: Bundle + Sized {
124    fn with<C: Component>(self, component: C) -> DynamicBundle<Self, C> {
125        DynamicBundle { bundle: self, component }
126    }
127}
128
129impl<T: Bundle> BundleExt for T {}
130
131impl<T: Component> Bundle for T {
132    fn get_infos() -> Vec<crate::archetype::ComponentInfo> {
133        vec![crate::archetype::ComponentInfo::of::<T>()]
134    }
135
136    fn apply(self, world: &mut crate::world::World, entity: crate::entity::Entity) {
137        world.add_component(entity, self);
138    }
139
140    unsafe fn write_to_archetype(self, arch: &mut crate::archetype::Archetype, row: usize, tick: u32) {
141        let col = arch.get_column_mut(std::any::TypeId::of::<T>()).expect("Component column missing in Archetype");
142        if col.len() <= row {
143            col.push_raw(&self as *const _ as *const u8, tick);
144            std::mem::forget(self);
145        } else {
146            let ptr = col.get_mut_ptr(row) as *mut T;
147            std::ptr::write(ptr, self);
148            *col.ticks_ptr_mut().add(row) = crate::archetype::ComponentTicks::new(tick);
149        }
150    }
151}
152
153macro_rules! impl_bundle_tuple {
154    ($($name:ident),*) => {
155        #[allow(non_snake_case)]
156        impl<$($name: crate::component::Bundle),*> Bundle for ($($name,)*) {
157            fn get_infos() -> Vec<crate::archetype::ComponentInfo> {
158                let mut infos = Vec::new();
159                $(
160                    infos.extend(<$name as crate::component::Bundle>::get_infos());
161                )*
162                infos
163            }
164
165            fn apply(self, world: &mut crate::world::World, entity: crate::entity::Entity) {
166                let ($($name,)*) = self;
167                $(
168                    $name.apply(world, entity);
169                )*
170            }
171
172            unsafe fn write_to_archetype(self, arch: &mut crate::archetype::Archetype, row: usize, tick: u32) {
173                let ($($name,)*) = self;
174                $(
175                    $name.write_to_archetype(arch, row, tick);
176                )*
177            }
178        }
179    };
180}
181
182impl_bundle_tuple!(A);
183impl_bundle_tuple!(A, B);
184impl_bundle_tuple!(A, B, C);
185impl_bundle_tuple!(A, B, C, D);
186impl_bundle_tuple!(A, B, C, D, E);
187impl_bundle_tuple!(A, B, C, D, E, F);
188impl_bundle_tuple!(A, B, C, D, E, F, G);
189impl_bundle_tuple!(A, B, C, D, E, F, G, H);
190impl_bundle_tuple!(A, B, C, D, E, F, G, H, I);
191impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J);
192impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K);
193impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
194impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
195impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
196impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
197impl_bundle_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);