use crate::{ObjectId, obj};
use crate::MjError;
pub fn mj_defaultLROpt() -> crate::mjLROpt {
let mut c = std::mem::MaybeUninit::<crate::mjLROpt>::uninit();
unsafe { crate::bindgen::mj_defaultLROpt(c.as_mut_ptr()) };
unsafe { c.assume_init() }
}
pub fn mj_defaultSolRefImp() -> (
[f64; crate::bindgen::mjNREF as usize],
[f64; crate::bindgen::mjNIMP as usize],
) {
let mut solref = [0.0; crate::bindgen::mjNREF as usize];
let mut solimp = [0.0; crate::bindgen::mjNIMP as usize];
unsafe { crate::bindgen::mj_defaultSolRefImp(solref.as_mut_ptr(), solimp.as_mut_ptr()) };
(solref, solimp)
}
pub fn mj_defaultOption() -> crate::mjOption {
let mut c = std::mem::MaybeUninit::<crate::mjOption>::uninit();
unsafe { crate::bindgen::mj_defaultOption(c.as_mut_ptr()); }
unsafe { c.assume_init() }
}
pub fn mj_defaultVisual() -> crate::mjVisual {
let mut c = std::mem::MaybeUninit::<crate::mjVisual>::uninit();
unsafe { crate::bindgen::mj_defaultVisual(c.as_mut_ptr()) };
unsafe { c.assume_init() }
}
pub unsafe fn mj_copyModel(dest: Option<&mut crate::mjModel>, src: &crate::mjModel) -> Option<crate::mjModel> {
match dest {
Some(dest) => {
unsafe { crate::bindgen::mj_copyModel(dest.as_mut_ptr(), src.as_ptr()) };
None
}
None => {
let ptr = std::ptr::null_mut();
unsafe { crate::bindgen::mj_copyModel(ptr, src.as_ptr()); }
Some(crate::mjModel::from_raw(ptr))
}
}
}
pub fn mj_saveModel(
m: &crate::mjModel,
filename: Option<impl Into<String>>,
buffer: Option<&mut [u8]>,
) {
let filename = filename.map(|s| std::ffi::CString::new(s.into()).unwrap());
let buffer_sz = buffer.as_ref().map_or(0, |b| b.len() as i32);
unsafe {
crate::bindgen::mj_saveModel(
m.as_ptr(),
filename.map_or(std::ptr::null(), |cstr| cstr.as_ptr()),
buffer.map_or(std::ptr::null_mut(), |b| b.as_mut_ptr() as *mut std::ffi::c_void),
buffer_sz,
);
}
}
pub fn mj_loadModel(
filename: impl Into<String>,
) -> crate::mjModel {
let filename = std::ffi::CString::new(filename.into()).unwrap();
let c_ptr = unsafe {
crate::bindgen::mj_loadModel(
filename.as_ptr(),
std::ptr::null(), )
};
#[cfg(debug_assertions)] {
assert!(!c_ptr.is_null(), "Failed to load model from file: {}", filename.to_string_lossy());
}
crate::mjModel::from_raw(c_ptr)
}
pub fn mj_deleteModel(m: &mut crate::mjModel) {
unsafe { crate::bindgen::mj_deleteModel(m.as_mut_ptr()); }
}
pub fn mj_sizeModel(m: &crate::mjModel) -> usize {
unsafe { crate::bindgen::mj_sizeModel(m.as_ptr()) as usize }
}
pub fn mj_makeData(m: &crate::mjModel) -> crate::mjData {
let c_ptr = unsafe { crate::bindgen::mj_makeData(m.as_ptr()) };
#[cfg(debug_assertions)] {
assert!(!c_ptr.is_null(), "Failed to allocate mjData for model");
}
crate::mjData::from_raw(c_ptr)
}
pub unsafe fn mj_copyData(dest: &mut crate::mjData, m: &crate::mjModel, src: &crate::mjData) {
unsafe { crate::bindgen::mj_copyData(dest.as_mut_ptr(), m.as_ptr(), src.as_ptr()) };
}
pub fn mj_resetData(m: &crate::mjModel, d: &mut crate::mjData) {
unsafe { crate::bindgen::mj_resetData(m.as_ptr(), d.as_mut_ptr()) }
}
pub fn mj_resetDataDebug(m: &crate::mjModel, d: &mut crate::mjData, debug_value: u8) {
unsafe { crate::bindgen::mj_resetDataDebug(m.as_ptr(), d.as_mut_ptr(), debug_value) }
}
pub fn mj_resetDataKeyframe(
m: &crate::mjModel,
d: &mut crate::mjData,
key: Option<ObjectId<obj::Key>>,
) {
unsafe {
crate::bindgen::mj_resetDataKeyframe(
m.as_ptr(),
d.as_mut_ptr(),
key.map_or(-1, |k| k.index() as i32)
)
}
}
pub fn mj_markStack(d: &mut crate::mjData) {
unsafe { crate::bindgen::mj_markStack(d.as_mut_ptr()) }
}
pub fn mj_freeStack(d: &mut crate::mjData) {
unsafe { crate::bindgen::mj_freeStack(d.as_mut_ptr()) }
}
pub fn mj_stackAllocByte(d: &mut crate::mjData, bytes: usize, alignment: usize) -> *mut u8 {
unsafe { crate::bindgen::mj_stackAllocByte(d.as_mut_ptr(), bytes, alignment) as *mut u8 }
}
pub fn mj_stackAllocNum(d: &mut crate::mjData, size: usize) -> *mut f64 {
unsafe { crate::bindgen::mj_stackAllocNum(d.as_mut_ptr(), size) as *mut f64 }
}
pub fn mj_stackAllocInt(d: &mut crate::mjData, size: usize) -> *mut i32 {
unsafe { crate::bindgen::mj_stackAllocInt(d.as_mut_ptr(), size) as *mut i32 }
}
pub fn mj_deleteData(d: &mut crate::mjData) {
unsafe { crate::bindgen::mj_deleteData(d.as_mut_ptr()) };
}
pub fn mj_resetCallbacks() {
unsafe { crate::bindgen::mj_resetCallbacks() };
}
pub fn mj_setConst(m: &mut crate::mjModel, d: &mut crate::mjData) {
unsafe { crate::bindgen::mj_setConst(m.as_mut_ptr(), d.as_mut_ptr()) };
}
pub fn mj_setLengthRange(
m: &mut crate::mjModel,
d: &mut crate::mjData,
index: ObjectId<obj::Actuator>,
opt: &crate::mjLROpt,
) -> Result<(), MjError> {
let mut error = MjError::init();
let status = unsafe {
let (err_ptr, err_len) = error.as_parts();
crate::bindgen::mj_setLengthRange(
m.as_mut_ptr(),
d.as_mut_ptr(),
index.index() as i32,
opt,
err_ptr,
err_len,
)
};
if status == 1 {
Ok(())
} else {
Err(error)
}
}
pub fn mj_makeSpec() -> crate::mjSpec {
let c_ptr = unsafe { crate::bindgen::mj_makeSpec() };
#[cfg(debug_assertions)] {
assert!(!c_ptr.is_null(), "Failed to create empty mjSpec");
}
crate::mjSpec::from_raw(c_ptr)
}
pub fn mj_copySpec(s: &crate::mjSpec) -> crate::mjSpec {
let c_ptr = unsafe { crate::bindgen::mj_copySpec(s.as_ptr()) };
#[cfg(debug_assertions)] {
assert!(!c_ptr.is_null(), "Failed to copy mjSpec");
}
crate::mjSpec::from_raw(c_ptr)
}
pub fn mj_deleteSpec(s: &mut crate::mjSpec) {
unsafe { crate::bindgen::mj_deleteSpec(s.as_mut_ptr()) };
drop(unsafe { Box::from_raw(s.as_mut_ptr()) });
}
pub fn mjs_activatePlugin(s: &mut crate::mjSpec, name: impl Into<String>) -> Result<(), MjError> {
let name = std::ffi::CString::new(name.into()).unwrap();
let status = unsafe { crate::bindgen::mjs_activatePlugin(s.as_mut_ptr(), name.as_ptr()) };
if status == 0 {
Ok(())
} else {
Err(MjError::from_error("Failed to activate plugin"))
}
}
pub fn mjs_setDeepCopy(s: &mut crate::mjSpec, deepcopy: bool) -> Result<(), MjError> {
let status = unsafe { crate::bindgen::mjs_setDeepCopy(s.as_mut_ptr(), deepcopy as i32) };
if status == 0 {
Ok(())
} else {
Err(MjError::from_error("Failed to set deep copy option"))
}
}