1use std::cell::RefCell;
2use std::rc::Rc;
3
4use deno_core::OpState;
5
6use crate::physics::types::*;
7use crate::physics::world::PhysicsWorld;
8
9pub struct PhysicsState(pub Option<PhysicsWorld>);
11
12#[deno_core::op2(fast)]
13fn op_create_physics_world(state: &mut OpState, gravity_x: f64, gravity_y: f64) {
14 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
15 physics.borrow_mut().0 = Some(PhysicsWorld::new(gravity_x as f32, gravity_y as f32));
16}
17
18#[deno_core::op2(fast)]
19fn op_destroy_physics_world(state: &mut OpState) {
20 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
21 physics.borrow_mut().0 = None;
22}
23
24#[deno_core::op2(fast)]
25fn op_physics_step(state: &mut OpState, dt: f64) {
26 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
27 if let Some(world) = physics.borrow_mut().0.as_mut() {
28 world.step(dt as f32);
29 }
30}
31
32#[deno_core::op2(fast)]
36fn op_create_body(
37 state: &mut OpState,
38 body_type: u32,
39 shape_type: u32,
40 shape_p1: f64,
41 shape_p2: f64,
42 x: f64,
43 y: f64,
44 mass: f64,
45 restitution: f64,
46 friction: f64,
47 layer: u32,
48 mask: u32,
49) -> u32 {
50 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
51 let mut ps = physics.borrow_mut();
52 let world = match ps.0.as_mut() {
53 Some(w) => w,
54 None => return u32::MAX,
55 };
56
57 let bt = match body_type {
58 0 => BodyType::Static,
59 1 => BodyType::Dynamic,
60 2 => BodyType::Kinematic,
61 _ => return u32::MAX,
62 };
63
64 let shape = match shape_type {
65 0 => Shape::Circle {
66 radius: shape_p1 as f32,
67 },
68 1 => Shape::AABB {
69 half_w: shape_p1 as f32,
70 half_h: shape_p2 as f32,
71 },
72 _ => return u32::MAX,
73 };
74
75 let material = Material {
76 restitution: restitution as f32,
77 friction: friction as f32,
78 };
79
80 world.add_body(bt, shape, x as f32, y as f32, mass as f32, material, layer as u16, mask as u16)
81}
82
83#[deno_core::op2(fast)]
84fn op_remove_body(state: &mut OpState, id: u32) {
85 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
86 let mut ps = physics.borrow_mut();
87 if let Some(world) = ps.0.as_mut() {
88 world.remove_body(id);
89 }
90}
91
92#[deno_core::op2]
94#[serde]
95fn op_get_body_state(state: &mut OpState, id: u32) -> Vec<f64> {
96 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
97 let ps = physics.borrow();
98 match ps.0.as_ref().and_then(|w| w.get_body(id)) {
99 Some(body) => vec![
100 body.x as f64,
101 body.y as f64,
102 body.angle as f64,
103 body.vx as f64,
104 body.vy as f64,
105 body.angular_velocity as f64,
106 if body.sleeping { 1.0 } else { 0.0 },
107 ],
108 None => vec![],
109 }
110}
111
112#[deno_core::op2(fast)]
113fn op_set_body_velocity(state: &mut OpState, id: u32, vx: f64, vy: f64) {
114 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
115 let mut ps = physics.borrow_mut();
116 if let Some(world) = ps.0.as_mut() {
117 world.set_velocity(id, vx as f32, vy as f32);
118 }
119}
120
121#[deno_core::op2(fast)]
122fn op_set_body_angular_velocity(state: &mut OpState, id: u32, av: f64) {
123 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
124 let mut ps = physics.borrow_mut();
125 if let Some(world) = ps.0.as_mut() {
126 world.set_angular_velocity(id, av as f32);
127 }
128}
129
130#[deno_core::op2(fast)]
131fn op_apply_force(state: &mut OpState, id: u32, fx: f64, fy: f64) {
132 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
133 let mut ps = physics.borrow_mut();
134 if let Some(world) = ps.0.as_mut() {
135 world.apply_force(id, fx as f32, fy as f32);
136 }
137}
138
139#[deno_core::op2(fast)]
140fn op_apply_impulse(state: &mut OpState, id: u32, ix: f64, iy: f64) {
141 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
142 let mut ps = physics.borrow_mut();
143 if let Some(world) = ps.0.as_mut() {
144 world.apply_impulse(id, ix as f32, iy as f32);
145 }
146}
147
148#[deno_core::op2(fast)]
149fn op_set_body_position(state: &mut OpState, id: u32, x: f64, y: f64) {
150 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
151 let mut ps = physics.borrow_mut();
152 if let Some(world) = ps.0.as_mut() {
153 world.set_position(id, x as f32, y as f32);
154 }
155}
156
157#[deno_core::op2(fast)]
158fn op_set_collision_layers(state: &mut OpState, id: u32, layer: u32, mask: u32) {
159 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
160 let mut ps = physics.borrow_mut();
161 if let Some(world) = ps.0.as_mut() {
162 world.set_collision_layers(id, layer as u16, mask as u16);
163 }
164}
165
166#[deno_core::op2(fast)]
167fn op_create_distance_joint(
168 state: &mut OpState,
169 body_a: u32,
170 body_b: u32,
171 distance: f64,
172) -> u32 {
173 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
174 let mut ps = physics.borrow_mut();
175 match ps.0.as_mut() {
176 Some(world) => world.add_constraint(Constraint::Distance {
177 id: 0,
178 body_a,
179 body_b,
180 distance: distance as f32,
181 anchor_a: (0.0, 0.0),
182 anchor_b: (0.0, 0.0),
183 }),
184 None => u32::MAX,
185 }
186}
187
188#[deno_core::op2(fast)]
189fn op_create_revolute_joint(
190 state: &mut OpState,
191 body_a: u32,
192 body_b: u32,
193 pivot_x: f64,
194 pivot_y: f64,
195) -> u32 {
196 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
197 let mut ps = physics.borrow_mut();
198 match ps.0.as_mut() {
199 Some(world) => world.add_constraint(Constraint::Revolute {
200 id: 0,
201 body_a,
202 body_b,
203 pivot: (pivot_x as f32, pivot_y as f32),
204 }),
205 None => u32::MAX,
206 }
207}
208
209#[deno_core::op2(fast)]
210fn op_remove_constraint(state: &mut OpState, id: u32) {
211 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
212 let mut ps = physics.borrow_mut();
213 if let Some(world) = ps.0.as_mut() {
214 world.remove_constraint(id);
215 }
216}
217
218#[deno_core::op2]
220#[serde]
221fn op_query_aabb(
222 state: &mut OpState,
223 min_x: f64,
224 min_y: f64,
225 max_x: f64,
226 max_y: f64,
227) -> Vec<u32> {
228 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
229 let ps = physics.borrow();
230 match ps.0.as_ref() {
231 Some(world) => world.query_aabb(min_x as f32, min_y as f32, max_x as f32, max_y as f32),
232 None => vec![],
233 }
234}
235
236#[deno_core::op2]
238#[serde]
239fn op_raycast(
240 state: &mut OpState,
241 origin_x: f64,
242 origin_y: f64,
243 dir_x: f64,
244 dir_y: f64,
245 max_dist: f64,
246) -> Vec<f64> {
247 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
248 let ps = physics.borrow();
249 match ps.0.as_ref() {
250 Some(world) => {
251 match world.raycast(
252 origin_x as f32,
253 origin_y as f32,
254 dir_x as f32,
255 dir_y as f32,
256 max_dist as f32,
257 ) {
258 Some((id, hx, hy, dist)) => {
259 vec![id as f64, hx as f64, hy as f64, dist as f64]
260 }
261 None => vec![],
262 }
263 }
264 None => vec![],
265 }
266}
267
268#[deno_core::op2]
270#[serde]
271fn op_get_contacts(state: &mut OpState) -> Vec<f64> {
272 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
273 let ps = physics.borrow();
274 match ps.0.as_ref() {
275 Some(world) => {
276 let contacts = world.get_contacts();
277 let mut result = Vec::with_capacity(contacts.len() * 7);
278 for c in contacts {
279 result.push(c.body_a as f64);
280 result.push(c.body_b as f64);
281 result.push(c.normal.0 as f64);
282 result.push(c.normal.1 as f64);
283 result.push(c.penetration as f64);
284 result.push(c.contact_point.0 as f64);
285 result.push(c.contact_point.1 as f64);
286 }
287 result
288 }
289 None => vec![],
290 }
291}
292
293deno_core::extension!(
294 physics_ext,
295 ops = [
296 op_create_physics_world,
297 op_destroy_physics_world,
298 op_physics_step,
299 op_create_body,
300 op_remove_body,
301 op_get_body_state,
302 op_set_body_velocity,
303 op_set_body_angular_velocity,
304 op_apply_force,
305 op_apply_impulse,
306 op_set_body_position,
307 op_set_collision_layers,
308 op_create_distance_joint,
309 op_create_revolute_joint,
310 op_remove_constraint,
311 op_query_aabb,
312 op_raycast,
313 op_get_contacts,
314 ],
315);