use crate::mujoco_c::*;
use std::ffi::CString;
use std::ops::Deref;
use crate::wrappers::mj_visualization::*;
use crate::wrappers::mj_model::MjModel;
use crate::wrappers::mj_data::MjData;
#[repr(C)]
struct mujoco_Simulate { _unused: [u8; 0] }
unsafe extern "C" {
fn mujoco_cSimulate_create(
cam: *mut mjvCamera,
opt: *mut mjvOption,
pert: *mut mjvPerturb,
user_scn: *mut mjvScene,
) -> *mut mujoco_Simulate;
fn mujoco_cSimulate_RenderInit(sim: *mut mujoco_Simulate);
fn mujoco_cSimulate_Load(sim: *mut mujoco_Simulate, m: *mut mjModel_, d: *mut mjData_, displayed_filename: *const std::os::raw::c_char);
fn mujoco_cSimulate_RenderStep(sim: *mut mujoco_Simulate) -> std::os::raw::c_int;
fn mujoco_cSimulate_Sync(sim: *mut mujoco_Simulate, state_only: std::os::raw::c_int);
fn mujoco_cSimulate_ExitRequest(sim: *mut mujoco_Simulate);
fn mujoco_cSimulate_destroy(sim: *mut mujoco_Simulate);
}
#[derive(Debug)]
pub struct MjViewerCpp {
sim: *mut mujoco_Simulate,
running: bool,
user_scn: Box<MjvScene>,
_cam: Box<MjvCamera>,
_opt: Box<MjvOption>,
_pert: Box<MjvPerturb>,
}
impl MjViewerCpp {
pub fn running(&self) -> bool {
self.running
}
pub fn user_scn_mut(&mut self) -> &mut MjvScene {
&mut self.user_scn
}
pub unsafe fn launch_passive<M: Deref<Target = MjModel> + Clone + Send + Sync>(model: M, data: &MjData<M>, max_user_geom: usize) -> Self {
let mut cam = Box::new(MjvCamera::default());
let mut opt: Box<MjvOption> = Box::new(MjvOption::default());
let mut pert = Box::new(MjvPerturb::default());
let mut user_scn = Box::new(MjvScene::new(model.clone(), max_user_geom));
let sim = unsafe { mujoco_cSimulate_create(&mut *cam, &mut *opt, &mut *pert, user_scn.ffi_mut()) };
assert!(!sim.is_null(), "mujoco_cSimulate_create returned a null pointer");
let sim_usize = sim as usize;
let model_usize = model.as_raw_ptr() as usize;
let data_usize = data.as_raw_ptr() as usize;
unsafe { mujoco_cSimulate_RenderInit(sim) };
let load_thread = std::thread::spawn(move || {
let sim = sim_usize as *mut mujoco_Simulate;
let m = model_usize as *mut mjModel_;
let d = data_usize as *mut mjData_;
let c_filename = CString::new("file.xml").unwrap();
unsafe { mujoco_cSimulate_Load(sim, m, d, c_filename.as_ptr()) };
});
while !load_thread.is_finished() {
let running = unsafe { mujoco_cSimulate_RenderStep(sim) };
if running == 0 {
break;
}
}
load_thread.join().unwrap();
Self {sim, running: true, user_scn, _cam: cam, _opt: opt, _pert: pert}
}
pub unsafe fn render(&mut self) -> Result<(), &'static str> {
if !self.running {
return Err("render called after viewer has been closed!");
}
unsafe { self.running = mujoco_cSimulate_RenderStep(self.sim) == 1; }
Ok(())
}
pub fn sync(&mut self) {
if !self.running {
return;
}
unsafe {
mujoco_cSimulate_Sync(self.sim, 0);
}
}
}
impl Drop for MjViewerCpp {
fn drop(&mut self) {
unsafe {
mujoco_cSimulate_ExitRequest(self.sim);
mujoco_cSimulate_destroy(self.sim);
}
}
}
unsafe impl Send for MjViewerCpp {}
unsafe impl Sync for MjViewerCpp {}