use std::ffi::CString;
use std::os::raw::c_char;
use xplm_sys::{XPLMCreateInstance, XPLMDestroyInstance, XPLMInstanceRef, XPLMInstanceSetPosition};
#[cfg(feature = "XPLM420")]
use xplm_sys::XPLMInstanceSetAutoShift;
use crate::scenery::{DrawInfo, Object};
pub struct Instance {
raw: XPLMInstanceRef,
dataref_count: usize,
}
unsafe impl Send for Instance {}
impl Instance {
pub fn new(object: &Object, datarefs: &[&str]) -> Option<Self> {
let c_strings: Vec<CString> = datarefs
.iter()
.map(|s| CString::new(*s))
.collect::<Result<_, _>>()
.ok()?;
let mut ptrs: Vec<*const c_char> = c_strings.iter().map(|s| s.as_ptr()).collect();
ptrs.push(std::ptr::null());
let raw = unsafe { XPLMCreateInstance(object.raw, ptrs.as_mut_ptr()) };
(!raw.is_null()).then_some(Self {
raw,
dataref_count: datarefs.len(),
})
}
#[cfg(feature = "XPLM420")]
pub fn set_auto_shift(&self) {
unsafe { XPLMInstanceSetAutoShift(self.raw) }
}
pub fn set_position(&self, position: DrawInfo, data: &[f32]) {
debug_assert_eq!(
data.len(),
self.dataref_count,
"Instance::set_position: data.len() must match the dataref count from Instance::new"
);
let raw_position = position.into();
unsafe { XPLMInstanceSetPosition(self.raw, &raw_position, data.as_ptr()) }
}
}
impl Drop for Instance {
fn drop(&mut self) {
unsafe { XPLMDestroyInstance(self.raw) }
}
}