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#[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
87pub 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);