emerald/
world.rs

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    /// Absorbs another world into this one. Resets and changes the Entity ids of the other worlds, when they are merged into this world.
59    /// All entities are placed into this world at their current transform.
60    /// The camera of the primary world will remain the current camera.
61    /// If physics is enabled, will keep its own physics settings.
62    /// Returns a map of OldEntity -> NewEntity. If you have components that store Entity references, use this map to update your references.
63    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    /// Helper function for [`merge`]
99    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        // create physics engine if it doesnt exist
106        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    /// We use this function to get the physics engine because we need to create one if it does not exist yet.
128    /// We by default have no engine to save memory and make worlds lighter.
129    /// Many worlds do not require physics and by not including it until it's needed,
130    /// we're more freely able to spam world creation.
131    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        // I'm not stoked on unwrapping internally, but this should be fine.
137        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    /// Disable all cameras then set the camera on the given entity as active.
151    /// Fails if the given entity does not exist, or does not have a camera.
152    #[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    /// Collects the ids of all entities with the given components
242    pub fn collect<Q: Query>(&self) -> Vec<Entity> {
243        self.query::<Q>().iter().map(|(id, _)| id).collect()
244    }
245
246    /// Collects the ids of all entities with the given components
247    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    /// Whether `entity` still exists
256    pub fn contains(&self, entity: Entity) -> bool {
257        self.inner.contains(entity)
258    }
259
260    /// The number of entities in the world
261    pub fn count(&self) -> usize {
262        self.inner.len() as usize
263    }
264
265    /// Whether or not the entity satisfies the query
266    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    /// Whether or not the entity has the component
275    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    /// Gets a reference to the entity
283    pub fn entity(&self, entity: Entity) -> Result<EntityRef<'_>, NoSuchEntity> {
284        self.inner.entity(entity)
285    }
286
287    /// Prepare a query against a single entity, using dynamic borrow checking
288    ///
289    /// Prefer [`query_one_mut`](Self::query_one_mut) when concurrent access to the [`World`] is not
290    /// required.
291    ///
292    /// Call [`get`](QueryOne::get) on the resulting [`QueryOne`] to actually execute the query. The
293    /// [`QueryOne`] value is responsible for releasing the dynamically-checked borrow made by
294    /// `get`, so it can't be dropped while references returned by `get` are live.
295    ///
296    /// Handy for accessing multiple components simultaneously.
297    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    /// Query a single entity in a uniquely borrow world
308    ///
309    /// Like [`query_one`](Self::query_one), but faster because dynamic borrow checks can be
310    /// skipped. Note that, unlike [`query_one`](Self::query_one), on success this returns the
311    /// query's results directly.
312    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                    // check if this is a ent path reference
408                    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        // Bundle should no longer exist
633        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        // This should fail because NoStruct doesn't exist on the entity
644        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}