oxygengine_physics_2d/
system.rs1use 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}