use core::ptr::NonNull;
use std::ffi::c_void;
use crate::brushes::Brush;
use crate::ffi::{
noesis_base_component_release, noesis_mesh_create, noesis_mesh_data_create,
noesis_mesh_data_get_bounds, noesis_mesh_data_get_indices, noesis_mesh_data_get_uvs,
noesis_mesh_data_get_vertices, noesis_mesh_data_set_bounds, noesis_mesh_data_set_indices,
noesis_mesh_data_set_uvs, noesis_mesh_data_set_vertices, noesis_mesh_get_brush,
noesis_mesh_get_data, noesis_mesh_set_brush, noesis_mesh_set_data,
};
pub struct MeshData {
ptr: NonNull<c_void>,
num_vertices: u32,
num_uvs: u32,
num_indices: u32,
}
unsafe impl Send for MeshData {}
impl MeshData {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_mesh_data_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_mesh_data_create returned null"),
num_vertices: 0,
num_uvs: 0,
num_indices: 0,
}
}
#[must_use]
pub fn raw(&self) -> *mut c_void {
self.ptr.as_ptr()
}
pub fn set_vertices(&mut self, vertices: &[[f32; 2]]) {
let count = u32::try_from(vertices.len()).expect("vertex count exceeds u32");
unsafe {
noesis_mesh_data_set_vertices(self.ptr.as_ptr(), vertices.as_ptr().cast(), count);
}
self.num_vertices = count;
}
#[must_use]
pub fn vertices(&self) -> Vec<[f32; 2]> {
let mut out = vec![[0.0f32; 2]; self.num_vertices as usize];
unsafe {
noesis_mesh_data_get_vertices(
self.ptr.as_ptr(),
out.as_mut_ptr().cast(),
self.num_vertices,
);
}
out
}
#[must_use]
pub fn num_vertices(&self) -> u32 {
self.num_vertices
}
pub fn set_uvs(&mut self, uvs: &[[f32; 2]]) {
let count = u32::try_from(uvs.len()).expect("uv count exceeds u32");
unsafe {
noesis_mesh_data_set_uvs(self.ptr.as_ptr(), uvs.as_ptr().cast(), count);
}
self.num_uvs = count;
}
#[must_use]
pub fn uvs(&self) -> Vec<[f32; 2]> {
let mut out = vec![[0.0f32; 2]; self.num_uvs as usize];
unsafe {
noesis_mesh_data_get_uvs(self.ptr.as_ptr(), out.as_mut_ptr().cast(), self.num_uvs);
}
out
}
#[must_use]
pub fn num_uvs(&self) -> u32 {
self.num_uvs
}
pub fn set_indices(&mut self, indices: &[u16]) {
let count = u32::try_from(indices.len()).expect("index count exceeds u32");
unsafe {
noesis_mesh_data_set_indices(self.ptr.as_ptr(), indices.as_ptr(), count);
}
self.num_indices = count;
}
#[must_use]
pub fn indices(&self) -> Vec<u16> {
let mut out = vec![0u16; self.num_indices as usize];
unsafe {
noesis_mesh_data_get_indices(self.ptr.as_ptr(), out.as_mut_ptr(), self.num_indices);
}
out
}
#[must_use]
pub fn num_indices(&self) -> u32 {
self.num_indices
}
pub fn set_bounds(&mut self, bounds: [f32; 4]) {
unsafe {
noesis_mesh_data_set_bounds(
self.ptr.as_ptr(),
bounds[0],
bounds[1],
bounds[2],
bounds[3],
);
}
}
#[must_use]
pub fn bounds(&self) -> [f32; 4] {
let mut out = [0.0f32; 4];
unsafe {
noesis_mesh_data_get_bounds(self.ptr.as_ptr(), out.as_mut_ptr());
}
out
}
}
impl Default for MeshData {
fn default() -> Self {
Self::new()
}
}
impl Drop for MeshData {
fn drop(&mut self) {
unsafe { noesis_base_component_release(self.ptr.as_ptr()) }
}
}
pub struct Mesh {
ptr: NonNull<c_void>,
}
unsafe impl Send for Mesh {}
impl Mesh {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_mesh_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_mesh_create returned null"),
}
}
#[must_use]
pub fn raw(&self) -> *mut c_void {
self.ptr.as_ptr()
}
#[must_use = "a false return means the data was not set (the Mesh pointer was null or not a Noesis::Mesh)"]
pub fn set_data(&mut self, data: &MeshData) -> bool {
unsafe { noesis_mesh_set_data(self.ptr.as_ptr(), data.raw()) }
}
#[must_use]
pub fn data(&self) -> Option<NonNull<c_void>> {
NonNull::new(unsafe { noesis_mesh_get_data(self.ptr.as_ptr()) })
}
#[must_use = "a false return means the brush was not set (the Mesh pointer was null or not a Noesis::Mesh)"]
pub fn set_brush(&mut self, brush: &dyn Brush) -> bool {
unsafe { noesis_mesh_set_brush(self.ptr.as_ptr(), brush.brush_raw()) }
}
#[must_use]
pub fn brush(&self) -> Option<NonNull<c_void>> {
NonNull::new(unsafe { noesis_mesh_get_brush(self.ptr.as_ptr()) })
}
}
impl Default for Mesh {
fn default() -> Self {
Self::new()
}
}
impl Drop for Mesh {
fn drop(&mut self) {
unsafe { noesis_base_component_release(self.ptr.as_ptr()) }
}
}