use crate::error::Error;
use crate::{f16, sys, DataType, FaceInfo, MeshType};
use cxx::let_cxx_string;
pub struct Writer(pub(crate) *mut sys::PtexWriter);
impl Drop for Writer {
fn drop(&mut self) {
unsafe {
sys::ptexwriter_release(self.0);
}
}
}
pub trait AsUInt8Ptr {
fn as_u8_ptr(&self) -> *const u8;
}
impl AsUInt8Ptr for &[u8] {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr()
}
}
impl AsUInt8Ptr for &[u16] {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl AsUInt8Ptr for &[f16] {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl AsUInt8Ptr for &[f32] {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl AsUInt8Ptr for Vec<u8> {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr()
}
}
impl AsUInt8Ptr for Vec<u16> {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl AsUInt8Ptr for Vec<f16> {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl AsUInt8Ptr for Vec<f32> {
fn as_u8_ptr(&self) -> *const u8 {
self.as_ptr() as *const u8
}
}
impl Writer {
pub fn new(
filename: &std::path::Path,
mesh_type: MeshType,
data_type: DataType,
num_channels: i32,
alpha_channel: i32,
num_faces: i32,
generate_mipmaps: bool,
) -> Result<Self, Error> {
let_cxx_string!(error_str = "");
let filename_str = filename.to_str().unwrap_or_default();
let writer = unsafe {
sys::ptexwriter_open(
filename_str,
mesh_type,
data_type,
num_channels,
alpha_channel,
num_faces,
generate_mipmaps,
error_str.as_mut().get_unchecked_mut(),
)
};
if writer.is_null() || !error_str.is_empty() {
let error_message = if error_str.is_empty() {
format!("ptex: Writer::new({filename_str}) failed: {error_str}")
} else {
format!("ptex: Writer::new({filename_str}) failed")
};
return Err(Error::FileIO(filename.to_path_buf(), error_message));
}
Ok(Self(writer))
}
pub fn close(&mut self) -> Result<(), Error> {
let error_message = unsafe { sys::ptexwriter_close(self.0) };
if !error_message.is_empty() {
return Err(Error::Message(error_message));
}
Ok(())
}
pub fn write_face<TexelBuf: AsUInt8Ptr>(
&self,
face_id: i32,
face_info: &FaceInfo,
texel_buf: &TexelBuf,
stride: i32,
) -> bool {
unsafe {
sys::ptexwriter_write_face(self.0, face_id, face_info, texel_buf.as_u8_ptr(), stride)
}
}
}