use std::cell::RefCell;
use std::rc::Rc;
use deno_core::OpState;
use crate::physics::types::*;
use super::physics_ops::PhysicsState;
#[deno_core::op2]
#[serde]
fn op_serialize_physics_state(state: &mut OpState) -> Vec<f64> {
let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
let ps = physics.borrow();
let world = match ps.0.as_ref() {
Some(w) => w,
None => return vec![],
};
let mut result: Vec<f64> = Vec::new();
let bodies = world.all_bodies();
let gravity = world.gravity();
result.push(bodies.len() as f64);
result.push(gravity.0 as f64);
result.push(gravity.1 as f64);
for body in &bodies {
result.push(body.id as f64);
result.push(match body.body_type {
BodyType::Static => 0.0,
BodyType::Dynamic => 1.0,
BodyType::Kinematic => 2.0,
});
match &body.shape {
Shape::Circle { radius } => {
result.push(0.0); result.push(*radius as f64); result.push(0.0); }
Shape::AABB { half_w, half_h } => {
result.push(1.0); result.push(*half_w as f64); result.push(*half_h as f64); }
Shape::Polygon { .. } => {
result.push(2.0); result.push(0.0);
result.push(0.0);
}
}
result.push(body.x as f64);
result.push(body.y as f64);
result.push(body.angle as f64);
result.push(body.vx as f64);
result.push(body.vy as f64);
result.push(body.angular_velocity as f64);
result.push(body.mass as f64);
result.push(body.material.restitution as f64);
result.push(body.material.friction as f64);
result.push(body.layer as f64);
result.push(body.mask as f64);
}
result
}
#[deno_core::op2]
fn op_restore_physics_state(state: &mut OpState, #[serde] data: Vec<f64>) {
if data.len() < 3 {
return;
}
let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
let mut ps = physics.borrow_mut();
let body_count = data[0] as usize;
let gravity_x = data[1] as f32;
let gravity_y = data[2] as f32;
let mut world = crate::physics::world::PhysicsWorld::new(gravity_x, gravity_y);
let mut offset = 3;
for _ in 0..body_count {
if offset + 16 > data.len() {
break;
}
let _id = data[offset] as u32;
let body_type = match data[offset + 1] as u32 {
0 => BodyType::Static,
1 => BodyType::Dynamic,
2 => BodyType::Kinematic,
_ => BodyType::Dynamic,
};
let shape_type = data[offset + 2] as u32;
let shape_p1 = data[offset + 3] as f32;
let shape_p2 = data[offset + 4] as f32;
let x = data[offset + 5] as f32;
let y = data[offset + 6] as f32;
let _angle = data[offset + 7] as f32;
let vx = data[offset + 8] as f32;
let vy = data[offset + 9] as f32;
let _angular_velocity = data[offset + 10] as f32;
let mass = data[offset + 11] as f32;
let restitution = data[offset + 12] as f32;
let friction = data[offset + 13] as f32;
let layer = data[offset + 14] as u16;
let mask = data[offset + 15] as u16;
let shape = match shape_type {
0 => Shape::Circle { radius: shape_p1 },
1 => Shape::AABB { half_w: shape_p1, half_h: shape_p2 },
_ => Shape::AABB { half_w: shape_p1, half_h: shape_p2 },
};
let id = world.add_body(
body_type,
shape,
x, y,
mass,
Material { restitution, friction },
layer, mask,
);
world.set_velocity(id, vx, vy);
offset += 16;
}
ps.0 = Some(world);
}
#[deno_core::op2(fast)]
fn op_get_physics_body_count(state: &mut OpState) -> u32 {
let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
let ps = physics.borrow();
match ps.0.as_ref() {
Some(world) => world.body_count() as u32,
None => 0,
}
}
deno_core::extension!(
replay_ext,
ops = [
op_serialize_physics_state,
op_restore_physics_state,
op_get_physics_body_count,
],
);