From 6ea43cd82fe606c10ffe40a0a117ca598ecb265f Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 18 Feb 2026 17:17:35 +0800 Subject: [PATCH] feat: update bamp-rs --- .../BMapSharp/BMapSharp/BMapWrapper.cs | 16 +- Assets/BMapBindings/bmap-rs/src/bmap.rs | 2 +- .../BMapBindings/bmap-rs/src/bmap_wrapper.rs | 604 +++++++++++++++++- Assets/BMapBindings/bmap-rs/src/lib.rs | 2 +- Assets/BMapBindings/bmap-rs/src/marshaler.rs | 7 +- .../bmap-rs/src/virtools_types.rs | 27 +- .../pybmap/src/pybmap/bmap_wrapper.py | 2 +- 7 files changed, 603 insertions(+), 57 deletions(-) diff --git a/Assets/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs b/Assets/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs index bd05c98..a751d06 100644 --- a/Assets/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs +++ b/Assets/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs @@ -515,7 +515,7 @@ namespace BMapSharp.BMapWrapper { BMapException.ThrowIfFailed(fct_cnt(this.GetPointer(), out uint out_count)); return out_count; } - private IEnumerable GetGenericObject(FctProtoGetCount fct_cnt, FctProtoGetObject fct_obj, FctProtoCreateInstance fct_crt) { + private IEnumerable GetGenericObjects(FctProtoGetCount fct_cnt, FctProtoGetObject fct_obj, FctProtoCreateInstance fct_crt) { uint count = GetGenericObjectCount(fct_cnt); for (uint i = 0; i < count; ++i) { BMapException.ThrowIfFailed(fct_obj(this.GetPointer(), i, out uint out_id)); @@ -526,31 +526,31 @@ namespace BMapSharp.BMapWrapper { public uint GetTextureCount() => GetGenericObjectCount(BMap.BMFile_GetTextureCount); public IEnumerable GetTextures() => - GetGenericObject(BMap.BMFile_GetTextureCount, BMap.BMFile_GetTexture, (bmf, id) => new BMTexture(bmf, id)); + GetGenericObjects(BMap.BMFile_GetTextureCount, BMap.BMFile_GetTexture, (bmf, id) => new BMTexture(bmf, id)); public uint GetMaterialCount() => GetGenericObjectCount(BMap.BMFile_GetMaterialCount); public IEnumerable GetMaterials() => - GetGenericObject(BMap.BMFile_GetMaterialCount, BMap.BMFile_GetMaterial, (bmf, id) => new BMMaterial(bmf, id)); + GetGenericObjects(BMap.BMFile_GetMaterialCount, BMap.BMFile_GetMaterial, (bmf, id) => new BMMaterial(bmf, id)); public uint GetMeshCount() => GetGenericObjectCount(BMap.BMFile_GetMeshCount); public IEnumerable GetMeshes() => - GetGenericObject(BMap.BMFile_GetMeshCount, BMap.BMFile_GetMesh, (bmf, id) => new BMMesh(bmf, id)); + GetGenericObjects(BMap.BMFile_GetMeshCount, BMap.BMFile_GetMesh, (bmf, id) => new BMMesh(bmf, id)); public uint Get3dObjectCount() => GetGenericObjectCount(BMap.BMFile_Get3dObjectCount); public IEnumerable Get3dObjects() => - GetGenericObject(BMap.BMFile_Get3dObjectCount, BMap.BMFile_Get3dObject, (bmf, id) => new BM3dObject(bmf, id)); + GetGenericObjects(BMap.BMFile_Get3dObjectCount, BMap.BMFile_Get3dObject, (bmf, id) => new BM3dObject(bmf, id)); public uint GetGroupCount() => GetGenericObjectCount(BMap.BMFile_GetGroupCount); public IEnumerable GetGroups() => - GetGenericObject(BMap.BMFile_GetGroupCount, BMap.BMFile_GetGroup, (bmf, id) => new BMGroup(bmf, id)); + GetGenericObjects(BMap.BMFile_GetGroupCount, BMap.BMFile_GetGroup, (bmf, id) => new BMGroup(bmf, id)); public uint GetTargetLightCount() => GetGenericObjectCount(BMap.BMFile_GetTargetLightCount); public IEnumerable GetTargetLights() => - GetGenericObject(BMap.BMFile_GetTargetLightCount, BMap.BMFile_GetTargetLight, (bmf, id) => new BMTargetLight(bmf, id)); + GetGenericObjects(BMap.BMFile_GetTargetLightCount, BMap.BMFile_GetTargetLight, (bmf, id) => new BMTargetLight(bmf, id)); public uint GetTargetCameraCount() => GetGenericObjectCount(BMap.BMFile_GetTargetCameraCount); public IEnumerable GetTargetCameras() => - GetGenericObject(BMap.BMFile_GetTargetCameraCount, BMap.BMFile_GetTargetCamera, (bmf, id) => new BMTargetCamera(bmf, id)); + GetGenericObjects(BMap.BMFile_GetTargetCameraCount, BMap.BMFile_GetTargetCamera, (bmf, id) => new BMTargetCamera(bmf, id)); } diff --git a/Assets/BMapBindings/bmap-rs/src/bmap.rs b/Assets/BMapBindings/bmap-rs/src/bmap.rs index c69f77f..884d0bd 100644 --- a/Assets/BMapBindings/bmap-rs/src/bmap.rs +++ b/Assets/BMapBindings/bmap-rs/src/bmap.rs @@ -23,7 +23,7 @@ pub type CKID = u32; pub type PCKID = *mut CKID; pub type CKFLOAT = c_float; pub type CKINT = i32; -pub type CKBYTE = i8; +pub type CKBYTE = u8; pub type BMBOOL = bool; pub type BMVOID = c_void; diff --git a/Assets/BMapBindings/bmap-rs/src/bmap_wrapper.rs b/Assets/BMapBindings/bmap-rs/src/bmap_wrapper.rs index 7707836..e819aed 100644 --- a/Assets/BMapBindings/bmap-rs/src/bmap_wrapper.rs +++ b/Assets/BMapBindings/bmap-rs/src/bmap_wrapper.rs @@ -1,9 +1,11 @@ //! The module includes all senior wrappers for BMap FFI calling in Rust style. //! //! This module is what user of this library should use. -use crate::bmap::{self, BMBOOL, CKID, CKSTRING, PBMVOID}; +use crate::bmap::{self, BMBOOL, CKDWORD, CKID, CKSTRING, PBMVOID}; use crate::marshaler; -use std::iter::{Iterator, FusedIterator, ExactSizeIterator}; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +use std::iter::{ExactSizeIterator, FusedIterator, Iterator}; use std::marker::PhantomData; use std::mem::MaybeUninit; use std::sync::LazyLock; @@ -55,6 +57,12 @@ pub trait AbstractObject: AbstractPointer { unsafe fn get_ckid(&self) -> CKID; } +/// Specialized AbstractPointer which is only implemented by BMFileReader and BMFileWriter. +trait BMFileRW: AbstractPointer {} + +/// Specialized AbstractPointer which is only implemented by BM Objects. +trait BMFileObject: AbstractObject {} + // endregion // region: Struct Iterator and Assigner @@ -69,7 +77,7 @@ where // Fetch item let item = match it.next() { Some(v) => v, - None => return Err(Error::OutOfLength) + None => return Err(Error::OutOfLength), }; // Write item unsafe { *ptr.add(i) = item }; @@ -237,9 +245,7 @@ impl Drop for BMapGuard { } } -static BMAP_SINGLETON: LazyLock> = LazyLock::new(|| { - BMapGuard::new() -}); +static BMAP_SINGLETON: LazyLock> = LazyLock::new(|| BMapGuard::new()); fn get_bmap_guard_singleton() -> Result<&'static BMapGuard> { BMAP_SINGLETON.as_ref().map_err(|e| e.clone()) @@ -253,24 +259,71 @@ pub fn is_bmap_available() -> bool { // region: BMFileReader +// type FnProtoGetCount = unsafe extern "C" fn(PBMVOID, param_out!(CKDWORD)); +// type FnProtoGetObject = unsafe extern "C" fn(PBMVOID, param_in!(CKDWORD), param_out!(CKID)); + +// pub struct FileObjectIterator<'a, RW, FT, O> +// where +// RW: BMFileRW, +// FT: Fn(PBMVOID, CKID) -> O, +// O: AbstractObject, +// { +// fget: FnProtoGetObject, +// fcret: FT, +// cnt: usize, +// i: usize, +// rw: &'a RW, +// } + pub struct BMFileReader<'a> { handle: PBMVOID, - phantom: PhantomData<&'a BMapGuard> + phantom: PhantomData<&'a BMapGuard>, } +impl<'a> BMFileReader<'a> { + pub fn new( + file_name: &str, + temp_folder: &str, + texture_folder: &str, + encodings: &[T], + ) -> Result + where + T: Into> + Copy, + { + let file_name = unsafe { marshaler::to_native_string(file_name)? }; + let temp_folder = unsafe { marshaler::to_native_string(temp_folder)? }; + let texture_folder = unsafe { marshaler::to_native_string(texture_folder) }?; + let encodings = unsafe { marshaler::to_native_string_array(encodings)? }; + } +} + +// impl<'a> BMFileReader<'a> { + +// fn get_generic_object_count(&self, fc: FnProtoGetCount) -> Result { + +// } + +// fn get_generic_objects<'a, O, FC, FO>(&'a self, fc: FnProtoGetCount, fo: FnProtoGetObject) -> Result> { +// todo!() +// } + +// } + impl<'a> AbstractPointer for BMFileReader<'a> { unsafe fn get_pointer(&self) -> PBMVOID { self.handle } } +impl<'a> BMFileRW for BMFileReader<'a> {} + // endregion // region: BMFileWriter pub struct BMFileWriter<'a> { handle: PBMVOID, - phantom: PhantomData<&'a BMapGuard> + phantom: PhantomData<&'a BMapGuard>, } impl<'a> AbstractPointer for BMFileWriter<'a> { @@ -279,11 +332,13 @@ impl<'a> AbstractPointer for BMFileWriter<'a> { } } +impl<'a> BMFileRW for BMFileWriter<'a> {} + // endregion -// region: CKObjects +// region: BMObjects -// region: Utilities Functions +// region: Utility Functions fn get_copyable_value( o: &O, @@ -357,7 +412,7 @@ where // region: Traits -pub trait CKObject: AbstractObject { +pub trait BMObject: AbstractObject { fn get_name(&self) -> Result> { get_string_value(self, bmap::BMObject_GetName) } @@ -366,39 +421,526 @@ pub trait CKObject: AbstractObject { } } -pub trait CKTexture: CKObject {} +pub trait BMTexture: BMObject { + fn get_file_name(&self) -> Result> { + get_string_value(self, bmap::BMTexture_GetFileName) + } -pub trait CKMaterial: CKObject {} + // YYC MARK: + // Although load_image and save_image is not a "value setter", + // but they have same function signature so we can reuse those code. + fn load_image(&mut self, filepath: &str) -> Result<()> { + set_string_value(self, bmap::BMTexture_LoadImage, Some(filepath)) + } + fn save_image(&self, filepath: &str) -> Result<()> { + set_string_value(self, bmap::BMTexture_SaveImage, Some(filepath)) + } -pub trait CKMesh: CKObject {} + fn get_save_options(&self) -> Result { + get_copyable_value(self, bmap::BMTexture_GetSaveOptions) + } + fn set_save_options(&mut self, opt: bmap::CK_TEXTURE_SAVEOPTIONS) -> Result<()> { + set_copyable_value(self, bmap::BMTexture_SetSaveOptions, opt) + } + fn get_video_format(&self) -> Result { + get_copyable_value(self, bmap::BMTexture_GetVideoFormat) + } + fn set_video_format(&mut self, fmt: bmap::VX_PIXELFORMAT) -> Result<()> { + set_copyable_value(self, bmap::BMTexture_SetVideoFormat, fmt) + } +} -pub trait CK3dEntity: CKObject {} +pub trait BMMaterial: BMObject { + fn get_diffuse(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetDiffuse) + } + fn set_diffuse(&mut self, col: bmap::VxColor) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetDiffuse, col) + } + fn get_ambient(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetAmbient) + } + fn set_ambient(&mut self, col: bmap::VxColor) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetAmbient, col) + } + fn get_specular(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetSpecular) + } + fn set_specular(&mut self, col: bmap::VxColor) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetSpecular, col) + } + fn get_emissive(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetEmissive) + } + fn set_emissive(&mut self, col: bmap::VxColor) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetEmissive, col) + } -pub trait CK3dObject: CK3dEntity {} + fn get_specular_power(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetSpecularPower) + } + fn set_specular_power(&mut self, power: f32) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetSpecularPower, power) + } -pub trait CKLight: CK3dEntity {} + fn get_texture(&self) -> Result>> { + todo!(); + } + fn set_texture(&mut self, texture: Option<&dyn BMTexture>) -> Result<()> { + todo!(); + } -pub trait CKTargetLight: CKLight {} + fn get_texture_border_color(&self) -> Result { + let intermediary = get_copyable_value(self, bmap::BMMaterial_GetTextureBorderColor)?; + Ok(bmap::VxColor::with_dword(intermediary)) + } + fn set_texture_border_color(&mut self, col: bmap::VxColor) -> Result<()> { + let intermediary = col.to_dword(); + set_copyable_value(self, bmap::BMMaterial_SetTextureBorderColor, intermediary) + } -pub trait CKCamera: CK3dEntity {} + fn get_texture_blend_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetTextureBlendMode) + } + fn set_texture_blend_mode(&mut self, data: bmap::VXTEXTURE_BLENDMODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetTextureBlendMode, data) + } + fn get_texture_min_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetTextureMinMode) + } + fn set_texture_min_mode(&mut self, data: bmap::VXTEXTURE_FILTERMODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetTextureMinMode, data) + } + fn get_texture_mag_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetTextureMagMode) + } + fn set_texture_mag_mode(&mut self, data: bmap::VXTEXTURE_FILTERMODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetTextureMagMode, data) + } + fn get_texture_address_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetTextureAddressMode) + } + fn set_texture_address_mode(&mut self, data: bmap::VXTEXTURE_ADDRESSMODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetTextureAddressMode, data) + } + fn get_source_blend(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetSourceBlend) + } + fn set_source_blend(&mut self, data: bmap::VXBLEND_MODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetSourceBlend, data) + } + fn get_dest_blend(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetDestBlend) + } + fn set_dest_blend(&mut self, data: bmap::VXBLEND_MODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetDestBlend, data) + } + fn get_fill_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetFillMode) + } + fn set_fill_mode(&mut self, data: bmap::VXFILL_MODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetFillMode, data) + } + fn get_shade_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetShadeMode) + } + fn set_shade_mode(&mut self, data: bmap::VXSHADE_MODE) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetShadeMode, data) + } -pub trait CKTargetCamera: CKCamera {} + fn get_alpha_test_enabled(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetAlphaTestEnabled) + } + fn set_alpha_test_enabled(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetAlphaTestEnabled, data) + } + fn get_alpha_blend_enabled(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetAlphaBlendEnabled) + } + fn set_alpha_blend_enabled(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetAlphaBlendEnabled, data) + } + fn get_perspective_correction_enabled(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetPerspectiveCorrectionEnabled) + } + fn set_perspective_correction_enabled(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetPerspectiveCorrectionEnabled, data) + } + fn get_z_write_enabled(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetZWriteEnabled) + } + fn set_z_write_enabled(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetZWriteEnabled, data) + } + fn get_two_sided_enabled(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetTwoSidedEnabled) + } + fn set_two_sided_enabled(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetTwoSidedEnabled, data) + } + + fn get_alpha_ref(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetAlphaRef) + } + fn set_alpha_ref(&mut self, data: u8) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetAlphaRef, data) + } + + fn get_alpha_func(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetAlphaFunc) + } + fn set_alpha_func(&mut self, data: bmap::VXCMPFUNC) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetAlphaFunc, data) + } + fn get_z_func(&self) -> Result { + get_copyable_value(self, bmap::BMMaterial_GetZFunc) + } + fn set_z_func(&mut self, data: bmap::VXCMPFUNC) -> Result<()> { + set_copyable_value(self, bmap::BMMaterial_SetZFunc, data) + } +} + +pub trait BMMesh: BMObject { + fn get_lit_mode(&self) -> Result { + get_copyable_value(self, bmap::BMMesh_GetLitMode) + } + fn set_lit_mode(&mut self, data: bmap::VXMESH_LITMODE) -> Result<()> { + set_copyable_value(self, bmap::BMMesh_SetLitMode, data) + } +} + +pub trait BM3dEntity: BMObject { + fn get_visibility(&self) -> Result { + get_copyable_value(self, bmap::BM3dEntity_GetVisibility) + } + fn set_visibility(&mut self, data: bool) -> Result<()> { + set_copyable_value(self, bmap::BM3dEntity_SetVisibility, data) + } +} + +pub trait BM3dObject: BM3dEntity {} + +pub trait BMLight: BM3dEntity { + fn get_type(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetType) + } + fn set_type(&mut self, data: bmap::VXLIGHT_TYPE) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetType, data) + } + + fn get_color(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetColor) + } + fn set_color(&mut self, col: bmap::VxColor) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetColor, col) + } + + fn get_constant_attenuation(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetConstantAttenuation) + } + fn set_constant_attenuation(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetConstantAttenuation, val) + } + fn get_linear_attenuation(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetLinearAttenuation) + } + fn set_linear_attenuation(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetLinearAttenuation, val) + } + fn get_quadratic_attenuation(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetQuadraticAttenuation) + } + fn set_quadratic_attenuation(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetQuadraticAttenuation, val) + } + + fn get_range(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetRange) + } + fn set_range(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetRange, val) + } + + fn get_hot_spot(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetHotSpot) + } + fn set_hot_spot(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetHotSpot, val) + } + fn get_falloff(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetFalloff) + } + fn set_falloff(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetFalloff, val) + } + fn get_falloff_shape(&self) -> Result { + get_copyable_value(self, bmap::BMLight_GetFalloffShape) + } + fn set_falloff_shape(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMLight_SetFalloffShape, val) + } +} + +pub trait BMTargetLight: BMLight {} + +pub trait BMCamera: BM3dEntity { + fn get_projection_type(&self) -> Result { + get_copyable_value(self, bmap::BMCamera_GetProjectionType) + } + fn set_projection_type(&mut self, data: bmap::CK_CAMERA_PROJECTION) -> Result<()> { + set_copyable_value(self, bmap::BMCamera_SetProjectionType, data) + } + + fn get_orthographic_zoom(&self) -> Result { + get_copyable_value(self, bmap::BMCamera_GetOrthographicZoom) + } + fn set_orthographic_zoom(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMCamera_SetOrthographicZoom, val) + } + + fn get_front_plane(&self) -> Result { + get_copyable_value(self, bmap::BMCamera_GetFrontPlane) + } + fn set_front_plane(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMCamera_SetFrontPlane, val) + } + fn get_back_plane(&self) -> Result { + get_copyable_value(self, bmap::BMCamera_GetBackPlane) + } + fn set_back_plane(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMCamera_SetBackPlane, val) + } + fn get_fov(&self) -> Result { + get_copyable_value(self, bmap::BMCamera_GetFov) + } + fn set_fov(&mut self, val: f32) -> Result<()> { + set_copyable_value(self, bmap::BMCamera_SetFov, val) + } + + fn get_aspect_ratio(&self) -> Result<(u32, u32)> { + let mut width = MaybeUninit::::uninit(); + let mut height = MaybeUninit::::uninit(); + bmap_exec!(bmap::BMCamera_GetAspectRatio( + self.get_pointer(), + self.get_ckid(), + arg_out!(width.as_mut_ptr(), CKDWORD), + arg_out!(height.as_mut_ptr(), CKDWORD) + )); + Ok(unsafe { (width.assume_init(), height.assume_init()) }) + } + fn set_aspect_ratio(&self, width: u32, height: u32) -> Result<()> { + bmap_exec!(bmap::BMCamera_SetAspectRatio( + self.get_pointer(), + self.get_ckid(), + arg_in!(width), + arg_in!(height) + )); + Ok(()) + } +} + +pub trait BMTargetCamera: BMCamera {} + +pub trait BMGroup: BMObject {} + +// endregion + +// region: Utility Macros + +macro_rules! libobj_struct { + ($name:ident) => { + #[derive(Debug)] + struct $name<'a, RW> + where + RW: BMFileRW, + { + handle: PBMVOID, + id: CKID, + parent: PhantomData<&'a RW>, + } + }; +} + +macro_rules! libobj_impl_new { + ($name:ident) => { + impl<'a, RW> $name<'a, RW> + where + RW: BMFileRW, + { + fn new(_: &'a RW, handle: PBMVOID, id: CKID) -> Self { + Self { + handle, + id, + parent: PhantomData::<&'a RW>, + } + } + } + }; +} + +macro_rules! libobj_impl_eq_ord_hash { + ($name:ident) => { + impl<'a, RW> PartialEq for $name<'a, RW> + where + RW: BMFileRW, + { + fn eq(&self, other: &Self) -> bool { + self.handle == other.handle && self.id == other.id + } + } + + impl<'a, RW> Eq for $name<'a, RW> where RW: BMFileRW {} + + impl<'a, RW> PartialOrd for $name<'a, RW> + where + RW: BMFileRW, + { + fn partial_cmp(&self, other: &Self) -> Option { + match self.handle.partial_cmp(&other.handle) { + Some(Ordering::Equal) => self.id.partial_cmp(&other.id), + other => other, + } + } + } + + impl<'a, RW> Ord for $name<'a, RW> + where + RW: BMFileRW, + { + fn cmp(&self, other: &Self) -> Ordering { + match self.handle.cmp(&other.handle) { + Ordering::Equal => self.id.cmp(&other.id), + other => other, + } + } + } + + impl<'a, RW> Hash for $name<'a, RW> + where + RW: BMFileRW, + { + fn hash(&self, state: &mut H) { + self.handle.hash(state); + self.id.hash(state); + } + } + }; +} + +macro_rules! libobj_impl_abstract_object { + ($name:ident) => { + impl<'a, RW> AbstractPointer for $name<'a, RW> + where + RW: BMFileRW, + { + unsafe fn get_pointer(&self) -> PBMVOID { + self.handle + } + } + + impl<'a, RW> AbstractObject for $name<'a, RW> + where + RW: BMFileRW, + { + unsafe fn get_ckid(&self) -> CKID { + self.id + } + } + }; +} + +macro_rules! libobj_impl_obj_trait { + ($name:ident, $trait:ident) => { + impl<'a, RW> $trait for $name<'a, RW> where RW: BMFileRW {} + }; +} // endregion // region: Structs -pub struct BMObject {} +libobj_struct!(BMObjectImpl); +libobj_impl_new!(BMObjectImpl); +libobj_impl_eq_ord_hash!(BMObjectImpl); +libobj_impl_abstract_object!(BMObjectImpl); +libobj_impl_obj_trait!(BMObjectImpl, BMObject); -pub struct BMTexture {} -pub struct BMMaterial {} -pub struct BMMesh {} -pub struct BM3dEntity {} -pub struct BM3dObject {} -pub struct BMLight {} -pub struct BMTargetLight {} -pub struct BMCamera {} -pub struct BMTargetCamera {} +libobj_struct!(BMTextureImpl); +libobj_impl_new!(BMTextureImpl); +libobj_impl_eq_ord_hash!(BMTextureImpl); +libobj_impl_abstract_object!(BMTextureImpl); +libobj_impl_obj_trait!(BMTextureImpl, BMObject); +libobj_impl_obj_trait!(BMTextureImpl, BMTexture); + +libobj_struct!(BMMaterialImpl); +libobj_impl_new!(BMMaterialImpl); +libobj_impl_eq_ord_hash!(BMMaterialImpl); +libobj_impl_abstract_object!(BMMaterialImpl); +libobj_impl_obj_trait!(BMMaterialImpl, BMObject); +libobj_impl_obj_trait!(BMMaterialImpl, BMMaterial); + +libobj_struct!(BMMeshImpl); +libobj_impl_new!(BMMeshImpl); +libobj_impl_eq_ord_hash!(BMMeshImpl); +libobj_impl_abstract_object!(BMMeshImpl); +libobj_impl_obj_trait!(BMMeshImpl, BMObject); +libobj_impl_obj_trait!(BMMeshImpl, BMMesh); + +libobj_struct!(BM3dEntityImpl); +libobj_impl_new!(BM3dEntityImpl); +libobj_impl_eq_ord_hash!(BM3dEntityImpl); +libobj_impl_abstract_object!(BM3dEntityImpl); +libobj_impl_obj_trait!(BM3dEntityImpl, BMObject); +libobj_impl_obj_trait!(BM3dEntityImpl, BM3dEntity); + +libobj_struct!(BM3dObjectImpl); +libobj_impl_new!(BM3dObjectImpl); +libobj_impl_eq_ord_hash!(BM3dObjectImpl); +libobj_impl_abstract_object!(BM3dObjectImpl); +libobj_impl_obj_trait!(BM3dObjectImpl, BMObject); +libobj_impl_obj_trait!(BM3dObjectImpl, BM3dEntity); +libobj_impl_obj_trait!(BM3dObjectImpl, BM3dObject); + +libobj_struct!(BMLightImpl); +libobj_impl_new!(BMLightImpl); +libobj_impl_eq_ord_hash!(BMLightImpl); +libobj_impl_abstract_object!(BMLightImpl); +libobj_impl_obj_trait!(BMLightImpl, BMObject); +libobj_impl_obj_trait!(BMLightImpl, BM3dEntity); +libobj_impl_obj_trait!(BMLightImpl, BMLight); + +libobj_struct!(BMTargetLightImpl); +libobj_impl_new!(BMTargetLightImpl); +libobj_impl_eq_ord_hash!(BMTargetLightImpl); +libobj_impl_abstract_object!(BMTargetLightImpl); +libobj_impl_obj_trait!(BMTargetLightImpl, BMObject); +libobj_impl_obj_trait!(BMTargetLightImpl, BM3dEntity); +libobj_impl_obj_trait!(BMTargetLightImpl, BMLight); +libobj_impl_obj_trait!(BMTargetLightImpl, BMTargetLight); + +libobj_struct!(BMCameraImpl); +libobj_impl_new!(BMCameraImpl); +libobj_impl_eq_ord_hash!(BMCameraImpl); +libobj_impl_abstract_object!(BMCameraImpl); +libobj_impl_obj_trait!(BMCameraImpl, BMObject); +libobj_impl_obj_trait!(BMCameraImpl, BM3dEntity); +libobj_impl_obj_trait!(BMCameraImpl, BMCamera); + +libobj_struct!(BMTargetCameraImpl); +libobj_impl_new!(BMTargetCameraImpl); +libobj_impl_eq_ord_hash!(BMTargetCameraImpl); +libobj_impl_abstract_object!(BMTargetCameraImpl); +libobj_impl_obj_trait!(BMTargetCameraImpl, BMObject); +libobj_impl_obj_trait!(BMTargetCameraImpl, BM3dEntity); +libobj_impl_obj_trait!(BMTargetCameraImpl, BMCamera); +libobj_impl_obj_trait!(BMTargetCameraImpl, BMTargetCamera); + +libobj_struct!(BMGroupImpl); +libobj_impl_new!(BMGroupImpl); +libobj_impl_eq_ord_hash!(BMGroupImpl); +libobj_impl_abstract_object!(BMGroupImpl); +libobj_impl_obj_trait!(BMGroupImpl, BMObject); +libobj_impl_obj_trait!(BMGroupImpl, BMGroup); // endregion @@ -408,7 +950,7 @@ pub struct BMTargetCamera {} pub struct BMMeshTrans<'a> { handle: PBMVOID, - phantom: PhantomData<&'a BMapGuard> + phantom: PhantomData<&'a BMapGuard>, } impl<'a> AbstractPointer for BMMeshTrans<'a> { diff --git a/Assets/BMapBindings/bmap-rs/src/lib.rs b/Assets/BMapBindings/bmap-rs/src/lib.rs index 37e1119..4e07014 100644 --- a/Assets/BMapBindings/bmap-rs/src/lib.rs +++ b/Assets/BMapBindings/bmap-rs/src/lib.rs @@ -1,5 +1,5 @@ //! The Rust binding to BMap. pub mod virtools_types; pub mod bmap; -pub mod marshaler; +pub(crate) mod marshaler; pub mod bmap_wrapper; diff --git a/Assets/BMapBindings/bmap-rs/src/marshaler.rs b/Assets/BMapBindings/bmap-rs/src/marshaler.rs index 4e6c0a7..b047308 100644 --- a/Assets/BMapBindings/bmap-rs/src/marshaler.rs +++ b/Assets/BMapBindings/bmap-rs/src/marshaler.rs @@ -75,7 +75,6 @@ where } pub struct BMStringArray { - #[allow(dead_code)] array_items: Vec, array_body: Vec, } @@ -103,7 +102,11 @@ impl BMStringArray { Ok(Self { array_items, array_body }) } - pub unsafe fn as_raw(&mut self) -> PCKSTRING { + pub fn len(&self) -> usize { + self.array_items.len() + } + + pub unsafe fn as_raw(&self) -> PCKSTRING { self.array_body.as_ptr() as PCKSTRING } } diff --git a/Assets/BMapBindings/bmap-rs/src/virtools_types.rs b/Assets/BMapBindings/bmap-rs/src/virtools_types.rs index 3cdf363..1dddf57 100644 --- a/Assets/BMapBindings/bmap-rs/src/virtools_types.rs +++ b/Assets/BMapBindings/bmap-rs/src/virtools_types.rs @@ -2,7 +2,7 @@ // region: Structures -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct VxVector2 { @@ -20,7 +20,7 @@ impl VxVector2 { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct VxVector3 { @@ -39,7 +39,7 @@ impl VxVector3 { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct VxColor { @@ -80,18 +80,19 @@ impl VxColor { self.a = (val & 0xFF) as f32 / 255.0; } - pub fn to_dword(&mut self) -> u32 { - // Regulate self first - self.regulate(); + pub fn to_dword(&self) -> u32 { + // Make a copy and regulate self first + let mut copied = self.clone(); + copied.regulate(); // Build result let mut rv = 0; - rv |= (self.b * 255.0) as u32; + rv |= (copied.b * 255.0) as u32; rv <<= 8; - rv |= (self.g * 255.0) as u32; + rv |= (copied.g * 255.0) as u32; rv <<= 8; - rv |= (self.r * 255.0) as u32; + rv |= (copied.r * 255.0) as u32; rv <<= 8; - rv |= (self.a * 255.0) as u32; + rv |= (copied.a * 255.0) as u32; return rv; } @@ -107,7 +108,7 @@ impl VxColor { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct VxMatrix { @@ -135,7 +136,7 @@ impl VxMatrix { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct CKFaceIndices { @@ -154,7 +155,7 @@ impl CKFaceIndices { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[repr(C)] #[repr(packed(4))] pub struct CKShortFaceIndices { diff --git a/Assets/BMapBindings/pybmap/src/pybmap/bmap_wrapper.py b/Assets/BMapBindings/pybmap/src/pybmap/bmap_wrapper.py index 15123e6..204895d 100644 --- a/Assets/BMapBindings/pybmap/src/pybmap/bmap_wrapper.py +++ b/Assets/BMapBindings/pybmap/src/pybmap/bmap_wrapper.py @@ -564,7 +564,7 @@ class BMTargetLight(BMLight): class BMCamera(BM3dEntity): def get_projection_type(self) -> virtools_types.CK_CAMERA_PROJECTION: return self._get_enum_value(virtools_types.CK_CAMERA_PROJECTION, bmap.BMCamera_GetProjectionType) - def set_type(self, data_: virtools_types.CK_CAMERA_PROJECTION) -> None: + def set_projection_type(self, data_: virtools_types.CK_CAMERA_PROJECTION) -> None: self._set_enum_value(bmap.BMCamera_SetProjectionType, data_) def get_orthographic_zoom(self) -> float: