1pub mod physics;
2
3pub mod ent;
4pub mod world_physics_loader;
5
6use std::collections::HashMap;
7
8use crate::{
9 rendering::components::Camera, resources::Resources, AssetLoadConfig, AssetLoader,
10 EmeraldError, PhysicsEngine, PhysicsHandler, Transform, WorldMergeHandler,
11};
12
13use hecs::{
14 Bundle, Component, ComponentRef, DynamicBundle, Entity, EntityRef, NoSuchEntity, Query,
15 QueryBorrow, QueryItem, QueryOne, SpawnBatchIter,
16};
17use rapier2d::prelude::{RigidBodyBuilder, RigidBodyHandle};
18
19use self::{
20 ent::{
21 ent_transform_loader::load_transform_from_toml, load_ent, EntLoadConfig,
22 TRANSFORM_SCHEMA_KEY,
23 },
24 world_physics_loader::load_world_physics,
25};
26
27pub struct World {
28 pub(crate) physics_engine: Option<PhysicsEngine>,
29 pub(crate) inner: hecs::World,
30 resources: Resources,
31 merge_handler: Option<WorldMergeHandler>,
32}
33impl Default for World {
34 fn default() -> Self {
35 World {
36 physics_engine: None,
37 inner: hecs::World::default(),
38 merge_handler: None,
39 resources: Resources::new(),
40 }
41 }
42}
43impl World {
44 pub fn new() -> Self {
45 Default::default()
46 }
47
48 pub fn new_with_merge_handler(world_merge_handler: WorldMergeHandler) -> Self {
49 let mut world = World::new();
50 world.set_merge_handler(world_merge_handler);
51 world
52 }
53
54 pub fn set_merge_handler(&mut self, world_merge_handler: WorldMergeHandler) {
55 self.merge_handler = Some(world_merge_handler);
56 }
57
58 pub fn merge(&mut self, mut other_world: World, offset: Transform) -> Result<(), EmeraldError> {
64 for (_, transform) in other_world.query::<&mut Transform>().iter() {
65 *transform = transform.clone() + offset.clone();
66 }
67
68 let mut entity_id_shift_map = HashMap::new();
69 let other_entities = other_world
70 .inner
71 .iter()
72 .map(|entity_ref| entity_ref.entity())
73 .collect::<Vec<Entity>>();
74
75 for old_id in other_entities {
76 let bundle = match other_world.inner.take(old_id.clone()) {
77 Err(_) => {
78 return Err(EmeraldError::new(format!(
79 "Entity {:?} does not exist, cannot merge.",
80 old_id
81 )))
82 }
83 Ok(bundle) => bundle,
84 };
85
86 let new_id = self.inner.spawn(bundle);
87 entity_id_shift_map.insert(old_id.clone(), new_id.clone());
88 self.merge_physics_entity(other_world.physics_engine(), old_id, new_id)?;
89 }
90
91 if let Some(merge_handler) = self.merge_handler {
92 (merge_handler)(self, &mut other_world, entity_id_shift_map)?;
93 }
94
95 Ok(())
96 }
97
98 fn merge_physics_entity(
100 &mut self,
101 other_world_physics: &mut PhysicsEngine,
102 old_id: Entity,
103 new_id: Entity,
104 ) -> Result<(), EmeraldError> {
105 self.physics_engine();
107
108 let mut colliders = Vec::new();
109 for c_id in other_world_physics.get_colliders_handles(old_id.clone()) {
110 if let Some(collider) = other_world_physics.remove_collider(c_id) {
111 colliders.push(collider);
112 }
113 }
114
115 if let Some(rigid_body) = other_world_physics.remove_body(old_id.clone()) {
116 let physics_engine = self.physics_engine.as_mut().unwrap();
117 let new_rbh = physics_engine.add_body(new_id.clone(), rigid_body, &mut self.inner)?;
118
119 for collider in colliders {
120 physics_engine.add_collider(new_rbh, collider);
121 }
122 }
123
124 Ok(())
125 }
126
127 pub(crate) fn physics_engine(&mut self) -> &mut PhysicsEngine {
132 if self.physics_engine.is_none() {
133 self.physics_engine = Some(PhysicsEngine::new());
134 }
135
136 self.physics_engine.as_mut().unwrap()
138 }
139
140 #[inline]
141 pub fn resources(&mut self) -> &mut Resources {
142 &mut self.resources
143 }
144
145 #[inline]
146 pub fn resources_ref(&self) -> &Resources {
147 &self.resources
148 }
149
150 #[inline]
153 pub fn make_active_camera(&mut self, entity: Entity) -> Result<(), EmeraldError> {
154 let mut set_camera = false;
155 if let Ok(mut camera) = self.get::<&mut Camera>(entity) {
156 camera.is_active = true;
157 set_camera = true;
158 }
159
160 if set_camera {
161 for (id, mut camera_to_disable) in self.query::<&mut Camera>().iter() {
162 if id != entity {
163 camera_to_disable.is_active = false;
164 }
165 }
166
167 return Ok(());
168 }
169
170 Err(EmeraldError::new(format!(
171 "Entity {:?} either does not exist or does not hold a camera",
172 entity
173 )))
174 }
175
176 #[inline]
177 pub fn get_active_camera(&self) -> Option<Entity> {
178 for (id, camera) in self.query::<&Camera>().iter() {
179 if camera.is_active {
180 return Some(id);
181 }
182 }
183
184 None
185 }
186
187 pub fn spawn(&mut self, components: impl DynamicBundle) -> Entity {
188 self.inner.spawn(components)
189 }
190
191 pub fn spawn_with_body(
192 &mut self,
193 components: impl DynamicBundle,
194 body_builder: RigidBodyBuilder,
195 ) -> Result<(Entity, RigidBodyHandle), EmeraldError> {
196 let entity = self.spawn(components);
197 let rbh = self.physics().build_body(entity, body_builder)?;
198
199 Ok((entity, rbh))
200 }
201
202 pub fn spawn_batch<I>(&mut self, iter: I) -> SpawnBatchIter<'_, I::IntoIter>
203 where
204 I: IntoIterator,
205 I::Item: Bundle + 'static,
206 {
207 self.inner.spawn_batch::<I>(iter)
208 }
209
210 pub fn despawn(&mut self, entity: Entity) -> Result<(), EmeraldError> {
211 self.physics_engine().remove_body(entity);
212
213 match self.inner.despawn(entity.clone()) {
214 Ok(()) => Ok(()),
215 Err(e) => Err(EmeraldError::new(format!(
216 "Error despawning entity {:?}. {:?}",
217 entity, e
218 ))),
219 }
220 }
221
222 pub fn clear(&mut self) {
223 self.inner.clear();
224 self.physics_engine = None;
225 }
226
227 pub fn query<Q: Query>(&self) -> QueryBorrow<'_, Q> {
228 self.inner.query::<Q>()
229 }
230
231 pub fn get<'a, T: ComponentRef<'a>>(&'a self, entity: Entity) -> Result<T::Ref, EmeraldError> {
232 match self.inner.get::<T>(entity.clone()) {
233 Ok(component_ref) => Ok(component_ref),
234 Err(e) => Err(EmeraldError::new(format!(
235 "Error getting component for entity {:?}. {:?}",
236 entity, e
237 ))),
238 }
239 }
240
241 pub fn collect<Q: Query>(&self) -> Vec<Entity> {
243 self.query::<Q>().iter().map(|(id, _)| id).collect()
244 }
245
246 pub fn collect_by<C: Component>(&self) -> Vec<Entity> {
248 self.query::<&C>().iter().map(|(id, _)| id).collect()
249 }
250
251 pub fn reserve_entity(&self) -> Entity {
252 self.inner.reserve_entity()
253 }
254
255 pub fn contains(&self, entity: Entity) -> bool {
257 self.inner.contains(entity)
258 }
259
260 pub fn count(&self) -> usize {
262 self.inner.len() as usize
263 }
264
265 pub fn satisfies<Q: Query>(&self, entity: Entity) -> bool {
267 self.inner
268 .satisfies::<Q>(entity)
269 .ok()
270 .map(|b| b)
271 .unwrap_or(false)
272 }
273
274 pub fn has<C: Component>(&self, entity: Entity) -> bool {
276 self.entity(entity)
277 .ok()
278 .map(|e| e.has::<C>())
279 .unwrap_or(false)
280 }
281
282 pub fn entity(&self, entity: Entity) -> Result<EntityRef<'_>, NoSuchEntity> {
284 self.inner.entity(entity)
285 }
286
287 pub fn query_one<Q: Query>(&self, entity: Entity) -> Result<QueryOne<'_, Q>, EmeraldError> {
298 match self.inner.query_one::<Q>(entity.clone()) {
299 Ok(component_ref) => Ok(component_ref),
300 Err(e) => Err(EmeraldError::new(format!(
301 "Error querying for entity {:?}. {:?}",
302 entity, e
303 ))),
304 }
305 }
306
307 pub fn query_one_mut<Q: Query>(
313 &mut self,
314 entity: Entity,
315 ) -> Result<QueryItem<'_, Q>, EmeraldError> {
316 match self.inner.query_one_mut::<Q>(entity.clone()) {
317 Ok(component_ref) => Ok(component_ref),
318 Err(e) => Err(EmeraldError::new(format!(
319 "Error querying for entity {:?}. {:?}",
320 entity, e
321 ))),
322 }
323 }
324
325 pub fn insert_one(
326 &mut self,
327 entity: Entity,
328 component: impl Component,
329 ) -> Result<(), NoSuchEntity> {
330 self.inner.insert(entity, (component,))
331 }
332
333 pub fn insert(
334 &mut self,
335 entity: Entity,
336 components: impl DynamicBundle,
337 ) -> Result<(), NoSuchEntity> {
338 self.inner.insert(entity, components)
339 }
340
341 pub fn remove<T: Bundle + 'static>(&mut self, entity: Entity) -> Result<T, EmeraldError> {
342 match self.inner.remove::<T>(entity.clone()) {
343 Ok(removed_bundle) => Ok(removed_bundle),
344 Err(e) => Err(EmeraldError::new(format!(
345 "Error removing bundle for entity {:?}. {:?}",
346 entity, e
347 ))),
348 }
349 }
350
351 pub fn remove_one<T: Component>(&mut self, entity: Entity) -> Result<T, EmeraldError> {
352 match self.inner.remove_one::<T>(entity.clone()) {
353 Ok(removed_component) => Ok(removed_component),
354 Err(e) => Err(EmeraldError::new(format!(
355 "Error removing component for entity {:?}. {:?}",
356 entity, e
357 ))),
358 }
359 }
360
361 pub fn physics(&mut self) -> PhysicsHandler<'_> {
362 self.physics_engine();
363 PhysicsHandler::new(self.physics_engine.as_mut().unwrap(), &mut self.inner)
364 }
365}
366
367pub struct WorldLoadConfig {
368 pub transform_offset: Transform,
369 pub merge_handler: Option<WorldMergeHandler>,
370}
371impl Default for WorldLoadConfig {
372 fn default() -> Self {
373 Self {
374 transform_offset: Default::default(),
375 merge_handler: None,
376 }
377 }
378}
379
380const PHYSICS_SCHEMA_KEY: &str = "physics";
381const ENTITIES_SCHEMA_KEY: &str = "entities";
382
383pub(crate) fn load_world(
384 loader: &mut AssetLoader<'_>,
385 toml: String,
386) -> Result<World, EmeraldError> {
387 let mut toml = toml.parse::<toml::Value>()?;
388 let mut world = World::new();
389
390 if let Some(merge_handler) = loader
391 .asset_engine
392 .load_config
393 .world_load_config
394 .merge_handler
395 {
396 world.set_merge_handler(merge_handler);
397 }
398
399 if let Some(table) = toml.as_table_mut() {
400 if let Some(physics_val) = table.remove(PHYSICS_SCHEMA_KEY) {
401 load_world_physics(loader, &mut world, &physics_val)?;
402 }
403
404 if let Some(mut entities_val) = table.remove(ENTITIES_SCHEMA_KEY) {
405 if let Some(entities) = entities_val.as_array_mut() {
406 for value in entities {
407 if let Some(path) = value.as_table_mut().map(|e| e.remove("path")).flatten() {
409 if let Some(path) = path.as_str() {
410 let transform = if let Some(toml) = value
411 .as_table_mut()
412 .map(|e| e.remove(TRANSFORM_SCHEMA_KEY))
413 .flatten()
414 {
415 load_transform_from_toml(&toml)?
416 } else {
417 Transform::default()
418 };
419 loader.ent(&mut world, path, transform)?;
420 }
421 } else {
422 load_ent(loader, &mut world, value, Transform::default())?;
423 }
424 }
425 }
426 }
427
428 if let Some(world_resource_loader) = loader.asset_engine.load_config.world_resource_loader {
429 for (key, value) in table.to_owned() {
430 (world_resource_loader)(loader, &mut world, value, key)?;
431 }
432 }
433 }
434
435 Ok(world)
436}
437
438#[cfg(test)]
439mod tests {
440 use hecs::Entity;
441
442 use crate::{rendering::components::Camera, Transform, World};
443
444 #[test]
445 fn make_active_camera_succeeds_on_entity_with_camera() {
446 let mut world = World::new();
447 let entity = world.spawn((Transform::default(), Camera::default()));
448 assert!(world.make_active_camera(entity).is_ok());
449
450 let active_camera_entity = world.get_active_camera().unwrap();
451
452 assert_eq!(entity, active_camera_entity);
453 }
454
455 #[test]
456 fn make_active_camera_fails_on_entity_without_camera() {
457 let mut world = World::new();
458 let entity = world.spawn((Transform::default(),));
459
460 assert!(world.make_active_camera(entity).is_err());
461 }
462
463 #[test]
464 fn collect_test() {
465 let mut world = World::new();
466 let mut transform_ents = world
467 .spawn_batch([(Transform::default(),), (Transform::default(),)])
468 .collect::<Vec<Entity>>();
469 let str_ents = world
470 .spawn_batch([
471 (Transform::default(), String::from("test1")),
472 (Transform::default(), String::from("test2")),
473 (Transform::default(), String::from("test3")),
474 ])
475 .collect::<Vec<Entity>>();
476 transform_ents.extend(str_ents.clone());
477
478 let usize_ent = world.spawn((Transform::default(), 1usize));
479 transform_ents.push(usize_ent.clone());
480
481 assert_eq!(world.collect::<&Transform>(), transform_ents);
482 assert_eq!(world.collect::<(&Transform, &String)>(), str_ents);
483 assert_eq!(world.collect::<(&Transform, &usize)>(), vec![usize_ent]);
484
485 assert_eq!(world.collect_by::<Transform>().len(), 6);
486 assert_eq!(world.collect_by::<String>().len(), 3);
487 assert_eq!(world.collect_by::<usize>().len(), 1);
488 }
489
490 #[test]
491 fn get_succeeds_on_preexisting_component() {
492 let mut world = World::new();
493 let entity = world.spawn((Transform::default(),));
494
495 assert!(world.get::<&Transform>(entity).is_ok());
496 }
497
498 #[test]
499 fn get_fails_on_nonexisting_component() {
500 let mut world = World::new();
501 let entity = world.spawn((Transform::default(),));
502
503 assert!(world.get::<&String>(entity).is_err());
504 }
505
506 #[test]
507 fn get_can_mutate() {
508 let mut world = World::new();
509 let entity = world.spawn((Transform::default(),));
510 let expected_value = 100.0;
511
512 {
513 let mut entity_transform = world.get::<&mut Transform>(entity).unwrap();
514 entity_transform.translation.x = expected_value;
515 }
516
517 assert!(world.get::<&Transform>(entity).unwrap().translation.x == expected_value);
518 }
519
520 #[test]
521 fn query_one_is_none_on_nonexisting_bundle() {
522 let mut world = World::new();
523 let entity = world.spawn((Transform::default(),));
524
525 let mut query = world.query_one::<(&Transform, &String)>(entity).unwrap();
526 assert!(query.get().is_none());
527 }
528
529 #[test]
530 fn satisfies_test() {
531 let mut world = World::new();
532
533 let id = world.spawn((Transform::default(), 100usize));
534
535 assert!(world.satisfies::<&Transform>(id));
536 assert!(world.satisfies::<(&Transform, &usize)>(id));
537 assert!(!world.satisfies::<(&Transform, &String)>(id));
538 assert!(!world.satisfies::<(&Transform, &usize, &String)>(id));
539 }
540
541 #[test]
542 fn has_test() {
543 let mut world = World::new();
544 let id = world.spawn((Transform::default(), 100usize));
545
546 assert!(world.has::<Transform>(id));
547 assert!(world.has::<usize>(id));
548 assert!(!world.has::<String>(id));
549 }
550
551 #[test]
552 fn query_one_is_some_on_existing_bundle() {
553 let mut world = World::new();
554 let entity = world.spawn((Transform::default(), "blah".to_string()));
555
556 let mut query = world.query_one::<(&Transform, &String)>(entity).unwrap();
557 assert!(query.get().is_some());
558 }
559
560 #[test]
561 fn query_one_mut_fails_on_nonexisting_bundle() {
562 let mut world = World::new();
563 let entity = world.spawn((Transform::default(),));
564
565 assert!(world
566 .query_one_mut::<(&Transform, &String)>(entity)
567 .is_err());
568 }
569
570 #[test]
571 fn query_one_mut_succeeds_on_existing_bundle() {
572 let mut world = World::new();
573 let entity = world.spawn((Transform::default(), "blah".to_string()));
574
575 assert!(world.query_one_mut::<(&Transform, &String)>(entity).is_ok());
576 }
577
578 #[test]
579 fn contains_is_accurate() {
580 let mut world = World::new();
581 let entity = world.spawn((Transform::default(),));
582
583 assert!(world.contains(entity));
584 world.despawn(entity).unwrap();
585 assert!(!world.contains(entity));
586 }
587
588 #[test]
589 fn count_is_accurate() {
590 let mut world = World::new();
591 let expected_count = 100;
592 for _ in 0..expected_count {
593 world.spawn((Transform::default(),));
594 }
595
596 assert_eq!(world.count(), expected_count);
597 }
598
599 #[test]
600 fn insert_fails_on_nonexisting_entity() {
601 let mut world = World::new();
602 let entity = world.spawn((Transform::default(),));
603 world.despawn(entity).unwrap();
604
605 assert!(world.insert_one(entity, 0).is_err());
606 }
607
608 #[test]
609 fn insert_overwrites_previous_component() {
610 struct TestStruct {
611 pub x: usize,
612 }
613 let expected_value = 100;
614 let mut world = World::new();
615 let entity = world.spawn((Transform::default(), TestStruct { x: 0 }));
616
617 world
618 .insert_one(entity, TestStruct { x: expected_value })
619 .unwrap();
620
621 assert_eq!(world.get::<&TestStruct>(entity).unwrap().x, expected_value);
622 }
623
624 #[test]
625 fn remove_succeeds_on_preexisting_bundle() {
626 struct TestStruct {}
627 let mut world = World::new();
628 let entity = world.spawn((Transform::default(), TestStruct {}));
629
630 assert!(world.remove::<(Transform, TestStruct)>(entity).is_ok());
631
632 assert!(world.remove::<(Transform, TestStruct)>(entity).is_err());
634 }
635
636 #[test]
637 fn remove_fails_on_nonexisting_bundle() {
638 struct TestStruct {}
639 struct NoStruct {}
640 let mut world = World::new();
641 let entity = world.spawn((Transform::default(), TestStruct {}));
642
643 assert!(world
645 .remove::<(Transform, TestStruct, NoStruct)>(entity)
646 .is_err());
647 }
648
649 #[test]
650 fn remove_one_succeeds_on_preexisting_component() {
651 struct TestStruct {}
652 let mut world = World::new();
653 let entity = world.spawn((Transform::default(), TestStruct {}));
654
655 assert!(world.remove_one::<TestStruct>(entity).is_ok());
656 assert!(world.remove_one::<TestStruct>(entity).is_err());
657 }
658
659 #[test]
660 fn remove_one_fails_on_nonexisting_component() {
661 struct TestStruct {}
662 let mut world = World::new();
663 let entity = world.spawn((Transform::default(),));
664
665 assert!(world.remove_one::<TestStruct>(entity).is_err());
666 }
667
668 mod resources_tests {
669 use crate::World;
670 struct MyResource {
671 pub value: usize,
672 }
673 struct MyOtherResource {
674 pub other_value: usize,
675 }
676
677 #[test]
678 fn retains_value() {
679 let mut world = World::new();
680 let expected_value = 10003;
681 world.resources().insert(MyResource {
682 value: expected_value,
683 });
684
685 assert_eq!(
686 world.resources().get::<MyResource>().unwrap().value,
687 expected_value
688 );
689 }
690
691 #[test]
692 fn mutates_value() {
693 let mut world = World::new();
694 let expected_value = 10003;
695 let init_value = 0;
696 world.resources().insert(MyResource { value: init_value });
697 world.resources().get_mut::<MyResource>().unwrap().value = expected_value;
698
699 assert_eq!(
700 world.resources().get::<MyResource>().unwrap().value,
701 expected_value
702 );
703 }
704
705 #[test]
706 fn holds_different_resources() {
707 let mut world = World::new();
708 let expected_value = 10003;
709 let other_expected_value = 3;
710 world.resources().insert(MyResource {
711 value: expected_value,
712 });
713 world.resources().insert(MyOtherResource {
714 other_value: other_expected_value,
715 });
716
717 assert_eq!(
718 world.resources().get::<MyResource>().unwrap().value,
719 expected_value
720 );
721
722 assert_eq!(
723 world
724 .resources()
725 .get::<MyOtherResource>()
726 .unwrap()
727 .other_value,
728 other_expected_value
729 );
730 }
731 }
732
733 mod physics_tests {
734 use rapier2d::prelude::RigidBodyBuilder;
735
736 use crate::{Transform, World};
737
738 #[test]
739 fn add_body_on_preexisting_entity() {
740 let mut world = World::new();
741
742 let entity = world.spawn((Transform::default(),));
743 let rbh = world
744 .physics()
745 .build_body(entity, RigidBodyBuilder::dynamic())
746 .unwrap();
747
748 assert!(world.physics().rigid_body(rbh).is_some());
749 }
750
751 #[test]
752 fn remove_body_is_some_on_entity_with_body() {
753 let mut world = World::new();
754
755 let (entity, _) = world
756 .spawn_with_body((Transform::default(),), RigidBodyBuilder::dynamic())
757 .unwrap();
758 assert!(world.physics().remove_body(entity).is_some());
759 }
760
761 #[test]
762 fn remove_body_is_empty_on_entity_with_body() {
763 let mut world = World::new();
764
765 let entity = world.spawn((Transform::default(),));
766 assert!(world.physics().remove_body(entity).is_none());
767 }
768 }
769}