Skip to main content

oxygengine_physics_2d/
system.rs

1use crate::{
2    component::{Collider2d, Collider2dBody, Collider2dInner, RigidBody2d, RigidBody2dInner},
3    resource::Physics2dWorld,
4};
5use core::{
6    app::AppLifeCycle,
7    ecs::{life_cycle::EntityChanges, Comp, Entity, Universe, WorldRef},
8};
9use nphysics2d::object::{BodyPartHandle, DefaultBodyHandle, DefaultColliderHandle};
10use std::collections::HashMap;
11
12#[derive(Debug, Default)]
13pub struct Physics2dSystemCache {
14    cached_bodies: HashMap<Entity, DefaultBodyHandle>,
15    cached_colliders: HashMap<Entity, DefaultColliderHandle>,
16}
17
18pub type Physics2dSystemResources<'a> = (
19    WorldRef,
20    &'a EntityChanges,
21    &'a AppLifeCycle,
22    &'a mut Physics2dWorld,
23    &'a mut Physics2dSystemCache,
24    Comp<&'a mut RigidBody2d>,
25    Comp<&'a mut Collider2d>,
26    Comp<&'a Collider2dBody>,
27);
28
29pub fn physics_2d_system(universe: &mut Universe) {
30    let (world, changes, lifecycle, mut physics, mut cache, ..) =
31        universe.query_resources::<Physics2dSystemResources>();
32
33    for entity in changes.despawned() {
34        if let Some(handle) = cache.cached_bodies.remove(&entity) {
35            physics.destroy_body(handle);
36        }
37        if let Some(handle) = cache.cached_colliders.remove(&entity) {
38            physics.destroy_collider(handle);
39        }
40    }
41
42    for (entity, body) in world.query::<&mut RigidBody2d>().iter() {
43        if !body.is_created() {
44            let b = body.take_description().unwrap().build();
45            let h = physics.insert_body(b);
46            body.0 = RigidBody2dInner::Handle(h);
47            cache.cached_bodies.insert(entity, h);
48        }
49    }
50
51    for (entity, (collider, collider_body)) in
52        world.query::<(&mut Collider2d, &Collider2dBody)>().iter()
53    {
54        if !collider.is_created() {
55            let other = match collider_body {
56                Collider2dBody::Me => entity,
57                Collider2dBody::Entity(other) => *other,
58            };
59            if let Ok(body) = unsafe { world.get_unchecked::<&RigidBody2d>(other) } {
60                if let Some(h) = body.handle() {
61                    let c = collider
62                        .take_description()
63                        .unwrap()
64                        .build(BodyPartHandle(h, 0));
65                    let h = physics.insert_collider(c, entity);
66                    collider.0 = Collider2dInner::Handle(h);
67                    cache.cached_colliders.insert(entity, h);
68                }
69            }
70        }
71    }
72
73    physics.process(lifecycle.delta_time_seconds());
74}