1use crate::{
2 entity::Entity,
3 world::{World, WorldError},
4 Component,
5};
6use intuicio_data::type_hash::TypeHash;
7use std::collections::HashMap;
8
9#[derive(Default)]
10pub struct WorldProcessor {
11 #[allow(clippy::type_complexity)]
12 remap_entities:
13 HashMap<TypeHash, Box<dyn Fn(*mut u8, WorldProcessorEntityMapping) + Send + Sync>>,
14 #[allow(clippy::type_complexity)]
15 related_entities: HashMap<TypeHash, Box<dyn Fn(*const u8) -> Vec<Entity> + Send + Sync>>,
16 #[allow(clippy::type_complexity)]
17 format: HashMap<
18 TypeHash,
19 Box<dyn Fn(*const u8, &mut std::fmt::Formatter) -> std::fmt::Result + Send + Sync>,
20 >,
21}
22
23impl WorldProcessor {
24 pub fn register_entity_remapping<T: Component>(
25 &mut self,
26 f: impl Fn(&mut T, WorldProcessorEntityMapping) + Send + Sync + 'static,
27 ) {
28 self.register_entity_remapping_raw(TypeHash::of::<T>(), move |pointer, mapping| {
29 f(unsafe { pointer.cast::<T>().as_mut().unwrap() }, mapping)
30 });
31 }
32
33 pub fn register_entity_remapping_raw(
34 &mut self,
35 type_hash: TypeHash,
36 f: impl Fn(*mut u8, WorldProcessorEntityMapping) + Send + Sync + 'static,
37 ) {
38 self.remap_entities.insert(type_hash, Box::new(f));
39 }
40
41 pub fn unregister_entity_remapping<T: Component>(&mut self) {
42 self.unregister_entity_remapping_raw(TypeHash::of::<T>());
43 }
44
45 pub fn unregister_entity_remapping_raw(&mut self, type_hash: TypeHash) {
46 self.remap_entities.remove(&type_hash);
47 }
48
49 pub fn remap_entities<T>(&self, data: &mut T, mappings: WorldProcessorEntityMapping) {
50 unsafe {
51 self.remap_entities_raw(TypeHash::of::<T>(), data as *mut T as *mut u8, mappings);
52 }
53 }
54
55 pub unsafe fn remap_entities_raw(
57 &self,
58 type_hash: TypeHash,
59 pointer: *mut u8,
60 mappings: WorldProcessorEntityMapping,
61 ) {
62 if let Some(remapper) = self.remap_entities.get(&type_hash) {
63 remapper(pointer, mappings);
64 }
65 }
66
67 pub fn register_entity_inspector<T: Component>(
68 &mut self,
69 f: impl Fn(&T) -> Vec<Entity> + Send + Sync + 'static,
70 ) {
71 self.register_entity_inspector_raw(TypeHash::of::<T>(), move |pointer| {
72 f(unsafe { pointer.cast::<T>().as_ref().unwrap() })
73 });
74 }
75
76 pub fn register_entity_inspector_raw(
77 &mut self,
78 type_hash: TypeHash,
79 f: impl Fn(*const u8) -> Vec<Entity> + Send + Sync + 'static,
80 ) {
81 self.related_entities.insert(type_hash, Box::new(f));
82 }
83
84 pub fn unregister_entity_inspector<T: Component>(&mut self) {
85 self.unregister_entity_inspector_raw(TypeHash::of::<T>());
86 }
87
88 pub fn unregister_entity_inspector_raw(&mut self, type_hash: TypeHash) {
89 self.related_entities.remove(&type_hash);
90 }
91
92 pub fn related_entities<T>(&self, data: &T) -> Vec<Entity> {
93 unsafe { self.related_entities_raw(TypeHash::of::<T>(), data as *const T as *const u8) }
94 }
95
96 pub unsafe fn related_entities_raw(
98 &self,
99 type_hash: TypeHash,
100 pointer: *const u8,
101 ) -> Vec<Entity> {
102 if let Some(inspector) = self.related_entities.get(&type_hash) {
103 inspector(pointer)
104 } else {
105 Default::default()
106 }
107 }
108
109 pub fn all_related_entities<const LOCKING: bool>(
110 &self,
111 world: &World,
112 entities: impl IntoIterator<Item = Entity>,
113 output: &mut Vec<Entity>,
114 ) -> Result<(), WorldError> {
115 let mut stack = entities.into_iter().collect::<Vec<_>>();
116 while let Some(entity) = stack.pop() {
117 if !output.contains(&entity) {
118 output.push(entity);
119 let row = world.row::<LOCKING>(entity)?;
120 for type_hash in row.types() {
121 unsafe {
122 let data = row.data(type_hash)?;
123 stack.extend(self.related_entities_raw(type_hash, data));
124 }
125 }
126 }
127 }
128 Ok(())
129 }
130
131 pub fn register_display_formatter<T: Component + std::fmt::Display>(&mut self) {
132 self.register_formatter::<T>(|data, fmt| data.fmt(fmt));
133 }
134
135 pub fn register_debug_formatter<T: Component + std::fmt::Debug>(&mut self) {
136 self.register_formatter::<T>(|data, fmt| data.fmt(fmt));
137 }
138
139 pub fn register_formatter<T: Component>(
140 &mut self,
141 f: impl Fn(&T, &mut std::fmt::Formatter) -> std::fmt::Result + Send + Sync + 'static,
142 ) {
143 self.register_formatter_raw(TypeHash::of::<T>(), move |pointer, fmt| {
144 f(unsafe { pointer.cast::<T>().as_ref().unwrap() }, fmt)
145 });
146 }
147
148 pub fn register_formatter_raw(
149 &mut self,
150 type_hash: TypeHash,
151 f: impl Fn(*const u8, &mut std::fmt::Formatter) -> std::fmt::Result + Send + Sync + 'static,
152 ) {
153 self.format.insert(type_hash, Box::new(f));
154 }
155
156 pub fn unregister_formatter<T: Component>(&mut self) {
157 self.unregister_formatter_raw(TypeHash::of::<T>());
158 }
159
160 pub fn unregister_formatter_raw(&mut self, type_hash: TypeHash) {
161 self.format.remove(&type_hash);
162 }
163
164 pub fn format_component<'a, T: Component>(
165 &'a self,
166 data: &'a T,
167 ) -> WorldProcessorComponentFormat<'a, T> {
168 WorldProcessorComponentFormat {
169 processor: self,
170 data,
171 }
172 }
173
174 pub unsafe fn format_component_raw(
176 &self,
177 type_hash: TypeHash,
178 pointer: *const u8,
179 ) -> WorldProcessorComponentFormatRaw<'_> {
180 WorldProcessorComponentFormatRaw {
181 processor: self,
182 type_hash,
183 pointer,
184 }
185 }
186
187 pub fn format_world<'a, const LOCKING: bool>(
188 &'a self,
189 world: &'a World,
190 ) -> WorldProcessorWorldFormat<'a, LOCKING> {
191 WorldProcessorWorldFormat {
192 processor: self,
193 world,
194 }
195 }
196}
197
198pub struct WorldProcessorEntityMapping<'a> {
199 mapping: &'a HashMap<Entity, Entity>,
200}
201
202impl<'a> WorldProcessorEntityMapping<'a> {
203 pub fn new(mapping: &'a HashMap<Entity, Entity>) -> Self {
204 Self { mapping }
205 }
206
207 pub fn remap(&self, entity: Entity) -> Entity {
208 self.mapping.get(&entity).copied().unwrap_or_default()
209 }
210}
211
212pub struct WorldProcessorComponentFormat<'a, T: Component> {
213 processor: &'a WorldProcessor,
214 data: &'a T,
215}
216
217impl<T: Component> WorldProcessorComponentFormat<'_, T> {
218 pub fn format(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
219 if let Some(formatter) = self.processor.format.get(&TypeHash::of::<T>()) {
220 formatter(self.data as *const T as *const u8, fmt)
221 } else {
222 write!(fmt, "<MISSING>")
223 }
224 }
225}
226
227impl<T: Component> std::fmt::Debug for WorldProcessorComponentFormat<'_, T> {
228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229 self.format(f)
230 }
231}
232
233impl<T: Component> std::fmt::Display for WorldProcessorComponentFormat<'_, T> {
234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 self.format(f)
236 }
237}
238
239pub struct WorldProcessorComponentFormatRaw<'a> {
240 processor: &'a WorldProcessor,
241 type_hash: TypeHash,
242 pointer: *const u8,
243}
244
245impl WorldProcessorComponentFormatRaw<'_> {
246 pub fn format(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
247 if let Some(formatter) = self.processor.format.get(&self.type_hash) {
248 formatter(self.pointer, fmt)
249 } else {
250 write!(fmt, "<MISSING>")
251 }
252 }
253}
254
255impl std::fmt::Debug for WorldProcessorComponentFormatRaw<'_> {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 self.format(f)
258 }
259}
260
261impl std::fmt::Display for WorldProcessorComponentFormatRaw<'_> {
262 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
263 self.format(f)
264 }
265}
266
267pub struct WorldProcessorWorldFormat<'a, const LOCKING: bool> {
268 processor: &'a WorldProcessor,
269 world: &'a World,
270}
271
272impl<const LOCKING: bool> WorldProcessorWorldFormat<'_, LOCKING> {
273 pub fn format(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
274 fmt.debug_list()
275 .entries(self.world.entities().map(|entity| {
276 let access = self.world.row::<LOCKING>(entity).unwrap();
277 WorldProcessorWorldRowFormat {
278 entity,
279 components: access
280 .types()
281 .map(|type_hash| WorldProcessorWorldColumnFormat {
282 processor: self.processor,
283 type_hash,
284 data: unsafe { access.data(type_hash).unwrap() },
285 })
286 .collect(),
287 }
288 }))
289 .finish()
290 }
291}
292
293impl<const LOCKING: bool> std::fmt::Debug for WorldProcessorWorldFormat<'_, LOCKING> {
294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295 self.format(f)
296 }
297}
298
299impl<const LOCKING: bool> std::fmt::Display for WorldProcessorWorldFormat<'_, LOCKING> {
300 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301 self.format(f)
302 }
303}
304
305struct WorldProcessorWorldRowFormat<'a> {
306 entity: Entity,
307 components: Vec<WorldProcessorWorldColumnFormat<'a>>,
308}
309
310impl WorldProcessorWorldRowFormat<'_> {
311 pub fn format(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
312 fmt.debug_list()
313 .entry(&self.entity)
314 .entries(self.components.iter())
315 .finish()
316 }
317}
318
319impl std::fmt::Debug for WorldProcessorWorldRowFormat<'_> {
320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321 self.format(f)
322 }
323}
324
325impl std::fmt::Display for WorldProcessorWorldRowFormat<'_> {
326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
327 self.format(f)
328 }
329}
330
331struct WorldProcessorWorldColumnFormat<'a> {
332 processor: &'a WorldProcessor,
333 type_hash: TypeHash,
334 data: *const u8,
335}
336
337impl WorldProcessorWorldColumnFormat<'_> {
338 pub fn format(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
339 fmt.debug_struct("Column")
340 .field("type_hash", &self.type_hash)
341 .field("component", unsafe {
342 &self
343 .processor
344 .format_component_raw(self.type_hash, self.data)
345 })
346 .finish()
347 }
348}
349
350impl std::fmt::Debug for WorldProcessorWorldColumnFormat<'_> {
351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352 self.format(f)
353 }
354}
355
356impl std::fmt::Display for WorldProcessorWorldColumnFormat<'_> {
357 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
358 self.format(f)
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use super::*;
365 use crate::world::{Relation, World};
366
367 #[test]
368 fn test_world_merge() {
369 let mut world = World::default();
370 world.spawn((10usize,)).unwrap();
371
372 let mut world2 = World::default();
373 let a = world2.spawn((42usize,)).unwrap();
374 let b = world2.spawn((false, Relation::new((), a))).unwrap();
375 world2.spawn((true, Relation::new((), b))).unwrap();
376
377 let mut processor = WorldProcessor::default();
378 Relation::<()>::register_to_processor(&mut processor);
379
380 world.merge::<true>(world2, &processor).unwrap();
381 let entities = world.entities().collect::<Vec<_>>();
382 assert_eq!(entities.len(), 4);
383 assert_eq!(*world.component::<true, usize>(entities[0]).unwrap(), 10);
384 assert_eq!(*world.component::<true, usize>(entities[1]).unwrap(), 42);
385 assert!(!*world.component::<true, bool>(entities[2]).unwrap());
386 assert_eq!(
387 *world
388 .component::<true, Relation<()>>(entities[2])
389 .unwrap()
390 .iter()
391 .map(|(_, entity)| entity)
392 .collect::<Vec<_>>(),
393 vec![entities[1]]
394 );
395 assert!(*world.component::<true, bool>(entities[3]).unwrap());
396 assert_eq!(
397 *world
398 .component::<true, Relation<()>>(entities[3])
399 .unwrap()
400 .iter()
401 .map(|(_, entity)| entity)
402 .collect::<Vec<_>>(),
403 vec![entities[2]]
404 );
405 }
406}