Skip to main content

whiteout/
m3.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Fernando Sahmkow
3// AUTOGENERATED by tools/codegen/emit_rust.py — do not edit.
4// Regenerate via:  python -m tools.codegen.codegen m3 --backend rust
5
6#![allow(clippy::too_many_arguments)]
7
8// Which of these a module needs depends on its shapes; the modules that
9// have no span accessors would otherwise trip the unused-import lint.
10#[allow(unused_imports)]
11use crate::support::{BorrowedSlice, Bytes};
12
13/// Vertex format flags determining vertex buffer layout
14///
15/// These bitmask flags control the per-vertex data layout in the U8__ vertex blob. The vertex stride is: 24 + (hasColor ? 4 : 0) + (numUVs * 4) + 4 bytes.
16/// Bit flags. Combine with `|`, test with [`VertexFormatFlag::contains`].
17#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
18pub struct VertexFormatFlag(pub i32);
19
20impl VertexFormatFlag {
21    pub const NONE: Self = Self(0);
22    /// Bit 10 (1-based): Has vertex color (adds 4 bytes)
23    pub const VERTEX_COLOR: Self = Self(512);
24    /// Bit 18 (1-based): Has UV layer 1 (adds 4 bytes)
25    pub const UV_1: Self = Self(131072);
26    /// Bit 19 (1-based): Has UV layer 2 (adds 4 bytes)
27    pub const UV_2: Self = Self(262144);
28    /// Bit 20 (1-based): Has UV layer 3 (adds 4 bytes)
29    pub const UV_3: Self = Self(524288);
30    /// Bit 21 (1-based): Has UV layer 4 (adds 4 bytes)
31    pub const UV_4: Self = Self(1048576);
32    /// Bit 30 (1-based): Has UV layer 5 (adds 4 bytes)
33    pub const UV_5: Self = Self(536870912);
34
35    #[inline]
36    pub const fn contains(self, other: Self) -> bool {
37        (self.0 & other.0) == other.0
38    }
39
40    #[inline]
41    pub const fn is_empty(self) -> bool {
42        self.0 == 0
43    }
44}
45
46impl core::ops::BitOr for VertexFormatFlag {
47    type Output = Self;
48    #[inline]
49    fn bitor(self, rhs: Self) -> Self {
50        Self(self.0 | rhs.0)
51    }
52}
53
54impl core::ops::BitAnd for VertexFormatFlag {
55    type Output = Self;
56    #[inline]
57    fn bitand(self, rhs: Self) -> Self {
58        Self(self.0 & rhs.0)
59    }
60}
61
62impl core::ops::Not for VertexFormatFlag {
63    type Output = Self;
64    #[inline]
65    fn not(self) -> Self {
66        Self(!self.0)
67    }
68}
69
70impl core::fmt::Debug for VertexFormatFlag {
71    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
72        write!(f, "VertexFormatFlag({:#x})", self.0)
73    }
74}
75
76/// Identifies which material array a MATM entry references
77#[repr(i32)]
78#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
79pub enum MaterialType {
80    /// MAT_ — Standard material
81    Standard = 1,
82    /// DIS_ — Displacement material
83    Displacement = 2,
84    /// CMP_ — Composite material
85    Composite = 3,
86    /// TER_ — Terrain material
87    Terrain = 4,
88    /// VOL_ — Volume material
89    Volume = 5,
90    /// VON_ — Volume noise material
91    VolumeNoise = 6,
92    /// CREP — Creep material
93    Creep = 7,
94    /// HAI_ — Hair material (defunct)
95    Hair = 8,
96    /// STBM — Splat terrain bake material
97    SplatTerrainBake = 9,
98    /// REF_ — Reflection material
99    Reflection = 10,
100    /// LFLR — Lens flare material
101    LensFlare = 11,
102    /// MADD — Data-driven material; what every other type is converted into at load
103    DataDriven = 12,
104}
105
106impl TryFrom<i32> for MaterialType {
107    type Error = crate::Error;
108    fn try_from(v: i32) -> Result<Self, crate::Error> {
109        match v {
110            1 => Ok(MaterialType::Standard),
111            2 => Ok(MaterialType::Displacement),
112            3 => Ok(MaterialType::Composite),
113            4 => Ok(MaterialType::Terrain),
114            5 => Ok(MaterialType::Volume),
115            6 => Ok(MaterialType::VolumeNoise),
116            7 => Ok(MaterialType::Creep),
117            8 => Ok(MaterialType::Hair),
118            9 => Ok(MaterialType::SplatTerrainBake),
119            10 => Ok(MaterialType::Reflection),
120            11 => Ok(MaterialType::LensFlare),
121            12 => Ok(MaterialType::DataDriven),
122            other => Err(crate::Error::UnknownEnum {
123                name: "MaterialType",
124                value: other,
125            }),
126        }
127    }
128}
129
130/// Light source type (LITE)
131#[repr(i32)]
132#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
133pub enum LightType {
134    /// Point light (omnidirectional)
135    Omni = 0,
136    /// Spot light (cone)
137    Spot = 1,
138    /// Directional light (infinite distance)
139    Directional = 2,
140}
141
142impl TryFrom<i32> for LightType {
143    type Error = crate::Error;
144    fn try_from(v: i32) -> Result<Self, crate::Error> {
145        match v {
146            0 => Ok(LightType::Omni),
147            1 => Ok(LightType::Spot),
148            2 => Ok(LightType::Directional),
149            other => Err(crate::Error::UnknownEnum {
150                name: "LightType",
151                value: other,
152            }),
153        }
154    }
155}
156
157/// Physics collision shape type (PHSH)
158#[repr(i32)]
159#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
160pub enum PhysicsShapeType {
161    /// Box (half-extents in shapeDimensions)
162    Box = 0,
163    /// Sphere (radius in shapeDimensions.x)
164    Sphere = 1,
165    /// Capsule (radius + height)
166    Capsule = 2,
167    /// Cylinder (radius + height)
168    Cylinder = 3,
169    /// Convex hull (vertex/half-edge data)
170    ConvexHull = 4,
171    /// Triangle mesh (face/edge/normal data)
172    Mesh = 5,
173}
174
175impl TryFrom<i32> for PhysicsShapeType {
176    type Error = crate::Error;
177    fn try_from(v: i32) -> Result<Self, crate::Error> {
178        match v {
179            0 => Ok(PhysicsShapeType::Box),
180            1 => Ok(PhysicsShapeType::Sphere),
181            2 => Ok(PhysicsShapeType::Capsule),
182            3 => Ok(PhysicsShapeType::Cylinder),
183            4 => Ok(PhysicsShapeType::ConvexHull),
184            5 => Ok(PhysicsShapeType::Mesh),
185            other => Err(crate::Error::UnknownEnum {
186                name: "PhysicsShapeType",
187                value: other,
188            }),
189        }
190    }
191}
192
193/// Hit-test shape type (SSGS / ATVL), same semantics as PhysicsShapeType but u32
194#[repr(i32)]
195#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
196pub enum HitTestShapeType {
197    Box = 0,
198    Sphere = 1,
199    Capsule = 2,
200    Cylinder = 3,
201    Mesh = 4,
202}
203
204impl TryFrom<i32> for HitTestShapeType {
205    type Error = crate::Error;
206    fn try_from(v: i32) -> Result<Self, crate::Error> {
207        match v {
208            0 => Ok(HitTestShapeType::Box),
209            1 => Ok(HitTestShapeType::Sphere),
210            2 => Ok(HitTestShapeType::Capsule),
211            3 => Ok(HitTestShapeType::Cylinder),
212            4 => Ok(HitTestShapeType::Mesh),
213            other => Err(crate::Error::UnknownEnum {
214                name: "HitTestShapeType",
215                value: other,
216            }),
217        }
218    }
219}
220
221/// Particle / ribbon emitter shape (PAR_ / RIB_)
222#[repr(i32)]
223#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
224pub enum EmitterShape {
225    /// Emit from a single point
226    Point = 0,
227    /// Emit from a rectangular plane
228    Plane = 1,
229    /// Emit from a sphere surface/volume
230    Sphere = 2,
231    /// Emit from a box volume
232    Box = 3,
233    /// Emit from a cylinder
234    Cylinder = 4,
235    /// Emit from a disc
236    Disc = 5,
237    /// Emit from a spline path, splineLineData
238    Spline = 6,
239    /// Emit from mesh surface, mesh region indices in shapeRegions
240    Mesh = 7,
241}
242
243impl TryFrom<i32> for EmitterShape {
244    type Error = crate::Error;
245    fn try_from(v: i32) -> Result<Self, crate::Error> {
246        match v {
247            0 => Ok(EmitterShape::Point),
248            1 => Ok(EmitterShape::Plane),
249            2 => Ok(EmitterShape::Sphere),
250            3 => Ok(EmitterShape::Box),
251            4 => Ok(EmitterShape::Cylinder),
252            5 => Ok(EmitterShape::Disc),
253            6 => Ok(EmitterShape::Spline),
254            7 => Ok(EmitterShape::Mesh),
255            other => Err(crate::Error::UnknownEnum {
256                name: "EmitterShape",
257                value: other,
258            }),
259        }
260    }
261}
262
263/// Particle visual / billboard type (maps to b_iInstanceType in Particle.fx)
264#[repr(i32)]
265#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
266pub enum ParticleInstanceType {
267    /// Camera-facing billboard quad
268    Billboard = 0,
269    /// Velocity-stretched quad
270    Tail = 1,
271    /// Quad oriented along instantaneous velocity
272    FaceTravelDir = 2,
273    /// Quad oriented along a fixed world direction
274    FaceWorldDir = 3,
275    /// Billboard locked to a single rotation axis
276    SingleAxis = 4,
277    /// Quad projected onto terrain normal
278    TerrainOriented = 5,
279    /// Terrain-oriented + velocity-stretched
280    TerrainDirOriented = 6,
281    /// Quad uses the emitter bone's orientation
282    EmitterOriented = 7,
283    /// Quad oriented by physics simulation
284    PhysicsOriented = 8,
285    /// Stretch between spawn origin and current position
286    Pinned = 9,
287    /// Like Tail but offset by one tail-length
288    Trail = 10,
289}
290
291impl TryFrom<i32> for ParticleInstanceType {
292    type Error = crate::Error;
293    fn try_from(v: i32) -> Result<Self, crate::Error> {
294        match v {
295            0 => Ok(ParticleInstanceType::Billboard),
296            1 => Ok(ParticleInstanceType::Tail),
297            2 => Ok(ParticleInstanceType::FaceTravelDir),
298            3 => Ok(ParticleInstanceType::FaceWorldDir),
299            4 => Ok(ParticleInstanceType::SingleAxis),
300            5 => Ok(ParticleInstanceType::TerrainOriented),
301            6 => Ok(ParticleInstanceType::TerrainDirOriented),
302            7 => Ok(ParticleInstanceType::EmitterOriented),
303            8 => Ok(ParticleInstanceType::PhysicsOriented),
304            9 => Ok(ParticleInstanceType::Pinned),
305            10 => Ok(ParticleInstanceType::Trail),
306            other => Err(crate::Error::UnknownEnum {
307                name: "ParticleInstanceType",
308                value: other,
309            }),
310        }
311    }
312}
313
314/// Force influence type (FOR_)
315#[repr(i32)]
316#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
317pub enum ForceType {
318    /// Radial force (outward from center)
319    Radial = 0,
320    /// Wind force (directional)
321    Wind = 1,
322    /// Explosion force (impulse)
323    Explosion = 2,
324}
325
326impl TryFrom<i32> for ForceType {
327    type Error = crate::Error;
328    fn try_from(v: i32) -> Result<Self, crate::Error> {
329        match v {
330            0 => Ok(ForceType::Radial),
331            1 => Ok(ForceType::Wind),
332            2 => Ok(ForceType::Explosion),
333            other => Err(crate::Error::UnknownEnum {
334                name: "ForceType",
335                value: other,
336            }),
337        }
338    }
339}
340
341/// Influence volume shape for a force (FOR_)
342#[repr(i32)]
343#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
344pub enum ForceShape {
345    /// Spherical influence volume
346    Sphere = 0,
347    /// Cylindrical influence volume
348    Cylinder = 1,
349    /// Box influence volume
350    Box = 2,
351    /// Hemispherical influence volume
352    Hemisphere = 3,
353}
354
355impl TryFrom<i32> for ForceShape {
356    type Error = crate::Error;
357    fn try_from(v: i32) -> Result<Self, crate::Error> {
358        match v {
359            0 => Ok(ForceShape::Sphere),
360            1 => Ok(ForceShape::Cylinder),
361            2 => Ok(ForceShape::Box),
362            3 => Ok(ForceShape::Hemisphere),
363            other => Err(crate::Error::UnknownEnum {
364                name: "ForceShape",
365                value: other,
366            }),
367        }
368    }
369}
370
371/// Ribbon cross-section type (maps to b_iRibbonType in Ribbon.fx)
372#[repr(i32)]
373#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
374pub enum RibbonType {
375    /// Camera-facing ribbon strip
376    Billboard = 0,
377    /// Flat/planar ribbon strip
378    Planar = 1,
379    /// Cylindrical cross-section
380    Cylinder = 2,
381    /// Star-shaped cross-section
382    Star = 3,
383}
384
385impl TryFrom<i32> for RibbonType {
386    type Error = crate::Error;
387    fn try_from(v: i32) -> Result<Self, crate::Error> {
388        match v {
389            0 => Ok(RibbonType::Billboard),
390            1 => Ok(RibbonType::Planar),
391            2 => Ok(RibbonType::Cylinder),
392            3 => Ok(RibbonType::Star),
393            other => Err(crate::Error::UnknownEnum {
394                name: "RibbonType",
395                value: other,
396            }),
397        }
398    }
399}
400
401/// Projector / decal projection type (PROJ)
402#[repr(i32)]
403#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
404pub enum ProjectionType {
405    /// Orthographic projection
406    Orthographic = 0,
407    /// Perspective projection
408    Perspective = 1,
409}
410
411impl TryFrom<i32> for ProjectionType {
412    type Error = crate::Error;
413    fn try_from(v: i32) -> Result<Self, crate::Error> {
414        match v {
415            0 => Ok(ProjectionType::Orthographic),
416            1 => Ok(ProjectionType::Perspective),
417            other => Err(crate::Error::UnknownEnum {
418                name: "ProjectionType",
419                value: other,
420            }),
421        }
422    }
423}
424
425/// Volume shape type (VOL_ / VON_)
426#[repr(i32)]
427#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
428pub enum VolumeType {
429    Box = 0,
430    Sphere = 1,
431    Capsule = 2,
432}
433
434impl TryFrom<i32> for VolumeType {
435    type Error = crate::Error;
436    fn try_from(v: i32) -> Result<Self, crate::Error> {
437        match v {
438            0 => Ok(VolumeType::Box),
439            1 => Ok(VolumeType::Sphere),
440            2 => Ok(VolumeType::Capsule),
441            other => Err(crate::Error::UnknownEnum {
442                name: "VolumeType",
443                value: other,
444            }),
445        }
446    }
447}
448
449/// Interpolation mode for particle/ribbon smoothing curves
450///
451/// Maps to RibbonParticleCommon.fx constants. Used by PAR_ colorSmoothing / sizeSmoothing / rotationSmoothing and RIB_ sizeSmoothing / colorSmoothing.
452#[repr(i32)]
453#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
454pub enum InterpolationMode {
455    /// ITERPOLATION_LINEAR
456    Linear = 0,
457    /// ITERPOLATION_LINEAR_SMOOTH
458    LinearSmooth = 1,
459    /// ITERPOLATION_BEZIER
460    Bezier = 2,
461    /// ITERPOLATION_LINEAR_WITH_HOLD
462    LinearWithHold = 3,
463    /// ITERPOLATION_BEZIER_WITH_HOLD
464    BezierWithHold = 4,
465}
466
467impl TryFrom<i32> for InterpolationMode {
468    type Error = crate::Error;
469    fn try_from(v: i32) -> Result<Self, crate::Error> {
470        match v {
471            0 => Ok(InterpolationMode::Linear),
472            1 => Ok(InterpolationMode::LinearSmooth),
473            2 => Ok(InterpolationMode::Bezier),
474            3 => Ok(InterpolationMode::LinearWithHold),
475            4 => Ok(InterpolationMode::BezierWithHold),
476            other => Err(crate::Error::UnknownEnum {
477                name: "InterpolationMode",
478                value: other,
479            }),
480        }
481    }
482}
483
484/// Model-wide flags (MODL.flags) — tangents, FOW, instancing, etc.
485/// Bit flags. Combine with `|`, test with [`ModelFlag::contains`].
486#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
487pub struct ModelFlag(pub i32);
488
489impl ModelFlag {
490    pub const NONE: Self = Self(0);
491    /// Tangents computed
492    pub const TANGENTS: Self = Self(1);
493    /// Bone transforms fixed
494    pub const BONES_FIXED: Self = Self(2);
495    /// UV densities computed
496    pub const UV_DENSITIES_COMPUTED: Self = Self(4);
497    /// Uses relative bounds
498    pub const RELATIVE_BOUNDS: Self = Self(8);
499    /// Section bounds fixed
500    pub const SECTION_BOUNDS_FIXED: Self = Self(16);
501    /// Track sets computed
502    pub const TRACK_SETS_COMPUTED: Self = Self(32);
503    /// Track collection sorted
504    pub const TRACK_COLLECTION_SORTED: Self = Self(64);
505    /// Model accepts splats
506    pub const ACCEPTS_SPLATS: Self = Self(128);
507    /// Animated base flag valid
508    pub const TRACK_ANIMATED_BASE_FLAG_VALID: Self = Self(2048);
509    /// File marked dirty
510    pub const FILE_DIRTY: Self = Self(4096);
511    /// FOW: do not tint
512    pub const FOW_DO_NOT_USE_TINT: Self = Self(16384);
513    /// Uses instanced vertex buffer
514    pub const INSTANCED_VB: Self = Self(32768);
515    /// Force sampled FOW
516    pub const FORCE_SAMPLED_FOW: Self = Self(65536);
517    /// Instanced model
518    pub const INSTANCED_MODEL: Self = Self(131072);
519    /// Never use FOW
520    pub const NEVER_USE_FOW: Self = Self(262144);
521    /// Bone animated flags solved
522    pub const BONE_ANIMATED_FLAG_SOLVED: Self = Self(524288);
523    /// Allow local light shadows
524    pub const ALLOW_LOCAL_LIGHT_SHADOWS: Self = Self(1048576);
525    /// Avoid sampled FOW
526    pub const AVOID_SAMPLED_FOW: Self = Self(2097152);
527
528    #[inline]
529    pub const fn contains(self, other: Self) -> bool {
530        (self.0 & other.0) == other.0
531    }
532
533    #[inline]
534    pub const fn is_empty(self) -> bool {
535        self.0 == 0
536    }
537}
538
539impl core::ops::BitOr for ModelFlag {
540    type Output = Self;
541    #[inline]
542    fn bitor(self, rhs: Self) -> Self {
543        Self(self.0 | rhs.0)
544    }
545}
546
547impl core::ops::BitAnd for ModelFlag {
548    type Output = Self;
549    #[inline]
550    fn bitand(self, rhs: Self) -> Self {
551        Self(self.0 & rhs.0)
552    }
553}
554
555impl core::ops::Not for ModelFlag {
556    type Output = Self;
557    #[inline]
558    fn not(self) -> Self {
559        Self(!self.0)
560    }
561}
562
563impl core::fmt::Debug for ModelFlag {
564    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
565        write!(f, "ModelFlag({:#x})", self.0)
566    }
567}
568
569/// Sequence playback flags (SEQS.flags)
570/// Bit flags. Combine with `|`, test with [`SequenceFlag::contains`].
571#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
572pub struct SequenceFlag(pub i32);
573
574impl SequenceFlag {
575    pub const NONE: Self = Self(0);
576    /// Sequence does not loop
577    pub const NOT_LOOPING: Self = Self(1);
578    /// Always plays globally
579    pub const ALWAYS_GLOBAL: Self = Self(2);
580    /// Unknown
581    pub const UNKNOWN_0X_4: Self = Self(4);
582    /// Global playback in editor
583    pub const GLOBAL_IN_PREVIEWER: Self = Self(8);
584
585    #[inline]
586    pub const fn contains(self, other: Self) -> bool {
587        (self.0 & other.0) == other.0
588    }
589
590    #[inline]
591    pub const fn is_empty(self) -> bool {
592        self.0 == 0
593    }
594}
595
596impl core::ops::BitOr for SequenceFlag {
597    type Output = Self;
598    #[inline]
599    fn bitor(self, rhs: Self) -> Self {
600        Self(self.0 | rhs.0)
601    }
602}
603
604impl core::ops::BitAnd for SequenceFlag {
605    type Output = Self;
606    #[inline]
607    fn bitand(self, rhs: Self) -> Self {
608        Self(self.0 & rhs.0)
609    }
610}
611
612impl core::ops::Not for SequenceFlag {
613    type Output = Self;
614    #[inline]
615    fn not(self) -> Self {
616        Self(!self.0)
617    }
618}
619
620impl core::fmt::Debug for SequenceFlag {
621    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
622        write!(f, "SequenceFlag({:#x})", self.0)
623    }
624}
625
626/// BBSC.billboardType — which axes a billboarded bone may turn about.
627///
628/// Recovered from `CBBSolver::ApplyBillboard` (SC2 `0x1027F1F30`). The aim direction points *away* from the eye, so "aims at" below means the named axis lies along it and its negation points back at the camera.
629#[repr(i32)]
630#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
631pub enum BillboardType {
632    /// Turns about world X; local +Y aims along the direction
633    LockWorldX = 0,
634    /// Turns about world Y; local +X aims (Y is the locked one)
635    LockWorldY = 1,
636    /// Turns about world Z; local +Y aims. The upright poster
637    LockWorldZ = 2,
638    /// Turns about the bone's own world X; local +Z faces the camera
639    LockBoneX = 3,
640    /// Parsed and instantiated, never applied
641    Disabled = 4,
642    /// The bone's own world Y becomes local Z; local +Y faces the camera
643    LockBoneY = 5,
644    /// Free; local +Y aims, and the camera's up axis sets the roll
645    Full = 6,
646}
647
648impl TryFrom<i32> for BillboardType {
649    type Error = crate::Error;
650    fn try_from(v: i32) -> Result<Self, crate::Error> {
651        match v {
652            0 => Ok(BillboardType::LockWorldX),
653            1 => Ok(BillboardType::LockWorldY),
654            2 => Ok(BillboardType::LockWorldZ),
655            3 => Ok(BillboardType::LockBoneX),
656            4 => Ok(BillboardType::Disabled),
657            5 => Ok(BillboardType::LockBoneY),
658            6 => Ok(BillboardType::Full),
659            other => Err(crate::Error::UnknownEnum {
660                name: "BillboardType",
661                value: other,
662            }),
663        }
664    }
665}
666
667/// Bone flags (BONE.flags) — inheritance, IK, skin
668/// Bit flags. Combine with `|`, test with [`BoneFlag::contains`].
669#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
670pub struct BoneFlag(pub i32);
671
672impl BoneFlag {
673    pub const NONE: Self = Self(0);
674    /// Inherit parent translation
675    pub const INHERIT_TRANSLATION: Self = Self(1);
676    /// Inherit parent scale
677    pub const INHERIT_SCALE: Self = Self(2);
678    /// Inherit parent rotation
679    pub const INHERIT_ROTATION: Self = Self(4);
680    /// Unused: set on no bone in 51469 corpus files
681    pub const BILLBOARD_1: Self = Self(16);
682    /// Unused: likewise. Billboarding comes from BBSC
683    pub const BILLBOARD_2: Self = Self(64);
684    /// 2D projection mode
685    pub const PROJECT_2D: Self = Self(256);
686    /// Has animation data
687    pub const ANIMATED: Self = Self(512);
688    /// IK bone
689    pub const INVERSE_KINEMATICS: Self = Self(1024);
690    /// Affects mesh skin
691    pub const SKINNED: Self = Self(2048);
692    /// Real bone (not helper)
693    pub const REAL: Self = Self(8192);
694    /// Primary batch bone
695    pub const BATCH_1: Self = Self(16384);
696    /// Descendant of batch1 bone
697    pub const BATCH_2: Self = Self(32768);
698
699    #[inline]
700    pub const fn contains(self, other: Self) -> bool {
701        (self.0 & other.0) == other.0
702    }
703
704    #[inline]
705    pub const fn is_empty(self) -> bool {
706        self.0 == 0
707    }
708}
709
710impl core::ops::BitOr for BoneFlag {
711    type Output = Self;
712    #[inline]
713    fn bitor(self, rhs: Self) -> Self {
714        Self(self.0 | rhs.0)
715    }
716}
717
718impl core::ops::BitAnd for BoneFlag {
719    type Output = Self;
720    #[inline]
721    fn bitand(self, rhs: Self) -> Self {
722        Self(self.0 & rhs.0)
723    }
724}
725
726impl core::ops::Not for BoneFlag {
727    type Output = Self;
728    #[inline]
729    fn not(self) -> Self {
730        Self(!self.0)
731    }
732}
733
734impl core::fmt::Debug for BoneFlag {
735    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
736        write!(f, "BoneFlag({:#x})", self.0)
737    }
738}
739
740/// Region flags (REGN.flags, v4+)
741/// Bit flags. Combine with `|`, test with [`RegionFlag::contains`].
742#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
743pub struct RegionFlag(pub i32);
744
745impl RegionFlag {
746    pub const NONE: Self = Self(0);
747    /// Region is hidden
748    pub const HIDDEN: Self = Self(1);
749    /// Placeholder region
750    pub const PLACEHOLDER: Self = Self(2);
751    /// Cloth-simulated
752    pub const CLOTH_SIMULATED: Self = Self(4);
753    /// Cloth-influenced
754    pub const CLOTH_INFLUENCED: Self = Self(8);
755
756    #[inline]
757    pub const fn contains(self, other: Self) -> bool {
758        (self.0 & other.0) == other.0
759    }
760
761    #[inline]
762    pub const fn is_empty(self) -> bool {
763        self.0 == 0
764    }
765}
766
767impl core::ops::BitOr for RegionFlag {
768    type Output = Self;
769    #[inline]
770    fn bitor(self, rhs: Self) -> Self {
771        Self(self.0 | rhs.0)
772    }
773}
774
775impl core::ops::BitAnd for RegionFlag {
776    type Output = Self;
777    #[inline]
778    fn bitand(self, rhs: Self) -> Self {
779        Self(self.0 & rhs.0)
780    }
781}
782
783impl core::ops::Not for RegionFlag {
784    type Output = Self;
785    #[inline]
786    fn not(self) -> Self {
787        Self(!self.0)
788    }
789}
790
791impl core::fmt::Debug for RegionFlag {
792    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
793        write!(f, "RegionFlag({:#x})", self.0)
794    }
795}
796
797/// Additional standard-material flags (MAT_.additionalFlags)
798/// Bit flags. Combine with `|`, test with [`MaterialAdditionalFlag::contains`].
799#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
800pub struct MaterialAdditionalFlag(pub i32);
801
802impl MaterialAdditionalFlag {
803    pub const NONE: Self = Self(0);
804    /// Enable depth blend falloff
805    pub const DEPTH_BLEND_FALLOFF: Self = Self(1);
806    /// Uses vertex color
807    pub const VERTEX_COLOR: Self = Self(4);
808    /// Uses vertex alpha
809    pub const VERTEX_ALPHA: Self = Self(8);
810
811    #[inline]
812    pub const fn contains(self, other: Self) -> bool {
813        (self.0 & other.0) == other.0
814    }
815
816    #[inline]
817    pub const fn is_empty(self) -> bool {
818        self.0 == 0
819    }
820}
821
822impl core::ops::BitOr for MaterialAdditionalFlag {
823    type Output = Self;
824    #[inline]
825    fn bitor(self, rhs: Self) -> Self {
826        Self(self.0 | rhs.0)
827    }
828}
829
830impl core::ops::BitAnd for MaterialAdditionalFlag {
831    type Output = Self;
832    #[inline]
833    fn bitand(self, rhs: Self) -> Self {
834        Self(self.0 & rhs.0)
835    }
836}
837
838impl core::ops::Not for MaterialAdditionalFlag {
839    type Output = Self;
840    #[inline]
841    fn not(self) -> Self {
842        Self(!self.0)
843    }
844}
845
846impl core::fmt::Debug for MaterialAdditionalFlag {
847    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
848        write!(f, "MaterialAdditionalFlag({:#x})", self.0)
849    }
850}
851
852/// Standard material rendering flags (MAT_.flags)
853/// Bit flags. Combine with `|`, test with [`MaterialFlag::contains`].
854#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
855pub struct MaterialFlag(pub i32);
856
857impl MaterialFlag {
858    pub const NONE: Self = Self(0);
859    /// Enable vertex color
860    pub const VERTEX_COLOR: Self = Self(1);
861    /// Enable vertex alpha
862    pub const VERTEX_ALPHA: Self = Self(2);
863    /// Blend the normal-blend layers by factors 0-3 (v19+)
864    pub const NORMAL_BLEND: Self = Self(4);
865    /// Two-sided rendering
866    pub const TWO_SIDED: Self = Self(8);
867    /// Unlit / unshaded
868    pub const UNSHADED: Self = Self(16);
869    /// Does not cast shadows
870    pub const NO_SHADOWS_CAST: Self = Self(32);
871    /// Excluded from hit testing
872    pub const NO_HIT_TEST: Self = Self(64);
873    /// Does not receive shadows
874    pub const NO_SHADOWS_RECEIVE: Self = Self(128);
875    /// Z-fill pre-pass
876    pub const DEPTH_PREPASS: Self = Self(256);
877    /// Terrain HDR mode
878    pub const TERRAIN_HDR: Self = Self(512);
879    /// Simulate roughness
880    pub const SIMULATE_ROUGHNESS: Self = Self(2048);
881    /// Pixel forward lighting
882    pub const PIXEL_FORWARD_LIGHTING: Self = Self(4096);
883    /// Not affected by fog
884    pub const UNFOGGED: Self = Self(8192);
885    /// Transparent shadows
886    pub const TRANSPARENT_SHADOWS: Self = Self(16384);
887    /// Decal lighting mode
888    pub const DECAL_LIGHTING: Self = Self(32768);
889    /// Transparent depth effects
890    pub const TRANSPARENT_DEPTH_EFFECTS: Self = Self(65536);
891    /// Transparent local lights
892    pub const TRANSPARENT_LOCAL_LIGHTS: Self = Self(131072);
893    /// Disable soft blending
894    pub const DISABLE_SOFT: Self = Self(262144);
895    /// Double Lambert shading
896    pub const DOUBLE_LAMBERT: Self = Self(524288);
897    /// Hair layer sorting
898    pub const HAIR_LAYER_SORTING: Self = Self(1048576);
899    /// Accept splat projections
900    pub const ACCEPT_SPLATS: Self = Self(2097152);
901    /// Decal low LOD required
902    pub const DECAL_LOW_REQUIRED: Self = Self(4194304);
903    /// Emissive low LOD required
904    pub const EMIS_LOW_REQUIRED: Self = Self(8388608);
905    /// Specular low LOD required
906    pub const SPEC_LOW_REQUIRED: Self = Self(16777216);
907    /// Accept splats only
908    pub const ACCEPT_SPLATS_ONLY: Self = Self(33554432);
909    /// Background object
910    pub const BACKGROUND_OBJECT: Self = Self(67108864);
911    /// Second normal blend, by factors 4-7 (v19+)
912    pub const NORMAL_BLEND_2: Self = Self(134217728);
913    /// Depth prepass low LOD
914    pub const DEPTH_PREPASS_LOW_REQUIRED: Self = Self(268435456);
915    /// Disable highlighting
916    pub const NO_HIGHLIGHTING: Self = Self(536870912);
917    /// Clamp output
918    pub const CLAMP_OUTPUT: Self = Self(1073741824);
919    /// Geometry visible (v17+)
920    pub const GEOMETRY_VISIBLE: Self = Self(-2147483648);
921
922    #[inline]
923    pub const fn contains(self, other: Self) -> bool {
924        (self.0 & other.0) == other.0
925    }
926
927    #[inline]
928    pub const fn is_empty(self) -> bool {
929        self.0 == 0
930    }
931}
932
933impl core::ops::BitOr for MaterialFlag {
934    type Output = Self;
935    #[inline]
936    fn bitor(self, rhs: Self) -> Self {
937        Self(self.0 | rhs.0)
938    }
939}
940
941impl core::ops::BitAnd for MaterialFlag {
942    type Output = Self;
943    #[inline]
944    fn bitand(self, rhs: Self) -> Self {
945        Self(self.0 & rhs.0)
946    }
947}
948
949impl core::ops::Not for MaterialFlag {
950    type Output = Self;
951    #[inline]
952    fn not(self) -> Self {
953        Self(!self.0)
954    }
955}
956
957impl core::fmt::Debug for MaterialFlag {
958    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
959        write!(f, "MaterialFlag({:#x})", self.0)
960    }
961}
962
963/// Texture layer flags (LAYR.flags)
964/// Bit flags. Combine with `|`, test with [`TextureLayerFlag::contains`].
965#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
966pub struct TextureLayerFlag(pub i32);
967
968impl TextureLayerFlag {
969    pub const NONE: Self = Self(0);
970    /// Wrap texture in U
971    pub const UV_WRAP_X: Self = Self(4);
972    /// Wrap texture in V
973    pub const UV_WRAP_Y: Self = Self(8);
974    /// Invert color
975    pub const COLOR_INVERT: Self = Self(16);
976    /// Clamp to `[0,1]`
977    pub const COLOR_CLAMP: Self = Self(32);
978    /// Additive blending
979    pub const COLOR_ADD: Self = Self(64);
980    /// Multiplicative blending
981    pub const COLOR_MULTIPLY: Self = Self(128);
982    /// Flipbook UVs for particles
983    pub const PARTICLE_UV_FLIPBOOK: Self = Self(256);
984    /// Video texture
985    pub const VIDEO: Self = Self(512);
986    /// Solid color (no texture)
987    pub const COLOR: Self = Self(1024);
988    /// Override texture source
989    pub const REPLACE_TEXTURE_SOURCE: Self = Self(2048);
990    /// Fresnel-based UV transform
991    pub const FRESNEL_TRANSFORM: Self = Self(16384);
992    /// Normalize fresnel values
993    pub const FRESNEL_NORMALIZE: Self = Self(32768);
994
995    #[inline]
996    pub const fn contains(self, other: Self) -> bool {
997        (self.0 & other.0) == other.0
998    }
999
1000    #[inline]
1001    pub const fn is_empty(self) -> bool {
1002        self.0 == 0
1003    }
1004}
1005
1006impl core::ops::BitOr for TextureLayerFlag {
1007    type Output = Self;
1008    #[inline]
1009    fn bitor(self, rhs: Self) -> Self {
1010        Self(self.0 | rhs.0)
1011    }
1012}
1013
1014impl core::ops::BitAnd for TextureLayerFlag {
1015    type Output = Self;
1016    #[inline]
1017    fn bitand(self, rhs: Self) -> Self {
1018        Self(self.0 & rhs.0)
1019    }
1020}
1021
1022impl core::ops::Not for TextureLayerFlag {
1023    type Output = Self;
1024    #[inline]
1025    fn not(self) -> Self {
1026        Self(!self.0)
1027    }
1028}
1029
1030impl core::fmt::Debug for TextureLayerFlag {
1031    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1032        write!(f, "TextureLayerFlag({:#x})", self.0)
1033    }
1034}
1035
1036/// Blend mode for materials (MAT_.blendMode, VOL_.blendMode)
1037#[repr(i32)]
1038#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1039pub enum BlendMode {
1040    /// Fully opaque
1041    Opaque = 0,
1042    /// Standard alpha blending
1043    AlphaBlend = 1,
1044    /// Additive blending
1045    Add = 2,
1046    /// Alpha-modulated additive
1047    AlphaAdd = 3,
1048    /// Multiplicative blending
1049    Mod = 4,
1050    /// Double multiplicative
1051    Mod2x = 5,
1052}
1053
1054impl TryFrom<i32> for BlendMode {
1055    type Error = crate::Error;
1056    fn try_from(v: i32) -> Result<Self, crate::Error> {
1057        match v {
1058            0 => Ok(BlendMode::Opaque),
1059            1 => Ok(BlendMode::AlphaBlend),
1060            2 => Ok(BlendMode::Add),
1061            3 => Ok(BlendMode::AlphaAdd),
1062            4 => Ok(BlendMode::Mod),
1063            5 => Ok(BlendMode::Mod2x),
1064            other => Err(crate::Error::UnknownEnum {
1065                name: "BlendMode",
1066                value: other,
1067            }),
1068        }
1069    }
1070}
1071
1072/// Material rendering class (MAT_.materialClass)
1073#[repr(i32)]
1074#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1075pub enum MaterialClass {
1076    /// Unit/character material
1077    Unit = 0,
1078    /// Building/structure material
1079    Building = 1,
1080    /// Doodad/prop material
1081    Doodad = 2,
1082    /// Special effect material
1083    SpecialFX = 3,
1084}
1085
1086impl TryFrom<i32> for MaterialClass {
1087    type Error = crate::Error;
1088    fn try_from(v: i32) -> Result<Self, crate::Error> {
1089        match v {
1090            0 => Ok(MaterialClass::Unit),
1091            1 => Ok(MaterialClass::Building),
1092            2 => Ok(MaterialClass::Doodad),
1093            3 => Ok(MaterialClass::SpecialFX),
1094            other => Err(crate::Error::UnknownEnum {
1095                name: "MaterialClass",
1096                value: other,
1097            }),
1098        }
1099    }
1100}
1101
1102/// Layer blend operation (MAT_.layerBlendMode, emissiveBlendMode)
1103#[repr(i32)]
1104#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1105pub enum LayerBlendOp {
1106    /// Multiply: base * layer
1107    Mod = 0,
1108    /// Double multiply: base * layer * 2
1109    Mod2x = 1,
1110    /// Add: base + layer
1111    Add = 2,
1112    /// Linear interpolate by layer alpha
1113    Lerp = 3,
1114    /// Team color emissive add
1115    TeamColorEmissiveAdd = 4,
1116    /// Team color diffuse add
1117    TeamColorDiffuseAdd = 5,
1118    /// Add ignoring alpha channel
1119    AddNoAlpha = 6,
1120}
1121
1122impl TryFrom<i32> for LayerBlendOp {
1123    type Error = crate::Error;
1124    fn try_from(v: i32) -> Result<Self, crate::Error> {
1125        match v {
1126            0 => Ok(LayerBlendOp::Mod),
1127            1 => Ok(LayerBlendOp::Mod2x),
1128            2 => Ok(LayerBlendOp::Add),
1129            3 => Ok(LayerBlendOp::Lerp),
1130            4 => Ok(LayerBlendOp::TeamColorEmissiveAdd),
1131            5 => Ok(LayerBlendOp::TeamColorDiffuseAdd),
1132            6 => Ok(LayerBlendOp::AddNoAlpha),
1133            other => Err(crate::Error::UnknownEnum {
1134                name: "LayerBlendOp",
1135                value: other,
1136            }),
1137        }
1138    }
1139}
1140
1141/// UV mapping source / projection mode (LAYR.uvMapping)
1142#[repr(i32)]
1143#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1144pub enum UVMappingMode {
1145    /// UV coordinate set 0
1146    ExplicitUV0 = 0,
1147    /// UV coordinate set 1
1148    ExplicitUV1 = 1,
1149    /// Cubic environment reflection
1150    ReflectCubicEnvio = 2,
1151    /// Spherical environment reflection
1152    ReflectSphericalEnvio = 3,
1153    /// Planar local UVs (Z plane)
1154    PlanarLocalZ = 4,
1155    /// Planar world UVs (Z plane)
1156    PlanarWorldZ = 5,
1157    /// Particle flipbook UVs
1158    ParticleFlipbook = 6,
1159    /// Cubic environment mapping
1160    CubicEnvio = 7,
1161    /// Spherical environment mapping
1162    SphericalEnvio = 8,
1163    /// UV coordinate set 2
1164    ExplicitUV2 = 9,
1165    /// UV coordinate set 3
1166    ExplicitUV3 = 10,
1167    /// Planar local UVs (X plane)
1168    PlanarLocalX = 11,
1169    /// Planar local UVs (Y plane)
1170    PlanarLocalY = 12,
1171    /// Planar world UVs (X plane)
1172    PlanarWorldX = 13,
1173    /// Planar world UVs (Y plane)
1174    PlanarWorldY = 14,
1175    /// Screen-space UVs
1176    ScreenSpace = 15,
1177    /// Tri-planar blending (local space)
1178    TriPlanarLocal = 16,
1179    /// Tri-planar blending (world space)
1180    TriPlanarWorld = 17,
1181    /// Tri-planar world with local Z
1182    TriPlanarWorldLocalZ = 18,
1183}
1184
1185impl TryFrom<i32> for UVMappingMode {
1186    type Error = crate::Error;
1187    fn try_from(v: i32) -> Result<Self, crate::Error> {
1188        match v {
1189            0 => Ok(UVMappingMode::ExplicitUV0),
1190            1 => Ok(UVMappingMode::ExplicitUV1),
1191            2 => Ok(UVMappingMode::ReflectCubicEnvio),
1192            3 => Ok(UVMappingMode::ReflectSphericalEnvio),
1193            4 => Ok(UVMappingMode::PlanarLocalZ),
1194            5 => Ok(UVMappingMode::PlanarWorldZ),
1195            6 => Ok(UVMappingMode::ParticleFlipbook),
1196            7 => Ok(UVMappingMode::CubicEnvio),
1197            8 => Ok(UVMappingMode::SphericalEnvio),
1198            9 => Ok(UVMappingMode::ExplicitUV2),
1199            10 => Ok(UVMappingMode::ExplicitUV3),
1200            11 => Ok(UVMappingMode::PlanarLocalX),
1201            12 => Ok(UVMappingMode::PlanarLocalY),
1202            13 => Ok(UVMappingMode::PlanarWorldX),
1203            14 => Ok(UVMappingMode::PlanarWorldY),
1204            15 => Ok(UVMappingMode::ScreenSpace),
1205            16 => Ok(UVMappingMode::TriPlanarLocal),
1206            17 => Ok(UVMappingMode::TriPlanarWorld),
1207            18 => Ok(UVMappingMode::TriPlanarWorldLocalZ),
1208            other => Err(crate::Error::UnknownEnum {
1209                name: "UVMappingMode",
1210                value: other,
1211            }),
1212        }
1213    }
1214}
1215
1216/// Color channel selection (LAYR.colorType)
1217#[repr(i32)]
1218#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1219pub enum ColorChannelSelect {
1220    /// Use RGB channels (alpha forced to 1)
1221    RGB = 0,
1222    /// Use all RGBA channels
1223    RGBA = 1,
1224    /// Use alpha channel only (splat to all)
1225    Alpha = 2,
1226    /// Use red channel only (splat to all)
1227    Red = 3,
1228    /// Use green channel only (splat to all)
1229    Green = 4,
1230    /// Use blue channel only (splat to all)
1231    Blue = 5,
1232}
1233
1234impl TryFrom<i32> for ColorChannelSelect {
1235    type Error = crate::Error;
1236    fn try_from(v: i32) -> Result<Self, crate::Error> {
1237        match v {
1238            0 => Ok(ColorChannelSelect::RGB),
1239            1 => Ok(ColorChannelSelect::RGBA),
1240            2 => Ok(ColorChannelSelect::Alpha),
1241            3 => Ok(ColorChannelSelect::Red),
1242            4 => Ok(ColorChannelSelect::Green),
1243            5 => Ok(ColorChannelSelect::Blue),
1244            other => Err(crate::Error::UnknownEnum {
1245                name: "ColorChannelSelect",
1246                value: other,
1247            }),
1248        }
1249    }
1250}
1251
1252/// Specular mode (MAT_.specularMode)
1253#[repr(i32)]
1254#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1255pub enum SpecularMode {
1256    /// Use RGB channels for specularity
1257    RGB = 0,
1258    /// Use alpha channel only
1259    AlphaOnly = 1,
1260}
1261
1262impl TryFrom<i32> for SpecularMode {
1263    type Error = crate::Error;
1264    fn try_from(v: i32) -> Result<Self, crate::Error> {
1265        match v {
1266            0 => Ok(SpecularMode::RGB),
1267            1 => Ok(SpecularMode::AlphaOnly),
1268            other => Err(crate::Error::UnknownEnum {
1269                name: "SpecularMode",
1270                value: other,
1271            }),
1272        }
1273    }
1274}
1275
1276/// Fresnel effect mode (LAYR.fresnelMode)
1277#[repr(i32)]
1278#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1279pub enum FresnelMode {
1280    /// No fresnel effect
1281    None = 0,
1282    /// Standard fresnel (edge glow)
1283    Standard = 1,
1284    /// Inverted fresnel (center glow)
1285    Inverted = 2,
1286}
1287
1288impl TryFrom<i32> for FresnelMode {
1289    type Error = crate::Error;
1290    fn try_from(v: i32) -> Result<Self, crate::Error> {
1291        match v {
1292            0 => Ok(FresnelMode::None),
1293            1 => Ok(FresnelMode::Standard),
1294            2 => Ok(FresnelMode::Inverted),
1295            other => Err(crate::Error::UnknownEnum {
1296                name: "FresnelMode",
1297                value: other,
1298            }),
1299        }
1300    }
1301}
1302
1303/// Reflection material flags (REF_.flags, v2+)
1304/// Bit flags. Combine with `|`, test with [`ReflectionMaterialFlag::contains`].
1305#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1306pub struct ReflectionMaterialFlag(pub i32);
1307
1308impl ReflectionMaterialFlag {
1309    pub const NONE: Self = Self(0);
1310    /// Use reflection map
1311    pub const USE_REFLECTION_MAP: Self = Self(1);
1312    /// Use displacement map
1313    pub const USE_DISPLACEMENT_MAP: Self = Self(2);
1314    /// Render in transparent pass
1315    pub const RENDER_IN_TRANSPARENT_PASS: Self = Self(4);
1316    /// Enable blurring
1317    pub const BLURRING: Self = Self(8);
1318    /// Use blur map
1319    pub const USE_BLUR_MAP: Self = Self(16);
1320
1321    #[inline]
1322    pub const fn contains(self, other: Self) -> bool {
1323        (self.0 & other.0) == other.0
1324    }
1325
1326    #[inline]
1327    pub const fn is_empty(self) -> bool {
1328        self.0 == 0
1329    }
1330}
1331
1332impl core::ops::BitOr for ReflectionMaterialFlag {
1333    type Output = Self;
1334    #[inline]
1335    fn bitor(self, rhs: Self) -> Self {
1336        Self(self.0 | rhs.0)
1337    }
1338}
1339
1340impl core::ops::BitAnd for ReflectionMaterialFlag {
1341    type Output = Self;
1342    #[inline]
1343    fn bitand(self, rhs: Self) -> Self {
1344        Self(self.0 & rhs.0)
1345    }
1346}
1347
1348impl core::ops::Not for ReflectionMaterialFlag {
1349    type Output = Self;
1350    #[inline]
1351    fn not(self) -> Self {
1352        Self(!self.0)
1353    }
1354}
1355
1356impl core::fmt::Debug for ReflectionMaterialFlag {
1357    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1358        write!(f, "ReflectionMaterialFlag({:#x})", self.0)
1359    }
1360}
1361
1362/// Volume noise material flags (VON_.flags)
1363#[repr(i32)]
1364#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1365pub enum VolumeNoiseMaterialFlag {
1366    None = 0,
1367    /// Draw in separate pass after transparency
1368    DrawAfterTransparency = 1,
1369}
1370
1371impl TryFrom<i32> for VolumeNoiseMaterialFlag {
1372    type Error = crate::Error;
1373    fn try_from(v: i32) -> Result<Self, crate::Error> {
1374        match v {
1375            0 => Ok(VolumeNoiseMaterialFlag::None),
1376            1 => Ok(VolumeNoiseMaterialFlag::DrawAfterTransparency),
1377            other => Err(crate::Error::UnknownEnum {
1378                name: "VolumeNoiseMaterialFlag",
1379                value: other,
1380            }),
1381        }
1382    }
1383}
1384
1385/// Volume density falloff type (VOL_.falloffType, VON_.falloffType)
1386#[repr(i32)]
1387#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1388pub enum VolumeFalloffType {
1389    /// Linear density falloff
1390    Linear = 0,
1391    /// Exponential density falloff
1392    Exponential = 1,
1393}
1394
1395impl TryFrom<i32> for VolumeFalloffType {
1396    type Error = crate::Error;
1397    fn try_from(v: i32) -> Result<Self, crate::Error> {
1398        match v {
1399            0 => Ok(VolumeFalloffType::Linear),
1400            1 => Ok(VolumeFalloffType::Exponential),
1401            other => Err(crate::Error::UnknownEnum {
1402                name: "VolumeFalloffType",
1403                value: other,
1404            }),
1405        }
1406    }
1407}
1408
1409/// Volume noise camera position mode (VON_.drawTransparency)
1410#[repr(i32)]
1411#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1412pub enum VolumeNoiseCameraMode {
1413    /// Camera is outside the volume
1414    Outside = 0,
1415    /// Camera is inside the volume
1416    Inside = 1,
1417}
1418
1419impl TryFrom<i32> for VolumeNoiseCameraMode {
1420    type Error = crate::Error;
1421    fn try_from(v: i32) -> Result<Self, crate::Error> {
1422        match v {
1423            0 => Ok(VolumeNoiseCameraMode::Outside),
1424            1 => Ok(VolumeNoiseCameraMode::Inside),
1425            other => Err(crate::Error::UnknownEnum {
1426                name: "VolumeNoiseCameraMode",
1427                value: other,
1428            }),
1429        }
1430    }
1431}
1432
1433/// Light flags (LITE.flags)
1434/// Bit flags. Combine with `|`, test with [`LightFlag::contains`].
1435#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1436pub struct LightFlag(pub i32);
1437
1438impl LightFlag {
1439    pub const NONE: Self = Self(0);
1440    /// Casts shadows
1441    pub const SHADOWS: Self = Self(1);
1442    /// Specular component
1443    pub const SPECULAR: Self = Self(2);
1444    /// AO influence
1445    pub const AMBIENT_OCCLUSION: Self = Self(4);
1446    /// Lights opaque objects
1447    pub const LIGHT_OPAQUE: Self = Self(8);
1448    /// Lights transparent objects
1449    pub const LIGHT_TRANSPARENT: Self = Self(16);
1450    /// Uses team color
1451    pub const TEAM_COLOR: Self = Self(32);
1452
1453    #[inline]
1454    pub const fn contains(self, other: Self) -> bool {
1455        (self.0 & other.0) == other.0
1456    }
1457
1458    #[inline]
1459    pub const fn is_empty(self) -> bool {
1460        self.0 == 0
1461    }
1462}
1463
1464impl core::ops::BitOr for LightFlag {
1465    type Output = Self;
1466    #[inline]
1467    fn bitor(self, rhs: Self) -> Self {
1468        Self(self.0 | rhs.0)
1469    }
1470}
1471
1472impl core::ops::BitAnd for LightFlag {
1473    type Output = Self;
1474    #[inline]
1475    fn bitand(self, rhs: Self) -> Self {
1476        Self(self.0 & rhs.0)
1477    }
1478}
1479
1480impl core::ops::Not for LightFlag {
1481    type Output = Self;
1482    #[inline]
1483    fn not(self) -> Self {
1484        Self(!self.0)
1485    }
1486}
1487
1488impl core::fmt::Debug for LightFlag {
1489    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1490        write!(f, "LightFlag({:#x})", self.0)
1491    }
1492}
1493
1494/// Particle emitter main flags (PAR_.flags)
1495/// Bit flags. Combine with `|`, test with [`ParticleFlag::contains`].
1496#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1497pub struct ParticleFlag(pub i32);
1498
1499impl ParticleFlag {
1500    pub const NONE: Self = Self(0);
1501    /// Sort by distance
1502    pub const SORT: Self = Self(1);
1503    /// Collide with terrain
1504    pub const COLLIDE_TERRAIN: Self = Self(2);
1505    /// Collide with objects
1506    pub const COLLIDE_OBJECTS: Self = Self(4);
1507    /// Emit on collision
1508    pub const COLLIDE_EMIT: Self = Self(8);
1509    /// Emit from shape cutout
1510    pub const EMIT_SHAPE_CUTOUT: Self = Self(16);
1511    /// Inherit emission parameters
1512    pub const INHERIT_EMIT_PARAMS: Self = Self(32);
1513    /// Inherit parent velocity
1514    pub const INHERIT_PARENT_VELOCITY: Self = Self(64);
1515    /// Sort by height
1516    pub const SORT_HEIGHT: Self = Self(128);
1517    /// Reverse sort order
1518    pub const SORT_REVERSE: Self = Self(256);
1519    /// Legacy rotation smoothing
1520    pub const OLD_ROTATION_SMOOTH: Self = Self(512);
1521    /// Legacy rotation bezier
1522    pub const OLD_ROTATION_BEZIER: Self = Self(1024);
1523    /// Legacy size smoothing
1524    pub const OLD_SIZE_SMOOTH: Self = Self(2048);
1525    /// Legacy size bezier
1526    pub const OLD_SIZE_BEZIER: Self = Self(4096);
1527    /// Legacy color smoothing
1528    pub const OLD_COLOR_SMOOTH: Self = Self(8192);
1529    /// Legacy color bezier
1530    pub const OLD_COLOR_BEZIER: Self = Self(16384);
1531    /// Lit particles → lit pixel-shader variant
1532    pub const LIT_PARTS: Self = Self(32768);
1533    /// Random flipbook start → shader b_randomFlipBookStart
1534    pub const RANDOM_FLIPBOOK_START: Self = Self(65536);
1535    /// Multiply gravity by mass
1536    pub const MULTIPLY_GRAVITY_BY_MASS: Self = Self(131072);
1537    /// Clamp tail length → shader b_clampedTailLength (Tail/Trail, not Pinned)
1538    pub const CLAMP_TAIL_LENGTH: Self = Self(262144);
1539    /// Spawn trailing particles (also forces b_useProceduralPosition)
1540    pub const SPAWN_TRAILING_PARTICLES: Self = Self(524288);
1541    /// Fix tail length on creation → shader b_fixedTailLength
1542    pub const FIX_TAIL_LENGTH_ON_CREATION: Self = Self(1048576);
1543    /// Use vertex alpha
1544    pub const USE_VERTEX_ALPHA: Self = Self(2097152);
1545    /// Use model particles (also forces b_useProceduralPosition)
1546    pub const MODEL_PARTICLES: Self = Self(4194304);
1547    /// Swap Y/Z on model particles
1548    pub const SWAP_YZ_ON_MODEL_PARTICLES: Self = Self(8388608);
1549    /// Scale time by parent
1550    pub const SCALE_TIME_BY_PARENT: Self = Self(16777216);
1551    /// Use local time
1552    pub const USE_LOCAL_TIME: Self = Self(33554432);
1553    /// Simulate on initialization
1554    pub const SIMULATE_INIT: Self = Self(67108864);
1555    /// Copy emitter
1556    pub const COPY: Self = Self(134217728);
1557    /// Part of the b_useProceduralPosition trigger mask (0x10480003)
1558    pub const REQUIRES_GPU_SIM: Self = Self(268435456);
1559    /// Toggles a particle shader permutation (role TBD)
1560    pub const SHADER_PERM_30: Self = Self(1073741824);
1561    /// Forces GPU procedural-position path (b_useProceduralPosition)
1562    pub const FORCE_PROCEDURAL_POSITION: Self = Self(-2147483648);
1563
1564    #[inline]
1565    pub const fn contains(self, other: Self) -> bool {
1566        (self.0 & other.0) == other.0
1567    }
1568
1569    #[inline]
1570    pub const fn is_empty(self) -> bool {
1571        self.0 == 0
1572    }
1573}
1574
1575impl core::ops::BitOr for ParticleFlag {
1576    type Output = Self;
1577    #[inline]
1578    fn bitor(self, rhs: Self) -> Self {
1579        Self(self.0 | rhs.0)
1580    }
1581}
1582
1583impl core::ops::BitAnd for ParticleFlag {
1584    type Output = Self;
1585    #[inline]
1586    fn bitand(self, rhs: Self) -> Self {
1587        Self(self.0 & rhs.0)
1588    }
1589}
1590
1591impl core::ops::Not for ParticleFlag {
1592    type Output = Self;
1593    #[inline]
1594    fn not(self) -> Self {
1595        Self(!self.0)
1596    }
1597}
1598
1599impl core::fmt::Debug for ParticleFlag {
1600    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1601        write!(f, "ParticleFlag({:#x})", self.0)
1602    }
1603}
1604
1605/// Particle emitter additional flags (PAR_.additionalFlags, v17+)
1606/// Bit flags. Combine with `|`, test with [`ParticleAdditionalFlag::contains`].
1607#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1608pub struct ParticleAdditionalFlag(pub i32);
1609
1610impl ParticleAdditionalFlag {
1611    pub const NONE: Self = Self(0);
1612    /// Randomize emission speed
1613    pub const EMIT_SPEED_RANDOMIZE: Self = Self(1);
1614    /// Randomize lifespan
1615    pub const LIFESPAN_RANDOMIZE: Self = Self(2);
1616    /// Randomize mass
1617    pub const MASS_RANDOMIZE: Self = Self(4);
1618    /// World-space coordinates
1619    pub const WORLD_SPACE: Self = Self(8);
1620
1621    #[inline]
1622    pub const fn contains(self, other: Self) -> bool {
1623        (self.0 & other.0) == other.0
1624    }
1625
1626    #[inline]
1627    pub const fn is_empty(self) -> bool {
1628        self.0 == 0
1629    }
1630}
1631
1632impl core::ops::BitOr for ParticleAdditionalFlag {
1633    type Output = Self;
1634    #[inline]
1635    fn bitor(self, rhs: Self) -> Self {
1636        Self(self.0 | rhs.0)
1637    }
1638}
1639
1640impl core::ops::BitAnd for ParticleAdditionalFlag {
1641    type Output = Self;
1642    #[inline]
1643    fn bitand(self, rhs: Self) -> Self {
1644        Self(self.0 & rhs.0)
1645    }
1646}
1647
1648impl core::ops::Not for ParticleAdditionalFlag {
1649    type Output = Self;
1650    #[inline]
1651    fn not(self) -> Self {
1652        Self(!self.0)
1653    }
1654}
1655
1656impl core::fmt::Debug for ParticleAdditionalFlag {
1657    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1658        write!(f, "ParticleAdditionalFlag({:#x})", self.0)
1659    }
1660}
1661
1662/// Particle rotation flags (PAR_.rotationFlags, v18+)
1663/// Bit flags. Combine with `|`, test with [`ParticleRotationFlag::contains`].
1664#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1665pub struct ParticleRotationFlag(pub i32);
1666
1667impl ParticleRotationFlag {
1668    pub const NONE: Self = Self(0);
1669    /// Relative rotation; the SC2 upgrade sets it from rotationRandomEnable (v≤18)
1670    pub const RELATIVE: Self = Self(2);
1671    /// Always set
1672    pub const ALWAYS_SET: Self = Self(4);
1673    /// Force-set by the SC2 version upgrade for all v≤20 emitters (role TBD)
1674    pub const UNKNOWN_6: Self = Self(64);
1675    /// Set by the SC2 upgrade for remapped Billboard model particles (role TBD)
1676    pub const UNKNOWN_7: Self = Self(128);
1677
1678    #[inline]
1679    pub const fn contains(self, other: Self) -> bool {
1680        (self.0 & other.0) == other.0
1681    }
1682
1683    #[inline]
1684    pub const fn is_empty(self) -> bool {
1685        self.0 == 0
1686    }
1687}
1688
1689impl core::ops::BitOr for ParticleRotationFlag {
1690    type Output = Self;
1691    #[inline]
1692    fn bitor(self, rhs: Self) -> Self {
1693        Self(self.0 | rhs.0)
1694    }
1695}
1696
1697impl core::ops::BitAnd for ParticleRotationFlag {
1698    type Output = Self;
1699    #[inline]
1700    fn bitand(self, rhs: Self) -> Self {
1701        Self(self.0 & rhs.0)
1702    }
1703}
1704
1705impl core::ops::Not for ParticleRotationFlag {
1706    type Output = Self;
1707    #[inline]
1708    fn not(self) -> Self {
1709        Self(!self.0)
1710    }
1711}
1712
1713impl core::fmt::Debug for ParticleRotationFlag {
1714    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1715        write!(f, "ParticleRotationFlag({:#x})", self.0)
1716    }
1717}
1718
1719/// Ribbon emitter main flags (RIB_.flags)
1720/// Bit flags. Combine with `|`, test with [`RibbonFlag::contains`].
1721#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1722pub struct RibbonFlag(pub i32);
1723
1724impl RibbonFlag {
1725    pub const NONE: Self = Self(0);
1726    /// Collide with terrain
1727    pub const COLLIDE_TERRAIN: Self = Self(2);
1728    /// Collide with objects
1729    pub const COLLIDE_OBJECTS: Self = Self(4);
1730    /// Fade edges
1731    pub const EDGE_FALLOFF: Self = Self(8);
1732    /// Inherit parent velocity
1733    pub const INHERIT_PARENT_VELOCITY: Self = Self(16);
1734    /// Smooth size
1735    pub const SMOOTH_SIZE: Self = Self(32);
1736    /// Bezier smooth size
1737    pub const BEZIER_SMOOTH_SIZE: Self = Self(64);
1738    /// Use vertex alpha
1739    pub const USE_VERTEX_ALPHA: Self = Self(128);
1740    /// Scale time by parent
1741    pub const SCALE_TIME_BY_PARENT: Self = Self(256);
1742    /// Force CPU simulation
1743    pub const FORCE_CPU_SIM: Self = Self(512);
1744    /// Use local time
1745    pub const LOCAL_TIME: Self = Self(1024);
1746    /// Simulate on init
1747    pub const SIMULATE_INIT: Self = Self(2048);
1748    /// Use length and time
1749    pub const USE_LENGTH_AND_TIME: Self = Self(4096);
1750    /// Accurate GPU tangents
1751    pub const ACCURATE_GPU_TANGENTS: Self = Self(8192);
1752    /// Derive yaw from speed
1753    pub const YAW_FROM_SPEED: Self = Self(16384);
1754    /// Use locator node
1755    pub const USE_LOCATOR: Self = Self(32768);
1756
1757    #[inline]
1758    pub const fn contains(self, other: Self) -> bool {
1759        (self.0 & other.0) == other.0
1760    }
1761
1762    #[inline]
1763    pub const fn is_empty(self) -> bool {
1764        self.0 == 0
1765    }
1766}
1767
1768impl core::ops::BitOr for RibbonFlag {
1769    type Output = Self;
1770    #[inline]
1771    fn bitor(self, rhs: Self) -> Self {
1772        Self(self.0 | rhs.0)
1773    }
1774}
1775
1776impl core::ops::BitAnd for RibbonFlag {
1777    type Output = Self;
1778    #[inline]
1779    fn bitand(self, rhs: Self) -> Self {
1780        Self(self.0 & rhs.0)
1781    }
1782}
1783
1784impl core::ops::Not for RibbonFlag {
1785    type Output = Self;
1786    #[inline]
1787    fn not(self) -> Self {
1788        Self(!self.0)
1789    }
1790}
1791
1792impl core::fmt::Debug for RibbonFlag {
1793    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1794        write!(f, "RibbonFlag({:#x})", self.0)
1795    }
1796}
1797
1798/// Ribbon emitter additional flags (RIB_.flags2, v8+)
1799/// Bit flags. Combine with `|`, test with [`RibbonAdditionalFlag::contains`].
1800#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1801pub struct RibbonAdditionalFlag(pub i32);
1802
1803impl RibbonAdditionalFlag {
1804    pub const NONE: Self = Self(0);
1805    /// Randomize emission speed
1806    pub const SPEED_RANDOMIZE: Self = Self(1);
1807    /// Randomize lifespan
1808    pub const LIFESPAN_RANDOMIZE: Self = Self(2);
1809    /// Randomize mass
1810    pub const MASS_RANDOMIZE: Self = Self(4);
1811    /// World-space coordinates
1812    pub const WORLD_SPACE: Self = Self(8);
1813
1814    #[inline]
1815    pub const fn contains(self, other: Self) -> bool {
1816        (self.0 & other.0) == other.0
1817    }
1818
1819    #[inline]
1820    pub const fn is_empty(self) -> bool {
1821        self.0 == 0
1822    }
1823}
1824
1825impl core::ops::BitOr for RibbonAdditionalFlag {
1826    type Output = Self;
1827    #[inline]
1828    fn bitor(self, rhs: Self) -> Self {
1829        Self(self.0 | rhs.0)
1830    }
1831}
1832
1833impl core::ops::BitAnd for RibbonAdditionalFlag {
1834    type Output = Self;
1835    #[inline]
1836    fn bitand(self, rhs: Self) -> Self {
1837        Self(self.0 & rhs.0)
1838    }
1839}
1840
1841impl core::ops::Not for RibbonAdditionalFlag {
1842    type Output = Self;
1843    #[inline]
1844    fn not(self) -> Self {
1845        Self(!self.0)
1846    }
1847}
1848
1849impl core::fmt::Debug for RibbonAdditionalFlag {
1850    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1851        write!(f, "RibbonAdditionalFlag({:#x})", self.0)
1852    }
1853}
1854
1855/// Projector flags (PROJ.flags)
1856/// Bit flags. Combine with `|`, test with [`ProjectorFlag::contains`].
1857#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1858pub struct ProjectorFlag(pub i32);
1859
1860impl ProjectorFlag {
1861    pub const NONE: Self = Self(0);
1862    /// Static position
1863    pub const STATIC: Self = Self(1);
1864    /// Unknown
1865    pub const UNKNOWN_FLAG_0X_2: Self = Self(2);
1866    /// Unknown
1867    pub const UNKNOWN_FLAG_0X_4: Self = Self(4);
1868    /// Unknown
1869    pub const UNKNOWN_FLAG_0X_8: Self = Self(8);
1870
1871    #[inline]
1872    pub const fn contains(self, other: Self) -> bool {
1873        (self.0 & other.0) == other.0
1874    }
1875
1876    #[inline]
1877    pub const fn is_empty(self) -> bool {
1878        self.0 == 0
1879    }
1880}
1881
1882impl core::ops::BitOr for ProjectorFlag {
1883    type Output = Self;
1884    #[inline]
1885    fn bitor(self, rhs: Self) -> Self {
1886        Self(self.0 | rhs.0)
1887    }
1888}
1889
1890impl core::ops::BitAnd for ProjectorFlag {
1891    type Output = Self;
1892    #[inline]
1893    fn bitand(self, rhs: Self) -> Self {
1894        Self(self.0 & rhs.0)
1895    }
1896}
1897
1898impl core::ops::Not for ProjectorFlag {
1899    type Output = Self;
1900    #[inline]
1901    fn not(self) -> Self {
1902        Self(!self.0)
1903    }
1904}
1905
1906impl core::fmt::Debug for ProjectorFlag {
1907    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1908        write!(f, "ProjectorFlag({:#x})", self.0)
1909    }
1910}
1911
1912/// Force flags (FOR_.flags)
1913/// Bit flags. Combine with `|`, test with [`ForceFlag::contains`].
1914#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1915pub struct ForceFlag(pub i32);
1916
1917impl ForceFlag {
1918    pub const NONE: Self = Self(0);
1919    /// Distance falloff
1920    pub const FALLOFF: Self = Self(1);
1921    /// Height gradient
1922    pub const HEIGHT_GRADIENT: Self = Self(2);
1923    /// Unbounded range
1924    pub const UNBOUNDED: Self = Self(4);
1925
1926    #[inline]
1927    pub const fn contains(self, other: Self) -> bool {
1928        (self.0 & other.0) == other.0
1929    }
1930
1931    #[inline]
1932    pub const fn is_empty(self) -> bool {
1933        self.0 == 0
1934    }
1935}
1936
1937impl core::ops::BitOr for ForceFlag {
1938    type Output = Self;
1939    #[inline]
1940    fn bitor(self, rhs: Self) -> Self {
1941        Self(self.0 | rhs.0)
1942    }
1943}
1944
1945impl core::ops::BitAnd for ForceFlag {
1946    type Output = Self;
1947    #[inline]
1948    fn bitand(self, rhs: Self) -> Self {
1949        Self(self.0 & rhs.0)
1950    }
1951}
1952
1953impl core::ops::Not for ForceFlag {
1954    type Output = Self;
1955    #[inline]
1956    fn not(self) -> Self {
1957        Self(!self.0)
1958    }
1959}
1960
1961impl core::fmt::Debug for ForceFlag {
1962    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1963        write!(f, "ForceFlag({:#x})", self.0)
1964    }
1965}
1966
1967/// Rigid body flags (PHRB.flags)
1968/// Bit flags. Combine with `|`, test with [`RigidBodyFlag::contains`].
1969#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
1970pub struct RigidBodyFlag(pub i32);
1971
1972impl RigidBodyFlag {
1973    pub const NONE: Self = Self(0);
1974    /// Can collide
1975    pub const COLLIDABLE: Self = Self(1);
1976    /// Walkable surface
1977    pub const WALKABLE: Self = Self(2);
1978    /// Can be stacked
1979    pub const STACKABLE: Self = Self(4);
1980    /// Simulate collisions
1981    pub const SIMULATE_COLLISION: Self = Self(8);
1982    /// Ignore local bodies
1983    pub const IGNORE_LOCAL_BODIES: Self = Self(16);
1984    /// Always present
1985    pub const ALWAYS_EXISTS: Self = Self(32);
1986    /// Unknown
1987    pub const UNKNOWN_6: Self = Self(64);
1988    /// Disable simulation
1989    pub const NO_SIMULATION: Self = Self(128);
1990    /// Unknown
1991    pub const UNKNOWN_9: Self = Self(512);
1992
1993    #[inline]
1994    pub const fn contains(self, other: Self) -> bool {
1995        (self.0 & other.0) == other.0
1996    }
1997
1998    #[inline]
1999    pub const fn is_empty(self) -> bool {
2000        self.0 == 0
2001    }
2002}
2003
2004impl core::ops::BitOr for RigidBodyFlag {
2005    type Output = Self;
2006    #[inline]
2007    fn bitor(self, rhs: Self) -> Self {
2008        Self(self.0 | rhs.0)
2009    }
2010}
2011
2012impl core::ops::BitAnd for RigidBodyFlag {
2013    type Output = Self;
2014    #[inline]
2015    fn bitand(self, rhs: Self) -> Self {
2016        Self(self.0 & rhs.0)
2017    }
2018}
2019
2020impl core::ops::Not for RigidBodyFlag {
2021    type Output = Self;
2022    #[inline]
2023    fn not(self) -> Self {
2024        Self(!self.0)
2025    }
2026}
2027
2028impl core::fmt::Debug for RigidBodyFlag {
2029    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2030        write!(f, "RigidBodyFlag({:#x})", self.0)
2031    }
2032}
2033
2034/// Shader family that prefixes a data-driven material's permutation name
2035///
2036/// Selects the base token the renderer seeds the effect-name hash with, before appending the fragment names.
2037#[repr(i32)]
2038#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2039pub enum MaterialShaderType {
2040    /// "Material"
2041    Material = 0,
2042    /// "MaterialMedium"
2043    MaterialMedium = 1,
2044    /// "MaterialSimple"
2045    MaterialSimple = 2,
2046    /// "MaterialParticle"
2047    MaterialParticle = 3,
2048    /// "MaterialSplat"
2049    MaterialSplat = 4,
2050}
2051
2052impl TryFrom<i32> for MaterialShaderType {
2053    type Error = crate::Error;
2054    fn try_from(v: i32) -> Result<Self, crate::Error> {
2055        match v {
2056            0 => Ok(MaterialShaderType::Material),
2057            1 => Ok(MaterialShaderType::MaterialMedium),
2058            2 => Ok(MaterialShaderType::MaterialSimple),
2059            3 => Ok(MaterialShaderType::MaterialParticle),
2060            4 => Ok(MaterialShaderType::MaterialSplat),
2061            other => Err(crate::Error::UnknownEnum {
2062                name: "MaterialShaderType",
2063                value: other,
2064            }),
2065        }
2066    }
2067}
2068
2069/// Color stored as BGRA (4 bytes)
2070///
2071/// Blue-green-red-alpha byte order, matching the M3 on-disk format.
2072pub struct ColorBGRA {
2073    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ColorBGRA>,
2074}
2075
2076impl Drop for ColorBGRA {
2077    fn drop(&mut self) {
2078        // SAFETY: `raw` came from a native constructor and Drop runs once.
2079        unsafe { ffi::whiteout_m3_M3ColorBGRA_delete(self.raw.as_ptr()) }
2080    }
2081}
2082
2083impl ColorBGRA {
2084    /// # Safety
2085    /// `raw` must be a live handle this value takes ownership of.
2086    #[allow(dead_code)] // used by whichever methods return this type
2087    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ColorBGRA) -> Option<Self> {
2088        core::ptr::NonNull::new(raw).map(|raw| ColorBGRA { raw })
2089    }
2090}
2091
2092// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2093// is deliberately NOT implemented — the C++ types make no documented
2094// guarantee about concurrent use, and claiming one we haven't verified
2095// would be unsound. See `@bind thread_safe` in the plan.
2096unsafe impl Send for ColorBGRA {}
2097
2098impl core::fmt::Debug for ColorBGRA {
2099    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2100        f.debug_struct("ColorBGRA").finish_non_exhaustive()
2101    }
2102}
2103
2104impl ColorBGRA {
2105    /// # Panics
2106    /// Panics if the native allocation fails.
2107    pub fn new() -> Self {
2108        // SAFETY: the native constructor returns a live handle; a null here
2109        // means the library is unusable.
2110        unsafe {
2111            let raw = ffi::whiteout_m3_M3ColorBGRA_new();
2112            Self::from_raw(raw).expect("native ColorBGRA allocation failed")
2113        }
2114    }
2115
2116    /// Blue channel
2117    pub fn b(&self) -> u8 {
2118        // SAFETY: plain scalar read through a live handle.
2119        unsafe { ffi::whiteout_m3_M3ColorBGRA_get_b(self.raw.as_ptr()) }
2120    }
2121
2122    pub fn set_b(&mut self, value: u8) {
2123        // SAFETY: plain scalar write through a live handle.
2124        unsafe { ffi::whiteout_m3_M3ColorBGRA_set_b(self.raw.as_ptr(), value) }
2125    }
2126
2127    /// Green channel
2128    pub fn g(&self) -> u8 {
2129        // SAFETY: plain scalar read through a live handle.
2130        unsafe { ffi::whiteout_m3_M3ColorBGRA_get_g(self.raw.as_ptr()) }
2131    }
2132
2133    pub fn set_g(&mut self, value: u8) {
2134        // SAFETY: plain scalar write through a live handle.
2135        unsafe { ffi::whiteout_m3_M3ColorBGRA_set_g(self.raw.as_ptr(), value) }
2136    }
2137
2138    /// Red channel
2139    pub fn r(&self) -> u8 {
2140        // SAFETY: plain scalar read through a live handle.
2141        unsafe { ffi::whiteout_m3_M3ColorBGRA_get_r(self.raw.as_ptr()) }
2142    }
2143
2144    pub fn set_r(&mut self, value: u8) {
2145        // SAFETY: plain scalar write through a live handle.
2146        unsafe { ffi::whiteout_m3_M3ColorBGRA_set_r(self.raw.as_ptr(), value) }
2147    }
2148
2149    /// Alpha channel
2150    pub fn a(&self) -> u8 {
2151        // SAFETY: plain scalar read through a live handle.
2152        unsafe { ffi::whiteout_m3_M3ColorBGRA_get_a(self.raw.as_ptr()) }
2153    }
2154
2155    pub fn set_a(&mut self, value: u8) {
2156        // SAFETY: plain scalar write through a live handle.
2157        unsafe { ffi::whiteout_m3_M3ColorBGRA_set_a(self.raw.as_ptr(), value) }
2158    }
2159}
2160
2161impl Default for ColorBGRA {
2162    fn default() -> Self {
2163        Self::new()
2164    }
2165}
2166
2167pub struct ColorBGR {
2168    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ColorBGR>,
2169}
2170
2171impl Drop for ColorBGR {
2172    fn drop(&mut self) {
2173        // SAFETY: `raw` came from a native constructor and Drop runs once.
2174        unsafe { ffi::whiteout_m3_M3ColorBGR_delete(self.raw.as_ptr()) }
2175    }
2176}
2177
2178impl ColorBGR {
2179    /// # Safety
2180    /// `raw` must be a live handle this value takes ownership of.
2181    #[allow(dead_code)] // used by whichever methods return this type
2182    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ColorBGR) -> Option<Self> {
2183        core::ptr::NonNull::new(raw).map(|raw| ColorBGR { raw })
2184    }
2185}
2186
2187// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2188// is deliberately NOT implemented — the C++ types make no documented
2189// guarantee about concurrent use, and claiming one we haven't verified
2190// would be unsound. See `@bind thread_safe` in the plan.
2191unsafe impl Send for ColorBGR {}
2192
2193impl core::fmt::Debug for ColorBGR {
2194    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2195        f.debug_struct("ColorBGR").finish_non_exhaustive()
2196    }
2197}
2198
2199impl ColorBGR {
2200    /// # Panics
2201    /// Panics if the native allocation fails.
2202    pub fn new() -> Self {
2203        // SAFETY: the native constructor returns a live handle; a null here
2204        // means the library is unusable.
2205        unsafe {
2206            let raw = ffi::whiteout_m3_M3ColorBGR_new();
2207            Self::from_raw(raw).expect("native ColorBGR allocation failed")
2208        }
2209    }
2210
2211    /// Blue channel
2212    pub fn b(&self) -> u8 {
2213        // SAFETY: plain scalar read through a live handle.
2214        unsafe { ffi::whiteout_m3_M3ColorBGR_get_b(self.raw.as_ptr()) }
2215    }
2216
2217    pub fn set_b(&mut self, value: u8) {
2218        // SAFETY: plain scalar write through a live handle.
2219        unsafe { ffi::whiteout_m3_M3ColorBGR_set_b(self.raw.as_ptr(), value) }
2220    }
2221
2222    /// Green channel
2223    pub fn g(&self) -> u8 {
2224        // SAFETY: plain scalar read through a live handle.
2225        unsafe { ffi::whiteout_m3_M3ColorBGR_get_g(self.raw.as_ptr()) }
2226    }
2227
2228    pub fn set_g(&mut self, value: u8) {
2229        // SAFETY: plain scalar write through a live handle.
2230        unsafe { ffi::whiteout_m3_M3ColorBGR_set_g(self.raw.as_ptr(), value) }
2231    }
2232
2233    /// Red channel
2234    pub fn r(&self) -> u8 {
2235        // SAFETY: plain scalar read through a live handle.
2236        unsafe { ffi::whiteout_m3_M3ColorBGR_get_r(self.raw.as_ptr()) }
2237    }
2238
2239    pub fn set_r(&mut self, value: u8) {
2240        // SAFETY: plain scalar write through a live handle.
2241        unsafe { ffi::whiteout_m3_M3ColorBGR_set_r(self.raw.as_ptr(), value) }
2242    }
2243}
2244
2245impl Default for ColorBGR {
2246    fn default() -> Self {
2247        Self::new()
2248    }
2249}
2250
2251/// Axis-aligned bounding box with bounding sphere radius (28 bytes)
2252///
2253/// Used throughout M3 for model bounds, collision bounds, and per-region extents.
2254pub struct Extent {
2255    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Extent>,
2256}
2257
2258impl Drop for Extent {
2259    fn drop(&mut self) {
2260        // SAFETY: `raw` came from a native constructor and Drop runs once.
2261        unsafe { ffi::whiteout_m3_M3Extent_delete(self.raw.as_ptr()) }
2262    }
2263}
2264
2265impl Extent {
2266    /// # Safety
2267    /// `raw` must be a live handle this value takes ownership of.
2268    #[allow(dead_code)] // used by whichever methods return this type
2269    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Extent) -> Option<Self> {
2270        core::ptr::NonNull::new(raw).map(|raw| Extent { raw })
2271    }
2272}
2273
2274// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2275// is deliberately NOT implemented — the C++ types make no documented
2276// guarantee about concurrent use, and claiming one we haven't verified
2277// would be unsound. See `@bind thread_safe` in the plan.
2278unsafe impl Send for Extent {}
2279
2280impl core::fmt::Debug for Extent {
2281    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2282        f.debug_struct("Extent").finish_non_exhaustive()
2283    }
2284}
2285
2286impl Extent {
2287    /// # Panics
2288    /// Panics if the native allocation fails.
2289    pub fn new() -> Self {
2290        // SAFETY: the native constructor returns a live handle; a null here
2291        // means the library is unusable.
2292        unsafe {
2293            let raw = ffi::whiteout_m3_M3Extent_new();
2294            Self::from_raw(raw).expect("native Extent allocation failed")
2295        }
2296    }
2297
2298    /// AABB minimum corner
2299    pub fn min(&self) -> crate::math::Vector3f {
2300        // SAFETY: the getter returns an interior pointer to a
2301        // layout-identical POD; we copy it out immediately.
2302        unsafe {
2303            *(ffi::whiteout_m3_M3Extent_get_min(self.raw.as_ptr()) as *const crate::math::Vector3f)
2304        }
2305    }
2306
2307    pub fn set_min(&mut self, value: crate::math::Vector3f) {
2308        // SAFETY: as above, in the other direction.
2309        unsafe {
2310            ffi::whiteout_m3_M3Extent_set_min(
2311                self.raw.as_ptr(),
2312                &value as *const crate::math::Vector3f as *const _,
2313            )
2314        }
2315    }
2316
2317    /// AABB maximum corner
2318    pub fn max(&self) -> crate::math::Vector3f {
2319        // SAFETY: the getter returns an interior pointer to a
2320        // layout-identical POD; we copy it out immediately.
2321        unsafe {
2322            *(ffi::whiteout_m3_M3Extent_get_max(self.raw.as_ptr()) as *const crate::math::Vector3f)
2323        }
2324    }
2325
2326    pub fn set_max(&mut self, value: crate::math::Vector3f) {
2327        // SAFETY: as above, in the other direction.
2328        unsafe {
2329            ffi::whiteout_m3_M3Extent_set_max(
2330                self.raw.as_ptr(),
2331                &value as *const crate::math::Vector3f as *const _,
2332            )
2333        }
2334    }
2335
2336    /// Bounding sphere radius
2337    pub fn radius(&self) -> f32 {
2338        // SAFETY: plain scalar read through a live handle.
2339        unsafe { ffi::whiteout_m3_M3Extent_get_radius(self.raw.as_ptr()) }
2340    }
2341
2342    pub fn set_radius(&mut self, value: f32) {
2343        // SAFETY: plain scalar write through a live handle.
2344        unsafe { ffi::whiteout_m3_M3Extent_set_radius(self.raw.as_ptr(), value) }
2345    }
2346}
2347
2348impl Default for Extent {
2349    fn default() -> Self {
2350        Self::new()
2351    }
2352}
2353
2354/// EVNT — Animation event (v0–v2, 104–108 bytes)
2355///
2356/// Named event triggered at a specific bone with an optional type code and parameter string. Used for sound cues, spawn effects, etc.
2357pub struct Event {
2358    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Event>,
2359}
2360
2361impl Drop for Event {
2362    fn drop(&mut self) {
2363        // SAFETY: `raw` came from a native constructor and Drop runs once.
2364        unsafe { ffi::whiteout_m3_M3Event_delete(self.raw.as_ptr()) }
2365    }
2366}
2367
2368impl Event {
2369    /// # Safety
2370    /// `raw` must be a live handle this value takes ownership of.
2371    #[allow(dead_code)] // used by whichever methods return this type
2372    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Event) -> Option<Self> {
2373        core::ptr::NonNull::new(raw).map(|raw| Event { raw })
2374    }
2375}
2376
2377// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2378// is deliberately NOT implemented — the C++ types make no documented
2379// guarantee about concurrent use, and claiming one we haven't verified
2380// would be unsound. See `@bind thread_safe` in the plan.
2381unsafe impl Send for Event {}
2382
2383impl core::fmt::Debug for Event {
2384    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2385        f.debug_struct("Event").finish_non_exhaustive()
2386    }
2387}
2388
2389impl Event {
2390    /// # Panics
2391    /// Panics if the native allocation fails.
2392    pub fn new() -> Self {
2393        // SAFETY: the native constructor returns a live handle; a null here
2394        // means the library is unusable.
2395        unsafe {
2396            let raw = ffi::whiteout_m3_M3Event_new();
2397            Self::from_raw(raw).expect("native Event allocation failed")
2398        }
2399    }
2400
2401    /// Event name (`Ref<CHAR>`)
2402    pub fn name(&self) -> String {
2403        // SAFETY: the native side hands over an owned CString.
2404        unsafe { crate::support::take_string(ffi::whiteout_m3_M3Event_get_name(self.raw.as_ptr())) }
2405    }
2406
2407    pub fn set_name(&mut self, value: &str) {
2408        let value = std::ffi::CString::new(value).unwrap_or_default();
2409        // SAFETY: the pointer outlives the call.
2410        unsafe { ffi::whiteout_m3_M3Event_set_name(self.raw.as_ptr(), value.as_ptr()) }
2411    }
2412
2413    /// Unknown field
2414    pub fn unknown(&self) -> u32 {
2415        // SAFETY: plain scalar read through a live handle.
2416        unsafe { ffi::whiteout_m3_M3Event_get_unknown(self.raw.as_ptr()) }
2417    }
2418
2419    pub fn set_unknown(&mut self, value: u32) {
2420        // SAFETY: plain scalar write through a live handle.
2421        unsafe { ffi::whiteout_m3_M3Event_set_unknown(self.raw.as_ptr(), value) }
2422    }
2423
2424    /// Index into BONE array
2425    pub fn bone_index(&self) -> u16 {
2426        // SAFETY: plain scalar read through a live handle.
2427        unsafe { ffi::whiteout_m3_M3Event_get_boneIndex(self.raw.as_ptr()) }
2428    }
2429
2430    pub fn set_bone_index(&mut self, value: u16) {
2431        // SAFETY: plain scalar write through a live handle.
2432        unsafe { ffi::whiteout_m3_M3Event_set_boneIndex(self.raw.as_ptr(), value) }
2433    }
2434
2435    /// Alignment padding
2436    pub fn padding(&self) -> u16 {
2437        // SAFETY: plain scalar read through a live handle.
2438        unsafe { ffi::whiteout_m3_M3Event_get_padding(self.raw.as_ptr()) }
2439    }
2440
2441    pub fn set_padding(&mut self, value: u16) {
2442        // SAFETY: plain scalar write through a live handle.
2443        unsafe { ffi::whiteout_m3_M3Event_set_padding(self.raw.as_ptr(), value) }
2444    }
2445
2446    /// Engine-specific event type code
2447    pub fn event_type(&self) -> u32 {
2448        // SAFETY: plain scalar read through a live handle.
2449        unsafe { ffi::whiteout_m3_M3Event_get_eventType(self.raw.as_ptr()) }
2450    }
2451
2452    pub fn set_event_type(&mut self, value: u32) {
2453        // SAFETY: plain scalar write through a live handle.
2454        unsafe { ffi::whiteout_m3_M3Event_set_eventType(self.raw.as_ptr(), value) }
2455    }
2456
2457    /// Optional parameter string (`Ref<CHAR>`)
2458    pub fn option_string(&self) -> String {
2459        // SAFETY: the native side hands over an owned CString.
2460        unsafe {
2461            crate::support::take_string(ffi::whiteout_m3_M3Event_get_optionString(
2462                self.raw.as_ptr(),
2463            ))
2464        }
2465    }
2466
2467    pub fn set_option_string(&mut self, value: &str) {
2468        let value = std::ffi::CString::new(value).unwrap_or_default();
2469        // SAFETY: the pointer outlives the call.
2470        unsafe { ffi::whiteout_m3_M3Event_set_optionString(self.raw.as_ptr(), value.as_ptr()) }
2471    }
2472
2473    /// RTT channel index
2474    pub fn rtt_channel_index(&self) -> u32 {
2475        // SAFETY: plain scalar read through a live handle.
2476        unsafe { ffi::whiteout_m3_M3Event_get_rttChannelIndex(self.raw.as_ptr()) }
2477    }
2478
2479    pub fn set_rtt_channel_index(&mut self, value: u32) {
2480        // SAFETY: plain scalar write through a live handle.
2481        unsafe { ffi::whiteout_m3_M3Event_set_rttChannelIndex(self.raw.as_ptr(), value) }
2482    }
2483
2484    /// Extra parameter (v2+)
2485    pub fn extra_parameter(&self) -> u32 {
2486        // SAFETY: plain scalar read through a live handle.
2487        unsafe { ffi::whiteout_m3_M3Event_get_extraParameter(self.raw.as_ptr()) }
2488    }
2489
2490    pub fn set_extra_parameter(&mut self, value: u32) {
2491        // SAFETY: plain scalar write through a live handle.
2492        unsafe { ffi::whiteout_m3_M3Event_set_extraParameter(self.raw.as_ptr(), value) }
2493    }
2494}
2495
2496impl Default for Event {
2497    fn default() -> Self {
2498        Self::new()
2499    }
2500}
2501
2502/// SEQS — Animation sequence (v0–v2, up to 92 bytes)
2503///
2504/// Defines a named animation clip with frame range, playback speed, looping flags, blend time, and bounding volume.
2505pub struct Sequence {
2506    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Sequence>,
2507}
2508
2509impl Drop for Sequence {
2510    fn drop(&mut self) {
2511        // SAFETY: `raw` came from a native constructor and Drop runs once.
2512        unsafe { ffi::whiteout_m3_M3Sequence_delete(self.raw.as_ptr()) }
2513    }
2514}
2515
2516impl Sequence {
2517    /// # Safety
2518    /// `raw` must be a live handle this value takes ownership of.
2519    #[allow(dead_code)] // used by whichever methods return this type
2520    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Sequence) -> Option<Self> {
2521        core::ptr::NonNull::new(raw).map(|raw| Sequence { raw })
2522    }
2523}
2524
2525// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2526// is deliberately NOT implemented — the C++ types make no documented
2527// guarantee about concurrent use, and claiming one we haven't verified
2528// would be unsound. See `@bind thread_safe` in the plan.
2529unsafe impl Send for Sequence {}
2530
2531impl core::fmt::Debug for Sequence {
2532    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2533        f.debug_struct("Sequence").finish_non_exhaustive()
2534    }
2535}
2536
2537impl Sequence {
2538    /// # Panics
2539    /// Panics if the native allocation fails.
2540    pub fn new() -> Self {
2541        // SAFETY: the native constructor returns a live handle; a null here
2542        // means the library is unusable.
2543        unsafe {
2544            let raw = ffi::whiteout_m3_M3Sequence_new();
2545            Self::from_raw(raw).expect("native Sequence allocation failed")
2546        }
2547    }
2548
2549    /// Unique sequence identifier
2550    pub fn id(&self) -> i32 {
2551        // SAFETY: plain scalar read through a live handle.
2552        unsafe { ffi::whiteout_m3_M3Sequence_get_id(self.raw.as_ptr()) }
2553    }
2554
2555    pub fn set_id(&mut self, value: i32) {
2556        // SAFETY: plain scalar write through a live handle.
2557        unsafe { ffi::whiteout_m3_M3Sequence_set_id(self.raw.as_ptr(), value) }
2558    }
2559
2560    /// Sequence index
2561    pub fn index(&self) -> i32 {
2562        // SAFETY: plain scalar read through a live handle.
2563        unsafe { ffi::whiteout_m3_M3Sequence_get_index(self.raw.as_ptr()) }
2564    }
2565
2566    pub fn set_index(&mut self, value: i32) {
2567        // SAFETY: plain scalar write through a live handle.
2568        unsafe { ffi::whiteout_m3_M3Sequence_set_index(self.raw.as_ptr(), value) }
2569    }
2570
2571    /// Sequence name (`Ref<CHAR>`)
2572    pub fn name(&self) -> String {
2573        // SAFETY: the native side hands over an owned CString.
2574        unsafe {
2575            crate::support::take_string(ffi::whiteout_m3_M3Sequence_get_name(self.raw.as_ptr()))
2576        }
2577    }
2578
2579    pub fn set_name(&mut self, value: &str) {
2580        let value = std::ffi::CString::new(value).unwrap_or_default();
2581        // SAFETY: the pointer outlives the call.
2582        unsafe { ffi::whiteout_m3_M3Sequence_set_name(self.raw.as_ptr(), value.as_ptr()) }
2583    }
2584
2585    /// First frame (inclusive)
2586    pub fn start_frame(&self) -> u32 {
2587        // SAFETY: plain scalar read through a live handle.
2588        unsafe { ffi::whiteout_m3_M3Sequence_get_startFrame(self.raw.as_ptr()) }
2589    }
2590
2591    pub fn set_start_frame(&mut self, value: u32) {
2592        // SAFETY: plain scalar write through a live handle.
2593        unsafe { ffi::whiteout_m3_M3Sequence_set_startFrame(self.raw.as_ptr(), value) }
2594    }
2595
2596    /// Last frame (inclusive)
2597    pub fn end_frame(&self) -> u32 {
2598        // SAFETY: plain scalar read through a live handle.
2599        unsafe { ffi::whiteout_m3_M3Sequence_get_endFrame(self.raw.as_ptr()) }
2600    }
2601
2602    pub fn set_end_frame(&mut self, value: u32) {
2603        // SAFETY: plain scalar write through a live handle.
2604        unsafe { ffi::whiteout_m3_M3Sequence_set_endFrame(self.raw.as_ptr(), value) }
2605    }
2606
2607    /// Movement speed multiplier
2608    pub fn move_speed(&self) -> f32 {
2609        // SAFETY: plain scalar read through a live handle.
2610        unsafe { ffi::whiteout_m3_M3Sequence_get_moveSpeed(self.raw.as_ptr()) }
2611    }
2612
2613    pub fn set_move_speed(&mut self, value: f32) {
2614        // SAFETY: plain scalar write through a live handle.
2615        unsafe { ffi::whiteout_m3_M3Sequence_set_moveSpeed(self.raw.as_ptr(), value) }
2616    }
2617
2618    /// Playback flags (loop, global, etc.)
2619    pub fn flags(&self) -> SequenceFlag {
2620        // SAFETY: scalar read; a flag set accepts any bits.
2621        SequenceFlag(unsafe { ffi::whiteout_m3_M3Sequence_get_flags(self.raw.as_ptr()) })
2622    }
2623
2624    pub fn set_flags(&mut self, value: SequenceFlag) {
2625        // SAFETY: scalar write through a live handle.
2626        unsafe { ffi::whiteout_m3_M3Sequence_set_flags(self.raw.as_ptr(), value.0) }
2627    }
2628
2629    /// Selection frequency / priority weight
2630    pub fn frequency(&self) -> u32 {
2631        // SAFETY: plain scalar read through a live handle.
2632        unsafe { ffi::whiteout_m3_M3Sequence_get_frequency(self.raw.as_ptr()) }
2633    }
2634
2635    pub fn set_frequency(&mut self, value: u32) {
2636        // SAFETY: plain scalar write through a live handle.
2637        unsafe { ffi::whiteout_m3_M3Sequence_set_frequency(self.raw.as_ptr(), value) }
2638    }
2639
2640    /// Replay region start frame
2641    pub fn replay_start(&self) -> u32 {
2642        // SAFETY: plain scalar read through a live handle.
2643        unsafe { ffi::whiteout_m3_M3Sequence_get_replayStart(self.raw.as_ptr()) }
2644    }
2645
2646    pub fn set_replay_start(&mut self, value: u32) {
2647        // SAFETY: plain scalar write through a live handle.
2648        unsafe { ffi::whiteout_m3_M3Sequence_set_replayStart(self.raw.as_ptr(), value) }
2649    }
2650
2651    /// Replay region end frame
2652    pub fn replay_end(&self) -> u32 {
2653        // SAFETY: plain scalar read through a live handle.
2654        unsafe { ffi::whiteout_m3_M3Sequence_get_replayEnd(self.raw.as_ptr()) }
2655    }
2656
2657    pub fn set_replay_end(&mut self, value: u32) {
2658        // SAFETY: plain scalar write through a live handle.
2659        unsafe { ffi::whiteout_m3_M3Sequence_set_replayEnd(self.raw.as_ptr(), value) }
2660    }
2661
2662    /// Blend-in time (ms)
2663    pub fn blend_time(&self) -> u32 {
2664        // SAFETY: plain scalar read through a live handle.
2665        unsafe { ffi::whiteout_m3_M3Sequence_get_blendTime(self.raw.as_ptr()) }
2666    }
2667
2668    pub fn set_blend_time(&mut self, value: u32) {
2669        // SAFETY: plain scalar write through a live handle.
2670        unsafe { ffi::whiteout_m3_M3Sequence_set_blendTime(self.raw.as_ptr(), value) }
2671    }
2672
2673    /// Animated bounding volume
2674    /// Borrows the field in place — no copy, no allocation.
2675    pub fn bounds(&self) -> crate::support::Ref<'_, Extent> {
2676        // SAFETY: an interior pointer into `self`, valid for this
2677        // borrow and never freed by the `Ref`.
2678        unsafe {
2679            crate::support::Ref::new(Extent {
2680                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Sequence_get_bounds(
2681                    self.raw.as_ptr(),
2682                )),
2683            })
2684        }
2685    }
2686
2687    pub fn bounds_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
2688        // SAFETY: as above; `&mut self` guarantees exclusivity.
2689        unsafe {
2690            crate::support::RefMut::new(Extent {
2691                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Sequence_get_bounds(
2692                    self.raw.as_ptr(),
2693                )),
2694            })
2695        }
2696    }
2697
2698    /// Animation set indices (U8__)
2699    /// Zero-copy view of the underlying `std::vector`.
2700    pub fn animation_sets(&self) -> &[u8] {
2701        // SAFETY: `_data`/`_count` describe one contiguous C++
2702        // allocation, borrowed for as long as `self` is.
2703        unsafe {
2704            let n = ffi::whiteout_m3_M3Sequence_get_animationSets_count(self.raw.as_ptr());
2705            let p = ffi::whiteout_m3_M3Sequence_get_animationSets_data(self.raw.as_ptr());
2706            if p.is_null() || n == 0 {
2707                &[]
2708            } else {
2709                core::slice::from_raw_parts(p, n)
2710            }
2711        }
2712    }
2713
2714    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2715    pub fn animation_sets_mut(&mut self) -> &mut [u8] {
2716        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2717        unsafe {
2718            let n = ffi::whiteout_m3_M3Sequence_get_animationSets_count(self.raw.as_ptr());
2719            let p =
2720                ffi::whiteout_m3_M3Sequence_get_animationSets_data(self.raw.as_ptr()) as *mut u8;
2721            if p.is_null() || n == 0 {
2722                &mut []
2723            } else {
2724                core::slice::from_raw_parts_mut(p, n)
2725            }
2726        }
2727    }
2728
2729    pub fn set_animation_sets(&mut self, values: &[u8]) {
2730        // SAFETY: the native side copies `values` before returning.
2731        unsafe {
2732            ffi::whiteout_m3_M3Sequence_assign_animationSets(
2733                self.raw.as_ptr(),
2734                values.as_ptr() as *const _,
2735                values.len(),
2736            )
2737        }
2738    }
2739
2740    pub fn resize_animation_sets(&mut self, count: usize) {
2741        // SAFETY: reallocation is safe here precisely because
2742        // `&mut self` means no slice borrow is outstanding.
2743        unsafe { ffi::whiteout_m3_M3Sequence_resize_animationSets(self.raw.as_ptr(), count) }
2744    }
2745}
2746
2747impl Default for Sequence {
2748    fn default() -> Self {
2749        Self::new()
2750    }
2751}
2752
2753/// STC_ — Sub-track container (v0–v4, 204 bytes)
2754///
2755/// Binds animation IDs to concrete keyframe data stored in 13 typed AnimBlock arrays (slots 0–12). Each slot handles a different value type: events, vectors, quaternions, colors, scalars, flags, and bounding extents.
2756pub struct SubTrackContainer {
2757    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3SubTrackContainer>,
2758}
2759
2760impl Drop for SubTrackContainer {
2761    fn drop(&mut self) {
2762        // SAFETY: `raw` came from a native constructor and Drop runs once.
2763        unsafe { ffi::whiteout_m3_M3SubTrackContainer_delete(self.raw.as_ptr()) }
2764    }
2765}
2766
2767impl SubTrackContainer {
2768    /// # Safety
2769    /// `raw` must be a live handle this value takes ownership of.
2770    #[allow(dead_code)] // used by whichever methods return this type
2771    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3SubTrackContainer) -> Option<Self> {
2772        core::ptr::NonNull::new(raw).map(|raw| SubTrackContainer { raw })
2773    }
2774}
2775
2776// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2777// is deliberately NOT implemented — the C++ types make no documented
2778// guarantee about concurrent use, and claiming one we haven't verified
2779// would be unsound. See `@bind thread_safe` in the plan.
2780unsafe impl Send for SubTrackContainer {}
2781
2782impl core::fmt::Debug for SubTrackContainer {
2783    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2784        f.debug_struct("SubTrackContainer").finish_non_exhaustive()
2785    }
2786}
2787
2788impl SubTrackContainer {
2789    /// # Panics
2790    /// Panics if the native allocation fails.
2791    pub fn new() -> Self {
2792        // SAFETY: the native constructor returns a live handle; a null here
2793        // means the library is unusable.
2794        unsafe {
2795            let raw = ffi::whiteout_m3_M3SubTrackContainer_new();
2796            Self::from_raw(raw).expect("native SubTrackContainer allocation failed")
2797        }
2798    }
2799
2800    /// Container name (`Ref<CHAR>`)
2801    pub fn name(&self) -> String {
2802        // SAFETY: the native side hands over an owned CString.
2803        unsafe {
2804            crate::support::take_string(ffi::whiteout_m3_M3SubTrackContainer_get_name(
2805                self.raw.as_ptr(),
2806            ))
2807        }
2808    }
2809
2810    pub fn set_name(&mut self, value: &str) {
2811        let value = std::ffi::CString::new(value).unwrap_or_default();
2812        // SAFETY: the pointer outlives the call.
2813        unsafe { ffi::whiteout_m3_M3SubTrackContainer_set_name(self.raw.as_ptr(), value.as_ptr()) }
2814    }
2815
2816    /// Non-zero if runs concurrently
2817    pub fn runs_concurrent(&self) -> u16 {
2818        // SAFETY: plain scalar read through a live handle.
2819        unsafe { ffi::whiteout_m3_M3SubTrackContainer_get_runsConcurrent(self.raw.as_ptr()) }
2820    }
2821
2822    pub fn set_runs_concurrent(&mut self, value: u16) {
2823        // SAFETY: plain scalar write through a live handle.
2824        unsafe { ffi::whiteout_m3_M3SubTrackContainer_set_runsConcurrent(self.raw.as_ptr(), value) }
2825    }
2826
2827    /// Animation priority level
2828    pub fn anim_priority(&self) -> u16 {
2829        // SAFETY: plain scalar read through a live handle.
2830        unsafe { ffi::whiteout_m3_M3SubTrackContainer_get_animPriority(self.raw.as_ptr()) }
2831    }
2832
2833    pub fn set_anim_priority(&mut self, value: u16) {
2834        // SAFETY: plain scalar write through a live handle.
2835        unsafe { ffi::whiteout_m3_M3SubTrackContainer_set_animPriority(self.raw.as_ptr(), value) }
2836    }
2837
2838    /// Parent STS_ index
2839    pub fn animation_state_index(&self) -> u16 {
2840        // SAFETY: plain scalar read through a live handle.
2841        unsafe { ffi::whiteout_m3_M3SubTrackContainer_get_animationStateIndex(self.raw.as_ptr()) }
2842    }
2843
2844    pub fn set_animation_state_index(&mut self, value: u16) {
2845        // SAFETY: plain scalar write through a live handle.
2846        unsafe {
2847            ffi::whiteout_m3_M3SubTrackContainer_set_animationStateIndex(self.raw.as_ptr(), value)
2848        }
2849    }
2850
2851    /// Second copy of the STS_ index; every one of the 2,197 shipped containers repeats the index here
2852    pub fn animation_state_index_copy(&self) -> u16 {
2853        // SAFETY: plain scalar read through a live handle.
2854        unsafe {
2855            ffi::whiteout_m3_M3SubTrackContainer_get_animationStateIndexCopy(self.raw.as_ptr())
2856        }
2857    }
2858
2859    pub fn set_animation_state_index_copy(&mut self, value: u16) {
2860        // SAFETY: plain scalar write through a live handle.
2861        unsafe {
2862            ffi::whiteout_m3_M3SubTrackContainer_set_animationStateIndexCopy(
2863                self.raw.as_ptr(),
2864                value,
2865            )
2866        }
2867    }
2868
2869    /// Animation IDs (U32_)
2870    /// Zero-copy view of the underlying `std::vector`.
2871    pub fn anim_ids(&self) -> &[u32] {
2872        // SAFETY: `_data`/`_count` describe one contiguous C++
2873        // allocation, borrowed for as long as `self` is.
2874        unsafe {
2875            let n = ffi::whiteout_m3_M3SubTrackContainer_get_animIds_count(self.raw.as_ptr());
2876            let p = ffi::whiteout_m3_M3SubTrackContainer_get_animIds_data(self.raw.as_ptr());
2877            if p.is_null() || n == 0 {
2878                &[]
2879            } else {
2880                core::slice::from_raw_parts(p, n)
2881            }
2882        }
2883    }
2884
2885    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2886    pub fn anim_ids_mut(&mut self) -> &mut [u32] {
2887        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2888        unsafe {
2889            let n = ffi::whiteout_m3_M3SubTrackContainer_get_animIds_count(self.raw.as_ptr());
2890            let p = ffi::whiteout_m3_M3SubTrackContainer_get_animIds_data(self.raw.as_ptr())
2891                as *mut u32;
2892            if p.is_null() || n == 0 {
2893                &mut []
2894            } else {
2895                core::slice::from_raw_parts_mut(p, n)
2896            }
2897        }
2898    }
2899
2900    pub fn set_anim_ids(&mut self, values: &[u32]) {
2901        // SAFETY: the native side copies `values` before returning.
2902        unsafe {
2903            ffi::whiteout_m3_M3SubTrackContainer_assign_animIds(
2904                self.raw.as_ptr(),
2905                values.as_ptr() as *const _,
2906                values.len(),
2907            )
2908        }
2909    }
2910
2911    pub fn resize_anim_ids(&mut self, count: usize) {
2912        // SAFETY: reallocation is safe here precisely because
2913        // `&mut self` means no slice borrow is outstanding.
2914        unsafe { ffi::whiteout_m3_M3SubTrackContainer_resize_animIds(self.raw.as_ptr(), count) }
2915    }
2916
2917    /// Animation reference indices (U32_)
2918    /// Zero-copy view of the underlying `std::vector`.
2919    pub fn anim_refs(&self) -> &[u32] {
2920        // SAFETY: `_data`/`_count` describe one contiguous C++
2921        // allocation, borrowed for as long as `self` is.
2922        unsafe {
2923            let n = ffi::whiteout_m3_M3SubTrackContainer_get_animRefs_count(self.raw.as_ptr());
2924            let p = ffi::whiteout_m3_M3SubTrackContainer_get_animRefs_data(self.raw.as_ptr());
2925            if p.is_null() || n == 0 {
2926                &[]
2927            } else {
2928                core::slice::from_raw_parts(p, n)
2929            }
2930        }
2931    }
2932
2933    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2934    pub fn anim_refs_mut(&mut self) -> &mut [u32] {
2935        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2936        unsafe {
2937            let n = ffi::whiteout_m3_M3SubTrackContainer_get_animRefs_count(self.raw.as_ptr());
2938            let p = ffi::whiteout_m3_M3SubTrackContainer_get_animRefs_data(self.raw.as_ptr())
2939                as *mut u32;
2940            if p.is_null() || n == 0 {
2941                &mut []
2942            } else {
2943                core::slice::from_raw_parts_mut(p, n)
2944            }
2945        }
2946    }
2947
2948    pub fn set_anim_refs(&mut self, values: &[u32]) {
2949        // SAFETY: the native side copies `values` before returning.
2950        unsafe {
2951            ffi::whiteout_m3_M3SubTrackContainer_assign_animRefs(
2952                self.raw.as_ptr(),
2953                values.as_ptr() as *const _,
2954                values.len(),
2955            )
2956        }
2957    }
2958
2959    pub fn resize_anim_refs(&mut self, count: usize) {
2960        // SAFETY: reallocation is safe here precisely because
2961        // `&mut self` means no slice borrow is outstanding.
2962        unsafe { ffi::whiteout_m3_M3SubTrackContainer_resize_animRefs(self.raw.as_ptr(), count) }
2963    }
2964
2965    /// Unknown field
2966    pub fn unknown(&self) -> u32 {
2967        // SAFETY: plain scalar read through a live handle.
2968        unsafe { ffi::whiteout_m3_M3SubTrackContainer_get_unknown(self.raw.as_ptr()) }
2969    }
2970
2971    pub fn set_unknown(&mut self, value: u32) {
2972        // SAFETY: plain scalar write through a live handle.
2973        unsafe { ffi::whiteout_m3_M3SubTrackContainer_set_unknown(self.raw.as_ptr(), value) }
2974    }
2975}
2976
2977impl Default for SubTrackContainer {
2978    fn default() -> Self {
2979        Self::new()
2980    }
2981}
2982
2983/// STG_ — Animation group (v0, 24 bytes)
2984///
2985/// Groups sub-track containers by name for organizational purposes.
2986pub struct AnimationGroup {
2987    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimationGroup>,
2988}
2989
2990impl Drop for AnimationGroup {
2991    fn drop(&mut self) {
2992        // SAFETY: `raw` came from a native constructor and Drop runs once.
2993        unsafe { ffi::whiteout_m3_M3AnimationGroup_delete(self.raw.as_ptr()) }
2994    }
2995}
2996
2997impl AnimationGroup {
2998    /// # Safety
2999    /// `raw` must be a live handle this value takes ownership of.
3000    #[allow(dead_code)] // used by whichever methods return this type
3001    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimationGroup) -> Option<Self> {
3002        core::ptr::NonNull::new(raw).map(|raw| AnimationGroup { raw })
3003    }
3004}
3005
3006// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3007// is deliberately NOT implemented — the C++ types make no documented
3008// guarantee about concurrent use, and claiming one we haven't verified
3009// would be unsound. See `@bind thread_safe` in the plan.
3010unsafe impl Send for AnimationGroup {}
3011
3012impl core::fmt::Debug for AnimationGroup {
3013    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3014        f.debug_struct("AnimationGroup").finish_non_exhaustive()
3015    }
3016}
3017
3018impl AnimationGroup {
3019    /// # Panics
3020    /// Panics if the native allocation fails.
3021    pub fn new() -> Self {
3022        // SAFETY: the native constructor returns a live handle; a null here
3023        // means the library is unusable.
3024        unsafe {
3025            let raw = ffi::whiteout_m3_M3AnimationGroup_new();
3026            Self::from_raw(raw).expect("native AnimationGroup allocation failed")
3027        }
3028    }
3029
3030    /// Group name (`Ref<CHAR>`)
3031    pub fn name(&self) -> String {
3032        // SAFETY: the native side hands over an owned CString.
3033        unsafe {
3034            crate::support::take_string(ffi::whiteout_m3_M3AnimationGroup_get_name(
3035                self.raw.as_ptr(),
3036            ))
3037        }
3038    }
3039
3040    pub fn set_name(&mut self, value: &str) {
3041        let value = std::ffi::CString::new(value).unwrap_or_default();
3042        // SAFETY: the pointer outlives the call.
3043        unsafe { ffi::whiteout_m3_M3AnimationGroup_set_name(self.raw.as_ptr(), value.as_ptr()) }
3044    }
3045
3046    /// Indices into STC_ array (U32_)
3047    /// Zero-copy view of the underlying `std::vector`.
3048    pub fn subtrack_indices(&self) -> &[u32] {
3049        // SAFETY: `_data`/`_count` describe one contiguous C++
3050        // allocation, borrowed for as long as `self` is.
3051        unsafe {
3052            let n = ffi::whiteout_m3_M3AnimationGroup_get_subtrackIndices_count(self.raw.as_ptr());
3053            let p = ffi::whiteout_m3_M3AnimationGroup_get_subtrackIndices_data(self.raw.as_ptr());
3054            if p.is_null() || n == 0 {
3055                &[]
3056            } else {
3057                core::slice::from_raw_parts(p, n)
3058            }
3059        }
3060    }
3061
3062    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
3063    pub fn subtrack_indices_mut(&mut self) -> &mut [u32] {
3064        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
3065        unsafe {
3066            let n = ffi::whiteout_m3_M3AnimationGroup_get_subtrackIndices_count(self.raw.as_ptr());
3067            let p = ffi::whiteout_m3_M3AnimationGroup_get_subtrackIndices_data(self.raw.as_ptr())
3068                as *mut u32;
3069            if p.is_null() || n == 0 {
3070                &mut []
3071            } else {
3072                core::slice::from_raw_parts_mut(p, n)
3073            }
3074        }
3075    }
3076
3077    pub fn set_subtrack_indices(&mut self, values: &[u32]) {
3078        // SAFETY: the native side copies `values` before returning.
3079        unsafe {
3080            ffi::whiteout_m3_M3AnimationGroup_assign_subtrackIndices(
3081                self.raw.as_ptr(),
3082                values.as_ptr() as *const _,
3083                values.len(),
3084            )
3085        }
3086    }
3087
3088    pub fn resize_subtrack_indices(&mut self, count: usize) {
3089        // SAFETY: reallocation is safe here precisely because
3090        // `&mut self` means no slice borrow is outstanding.
3091        unsafe {
3092            ffi::whiteout_m3_M3AnimationGroup_resize_subtrackIndices(self.raw.as_ptr(), count)
3093        }
3094    }
3095}
3096
3097impl Default for AnimationGroup {
3098    fn default() -> Self {
3099        Self::new()
3100    }
3101}
3102
3103/// STS_ — Animation state (v0, 28 bytes)
3104///
3105/// Top-level animation state containing a set of animation IDs and 16 bytes of unknown state data.
3106pub struct AnimationState {
3107    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimationState>,
3108}
3109
3110impl Drop for AnimationState {
3111    fn drop(&mut self) {
3112        // SAFETY: `raw` came from a native constructor and Drop runs once.
3113        unsafe { ffi::whiteout_m3_M3AnimationState_delete(self.raw.as_ptr()) }
3114    }
3115}
3116
3117impl AnimationState {
3118    /// # Safety
3119    /// `raw` must be a live handle this value takes ownership of.
3120    #[allow(dead_code)] // used by whichever methods return this type
3121    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimationState) -> Option<Self> {
3122        core::ptr::NonNull::new(raw).map(|raw| AnimationState { raw })
3123    }
3124}
3125
3126// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3127// is deliberately NOT implemented — the C++ types make no documented
3128// guarantee about concurrent use, and claiming one we haven't verified
3129// would be unsound. See `@bind thread_safe` in the plan.
3130unsafe impl Send for AnimationState {}
3131
3132impl core::fmt::Debug for AnimationState {
3133    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3134        f.debug_struct("AnimationState").finish_non_exhaustive()
3135    }
3136}
3137
3138impl AnimationState {
3139    /// # Panics
3140    /// Panics if the native allocation fails.
3141    pub fn new() -> Self {
3142        // SAFETY: the native constructor returns a live handle; a null here
3143        // means the library is unusable.
3144        unsafe {
3145            let raw = ffi::whiteout_m3_M3AnimationState_new();
3146            Self::from_raw(raw).expect("native AnimationState allocation failed")
3147        }
3148    }
3149
3150    /// Animation IDs (U32_)
3151    /// Zero-copy view of the underlying `std::vector`.
3152    pub fn anim_ids(&self) -> &[u32] {
3153        // SAFETY: `_data`/`_count` describe one contiguous C++
3154        // allocation, borrowed for as long as `self` is.
3155        unsafe {
3156            let n = ffi::whiteout_m3_M3AnimationState_get_animIds_count(self.raw.as_ptr());
3157            let p = ffi::whiteout_m3_M3AnimationState_get_animIds_data(self.raw.as_ptr());
3158            if p.is_null() || n == 0 {
3159                &[]
3160            } else {
3161                core::slice::from_raw_parts(p, n)
3162            }
3163        }
3164    }
3165
3166    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
3167    pub fn anim_ids_mut(&mut self) -> &mut [u32] {
3168        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
3169        unsafe {
3170            let n = ffi::whiteout_m3_M3AnimationState_get_animIds_count(self.raw.as_ptr());
3171            let p =
3172                ffi::whiteout_m3_M3AnimationState_get_animIds_data(self.raw.as_ptr()) as *mut u32;
3173            if p.is_null() || n == 0 {
3174                &mut []
3175            } else {
3176                core::slice::from_raw_parts_mut(p, n)
3177            }
3178        }
3179    }
3180
3181    pub fn set_anim_ids(&mut self, values: &[u32]) {
3182        // SAFETY: the native side copies `values` before returning.
3183        unsafe {
3184            ffi::whiteout_m3_M3AnimationState_assign_animIds(
3185                self.raw.as_ptr(),
3186                values.as_ptr() as *const _,
3187                values.len(),
3188            )
3189        }
3190    }
3191
3192    pub fn resize_anim_ids(&mut self, count: usize) {
3193        // SAFETY: reallocation is safe here precisely because
3194        // `&mut self` means no slice borrow is outstanding.
3195        unsafe { ffi::whiteout_m3_M3AnimationState_resize_animIds(self.raw.as_ptr(), count) }
3196    }
3197
3198    /// Unknown state data (16 bytes)
3199    /// Number of elements — a fixed-size C++ array.
3200    pub const fn unknown_len() -> usize {
3201        16
3202    }
3203
3204    /// # Panics
3205    /// If `index >= 16`, matching Rust slice indexing.
3206    pub fn unknown(&self, index: usize) -> u8 {
3207        assert!(index < 16, "unknown index {index} out of range (len 16)");
3208        // SAFETY: index checked above; plain scalar read.
3209        unsafe { ffi::whiteout_m3_M3AnimationState_get_unknown_at(self.raw.as_ptr(), index) }
3210    }
3211
3212    /// # Panics
3213    /// If `index >= 16`.
3214    pub fn set_unknown(&mut self, index: usize, value: u8) {
3215        assert!(index < 16, "unknown index {index} out of range (len 16)");
3216        // SAFETY: index checked above.
3217        unsafe { ffi::whiteout_m3_M3AnimationState_set_unknown_at(self.raw.as_ptr(), index, value) }
3218    }
3219}
3220
3221impl Default for AnimationState {
3222    fn default() -> Self {
3223        Self::new()
3224    }
3225}
3226
3227/// BSET — Bone animation set (v0, 32 bytes)
3228///
3229/// Maps a bone to specific animation sequences with fallback support. In practice, always null in observed corpus data.
3230pub struct BoneAnimationSet {
3231    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3BoneAnimationSet>,
3232}
3233
3234impl Drop for BoneAnimationSet {
3235    fn drop(&mut self) {
3236        // SAFETY: `raw` came from a native constructor and Drop runs once.
3237        unsafe { ffi::whiteout_m3_M3BoneAnimationSet_delete(self.raw.as_ptr()) }
3238    }
3239}
3240
3241impl BoneAnimationSet {
3242    /// # Safety
3243    /// `raw` must be a live handle this value takes ownership of.
3244    #[allow(dead_code)] // used by whichever methods return this type
3245    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3BoneAnimationSet) -> Option<Self> {
3246        core::ptr::NonNull::new(raw).map(|raw| BoneAnimationSet { raw })
3247    }
3248}
3249
3250// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3251// is deliberately NOT implemented — the C++ types make no documented
3252// guarantee about concurrent use, and claiming one we haven't verified
3253// would be unsound. See `@bind thread_safe` in the plan.
3254unsafe impl Send for BoneAnimationSet {}
3255
3256impl core::fmt::Debug for BoneAnimationSet {
3257    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3258        f.debug_struct("BoneAnimationSet").finish_non_exhaustive()
3259    }
3260}
3261
3262impl BoneAnimationSet {
3263    /// # Panics
3264    /// Panics if the native allocation fails.
3265    pub fn new() -> Self {
3266        // SAFETY: the native constructor returns a live handle; a null here
3267        // means the library is unusable.
3268        unsafe {
3269            let raw = ffi::whiteout_m3_M3BoneAnimationSet_new();
3270            Self::from_raw(raw).expect("native BoneAnimationSet allocation failed")
3271        }
3272    }
3273
3274    /// Primary sequence index
3275    pub fn animation_sequence_index(&self) -> u16 {
3276        // SAFETY: plain scalar read through a live handle.
3277        unsafe { ffi::whiteout_m3_M3BoneAnimationSet_get_animationSequenceIndex(self.raw.as_ptr()) }
3278    }
3279
3280    pub fn set_animation_sequence_index(&mut self, value: u16) {
3281        // SAFETY: plain scalar write through a live handle.
3282        unsafe {
3283            ffi::whiteout_m3_M3BoneAnimationSet_set_animationSequenceIndex(self.raw.as_ptr(), value)
3284        }
3285    }
3286
3287    /// Fallback sequence index
3288    pub fn fallback_sequence_index(&self) -> u16 {
3289        // SAFETY: plain scalar read through a live handle.
3290        unsafe { ffi::whiteout_m3_M3BoneAnimationSet_get_fallbackSequenceIndex(self.raw.as_ptr()) }
3291    }
3292
3293    pub fn set_fallback_sequence_index(&mut self, value: u16) {
3294        // SAFETY: plain scalar write through a live handle.
3295        unsafe {
3296            ffi::whiteout_m3_M3BoneAnimationSet_set_fallbackSequenceIndex(self.raw.as_ptr(), value)
3297        }
3298    }
3299
3300    /// Set name (`Ref<CHAR>`)
3301    pub fn name(&self) -> String {
3302        // SAFETY: the native side hands over an owned CString.
3303        unsafe {
3304            crate::support::take_string(ffi::whiteout_m3_M3BoneAnimationSet_get_name(
3305                self.raw.as_ptr(),
3306            ))
3307        }
3308    }
3309
3310    pub fn set_name(&mut self, value: &str) {
3311        let value = std::ffi::CString::new(value).unwrap_or_default();
3312        // SAFETY: the pointer outlives the call.
3313        unsafe { ffi::whiteout_m3_M3BoneAnimationSet_set_name(self.raw.as_ptr(), value.as_ptr()) }
3314    }
3315
3316    /// Split item indices (U16_)
3317    /// Zero-copy view of the underlying `std::vector`.
3318    pub fn split_items(&self) -> &[u16] {
3319        // SAFETY: `_data`/`_count` describe one contiguous C++
3320        // allocation, borrowed for as long as `self` is.
3321        unsafe {
3322            let n = ffi::whiteout_m3_M3BoneAnimationSet_get_splitItems_count(self.raw.as_ptr());
3323            let p = ffi::whiteout_m3_M3BoneAnimationSet_get_splitItems_data(self.raw.as_ptr());
3324            if p.is_null() || n == 0 {
3325                &[]
3326            } else {
3327                core::slice::from_raw_parts(p, n)
3328            }
3329        }
3330    }
3331
3332    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
3333    pub fn split_items_mut(&mut self) -> &mut [u16] {
3334        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
3335        unsafe {
3336            let n = ffi::whiteout_m3_M3BoneAnimationSet_get_splitItems_count(self.raw.as_ptr());
3337            let p = ffi::whiteout_m3_M3BoneAnimationSet_get_splitItems_data(self.raw.as_ptr())
3338                as *mut u16;
3339            if p.is_null() || n == 0 {
3340                &mut []
3341            } else {
3342                core::slice::from_raw_parts_mut(p, n)
3343            }
3344        }
3345    }
3346
3347    pub fn set_split_items(&mut self, values: &[u16]) {
3348        // SAFETY: the native side copies `values` before returning.
3349        unsafe {
3350            ffi::whiteout_m3_M3BoneAnimationSet_assign_splitItems(
3351                self.raw.as_ptr(),
3352                values.as_ptr() as *const _,
3353                values.len(),
3354            )
3355        }
3356    }
3357
3358    pub fn resize_split_items(&mut self, count: usize) {
3359        // SAFETY: reallocation is safe here precisely because
3360        // `&mut self` means no slice borrow is outstanding.
3361        unsafe { ffi::whiteout_m3_M3BoneAnimationSet_resize_splitItems(self.raw.as_ptr(), count) }
3362    }
3363}
3364
3365impl Default for BoneAnimationSet {
3366    fn default() -> Self {
3367        Self::new()
3368    }
3369}
3370
3371/// PAR_ — Particle emitter (v10–v24, 1300–1496 bytes)
3372///
3373/// The most complex M3 chunk type. Contains bone/material binding, emission shape/rate, per-particle lifetime/velocity/color/size/rotation curves, physics (drag, mass, forces), noise, collision, flipbook, variation channels, spline data, LOD, trails, and splat references. Version extensions add additional flags, force multipliers, UV transforms, phase shift, and ribbon-on-bounce parameters.
3374pub struct ParticleEmitter {
3375    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ParticleEmitter>,
3376}
3377
3378impl Drop for ParticleEmitter {
3379    fn drop(&mut self) {
3380        // SAFETY: `raw` came from a native constructor and Drop runs once.
3381        unsafe { ffi::whiteout_m3_M3ParticleEmitter_delete(self.raw.as_ptr()) }
3382    }
3383}
3384
3385impl ParticleEmitter {
3386    /// # Safety
3387    /// `raw` must be a live handle this value takes ownership of.
3388    #[allow(dead_code)] // used by whichever methods return this type
3389    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ParticleEmitter) -> Option<Self> {
3390        core::ptr::NonNull::new(raw).map(|raw| ParticleEmitter { raw })
3391    }
3392}
3393
3394// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3395// is deliberately NOT implemented — the C++ types make no documented
3396// guarantee about concurrent use, and claiming one we haven't verified
3397// would be unsound. See `@bind thread_safe` in the plan.
3398unsafe impl Send for ParticleEmitter {}
3399
3400impl core::fmt::Debug for ParticleEmitter {
3401    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3402        f.debug_struct("ParticleEmitter").finish_non_exhaustive()
3403    }
3404}
3405
3406impl ParticleEmitter {
3407    /// # Panics
3408    /// Panics if the native allocation fails.
3409    pub fn new() -> Self {
3410        // SAFETY: the native constructor returns a live handle; a null here
3411        // means the library is unusable.
3412        unsafe {
3413            let raw = ffi::whiteout_m3_M3ParticleEmitter_new();
3414            Self::from_raw(raw).expect("native ParticleEmitter allocation failed")
3415        }
3416    }
3417
3418    /// Index into BONE array
3419    pub fn bone_index(&self) -> u32 {
3420        // SAFETY: plain scalar read through a live handle.
3421        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_boneIndex(self.raw.as_ptr()) }
3422    }
3423
3424    pub fn set_bone_index(&mut self, value: u32) {
3425        // SAFETY: plain scalar write through a live handle.
3426        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_boneIndex(self.raw.as_ptr(), value) }
3427    }
3428
3429    /// Index into MATM material map array
3430    pub fn material_index(&self) -> u32 {
3431        // SAFETY: plain scalar read through a live handle.
3432        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_materialIndex(self.raw.as_ptr()) }
3433    }
3434
3435    pub fn set_material_index(&mut self, value: u32) {
3436        // SAFETY: plain scalar write through a live handle.
3437        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_materialIndex(self.raw.as_ptr(), value) }
3438    }
3439
3440    pub fn additional_flags(&self) -> ParticleAdditionalFlag {
3441        // SAFETY: scalar read; a flag set accepts any bits.
3442        ParticleAdditionalFlag(unsafe {
3443            ffi::whiteout_m3_M3ParticleEmitter_get_additionalFlags(self.raw.as_ptr())
3444        })
3445    }
3446
3447    pub fn set_additional_flags(&mut self, value: ParticleAdditionalFlag) {
3448        // SAFETY: scalar write through a live handle.
3449        unsafe {
3450            ffi::whiteout_m3_M3ParticleEmitter_set_additionalFlags(self.raw.as_ptr(), value.0)
3451        }
3452    }
3453
3454    /// Initial particle speed
3455    /// Borrows the field in place — no copy, no allocation.
3456    pub fn initial_speed(&self) -> crate::support::Ref<'_, AnimRefF32> {
3457        // SAFETY: an interior pointer into `self`, valid for this
3458        // borrow and never freed by the `Ref`.
3459        unsafe {
3460            crate::support::Ref::new(AnimRefF32 {
3461                raw: core::ptr::NonNull::new_unchecked(
3462                    ffi::whiteout_m3_M3ParticleEmitter_get_initialSpeed(self.raw.as_ptr()),
3463                ),
3464            })
3465        }
3466    }
3467
3468    pub fn initial_speed_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3469        // SAFETY: as above; `&mut self` guarantees exclusivity.
3470        unsafe {
3471            crate::support::RefMut::new(AnimRefF32 {
3472                raw: core::ptr::NonNull::new_unchecked(
3473                    ffi::whiteout_m3_M3ParticleEmitter_get_initialSpeed(self.raw.as_ptr()),
3474                ),
3475            })
3476        }
3477    }
3478
3479    /// Random speed variation
3480    /// Borrows the field in place — no copy, no allocation.
3481    pub fn initial_speed_random(&self) -> crate::support::Ref<'_, AnimRefF32> {
3482        // SAFETY: an interior pointer into `self`, valid for this
3483        // borrow and never freed by the `Ref`.
3484        unsafe {
3485            crate::support::Ref::new(AnimRefF32 {
3486                raw: core::ptr::NonNull::new_unchecked(
3487                    ffi::whiteout_m3_M3ParticleEmitter_get_initialSpeedRandom(self.raw.as_ptr()),
3488                ),
3489            })
3490        }
3491    }
3492
3493    pub fn initial_speed_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3494        // SAFETY: as above; `&mut self` guarantees exclusivity.
3495        unsafe {
3496            crate::support::RefMut::new(AnimRefF32 {
3497                raw: core::ptr::NonNull::new_unchecked(
3498                    ffi::whiteout_m3_M3ParticleEmitter_get_initialSpeedRandom(self.raw.as_ptr()),
3499                ),
3500            })
3501        }
3502    }
3503
3504    /// Initial yaw angle
3505    /// Borrows the field in place — no copy, no allocation.
3506    pub fn initial_yaw(&self) -> crate::support::Ref<'_, AnimRefF32> {
3507        // SAFETY: an interior pointer into `self`, valid for this
3508        // borrow and never freed by the `Ref`.
3509        unsafe {
3510            crate::support::Ref::new(AnimRefF32 {
3511                raw: core::ptr::NonNull::new_unchecked(
3512                    ffi::whiteout_m3_M3ParticleEmitter_get_initialYaw(self.raw.as_ptr()),
3513                ),
3514            })
3515        }
3516    }
3517
3518    pub fn initial_yaw_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3519        // SAFETY: as above; `&mut self` guarantees exclusivity.
3520        unsafe {
3521            crate::support::RefMut::new(AnimRefF32 {
3522                raw: core::ptr::NonNull::new_unchecked(
3523                    ffi::whiteout_m3_M3ParticleEmitter_get_initialYaw(self.raw.as_ptr()),
3524                ),
3525            })
3526        }
3527    }
3528
3529    /// Initial pitch angle
3530    /// Borrows the field in place — no copy, no allocation.
3531    pub fn initial_pitch(&self) -> crate::support::Ref<'_, AnimRefF32> {
3532        // SAFETY: an interior pointer into `self`, valid for this
3533        // borrow and never freed by the `Ref`.
3534        unsafe {
3535            crate::support::Ref::new(AnimRefF32 {
3536                raw: core::ptr::NonNull::new_unchecked(
3537                    ffi::whiteout_m3_M3ParticleEmitter_get_initialPitch(self.raw.as_ptr()),
3538                ),
3539            })
3540        }
3541    }
3542
3543    pub fn initial_pitch_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3544        // SAFETY: as above; `&mut self` guarantees exclusivity.
3545        unsafe {
3546            crate::support::RefMut::new(AnimRefF32 {
3547                raw: core::ptr::NonNull::new_unchecked(
3548                    ffi::whiteout_m3_M3ParticleEmitter_get_initialPitch(self.raw.as_ptr()),
3549                ),
3550            })
3551        }
3552    }
3553
3554    /// Initial horizontal spread
3555    /// Borrows the field in place — no copy, no allocation.
3556    pub fn initial_horizontal(&self) -> crate::support::Ref<'_, AnimRefF32> {
3557        // SAFETY: an interior pointer into `self`, valid for this
3558        // borrow and never freed by the `Ref`.
3559        unsafe {
3560            crate::support::Ref::new(AnimRefF32 {
3561                raw: core::ptr::NonNull::new_unchecked(
3562                    ffi::whiteout_m3_M3ParticleEmitter_get_initialHorizontal(self.raw.as_ptr()),
3563                ),
3564            })
3565        }
3566    }
3567
3568    pub fn initial_horizontal_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3569        // SAFETY: as above; `&mut self` guarantees exclusivity.
3570        unsafe {
3571            crate::support::RefMut::new(AnimRefF32 {
3572                raw: core::ptr::NonNull::new_unchecked(
3573                    ffi::whiteout_m3_M3ParticleEmitter_get_initialHorizontal(self.raw.as_ptr()),
3574                ),
3575            })
3576        }
3577    }
3578
3579    /// Initial vertical spread
3580    /// Borrows the field in place — no copy, no allocation.
3581    pub fn initial_vertical(&self) -> crate::support::Ref<'_, AnimRefF32> {
3582        // SAFETY: an interior pointer into `self`, valid for this
3583        // borrow and never freed by the `Ref`.
3584        unsafe {
3585            crate::support::Ref::new(AnimRefF32 {
3586                raw: core::ptr::NonNull::new_unchecked(
3587                    ffi::whiteout_m3_M3ParticleEmitter_get_initialVertical(self.raw.as_ptr()),
3588                ),
3589            })
3590        }
3591    }
3592
3593    pub fn initial_vertical_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3594        // SAFETY: as above; `&mut self` guarantees exclusivity.
3595        unsafe {
3596            crate::support::RefMut::new(AnimRefF32 {
3597                raw: core::ptr::NonNull::new_unchecked(
3598                    ffi::whiteout_m3_M3ParticleEmitter_get_initialVertical(self.raw.as_ptr()),
3599                ),
3600            })
3601        }
3602    }
3603
3604    /// Base particle lifetime
3605    /// Borrows the field in place — no copy, no allocation.
3606    pub fn lifetime(&self) -> crate::support::Ref<'_, AnimRefF32> {
3607        // SAFETY: an interior pointer into `self`, valid for this
3608        // borrow and never freed by the `Ref`.
3609        unsafe {
3610            crate::support::Ref::new(AnimRefF32 {
3611                raw: core::ptr::NonNull::new_unchecked(
3612                    ffi::whiteout_m3_M3ParticleEmitter_get_lifetime(self.raw.as_ptr()),
3613                ),
3614            })
3615        }
3616    }
3617
3618    pub fn lifetime_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3619        // SAFETY: as above; `&mut self` guarantees exclusivity.
3620        unsafe {
3621            crate::support::RefMut::new(AnimRefF32 {
3622                raw: core::ptr::NonNull::new_unchecked(
3623                    ffi::whiteout_m3_M3ParticleEmitter_get_lifetime(self.raw.as_ptr()),
3624                ),
3625            })
3626        }
3627    }
3628
3629    /// Random lifetime variation
3630    /// Borrows the field in place — no copy, no allocation.
3631    pub fn lifetime_random(&self) -> crate::support::Ref<'_, AnimRefF32> {
3632        // SAFETY: an interior pointer into `self`, valid for this
3633        // borrow and never freed by the `Ref`.
3634        unsafe {
3635            crate::support::Ref::new(AnimRefF32 {
3636                raw: core::ptr::NonNull::new_unchecked(
3637                    ffi::whiteout_m3_M3ParticleEmitter_get_lifetimeRandom(self.raw.as_ptr()),
3638                ),
3639            })
3640        }
3641    }
3642
3643    pub fn lifetime_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
3644        // SAFETY: as above; `&mut self` guarantees exclusivity.
3645        unsafe {
3646            crate::support::RefMut::new(AnimRefF32 {
3647                raw: core::ptr::NonNull::new_unchecked(
3648                    ffi::whiteout_m3_M3ParticleEmitter_get_lifetimeRandom(self.raw.as_ptr()),
3649                ),
3650            })
3651        }
3652    }
3653
3654    /// Kill radius (particles beyond this are destroyed)
3655    pub fn kill_radius(&self) -> f32 {
3656        // SAFETY: plain scalar read through a live handle.
3657        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_killRadius(self.raw.as_ptr()) }
3658    }
3659
3660    pub fn set_kill_radius(&mut self, value: f32) {
3661        // SAFETY: plain scalar write through a live handle.
3662        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_killRadius(self.raw.as_ptr(), value) }
3663    }
3664
3665    /// Gravity X component (expected 0)
3666    pub fn gravity_x(&self) -> u32 {
3667        // SAFETY: plain scalar read through a live handle.
3668        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_gravityX(self.raw.as_ptr()) }
3669    }
3670
3671    pub fn set_gravity_x(&mut self, value: u32) {
3672        // SAFETY: plain scalar write through a live handle.
3673        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_gravityX(self.raw.as_ptr(), value) }
3674    }
3675
3676    /// Gravity Y component (expected 0)
3677    pub fn gravity_y(&self) -> u32 {
3678        // SAFETY: plain scalar read through a live handle.
3679        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_gravityY(self.raw.as_ptr()) }
3680    }
3681
3682    pub fn set_gravity_y(&mut self, value: u32) {
3683        // SAFETY: plain scalar write through a live handle.
3684        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_gravityY(self.raw.as_ptr(), value) }
3685    }
3686
3687    /// Gravity Z component
3688    pub fn gravity(&self) -> f32 {
3689        // SAFETY: plain scalar read through a live handle.
3690        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_gravity(self.raw.as_ptr()) }
3691    }
3692
3693    pub fn set_gravity(&mut self, value: f32) {
3694        // SAFETY: plain scalar write through a live handle.
3695        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_gravity(self.raw.as_ptr(), value) }
3696    }
3697
3698    /// Size midpoint time (0–1, v12+)
3699    pub fn size_mid_time(&self) -> f32 {
3700        // SAFETY: plain scalar read through a live handle.
3701        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_sizeMidTime(self.raw.as_ptr()) }
3702    }
3703
3704    pub fn set_size_mid_time(&mut self, value: f32) {
3705        // SAFETY: plain scalar write through a live handle.
3706        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_sizeMidTime(self.raw.as_ptr(), value) }
3707    }
3708
3709    /// Color midpoint time (0–1, v12+)
3710    pub fn color_mid_time(&self) -> f32 {
3711        // SAFETY: plain scalar read through a live handle.
3712        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_colorMidTime(self.raw.as_ptr()) }
3713    }
3714
3715    pub fn set_color_mid_time(&mut self, value: f32) {
3716        // SAFETY: plain scalar write through a live handle.
3717        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_colorMidTime(self.raw.as_ptr(), value) }
3718    }
3719
3720    /// Alpha midpoint time (0–1, v12+)
3721    pub fn alpha_mid_time(&self) -> f32 {
3722        // SAFETY: plain scalar read through a live handle.
3723        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_alphaMidTime(self.raw.as_ptr()) }
3724    }
3725
3726    pub fn set_alpha_mid_time(&mut self, value: f32) {
3727        // SAFETY: plain scalar write through a live handle.
3728        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_alphaMidTime(self.raw.as_ptr(), value) }
3729    }
3730
3731    /// Rotation midpoint time (0–1, v12+)
3732    pub fn rotation_mid_time(&self) -> f32 {
3733        // SAFETY: plain scalar read through a live handle.
3734        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_rotationMidTime(self.raw.as_ptr()) }
3735    }
3736
3737    pub fn set_rotation_mid_time(&mut self, value: f32) {
3738        // SAFETY: plain scalar write through a live handle.
3739        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_rotationMidTime(self.raw.as_ptr(), value) }
3740    }
3741
3742    /// Size hold time at midpoint (v14+)
3743    pub fn size_mid_hold_time(&self) -> f32 {
3744        // SAFETY: plain scalar read through a live handle.
3745        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_sizeMidHoldTime(self.raw.as_ptr()) }
3746    }
3747
3748    pub fn set_size_mid_hold_time(&mut self, value: f32) {
3749        // SAFETY: plain scalar write through a live handle.
3750        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_sizeMidHoldTime(self.raw.as_ptr(), value) }
3751    }
3752
3753    /// Color hold time at midpoint (v14+)
3754    pub fn color_mid_hold_time(&self) -> f32 {
3755        // SAFETY: plain scalar read through a live handle.
3756        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_colorMidHoldTime(self.raw.as_ptr()) }
3757    }
3758
3759    pub fn set_color_mid_hold_time(&mut self, value: f32) {
3760        // SAFETY: plain scalar write through a live handle.
3761        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_colorMidHoldTime(self.raw.as_ptr(), value) }
3762    }
3763
3764    /// Alpha hold time at midpoint (v14+)
3765    pub fn alpha_mid_hold_time(&self) -> f32 {
3766        // SAFETY: plain scalar read through a live handle.
3767        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_alphaMidHoldTime(self.raw.as_ptr()) }
3768    }
3769
3770    pub fn set_alpha_mid_hold_time(&mut self, value: f32) {
3771        // SAFETY: plain scalar write through a live handle.
3772        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_alphaMidHoldTime(self.raw.as_ptr(), value) }
3773    }
3774
3775    /// Rotation hold time at midpoint (v14+)
3776    pub fn rotation_mid_hold_time(&self) -> f32 {
3777        // SAFETY: plain scalar read through a live handle.
3778        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_rotationMidHoldTime(self.raw.as_ptr()) }
3779    }
3780
3781    pub fn set_rotation_mid_hold_time(&mut self, value: f32) {
3782        // SAFETY: plain scalar write through a live handle.
3783        unsafe {
3784            ffi::whiteout_m3_M3ParticleEmitter_set_rotationMidHoldTime(self.raw.as_ptr(), value)
3785        }
3786    }
3787
3788    /// Size curve (start, mid, end)
3789    /// Borrows the field in place — no copy, no allocation.
3790    pub fn size_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
3791        // SAFETY: an interior pointer into `self`, valid for this
3792        // borrow and never freed by the `Ref`.
3793        unsafe {
3794            crate::support::Ref::new(AnimRefVector3f {
3795                raw: core::ptr::NonNull::new_unchecked(
3796                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeAnimation(self.raw.as_ptr()),
3797                ),
3798            })
3799        }
3800    }
3801
3802    pub fn size_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
3803        // SAFETY: as above; `&mut self` guarantees exclusivity.
3804        unsafe {
3805            crate::support::RefMut::new(AnimRefVector3f {
3806                raw: core::ptr::NonNull::new_unchecked(
3807                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeAnimation(self.raw.as_ptr()),
3808                ),
3809            })
3810        }
3811    }
3812
3813    /// Rotation curve (start, mid, end)
3814    /// Borrows the field in place — no copy, no allocation.
3815    pub fn rotation_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
3816        // SAFETY: an interior pointer into `self`, valid for this
3817        // borrow and never freed by the `Ref`.
3818        unsafe {
3819            crate::support::Ref::new(AnimRefVector3f {
3820                raw: core::ptr::NonNull::new_unchecked(
3821                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationAnimation(self.raw.as_ptr()),
3822                ),
3823            })
3824        }
3825    }
3826
3827    pub fn rotation_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
3828        // SAFETY: as above; `&mut self` guarantees exclusivity.
3829        unsafe {
3830            crate::support::RefMut::new(AnimRefVector3f {
3831                raw: core::ptr::NonNull::new_unchecked(
3832                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationAnimation(self.raw.as_ptr()),
3833                ),
3834            })
3835        }
3836    }
3837
3838    /// Color at birth
3839    /// Borrows the field in place — no copy, no allocation.
3840    pub fn color_start(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
3841        // SAFETY: an interior pointer into `self`, valid for this
3842        // borrow and never freed by the `Ref`.
3843        unsafe {
3844            crate::support::Ref::new(AnimRefM3ColorBGRA {
3845                raw: core::ptr::NonNull::new_unchecked(
3846                    ffi::whiteout_m3_M3ParticleEmitter_get_colorStart(self.raw.as_ptr()),
3847                ),
3848            })
3849        }
3850    }
3851
3852    pub fn color_start_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
3853        // SAFETY: as above; `&mut self` guarantees exclusivity.
3854        unsafe {
3855            crate::support::RefMut::new(AnimRefM3ColorBGRA {
3856                raw: core::ptr::NonNull::new_unchecked(
3857                    ffi::whiteout_m3_M3ParticleEmitter_get_colorStart(self.raw.as_ptr()),
3858                ),
3859            })
3860        }
3861    }
3862
3863    /// Color at midpoint
3864    /// Borrows the field in place — no copy, no allocation.
3865    pub fn color_mid(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
3866        // SAFETY: an interior pointer into `self`, valid for this
3867        // borrow and never freed by the `Ref`.
3868        unsafe {
3869            crate::support::Ref::new(AnimRefM3ColorBGRA {
3870                raw: core::ptr::NonNull::new_unchecked(
3871                    ffi::whiteout_m3_M3ParticleEmitter_get_colorMid(self.raw.as_ptr()),
3872                ),
3873            })
3874        }
3875    }
3876
3877    pub fn color_mid_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
3878        // SAFETY: as above; `&mut self` guarantees exclusivity.
3879        unsafe {
3880            crate::support::RefMut::new(AnimRefM3ColorBGRA {
3881                raw: core::ptr::NonNull::new_unchecked(
3882                    ffi::whiteout_m3_M3ParticleEmitter_get_colorMid(self.raw.as_ptr()),
3883                ),
3884            })
3885        }
3886    }
3887
3888    /// Color at death
3889    /// Borrows the field in place — no copy, no allocation.
3890    pub fn color_end(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
3891        // SAFETY: an interior pointer into `self`, valid for this
3892        // borrow and never freed by the `Ref`.
3893        unsafe {
3894            crate::support::Ref::new(AnimRefM3ColorBGRA {
3895                raw: core::ptr::NonNull::new_unchecked(
3896                    ffi::whiteout_m3_M3ParticleEmitter_get_colorEnd(self.raw.as_ptr()),
3897                ),
3898            })
3899        }
3900    }
3901
3902    pub fn color_end_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
3903        // SAFETY: as above; `&mut self` guarantees exclusivity.
3904        unsafe {
3905            crate::support::RefMut::new(AnimRefM3ColorBGRA {
3906                raw: core::ptr::NonNull::new_unchecked(
3907                    ffi::whiteout_m3_M3ParticleEmitter_get_colorEnd(self.raw.as_ptr()),
3908                ),
3909            })
3910        }
3911    }
3912
3913    /// Air drag coefficient
3914    pub fn drag(&self) -> f32 {
3915        // SAFETY: plain scalar read through a live handle.
3916        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_drag(self.raw.as_ptr()) }
3917    }
3918
3919    pub fn set_drag(&mut self, value: f32) {
3920        // SAFETY: plain scalar write through a live handle.
3921        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_drag(self.raw.as_ptr(), value) }
3922    }
3923
3924    /// Particle mass
3925    pub fn mass(&self) -> f32 {
3926        // SAFETY: plain scalar read through a live handle.
3927        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_mass(self.raw.as_ptr()) }
3928    }
3929
3930    pub fn set_mass(&mut self, value: f32) {
3931        // SAFETY: plain scalar write through a live handle.
3932        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_mass(self.raw.as_ptr(), value) }
3933    }
3934
3935    /// Random mass variation multiplier
3936    pub fn mass_random(&self) -> f32 {
3937        // SAFETY: plain scalar read through a live handle.
3938        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_massRandom(self.raw.as_ptr()) }
3939    }
3940
3941    pub fn set_mass_random(&mut self, value: f32) {
3942        // SAFETY: plain scalar write through a live handle.
3943        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_massRandom(self.raw.as_ptr(), value) }
3944    }
3945
3946    /// Mass–size coupling (v12+)
3947    pub fn mass_size_multiplier(&self) -> f32 {
3948        // SAFETY: plain scalar read through a live handle.
3949        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_massSizeMultiplier(self.raw.as_ptr()) }
3950    }
3951
3952    pub fn set_mass_size_multiplier(&mut self, value: f32) {
3953        // SAFETY: plain scalar write through a live handle.
3954        unsafe {
3955            ffi::whiteout_m3_M3ParticleEmitter_set_massSizeMultiplier(self.raw.as_ptr(), value)
3956        }
3957    }
3958
3959    /// Local force channel bitmask
3960    pub fn local_forces(&self) -> u16 {
3961        // SAFETY: plain scalar read through a live handle.
3962        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_localForces(self.raw.as_ptr()) }
3963    }
3964
3965    pub fn set_local_forces(&mut self, value: u16) {
3966        // SAFETY: plain scalar write through a live handle.
3967        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_localForces(self.raw.as_ptr(), value) }
3968    }
3969
3970    /// World force channel bitmask
3971    pub fn world_forces(&self) -> u16 {
3972        // SAFETY: plain scalar read through a live handle.
3973        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_worldForces(self.raw.as_ptr()) }
3974    }
3975
3976    pub fn set_world_forces(&mut self, value: u16) {
3977        // SAFETY: plain scalar write through a live handle.
3978        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_worldForces(self.raw.as_ptr(), value) }
3979    }
3980
3981    /// Fallback local force channels
3982    pub fn local_forces_fallback(&self) -> u16 {
3983        // SAFETY: plain scalar read through a live handle.
3984        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_localForcesFallback(self.raw.as_ptr()) }
3985    }
3986
3987    pub fn set_local_forces_fallback(&mut self, value: u16) {
3988        // SAFETY: plain scalar write through a live handle.
3989        unsafe {
3990            ffi::whiteout_m3_M3ParticleEmitter_set_localForcesFallback(self.raw.as_ptr(), value)
3991        }
3992    }
3993
3994    /// Fallback world force channels
3995    pub fn world_forces_fallback(&self) -> u16 {
3996        // SAFETY: plain scalar read through a live handle.
3997        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_worldForcesFallback(self.raw.as_ptr()) }
3998    }
3999
4000    pub fn set_world_forces_fallback(&mut self, value: u16) {
4001        // SAFETY: plain scalar write through a live handle.
4002        unsafe {
4003            ffi::whiteout_m3_M3ParticleEmitter_set_worldForcesFallback(self.raw.as_ptr(), value)
4004        }
4005    }
4006
4007    /// World force mass multiplier (v24+)
4008    pub fn world_forces_mass_multiplier(&self) -> f32 {
4009        // SAFETY: plain scalar read through a live handle.
4010        unsafe {
4011            ffi::whiteout_m3_M3ParticleEmitter_get_worldForcesMassMultiplier(self.raw.as_ptr())
4012        }
4013    }
4014
4015    pub fn set_world_forces_mass_multiplier(&mut self, value: f32) {
4016        // SAFETY: plain scalar write through a live handle.
4017        unsafe {
4018            ffi::whiteout_m3_M3ParticleEmitter_set_worldForcesMassMultiplier(
4019                self.raw.as_ptr(),
4020                value,
4021            )
4022        }
4023    }
4024
4025    /// Noise displacement amplitude
4026    pub fn noise_amplitude(&self) -> f32 {
4027        // SAFETY: plain scalar read through a live handle.
4028        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_noiseAmplitude(self.raw.as_ptr()) }
4029    }
4030
4031    pub fn set_noise_amplitude(&mut self, value: f32) {
4032        // SAFETY: plain scalar write through a live handle.
4033        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_noiseAmplitude(self.raw.as_ptr(), value) }
4034    }
4035
4036    /// Noise spatial frequency
4037    pub fn noise_frequency(&self) -> f32 {
4038        // SAFETY: plain scalar read through a live handle.
4039        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_noiseFrequency(self.raw.as_ptr()) }
4040    }
4041
4042    pub fn set_noise_frequency(&mut self, value: f32) {
4043        // SAFETY: plain scalar write through a live handle.
4044        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_noiseFrequency(self.raw.as_ptr(), value) }
4045    }
4046
4047    /// Noise temporal coherence
4048    pub fn noise_coherence(&self) -> f32 {
4049        // SAFETY: plain scalar read through a live handle.
4050        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_noiseCoherence(self.raw.as_ptr()) }
4051    }
4052
4053    pub fn set_noise_coherence(&mut self, value: f32) {
4054        // SAFETY: plain scalar write through a live handle.
4055        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_noiseCoherence(self.raw.as_ptr(), value) }
4056    }
4057
4058    /// Noise edge sharpness
4059    pub fn noise_edge(&self) -> f32 {
4060        // SAFETY: plain scalar read through a live handle.
4061        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_noiseEdge(self.raw.as_ptr()) }
4062    }
4063
4064    pub fn set_noise_edge(&mut self, value: f32) {
4065        // SAFETY: plain scalar write through a live handle.
4066        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_noiseEdge(self.raw.as_ptr(), value) }
4067    }
4068
4069    /// Index + length (v11+)
4070    pub fn index_plus_length(&self) -> u32 {
4071        // SAFETY: plain scalar read through a live handle.
4072        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_indexPlusLength(self.raw.as_ptr()) }
4073    }
4074
4075    pub fn set_index_plus_length(&mut self, value: u32) {
4076        // SAFETY: plain scalar write through a live handle.
4077        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_indexPlusLength(self.raw.as_ptr(), value) }
4078    }
4079
4080    /// Maximum live particle count
4081    pub fn max_particles(&self) -> u32 {
4082        // SAFETY: plain scalar read through a live handle.
4083        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_maxParticles(self.raw.as_ptr()) }
4084    }
4085
4086    pub fn set_max_particles(&mut self, value: u32) {
4087        // SAFETY: plain scalar write through a live handle.
4088        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_maxParticles(self.raw.as_ptr(), value) }
4089    }
4090
4091    /// Animated emission rate (particles/sec)
4092    /// Borrows the field in place — no copy, no allocation.
4093    pub fn emission_rate(&self) -> crate::support::Ref<'_, AnimRefF32> {
4094        // SAFETY: an interior pointer into `self`, valid for this
4095        // borrow and never freed by the `Ref`.
4096        unsafe {
4097            crate::support::Ref::new(AnimRefF32 {
4098                raw: core::ptr::NonNull::new_unchecked(
4099                    ffi::whiteout_m3_M3ParticleEmitter_get_emissionRate(self.raw.as_ptr()),
4100                ),
4101            })
4102        }
4103    }
4104
4105    pub fn emission_rate_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4106        // SAFETY: as above; `&mut self` guarantees exclusivity.
4107        unsafe {
4108            crate::support::RefMut::new(AnimRefF32 {
4109                raw: core::ptr::NonNull::new_unchecked(
4110                    ffi::whiteout_m3_M3ParticleEmitter_get_emissionRate(self.raw.as_ptr()),
4111                ),
4112            })
4113        }
4114    }
4115
4116    /// Emission shape
4117    pub fn emitter_shape(&self) -> EmitterShape {
4118        // SAFETY: scalar read; the discriminant is validated below.
4119        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_emitterShape(self.raw.as_ptr()) }
4120            .try_into()
4121            .expect("unknown enum discriminant from the native library")
4122    }
4123
4124    pub fn set_emitter_shape(&mut self, value: EmitterShape) {
4125        // SAFETY: scalar write through a live handle.
4126        unsafe {
4127            ffi::whiteout_m3_M3ParticleEmitter_set_emitterShape(self.raw.as_ptr(), value as i32)
4128        }
4129    }
4130
4131    /// Animated outer shape dimensions
4132    /// Borrows the field in place — no copy, no allocation.
4133    pub fn shape_outer(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
4134        // SAFETY: an interior pointer into `self`, valid for this
4135        // borrow and never freed by the `Ref`.
4136        unsafe {
4137            crate::support::Ref::new(AnimRefVector3f {
4138                raw: core::ptr::NonNull::new_unchecked(
4139                    ffi::whiteout_m3_M3ParticleEmitter_get_shapeOuter(self.raw.as_ptr()),
4140                ),
4141            })
4142        }
4143    }
4144
4145    pub fn shape_outer_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
4146        // SAFETY: as above; `&mut self` guarantees exclusivity.
4147        unsafe {
4148            crate::support::RefMut::new(AnimRefVector3f {
4149                raw: core::ptr::NonNull::new_unchecked(
4150                    ffi::whiteout_m3_M3ParticleEmitter_get_shapeOuter(self.raw.as_ptr()),
4151                ),
4152            })
4153        }
4154    }
4155
4156    /// Animated inner shape dimensions
4157    /// Borrows the field in place — no copy, no allocation.
4158    pub fn shape_inner(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
4159        // SAFETY: an interior pointer into `self`, valid for this
4160        // borrow and never freed by the `Ref`.
4161        unsafe {
4162            crate::support::Ref::new(AnimRefVector3f {
4163                raw: core::ptr::NonNull::new_unchecked(
4164                    ffi::whiteout_m3_M3ParticleEmitter_get_shapeInner(self.raw.as_ptr()),
4165                ),
4166            })
4167        }
4168    }
4169
4170    pub fn shape_inner_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
4171        // SAFETY: as above; `&mut self` guarantees exclusivity.
4172        unsafe {
4173            crate::support::RefMut::new(AnimRefVector3f {
4174                raw: core::ptr::NonNull::new_unchecked(
4175                    ffi::whiteout_m3_M3ParticleEmitter_get_shapeInner(self.raw.as_ptr()),
4176                ),
4177            })
4178        }
4179    }
4180
4181    /// Animated outer radius
4182    /// Borrows the field in place — no copy, no allocation.
4183    pub fn outer_radius(&self) -> crate::support::Ref<'_, AnimRefF32> {
4184        // SAFETY: an interior pointer into `self`, valid for this
4185        // borrow and never freed by the `Ref`.
4186        unsafe {
4187            crate::support::Ref::new(AnimRefF32 {
4188                raw: core::ptr::NonNull::new_unchecked(
4189                    ffi::whiteout_m3_M3ParticleEmitter_get_outerRadius(self.raw.as_ptr()),
4190                ),
4191            })
4192        }
4193    }
4194
4195    pub fn outer_radius_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4196        // SAFETY: as above; `&mut self` guarantees exclusivity.
4197        unsafe {
4198            crate::support::RefMut::new(AnimRefF32 {
4199                raw: core::ptr::NonNull::new_unchecked(
4200                    ffi::whiteout_m3_M3ParticleEmitter_get_outerRadius(self.raw.as_ptr()),
4201                ),
4202            })
4203        }
4204    }
4205
4206    /// Animated inner radius
4207    /// Borrows the field in place — no copy, no allocation.
4208    pub fn inner_radius(&self) -> crate::support::Ref<'_, AnimRefF32> {
4209        // SAFETY: an interior pointer into `self`, valid for this
4210        // borrow and never freed by the `Ref`.
4211        unsafe {
4212            crate::support::Ref::new(AnimRefF32 {
4213                raw: core::ptr::NonNull::new_unchecked(
4214                    ffi::whiteout_m3_M3ParticleEmitter_get_innerRadius(self.raw.as_ptr()),
4215                ),
4216            })
4217        }
4218    }
4219
4220    pub fn inner_radius_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4221        // SAFETY: as above; `&mut self` guarantees exclusivity.
4222        unsafe {
4223            crate::support::RefMut::new(AnimRefF32 {
4224                raw: core::ptr::NonNull::new_unchecked(
4225                    ffi::whiteout_m3_M3ParticleEmitter_get_innerRadius(self.raw.as_ptr()),
4226                ),
4227            })
4228        }
4229    }
4230
4231    /// Shape region indices (U32_, v14+), which mesh region from div to use
4232    /// Zero-copy view of the underlying `std::vector`.
4233    pub fn shape_regions(&self) -> &[u32] {
4234        // SAFETY: `_data`/`_count` describe one contiguous C++
4235        // allocation, borrowed for as long as `self` is.
4236        unsafe {
4237            let n = ffi::whiteout_m3_M3ParticleEmitter_get_shapeRegions_count(self.raw.as_ptr());
4238            let p = ffi::whiteout_m3_M3ParticleEmitter_get_shapeRegions_data(self.raw.as_ptr());
4239            if p.is_null() || n == 0 {
4240                &[]
4241            } else {
4242                core::slice::from_raw_parts(p, n)
4243            }
4244        }
4245    }
4246
4247    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
4248    pub fn shape_regions_mut(&mut self) -> &mut [u32] {
4249        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
4250        unsafe {
4251            let n = ffi::whiteout_m3_M3ParticleEmitter_get_shapeRegions_count(self.raw.as_ptr());
4252            let p = ffi::whiteout_m3_M3ParticleEmitter_get_shapeRegions_data(self.raw.as_ptr())
4253                as *mut u32;
4254            if p.is_null() || n == 0 {
4255                &mut []
4256            } else {
4257                core::slice::from_raw_parts_mut(p, n)
4258            }
4259        }
4260    }
4261
4262    pub fn set_shape_regions(&mut self, values: &[u32]) {
4263        // SAFETY: the native side copies `values` before returning.
4264        unsafe {
4265            ffi::whiteout_m3_M3ParticleEmitter_assign_shapeRegions(
4266                self.raw.as_ptr(),
4267                values.as_ptr() as *const _,
4268                values.len(),
4269            )
4270        }
4271    }
4272
4273    pub fn resize_shape_regions(&mut self, count: usize) {
4274        // SAFETY: reallocation is safe here precisely because
4275        // `&mut self` means no slice borrow is outstanding.
4276        unsafe { ffi::whiteout_m3_M3ParticleEmitter_resize_shapeRegions(self.raw.as_ptr(), count) }
4277    }
4278
4279    /// Velocity randomization type
4280    pub fn velocity_type(&self) -> u32 {
4281        // SAFETY: plain scalar read through a live handle.
4282        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_velocityType(self.raw.as_ptr()) }
4283    }
4284
4285    pub fn set_velocity_type(&mut self, value: u32) {
4286        // SAFETY: plain scalar write through a live handle.
4287        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_velocityType(self.raw.as_ptr(), value) }
4288    }
4289
4290    /// Enable size randomization
4291    pub fn size_random_enable(&self) -> u32 {
4292        // SAFETY: plain scalar read through a live handle.
4293        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_sizeRandomEnable(self.raw.as_ptr()) }
4294    }
4295
4296    pub fn set_size_random_enable(&mut self, value: u32) {
4297        // SAFETY: plain scalar write through a live handle.
4298        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_sizeRandomEnable(self.raw.as_ptr(), value) }
4299    }
4300
4301    /// Random size curve
4302    /// Borrows the field in place — no copy, no allocation.
4303    pub fn size_random_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
4304        // SAFETY: an interior pointer into `self`, valid for this
4305        // borrow and never freed by the `Ref`.
4306        unsafe {
4307            crate::support::Ref::new(AnimRefVector3f {
4308                raw: core::ptr::NonNull::new_unchecked(
4309                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeRandomAnimation(self.raw.as_ptr()),
4310                ),
4311            })
4312        }
4313    }
4314
4315    pub fn size_random_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
4316        // SAFETY: as above; `&mut self` guarantees exclusivity.
4317        unsafe {
4318            crate::support::RefMut::new(AnimRefVector3f {
4319                raw: core::ptr::NonNull::new_unchecked(
4320                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeRandomAnimation(self.raw.as_ptr()),
4321                ),
4322            })
4323        }
4324    }
4325
4326    /// Enable rotation randomization
4327    pub fn rotation_random_enable(&self) -> u32 {
4328        // SAFETY: plain scalar read through a live handle.
4329        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_rotationRandomEnable(self.raw.as_ptr()) }
4330    }
4331
4332    pub fn set_rotation_random_enable(&mut self, value: u32) {
4333        // SAFETY: plain scalar write through a live handle.
4334        unsafe {
4335            ffi::whiteout_m3_M3ParticleEmitter_set_rotationRandomEnable(self.raw.as_ptr(), value)
4336        }
4337    }
4338
4339    /// Random rotation curve
4340    /// Borrows the field in place — no copy, no allocation.
4341    pub fn rotation_random_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
4342        // SAFETY: an interior pointer into `self`, valid for this
4343        // borrow and never freed by the `Ref`.
4344        unsafe {
4345            crate::support::Ref::new(AnimRefVector3f {
4346                raw: core::ptr::NonNull::new_unchecked(
4347                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationRandomAnimation(
4348                        self.raw.as_ptr(),
4349                    ),
4350                ),
4351            })
4352        }
4353    }
4354
4355    pub fn rotation_random_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
4356        // SAFETY: as above; `&mut self` guarantees exclusivity.
4357        unsafe {
4358            crate::support::RefMut::new(AnimRefVector3f {
4359                raw: core::ptr::NonNull::new_unchecked(
4360                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationRandomAnimation(
4361                        self.raw.as_ptr(),
4362                    ),
4363                ),
4364            })
4365        }
4366    }
4367
4368    /// Enable color randomization
4369    pub fn color_random_enable(&self) -> u32 {
4370        // SAFETY: plain scalar read through a live handle.
4371        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_colorRandomEnable(self.raw.as_ptr()) }
4372    }
4373
4374    pub fn set_color_random_enable(&mut self, value: u32) {
4375        // SAFETY: plain scalar write through a live handle.
4376        unsafe {
4377            ffi::whiteout_m3_M3ParticleEmitter_set_colorRandomEnable(self.raw.as_ptr(), value)
4378        }
4379    }
4380
4381    /// Random color at birth
4382    /// Borrows the field in place — no copy, no allocation.
4383    pub fn color_start_random(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
4384        // SAFETY: an interior pointer into `self`, valid for this
4385        // borrow and never freed by the `Ref`.
4386        unsafe {
4387            crate::support::Ref::new(AnimRefM3ColorBGRA {
4388                raw: core::ptr::NonNull::new_unchecked(
4389                    ffi::whiteout_m3_M3ParticleEmitter_get_colorStartRandom(self.raw.as_ptr()),
4390                ),
4391            })
4392        }
4393    }
4394
4395    pub fn color_start_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
4396        // SAFETY: as above; `&mut self` guarantees exclusivity.
4397        unsafe {
4398            crate::support::RefMut::new(AnimRefM3ColorBGRA {
4399                raw: core::ptr::NonNull::new_unchecked(
4400                    ffi::whiteout_m3_M3ParticleEmitter_get_colorStartRandom(self.raw.as_ptr()),
4401                ),
4402            })
4403        }
4404    }
4405
4406    /// Random color at midpoint
4407    /// Borrows the field in place — no copy, no allocation.
4408    pub fn color_mid_random(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
4409        // SAFETY: an interior pointer into `self`, valid for this
4410        // borrow and never freed by the `Ref`.
4411        unsafe {
4412            crate::support::Ref::new(AnimRefM3ColorBGRA {
4413                raw: core::ptr::NonNull::new_unchecked(
4414                    ffi::whiteout_m3_M3ParticleEmitter_get_colorMidRandom(self.raw.as_ptr()),
4415                ),
4416            })
4417        }
4418    }
4419
4420    pub fn color_mid_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
4421        // SAFETY: as above; `&mut self` guarantees exclusivity.
4422        unsafe {
4423            crate::support::RefMut::new(AnimRefM3ColorBGRA {
4424                raw: core::ptr::NonNull::new_unchecked(
4425                    ffi::whiteout_m3_M3ParticleEmitter_get_colorMidRandom(self.raw.as_ptr()),
4426                ),
4427            })
4428        }
4429    }
4430
4431    /// Random color at death
4432    /// Borrows the field in place — no copy, no allocation.
4433    pub fn color_end_random(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
4434        // SAFETY: an interior pointer into `self`, valid for this
4435        // borrow and never freed by the `Ref`.
4436        unsafe {
4437            crate::support::Ref::new(AnimRefM3ColorBGRA {
4438                raw: core::ptr::NonNull::new_unchecked(
4439                    ffi::whiteout_m3_M3ParticleEmitter_get_colorEndRandom(self.raw.as_ptr()),
4440                ),
4441            })
4442        }
4443    }
4444
4445    pub fn color_end_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
4446        // SAFETY: as above; `&mut self` guarantees exclusivity.
4447        unsafe {
4448            crate::support::RefMut::new(AnimRefM3ColorBGRA {
4449                raw: core::ptr::NonNull::new_unchecked(
4450                    ffi::whiteout_m3_M3ParticleEmitter_get_colorEndRandom(self.raw.as_ptr()),
4451                ),
4452            })
4453        }
4454    }
4455
4456    /// Enable alpha randomization
4457    pub fn alpha_random_enable(&self) -> u32 {
4458        // SAFETY: plain scalar read through a live handle.
4459        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_alphaRandomEnable(self.raw.as_ptr()) }
4460    }
4461
4462    pub fn set_alpha_random_enable(&mut self, value: u32) {
4463        // SAFETY: plain scalar write through a live handle.
4464        unsafe {
4465            ffi::whiteout_m3_M3ParticleEmitter_set_alphaRandomEnable(self.raw.as_ptr(), value)
4466        }
4467    }
4468
4469    /// Animated squirt burst count
4470    /// Borrows the field in place — no copy, no allocation.
4471    pub fn squirt_amount(&self) -> crate::support::Ref<'_, AnimRefU16> {
4472        // SAFETY: an interior pointer into `self`, valid for this
4473        // borrow and never freed by the `Ref`.
4474        unsafe {
4475            crate::support::Ref::new(AnimRefU16 {
4476                raw: core::ptr::NonNull::new_unchecked(
4477                    ffi::whiteout_m3_M3ParticleEmitter_get_squirtAmount(self.raw.as_ptr()),
4478                ),
4479            })
4480        }
4481    }
4482
4483    pub fn squirt_amount_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU16> {
4484        // SAFETY: as above; `&mut self` guarantees exclusivity.
4485        unsafe {
4486            crate::support::RefMut::new(AnimRefU16 {
4487                raw: core::ptr::NonNull::new_unchecked(
4488                    ffi::whiteout_m3_M3ParticleEmitter_get_squirtAmount(self.raw.as_ptr()),
4489                ),
4490            })
4491        }
4492    }
4493
4494    /// Flipbook start initial frame index
4495    pub fn flipbook_start_init_index(&self) -> u8 {
4496        // SAFETY: plain scalar read through a live handle.
4497        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookStartInitIndex(self.raw.as_ptr()) }
4498    }
4499
4500    pub fn set_flipbook_start_init_index(&mut self, value: u8) {
4501        // SAFETY: plain scalar write through a live handle.
4502        unsafe {
4503            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookStartInitIndex(self.raw.as_ptr(), value)
4504        }
4505    }
4506
4507    /// Flipbook start stop frame index
4508    pub fn flipbook_start_stop_index(&self) -> u8 {
4509        // SAFETY: plain scalar read through a live handle.
4510        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookStartStopIndex(self.raw.as_ptr()) }
4511    }
4512
4513    pub fn set_flipbook_start_stop_index(&mut self, value: u8) {
4514        // SAFETY: plain scalar write through a live handle.
4515        unsafe {
4516            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookStartStopIndex(self.raw.as_ptr(), value)
4517        }
4518    }
4519
4520    /// Flipbook end initial frame index
4521    pub fn flipbook_end_init_index(&self) -> u8 {
4522        // SAFETY: plain scalar read through a live handle.
4523        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookEndInitIndex(self.raw.as_ptr()) }
4524    }
4525
4526    pub fn set_flipbook_end_init_index(&mut self, value: u8) {
4527        // SAFETY: plain scalar write through a live handle.
4528        unsafe {
4529            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookEndInitIndex(self.raw.as_ptr(), value)
4530        }
4531    }
4532
4533    /// Flipbook end stop frame index
4534    pub fn flipbook_end_stop_index(&self) -> u8 {
4535        // SAFETY: plain scalar read through a live handle.
4536        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookEndStopIndex(self.raw.as_ptr()) }
4537    }
4538
4539    pub fn set_flipbook_end_stop_index(&mut self, value: u8) {
4540        // SAFETY: plain scalar write through a live handle.
4541        unsafe {
4542            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookEndStopIndex(self.raw.as_ptr(), value)
4543        }
4544    }
4545
4546    /// Flipbook midpoint time (0–1)
4547    pub fn flipbook_mid_time(&self) -> f32 {
4548        // SAFETY: plain scalar read through a live handle.
4549        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookMidTime(self.raw.as_ptr()) }
4550    }
4551
4552    pub fn set_flipbook_mid_time(&mut self, value: f32) {
4553        // SAFETY: plain scalar write through a live handle.
4554        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_flipbookMidTime(self.raw.as_ptr(), value) }
4555    }
4556
4557    /// Flipbook grid columns
4558    pub fn flipbook_columns(&self) -> u16 {
4559        // SAFETY: plain scalar read through a live handle.
4560        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookColumns(self.raw.as_ptr()) }
4561    }
4562
4563    pub fn set_flipbook_columns(&mut self, value: u16) {
4564        // SAFETY: plain scalar write through a live handle.
4565        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_flipbookColumns(self.raw.as_ptr(), value) }
4566    }
4567
4568    /// Flipbook grid rows
4569    pub fn flipbook_rows(&self) -> u16 {
4570        // SAFETY: plain scalar read through a live handle.
4571        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookRows(self.raw.as_ptr()) }
4572    }
4573
4574    pub fn set_flipbook_rows(&mut self, value: u16) {
4575        // SAFETY: plain scalar write through a live handle.
4576        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_flipbookRows(self.raw.as_ptr(), value) }
4577    }
4578
4579    /// Column fraction (v12+)
4580    pub fn flipbook_column_fraction(&self) -> f32 {
4581        // SAFETY: plain scalar read through a live handle.
4582        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookColumnFraction(self.raw.as_ptr()) }
4583    }
4584
4585    pub fn set_flipbook_column_fraction(&mut self, value: f32) {
4586        // SAFETY: plain scalar write through a live handle.
4587        unsafe {
4588            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookColumnFraction(self.raw.as_ptr(), value)
4589        }
4590    }
4591
4592    /// Row fraction (v12+)
4593    pub fn flipbook_row_fraction(&self) -> f32 {
4594        // SAFETY: plain scalar read through a live handle.
4595        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flipbookRowFraction(self.raw.as_ptr()) }
4596    }
4597
4598    pub fn set_flipbook_row_fraction(&mut self, value: f32) {
4599        // SAFETY: plain scalar write through a live handle.
4600        unsafe {
4601            ffi::whiteout_m3_M3ParticleEmitter_set_flipbookRowFraction(self.raw.as_ptr(), value)
4602        }
4603    }
4604
4605    /// Bounce coefficient
4606    pub fn bounce(&self) -> f32 {
4607        // SAFETY: plain scalar read through a live handle.
4608        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_bounce(self.raw.as_ptr()) }
4609    }
4610
4611    pub fn set_bounce(&mut self, value: f32) {
4612        // SAFETY: plain scalar write through a live handle.
4613        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_bounce(self.raw.as_ptr(), value) }
4614    }
4615
4616    /// Friction coefficient
4617    pub fn friction(&self) -> f32 {
4618        // SAFETY: plain scalar read through a live handle.
4619        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_friction(self.raw.as_ptr()) }
4620    }
4621
4622    pub fn set_friction(&mut self, value: f32) {
4623        // SAFETY: plain scalar write through a live handle.
4624        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_friction(self.raw.as_ptr(), value) }
4625    }
4626
4627    /// Emitter index to spawn on collision (-1 = none)
4628    pub fn collision_spawn_index(&self) -> i32 {
4629        // SAFETY: plain scalar read through a live handle.
4630        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionSpawnIndex(self.raw.as_ptr()) }
4631    }
4632
4633    pub fn set_collision_spawn_index(&mut self, value: i32) {
4634        // SAFETY: plain scalar write through a live handle.
4635        unsafe {
4636            ffi::whiteout_m3_M3ParticleEmitter_set_collisionSpawnIndex(self.raw.as_ptr(), value)
4637        }
4638    }
4639
4640    /// Minimum spawn count on collision
4641    pub fn collision_spawn_min(&self) -> u32 {
4642        // SAFETY: plain scalar read through a live handle.
4643        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionSpawnMin(self.raw.as_ptr()) }
4644    }
4645
4646    pub fn set_collision_spawn_min(&mut self, value: u32) {
4647        // SAFETY: plain scalar write through a live handle.
4648        unsafe {
4649            ffi::whiteout_m3_M3ParticleEmitter_set_collisionSpawnMin(self.raw.as_ptr(), value)
4650        }
4651    }
4652
4653    /// Maximum spawn count on collision
4654    pub fn collision_spawn_max(&self) -> u32 {
4655        // SAFETY: plain scalar read through a live handle.
4656        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionSpawnMax(self.raw.as_ptr()) }
4657    }
4658
4659    pub fn set_collision_spawn_max(&mut self, value: u32) {
4660        // SAFETY: plain scalar write through a live handle.
4661        unsafe {
4662            ffi::whiteout_m3_M3ParticleEmitter_set_collisionSpawnMax(self.raw.as_ptr(), value)
4663        }
4664    }
4665
4666    /// Spawn probability on collision
4667    pub fn collision_spawn_chance(&self) -> f32 {
4668        // SAFETY: plain scalar read through a live handle.
4669        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionSpawnChance(self.raw.as_ptr()) }
4670    }
4671
4672    pub fn set_collision_spawn_chance(&mut self, value: f32) {
4673        // SAFETY: plain scalar write through a live handle.
4674        unsafe {
4675            ffi::whiteout_m3_M3ParticleEmitter_set_collisionSpawnChance(self.raw.as_ptr(), value)
4676        }
4677    }
4678
4679    /// Spawn energy transfer
4680    pub fn collision_spawn_energy(&self) -> f32 {
4681        // SAFETY: plain scalar read through a live handle.
4682        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionSpawnEnergy(self.raw.as_ptr()) }
4683    }
4684
4685    pub fn set_collision_spawn_energy(&mut self, value: f32) {
4686        // SAFETY: plain scalar write through a live handle.
4687        unsafe {
4688            ffi::whiteout_m3_M3ParticleEmitter_set_collisionSpawnEnergy(self.raw.as_ptr(), value)
4689        }
4690    }
4691
4692    /// Die after N bounces
4693    pub fn collision_die_bounce(&self) -> u32 {
4694        // SAFETY: plain scalar read through a live handle.
4695        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_collisionDieBounce(self.raw.as_ptr()) }
4696    }
4697
4698    pub fn set_collision_die_bounce(&mut self, value: u32) {
4699        // SAFETY: plain scalar write through a live handle.
4700        unsafe {
4701            ffi::whiteout_m3_M3ParticleEmitter_set_collisionDieBounce(self.raw.as_ptr(), value)
4702        }
4703    }
4704
4705    /// Visual type → shader b_iInstanceType
4706    pub fn instance_type(&self) -> ParticleInstanceType {
4707        // SAFETY: scalar read; the discriminant is validated below.
4708        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_instanceType(self.raw.as_ptr()) }
4709            .try_into()
4710            .expect("unknown enum discriminant from the native library")
4711    }
4712
4713    pub fn set_instance_type(&mut self, value: ParticleInstanceType) {
4714        // SAFETY: scalar write through a live handle.
4715        unsafe {
4716            ffi::whiteout_m3_M3ParticleEmitter_set_instanceType(self.raw.as_ptr(), value as i32)
4717        }
4718    }
4719
4720    /// Tail length for Tail/Trail types
4721    pub fn tail_length(&self) -> f32 {
4722        // SAFETY: plain scalar read through a live handle.
4723        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_tailLength(self.raw.as_ptr()) }
4724    }
4725
4726    pub fn set_tail_length(&mut self, value: f32) {
4727        // SAFETY: plain scalar write through a live handle.
4728        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_tailLength(self.raw.as_ptr(), value) }
4729    }
4730
4731    /// Instance orientation angles
4732    pub fn instance_angle(&self) -> crate::math::Vector3f {
4733        // SAFETY: the getter returns an interior pointer to a
4734        // layout-identical POD; we copy it out immediately.
4735        unsafe {
4736            *(ffi::whiteout_m3_M3ParticleEmitter_get_instanceAngle(self.raw.as_ptr())
4737                as *const crate::math::Vector3f)
4738        }
4739    }
4740
4741    pub fn set_instance_angle(&mut self, value: crate::math::Vector3f) {
4742        // SAFETY: as above, in the other direction.
4743        unsafe {
4744            ffi::whiteout_m3_M3ParticleEmitter_set_instanceAngle(
4745                self.raw.as_ptr(),
4746                &value as *const crate::math::Vector3f as *const _,
4747            )
4748        }
4749    }
4750
4751    /// Instance distance (v17+)
4752    pub fn instance_distance(&self) -> f32 {
4753        // SAFETY: plain scalar read through a live handle.
4754        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_instanceDistance(self.raw.as_ptr()) }
4755    }
4756
4757    pub fn set_instance_distance(&mut self, value: f32) {
4758        // SAFETY: plain scalar write through a live handle.
4759        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_instanceDistance(self.raw.as_ptr(), value) }
4760    }
4761
4762    /// Pitch variation type
4763    pub fn pitch_type(&self) -> u32 {
4764        // SAFETY: plain scalar read through a live handle.
4765        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_pitchType(self.raw.as_ptr()) }
4766    }
4767
4768    pub fn set_pitch_type(&mut self, value: u32) {
4769        // SAFETY: plain scalar write through a live handle.
4770        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_pitchType(self.raw.as_ptr(), value) }
4771    }
4772
4773    /// Pitch variation amplitude
4774    /// Borrows the field in place — no copy, no allocation.
4775    pub fn pitch_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
4776        // SAFETY: an interior pointer into `self`, valid for this
4777        // borrow and never freed by the `Ref`.
4778        unsafe {
4779            crate::support::Ref::new(AnimRefF32 {
4780                raw: core::ptr::NonNull::new_unchecked(
4781                    ffi::whiteout_m3_M3ParticleEmitter_get_pitchAmplitude(self.raw.as_ptr()),
4782                ),
4783            })
4784        }
4785    }
4786
4787    pub fn pitch_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4788        // SAFETY: as above; `&mut self` guarantees exclusivity.
4789        unsafe {
4790            crate::support::RefMut::new(AnimRefF32 {
4791                raw: core::ptr::NonNull::new_unchecked(
4792                    ffi::whiteout_m3_M3ParticleEmitter_get_pitchAmplitude(self.raw.as_ptr()),
4793                ),
4794            })
4795        }
4796    }
4797
4798    /// Pitch variation frequency
4799    /// Borrows the field in place — no copy, no allocation.
4800    pub fn pitch_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
4801        // SAFETY: an interior pointer into `self`, valid for this
4802        // borrow and never freed by the `Ref`.
4803        unsafe {
4804            crate::support::Ref::new(AnimRefF32 {
4805                raw: core::ptr::NonNull::new_unchecked(
4806                    ffi::whiteout_m3_M3ParticleEmitter_get_pitchFrequency(self.raw.as_ptr()),
4807                ),
4808            })
4809        }
4810    }
4811
4812    pub fn pitch_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4813        // SAFETY: as above; `&mut self` guarantees exclusivity.
4814        unsafe {
4815            crate::support::RefMut::new(AnimRefF32 {
4816                raw: core::ptr::NonNull::new_unchecked(
4817                    ffi::whiteout_m3_M3ParticleEmitter_get_pitchFrequency(self.raw.as_ptr()),
4818                ),
4819            })
4820        }
4821    }
4822
4823    /// Yaw variation type
4824    pub fn yaw_type(&self) -> u32 {
4825        // SAFETY: plain scalar read through a live handle.
4826        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_yawType(self.raw.as_ptr()) }
4827    }
4828
4829    pub fn set_yaw_type(&mut self, value: u32) {
4830        // SAFETY: plain scalar write through a live handle.
4831        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_yawType(self.raw.as_ptr(), value) }
4832    }
4833
4834    /// Yaw variation amplitude
4835    /// Borrows the field in place — no copy, no allocation.
4836    pub fn yaw_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
4837        // SAFETY: an interior pointer into `self`, valid for this
4838        // borrow and never freed by the `Ref`.
4839        unsafe {
4840            crate::support::Ref::new(AnimRefF32 {
4841                raw: core::ptr::NonNull::new_unchecked(
4842                    ffi::whiteout_m3_M3ParticleEmitter_get_yawAmplitude(self.raw.as_ptr()),
4843                ),
4844            })
4845        }
4846    }
4847
4848    pub fn yaw_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4849        // SAFETY: as above; `&mut self` guarantees exclusivity.
4850        unsafe {
4851            crate::support::RefMut::new(AnimRefF32 {
4852                raw: core::ptr::NonNull::new_unchecked(
4853                    ffi::whiteout_m3_M3ParticleEmitter_get_yawAmplitude(self.raw.as_ptr()),
4854                ),
4855            })
4856        }
4857    }
4858
4859    /// Yaw variation frequency
4860    /// Borrows the field in place — no copy, no allocation.
4861    pub fn yaw_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
4862        // SAFETY: an interior pointer into `self`, valid for this
4863        // borrow and never freed by the `Ref`.
4864        unsafe {
4865            crate::support::Ref::new(AnimRefF32 {
4866                raw: core::ptr::NonNull::new_unchecked(
4867                    ffi::whiteout_m3_M3ParticleEmitter_get_yawFrequency(self.raw.as_ptr()),
4868                ),
4869            })
4870        }
4871    }
4872
4873    pub fn yaw_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4874        // SAFETY: as above; `&mut self` guarantees exclusivity.
4875        unsafe {
4876            crate::support::RefMut::new(AnimRefF32 {
4877                raw: core::ptr::NonNull::new_unchecked(
4878                    ffi::whiteout_m3_M3ParticleEmitter_get_yawFrequency(self.raw.as_ptr()),
4879                ),
4880            })
4881        }
4882    }
4883
4884    /// Speed variation type
4885    pub fn speed_type(&self) -> u32 {
4886        // SAFETY: plain scalar read through a live handle.
4887        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_speedType(self.raw.as_ptr()) }
4888    }
4889
4890    pub fn set_speed_type(&mut self, value: u32) {
4891        // SAFETY: plain scalar write through a live handle.
4892        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_speedType(self.raw.as_ptr(), value) }
4893    }
4894
4895    /// Speed variation amplitude
4896    /// Borrows the field in place — no copy, no allocation.
4897    pub fn speed_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
4898        // SAFETY: an interior pointer into `self`, valid for this
4899        // borrow and never freed by the `Ref`.
4900        unsafe {
4901            crate::support::Ref::new(AnimRefF32 {
4902                raw: core::ptr::NonNull::new_unchecked(
4903                    ffi::whiteout_m3_M3ParticleEmitter_get_speedAmplitude(self.raw.as_ptr()),
4904                ),
4905            })
4906        }
4907    }
4908
4909    pub fn speed_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4910        // SAFETY: as above; `&mut self` guarantees exclusivity.
4911        unsafe {
4912            crate::support::RefMut::new(AnimRefF32 {
4913                raw: core::ptr::NonNull::new_unchecked(
4914                    ffi::whiteout_m3_M3ParticleEmitter_get_speedAmplitude(self.raw.as_ptr()),
4915                ),
4916            })
4917        }
4918    }
4919
4920    /// Speed variation frequency
4921    /// Borrows the field in place — no copy, no allocation.
4922    pub fn speed_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
4923        // SAFETY: an interior pointer into `self`, valid for this
4924        // borrow and never freed by the `Ref`.
4925        unsafe {
4926            crate::support::Ref::new(AnimRefF32 {
4927                raw: core::ptr::NonNull::new_unchecked(
4928                    ffi::whiteout_m3_M3ParticleEmitter_get_speedFrequency(self.raw.as_ptr()),
4929                ),
4930            })
4931        }
4932    }
4933
4934    pub fn speed_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4935        // SAFETY: as above; `&mut self` guarantees exclusivity.
4936        unsafe {
4937            crate::support::RefMut::new(AnimRefF32 {
4938                raw: core::ptr::NonNull::new_unchecked(
4939                    ffi::whiteout_m3_M3ParticleEmitter_get_speedFrequency(self.raw.as_ptr()),
4940                ),
4941            })
4942        }
4943    }
4944
4945    /// Size variation type
4946    pub fn size_type(&self) -> u32 {
4947        // SAFETY: plain scalar read through a live handle.
4948        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_sizeType(self.raw.as_ptr()) }
4949    }
4950
4951    pub fn set_size_type(&mut self, value: u32) {
4952        // SAFETY: plain scalar write through a live handle.
4953        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_sizeType(self.raw.as_ptr(), value) }
4954    }
4955
4956    /// Size variation amplitude
4957    /// Borrows the field in place — no copy, no allocation.
4958    pub fn size_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
4959        // SAFETY: an interior pointer into `self`, valid for this
4960        // borrow and never freed by the `Ref`.
4961        unsafe {
4962            crate::support::Ref::new(AnimRefF32 {
4963                raw: core::ptr::NonNull::new_unchecked(
4964                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeAmplitude(self.raw.as_ptr()),
4965                ),
4966            })
4967        }
4968    }
4969
4970    pub fn size_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4971        // SAFETY: as above; `&mut self` guarantees exclusivity.
4972        unsafe {
4973            crate::support::RefMut::new(AnimRefF32 {
4974                raw: core::ptr::NonNull::new_unchecked(
4975                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeAmplitude(self.raw.as_ptr()),
4976                ),
4977            })
4978        }
4979    }
4980
4981    /// Size variation frequency
4982    /// Borrows the field in place — no copy, no allocation.
4983    pub fn size_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
4984        // SAFETY: an interior pointer into `self`, valid for this
4985        // borrow and never freed by the `Ref`.
4986        unsafe {
4987            crate::support::Ref::new(AnimRefF32 {
4988                raw: core::ptr::NonNull::new_unchecked(
4989                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeFrequency(self.raw.as_ptr()),
4990                ),
4991            })
4992        }
4993    }
4994
4995    pub fn size_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
4996        // SAFETY: as above; `&mut self` guarantees exclusivity.
4997        unsafe {
4998            crate::support::RefMut::new(AnimRefF32 {
4999                raw: core::ptr::NonNull::new_unchecked(
5000                    ffi::whiteout_m3_M3ParticleEmitter_get_sizeFrequency(self.raw.as_ptr()),
5001                ),
5002            })
5003        }
5004    }
5005
5006    /// Alpha variation type
5007    pub fn alpha_type(&self) -> u32 {
5008        // SAFETY: plain scalar read through a live handle.
5009        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_alphaType(self.raw.as_ptr()) }
5010    }
5011
5012    pub fn set_alpha_type(&mut self, value: u32) {
5013        // SAFETY: plain scalar write through a live handle.
5014        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_alphaType(self.raw.as_ptr(), value) }
5015    }
5016
5017    /// Alpha variation amplitude
5018    /// Borrows the field in place — no copy, no allocation.
5019    pub fn alpha_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
5020        // SAFETY: an interior pointer into `self`, valid for this
5021        // borrow and never freed by the `Ref`.
5022        unsafe {
5023            crate::support::Ref::new(AnimRefF32 {
5024                raw: core::ptr::NonNull::new_unchecked(
5025                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaAmplitude(self.raw.as_ptr()),
5026                ),
5027            })
5028        }
5029    }
5030
5031    pub fn alpha_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5032        // SAFETY: as above; `&mut self` guarantees exclusivity.
5033        unsafe {
5034            crate::support::RefMut::new(AnimRefF32 {
5035                raw: core::ptr::NonNull::new_unchecked(
5036                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaAmplitude(self.raw.as_ptr()),
5037                ),
5038            })
5039        }
5040    }
5041
5042    /// Alpha variation frequency
5043    /// Borrows the field in place — no copy, no allocation.
5044    pub fn alpha_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
5045        // SAFETY: an interior pointer into `self`, valid for this
5046        // borrow and never freed by the `Ref`.
5047        unsafe {
5048            crate::support::Ref::new(AnimRefF32 {
5049                raw: core::ptr::NonNull::new_unchecked(
5050                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaFrequency(self.raw.as_ptr()),
5051                ),
5052            })
5053        }
5054    }
5055
5056    pub fn alpha_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5057        // SAFETY: as above; `&mut self` guarantees exclusivity.
5058        unsafe {
5059            crate::support::RefMut::new(AnimRefF32 {
5060                raw: core::ptr::NonNull::new_unchecked(
5061                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaFrequency(self.raw.as_ptr()),
5062                ),
5063            })
5064        }
5065    }
5066
5067    /// Color variation type
5068    pub fn color_type(&self) -> u32 {
5069        // SAFETY: plain scalar read through a live handle.
5070        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_colorType(self.raw.as_ptr()) }
5071    }
5072
5073    pub fn set_color_type(&mut self, value: u32) {
5074        // SAFETY: plain scalar write through a live handle.
5075        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_colorType(self.raw.as_ptr(), value) }
5076    }
5077
5078    /// Color variation amplitude
5079    /// Borrows the field in place — no copy, no allocation.
5080    pub fn color_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
5081        // SAFETY: an interior pointer into `self`, valid for this
5082        // borrow and never freed by the `Ref`.
5083        unsafe {
5084            crate::support::Ref::new(AnimRefF32 {
5085                raw: core::ptr::NonNull::new_unchecked(
5086                    ffi::whiteout_m3_M3ParticleEmitter_get_colorAmplitude(self.raw.as_ptr()),
5087                ),
5088            })
5089        }
5090    }
5091
5092    pub fn color_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5093        // SAFETY: as above; `&mut self` guarantees exclusivity.
5094        unsafe {
5095            crate::support::RefMut::new(AnimRefF32 {
5096                raw: core::ptr::NonNull::new_unchecked(
5097                    ffi::whiteout_m3_M3ParticleEmitter_get_colorAmplitude(self.raw.as_ptr()),
5098                ),
5099            })
5100        }
5101    }
5102
5103    /// Color variation frequency
5104    /// Borrows the field in place — no copy, no allocation.
5105    pub fn color_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
5106        // SAFETY: an interior pointer into `self`, valid for this
5107        // borrow and never freed by the `Ref`.
5108        unsafe {
5109            crate::support::Ref::new(AnimRefF32 {
5110                raw: core::ptr::NonNull::new_unchecked(
5111                    ffi::whiteout_m3_M3ParticleEmitter_get_colorFrequency(self.raw.as_ptr()),
5112                ),
5113            })
5114        }
5115    }
5116
5117    pub fn color_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5118        // SAFETY: as above; `&mut self` guarantees exclusivity.
5119        unsafe {
5120            crate::support::RefMut::new(AnimRefF32 {
5121                raw: core::ptr::NonNull::new_unchecked(
5122                    ffi::whiteout_m3_M3ParticleEmitter_get_colorFrequency(self.raw.as_ptr()),
5123                ),
5124            })
5125        }
5126    }
5127
5128    /// Rotation variation type
5129    pub fn rotation_type(&self) -> u32 {
5130        // SAFETY: plain scalar read through a live handle.
5131        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_rotationType(self.raw.as_ptr()) }
5132    }
5133
5134    pub fn set_rotation_type(&mut self, value: u32) {
5135        // SAFETY: plain scalar write through a live handle.
5136        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_rotationType(self.raw.as_ptr(), value) }
5137    }
5138
5139    /// Rotation variation amplitude
5140    /// Borrows the field in place — no copy, no allocation.
5141    pub fn rotation_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
5142        // SAFETY: an interior pointer into `self`, valid for this
5143        // borrow and never freed by the `Ref`.
5144        unsafe {
5145            crate::support::Ref::new(AnimRefF32 {
5146                raw: core::ptr::NonNull::new_unchecked(
5147                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationAmplitude(self.raw.as_ptr()),
5148                ),
5149            })
5150        }
5151    }
5152
5153    pub fn rotation_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5154        // SAFETY: as above; `&mut self` guarantees exclusivity.
5155        unsafe {
5156            crate::support::RefMut::new(AnimRefF32 {
5157                raw: core::ptr::NonNull::new_unchecked(
5158                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationAmplitude(self.raw.as_ptr()),
5159                ),
5160            })
5161        }
5162    }
5163
5164    /// Rotation variation frequency
5165    /// Borrows the field in place — no copy, no allocation.
5166    pub fn rotation_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
5167        // SAFETY: an interior pointer into `self`, valid for this
5168        // borrow and never freed by the `Ref`.
5169        unsafe {
5170            crate::support::Ref::new(AnimRefF32 {
5171                raw: core::ptr::NonNull::new_unchecked(
5172                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationFrequency(self.raw.as_ptr()),
5173                ),
5174            })
5175        }
5176    }
5177
5178    pub fn rotation_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5179        // SAFETY: as above; `&mut self` guarantees exclusivity.
5180        unsafe {
5181            crate::support::RefMut::new(AnimRefF32 {
5182                raw: core::ptr::NonNull::new_unchecked(
5183                    ffi::whiteout_m3_M3ParticleEmitter_get_rotationFrequency(self.raw.as_ptr()),
5184                ),
5185            })
5186        }
5187    }
5188
5189    /// Horizontal variation type
5190    pub fn horizontal_type(&self) -> u32 {
5191        // SAFETY: plain scalar read through a live handle.
5192        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_horizontalType(self.raw.as_ptr()) }
5193    }
5194
5195    pub fn set_horizontal_type(&mut self, value: u32) {
5196        // SAFETY: plain scalar write through a live handle.
5197        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_horizontalType(self.raw.as_ptr(), value) }
5198    }
5199
5200    /// Horizontal variation amplitude
5201    /// Borrows the field in place — no copy, no allocation.
5202    pub fn horizontal_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
5203        // SAFETY: an interior pointer into `self`, valid for this
5204        // borrow and never freed by the `Ref`.
5205        unsafe {
5206            crate::support::Ref::new(AnimRefF32 {
5207                raw: core::ptr::NonNull::new_unchecked(
5208                    ffi::whiteout_m3_M3ParticleEmitter_get_horizontalAmplitude(self.raw.as_ptr()),
5209                ),
5210            })
5211        }
5212    }
5213
5214    pub fn horizontal_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5215        // SAFETY: as above; `&mut self` guarantees exclusivity.
5216        unsafe {
5217            crate::support::RefMut::new(AnimRefF32 {
5218                raw: core::ptr::NonNull::new_unchecked(
5219                    ffi::whiteout_m3_M3ParticleEmitter_get_horizontalAmplitude(self.raw.as_ptr()),
5220                ),
5221            })
5222        }
5223    }
5224
5225    /// Horizontal variation frequency
5226    /// Borrows the field in place — no copy, no allocation.
5227    pub fn horizontal_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
5228        // SAFETY: an interior pointer into `self`, valid for this
5229        // borrow and never freed by the `Ref`.
5230        unsafe {
5231            crate::support::Ref::new(AnimRefF32 {
5232                raw: core::ptr::NonNull::new_unchecked(
5233                    ffi::whiteout_m3_M3ParticleEmitter_get_horizontalFrequency(self.raw.as_ptr()),
5234                ),
5235            })
5236        }
5237    }
5238
5239    pub fn horizontal_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5240        // SAFETY: as above; `&mut self` guarantees exclusivity.
5241        unsafe {
5242            crate::support::RefMut::new(AnimRefF32 {
5243                raw: core::ptr::NonNull::new_unchecked(
5244                    ffi::whiteout_m3_M3ParticleEmitter_get_horizontalFrequency(self.raw.as_ptr()),
5245                ),
5246            })
5247        }
5248    }
5249
5250    /// Vertical variation type
5251    pub fn vertical_type(&self) -> u32 {
5252        // SAFETY: plain scalar read through a live handle.
5253        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_verticalType(self.raw.as_ptr()) }
5254    }
5255
5256    pub fn set_vertical_type(&mut self, value: u32) {
5257        // SAFETY: plain scalar write through a live handle.
5258        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_verticalType(self.raw.as_ptr(), value) }
5259    }
5260
5261    /// Vertical variation amplitude
5262    /// Borrows the field in place — no copy, no allocation.
5263    pub fn vertical_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
5264        // SAFETY: an interior pointer into `self`, valid for this
5265        // borrow and never freed by the `Ref`.
5266        unsafe {
5267            crate::support::Ref::new(AnimRefF32 {
5268                raw: core::ptr::NonNull::new_unchecked(
5269                    ffi::whiteout_m3_M3ParticleEmitter_get_verticalAmplitude(self.raw.as_ptr()),
5270                ),
5271            })
5272        }
5273    }
5274
5275    pub fn vertical_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5276        // SAFETY: as above; `&mut self` guarantees exclusivity.
5277        unsafe {
5278            crate::support::RefMut::new(AnimRefF32 {
5279                raw: core::ptr::NonNull::new_unchecked(
5280                    ffi::whiteout_m3_M3ParticleEmitter_get_verticalAmplitude(self.raw.as_ptr()),
5281                ),
5282            })
5283        }
5284    }
5285
5286    /// Vertical variation frequency;
5287    /// Borrows the field in place — no copy, no allocation.
5288    pub fn vertical_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
5289        // SAFETY: an interior pointer into `self`, valid for this
5290        // borrow and never freed by the `Ref`.
5291        unsafe {
5292            crate::support::Ref::new(AnimRefF32 {
5293                raw: core::ptr::NonNull::new_unchecked(
5294                    ffi::whiteout_m3_M3ParticleEmitter_get_verticalFrequency(self.raw.as_ptr()),
5295                ),
5296            })
5297        }
5298    }
5299
5300    pub fn vertical_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5301        // SAFETY: as above; `&mut self` guarantees exclusivity.
5302        unsafe {
5303            crate::support::RefMut::new(AnimRefF32 {
5304                raw: core::ptr::NonNull::new_unchecked(
5305                    ffi::whiteout_m3_M3ParticleEmitter_get_verticalFrequency(self.raw.as_ptr()),
5306                ),
5307            })
5308        }
5309    }
5310
5311    /// Animated parent velocity influence
5312    /// Borrows the field in place — no copy, no allocation.
5313    pub fn particle_velocity(&self) -> crate::support::Ref<'_, AnimRefF32> {
5314        // SAFETY: an interior pointer into `self`, valid for this
5315        // borrow and never freed by the `Ref`.
5316        unsafe {
5317            crate::support::Ref::new(AnimRefF32 {
5318                raw: core::ptr::NonNull::new_unchecked(
5319                    ffi::whiteout_m3_M3ParticleEmitter_get_particleVelocity(self.raw.as_ptr()),
5320                ),
5321            })
5322        }
5323    }
5324
5325    pub fn particle_velocity_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5326        // SAFETY: as above; `&mut self` guarantees exclusivity.
5327        unsafe {
5328            crate::support::RefMut::new(AnimRefF32 {
5329                raw: core::ptr::NonNull::new_unchecked(
5330                    ffi::whiteout_m3_M3ParticleEmitter_get_particleVelocity(self.raw.as_ptr()),
5331                ),
5332            })
5333        }
5334    }
5335
5336    /// Animated phase shift (v22+)
5337    /// Borrows the field in place — no copy, no allocation.
5338    pub fn phase_shift(&self) -> crate::support::Ref<'_, AnimRefF32> {
5339        // SAFETY: an interior pointer into `self`, valid for this
5340        // borrow and never freed by the `Ref`.
5341        unsafe {
5342            crate::support::Ref::new(AnimRefF32 {
5343                raw: core::ptr::NonNull::new_unchecked(
5344                    ffi::whiteout_m3_M3ParticleEmitter_get_phaseShift(self.raw.as_ptr()),
5345                ),
5346            })
5347        }
5348    }
5349
5350    pub fn phase_shift_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5351        // SAFETY: as above; `&mut self` guarantees exclusivity.
5352        unsafe {
5353            crate::support::RefMut::new(AnimRefF32 {
5354                raw: core::ptr::NonNull::new_unchecked(
5355                    ffi::whiteout_m3_M3ParticleEmitter_get_phaseShift(self.raw.as_ptr()),
5356                ),
5357            })
5358        }
5359    }
5360
5361    /// Main particle flags
5362    pub fn flags(&self) -> ParticleFlag {
5363        // SAFETY: scalar read; a flag set accepts any bits.
5364        ParticleFlag(unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_flags(self.raw.as_ptr()) })
5365    }
5366
5367    pub fn set_flags(&mut self, value: ParticleFlag) {
5368        // SAFETY: scalar write through a live handle.
5369        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_flags(self.raw.as_ptr(), value.0) }
5370    }
5371
5372    /// Rotation flags (v18+)
5373    pub fn rotation_flags(&self) -> ParticleRotationFlag {
5374        // SAFETY: scalar read; a flag set accepts any bits.
5375        ParticleRotationFlag(unsafe {
5376            ffi::whiteout_m3_M3ParticleEmitter_get_rotationFlags(self.raw.as_ptr())
5377        })
5378    }
5379
5380    pub fn set_rotation_flags(&mut self, value: ParticleRotationFlag) {
5381        // SAFETY: scalar write through a live handle.
5382        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_rotationFlags(self.raw.as_ptr(), value.0) }
5383    }
5384
5385    pub fn color_smoothing(&self) -> InterpolationMode {
5386        // SAFETY: scalar read; the discriminant is validated below.
5387        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_colorSmoothing(self.raw.as_ptr()) }
5388            .try_into()
5389            .expect("unknown enum discriminant from the native library")
5390    }
5391
5392    pub fn set_color_smoothing(&mut self, value: InterpolationMode) {
5393        // SAFETY: scalar write through a live handle.
5394        unsafe {
5395            ffi::whiteout_m3_M3ParticleEmitter_set_colorSmoothing(self.raw.as_ptr(), value as i32)
5396        }
5397    }
5398
5399    pub fn size_smoothing(&self) -> InterpolationMode {
5400        // SAFETY: scalar read; the discriminant is validated below.
5401        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_sizeSmoothing(self.raw.as_ptr()) }
5402            .try_into()
5403            .expect("unknown enum discriminant from the native library")
5404    }
5405
5406    pub fn set_size_smoothing(&mut self, value: InterpolationMode) {
5407        // SAFETY: scalar write through a live handle.
5408        unsafe {
5409            ffi::whiteout_m3_M3ParticleEmitter_set_sizeSmoothing(self.raw.as_ptr(), value as i32)
5410        }
5411    }
5412
5413    pub fn rotation_smoothing(&self) -> InterpolationMode {
5414        // SAFETY: scalar read; the discriminant is validated below.
5415        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_rotationSmoothing(self.raw.as_ptr()) }
5416            .try_into()
5417            .expect("unknown enum discriminant from the native library")
5418    }
5419
5420    pub fn set_rotation_smoothing(&mut self, value: InterpolationMode) {
5421        // SAFETY: scalar write through a live handle.
5422        unsafe {
5423            ffi::whiteout_m3_M3ParticleEmitter_set_rotationSmoothing(
5424                self.raw.as_ptr(),
5425                value as i32,
5426            )
5427        }
5428    }
5429
5430    /// Animated alpha threshold
5431    /// Borrows the field in place — no copy, no allocation.
5432    pub fn alpha_threshold(&self) -> crate::support::Ref<'_, AnimRefF32> {
5433        // SAFETY: an interior pointer into `self`, valid for this
5434        // borrow and never freed by the `Ref`.
5435        unsafe {
5436            crate::support::Ref::new(AnimRefF32 {
5437                raw: core::ptr::NonNull::new_unchecked(
5438                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaThreshold(self.raw.as_ptr()),
5439                ),
5440            })
5441        }
5442    }
5443
5444    pub fn alpha_threshold_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5445        // SAFETY: as above; `&mut self` guarantees exclusivity.
5446        unsafe {
5447            crate::support::RefMut::new(AnimRefF32 {
5448                raw: core::ptr::NonNull::new_unchecked(
5449                    ffi::whiteout_m3_M3ParticleEmitter_get_alphaThreshold(self.raw.as_ptr()),
5450                ),
5451            })
5452        }
5453    }
5454
5455    /// Animated UV offset
5456    /// Borrows the field in place — no copy, no allocation.
5457    pub fn uv_offset(&self) -> crate::support::Ref<'_, AnimRefVector2f> {
5458        // SAFETY: an interior pointer into `self`, valid for this
5459        // borrow and never freed by the `Ref`.
5460        unsafe {
5461            crate::support::Ref::new(AnimRefVector2f {
5462                raw: core::ptr::NonNull::new_unchecked(
5463                    ffi::whiteout_m3_M3ParticleEmitter_get_uvOffset(self.raw.as_ptr()),
5464                ),
5465            })
5466        }
5467    }
5468
5469    pub fn uv_offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector2f> {
5470        // SAFETY: as above; `&mut self` guarantees exclusivity.
5471        unsafe {
5472            crate::support::RefMut::new(AnimRefVector2f {
5473                raw: core::ptr::NonNull::new_unchecked(
5474                    ffi::whiteout_m3_M3ParticleEmitter_get_uvOffset(self.raw.as_ptr()),
5475                ),
5476            })
5477        }
5478    }
5479
5480    /// Animated UV rotation angles
5481    /// Borrows the field in place — no copy, no allocation.
5482    pub fn uv_angle(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
5483        // SAFETY: an interior pointer into `self`, valid for this
5484        // borrow and never freed by the `Ref`.
5485        unsafe {
5486            crate::support::Ref::new(AnimRefVector3f {
5487                raw: core::ptr::NonNull::new_unchecked(
5488                    ffi::whiteout_m3_M3ParticleEmitter_get_uvAngle(self.raw.as_ptr()),
5489                ),
5490            })
5491        }
5492    }
5493
5494    pub fn uv_angle_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
5495        // SAFETY: as above; `&mut self` guarantees exclusivity.
5496        unsafe {
5497            crate::support::RefMut::new(AnimRefVector3f {
5498                raw: core::ptr::NonNull::new_unchecked(
5499                    ffi::whiteout_m3_M3ParticleEmitter_get_uvAngle(self.raw.as_ptr()),
5500                ),
5501            })
5502        }
5503    }
5504
5505    /// Animated UV tiling
5506    /// Borrows the field in place — no copy, no allocation.
5507    pub fn uv_tiling(&self) -> crate::support::Ref<'_, AnimRefVector2f> {
5508        // SAFETY: an interior pointer into `self`, valid for this
5509        // borrow and never freed by the `Ref`.
5510        unsafe {
5511            crate::support::Ref::new(AnimRefVector2f {
5512                raw: core::ptr::NonNull::new_unchecked(
5513                    ffi::whiteout_m3_M3ParticleEmitter_get_uvTiling(self.raw.as_ptr()),
5514                ),
5515            })
5516        }
5517    }
5518
5519    pub fn uv_tiling_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector2f> {
5520        // SAFETY: as above; `&mut self` guarantees exclusivity.
5521        unsafe {
5522            crate::support::RefMut::new(AnimRefVector2f {
5523                raw: core::ptr::NonNull::new_unchecked(
5524                    ffi::whiteout_m3_M3ParticleEmitter_get_uvTiling(self.raw.as_ptr()),
5525                ),
5526            })
5527        }
5528    }
5529
5530    /// Spline control points (SVC3)
5531    pub fn spline_line_data_len(&self) -> usize {
5532        // SAFETY: scalar read through a live handle.
5533        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_splineLineData_count(self.raw.as_ptr()) }
5534    }
5535
5536    /// Borrows element `index` in place. `None` when out of range.
5537    pub fn spline_line_data(
5538        &self,
5539        index: usize,
5540    ) -> Option<crate::support::Ref<'_, AnimRefVector3f>> {
5541        if index >= self.spline_line_data_len() {
5542            return None;
5543        }
5544        // SAFETY: index checked above; the pointer is interior to `self`.
5545        unsafe {
5546            Some(crate::support::Ref::new(AnimRefVector3f {
5547                raw: core::ptr::NonNull::new_unchecked(
5548                    ffi::whiteout_m3_M3ParticleEmitter_get_splineLineData_at(
5549                        self.raw.as_ptr(),
5550                        index,
5551                    ),
5552                ),
5553            }))
5554        }
5555    }
5556
5557    pub fn spline_line_data_mut(
5558        &mut self,
5559        index: usize,
5560    ) -> Option<crate::support::RefMut<'_, AnimRefVector3f>> {
5561        if index >= self.spline_line_data_len() {
5562            return None;
5563        }
5564        // SAFETY: as above; `&mut self` guarantees exclusivity.
5565        unsafe {
5566            Some(crate::support::RefMut::new(AnimRefVector3f {
5567                raw: core::ptr::NonNull::new_unchecked(
5568                    ffi::whiteout_m3_M3ParticleEmitter_get_splineLineData_at(
5569                        self.raw.as_ptr(),
5570                        index,
5571                    ),
5572                ),
5573            }))
5574        }
5575    }
5576
5577    /// Iterate the elements, borrowing each in turn.
5578    pub fn spline_line_data_iter(
5579        &self,
5580    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AnimRefVector3f>> {
5581        (0..self.spline_line_data_len())
5582            .map(move |i| self.spline_line_data(i).expect("index below len"))
5583    }
5584
5585    pub fn resize_spline_line_data(&mut self, count: usize) {
5586        // SAFETY: exclusive access, so no borrow is outstanding.
5587        unsafe {
5588            ffi::whiteout_m3_M3ParticleEmitter_resize_splineLineData(self.raw.as_ptr(), count)
5589        }
5590    }
5591
5592    /// Wind influence multiplier
5593    pub fn wind_multiplier(&self) -> f32 {
5594        // SAFETY: plain scalar read through a live handle.
5595        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_windMultiplier(self.raw.as_ptr()) }
5596    }
5597
5598    pub fn set_wind_multiplier(&mut self, value: f32) {
5599        // SAFETY: plain scalar write through a live handle.
5600        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_windMultiplier(self.raw.as_ptr(), value) }
5601    }
5602
5603    /// LOD reduction level
5604    pub fn lod_reduce(&self) -> u32 {
5605        // SAFETY: plain scalar read through a live handle.
5606        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_lodReduce(self.raw.as_ptr()) }
5607    }
5608
5609    pub fn set_lod_reduce(&mut self, value: u32) {
5610        // SAFETY: plain scalar write through a live handle.
5611        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_lodReduce(self.raw.as_ptr(), value) }
5612    }
5613
5614    /// LOD cut-off level
5615    pub fn lod_cut(&self) -> u32 {
5616        // SAFETY: plain scalar read through a live handle.
5617        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_lodCut(self.raw.as_ptr()) }
5618    }
5619
5620    pub fn set_lod_cut(&mut self, value: u32) {
5621        // SAFETY: plain scalar write through a live handle.
5622        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_lodCut(self.raw.as_ptr(), value) }
5623    }
5624
5625    /// Animated lower bound
5626    /// Borrows the field in place — no copy, no allocation.
5627    pub fn lower_bound(&self) -> crate::support::Ref<'_, AnimRefF32> {
5628        // SAFETY: an interior pointer into `self`, valid for this
5629        // borrow and never freed by the `Ref`.
5630        unsafe {
5631            crate::support::Ref::new(AnimRefF32 {
5632                raw: core::ptr::NonNull::new_unchecked(
5633                    ffi::whiteout_m3_M3ParticleEmitter_get_lowerBound(self.raw.as_ptr()),
5634                ),
5635            })
5636        }
5637    }
5638
5639    pub fn lower_bound_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5640        // SAFETY: as above; `&mut self` guarantees exclusivity.
5641        unsafe {
5642            crate::support::RefMut::new(AnimRefF32 {
5643                raw: core::ptr::NonNull::new_unchecked(
5644                    ffi::whiteout_m3_M3ParticleEmitter_get_lowerBound(self.raw.as_ptr()),
5645                ),
5646            })
5647        }
5648    }
5649
5650    /// Animated upper bound
5651    /// Borrows the field in place — no copy, no allocation.
5652    pub fn upper_bound(&self) -> crate::support::Ref<'_, AnimRefF32> {
5653        // SAFETY: an interior pointer into `self`, valid for this
5654        // borrow and never freed by the `Ref`.
5655        unsafe {
5656            crate::support::Ref::new(AnimRefF32 {
5657                raw: core::ptr::NonNull::new_unchecked(
5658                    ffi::whiteout_m3_M3ParticleEmitter_get_upperBound(self.raw.as_ptr()),
5659                ),
5660            })
5661        }
5662    }
5663
5664    pub fn upper_bound_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5665        // SAFETY: as above; `&mut self` guarantees exclusivity.
5666        unsafe {
5667            crate::support::RefMut::new(AnimRefF32 {
5668                raw: core::ptr::NonNull::new_unchecked(
5669                    ffi::whiteout_m3_M3ParticleEmitter_get_upperBound(self.raw.as_ptr()),
5670                ),
5671            })
5672        }
5673    }
5674
5675    pub fn trail_link_index(&self) -> i32 {
5676        // SAFETY: plain scalar read through a live handle.
5677        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_trailLinkIndex(self.raw.as_ptr()) }
5678    }
5679
5680    pub fn set_trail_link_index(&mut self, value: i32) {
5681        // SAFETY: plain scalar write through a live handle.
5682        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_trailLinkIndex(self.raw.as_ptr(), value) }
5683    }
5684
5685    /// Trail spawn probability
5686    pub fn trail_chance(&self) -> f32 {
5687        // SAFETY: plain scalar read through a live handle.
5688        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_trailChance(self.raw.as_ptr()) }
5689    }
5690
5691    pub fn set_trail_chance(&mut self, value: f32) {
5692        // SAFETY: plain scalar write through a live handle.
5693        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_trailChance(self.raw.as_ptr(), value) }
5694    }
5695
5696    /// Animated trail emission rate
5697    /// Borrows the field in place — no copy, no allocation.
5698    pub fn trail_emission_rate(&self) -> crate::support::Ref<'_, AnimRefF32> {
5699        // SAFETY: an interior pointer into `self`, valid for this
5700        // borrow and never freed by the `Ref`.
5701        unsafe {
5702            crate::support::Ref::new(AnimRefF32 {
5703                raw: core::ptr::NonNull::new_unchecked(
5704                    ffi::whiteout_m3_M3ParticleEmitter_get_trailEmissionRate(self.raw.as_ptr()),
5705                ),
5706            })
5707        }
5708    }
5709
5710    pub fn trail_emission_rate_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5711        // SAFETY: as above; `&mut self` guarantees exclusivity.
5712        unsafe {
5713            crate::support::RefMut::new(AnimRefF32 {
5714                raw: core::ptr::NonNull::new_unchecked(
5715                    ffi::whiteout_m3_M3ParticleEmitter_get_trailEmissionRate(self.raw.as_ptr()),
5716                ),
5717            })
5718        }
5719    }
5720
5721    /// Linked projector index (-1 = none)
5722    pub fn splat_projection_index(&self) -> i32 {
5723        // SAFETY: plain scalar read through a live handle.
5724        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_splatProjectionIndex(self.raw.as_ptr()) }
5725    }
5726
5727    pub fn set_splat_projection_index(&mut self, value: i32) {
5728        // SAFETY: plain scalar write through a live handle.
5729        unsafe {
5730            ffi::whiteout_m3_M3ParticleEmitter_set_splatProjectionIndex(self.raw.as_ptr(), value)
5731        }
5732    }
5733
5734    /// Splat spawn probability
5735    pub fn splat_chance(&self) -> f32 {
5736        // SAFETY: plain scalar read through a live handle.
5737        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_splatChance(self.raw.as_ptr()) }
5738    }
5739
5740    pub fn set_splat_chance(&mut self, value: f32) {
5741        // SAFETY: plain scalar write through a live handle.
5742        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_splatChance(self.raw.as_ptr(), value) }
5743    }
5744
5745    /// Emitter copy indices (U32_)
5746    /// Zero-copy view of the underlying `std::vector`.
5747    pub fn copy_indices(&self) -> &[u32] {
5748        // SAFETY: `_data`/`_count` describe one contiguous C++
5749        // allocation, borrowed for as long as `self` is.
5750        unsafe {
5751            let n = ffi::whiteout_m3_M3ParticleEmitter_get_copyIndices_count(self.raw.as_ptr());
5752            let p = ffi::whiteout_m3_M3ParticleEmitter_get_copyIndices_data(self.raw.as_ptr());
5753            if p.is_null() || n == 0 {
5754                &[]
5755            } else {
5756                core::slice::from_raw_parts(p, n)
5757            }
5758        }
5759    }
5760
5761    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
5762    pub fn copy_indices_mut(&mut self) -> &mut [u32] {
5763        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
5764        unsafe {
5765            let n = ffi::whiteout_m3_M3ParticleEmitter_get_copyIndices_count(self.raw.as_ptr());
5766            let p = ffi::whiteout_m3_M3ParticleEmitter_get_copyIndices_data(self.raw.as_ptr())
5767                as *mut u32;
5768            if p.is_null() || n == 0 {
5769                &mut []
5770            } else {
5771                core::slice::from_raw_parts_mut(p, n)
5772            }
5773        }
5774    }
5775
5776    pub fn set_copy_indices(&mut self, values: &[u32]) {
5777        // SAFETY: the native side copies `values` before returning.
5778        unsafe {
5779            ffi::whiteout_m3_M3ParticleEmitter_assign_copyIndices(
5780                self.raw.as_ptr(),
5781                values.as_ptr() as *const _,
5782                values.len(),
5783            )
5784        }
5785    }
5786
5787    pub fn resize_copy_indices(&mut self, count: usize) {
5788        // SAFETY: reallocation is safe here precisely because
5789        // `&mut self` means no slice borrow is outstanding.
5790        unsafe { ffi::whiteout_m3_M3ParticleEmitter_resize_copyIndices(self.raw.as_ptr(), count) }
5791    }
5792
5793    /// Ribbon spawn probability on bounce (v23+)
5794    pub fn spawn_ribbon_on_bounce_chance(&self) -> f32 {
5795        // SAFETY: plain scalar read through a live handle.
5796        unsafe {
5797            ffi::whiteout_m3_M3ParticleEmitter_get_spawnRibbonOnBounceChance(self.raw.as_ptr())
5798        }
5799    }
5800
5801    pub fn set_spawn_ribbon_on_bounce_chance(&mut self, value: f32) {
5802        // SAFETY: plain scalar write through a live handle.
5803        unsafe {
5804            ffi::whiteout_m3_M3ParticleEmitter_set_spawnRibbonOnBounceChance(
5805                self.raw.as_ptr(),
5806                value,
5807            )
5808        }
5809    }
5810
5811    /// Index into RIB_ array (-1 = none, v23+)
5812    pub fn ribbon_link_index(&self) -> i32 {
5813        // SAFETY: plain scalar read through a live handle.
5814        unsafe { ffi::whiteout_m3_M3ParticleEmitter_get_ribbonLinkIndex(self.raw.as_ptr()) }
5815    }
5816
5817    pub fn set_ribbon_link_index(&mut self, value: i32) {
5818        // SAFETY: plain scalar write through a live handle.
5819        unsafe { ffi::whiteout_m3_M3ParticleEmitter_set_ribbonLinkIndex(self.raw.as_ptr(), value) }
5820    }
5821}
5822
5823impl Default for ParticleEmitter {
5824    fn default() -> Self {
5825        Self::new()
5826    }
5827}
5828
5829/// PARC — Particle emitter copy (v0, 40 bytes)
5830///
5831/// Lightweight copy of a particle emitter with overridden emission rate, squirt amount, and bone index. References the original PAR_ via Model.copyIndices.
5832pub struct ParticleEmitterCopy {
5833    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ParticleEmitterCopy>,
5834}
5835
5836impl Drop for ParticleEmitterCopy {
5837    fn drop(&mut self) {
5838        // SAFETY: `raw` came from a native constructor and Drop runs once.
5839        unsafe { ffi::whiteout_m3_M3ParticleEmitterCopy_delete(self.raw.as_ptr()) }
5840    }
5841}
5842
5843impl ParticleEmitterCopy {
5844    /// # Safety
5845    /// `raw` must be a live handle this value takes ownership of.
5846    #[allow(dead_code)] // used by whichever methods return this type
5847    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ParticleEmitterCopy) -> Option<Self> {
5848        core::ptr::NonNull::new(raw).map(|raw| ParticleEmitterCopy { raw })
5849    }
5850}
5851
5852// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
5853// is deliberately NOT implemented — the C++ types make no documented
5854// guarantee about concurrent use, and claiming one we haven't verified
5855// would be unsound. See `@bind thread_safe` in the plan.
5856unsafe impl Send for ParticleEmitterCopy {}
5857
5858impl core::fmt::Debug for ParticleEmitterCopy {
5859    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5860        f.debug_struct("ParticleEmitterCopy")
5861            .finish_non_exhaustive()
5862    }
5863}
5864
5865impl ParticleEmitterCopy {
5866    /// # Panics
5867    /// Panics if the native allocation fails.
5868    pub fn new() -> Self {
5869        // SAFETY: the native constructor returns a live handle; a null here
5870        // means the library is unusable.
5871        unsafe {
5872            let raw = ffi::whiteout_m3_M3ParticleEmitterCopy_new();
5873            Self::from_raw(raw).expect("native ParticleEmitterCopy allocation failed")
5874        }
5875    }
5876
5877    /// Overridden emission rate
5878    /// Borrows the field in place — no copy, no allocation.
5879    pub fn emission_rate(&self) -> crate::support::Ref<'_, AnimRefF32> {
5880        // SAFETY: an interior pointer into `self`, valid for this
5881        // borrow and never freed by the `Ref`.
5882        unsafe {
5883            crate::support::Ref::new(AnimRefF32 {
5884                raw: core::ptr::NonNull::new_unchecked(
5885                    ffi::whiteout_m3_M3ParticleEmitterCopy_get_emissionRate(self.raw.as_ptr()),
5886                ),
5887            })
5888        }
5889    }
5890
5891    pub fn emission_rate_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
5892        // SAFETY: as above; `&mut self` guarantees exclusivity.
5893        unsafe {
5894            crate::support::RefMut::new(AnimRefF32 {
5895                raw: core::ptr::NonNull::new_unchecked(
5896                    ffi::whiteout_m3_M3ParticleEmitterCopy_get_emissionRate(self.raw.as_ptr()),
5897                ),
5898            })
5899        }
5900    }
5901
5902    /// Overridden squirt burst count
5903    /// Borrows the field in place — no copy, no allocation.
5904    pub fn squirt_amount(&self) -> crate::support::Ref<'_, AnimRefU16> {
5905        // SAFETY: an interior pointer into `self`, valid for this
5906        // borrow and never freed by the `Ref`.
5907        unsafe {
5908            crate::support::Ref::new(AnimRefU16 {
5909                raw: core::ptr::NonNull::new_unchecked(
5910                    ffi::whiteout_m3_M3ParticleEmitterCopy_get_squirtAmount(self.raw.as_ptr()),
5911                ),
5912            })
5913        }
5914    }
5915
5916    pub fn squirt_amount_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU16> {
5917        // SAFETY: as above; `&mut self` guarantees exclusivity.
5918        unsafe {
5919            crate::support::RefMut::new(AnimRefU16 {
5920                raw: core::ptr::NonNull::new_unchecked(
5921                    ffi::whiteout_m3_M3ParticleEmitterCopy_get_squirtAmount(self.raw.as_ptr()),
5922                ),
5923            })
5924        }
5925    }
5926
5927    /// Index into BONE array
5928    pub fn bone_index(&self) -> u32 {
5929        // SAFETY: plain scalar read through a live handle.
5930        unsafe { ffi::whiteout_m3_M3ParticleEmitterCopy_get_boneIndex(self.raw.as_ptr()) }
5931    }
5932
5933    pub fn set_bone_index(&mut self, value: u32) {
5934        // SAFETY: plain scalar write through a live handle.
5935        unsafe { ffi::whiteout_m3_M3ParticleEmitterCopy_set_boneIndex(self.raw.as_ptr(), value) }
5936    }
5937}
5938
5939impl Default for ParticleEmitterCopy {
5940    fn default() -> Self {
5941        Self::new()
5942    }
5943}
5944
5945/// SRIB — Spline ribbon segment (v0, 272 bytes)
5946///
5947/// Defines a single segment of a spline-based ribbon with emission offset/vector, velocity, bone binding, and pitch/yaw/velocity variation channels.
5948pub struct SplineRibbon {
5949    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3SplineRibbon>,
5950}
5951
5952impl Drop for SplineRibbon {
5953    fn drop(&mut self) {
5954        // SAFETY: `raw` came from a native constructor and Drop runs once.
5955        unsafe { ffi::whiteout_m3_M3SplineRibbon_delete(self.raw.as_ptr()) }
5956    }
5957}
5958
5959impl SplineRibbon {
5960    /// # Safety
5961    /// `raw` must be a live handle this value takes ownership of.
5962    #[allow(dead_code)] // used by whichever methods return this type
5963    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3SplineRibbon) -> Option<Self> {
5964        core::ptr::NonNull::new(raw).map(|raw| SplineRibbon { raw })
5965    }
5966}
5967
5968// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
5969// is deliberately NOT implemented — the C++ types make no documented
5970// guarantee about concurrent use, and claiming one we haven't verified
5971// would be unsound. See `@bind thread_safe` in the plan.
5972unsafe impl Send for SplineRibbon {}
5973
5974impl core::fmt::Debug for SplineRibbon {
5975    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5976        f.debug_struct("SplineRibbon").finish_non_exhaustive()
5977    }
5978}
5979
5980impl SplineRibbon {
5981    /// # Panics
5982    /// Panics if the native allocation fails.
5983    pub fn new() -> Self {
5984        // SAFETY: the native constructor returns a live handle; a null here
5985        // means the library is unusable.
5986        unsafe {
5987            let raw = ffi::whiteout_m3_M3SplineRibbon_new();
5988            Self::from_raw(raw).expect("native SplineRibbon allocation failed")
5989        }
5990    }
5991
5992    /// Emission point offset from bone
5993    pub fn emission_offset(&self) -> crate::math::Vector3f {
5994        // SAFETY: the getter returns an interior pointer to a
5995        // layout-identical POD; we copy it out immediately.
5996        unsafe {
5997            *(ffi::whiteout_m3_M3SplineRibbon_get_emissionOffset(self.raw.as_ptr())
5998                as *const crate::math::Vector3f)
5999        }
6000    }
6001
6002    pub fn set_emission_offset(&mut self, value: crate::math::Vector3f) {
6003        // SAFETY: as above, in the other direction.
6004        unsafe {
6005            ffi::whiteout_m3_M3SplineRibbon_set_emissionOffset(
6006                self.raw.as_ptr(),
6007                &value as *const crate::math::Vector3f as *const _,
6008            )
6009        }
6010    }
6011
6012    /// Emission direction vector
6013    pub fn emission_vector(&self) -> crate::math::Vector3f {
6014        // SAFETY: the getter returns an interior pointer to a
6015        // layout-identical POD; we copy it out immediately.
6016        unsafe {
6017            *(ffi::whiteout_m3_M3SplineRibbon_get_emissionVector(self.raw.as_ptr())
6018                as *const crate::math::Vector3f)
6019        }
6020    }
6021
6022    pub fn set_emission_vector(&mut self, value: crate::math::Vector3f) {
6023        // SAFETY: as above, in the other direction.
6024        unsafe {
6025            ffi::whiteout_m3_M3SplineRibbon_set_emissionVector(
6026                self.raw.as_ptr(),
6027                &value as *const crate::math::Vector3f as *const _,
6028            )
6029        }
6030    }
6031
6032    /// Animated base velocity
6033    /// Borrows the field in place — no copy, no allocation.
6034    pub fn velocity(&self) -> crate::support::Ref<'_, AnimRefF32> {
6035        // SAFETY: an interior pointer into `self`, valid for this
6036        // borrow and never freed by the `Ref`.
6037        unsafe {
6038            crate::support::Ref::new(AnimRefF32 {
6039                raw: core::ptr::NonNull::new_unchecked(
6040                    ffi::whiteout_m3_M3SplineRibbon_get_velocity(self.raw.as_ptr()),
6041                ),
6042            })
6043        }
6044    }
6045
6046    pub fn velocity_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6047        // SAFETY: as above; `&mut self` guarantees exclusivity.
6048        unsafe {
6049            crate::support::RefMut::new(AnimRefF32 {
6050                raw: core::ptr::NonNull::new_unchecked(
6051                    ffi::whiteout_m3_M3SplineRibbon_get_velocity(self.raw.as_ptr()),
6052                ),
6053            })
6054        }
6055    }
6056
6057    /// Reserved (always 0)
6058    pub fn reserved(&self) -> u32 {
6059        // SAFETY: plain scalar read through a live handle.
6060        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_reserved(self.raw.as_ptr()) }
6061    }
6062
6063    pub fn set_reserved(&mut self, value: u32) {
6064        // SAFETY: plain scalar write through a live handle.
6065        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_reserved(self.raw.as_ptr(), value) }
6066    }
6067
6068    /// Index into BONE array
6069    pub fn bone_index(&self) -> u32 {
6070        // SAFETY: plain scalar read through a live handle.
6071        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_boneIndex(self.raw.as_ptr()) }
6072    }
6073
6074    pub fn set_bone_index(&mut self, value: u32) {
6075        // SAFETY: plain scalar write through a live handle.
6076        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_boneIndex(self.raw.as_ptr(), value) }
6077    }
6078
6079    /// Animated base velocity factor
6080    /// Borrows the field in place — no copy, no allocation.
6081    pub fn velocity_base_factor(&self) -> crate::support::Ref<'_, AnimRefF32> {
6082        // SAFETY: an interior pointer into `self`, valid for this
6083        // borrow and never freed by the `Ref`.
6084        unsafe {
6085            crate::support::Ref::new(AnimRefF32 {
6086                raw: core::ptr::NonNull::new_unchecked(
6087                    ffi::whiteout_m3_M3SplineRibbon_get_velocityBaseFactor(self.raw.as_ptr()),
6088                ),
6089            })
6090        }
6091    }
6092
6093    pub fn velocity_base_factor_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6094        // SAFETY: as above; `&mut self` guarantees exclusivity.
6095        unsafe {
6096            crate::support::RefMut::new(AnimRefF32 {
6097                raw: core::ptr::NonNull::new_unchecked(
6098                    ffi::whiteout_m3_M3SplineRibbon_get_velocityBaseFactor(self.raw.as_ptr()),
6099                ),
6100            })
6101        }
6102    }
6103
6104    /// Animated end velocity factor
6105    /// Borrows the field in place — no copy, no allocation.
6106    pub fn velocity_end_factor(&self) -> crate::support::Ref<'_, AnimRefF32> {
6107        // SAFETY: an interior pointer into `self`, valid for this
6108        // borrow and never freed by the `Ref`.
6109        unsafe {
6110            crate::support::Ref::new(AnimRefF32 {
6111                raw: core::ptr::NonNull::new_unchecked(
6112                    ffi::whiteout_m3_M3SplineRibbon_get_velocityEndFactor(self.raw.as_ptr()),
6113                ),
6114            })
6115        }
6116    }
6117
6118    pub fn velocity_end_factor_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6119        // SAFETY: as above; `&mut self` guarantees exclusivity.
6120        unsafe {
6121            crate::support::RefMut::new(AnimRefF32 {
6122                raw: core::ptr::NonNull::new_unchecked(
6123                    ffi::whiteout_m3_M3SplineRibbon_get_velocityEndFactor(self.raw.as_ptr()),
6124                ),
6125            })
6126        }
6127    }
6128
6129    /// Yaw variation type
6130    pub fn yaw_type(&self) -> u32 {
6131        // SAFETY: plain scalar read through a live handle.
6132        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_yawType(self.raw.as_ptr()) }
6133    }
6134
6135    pub fn set_yaw_type(&mut self, value: u32) {
6136        // SAFETY: plain scalar write through a live handle.
6137        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_yawType(self.raw.as_ptr(), value) }
6138    }
6139
6140    /// Yaw variation amplitude
6141    /// Borrows the field in place — no copy, no allocation.
6142    pub fn yaw_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
6143        // SAFETY: an interior pointer into `self`, valid for this
6144        // borrow and never freed by the `Ref`.
6145        unsafe {
6146            crate::support::Ref::new(AnimRefF32 {
6147                raw: core::ptr::NonNull::new_unchecked(
6148                    ffi::whiteout_m3_M3SplineRibbon_get_yawAmplitude(self.raw.as_ptr()),
6149                ),
6150            })
6151        }
6152    }
6153
6154    pub fn yaw_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6155        // SAFETY: as above; `&mut self` guarantees exclusivity.
6156        unsafe {
6157            crate::support::RefMut::new(AnimRefF32 {
6158                raw: core::ptr::NonNull::new_unchecked(
6159                    ffi::whiteout_m3_M3SplineRibbon_get_yawAmplitude(self.raw.as_ptr()),
6160                ),
6161            })
6162        }
6163    }
6164
6165    /// Yaw variation frequency
6166    /// Borrows the field in place — no copy, no allocation.
6167    pub fn yaw_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
6168        // SAFETY: an interior pointer into `self`, valid for this
6169        // borrow and never freed by the `Ref`.
6170        unsafe {
6171            crate::support::Ref::new(AnimRefF32 {
6172                raw: core::ptr::NonNull::new_unchecked(
6173                    ffi::whiteout_m3_M3SplineRibbon_get_yawFrequency(self.raw.as_ptr()),
6174                ),
6175            })
6176        }
6177    }
6178
6179    pub fn yaw_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6180        // SAFETY: as above; `&mut self` guarantees exclusivity.
6181        unsafe {
6182            crate::support::RefMut::new(AnimRefF32 {
6183                raw: core::ptr::NonNull::new_unchecked(
6184                    ffi::whiteout_m3_M3SplineRibbon_get_yawFrequency(self.raw.as_ptr()),
6185                ),
6186            })
6187        }
6188    }
6189
6190    /// Pitch variation type
6191    pub fn pitch_type(&self) -> u32 {
6192        // SAFETY: plain scalar read through a live handle.
6193        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_pitchType(self.raw.as_ptr()) }
6194    }
6195
6196    pub fn set_pitch_type(&mut self, value: u32) {
6197        // SAFETY: plain scalar write through a live handle.
6198        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_pitchType(self.raw.as_ptr(), value) }
6199    }
6200
6201    /// Pitch variation amplitude
6202    /// Borrows the field in place — no copy, no allocation.
6203    pub fn pitch_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
6204        // SAFETY: an interior pointer into `self`, valid for this
6205        // borrow and never freed by the `Ref`.
6206        unsafe {
6207            crate::support::Ref::new(AnimRefF32 {
6208                raw: core::ptr::NonNull::new_unchecked(
6209                    ffi::whiteout_m3_M3SplineRibbon_get_pitchAmplitude(self.raw.as_ptr()),
6210                ),
6211            })
6212        }
6213    }
6214
6215    pub fn pitch_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6216        // SAFETY: as above; `&mut self` guarantees exclusivity.
6217        unsafe {
6218            crate::support::RefMut::new(AnimRefF32 {
6219                raw: core::ptr::NonNull::new_unchecked(
6220                    ffi::whiteout_m3_M3SplineRibbon_get_pitchAmplitude(self.raw.as_ptr()),
6221                ),
6222            })
6223        }
6224    }
6225
6226    /// Pitch variation frequency
6227    /// Borrows the field in place — no copy, no allocation.
6228    pub fn pitch_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
6229        // SAFETY: an interior pointer into `self`, valid for this
6230        // borrow and never freed by the `Ref`.
6231        unsafe {
6232            crate::support::Ref::new(AnimRefF32 {
6233                raw: core::ptr::NonNull::new_unchecked(
6234                    ffi::whiteout_m3_M3SplineRibbon_get_pitchFrequency(self.raw.as_ptr()),
6235                ),
6236            })
6237        }
6238    }
6239
6240    pub fn pitch_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6241        // SAFETY: as above; `&mut self` guarantees exclusivity.
6242        unsafe {
6243            crate::support::RefMut::new(AnimRefF32 {
6244                raw: core::ptr::NonNull::new_unchecked(
6245                    ffi::whiteout_m3_M3SplineRibbon_get_pitchFrequency(self.raw.as_ptr()),
6246                ),
6247            })
6248        }
6249    }
6250
6251    /// Velocity variation type
6252    pub fn velocity_type(&self) -> u32 {
6253        // SAFETY: plain scalar read through a live handle.
6254        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_velocityType(self.raw.as_ptr()) }
6255    }
6256
6257    pub fn set_velocity_type(&mut self, value: u32) {
6258        // SAFETY: plain scalar write through a live handle.
6259        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_velocityType(self.raw.as_ptr(), value) }
6260    }
6261
6262    /// Velocity variation amplitude
6263    /// Borrows the field in place — no copy, no allocation.
6264    pub fn velocity_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
6265        // SAFETY: an interior pointer into `self`, valid for this
6266        // borrow and never freed by the `Ref`.
6267        unsafe {
6268            crate::support::Ref::new(AnimRefF32 {
6269                raw: core::ptr::NonNull::new_unchecked(
6270                    ffi::whiteout_m3_M3SplineRibbon_get_velocityAmplitude(self.raw.as_ptr()),
6271                ),
6272            })
6273        }
6274    }
6275
6276    pub fn velocity_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6277        // SAFETY: as above; `&mut self` guarantees exclusivity.
6278        unsafe {
6279            crate::support::RefMut::new(AnimRefF32 {
6280                raw: core::ptr::NonNull::new_unchecked(
6281                    ffi::whiteout_m3_M3SplineRibbon_get_velocityAmplitude(self.raw.as_ptr()),
6282                ),
6283            })
6284        }
6285    }
6286
6287    /// Velocity variation frequency
6288    /// Borrows the field in place — no copy, no allocation.
6289    pub fn velocity_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
6290        // SAFETY: an interior pointer into `self`, valid for this
6291        // borrow and never freed by the `Ref`.
6292        unsafe {
6293            crate::support::Ref::new(AnimRefF32 {
6294                raw: core::ptr::NonNull::new_unchecked(
6295                    ffi::whiteout_m3_M3SplineRibbon_get_velocityFrequency(self.raw.as_ptr()),
6296                ),
6297            })
6298        }
6299    }
6300
6301    pub fn velocity_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6302        // SAFETY: as above; `&mut self` guarantees exclusivity.
6303        unsafe {
6304            crate::support::RefMut::new(AnimRefF32 {
6305                raw: core::ptr::NonNull::new_unchecked(
6306                    ffi::whiteout_m3_M3SplineRibbon_get_velocityFrequency(self.raw.as_ptr()),
6307                ),
6308            })
6309        }
6310    }
6311
6312    /// Animated yaw angle
6313    /// Borrows the field in place — no copy, no allocation.
6314    pub fn yaw(&self) -> crate::support::Ref<'_, AnimRefF32> {
6315        // SAFETY: an interior pointer into `self`, valid for this
6316        // borrow and never freed by the `Ref`.
6317        unsafe {
6318            crate::support::Ref::new(AnimRefF32 {
6319                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SplineRibbon_get_yaw(
6320                    self.raw.as_ptr(),
6321                )),
6322            })
6323        }
6324    }
6325
6326    pub fn yaw_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6327        // SAFETY: as above; `&mut self` guarantees exclusivity.
6328        unsafe {
6329            crate::support::RefMut::new(AnimRefF32 {
6330                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SplineRibbon_get_yaw(
6331                    self.raw.as_ptr(),
6332                )),
6333            })
6334        }
6335    }
6336
6337    /// Animated pitch angle
6338    /// Borrows the field in place — no copy, no allocation.
6339    pub fn pitch(&self) -> crate::support::Ref<'_, AnimRefF32> {
6340        // SAFETY: an interior pointer into `self`, valid for this
6341        // borrow and never freed by the `Ref`.
6342        unsafe {
6343            crate::support::Ref::new(AnimRefF32 {
6344                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SplineRibbon_get_pitch(
6345                    self.raw.as_ptr(),
6346                )),
6347            })
6348        }
6349    }
6350
6351    pub fn pitch_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6352        // SAFETY: as above; `&mut self` guarantees exclusivity.
6353        unsafe {
6354            crate::support::RefMut::new(AnimRefF32 {
6355                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SplineRibbon_get_pitch(
6356                    self.raw.as_ptr(),
6357                )),
6358            })
6359        }
6360    }
6361
6362    /// Precomputed ≈ 0.01 / |emissionVector|
6363    pub fn emission_vector_norm_factor(&self) -> f32 {
6364        // SAFETY: plain scalar read through a live handle.
6365        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_emissionVectorNormFactor(self.raw.as_ptr()) }
6366    }
6367
6368    pub fn set_emission_vector_norm_factor(&mut self, value: f32) {
6369        // SAFETY: plain scalar write through a live handle.
6370        unsafe {
6371            ffi::whiteout_m3_M3SplineRibbon_set_emissionVectorNormFactor(self.raw.as_ptr(), value)
6372        }
6373    }
6374
6375    /// Precomputed ≈ 0.01 / velocity.initValue
6376    pub fn velocity_norm_factor(&self) -> f32 {
6377        // SAFETY: plain scalar read through a live handle.
6378        unsafe { ffi::whiteout_m3_M3SplineRibbon_get_velocityNormFactor(self.raw.as_ptr()) }
6379    }
6380
6381    pub fn set_velocity_norm_factor(&mut self, value: f32) {
6382        // SAFETY: plain scalar write through a live handle.
6383        unsafe { ffi::whiteout_m3_M3SplineRibbon_set_velocityNormFactor(self.raw.as_ptr(), value) }
6384    }
6385}
6386
6387impl Default for SplineRibbon {
6388    fn default() -> Self {
6389        Self::new()
6390    }
6391}
6392
6393/// RIB_ — Ribbon emitter (v4–v9, 744–760 bytes)
6394///
6395/// Ribbon strip effect with per-particle lifetime, velocity, color/size curves, physics, noise, spline segments, variation channels, and smoothing/collision settings. Shares many fields with ParticleEmitter.
6396pub struct RibbonEmitter {
6397    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3RibbonEmitter>,
6398}
6399
6400impl Drop for RibbonEmitter {
6401    fn drop(&mut self) {
6402        // SAFETY: `raw` came from a native constructor and Drop runs once.
6403        unsafe { ffi::whiteout_m3_M3RibbonEmitter_delete(self.raw.as_ptr()) }
6404    }
6405}
6406
6407impl RibbonEmitter {
6408    /// # Safety
6409    /// `raw` must be a live handle this value takes ownership of.
6410    #[allow(dead_code)] // used by whichever methods return this type
6411    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3RibbonEmitter) -> Option<Self> {
6412        core::ptr::NonNull::new(raw).map(|raw| RibbonEmitter { raw })
6413    }
6414}
6415
6416// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6417// is deliberately NOT implemented — the C++ types make no documented
6418// guarantee about concurrent use, and claiming one we haven't verified
6419// would be unsound. See `@bind thread_safe` in the plan.
6420unsafe impl Send for RibbonEmitter {}
6421
6422impl core::fmt::Debug for RibbonEmitter {
6423    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6424        f.debug_struct("RibbonEmitter").finish_non_exhaustive()
6425    }
6426}
6427
6428impl RibbonEmitter {
6429    /// # Panics
6430    /// Panics if the native allocation fails.
6431    pub fn new() -> Self {
6432        // SAFETY: the native constructor returns a live handle; a null here
6433        // means the library is unusable.
6434        unsafe {
6435            let raw = ffi::whiteout_m3_M3RibbonEmitter_new();
6436            Self::from_raw(raw).expect("native RibbonEmitter allocation failed")
6437        }
6438    }
6439
6440    /// Primary bone index
6441    pub fn bone_index(&self) -> u16 {
6442        // SAFETY: plain scalar read through a live handle.
6443        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_boneIndex(self.raw.as_ptr()) }
6444    }
6445
6446    pub fn set_bone_index(&mut self, value: u16) {
6447        // SAFETY: plain scalar write through a live handle.
6448        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_boneIndex(self.raw.as_ptr(), value) }
6449    }
6450
6451    /// Fallback bone index
6452    pub fn bone_index_fallback(&self) -> u16 {
6453        // SAFETY: plain scalar read through a live handle.
6454        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_boneIndexFallback(self.raw.as_ptr()) }
6455    }
6456
6457    pub fn set_bone_index_fallback(&mut self, value: u16) {
6458        // SAFETY: plain scalar write through a live handle.
6459        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_boneIndexFallback(self.raw.as_ptr(), value) }
6460    }
6461
6462    /// Index into MATM material map array
6463    pub fn material_index(&self) -> u32 {
6464        // SAFETY: plain scalar read through a live handle.
6465        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_materialIndex(self.raw.as_ptr()) }
6466    }
6467
6468    pub fn set_material_index(&mut self, value: u32) {
6469        // SAFETY: plain scalar write through a live handle.
6470        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_materialIndex(self.raw.as_ptr(), value) }
6471    }
6472
6473    /// Additional flags (v8+)
6474    pub fn additional_flags(&self) -> RibbonAdditionalFlag {
6475        // SAFETY: scalar read; a flag set accepts any bits.
6476        RibbonAdditionalFlag(unsafe {
6477            ffi::whiteout_m3_M3RibbonEmitter_get_additionalFlags(self.raw.as_ptr())
6478        })
6479    }
6480
6481    pub fn set_additional_flags(&mut self, value: RibbonAdditionalFlag) {
6482        // SAFETY: scalar write through a live handle.
6483        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_additionalFlags(self.raw.as_ptr(), value.0) }
6484    }
6485
6486    /// Initial ribbon segment speed
6487    /// Borrows the field in place — no copy, no allocation.
6488    pub fn initial_speed(&self) -> crate::support::Ref<'_, AnimRefF32> {
6489        // SAFETY: an interior pointer into `self`, valid for this
6490        // borrow and never freed by the `Ref`.
6491        unsafe {
6492            crate::support::Ref::new(AnimRefF32 {
6493                raw: core::ptr::NonNull::new_unchecked(
6494                    ffi::whiteout_m3_M3RibbonEmitter_get_initialSpeed(self.raw.as_ptr()),
6495                ),
6496            })
6497        }
6498    }
6499
6500    pub fn initial_speed_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6501        // SAFETY: as above; `&mut self` guarantees exclusivity.
6502        unsafe {
6503            crate::support::RefMut::new(AnimRefF32 {
6504                raw: core::ptr::NonNull::new_unchecked(
6505                    ffi::whiteout_m3_M3RibbonEmitter_get_initialSpeed(self.raw.as_ptr()),
6506                ),
6507            })
6508        }
6509    }
6510
6511    /// Random speed variation
6512    /// Borrows the field in place — no copy, no allocation.
6513    pub fn initial_speed_random(&self) -> crate::support::Ref<'_, AnimRefF32> {
6514        // SAFETY: an interior pointer into `self`, valid for this
6515        // borrow and never freed by the `Ref`.
6516        unsafe {
6517            crate::support::Ref::new(AnimRefF32 {
6518                raw: core::ptr::NonNull::new_unchecked(
6519                    ffi::whiteout_m3_M3RibbonEmitter_get_initialSpeedRandom(self.raw.as_ptr()),
6520                ),
6521            })
6522        }
6523    }
6524
6525    pub fn initial_speed_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6526        // SAFETY: as above; `&mut self` guarantees exclusivity.
6527        unsafe {
6528            crate::support::RefMut::new(AnimRefF32 {
6529                raw: core::ptr::NonNull::new_unchecked(
6530                    ffi::whiteout_m3_M3RibbonEmitter_get_initialSpeedRandom(self.raw.as_ptr()),
6531                ),
6532            })
6533        }
6534    }
6535
6536    /// Initial yaw angle
6537    /// Borrows the field in place — no copy, no allocation.
6538    pub fn initial_yaw(&self) -> crate::support::Ref<'_, AnimRefF32> {
6539        // SAFETY: an interior pointer into `self`, valid for this
6540        // borrow and never freed by the `Ref`.
6541        unsafe {
6542            crate::support::Ref::new(AnimRefF32 {
6543                raw: core::ptr::NonNull::new_unchecked(
6544                    ffi::whiteout_m3_M3RibbonEmitter_get_initialYaw(self.raw.as_ptr()),
6545                ),
6546            })
6547        }
6548    }
6549
6550    pub fn initial_yaw_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6551        // SAFETY: as above; `&mut self` guarantees exclusivity.
6552        unsafe {
6553            crate::support::RefMut::new(AnimRefF32 {
6554                raw: core::ptr::NonNull::new_unchecked(
6555                    ffi::whiteout_m3_M3RibbonEmitter_get_initialYaw(self.raw.as_ptr()),
6556                ),
6557            })
6558        }
6559    }
6560
6561    /// Initial pitch angle
6562    /// Borrows the field in place — no copy, no allocation.
6563    pub fn initial_pitch(&self) -> crate::support::Ref<'_, AnimRefF32> {
6564        // SAFETY: an interior pointer into `self`, valid for this
6565        // borrow and never freed by the `Ref`.
6566        unsafe {
6567            crate::support::Ref::new(AnimRefF32 {
6568                raw: core::ptr::NonNull::new_unchecked(
6569                    ffi::whiteout_m3_M3RibbonEmitter_get_initialPitch(self.raw.as_ptr()),
6570                ),
6571            })
6572        }
6573    }
6574
6575    pub fn initial_pitch_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6576        // SAFETY: as above; `&mut self` guarantees exclusivity.
6577        unsafe {
6578            crate::support::RefMut::new(AnimRefF32 {
6579                raw: core::ptr::NonNull::new_unchecked(
6580                    ffi::whiteout_m3_M3RibbonEmitter_get_initialPitch(self.raw.as_ptr()),
6581                ),
6582            })
6583        }
6584    }
6585
6586    /// Initial horizontal spread
6587    /// Borrows the field in place — no copy, no allocation.
6588    pub fn initial_horizontal(&self) -> crate::support::Ref<'_, AnimRefF32> {
6589        // SAFETY: an interior pointer into `self`, valid for this
6590        // borrow and never freed by the `Ref`.
6591        unsafe {
6592            crate::support::Ref::new(AnimRefF32 {
6593                raw: core::ptr::NonNull::new_unchecked(
6594                    ffi::whiteout_m3_M3RibbonEmitter_get_initialHorizontal(self.raw.as_ptr()),
6595                ),
6596            })
6597        }
6598    }
6599
6600    pub fn initial_horizontal_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6601        // SAFETY: as above; `&mut self` guarantees exclusivity.
6602        unsafe {
6603            crate::support::RefMut::new(AnimRefF32 {
6604                raw: core::ptr::NonNull::new_unchecked(
6605                    ffi::whiteout_m3_M3RibbonEmitter_get_initialHorizontal(self.raw.as_ptr()),
6606                ),
6607            })
6608        }
6609    }
6610
6611    /// Initial vertical spread
6612    /// Borrows the field in place — no copy, no allocation.
6613    pub fn initial_vertical(&self) -> crate::support::Ref<'_, AnimRefF32> {
6614        // SAFETY: an interior pointer into `self`, valid for this
6615        // borrow and never freed by the `Ref`.
6616        unsafe {
6617            crate::support::Ref::new(AnimRefF32 {
6618                raw: core::ptr::NonNull::new_unchecked(
6619                    ffi::whiteout_m3_M3RibbonEmitter_get_initialVertical(self.raw.as_ptr()),
6620                ),
6621            })
6622        }
6623    }
6624
6625    pub fn initial_vertical_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6626        // SAFETY: as above; `&mut self` guarantees exclusivity.
6627        unsafe {
6628            crate::support::RefMut::new(AnimRefF32 {
6629                raw: core::ptr::NonNull::new_unchecked(
6630                    ffi::whiteout_m3_M3RibbonEmitter_get_initialVertical(self.raw.as_ptr()),
6631                ),
6632            })
6633        }
6634    }
6635
6636    /// Base segment lifetime
6637    /// Borrows the field in place — no copy, no allocation.
6638    pub fn lifetime(&self) -> crate::support::Ref<'_, AnimRefF32> {
6639        // SAFETY: an interior pointer into `self`, valid for this
6640        // borrow and never freed by the `Ref`.
6641        unsafe {
6642            crate::support::Ref::new(AnimRefF32 {
6643                raw: core::ptr::NonNull::new_unchecked(
6644                    ffi::whiteout_m3_M3RibbonEmitter_get_lifetime(self.raw.as_ptr()),
6645                ),
6646            })
6647        }
6648    }
6649
6650    pub fn lifetime_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6651        // SAFETY: as above; `&mut self` guarantees exclusivity.
6652        unsafe {
6653            crate::support::RefMut::new(AnimRefF32 {
6654                raw: core::ptr::NonNull::new_unchecked(
6655                    ffi::whiteout_m3_M3RibbonEmitter_get_lifetime(self.raw.as_ptr()),
6656                ),
6657            })
6658        }
6659    }
6660
6661    /// Random lifetime variation
6662    /// Borrows the field in place — no copy, no allocation.
6663    pub fn lifetime_random(&self) -> crate::support::Ref<'_, AnimRefF32> {
6664        // SAFETY: an interior pointer into `self`, valid for this
6665        // borrow and never freed by the `Ref`.
6666        unsafe {
6667            crate::support::Ref::new(AnimRefF32 {
6668                raw: core::ptr::NonNull::new_unchecked(
6669                    ffi::whiteout_m3_M3RibbonEmitter_get_lifetimeRandom(self.raw.as_ptr()),
6670                ),
6671            })
6672        }
6673    }
6674
6675    pub fn lifetime_random_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
6676        // SAFETY: as above; `&mut self` guarantees exclusivity.
6677        unsafe {
6678            crate::support::RefMut::new(AnimRefF32 {
6679                raw: core::ptr::NonNull::new_unchecked(
6680                    ffi::whiteout_m3_M3RibbonEmitter_get_lifetimeRandom(self.raw.as_ptr()),
6681                ),
6682            })
6683        }
6684    }
6685
6686    /// Kill radius
6687    pub fn kill_radius(&self) -> u32 {
6688        // SAFETY: plain scalar read through a live handle.
6689        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_killRadius(self.raw.as_ptr()) }
6690    }
6691
6692    pub fn set_kill_radius(&mut self, value: u32) {
6693        // SAFETY: plain scalar write through a live handle.
6694        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_killRadius(self.raw.as_ptr(), value) }
6695    }
6696
6697    /// Gravity X component
6698    pub fn gravity_x(&self) -> f32 {
6699        // SAFETY: plain scalar read through a live handle.
6700        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_gravityX(self.raw.as_ptr()) }
6701    }
6702
6703    pub fn set_gravity_x(&mut self, value: f32) {
6704        // SAFETY: plain scalar write through a live handle.
6705        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_gravityX(self.raw.as_ptr(), value) }
6706    }
6707
6708    /// Gravity Y component
6709    pub fn gravity_y(&self) -> f32 {
6710        // SAFETY: plain scalar read through a live handle.
6711        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_gravityY(self.raw.as_ptr()) }
6712    }
6713
6714    pub fn set_gravity_y(&mut self, value: f32) {
6715        // SAFETY: plain scalar write through a live handle.
6716        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_gravityY(self.raw.as_ptr(), value) }
6717    }
6718
6719    /// Gravity Z component
6720    pub fn gravity(&self) -> f32 {
6721        // SAFETY: plain scalar read through a live handle.
6722        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_gravity(self.raw.as_ptr()) }
6723    }
6724
6725    pub fn set_gravity(&mut self, value: f32) {
6726        // SAFETY: plain scalar write through a live handle.
6727        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_gravity(self.raw.as_ptr(), value) }
6728    }
6729
6730    /// Size midpoint time (0–1)
6731    pub fn size_mid_time(&self) -> f32 {
6732        // SAFETY: plain scalar read through a live handle.
6733        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_sizeMidTime(self.raw.as_ptr()) }
6734    }
6735
6736    pub fn set_size_mid_time(&mut self, value: f32) {
6737        // SAFETY: plain scalar write through a live handle.
6738        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_sizeMidTime(self.raw.as_ptr(), value) }
6739    }
6740
6741    /// Color midpoint time (0–1)
6742    pub fn color_mid_time(&self) -> f32 {
6743        // SAFETY: plain scalar read through a live handle.
6744        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_colorMidTime(self.raw.as_ptr()) }
6745    }
6746
6747    pub fn set_color_mid_time(&mut self, value: f32) {
6748        // SAFETY: plain scalar write through a live handle.
6749        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_colorMidTime(self.raw.as_ptr(), value) }
6750    }
6751
6752    /// Alpha midpoint time (0–1)
6753    pub fn alpha_mid_time(&self) -> f32 {
6754        // SAFETY: plain scalar read through a live handle.
6755        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_alphaMidTime(self.raw.as_ptr()) }
6756    }
6757
6758    pub fn set_alpha_mid_time(&mut self, value: f32) {
6759        // SAFETY: plain scalar write through a live handle.
6760        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_alphaMidTime(self.raw.as_ptr(), value) }
6761    }
6762
6763    /// Rotation midpoint time (0–1)
6764    pub fn rotation_mid_time(&self) -> f32 {
6765        // SAFETY: plain scalar read through a live handle.
6766        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_rotationMidTime(self.raw.as_ptr()) }
6767    }
6768
6769    pub fn set_rotation_mid_time(&mut self, value: f32) {
6770        // SAFETY: plain scalar write through a live handle.
6771        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_rotationMidTime(self.raw.as_ptr(), value) }
6772    }
6773
6774    /// Size hold time at midpoint
6775    pub fn size_mid_hold_time(&self) -> f32 {
6776        // SAFETY: plain scalar read through a live handle.
6777        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_sizeMidHoldTime(self.raw.as_ptr()) }
6778    }
6779
6780    pub fn set_size_mid_hold_time(&mut self, value: f32) {
6781        // SAFETY: plain scalar write through a live handle.
6782        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_sizeMidHoldTime(self.raw.as_ptr(), value) }
6783    }
6784
6785    /// Color hold time at midpoint
6786    pub fn color_mid_hold_time(&self) -> f32 {
6787        // SAFETY: plain scalar read through a live handle.
6788        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_colorMidHoldTime(self.raw.as_ptr()) }
6789    }
6790
6791    pub fn set_color_mid_hold_time(&mut self, value: f32) {
6792        // SAFETY: plain scalar write through a live handle.
6793        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_colorMidHoldTime(self.raw.as_ptr(), value) }
6794    }
6795
6796    /// Alpha hold time at midpoint
6797    pub fn alpha_mid_hold_time(&self) -> f32 {
6798        // SAFETY: plain scalar read through a live handle.
6799        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_alphaMidHoldTime(self.raw.as_ptr()) }
6800    }
6801
6802    pub fn set_alpha_mid_hold_time(&mut self, value: f32) {
6803        // SAFETY: plain scalar write through a live handle.
6804        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_alphaMidHoldTime(self.raw.as_ptr(), value) }
6805    }
6806
6807    /// Rotation hold time at midpoint
6808    pub fn rotation_mid_hold_time(&self) -> f32 {
6809        // SAFETY: plain scalar read through a live handle.
6810        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_rotationMidHoldTime(self.raw.as_ptr()) }
6811    }
6812
6813    pub fn set_rotation_mid_hold_time(&mut self, value: f32) {
6814        // SAFETY: plain scalar write through a live handle.
6815        unsafe {
6816            ffi::whiteout_m3_M3RibbonEmitter_set_rotationMidHoldTime(self.raw.as_ptr(), value)
6817        }
6818    }
6819
6820    /// Size curve (start, mid, end)
6821    /// Borrows the field in place — no copy, no allocation.
6822    pub fn size_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
6823        // SAFETY: an interior pointer into `self`, valid for this
6824        // borrow and never freed by the `Ref`.
6825        unsafe {
6826            crate::support::Ref::new(AnimRefVector3f {
6827                raw: core::ptr::NonNull::new_unchecked(
6828                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeAnimation(self.raw.as_ptr()),
6829                ),
6830            })
6831        }
6832    }
6833
6834    pub fn size_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
6835        // SAFETY: as above; `&mut self` guarantees exclusivity.
6836        unsafe {
6837            crate::support::RefMut::new(AnimRefVector3f {
6838                raw: core::ptr::NonNull::new_unchecked(
6839                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeAnimation(self.raw.as_ptr()),
6840                ),
6841            })
6842        }
6843    }
6844
6845    /// Rotation curve (start, mid, end)
6846    /// Borrows the field in place — no copy, no allocation.
6847    pub fn rotation_animation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
6848        // SAFETY: an interior pointer into `self`, valid for this
6849        // borrow and never freed by the `Ref`.
6850        unsafe {
6851            crate::support::Ref::new(AnimRefVector3f {
6852                raw: core::ptr::NonNull::new_unchecked(
6853                    ffi::whiteout_m3_M3RibbonEmitter_get_rotationAnimation(self.raw.as_ptr()),
6854                ),
6855            })
6856        }
6857    }
6858
6859    pub fn rotation_animation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
6860        // SAFETY: as above; `&mut self` guarantees exclusivity.
6861        unsafe {
6862            crate::support::RefMut::new(AnimRefVector3f {
6863                raw: core::ptr::NonNull::new_unchecked(
6864                    ffi::whiteout_m3_M3RibbonEmitter_get_rotationAnimation(self.raw.as_ptr()),
6865                ),
6866            })
6867        }
6868    }
6869
6870    /// Color at birth
6871    /// Borrows the field in place — no copy, no allocation.
6872    pub fn color_start(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
6873        // SAFETY: an interior pointer into `self`, valid for this
6874        // borrow and never freed by the `Ref`.
6875        unsafe {
6876            crate::support::Ref::new(AnimRefM3ColorBGRA {
6877                raw: core::ptr::NonNull::new_unchecked(
6878                    ffi::whiteout_m3_M3RibbonEmitter_get_colorStart(self.raw.as_ptr()),
6879                ),
6880            })
6881        }
6882    }
6883
6884    pub fn color_start_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
6885        // SAFETY: as above; `&mut self` guarantees exclusivity.
6886        unsafe {
6887            crate::support::RefMut::new(AnimRefM3ColorBGRA {
6888                raw: core::ptr::NonNull::new_unchecked(
6889                    ffi::whiteout_m3_M3RibbonEmitter_get_colorStart(self.raw.as_ptr()),
6890                ),
6891            })
6892        }
6893    }
6894
6895    /// Color at midpoint
6896    /// Borrows the field in place — no copy, no allocation.
6897    pub fn color_mid(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
6898        // SAFETY: an interior pointer into `self`, valid for this
6899        // borrow and never freed by the `Ref`.
6900        unsafe {
6901            crate::support::Ref::new(AnimRefM3ColorBGRA {
6902                raw: core::ptr::NonNull::new_unchecked(
6903                    ffi::whiteout_m3_M3RibbonEmitter_get_colorMid(self.raw.as_ptr()),
6904                ),
6905            })
6906        }
6907    }
6908
6909    pub fn color_mid_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
6910        // SAFETY: as above; `&mut self` guarantees exclusivity.
6911        unsafe {
6912            crate::support::RefMut::new(AnimRefM3ColorBGRA {
6913                raw: core::ptr::NonNull::new_unchecked(
6914                    ffi::whiteout_m3_M3RibbonEmitter_get_colorMid(self.raw.as_ptr()),
6915                ),
6916            })
6917        }
6918    }
6919
6920    /// Color at death
6921    /// Borrows the field in place — no copy, no allocation.
6922    pub fn color_end(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
6923        // SAFETY: an interior pointer into `self`, valid for this
6924        // borrow and never freed by the `Ref`.
6925        unsafe {
6926            crate::support::Ref::new(AnimRefM3ColorBGRA {
6927                raw: core::ptr::NonNull::new_unchecked(
6928                    ffi::whiteout_m3_M3RibbonEmitter_get_colorEnd(self.raw.as_ptr()),
6929                ),
6930            })
6931        }
6932    }
6933
6934    pub fn color_end_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
6935        // SAFETY: as above; `&mut self` guarantees exclusivity.
6936        unsafe {
6937            crate::support::RefMut::new(AnimRefM3ColorBGRA {
6938                raw: core::ptr::NonNull::new_unchecked(
6939                    ffi::whiteout_m3_M3RibbonEmitter_get_colorEnd(self.raw.as_ptr()),
6940                ),
6941            })
6942        }
6943    }
6944
6945    /// Air drag coefficient
6946    pub fn drag(&self) -> f32 {
6947        // SAFETY: plain scalar read through a live handle.
6948        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_drag(self.raw.as_ptr()) }
6949    }
6950
6951    pub fn set_drag(&mut self, value: f32) {
6952        // SAFETY: plain scalar write through a live handle.
6953        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_drag(self.raw.as_ptr(), value) }
6954    }
6955
6956    /// Segment mass
6957    pub fn mass(&self) -> f32 {
6958        // SAFETY: plain scalar read through a live handle.
6959        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_mass(self.raw.as_ptr()) }
6960    }
6961
6962    pub fn set_mass(&mut self, value: f32) {
6963        // SAFETY: plain scalar write through a live handle.
6964        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_mass(self.raw.as_ptr(), value) }
6965    }
6966
6967    /// Random mass variation
6968    pub fn mass_random(&self) -> f32 {
6969        // SAFETY: plain scalar read through a live handle.
6970        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_massRandom(self.raw.as_ptr()) }
6971    }
6972
6973    pub fn set_mass_random(&mut self, value: f32) {
6974        // SAFETY: plain scalar write through a live handle.
6975        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_massRandom(self.raw.as_ptr(), value) }
6976    }
6977
6978    /// Mass–size coupling
6979    pub fn mass_size_multiplier(&self) -> f32 {
6980        // SAFETY: plain scalar read through a live handle.
6981        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_massSizeMultiplier(self.raw.as_ptr()) }
6982    }
6983
6984    pub fn set_mass_size_multiplier(&mut self, value: f32) {
6985        // SAFETY: plain scalar write through a live handle.
6986        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_massSizeMultiplier(self.raw.as_ptr(), value) }
6987    }
6988
6989    /// Local force channel bitmask
6990    pub fn local_forces(&self) -> u16 {
6991        // SAFETY: plain scalar read through a live handle.
6992        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_localForces(self.raw.as_ptr()) }
6993    }
6994
6995    pub fn set_local_forces(&mut self, value: u16) {
6996        // SAFETY: plain scalar write through a live handle.
6997        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_localForces(self.raw.as_ptr(), value) }
6998    }
6999
7000    /// World force channel bitmask
7001    pub fn world_forces(&self) -> u16 {
7002        // SAFETY: plain scalar read through a live handle.
7003        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_worldForces(self.raw.as_ptr()) }
7004    }
7005
7006    pub fn set_world_forces(&mut self, value: u16) {
7007        // SAFETY: plain scalar write through a live handle.
7008        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_worldForces(self.raw.as_ptr(), value) }
7009    }
7010
7011    /// Fallback local force channels
7012    pub fn local_forces_fallback(&self) -> u16 {
7013        // SAFETY: plain scalar read through a live handle.
7014        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_localForcesFallback(self.raw.as_ptr()) }
7015    }
7016
7017    pub fn set_local_forces_fallback(&mut self, value: u16) {
7018        // SAFETY: plain scalar write through a live handle.
7019        unsafe {
7020            ffi::whiteout_m3_M3RibbonEmitter_set_localForcesFallback(self.raw.as_ptr(), value)
7021        }
7022    }
7023
7024    /// Fallback world force channels
7025    pub fn world_forces_fallback(&self) -> u16 {
7026        // SAFETY: plain scalar read through a live handle.
7027        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_worldForcesFallback(self.raw.as_ptr()) }
7028    }
7029
7030    pub fn set_world_forces_fallback(&mut self, value: u16) {
7031        // SAFETY: plain scalar write through a live handle.
7032        unsafe {
7033            ffi::whiteout_m3_M3RibbonEmitter_set_worldForcesFallback(self.raw.as_ptr(), value)
7034        }
7035    }
7036
7037    /// World force mass multiplier
7038    pub fn world_forces_mass_multiplier(&self) -> f32 {
7039        // SAFETY: plain scalar read through a live handle.
7040        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_worldForcesMassMultiplier(self.raw.as_ptr()) }
7041    }
7042
7043    pub fn set_world_forces_mass_multiplier(&mut self, value: f32) {
7044        // SAFETY: plain scalar write through a live handle.
7045        unsafe {
7046            ffi::whiteout_m3_M3RibbonEmitter_set_worldForcesMassMultiplier(self.raw.as_ptr(), value)
7047        }
7048    }
7049
7050    /// Noise displacement amplitude
7051    pub fn noise_amplitude(&self) -> f32 {
7052        // SAFETY: plain scalar read through a live handle.
7053        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_noiseAmplitude(self.raw.as_ptr()) }
7054    }
7055
7056    pub fn set_noise_amplitude(&mut self, value: f32) {
7057        // SAFETY: plain scalar write through a live handle.
7058        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_noiseAmplitude(self.raw.as_ptr(), value) }
7059    }
7060
7061    /// Noise spatial frequency
7062    pub fn noise_frequency(&self) -> f32 {
7063        // SAFETY: plain scalar read through a live handle.
7064        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_noiseFrequency(self.raw.as_ptr()) }
7065    }
7066
7067    pub fn set_noise_frequency(&mut self, value: f32) {
7068        // SAFETY: plain scalar write through a live handle.
7069        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_noiseFrequency(self.raw.as_ptr(), value) }
7070    }
7071
7072    /// Noise temporal coherence
7073    pub fn noise_coherence(&self) -> f32 {
7074        // SAFETY: plain scalar read through a live handle.
7075        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_noiseCoherence(self.raw.as_ptr()) }
7076    }
7077
7078    pub fn set_noise_coherence(&mut self, value: f32) {
7079        // SAFETY: plain scalar write through a live handle.
7080        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_noiseCoherence(self.raw.as_ptr(), value) }
7081    }
7082
7083    /// Noise edge sharpness
7084    pub fn noise_edge(&self) -> f32 {
7085        // SAFETY: plain scalar read through a live handle.
7086        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_noiseEdge(self.raw.as_ptr()) }
7087    }
7088
7089    pub fn set_noise_edge(&mut self, value: f32) {
7090        // SAFETY: plain scalar write through a live handle.
7091        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_noiseEdge(self.raw.as_ptr(), value) }
7092    }
7093
7094    /// Index + length
7095    pub fn index_plus_length(&self) -> u32 {
7096        // SAFETY: plain scalar read through a live handle.
7097        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_indexPlusLength(self.raw.as_ptr()) }
7098    }
7099
7100    pub fn set_index_plus_length(&mut self, value: u32) {
7101        // SAFETY: plain scalar write through a live handle.
7102        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_indexPlusLength(self.raw.as_ptr(), value) }
7103    }
7104
7105    /// Emitter shape type
7106    pub fn emitter_shape(&self) -> u32 {
7107        // SAFETY: plain scalar read through a live handle.
7108        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_emitterShape(self.raw.as_ptr()) }
7109    }
7110
7111    pub fn set_emitter_shape(&mut self, value: u32) {
7112        // SAFETY: plain scalar write through a live handle.
7113        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_emitterShape(self.raw.as_ptr(), value) }
7114    }
7115
7116    /// Ribbon cross-section type
7117    pub fn ribbon_type(&self) -> RibbonType {
7118        // SAFETY: scalar read; the discriminant is validated below.
7119        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_ribbonType(self.raw.as_ptr()) }
7120            .try_into()
7121            .expect("unknown enum discriminant from the native library")
7122    }
7123
7124    pub fn set_ribbon_type(&mut self, value: RibbonType) {
7125        // SAFETY: scalar write through a live handle.
7126        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_ribbonType(self.raw.as_ptr(), value as i32) }
7127    }
7128
7129    /// Number of ribbon divisions
7130    pub fn divisions(&self) -> f32 {
7131        // SAFETY: plain scalar read through a live handle.
7132        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_divisions(self.raw.as_ptr()) }
7133    }
7134
7135    pub fn set_divisions(&mut self, value: f32) {
7136        // SAFETY: plain scalar write through a live handle.
7137        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_divisions(self.raw.as_ptr(), value) }
7138    }
7139
7140    /// Number of cross-section edges
7141    pub fn edges(&self) -> u32 {
7142        // SAFETY: plain scalar read through a live handle.
7143        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_edges(self.raw.as_ptr()) }
7144    }
7145
7146    pub fn set_edges(&mut self, value: u32) {
7147        // SAFETY: plain scalar write through a live handle.
7148        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_edges(self.raw.as_ptr(), value) }
7149    }
7150
7151    /// Inner radius
7152    pub fn inner_radius(&self) -> f32 {
7153        // SAFETY: plain scalar read through a live handle.
7154        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_innerRadius(self.raw.as_ptr()) }
7155    }
7156
7157    pub fn set_inner_radius(&mut self, value: f32) {
7158        // SAFETY: plain scalar write through a live handle.
7159        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_innerRadius(self.raw.as_ptr(), value) }
7160    }
7161
7162    /// Animated maximum ribbon length
7163    /// Borrows the field in place — no copy, no allocation.
7164    pub fn max_length(&self) -> crate::support::Ref<'_, AnimRefF32> {
7165        // SAFETY: an interior pointer into `self`, valid for this
7166        // borrow and never freed by the `Ref`.
7167        unsafe {
7168            crate::support::Ref::new(AnimRefF32 {
7169                raw: core::ptr::NonNull::new_unchecked(
7170                    ffi::whiteout_m3_M3RibbonEmitter_get_maxLength(self.raw.as_ptr()),
7171                ),
7172            })
7173        }
7174    }
7175
7176    pub fn max_length_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7177        // SAFETY: as above; `&mut self` guarantees exclusivity.
7178        unsafe {
7179            crate::support::RefMut::new(AnimRefF32 {
7180                raw: core::ptr::NonNull::new_unchecked(
7181                    ffi::whiteout_m3_M3RibbonEmitter_get_maxLength(self.raw.as_ptr()),
7182                ),
7183            })
7184        }
7185    }
7186
7187    /// Spline ribbon segments (SRIB)
7188    pub fn spline_ribbons_len(&self) -> usize {
7189        // SAFETY: scalar read through a live handle.
7190        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_splineRibbons_count(self.raw.as_ptr()) }
7191    }
7192
7193    /// Borrows element `index` in place. `None` when out of range.
7194    pub fn spline_ribbons(&self, index: usize) -> Option<crate::support::Ref<'_, SplineRibbon>> {
7195        if index >= self.spline_ribbons_len() {
7196            return None;
7197        }
7198        // SAFETY: index checked above; the pointer is interior to `self`.
7199        unsafe {
7200            Some(crate::support::Ref::new(SplineRibbon {
7201                raw: core::ptr::NonNull::new_unchecked(
7202                    ffi::whiteout_m3_M3RibbonEmitter_get_splineRibbons_at(self.raw.as_ptr(), index),
7203                ),
7204            }))
7205        }
7206    }
7207
7208    pub fn spline_ribbons_mut(
7209        &mut self,
7210        index: usize,
7211    ) -> Option<crate::support::RefMut<'_, SplineRibbon>> {
7212        if index >= self.spline_ribbons_len() {
7213            return None;
7214        }
7215        // SAFETY: as above; `&mut self` guarantees exclusivity.
7216        unsafe {
7217            Some(crate::support::RefMut::new(SplineRibbon {
7218                raw: core::ptr::NonNull::new_unchecked(
7219                    ffi::whiteout_m3_M3RibbonEmitter_get_splineRibbons_at(self.raw.as_ptr(), index),
7220                ),
7221            }))
7222        }
7223    }
7224
7225    /// Iterate the elements, borrowing each in turn.
7226    pub fn spline_ribbons_iter(
7227        &self,
7228    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SplineRibbon>> {
7229        (0..self.spline_ribbons_len())
7230            .map(move |i| self.spline_ribbons(i).expect("index below len"))
7231    }
7232
7233    pub fn resize_spline_ribbons(&mut self, count: usize) {
7234        // SAFETY: exclusive access, so no borrow is outstanding.
7235        unsafe { ffi::whiteout_m3_M3RibbonEmitter_resize_splineRibbons(self.raw.as_ptr(), count) }
7236    }
7237
7238    /// Animated active state
7239    /// Borrows the field in place — no copy, no allocation.
7240    pub fn active(&self) -> crate::support::Ref<'_, AnimRefU32> {
7241        // SAFETY: an interior pointer into `self`, valid for this
7242        // borrow and never freed by the `Ref`.
7243        unsafe {
7244            crate::support::Ref::new(AnimRefU32 {
7245                raw: core::ptr::NonNull::new_unchecked(
7246                    ffi::whiteout_m3_M3RibbonEmitter_get_active(self.raw.as_ptr()),
7247                ),
7248            })
7249        }
7250    }
7251
7252    pub fn active_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
7253        // SAFETY: as above; `&mut self` guarantees exclusivity.
7254        unsafe {
7255            crate::support::RefMut::new(AnimRefU32 {
7256                raw: core::ptr::NonNull::new_unchecked(
7257                    ffi::whiteout_m3_M3RibbonEmitter_get_active(self.raw.as_ptr()),
7258                ),
7259            })
7260        }
7261    }
7262
7263    /// Ribbon emitter flags
7264    pub fn flags(&self) -> RibbonFlag {
7265        // SAFETY: scalar read; a flag set accepts any bits.
7266        RibbonFlag(unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_flags(self.raw.as_ptr()) })
7267    }
7268
7269    pub fn set_flags(&mut self, value: RibbonFlag) {
7270        // SAFETY: scalar write through a live handle.
7271        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_flags(self.raw.as_ptr(), value.0) }
7272    }
7273
7274    /// Size interpolation mode
7275    pub fn size_smoothing(&self) -> InterpolationMode {
7276        // SAFETY: scalar read; the discriminant is validated below.
7277        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_sizeSmoothing(self.raw.as_ptr()) }
7278            .try_into()
7279            .expect("unknown enum discriminant from the native library")
7280    }
7281
7282    pub fn set_size_smoothing(&mut self, value: InterpolationMode) {
7283        // SAFETY: scalar write through a live handle.
7284        unsafe {
7285            ffi::whiteout_m3_M3RibbonEmitter_set_sizeSmoothing(self.raw.as_ptr(), value as i32)
7286        }
7287    }
7288
7289    /// Color interpolation mode
7290    pub fn color_smoothing(&self) -> InterpolationMode {
7291        // SAFETY: scalar read; the discriminant is validated below.
7292        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_colorSmoothing(self.raw.as_ptr()) }
7293            .try_into()
7294            .expect("unknown enum discriminant from the native library")
7295    }
7296
7297    pub fn set_color_smoothing(&mut self, value: InterpolationMode) {
7298        // SAFETY: scalar write through a live handle.
7299        unsafe {
7300            ffi::whiteout_m3_M3RibbonEmitter_set_colorSmoothing(self.raw.as_ptr(), value as i32)
7301        }
7302    }
7303
7304    /// Friction coefficient
7305    pub fn friction(&self) -> f32 {
7306        // SAFETY: plain scalar read through a live handle.
7307        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_friction(self.raw.as_ptr()) }
7308    }
7309
7310    pub fn set_friction(&mut self, value: f32) {
7311        // SAFETY: plain scalar write through a live handle.
7312        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_friction(self.raw.as_ptr(), value) }
7313    }
7314
7315    /// Bounce coefficient
7316    pub fn bounce(&self) -> f32 {
7317        // SAFETY: plain scalar read through a live handle.
7318        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_bounce(self.raw.as_ptr()) }
7319    }
7320
7321    pub fn set_bounce(&mut self, value: f32) {
7322        // SAFETY: plain scalar write through a live handle.
7323        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_bounce(self.raw.as_ptr(), value) }
7324    }
7325
7326    /// LOD reduction level
7327    pub fn lod_reduce(&self) -> u32 {
7328        // SAFETY: plain scalar read through a live handle.
7329        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_lodReduce(self.raw.as_ptr()) }
7330    }
7331
7332    pub fn set_lod_reduce(&mut self, value: u32) {
7333        // SAFETY: plain scalar write through a live handle.
7334        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_lodReduce(self.raw.as_ptr(), value) }
7335    }
7336
7337    /// LOD cut-off level
7338    pub fn lod_cut(&self) -> u32 {
7339        // SAFETY: plain scalar read through a live handle.
7340        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_lodCut(self.raw.as_ptr()) }
7341    }
7342
7343    pub fn set_lod_cut(&mut self, value: u32) {
7344        // SAFETY: plain scalar write through a live handle.
7345        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_lodCut(self.raw.as_ptr(), value) }
7346    }
7347
7348    /// Yaw variation type
7349    pub fn yaw_type(&self) -> u32 {
7350        // SAFETY: plain scalar read through a live handle.
7351        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_yawType(self.raw.as_ptr()) }
7352    }
7353
7354    pub fn set_yaw_type(&mut self, value: u32) {
7355        // SAFETY: plain scalar write through a live handle.
7356        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_yawType(self.raw.as_ptr(), value) }
7357    }
7358
7359    /// Yaw variation amplitude
7360    /// Borrows the field in place — no copy, no allocation.
7361    pub fn yaw_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
7362        // SAFETY: an interior pointer into `self`, valid for this
7363        // borrow and never freed by the `Ref`.
7364        unsafe {
7365            crate::support::Ref::new(AnimRefF32 {
7366                raw: core::ptr::NonNull::new_unchecked(
7367                    ffi::whiteout_m3_M3RibbonEmitter_get_yawAmplitude(self.raw.as_ptr()),
7368                ),
7369            })
7370        }
7371    }
7372
7373    pub fn yaw_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7374        // SAFETY: as above; `&mut self` guarantees exclusivity.
7375        unsafe {
7376            crate::support::RefMut::new(AnimRefF32 {
7377                raw: core::ptr::NonNull::new_unchecked(
7378                    ffi::whiteout_m3_M3RibbonEmitter_get_yawAmplitude(self.raw.as_ptr()),
7379                ),
7380            })
7381        }
7382    }
7383
7384    /// Yaw variation frequency
7385    /// Borrows the field in place — no copy, no allocation.
7386    pub fn yaw_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
7387        // SAFETY: an interior pointer into `self`, valid for this
7388        // borrow and never freed by the `Ref`.
7389        unsafe {
7390            crate::support::Ref::new(AnimRefF32 {
7391                raw: core::ptr::NonNull::new_unchecked(
7392                    ffi::whiteout_m3_M3RibbonEmitter_get_yawFrequency(self.raw.as_ptr()),
7393                ),
7394            })
7395        }
7396    }
7397
7398    pub fn yaw_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7399        // SAFETY: as above; `&mut self` guarantees exclusivity.
7400        unsafe {
7401            crate::support::RefMut::new(AnimRefF32 {
7402                raw: core::ptr::NonNull::new_unchecked(
7403                    ffi::whiteout_m3_M3RibbonEmitter_get_yawFrequency(self.raw.as_ptr()),
7404                ),
7405            })
7406        }
7407    }
7408
7409    /// Pitch variation type
7410    pub fn pitch_type(&self) -> u32 {
7411        // SAFETY: plain scalar read through a live handle.
7412        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_pitchType(self.raw.as_ptr()) }
7413    }
7414
7415    pub fn set_pitch_type(&mut self, value: u32) {
7416        // SAFETY: plain scalar write through a live handle.
7417        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_pitchType(self.raw.as_ptr(), value) }
7418    }
7419
7420    /// Pitch variation amplitude
7421    /// Borrows the field in place — no copy, no allocation.
7422    pub fn pitch_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
7423        // SAFETY: an interior pointer into `self`, valid for this
7424        // borrow and never freed by the `Ref`.
7425        unsafe {
7426            crate::support::Ref::new(AnimRefF32 {
7427                raw: core::ptr::NonNull::new_unchecked(
7428                    ffi::whiteout_m3_M3RibbonEmitter_get_pitchAmplitude(self.raw.as_ptr()),
7429                ),
7430            })
7431        }
7432    }
7433
7434    pub fn pitch_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7435        // SAFETY: as above; `&mut self` guarantees exclusivity.
7436        unsafe {
7437            crate::support::RefMut::new(AnimRefF32 {
7438                raw: core::ptr::NonNull::new_unchecked(
7439                    ffi::whiteout_m3_M3RibbonEmitter_get_pitchAmplitude(self.raw.as_ptr()),
7440                ),
7441            })
7442        }
7443    }
7444
7445    /// Pitch variation frequency
7446    /// Borrows the field in place — no copy, no allocation.
7447    pub fn pitch_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
7448        // SAFETY: an interior pointer into `self`, valid for this
7449        // borrow and never freed by the `Ref`.
7450        unsafe {
7451            crate::support::Ref::new(AnimRefF32 {
7452                raw: core::ptr::NonNull::new_unchecked(
7453                    ffi::whiteout_m3_M3RibbonEmitter_get_pitchFrequency(self.raw.as_ptr()),
7454                ),
7455            })
7456        }
7457    }
7458
7459    pub fn pitch_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7460        // SAFETY: as above; `&mut self` guarantees exclusivity.
7461        unsafe {
7462            crate::support::RefMut::new(AnimRefF32 {
7463                raw: core::ptr::NonNull::new_unchecked(
7464                    ffi::whiteout_m3_M3RibbonEmitter_get_pitchFrequency(self.raw.as_ptr()),
7465                ),
7466            })
7467        }
7468    }
7469
7470    /// Speed variation type
7471    pub fn speed_type(&self) -> u32 {
7472        // SAFETY: plain scalar read through a live handle.
7473        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_speedType(self.raw.as_ptr()) }
7474    }
7475
7476    pub fn set_speed_type(&mut self, value: u32) {
7477        // SAFETY: plain scalar write through a live handle.
7478        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_speedType(self.raw.as_ptr(), value) }
7479    }
7480
7481    /// Speed variation amplitude
7482    /// Borrows the field in place — no copy, no allocation.
7483    pub fn speed_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
7484        // SAFETY: an interior pointer into `self`, valid for this
7485        // borrow and never freed by the `Ref`.
7486        unsafe {
7487            crate::support::Ref::new(AnimRefF32 {
7488                raw: core::ptr::NonNull::new_unchecked(
7489                    ffi::whiteout_m3_M3RibbonEmitter_get_speedAmplitude(self.raw.as_ptr()),
7490                ),
7491            })
7492        }
7493    }
7494
7495    pub fn speed_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7496        // SAFETY: as above; `&mut self` guarantees exclusivity.
7497        unsafe {
7498            crate::support::RefMut::new(AnimRefF32 {
7499                raw: core::ptr::NonNull::new_unchecked(
7500                    ffi::whiteout_m3_M3RibbonEmitter_get_speedAmplitude(self.raw.as_ptr()),
7501                ),
7502            })
7503        }
7504    }
7505
7506    /// Speed variation frequency
7507    /// Borrows the field in place — no copy, no allocation.
7508    pub fn speed_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
7509        // SAFETY: an interior pointer into `self`, valid for this
7510        // borrow and never freed by the `Ref`.
7511        unsafe {
7512            crate::support::Ref::new(AnimRefF32 {
7513                raw: core::ptr::NonNull::new_unchecked(
7514                    ffi::whiteout_m3_M3RibbonEmitter_get_speedFrequency(self.raw.as_ptr()),
7515                ),
7516            })
7517        }
7518    }
7519
7520    pub fn speed_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7521        // SAFETY: as above; `&mut self` guarantees exclusivity.
7522        unsafe {
7523            crate::support::RefMut::new(AnimRefF32 {
7524                raw: core::ptr::NonNull::new_unchecked(
7525                    ffi::whiteout_m3_M3RibbonEmitter_get_speedFrequency(self.raw.as_ptr()),
7526                ),
7527            })
7528        }
7529    }
7530
7531    /// Size variation type
7532    pub fn size_type(&self) -> u32 {
7533        // SAFETY: plain scalar read through a live handle.
7534        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_sizeType(self.raw.as_ptr()) }
7535    }
7536
7537    pub fn set_size_type(&mut self, value: u32) {
7538        // SAFETY: plain scalar write through a live handle.
7539        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_sizeType(self.raw.as_ptr(), value) }
7540    }
7541
7542    /// Size variation amplitude
7543    /// Borrows the field in place — no copy, no allocation.
7544    pub fn size_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
7545        // SAFETY: an interior pointer into `self`, valid for this
7546        // borrow and never freed by the `Ref`.
7547        unsafe {
7548            crate::support::Ref::new(AnimRefF32 {
7549                raw: core::ptr::NonNull::new_unchecked(
7550                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeAmplitude(self.raw.as_ptr()),
7551                ),
7552            })
7553        }
7554    }
7555
7556    pub fn size_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7557        // SAFETY: as above; `&mut self` guarantees exclusivity.
7558        unsafe {
7559            crate::support::RefMut::new(AnimRefF32 {
7560                raw: core::ptr::NonNull::new_unchecked(
7561                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeAmplitude(self.raw.as_ptr()),
7562                ),
7563            })
7564        }
7565    }
7566
7567    /// Size variation frequency
7568    /// Borrows the field in place — no copy, no allocation.
7569    pub fn size_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
7570        // SAFETY: an interior pointer into `self`, valid for this
7571        // borrow and never freed by the `Ref`.
7572        unsafe {
7573            crate::support::Ref::new(AnimRefF32 {
7574                raw: core::ptr::NonNull::new_unchecked(
7575                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeFrequency(self.raw.as_ptr()),
7576                ),
7577            })
7578        }
7579    }
7580
7581    pub fn size_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7582        // SAFETY: as above; `&mut self` guarantees exclusivity.
7583        unsafe {
7584            crate::support::RefMut::new(AnimRefF32 {
7585                raw: core::ptr::NonNull::new_unchecked(
7586                    ffi::whiteout_m3_M3RibbonEmitter_get_sizeFrequency(self.raw.as_ptr()),
7587                ),
7588            })
7589        }
7590    }
7591
7592    /// Alpha variation type
7593    pub fn alpha_type(&self) -> u32 {
7594        // SAFETY: plain scalar read through a live handle.
7595        unsafe { ffi::whiteout_m3_M3RibbonEmitter_get_alphaType(self.raw.as_ptr()) }
7596    }
7597
7598    pub fn set_alpha_type(&mut self, value: u32) {
7599        // SAFETY: plain scalar write through a live handle.
7600        unsafe { ffi::whiteout_m3_M3RibbonEmitter_set_alphaType(self.raw.as_ptr(), value) }
7601    }
7602
7603    /// Alpha variation amplitude
7604    /// Borrows the field in place — no copy, no allocation.
7605    pub fn alpha_amplitude(&self) -> crate::support::Ref<'_, AnimRefF32> {
7606        // SAFETY: an interior pointer into `self`, valid for this
7607        // borrow and never freed by the `Ref`.
7608        unsafe {
7609            crate::support::Ref::new(AnimRefF32 {
7610                raw: core::ptr::NonNull::new_unchecked(
7611                    ffi::whiteout_m3_M3RibbonEmitter_get_alphaAmplitude(self.raw.as_ptr()),
7612                ),
7613            })
7614        }
7615    }
7616
7617    pub fn alpha_amplitude_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7618        // SAFETY: as above; `&mut self` guarantees exclusivity.
7619        unsafe {
7620            crate::support::RefMut::new(AnimRefF32 {
7621                raw: core::ptr::NonNull::new_unchecked(
7622                    ffi::whiteout_m3_M3RibbonEmitter_get_alphaAmplitude(self.raw.as_ptr()),
7623                ),
7624            })
7625        }
7626    }
7627
7628    /// Alpha variation frequency
7629    /// Borrows the field in place — no copy, no allocation.
7630    pub fn alpha_frequency(&self) -> crate::support::Ref<'_, AnimRefF32> {
7631        // SAFETY: an interior pointer into `self`, valid for this
7632        // borrow and never freed by the `Ref`.
7633        unsafe {
7634            crate::support::Ref::new(AnimRefF32 {
7635                raw: core::ptr::NonNull::new_unchecked(
7636                    ffi::whiteout_m3_M3RibbonEmitter_get_alphaFrequency(self.raw.as_ptr()),
7637                ),
7638            })
7639        }
7640    }
7641
7642    pub fn alpha_frequency_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7643        // SAFETY: as above; `&mut self` guarantees exclusivity.
7644        unsafe {
7645            crate::support::RefMut::new(AnimRefF32 {
7646                raw: core::ptr::NonNull::new_unchecked(
7647                    ffi::whiteout_m3_M3RibbonEmitter_get_alphaFrequency(self.raw.as_ptr()),
7648                ),
7649            })
7650        }
7651    }
7652
7653    /// Animated parent velocity influence
7654    /// Borrows the field in place — no copy, no allocation.
7655    pub fn particle_velocity(&self) -> crate::support::Ref<'_, AnimRefF32> {
7656        // SAFETY: an interior pointer into `self`, valid for this
7657        // borrow and never freed by the `Ref`.
7658        unsafe {
7659            crate::support::Ref::new(AnimRefF32 {
7660                raw: core::ptr::NonNull::new_unchecked(
7661                    ffi::whiteout_m3_M3RibbonEmitter_get_particleVelocity(self.raw.as_ptr()),
7662                ),
7663            })
7664        }
7665    }
7666
7667    pub fn particle_velocity_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7668        // SAFETY: as above; `&mut self` guarantees exclusivity.
7669        unsafe {
7670            crate::support::RefMut::new(AnimRefF32 {
7671                raw: core::ptr::NonNull::new_unchecked(
7672                    ffi::whiteout_m3_M3RibbonEmitter_get_particleVelocity(self.raw.as_ptr()),
7673                ),
7674            })
7675        }
7676    }
7677
7678    /// Animated overlay effect
7679    /// Borrows the field in place — no copy, no allocation.
7680    pub fn overlay(&self) -> crate::support::Ref<'_, AnimRefF32> {
7681        // SAFETY: an interior pointer into `self`, valid for this
7682        // borrow and never freed by the `Ref`.
7683        unsafe {
7684            crate::support::Ref::new(AnimRefF32 {
7685                raw: core::ptr::NonNull::new_unchecked(
7686                    ffi::whiteout_m3_M3RibbonEmitter_get_overlay(self.raw.as_ptr()),
7687                ),
7688            })
7689        }
7690    }
7691
7692    pub fn overlay_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7693        // SAFETY: as above; `&mut self` guarantees exclusivity.
7694        unsafe {
7695            crate::support::RefMut::new(AnimRefF32 {
7696                raw: core::ptr::NonNull::new_unchecked(
7697                    ffi::whiteout_m3_M3RibbonEmitter_get_overlay(self.raw.as_ptr()),
7698                ),
7699            })
7700        }
7701    }
7702}
7703
7704impl Default for RibbonEmitter {
7705    fn default() -> Self {
7706        Self::new()
7707    }
7708}
7709
7710/// PROJ — Projector / decal (v0–v5, 388 bytes)
7711///
7712/// Projects a material onto scene geometry with animated offset, orientation, field of view, aspect ratio, clipping planes, alpha lifecycle, and attenuation distance.
7713pub struct Projector {
7714    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Projector>,
7715}
7716
7717impl Drop for Projector {
7718    fn drop(&mut self) {
7719        // SAFETY: `raw` came from a native constructor and Drop runs once.
7720        unsafe { ffi::whiteout_m3_M3Projector_delete(self.raw.as_ptr()) }
7721    }
7722}
7723
7724impl Projector {
7725    /// # Safety
7726    /// `raw` must be a live handle this value takes ownership of.
7727    #[allow(dead_code)] // used by whichever methods return this type
7728    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Projector) -> Option<Self> {
7729        core::ptr::NonNull::new(raw).map(|raw| Projector { raw })
7730    }
7731}
7732
7733// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7734// is deliberately NOT implemented — the C++ types make no documented
7735// guarantee about concurrent use, and claiming one we haven't verified
7736// would be unsound. See `@bind thread_safe` in the plan.
7737unsafe impl Send for Projector {}
7738
7739impl core::fmt::Debug for Projector {
7740    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7741        f.debug_struct("Projector").finish_non_exhaustive()
7742    }
7743}
7744
7745impl Projector {
7746    /// # Panics
7747    /// Panics if the native allocation fails.
7748    pub fn new() -> Self {
7749        // SAFETY: the native constructor returns a live handle; a null here
7750        // means the library is unusable.
7751        unsafe {
7752            let raw = ffi::whiteout_m3_M3Projector_new();
7753            Self::from_raw(raw).expect("native Projector allocation failed")
7754        }
7755    }
7756
7757    /// Projection type (ortho/perspective)
7758    pub fn projection_type(&self) -> ProjectionType {
7759        // SAFETY: scalar read; the discriminant is validated below.
7760        unsafe { ffi::whiteout_m3_M3Projector_get_projectionType(self.raw.as_ptr()) }
7761            .try_into()
7762            .expect("unknown enum discriminant from the native library")
7763    }
7764
7765    pub fn set_projection_type(&mut self, value: ProjectionType) {
7766        // SAFETY: scalar write through a live handle.
7767        unsafe { ffi::whiteout_m3_M3Projector_set_projectionType(self.raw.as_ptr(), value as i32) }
7768    }
7769
7770    /// Index into BONE array
7771    pub fn bone(&self) -> u32 {
7772        // SAFETY: plain scalar read through a live handle.
7773        unsafe { ffi::whiteout_m3_M3Projector_get_bone(self.raw.as_ptr()) }
7774    }
7775
7776    pub fn set_bone(&mut self, value: u32) {
7777        // SAFETY: plain scalar write through a live handle.
7778        unsafe { ffi::whiteout_m3_M3Projector_set_bone(self.raw.as_ptr(), value) }
7779    }
7780
7781    /// Index into MATM material map
7782    pub fn material_reference_index(&self) -> u32 {
7783        // SAFETY: plain scalar read through a live handle.
7784        unsafe { ffi::whiteout_m3_M3Projector_get_materialReferenceIndex(self.raw.as_ptr()) }
7785    }
7786
7787    pub fn set_material_reference_index(&mut self, value: u32) {
7788        // SAFETY: plain scalar write through a live handle.
7789        unsafe { ffi::whiteout_m3_M3Projector_set_materialReferenceIndex(self.raw.as_ptr(), value) }
7790    }
7791
7792    /// Animated position offset
7793    /// Borrows the field in place — no copy, no allocation.
7794    pub fn offset(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
7795        // SAFETY: an interior pointer into `self`, valid for this
7796        // borrow and never freed by the `Ref`.
7797        unsafe {
7798            crate::support::Ref::new(AnimRefVector3f {
7799                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_offset(
7800                    self.raw.as_ptr(),
7801                )),
7802            })
7803        }
7804    }
7805
7806    pub fn offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
7807        // SAFETY: as above; `&mut self` guarantees exclusivity.
7808        unsafe {
7809            crate::support::RefMut::new(AnimRefVector3f {
7810                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_offset(
7811                    self.raw.as_ptr(),
7812                )),
7813            })
7814        }
7815    }
7816
7817    /// Animated pitch angle
7818    /// Borrows the field in place — no copy, no allocation.
7819    pub fn pitch(&self) -> crate::support::Ref<'_, AnimRefF32> {
7820        // SAFETY: an interior pointer into `self`, valid for this
7821        // borrow and never freed by the `Ref`.
7822        unsafe {
7823            crate::support::Ref::new(AnimRefF32 {
7824                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_pitch(
7825                    self.raw.as_ptr(),
7826                )),
7827            })
7828        }
7829    }
7830
7831    pub fn pitch_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7832        // SAFETY: as above; `&mut self` guarantees exclusivity.
7833        unsafe {
7834            crate::support::RefMut::new(AnimRefF32 {
7835                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_pitch(
7836                    self.raw.as_ptr(),
7837                )),
7838            })
7839        }
7840    }
7841
7842    /// Animated yaw angle
7843    /// Borrows the field in place — no copy, no allocation.
7844    pub fn yaw(&self) -> crate::support::Ref<'_, AnimRefF32> {
7845        // SAFETY: an interior pointer into `self`, valid for this
7846        // borrow and never freed by the `Ref`.
7847        unsafe {
7848            crate::support::Ref::new(AnimRefF32 {
7849                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_yaw(
7850                    self.raw.as_ptr(),
7851                )),
7852            })
7853        }
7854    }
7855
7856    pub fn yaw_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7857        // SAFETY: as above; `&mut self` guarantees exclusivity.
7858        unsafe {
7859            crate::support::RefMut::new(AnimRefF32 {
7860                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_yaw(
7861                    self.raw.as_ptr(),
7862                )),
7863            })
7864        }
7865    }
7866
7867    /// Animated roll angle
7868    /// Borrows the field in place — no copy, no allocation.
7869    pub fn roll(&self) -> crate::support::Ref<'_, AnimRefF32> {
7870        // SAFETY: an interior pointer into `self`, valid for this
7871        // borrow and never freed by the `Ref`.
7872        unsafe {
7873            crate::support::Ref::new(AnimRefF32 {
7874                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_roll(
7875                    self.raw.as_ptr(),
7876                )),
7877            })
7878        }
7879    }
7880
7881    pub fn roll_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7882        // SAFETY: as above; `&mut self` guarantees exclusivity.
7883        unsafe {
7884            crate::support::RefMut::new(AnimRefF32 {
7885                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_roll(
7886                    self.raw.as_ptr(),
7887                )),
7888            })
7889        }
7890    }
7891
7892    /// Animated field of view
7893    /// Borrows the field in place — no copy, no allocation.
7894    pub fn field_of_view(&self) -> crate::support::Ref<'_, AnimRefF32> {
7895        // SAFETY: an interior pointer into `self`, valid for this
7896        // borrow and never freed by the `Ref`.
7897        unsafe {
7898            crate::support::Ref::new(AnimRefF32 {
7899                raw: core::ptr::NonNull::new_unchecked(
7900                    ffi::whiteout_m3_M3Projector_get_fieldOfView(self.raw.as_ptr()),
7901                ),
7902            })
7903        }
7904    }
7905
7906    pub fn field_of_view_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7907        // SAFETY: as above; `&mut self` guarantees exclusivity.
7908        unsafe {
7909            crate::support::RefMut::new(AnimRefF32 {
7910                raw: core::ptr::NonNull::new_unchecked(
7911                    ffi::whiteout_m3_M3Projector_get_fieldOfView(self.raw.as_ptr()),
7912                ),
7913            })
7914        }
7915    }
7916
7917    /// Animated aspect ratio
7918    /// Borrows the field in place — no copy, no allocation.
7919    pub fn aspect_ratio(&self) -> crate::support::Ref<'_, AnimRefF32> {
7920        // SAFETY: an interior pointer into `self`, valid for this
7921        // borrow and never freed by the `Ref`.
7922        unsafe {
7923            crate::support::Ref::new(AnimRefF32 {
7924                raw: core::ptr::NonNull::new_unchecked(
7925                    ffi::whiteout_m3_M3Projector_get_aspectRatio(self.raw.as_ptr()),
7926                ),
7927            })
7928        }
7929    }
7930
7931    pub fn aspect_ratio_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7932        // SAFETY: as above; `&mut self` guarantees exclusivity.
7933        unsafe {
7934            crate::support::RefMut::new(AnimRefF32 {
7935                raw: core::ptr::NonNull::new_unchecked(
7936                    ffi::whiteout_m3_M3Projector_get_aspectRatio(self.raw.as_ptr()),
7937                ),
7938            })
7939        }
7940    }
7941
7942    /// Animated near clip plane
7943    /// Borrows the field in place — no copy, no allocation.
7944    pub fn near(&self) -> crate::support::Ref<'_, AnimRefF32> {
7945        // SAFETY: an interior pointer into `self`, valid for this
7946        // borrow and never freed by the `Ref`.
7947        unsafe {
7948            crate::support::Ref::new(AnimRefF32 {
7949                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_near(
7950                    self.raw.as_ptr(),
7951                )),
7952            })
7953        }
7954    }
7955
7956    pub fn near_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7957        // SAFETY: as above; `&mut self` guarantees exclusivity.
7958        unsafe {
7959            crate::support::RefMut::new(AnimRefF32 {
7960                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_near(
7961                    self.raw.as_ptr(),
7962                )),
7963            })
7964        }
7965    }
7966
7967    /// Animated far clip plane
7968    /// Borrows the field in place — no copy, no allocation.
7969    pub fn far(&self) -> crate::support::Ref<'_, AnimRefF32> {
7970        // SAFETY: an interior pointer into `self`, valid for this
7971        // borrow and never freed by the `Ref`.
7972        unsafe {
7973            crate::support::Ref::new(AnimRefF32 {
7974                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_far(
7975                    self.raw.as_ptr(),
7976                )),
7977            })
7978        }
7979    }
7980
7981    pub fn far_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
7982        // SAFETY: as above; `&mut self` guarantees exclusivity.
7983        unsafe {
7984            crate::support::RefMut::new(AnimRefF32 {
7985                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_far(
7986                    self.raw.as_ptr(),
7987                )),
7988            })
7989        }
7990    }
7991
7992    /// Animated box Z bottom offset
7993    /// Borrows the field in place — no copy, no allocation.
7994    pub fn box_offset_z_bottom(&self) -> crate::support::Ref<'_, AnimRefF32> {
7995        // SAFETY: an interior pointer into `self`, valid for this
7996        // borrow and never freed by the `Ref`.
7997        unsafe {
7998            crate::support::Ref::new(AnimRefF32 {
7999                raw: core::ptr::NonNull::new_unchecked(
8000                    ffi::whiteout_m3_M3Projector_get_boxOffsetZBottom(self.raw.as_ptr()),
8001                ),
8002            })
8003        }
8004    }
8005
8006    pub fn box_offset_z_bottom_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8007        // SAFETY: as above; `&mut self` guarantees exclusivity.
8008        unsafe {
8009            crate::support::RefMut::new(AnimRefF32 {
8010                raw: core::ptr::NonNull::new_unchecked(
8011                    ffi::whiteout_m3_M3Projector_get_boxOffsetZBottom(self.raw.as_ptr()),
8012                ),
8013            })
8014        }
8015    }
8016
8017    /// Animated box Z top offset
8018    /// Borrows the field in place — no copy, no allocation.
8019    pub fn box_offset_z_top(&self) -> crate::support::Ref<'_, AnimRefF32> {
8020        // SAFETY: an interior pointer into `self`, valid for this
8021        // borrow and never freed by the `Ref`.
8022        unsafe {
8023            crate::support::Ref::new(AnimRefF32 {
8024                raw: core::ptr::NonNull::new_unchecked(
8025                    ffi::whiteout_m3_M3Projector_get_boxOffsetZTop(self.raw.as_ptr()),
8026                ),
8027            })
8028        }
8029    }
8030
8031    pub fn box_offset_z_top_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8032        // SAFETY: as above; `&mut self` guarantees exclusivity.
8033        unsafe {
8034            crate::support::RefMut::new(AnimRefF32 {
8035                raw: core::ptr::NonNull::new_unchecked(
8036                    ffi::whiteout_m3_M3Projector_get_boxOffsetZTop(self.raw.as_ptr()),
8037                ),
8038            })
8039        }
8040    }
8041
8042    /// Animated box X left offset
8043    /// Borrows the field in place — no copy, no allocation.
8044    pub fn box_offset_x_left(&self) -> crate::support::Ref<'_, AnimRefF32> {
8045        // SAFETY: an interior pointer into `self`, valid for this
8046        // borrow and never freed by the `Ref`.
8047        unsafe {
8048            crate::support::Ref::new(AnimRefF32 {
8049                raw: core::ptr::NonNull::new_unchecked(
8050                    ffi::whiteout_m3_M3Projector_get_boxOffsetXLeft(self.raw.as_ptr()),
8051                ),
8052            })
8053        }
8054    }
8055
8056    pub fn box_offset_x_left_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8057        // SAFETY: as above; `&mut self` guarantees exclusivity.
8058        unsafe {
8059            crate::support::RefMut::new(AnimRefF32 {
8060                raw: core::ptr::NonNull::new_unchecked(
8061                    ffi::whiteout_m3_M3Projector_get_boxOffsetXLeft(self.raw.as_ptr()),
8062                ),
8063            })
8064        }
8065    }
8066
8067    /// Animated box X right offset
8068    /// Borrows the field in place — no copy, no allocation.
8069    pub fn box_offset_x_right(&self) -> crate::support::Ref<'_, AnimRefF32> {
8070        // SAFETY: an interior pointer into `self`, valid for this
8071        // borrow and never freed by the `Ref`.
8072        unsafe {
8073            crate::support::Ref::new(AnimRefF32 {
8074                raw: core::ptr::NonNull::new_unchecked(
8075                    ffi::whiteout_m3_M3Projector_get_boxOffsetXRight(self.raw.as_ptr()),
8076                ),
8077            })
8078        }
8079    }
8080
8081    pub fn box_offset_x_right_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8082        // SAFETY: as above; `&mut self` guarantees exclusivity.
8083        unsafe {
8084            crate::support::RefMut::new(AnimRefF32 {
8085                raw: core::ptr::NonNull::new_unchecked(
8086                    ffi::whiteout_m3_M3Projector_get_boxOffsetXRight(self.raw.as_ptr()),
8087                ),
8088            })
8089        }
8090    }
8091
8092    /// Animated box Y front offset
8093    /// Borrows the field in place — no copy, no allocation.
8094    pub fn box_offset_y_front(&self) -> crate::support::Ref<'_, AnimRefF32> {
8095        // SAFETY: an interior pointer into `self`, valid for this
8096        // borrow and never freed by the `Ref`.
8097        unsafe {
8098            crate::support::Ref::new(AnimRefF32 {
8099                raw: core::ptr::NonNull::new_unchecked(
8100                    ffi::whiteout_m3_M3Projector_get_boxOffsetYFront(self.raw.as_ptr()),
8101                ),
8102            })
8103        }
8104    }
8105
8106    pub fn box_offset_y_front_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8107        // SAFETY: as above; `&mut self` guarantees exclusivity.
8108        unsafe {
8109            crate::support::RefMut::new(AnimRefF32 {
8110                raw: core::ptr::NonNull::new_unchecked(
8111                    ffi::whiteout_m3_M3Projector_get_boxOffsetYFront(self.raw.as_ptr()),
8112                ),
8113            })
8114        }
8115    }
8116
8117    /// Animated box Y back offset
8118    /// Borrows the field in place — no copy, no allocation.
8119    pub fn box_offset_y_back(&self) -> crate::support::Ref<'_, AnimRefF32> {
8120        // SAFETY: an interior pointer into `self`, valid for this
8121        // borrow and never freed by the `Ref`.
8122        unsafe {
8123            crate::support::Ref::new(AnimRefF32 {
8124                raw: core::ptr::NonNull::new_unchecked(
8125                    ffi::whiteout_m3_M3Projector_get_boxOffsetYBack(self.raw.as_ptr()),
8126                ),
8127            })
8128        }
8129    }
8130
8131    pub fn box_offset_y_back_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8132        // SAFETY: as above; `&mut self` guarantees exclusivity.
8133        unsafe {
8134            crate::support::RefMut::new(AnimRefF32 {
8135                raw: core::ptr::NonNull::new_unchecked(
8136                    ffi::whiteout_m3_M3Projector_get_boxOffsetYBack(self.raw.as_ptr()),
8137                ),
8138            })
8139        }
8140    }
8141
8142    /// Projection falloff distance
8143    pub fn falloff(&self) -> f32 {
8144        // SAFETY: plain scalar read through a live handle.
8145        unsafe { ffi::whiteout_m3_M3Projector_get_falloff(self.raw.as_ptr()) }
8146    }
8147
8148    pub fn set_falloff(&mut self, value: f32) {
8149        // SAFETY: plain scalar write through a live handle.
8150        unsafe { ffi::whiteout_m3_M3Projector_set_falloff(self.raw.as_ptr(), value) }
8151    }
8152
8153    /// Alpha at creation
8154    pub fn alpha_init(&self) -> f32 {
8155        // SAFETY: plain scalar read through a live handle.
8156        unsafe { ffi::whiteout_m3_M3Projector_get_alphaInit(self.raw.as_ptr()) }
8157    }
8158
8159    pub fn set_alpha_init(&mut self, value: f32) {
8160        // SAFETY: plain scalar write through a live handle.
8161        unsafe { ffi::whiteout_m3_M3Projector_set_alphaInit(self.raw.as_ptr(), value) }
8162    }
8163
8164    /// Alpha at midpoint
8165    pub fn alpha_mid(&self) -> f32 {
8166        // SAFETY: plain scalar read through a live handle.
8167        unsafe { ffi::whiteout_m3_M3Projector_get_alphaMid(self.raw.as_ptr()) }
8168    }
8169
8170    pub fn set_alpha_mid(&mut self, value: f32) {
8171        // SAFETY: plain scalar write through a live handle.
8172        unsafe { ffi::whiteout_m3_M3Projector_set_alphaMid(self.raw.as_ptr(), value) }
8173    }
8174
8175    /// Alpha at end
8176    pub fn alpha_end(&self) -> f32 {
8177        // SAFETY: plain scalar read through a live handle.
8178        unsafe { ffi::whiteout_m3_M3Projector_get_alphaEnd(self.raw.as_ptr()) }
8179    }
8180
8181    pub fn set_alpha_end(&mut self, value: f32) {
8182        // SAFETY: plain scalar write through a live handle.
8183        unsafe { ffi::whiteout_m3_M3Projector_set_alphaEnd(self.raw.as_ptr(), value) }
8184    }
8185
8186    /// Attack phase duration
8187    pub fn lifetime_attack(&self) -> f32 {
8188        // SAFETY: plain scalar read through a live handle.
8189        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeAttack(self.raw.as_ptr()) }
8190    }
8191
8192    pub fn set_lifetime_attack(&mut self, value: f32) {
8193        // SAFETY: plain scalar write through a live handle.
8194        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeAttack(self.raw.as_ptr(), value) }
8195    }
8196
8197    /// Attack target time
8198    pub fn lifetime_attack_to(&self) -> f32 {
8199        // SAFETY: plain scalar read through a live handle.
8200        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeAttackTo(self.raw.as_ptr()) }
8201    }
8202
8203    pub fn set_lifetime_attack_to(&mut self, value: f32) {
8204        // SAFETY: plain scalar write through a live handle.
8205        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeAttackTo(self.raw.as_ptr(), value) }
8206    }
8207
8208    /// Hold phase duration
8209    pub fn lifetime_hold(&self) -> f32 {
8210        // SAFETY: plain scalar read through a live handle.
8211        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeHold(self.raw.as_ptr()) }
8212    }
8213
8214    pub fn set_lifetime_hold(&mut self, value: f32) {
8215        // SAFETY: plain scalar write through a live handle.
8216        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeHold(self.raw.as_ptr(), value) }
8217    }
8218
8219    /// Hold target time
8220    pub fn lifetime_hold_to(&self) -> f32 {
8221        // SAFETY: plain scalar read through a live handle.
8222        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeHoldTo(self.raw.as_ptr()) }
8223    }
8224
8225    pub fn set_lifetime_hold_to(&mut self, value: f32) {
8226        // SAFETY: plain scalar write through a live handle.
8227        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeHoldTo(self.raw.as_ptr(), value) }
8228    }
8229
8230    /// Decay phase duration
8231    pub fn lifetime_decay(&self) -> f32 {
8232        // SAFETY: plain scalar read through a live handle.
8233        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeDecay(self.raw.as_ptr()) }
8234    }
8235
8236    pub fn set_lifetime_decay(&mut self, value: f32) {
8237        // SAFETY: plain scalar write through a live handle.
8238        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeDecay(self.raw.as_ptr(), value) }
8239    }
8240
8241    /// Decay target time
8242    pub fn lifetime_decay_to(&self) -> f32 {
8243        // SAFETY: plain scalar read through a live handle.
8244        unsafe { ffi::whiteout_m3_M3Projector_get_lifetimeDecayTo(self.raw.as_ptr()) }
8245    }
8246
8247    pub fn set_lifetime_decay_to(&mut self, value: f32) {
8248        // SAFETY: plain scalar write through a live handle.
8249        unsafe { ffi::whiteout_m3_M3Projector_set_lifetimeDecayTo(self.raw.as_ptr(), value) }
8250    }
8251
8252    /// Distance-based attenuation
8253    pub fn attenuation_distance(&self) -> f32 {
8254        // SAFETY: plain scalar read through a live handle.
8255        unsafe { ffi::whiteout_m3_M3Projector_get_attenuationDistance(self.raw.as_ptr()) }
8256    }
8257
8258    pub fn set_attenuation_distance(&mut self, value: f32) {
8259        // SAFETY: plain scalar write through a live handle.
8260        unsafe { ffi::whiteout_m3_M3Projector_set_attenuationDistance(self.raw.as_ptr(), value) }
8261    }
8262
8263    /// Animated active state
8264    /// Borrows the field in place — no copy, no allocation.
8265    pub fn active(&self) -> crate::support::Ref<'_, AnimRefU32> {
8266        // SAFETY: an interior pointer into `self`, valid for this
8267        // borrow and never freed by the `Ref`.
8268        unsafe {
8269            crate::support::Ref::new(AnimRefU32 {
8270                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_active(
8271                    self.raw.as_ptr(),
8272                )),
8273            })
8274        }
8275    }
8276
8277    pub fn active_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
8278        // SAFETY: as above; `&mut self` guarantees exclusivity.
8279        unsafe {
8280            crate::support::RefMut::new(AnimRefU32 {
8281                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Projector_get_active(
8282                    self.raw.as_ptr(),
8283                )),
8284            })
8285        }
8286    }
8287
8288    /// Render layer
8289    pub fn layer(&self) -> u32 {
8290        // SAFETY: plain scalar read through a live handle.
8291        unsafe { ffi::whiteout_m3_M3Projector_get_layer(self.raw.as_ptr()) }
8292    }
8293
8294    pub fn set_layer(&mut self, value: u32) {
8295        // SAFETY: plain scalar write through a live handle.
8296        unsafe { ffi::whiteout_m3_M3Projector_set_layer(self.raw.as_ptr(), value) }
8297    }
8298
8299    /// LOD reduction level
8300    pub fn lod_reduce(&self) -> u32 {
8301        // SAFETY: plain scalar read through a live handle.
8302        unsafe { ffi::whiteout_m3_M3Projector_get_lodReduce(self.raw.as_ptr()) }
8303    }
8304
8305    pub fn set_lod_reduce(&mut self, value: u32) {
8306        // SAFETY: plain scalar write through a live handle.
8307        unsafe { ffi::whiteout_m3_M3Projector_set_lodReduce(self.raw.as_ptr(), value) }
8308    }
8309
8310    /// LOD cut-off level
8311    pub fn lod_cut(&self) -> u32 {
8312        // SAFETY: plain scalar read through a live handle.
8313        unsafe { ffi::whiteout_m3_M3Projector_get_lodCut(self.raw.as_ptr()) }
8314    }
8315
8316    pub fn set_lod_cut(&mut self, value: u32) {
8317        // SAFETY: plain scalar write through a live handle.
8318        unsafe { ffi::whiteout_m3_M3Projector_set_lodCut(self.raw.as_ptr(), value) }
8319    }
8320
8321    /// Projector flags
8322    pub fn flags(&self) -> ProjectorFlag {
8323        // SAFETY: scalar read; a flag set accepts any bits.
8324        ProjectorFlag(unsafe { ffi::whiteout_m3_M3Projector_get_flags(self.raw.as_ptr()) })
8325    }
8326
8327    pub fn set_flags(&mut self, value: ProjectorFlag) {
8328        // SAFETY: scalar write through a live handle.
8329        unsafe { ffi::whiteout_m3_M3Projector_set_flags(self.raw.as_ptr(), value.0) }
8330    }
8331}
8332
8333impl Default for Projector {
8334    fn default() -> Self {
8335        Self::new()
8336    }
8337}
8338
8339/// MATM — Material map entry (v0, 8 bytes)
8340///
8341/// Maps a material type enum to an index into the corresponding material array. The MODL root references an array of these; the renderer uses materialType to dispatch to the correct material vector.
8342pub struct MaterialMap {
8343    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3MaterialMap>,
8344}
8345
8346impl Drop for MaterialMap {
8347    fn drop(&mut self) {
8348        // SAFETY: `raw` came from a native constructor and Drop runs once.
8349        unsafe { ffi::whiteout_m3_M3MaterialMap_delete(self.raw.as_ptr()) }
8350    }
8351}
8352
8353impl MaterialMap {
8354    /// # Safety
8355    /// `raw` must be a live handle this value takes ownership of.
8356    #[allow(dead_code)] // used by whichever methods return this type
8357    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3MaterialMap) -> Option<Self> {
8358        core::ptr::NonNull::new(raw).map(|raw| MaterialMap { raw })
8359    }
8360}
8361
8362// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8363// is deliberately NOT implemented — the C++ types make no documented
8364// guarantee about concurrent use, and claiming one we haven't verified
8365// would be unsound. See `@bind thread_safe` in the plan.
8366unsafe impl Send for MaterialMap {}
8367
8368impl core::fmt::Debug for MaterialMap {
8369    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8370        f.debug_struct("MaterialMap").finish_non_exhaustive()
8371    }
8372}
8373
8374impl MaterialMap {
8375    /// # Panics
8376    /// Panics if the native allocation fails.
8377    pub fn new() -> Self {
8378        // SAFETY: the native constructor returns a live handle; a null here
8379        // means the library is unusable.
8380        unsafe {
8381            let raw = ffi::whiteout_m3_M3MaterialMap_new();
8382            Self::from_raw(raw).expect("native MaterialMap allocation failed")
8383        }
8384    }
8385
8386    /// Material type (1=standard, 2=displacement, etc.)
8387    pub fn material_type(&self) -> MaterialType {
8388        // SAFETY: scalar read; the discriminant is validated below.
8389        unsafe { ffi::whiteout_m3_M3MaterialMap_get_materialType(self.raw.as_ptr()) }
8390            .try_into()
8391            .expect("unknown enum discriminant from the native library")
8392    }
8393
8394    pub fn set_material_type(&mut self, value: MaterialType) {
8395        // SAFETY: scalar write through a live handle.
8396        unsafe { ffi::whiteout_m3_M3MaterialMap_set_materialType(self.raw.as_ptr(), value as i32) }
8397    }
8398
8399    /// Index into the typed material array
8400    pub fn material_index(&self) -> u32 {
8401        // SAFETY: plain scalar read through a live handle.
8402        unsafe { ffi::whiteout_m3_M3MaterialMap_get_materialIndex(self.raw.as_ptr()) }
8403    }
8404
8405    pub fn set_material_index(&mut self, value: u32) {
8406        // SAFETY: plain scalar write through a live handle.
8407        unsafe { ffi::whiteout_m3_M3MaterialMap_set_materialIndex(self.raw.as_ptr(), value) }
8408    }
8409}
8410
8411impl Default for MaterialMap {
8412    fn default() -> Self {
8413        Self::new()
8414    }
8415}
8416
8417/// LAYR — Texture layer (v0–v26, 352–464 bytes)
8418///
8419/// A single texture binding with animated color tint, UV transforms, flipbook parameters, fresnel settings, and AVI video playback controls. Materials embed multiple optional TextureLayer instances for diffuse, specular, emissive, normal, and other texture slots.
8420///
8421/// Every field is initialised for the same reason `StandardMaterial`'s are: the parser fills all of them, but a conversion builds a layer from scratch (`layerFrom`) and a default-initialised one handed to the writer carries stack junk into the file. It did -- the halves of live heap pointers landed in `flipbookColumns`, `textureSource` and the fresnel fields of every exported layer, and the Galaxy editor crashed on the ones whose low byte came out zero (`reference_m3_layer_stack_junk`).
8422pub struct TextureLayer {
8423    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3TextureLayer>,
8424}
8425
8426impl Drop for TextureLayer {
8427    fn drop(&mut self) {
8428        // SAFETY: `raw` came from a native constructor and Drop runs once.
8429        unsafe { ffi::whiteout_m3_M3TextureLayer_delete(self.raw.as_ptr()) }
8430    }
8431}
8432
8433impl TextureLayer {
8434    /// # Safety
8435    /// `raw` must be a live handle this value takes ownership of.
8436    #[allow(dead_code)] // used by whichever methods return this type
8437    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3TextureLayer) -> Option<Self> {
8438        core::ptr::NonNull::new(raw).map(|raw| TextureLayer { raw })
8439    }
8440}
8441
8442// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8443// is deliberately NOT implemented — the C++ types make no documented
8444// guarantee about concurrent use, and claiming one we haven't verified
8445// would be unsound. See `@bind thread_safe` in the plan.
8446unsafe impl Send for TextureLayer {}
8447
8448impl core::fmt::Debug for TextureLayer {
8449    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8450        f.debug_struct("TextureLayer").finish_non_exhaustive()
8451    }
8452}
8453
8454impl TextureLayer {
8455    /// # Panics
8456    /// Panics if the native allocation fails.
8457    pub fn new() -> Self {
8458        // SAFETY: the native constructor returns a live handle; a null here
8459        // means the library is unusable.
8460        unsafe {
8461            let raw = ffi::whiteout_m3_M3TextureLayer_new();
8462            Self::from_raw(raw).expect("native TextureLayer allocation failed")
8463        }
8464    }
8465
8466    /// Layer identifier
8467    pub fn id(&self) -> u32 {
8468        // SAFETY: plain scalar read through a live handle.
8469        unsafe { ffi::whiteout_m3_M3TextureLayer_get_id(self.raw.as_ptr()) }
8470    }
8471
8472    pub fn set_id(&mut self, value: u32) {
8473        // SAFETY: plain scalar write through a live handle.
8474        unsafe { ffi::whiteout_m3_M3TextureLayer_set_id(self.raw.as_ptr(), value) }
8475    }
8476
8477    /// Texture file path (`Ref<CHAR>`)
8478    pub fn texture_path(&self) -> String {
8479        // SAFETY: the native side hands over an owned CString.
8480        unsafe {
8481            crate::support::take_string(ffi::whiteout_m3_M3TextureLayer_get_texturePath(
8482                self.raw.as_ptr(),
8483            ))
8484        }
8485    }
8486
8487    pub fn set_texture_path(&mut self, value: &str) {
8488        let value = std::ffi::CString::new(value).unwrap_or_default();
8489        // SAFETY: the pointer outlives the call.
8490        unsafe {
8491            ffi::whiteout_m3_M3TextureLayer_set_texturePath(self.raw.as_ptr(), value.as_ptr())
8492        }
8493    }
8494
8495    /// Animated color tint
8496    /// Borrows the field in place — no copy, no allocation.
8497    pub fn color(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
8498        // SAFETY: an interior pointer into `self`, valid for this
8499        // borrow and never freed by the `Ref`.
8500        unsafe {
8501            crate::support::Ref::new(AnimRefM3ColorBGRA {
8502                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3TextureLayer_get_color(
8503                    self.raw.as_ptr(),
8504                )),
8505            })
8506        }
8507    }
8508
8509    pub fn color_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
8510        // SAFETY: as above; `&mut self` guarantees exclusivity.
8511        unsafe {
8512            crate::support::RefMut::new(AnimRefM3ColorBGRA {
8513                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3TextureLayer_get_color(
8514                    self.raw.as_ptr(),
8515                )),
8516            })
8517        }
8518    }
8519
8520    /// Layer flags (wrap, flipbook, video, etc.)
8521    pub fn flags(&self) -> TextureLayerFlag {
8522        // SAFETY: scalar read; a flag set accepts any bits.
8523        TextureLayerFlag(unsafe { ffi::whiteout_m3_M3TextureLayer_get_flags(self.raw.as_ptr()) })
8524    }
8525
8526    pub fn set_flags(&mut self, value: TextureLayerFlag) {
8527        // SAFETY: scalar write through a live handle.
8528        unsafe { ffi::whiteout_m3_M3TextureLayer_set_flags(self.raw.as_ptr(), value.0) }
8529    }
8530
8531    /// UV mapping source
8532    pub fn uv_mapping(&self) -> UVMappingMode {
8533        // SAFETY: scalar read; the discriminant is validated below.
8534        unsafe { ffi::whiteout_m3_M3TextureLayer_get_uvMapping(self.raw.as_ptr()) }
8535            .try_into()
8536            .expect("unknown enum discriminant from the native library")
8537    }
8538
8539    pub fn set_uv_mapping(&mut self, value: UVMappingMode) {
8540        // SAFETY: scalar write through a live handle.
8541        unsafe { ffi::whiteout_m3_M3TextureLayer_set_uvMapping(self.raw.as_ptr(), value as i32) }
8542    }
8543
8544    /// Channel selection
8545    pub fn color_type(&self) -> ColorChannelSelect {
8546        // SAFETY: scalar read; the discriminant is validated below.
8547        unsafe { ffi::whiteout_m3_M3TextureLayer_get_colorType(self.raw.as_ptr()) }
8548            .try_into()
8549            .expect("unknown enum discriminant from the native library")
8550    }
8551
8552    pub fn set_color_type(&mut self, value: ColorChannelSelect) {
8553        // SAFETY: scalar write through a live handle.
8554        unsafe { ffi::whiteout_m3_M3TextureLayer_set_colorType(self.raw.as_ptr(), value as i32) }
8555    }
8556
8557    /// RGB multiply factor
8558    /// Borrows the field in place — no copy, no allocation.
8559    pub fn rgb_multiply(&self) -> crate::support::Ref<'_, AnimRefF32> {
8560        // SAFETY: an interior pointer into `self`, valid for this
8561        // borrow and never freed by the `Ref`.
8562        unsafe {
8563            crate::support::Ref::new(AnimRefF32 {
8564                raw: core::ptr::NonNull::new_unchecked(
8565                    ffi::whiteout_m3_M3TextureLayer_get_rgbMultiply(self.raw.as_ptr()),
8566                ),
8567            })
8568        }
8569    }
8570
8571    pub fn rgb_multiply_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8572        // SAFETY: as above; `&mut self` guarantees exclusivity.
8573        unsafe {
8574            crate::support::RefMut::new(AnimRefF32 {
8575                raw: core::ptr::NonNull::new_unchecked(
8576                    ffi::whiteout_m3_M3TextureLayer_get_rgbMultiply(self.raw.as_ptr()),
8577                ),
8578            })
8579        }
8580    }
8581
8582    /// RGB additive factor
8583    /// Borrows the field in place — no copy, no allocation.
8584    pub fn rgb_add(&self) -> crate::support::Ref<'_, AnimRefF32> {
8585        // SAFETY: an interior pointer into `self`, valid for this
8586        // borrow and never freed by the `Ref`.
8587        unsafe {
8588            crate::support::Ref::new(AnimRefF32 {
8589                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3TextureLayer_get_rgbAdd(
8590                    self.raw.as_ptr(),
8591                )),
8592            })
8593        }
8594    }
8595
8596    pub fn rgb_add_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8597        // SAFETY: as above; `&mut self` guarantees exclusivity.
8598        unsafe {
8599            crate::support::RefMut::new(AnimRefF32 {
8600                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3TextureLayer_get_rgbAdd(
8601                    self.raw.as_ptr(),
8602                )),
8603            })
8604        }
8605    }
8606
8607    /// POC texture reference
8608    pub fn poc_texture(&self) -> u32 {
8609        // SAFETY: plain scalar read through a live handle.
8610        unsafe { ffi::whiteout_m3_M3TextureLayer_get_pocTexture(self.raw.as_ptr()) }
8611    }
8612
8613    pub fn set_poc_texture(&mut self, value: u32) {
8614        // SAFETY: plain scalar write through a live handle.
8615        unsafe { ffi::whiteout_m3_M3TextureLayer_set_pocTexture(self.raw.as_ptr(), value) }
8616    }
8617
8618    /// Noise amplitude (v24+)
8619    pub fn noise_amplitude(&self) -> f32 {
8620        // SAFETY: plain scalar read through a live handle.
8621        unsafe { ffi::whiteout_m3_M3TextureLayer_get_noiseAmplitude(self.raw.as_ptr()) }
8622    }
8623
8624    pub fn set_noise_amplitude(&mut self, value: f32) {
8625        // SAFETY: plain scalar write through a live handle.
8626        unsafe { ffi::whiteout_m3_M3TextureLayer_set_noiseAmplitude(self.raw.as_ptr(), value) }
8627    }
8628
8629    /// Noise frequency (v24+)
8630    pub fn noise_frequency(&self) -> f32 {
8631        // SAFETY: plain scalar read through a live handle.
8632        unsafe { ffi::whiteout_m3_M3TextureLayer_get_noiseFrequency(self.raw.as_ptr()) }
8633    }
8634
8635    pub fn set_noise_frequency(&mut self, value: f32) {
8636        // SAFETY: plain scalar write through a live handle.
8637        unsafe { ffi::whiteout_m3_M3TextureLayer_set_noiseFrequency(self.raw.as_ptr(), value) }
8638    }
8639
8640    /// Texture source override
8641    pub fn texture_source(&self) -> u32 {
8642        // SAFETY: plain scalar read through a live handle.
8643        unsafe { ffi::whiteout_m3_M3TextureLayer_get_textureSource(self.raw.as_ptr()) }
8644    }
8645
8646    pub fn set_texture_source(&mut self, value: u32) {
8647        // SAFETY: plain scalar write through a live handle.
8648        unsafe { ffi::whiteout_m3_M3TextureLayer_set_textureSource(self.raw.as_ptr(), value) }
8649    }
8650
8651    /// AVI playback frame rate
8652    pub fn avi_frame_rate(&self) -> u32 {
8653        // SAFETY: plain scalar read through a live handle.
8654        unsafe { ffi::whiteout_m3_M3TextureLayer_get_aviFrameRate(self.raw.as_ptr()) }
8655    }
8656
8657    pub fn set_avi_frame_rate(&mut self, value: u32) {
8658        // SAFETY: plain scalar write through a live handle.
8659        unsafe { ffi::whiteout_m3_M3TextureLayer_set_aviFrameRate(self.raw.as_ptr(), value) }
8660    }
8661
8662    /// AVI start frame
8663    pub fn avi_start(&self) -> u32 {
8664        // SAFETY: plain scalar read through a live handle.
8665        unsafe { ffi::whiteout_m3_M3TextureLayer_get_aviStart(self.raw.as_ptr()) }
8666    }
8667
8668    pub fn set_avi_start(&mut self, value: u32) {
8669        // SAFETY: plain scalar write through a live handle.
8670        unsafe { ffi::whiteout_m3_M3TextureLayer_set_aviStart(self.raw.as_ptr(), value) }
8671    }
8672
8673    /// AVI stop frame
8674    pub fn avi_stop(&self) -> u32 {
8675        // SAFETY: plain scalar read through a live handle.
8676        unsafe { ffi::whiteout_m3_M3TextureLayer_get_aviStop(self.raw.as_ptr()) }
8677    }
8678
8679    pub fn set_avi_stop(&mut self, value: u32) {
8680        // SAFETY: plain scalar write through a live handle.
8681        unsafe { ffi::whiteout_m3_M3TextureLayer_set_aviStop(self.raw.as_ptr(), value) }
8682    }
8683
8684    /// AVI loop mode
8685    pub fn avi_loop(&self) -> u32 {
8686        // SAFETY: plain scalar read through a live handle.
8687        unsafe { ffi::whiteout_m3_M3TextureLayer_get_aviLoop(self.raw.as_ptr()) }
8688    }
8689
8690    pub fn set_avi_loop(&mut self, value: u32) {
8691        // SAFETY: plain scalar write through a live handle.
8692        unsafe { ffi::whiteout_m3_M3TextureLayer_set_aviLoop(self.raw.as_ptr(), value) }
8693    }
8694
8695    /// AVI sync mode
8696    pub fn avi_sync(&self) -> u32 {
8697        // SAFETY: plain scalar read through a live handle.
8698        unsafe { ffi::whiteout_m3_M3TextureLayer_get_aviSync(self.raw.as_ptr()) }
8699    }
8700
8701    pub fn set_avi_sync(&mut self, value: u32) {
8702        // SAFETY: plain scalar write through a live handle.
8703        unsafe { ffi::whiteout_m3_M3TextureLayer_set_aviSync(self.raw.as_ptr(), value) }
8704    }
8705
8706    /// AVI play control
8707    /// Borrows the field in place — no copy, no allocation.
8708    pub fn avi_play(&self) -> crate::support::Ref<'_, AnimRefU32> {
8709        // SAFETY: an interior pointer into `self`, valid for this
8710        // borrow and never freed by the `Ref`.
8711        unsafe {
8712            crate::support::Ref::new(AnimRefU32 {
8713                raw: core::ptr::NonNull::new_unchecked(
8714                    ffi::whiteout_m3_M3TextureLayer_get_aviPlay(self.raw.as_ptr()),
8715                ),
8716            })
8717        }
8718    }
8719
8720    pub fn avi_play_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
8721        // SAFETY: as above; `&mut self` guarantees exclusivity.
8722        unsafe {
8723            crate::support::RefMut::new(AnimRefU32 {
8724                raw: core::ptr::NonNull::new_unchecked(
8725                    ffi::whiteout_m3_M3TextureLayer_get_aviPlay(self.raw.as_ptr()),
8726                ),
8727            })
8728        }
8729    }
8730
8731    /// AVI restart control
8732    /// Borrows the field in place — no copy, no allocation.
8733    pub fn avi_restart(&self) -> crate::support::Ref<'_, AnimRefU32> {
8734        // SAFETY: an interior pointer into `self`, valid for this
8735        // borrow and never freed by the `Ref`.
8736        unsafe {
8737            crate::support::Ref::new(AnimRefU32 {
8738                raw: core::ptr::NonNull::new_unchecked(
8739                    ffi::whiteout_m3_M3TextureLayer_get_aviRestart(self.raw.as_ptr()),
8740                ),
8741            })
8742        }
8743    }
8744
8745    pub fn avi_restart_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
8746        // SAFETY: as above; `&mut self` guarantees exclusivity.
8747        unsafe {
8748            crate::support::RefMut::new(AnimRefU32 {
8749                raw: core::ptr::NonNull::new_unchecked(
8750                    ffi::whiteout_m3_M3TextureLayer_get_aviRestart(self.raw.as_ptr()),
8751                ),
8752            })
8753        }
8754    }
8755
8756    /// Flipbook grid rows
8757    pub fn flipbook_rows(&self) -> u32 {
8758        // SAFETY: plain scalar read through a live handle.
8759        unsafe { ffi::whiteout_m3_M3TextureLayer_get_flipbookRows(self.raw.as_ptr()) }
8760    }
8761
8762    pub fn set_flipbook_rows(&mut self, value: u32) {
8763        // SAFETY: plain scalar write through a live handle.
8764        unsafe { ffi::whiteout_m3_M3TextureLayer_set_flipbookRows(self.raw.as_ptr(), value) }
8765    }
8766
8767    /// Flipbook grid columns
8768    pub fn flipbook_columns(&self) -> u32 {
8769        // SAFETY: plain scalar read through a live handle.
8770        unsafe { ffi::whiteout_m3_M3TextureLayer_get_flipbookColumns(self.raw.as_ptr()) }
8771    }
8772
8773    pub fn set_flipbook_columns(&mut self, value: u32) {
8774        // SAFETY: plain scalar write through a live handle.
8775        unsafe { ffi::whiteout_m3_M3TextureLayer_set_flipbookColumns(self.raw.as_ptr(), value) }
8776    }
8777
8778    /// Animated flipbook frame index
8779    /// Borrows the field in place — no copy, no allocation.
8780    pub fn current_frame(&self) -> crate::support::Ref<'_, AnimRefU16> {
8781        // SAFETY: an interior pointer into `self`, valid for this
8782        // borrow and never freed by the `Ref`.
8783        unsafe {
8784            crate::support::Ref::new(AnimRefU16 {
8785                raw: core::ptr::NonNull::new_unchecked(
8786                    ffi::whiteout_m3_M3TextureLayer_get_currentFrame(self.raw.as_ptr()),
8787                ),
8788            })
8789        }
8790    }
8791
8792    pub fn current_frame_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU16> {
8793        // SAFETY: as above; `&mut self` guarantees exclusivity.
8794        unsafe {
8795            crate::support::RefMut::new(AnimRefU16 {
8796                raw: core::ptr::NonNull::new_unchecked(
8797                    ffi::whiteout_m3_M3TextureLayer_get_currentFrame(self.raw.as_ptr()),
8798                ),
8799            })
8800        }
8801    }
8802
8803    /// Animated UV offset
8804    /// Borrows the field in place — no copy, no allocation.
8805    pub fn uv_offset(&self) -> crate::support::Ref<'_, AnimRefVector2f> {
8806        // SAFETY: an interior pointer into `self`, valid for this
8807        // borrow and never freed by the `Ref`.
8808        unsafe {
8809            crate::support::Ref::new(AnimRefVector2f {
8810                raw: core::ptr::NonNull::new_unchecked(
8811                    ffi::whiteout_m3_M3TextureLayer_get_uvOffset(self.raw.as_ptr()),
8812                ),
8813            })
8814        }
8815    }
8816
8817    pub fn uv_offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector2f> {
8818        // SAFETY: as above; `&mut self` guarantees exclusivity.
8819        unsafe {
8820            crate::support::RefMut::new(AnimRefVector2f {
8821                raw: core::ptr::NonNull::new_unchecked(
8822                    ffi::whiteout_m3_M3TextureLayer_get_uvOffset(self.raw.as_ptr()),
8823                ),
8824            })
8825        }
8826    }
8827
8828    /// Animated UV rotation angles
8829    /// Borrows the field in place — no copy, no allocation.
8830    pub fn uv_angle(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
8831        // SAFETY: an interior pointer into `self`, valid for this
8832        // borrow and never freed by the `Ref`.
8833        unsafe {
8834            crate::support::Ref::new(AnimRefVector3f {
8835                raw: core::ptr::NonNull::new_unchecked(
8836                    ffi::whiteout_m3_M3TextureLayer_get_uvAngle(self.raw.as_ptr()),
8837                ),
8838            })
8839        }
8840    }
8841
8842    pub fn uv_angle_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
8843        // SAFETY: as above; `&mut self` guarantees exclusivity.
8844        unsafe {
8845            crate::support::RefMut::new(AnimRefVector3f {
8846                raw: core::ptr::NonNull::new_unchecked(
8847                    ffi::whiteout_m3_M3TextureLayer_get_uvAngle(self.raw.as_ptr()),
8848                ),
8849            })
8850        }
8851    }
8852
8853    /// Animated UV tiling
8854    /// Borrows the field in place — no copy, no allocation.
8855    pub fn uv_tiling(&self) -> crate::support::Ref<'_, AnimRefVector2f> {
8856        // SAFETY: an interior pointer into `self`, valid for this
8857        // borrow and never freed by the `Ref`.
8858        unsafe {
8859            crate::support::Ref::new(AnimRefVector2f {
8860                raw: core::ptr::NonNull::new_unchecked(
8861                    ffi::whiteout_m3_M3TextureLayer_get_uvTiling(self.raw.as_ptr()),
8862                ),
8863            })
8864        }
8865    }
8866
8867    pub fn uv_tiling_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector2f> {
8868        // SAFETY: as above; `&mut self` guarantees exclusivity.
8869        unsafe {
8870            crate::support::RefMut::new(AnimRefVector2f {
8871                raw: core::ptr::NonNull::new_unchecked(
8872                    ffi::whiteout_m3_M3TextureLayer_get_uvTiling(self.raw.as_ptr()),
8873                ),
8874            })
8875        }
8876    }
8877
8878    /// Animated W offset (3D textures)
8879    /// Borrows the field in place — no copy, no allocation.
8880    pub fn w_offset(&self) -> crate::support::Ref<'_, AnimRefF32> {
8881        // SAFETY: an interior pointer into `self`, valid for this
8882        // borrow and never freed by the `Ref`.
8883        unsafe {
8884            crate::support::Ref::new(AnimRefF32 {
8885                raw: core::ptr::NonNull::new_unchecked(
8886                    ffi::whiteout_m3_M3TextureLayer_get_wOffset(self.raw.as_ptr()),
8887                ),
8888            })
8889        }
8890    }
8891
8892    pub fn w_offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8893        // SAFETY: as above; `&mut self` guarantees exclusivity.
8894        unsafe {
8895            crate::support::RefMut::new(AnimRefF32 {
8896                raw: core::ptr::NonNull::new_unchecked(
8897                    ffi::whiteout_m3_M3TextureLayer_get_wOffset(self.raw.as_ptr()),
8898                ),
8899            })
8900        }
8901    }
8902
8903    /// Animated W tiling (3D textures)
8904    /// Borrows the field in place — no copy, no allocation.
8905    pub fn w_tiling(&self) -> crate::support::Ref<'_, AnimRefF32> {
8906        // SAFETY: an interior pointer into `self`, valid for this
8907        // borrow and never freed by the `Ref`.
8908        unsafe {
8909            crate::support::Ref::new(AnimRefF32 {
8910                raw: core::ptr::NonNull::new_unchecked(
8911                    ffi::whiteout_m3_M3TextureLayer_get_wTiling(self.raw.as_ptr()),
8912                ),
8913            })
8914        }
8915    }
8916
8917    pub fn w_tiling_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8918        // SAFETY: as above; `&mut self` guarantees exclusivity.
8919        unsafe {
8920            crate::support::RefMut::new(AnimRefF32 {
8921                raw: core::ptr::NonNull::new_unchecked(
8922                    ffi::whiteout_m3_M3TextureLayer_get_wTiling(self.raw.as_ptr()),
8923                ),
8924            })
8925        }
8926    }
8927
8928    /// Animated map alpha; rests at one (above)
8929    /// Borrows the field in place — no copy, no allocation.
8930    pub fn map_alpha(&self) -> crate::support::Ref<'_, AnimRefF32> {
8931        // SAFETY: an interior pointer into `self`, valid for this
8932        // borrow and never freed by the `Ref`.
8933        unsafe {
8934            crate::support::Ref::new(AnimRefF32 {
8935                raw: core::ptr::NonNull::new_unchecked(
8936                    ffi::whiteout_m3_M3TextureLayer_get_mapAlpha(self.raw.as_ptr()),
8937                ),
8938            })
8939        }
8940    }
8941
8942    pub fn map_alpha_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
8943        // SAFETY: as above; `&mut self` guarantees exclusivity.
8944        unsafe {
8945            crate::support::RefMut::new(AnimRefF32 {
8946                raw: core::ptr::NonNull::new_unchecked(
8947                    ffi::whiteout_m3_M3TextureLayer_get_mapAlpha(self.raw.as_ptr()),
8948                ),
8949            })
8950        }
8951    }
8952
8953    /// Tri-planar UV offset (v23+)
8954    /// Borrows the field in place — no copy, no allocation.
8955    pub fn triplanar_offset(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
8956        // SAFETY: an interior pointer into `self`, valid for this
8957        // borrow and never freed by the `Ref`.
8958        unsafe {
8959            crate::support::Ref::new(AnimRefVector3f {
8960                raw: core::ptr::NonNull::new_unchecked(
8961                    ffi::whiteout_m3_M3TextureLayer_get_triplanarOffset(self.raw.as_ptr()),
8962                ),
8963            })
8964        }
8965    }
8966
8967    pub fn triplanar_offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
8968        // SAFETY: as above; `&mut self` guarantees exclusivity.
8969        unsafe {
8970            crate::support::RefMut::new(AnimRefVector3f {
8971                raw: core::ptr::NonNull::new_unchecked(
8972                    ffi::whiteout_m3_M3TextureLayer_get_triplanarOffset(self.raw.as_ptr()),
8973                ),
8974            })
8975        }
8976    }
8977
8978    /// Tri-planar UV scale (v23+)
8979    /// Borrows the field in place — no copy, no allocation.
8980    pub fn triplanar_scale(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
8981        // SAFETY: an interior pointer into `self`, valid for this
8982        // borrow and never freed by the `Ref`.
8983        unsafe {
8984            crate::support::Ref::new(AnimRefVector3f {
8985                raw: core::ptr::NonNull::new_unchecked(
8986                    ffi::whiteout_m3_M3TextureLayer_get_triplanarScale(self.raw.as_ptr()),
8987                ),
8988            })
8989        }
8990    }
8991
8992    pub fn triplanar_scale_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
8993        // SAFETY: as above; `&mut self` guarantees exclusivity.
8994        unsafe {
8995            crate::support::RefMut::new(AnimRefVector3f {
8996                raw: core::ptr::NonNull::new_unchecked(
8997                    ffi::whiteout_m3_M3TextureLayer_get_triplanarScale(self.raw.as_ptr()),
8998                ),
8999            })
9000        }
9001    }
9002
9003    /// Layer whose UV setup this one shares; -1 = own
9004    pub fn uv_source_related(&self) -> u32 {
9005        // SAFETY: plain scalar read through a live handle.
9006        unsafe { ffi::whiteout_m3_M3TextureLayer_get_uvSourceRelated(self.raw.as_ptr()) }
9007    }
9008
9009    pub fn set_uv_source_related(&mut self, value: u32) {
9010        // SAFETY: plain scalar write through a live handle.
9011        unsafe { ffi::whiteout_m3_M3TextureLayer_set_uvSourceRelated(self.raw.as_ptr(), value) }
9012    }
9013
9014    /// Fresnel effect mode
9015    pub fn fresnel_mode(&self) -> FresnelMode {
9016        // SAFETY: scalar read; the discriminant is validated below.
9017        unsafe { ffi::whiteout_m3_M3TextureLayer_get_fresnelMode(self.raw.as_ptr()) }
9018            .try_into()
9019            .expect("unknown enum discriminant from the native library")
9020    }
9021
9022    pub fn set_fresnel_mode(&mut self, value: FresnelMode) {
9023        // SAFETY: scalar write through a live handle.
9024        unsafe { ffi::whiteout_m3_M3TextureLayer_set_fresnelMode(self.raw.as_ptr(), value as i32) }
9025    }
9026
9027    /// Fresnel exponent (edge sharpness)
9028    pub fn fresnel_exponent(&self) -> f32 {
9029        // SAFETY: plain scalar read through a live handle.
9030        unsafe { ffi::whiteout_m3_M3TextureLayer_get_fresnelExponent(self.raw.as_ptr()) }
9031    }
9032
9033    pub fn set_fresnel_exponent(&mut self, value: f32) {
9034        // SAFETY: plain scalar write through a live handle.
9035        unsafe { ffi::whiteout_m3_M3TextureLayer_set_fresnelExponent(self.raw.as_ptr(), value) }
9036    }
9037
9038    /// Fresnel minimum intensity
9039    pub fn fresnel_min(&self) -> f32 {
9040        // SAFETY: plain scalar read through a live handle.
9041        unsafe { ffi::whiteout_m3_M3TextureLayer_get_fresnelMin(self.raw.as_ptr()) }
9042    }
9043
9044    pub fn set_fresnel_min(&mut self, value: f32) {
9045        // SAFETY: plain scalar write through a live handle.
9046        unsafe { ffi::whiteout_m3_M3TextureLayer_set_fresnelMin(self.raw.as_ptr(), value) }
9047    }
9048
9049    /// Fresnel maximum intensity
9050    pub fn fresnel_max(&self) -> f32 {
9051        // SAFETY: plain scalar read through a live handle.
9052        unsafe { ffi::whiteout_m3_M3TextureLayer_get_fresnelMax(self.raw.as_ptr()) }
9053    }
9054
9055    pub fn set_fresnel_max(&mut self, value: f32) {
9056        // SAFETY: plain scalar write through a live handle.
9057        unsafe { ffi::whiteout_m3_M3TextureLayer_set_fresnelMax(self.raw.as_ptr(), value) }
9058    }
9059
9060    /// Fresnel UV translation (v25+)
9061    pub fn fresnel_translation(&self) -> crate::math::Vector3f {
9062        // SAFETY: the getter returns an interior pointer to a
9063        // layout-identical POD; we copy it out immediately.
9064        unsafe {
9065            *(ffi::whiteout_m3_M3TextureLayer_get_fresnelTranslation(self.raw.as_ptr())
9066                as *const crate::math::Vector3f)
9067        }
9068    }
9069
9070    pub fn set_fresnel_translation(&mut self, value: crate::math::Vector3f) {
9071        // SAFETY: as above, in the other direction.
9072        unsafe {
9073            ffi::whiteout_m3_M3TextureLayer_set_fresnelTranslation(
9074                self.raw.as_ptr(),
9075                &value as *const crate::math::Vector3f as *const _,
9076            )
9077        }
9078    }
9079
9080    /// Fresnel mask vector (v25+)
9081    pub fn fresnel_mask(&self) -> crate::math::Vector3f {
9082        // SAFETY: the getter returns an interior pointer to a
9083        // layout-identical POD; we copy it out immediately.
9084        unsafe {
9085            *(ffi::whiteout_m3_M3TextureLayer_get_fresnelMask(self.raw.as_ptr())
9086                as *const crate::math::Vector3f)
9087        }
9088    }
9089
9090    pub fn set_fresnel_mask(&mut self, value: crate::math::Vector3f) {
9091        // SAFETY: as above, in the other direction.
9092        unsafe {
9093            ffi::whiteout_m3_M3TextureLayer_set_fresnelMask(
9094                self.raw.as_ptr(),
9095                &value as *const crate::math::Vector3f as *const _,
9096            )
9097        }
9098    }
9099
9100    /// Fresnel UV rotation (v25+)
9101    pub fn fresnel_rotation(&self) -> crate::math::Vector2f {
9102        // SAFETY: the getter returns an interior pointer to a
9103        // layout-identical POD; we copy it out immediately.
9104        unsafe {
9105            *(ffi::whiteout_m3_M3TextureLayer_get_fresnelRotation(self.raw.as_ptr())
9106                as *const crate::math::Vector2f)
9107        }
9108    }
9109
9110    pub fn set_fresnel_rotation(&mut self, value: crate::math::Vector2f) {
9111        // SAFETY: as above, in the other direction.
9112        unsafe {
9113            ffi::whiteout_m3_M3TextureLayer_set_fresnelRotation(
9114                self.raw.as_ptr(),
9115                &value as *const crate::math::Vector2f as *const _,
9116            )
9117        }
9118    }
9119
9120    /// UV density hint (v0–v25, absent in v26)
9121    pub fn uv_density(&self) -> u32 {
9122        // SAFETY: plain scalar read through a live handle.
9123        unsafe { ffi::whiteout_m3_M3TextureLayer_get_uvDensity(self.raw.as_ptr()) }
9124    }
9125
9126    pub fn set_uv_density(&mut self, value: u32) {
9127        // SAFETY: plain scalar write through a live handle.
9128        unsafe { ffi::whiteout_m3_M3TextureLayer_set_uvDensity(self.raw.as_ptr(), value) }
9129    }
9130}
9131
9132impl Default for TextureLayer {
9133    fn default() -> Self {
9134        Self::new()
9135    }
9136}
9137
9138/// MAT_ — Standard material (v0–v20, 268–352 bytes)
9139///
9140/// The primary material type with up to 18 texture layers (diffuse, specular, emissive, normal, height, etc.), blend mode, HDR multipliers, and per-version extensions for normal-blend and gloss layers.
9141pub struct StandardMaterial {
9142    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3StandardMaterial>,
9143}
9144
9145impl Drop for StandardMaterial {
9146    fn drop(&mut self) {
9147        // SAFETY: `raw` came from a native constructor and Drop runs once.
9148        unsafe { ffi::whiteout_m3_M3StandardMaterial_delete(self.raw.as_ptr()) }
9149    }
9150}
9151
9152impl StandardMaterial {
9153    /// # Safety
9154    /// `raw` must be a live handle this value takes ownership of.
9155    #[allow(dead_code)] // used by whichever methods return this type
9156    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3StandardMaterial) -> Option<Self> {
9157        core::ptr::NonNull::new(raw).map(|raw| StandardMaterial { raw })
9158    }
9159}
9160
9161// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9162// is deliberately NOT implemented — the C++ types make no documented
9163// guarantee about concurrent use, and claiming one we haven't verified
9164// would be unsound. See `@bind thread_safe` in the plan.
9165unsafe impl Send for StandardMaterial {}
9166
9167impl core::fmt::Debug for StandardMaterial {
9168    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9169        f.debug_struct("StandardMaterial").finish_non_exhaustive()
9170    }
9171}
9172
9173impl StandardMaterial {
9174    /// # Panics
9175    /// Panics if the native allocation fails.
9176    pub fn new() -> Self {
9177        // SAFETY: the native constructor returns a live handle; a null here
9178        // means the library is unusable.
9179        unsafe {
9180            let raw = ffi::whiteout_m3_M3StandardMaterial_new();
9181            Self::from_raw(raw).expect("native StandardMaterial allocation failed")
9182        }
9183    }
9184
9185    /// Material name (`Ref<CHAR>`)
9186    pub fn name(&self) -> String {
9187        // SAFETY: the native side hands over an owned CString.
9188        unsafe {
9189            crate::support::take_string(ffi::whiteout_m3_M3StandardMaterial_get_name(
9190                self.raw.as_ptr(),
9191            ))
9192        }
9193    }
9194
9195    pub fn set_name(&mut self, value: &str) {
9196        let value = std::ffi::CString::new(value).unwrap_or_default();
9197        // SAFETY: the pointer outlives the call.
9198        unsafe { ffi::whiteout_m3_M3StandardMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
9199    }
9200
9201    /// Additional flags
9202    pub fn additional_flags(&self) -> MaterialAdditionalFlag {
9203        // SAFETY: scalar read; a flag set accepts any bits.
9204        MaterialAdditionalFlag(unsafe {
9205            ffi::whiteout_m3_M3StandardMaterial_get_additionalFlags(self.raw.as_ptr())
9206        })
9207    }
9208
9209    pub fn set_additional_flags(&mut self, value: MaterialAdditionalFlag) {
9210        // SAFETY: scalar write through a live handle.
9211        unsafe {
9212            ffi::whiteout_m3_M3StandardMaterial_set_additionalFlags(self.raw.as_ptr(), value.0)
9213        }
9214    }
9215
9216    /// Material rendering flags
9217    pub fn flags(&self) -> MaterialFlag {
9218        // SAFETY: scalar read; a flag set accepts any bits.
9219        MaterialFlag(unsafe { ffi::whiteout_m3_M3StandardMaterial_get_flags(self.raw.as_ptr()) })
9220    }
9221
9222    pub fn set_flags(&mut self, value: MaterialFlag) {
9223        // SAFETY: scalar write through a live handle.
9224        unsafe { ffi::whiteout_m3_M3StandardMaterial_set_flags(self.raw.as_ptr(), value.0) }
9225    }
9226
9227    /// Alpha blend mode
9228    pub fn blend_mode(&self) -> BlendMode {
9229        // SAFETY: scalar read; the discriminant is validated below.
9230        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_blendMode(self.raw.as_ptr()) }
9231            .try_into()
9232            .expect("unknown enum discriminant from the native library")
9233    }
9234
9235    pub fn set_blend_mode(&mut self, value: BlendMode) {
9236        // SAFETY: scalar write through a live handle.
9237        unsafe {
9238            ffi::whiteout_m3_M3StandardMaterial_set_blendMode(self.raw.as_ptr(), value as i32)
9239        }
9240    }
9241
9242    /// Render priority (lower = earlier)
9243    pub fn priority(&self) -> i32 {
9244        // SAFETY: plain scalar read through a live handle.
9245        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_priority(self.raw.as_ptr()) }
9246    }
9247
9248    pub fn set_priority(&mut self, value: i32) {
9249        // SAFETY: plain scalar write through a live handle.
9250        unsafe { ffi::whiteout_m3_M3StandardMaterial_set_priority(self.raw.as_ptr(), value) }
9251    }
9252
9253    /// RTT channel mask
9254    pub fn rtt_channels(&self) -> u32 {
9255        // SAFETY: plain scalar read through a live handle.
9256        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_rttChannels(self.raw.as_ptr()) }
9257    }
9258
9259    pub fn set_rtt_channels(&mut self, value: u32) {
9260        // SAFETY: plain scalar write through a live handle.
9261        unsafe { ffi::whiteout_m3_M3StandardMaterial_set_rttChannels(self.raw.as_ptr(), value) }
9262    }
9263
9264    /// Specular highlight exponent
9265    pub fn specular_exponent(&self) -> f32 {
9266        // SAFETY: plain scalar read through a live handle.
9267        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_specularExponent(self.raw.as_ptr()) }
9268    }
9269
9270    pub fn set_specular_exponent(&mut self, value: f32) {
9271        // SAFETY: plain scalar write through a live handle.
9272        unsafe {
9273            ffi::whiteout_m3_M3StandardMaterial_set_specularExponent(self.raw.as_ptr(), value)
9274        }
9275    }
9276
9277    /// Depth blend falloff distance
9278    pub fn depth_blend_falloff(&self) -> f32 {
9279        // SAFETY: plain scalar read through a live handle.
9280        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_depthBlendFalloff(self.raw.as_ptr()) }
9281    }
9282
9283    pub fn set_depth_blend_falloff(&mut self, value: f32) {
9284        // SAFETY: plain scalar write through a live handle.
9285        unsafe {
9286            ffi::whiteout_m3_M3StandardMaterial_set_depthBlendFalloff(self.raw.as_ptr(), value)
9287        }
9288    }
9289
9290    /// Alpha test cut-off value
9291    pub fn alpha_test_threshold(&self) -> u32 {
9292        // SAFETY: plain scalar read through a live handle.
9293        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_alphaTestThreshold(self.raw.as_ptr()) }
9294    }
9295
9296    pub fn set_alpha_test_threshold(&mut self, value: u32) {
9297        // SAFETY: plain scalar write through a live handle.
9298        unsafe {
9299            ffi::whiteout_m3_M3StandardMaterial_set_alphaTestThreshold(self.raw.as_ptr(), value)
9300        }
9301    }
9302
9303    /// HDR specular multiplier
9304    pub fn hdr_specular_multiplier(&self) -> f32 {
9305        // SAFETY: plain scalar read through a live handle.
9306        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_hdrSpecularMultiplier(self.raw.as_ptr()) }
9307    }
9308
9309    pub fn set_hdr_specular_multiplier(&mut self, value: f32) {
9310        // SAFETY: plain scalar write through a live handle.
9311        unsafe {
9312            ffi::whiteout_m3_M3StandardMaterial_set_hdrSpecularMultiplier(self.raw.as_ptr(), value)
9313        }
9314    }
9315
9316    /// HDR emissive multiplier
9317    pub fn hdr_emissive_multiplier(&self) -> f32 {
9318        // SAFETY: plain scalar read through a live handle.
9319        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_hdrEmissiveMultiplier(self.raw.as_ptr()) }
9320    }
9321
9322    pub fn set_hdr_emissive_multiplier(&mut self, value: f32) {
9323        // SAFETY: plain scalar write through a live handle.
9324        unsafe {
9325            ffi::whiteout_m3_M3StandardMaterial_set_hdrEmissiveMultiplier(self.raw.as_ptr(), value)
9326        }
9327    }
9328
9329    /// HDR environment constant (v20)
9330    pub fn hdr_environment_constant(&self) -> f32 {
9331        // SAFETY: plain scalar read through a live handle.
9332        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_hdrEnvironmentConstant(self.raw.as_ptr()) }
9333    }
9334
9335    pub fn set_hdr_environment_constant(&mut self, value: f32) {
9336        // SAFETY: plain scalar write through a live handle.
9337        unsafe {
9338            ffi::whiteout_m3_M3StandardMaterial_set_hdrEnvironmentConstant(self.raw.as_ptr(), value)
9339        }
9340    }
9341
9342    /// HDR environment diffuse (v20)
9343    pub fn hdr_environment_diffuse(&self) -> f32 {
9344        // SAFETY: plain scalar read through a live handle.
9345        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_hdrEnvironmentDiffuse(self.raw.as_ptr()) }
9346    }
9347
9348    pub fn set_hdr_environment_diffuse(&mut self, value: f32) {
9349        // SAFETY: plain scalar write through a live handle.
9350        unsafe {
9351            ffi::whiteout_m3_M3StandardMaterial_set_hdrEnvironmentDiffuse(self.raw.as_ptr(), value)
9352        }
9353    }
9354
9355    /// HDR environment specular (v20)
9356    pub fn hdr_environment_specular(&self) -> f32 {
9357        // SAFETY: plain scalar read through a live handle.
9358        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_hdrEnvironmentSpecular(self.raw.as_ptr()) }
9359    }
9360
9361    pub fn set_hdr_environment_specular(&mut self, value: f32) {
9362        // SAFETY: plain scalar write through a live handle.
9363        unsafe {
9364            ffi::whiteout_m3_M3StandardMaterial_set_hdrEnvironmentSpecular(self.raw.as_ptr(), value)
9365        }
9366    }
9367
9368    /// Material class (unit, building, etc.)
9369    pub fn material_class(&self) -> MaterialClass {
9370        // SAFETY: scalar read; the discriminant is validated below.
9371        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_materialClass(self.raw.as_ptr()) }
9372            .try_into()
9373            .expect("unknown enum discriminant from the native library")
9374    }
9375
9376    pub fn set_material_class(&mut self, value: MaterialClass) {
9377        // SAFETY: scalar write through a live handle.
9378        unsafe {
9379            ffi::whiteout_m3_M3StandardMaterial_set_materialClass(self.raw.as_ptr(), value as i32)
9380        }
9381    }
9382
9383    /// Layer blend operation
9384    pub fn layer_blend_mode(&self) -> LayerBlendOp {
9385        // SAFETY: scalar read; the discriminant is validated below.
9386        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_layerBlendMode(self.raw.as_ptr()) }
9387            .try_into()
9388            .expect("unknown enum discriminant from the native library")
9389    }
9390
9391    pub fn set_layer_blend_mode(&mut self, value: LayerBlendOp) {
9392        // SAFETY: scalar write through a live handle.
9393        unsafe {
9394            ffi::whiteout_m3_M3StandardMaterial_set_layerBlendMode(self.raw.as_ptr(), value as i32)
9395        }
9396    }
9397
9398    /// Emissive layer 1 blend mode
9399    pub fn emissive_blend_mode_1(&self) -> LayerBlendOp {
9400        // SAFETY: scalar read; the discriminant is validated below.
9401        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_emissiveBlendMode1(self.raw.as_ptr()) }
9402            .try_into()
9403            .expect("unknown enum discriminant from the native library")
9404    }
9405
9406    pub fn set_emissive_blend_mode_1(&mut self, value: LayerBlendOp) {
9407        // SAFETY: scalar write through a live handle.
9408        unsafe {
9409            ffi::whiteout_m3_M3StandardMaterial_set_emissiveBlendMode1(
9410                self.raw.as_ptr(),
9411                value as i32,
9412            )
9413        }
9414    }
9415
9416    /// Emissive layer 2 blend mode
9417    pub fn emissive_blend_mode_2(&self) -> LayerBlendOp {
9418        // SAFETY: scalar read; the discriminant is validated below.
9419        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_emissiveBlendMode2(self.raw.as_ptr()) }
9420            .try_into()
9421            .expect("unknown enum discriminant from the native library")
9422    }
9423
9424    pub fn set_emissive_blend_mode_2(&mut self, value: LayerBlendOp) {
9425        // SAFETY: scalar write through a live handle.
9426        unsafe {
9427            ffi::whiteout_m3_M3StandardMaterial_set_emissiveBlendMode2(
9428                self.raw.as_ptr(),
9429                value as i32,
9430            )
9431        }
9432    }
9433
9434    /// Specular computation mode
9435    pub fn specular_mode(&self) -> SpecularMode {
9436        // SAFETY: scalar read; the discriminant is validated below.
9437        unsafe { ffi::whiteout_m3_M3StandardMaterial_get_specularMode(self.raw.as_ptr()) }
9438            .try_into()
9439            .expect("unknown enum discriminant from the native library")
9440    }
9441
9442    pub fn set_specular_mode(&mut self, value: SpecularMode) {
9443        // SAFETY: scalar write through a live handle.
9444        unsafe {
9445            ffi::whiteout_m3_M3StandardMaterial_set_specularMode(self.raw.as_ptr(), value as i32)
9446        }
9447    }
9448
9449    /// Animated parallax height
9450    /// Borrows the field in place — no copy, no allocation.
9451    pub fn parallax_height(&self) -> crate::support::Ref<'_, AnimRefF32> {
9452        // SAFETY: an interior pointer into `self`, valid for this
9453        // borrow and never freed by the `Ref`.
9454        unsafe {
9455            crate::support::Ref::new(AnimRefF32 {
9456                raw: core::ptr::NonNull::new_unchecked(
9457                    ffi::whiteout_m3_M3StandardMaterial_get_parallaxHeight(self.raw.as_ptr()),
9458                ),
9459            })
9460        }
9461    }
9462
9463    pub fn parallax_height_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
9464        // SAFETY: as above; `&mut self` guarantees exclusivity.
9465        unsafe {
9466            crate::support::RefMut::new(AnimRefF32 {
9467                raw: core::ptr::NonNull::new_unchecked(
9468                    ffi::whiteout_m3_M3StandardMaterial_get_parallaxHeight(self.raw.as_ptr()),
9469                ),
9470            })
9471        }
9472    }
9473
9474    /// Animated motion blur amount
9475    /// Borrows the field in place — no copy, no allocation.
9476    pub fn motion_blur_amount(&self) -> crate::support::Ref<'_, AnimRefF32> {
9477        // SAFETY: an interior pointer into `self`, valid for this
9478        // borrow and never freed by the `Ref`.
9479        unsafe {
9480            crate::support::Ref::new(AnimRefF32 {
9481                raw: core::ptr::NonNull::new_unchecked(
9482                    ffi::whiteout_m3_M3StandardMaterial_get_motionBlurAmount(self.raw.as_ptr()),
9483                ),
9484            })
9485        }
9486    }
9487
9488    pub fn motion_blur_amount_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
9489        // SAFETY: as above; `&mut self` guarantees exclusivity.
9490        unsafe {
9491            crate::support::RefMut::new(AnimRefF32 {
9492                raw: core::ptr::NonNull::new_unchecked(
9493                    ffi::whiteout_m3_M3StandardMaterial_get_motionBlurAmount(self.raw.as_ptr()),
9494                ),
9495            })
9496        }
9497    }
9498
9499    /// Normal blend factors (v19+)
9500    pub fn normal_blend_factors_len(&self) -> usize {
9501        // SAFETY: scalar read through a live handle.
9502        unsafe {
9503            ffi::whiteout_m3_M3StandardMaterial_get_normalBlendFactors_count(self.raw.as_ptr())
9504        }
9505    }
9506
9507    /// Borrows element `index` in place. `None` when out of range.
9508    pub fn normal_blend_factors(
9509        &self,
9510        index: usize,
9511    ) -> Option<crate::support::Ref<'_, AnimRefF32>> {
9512        if index >= self.normal_blend_factors_len() {
9513            return None;
9514        }
9515        // SAFETY: index checked above; the pointer is interior to `self`.
9516        unsafe {
9517            Some(crate::support::Ref::new(AnimRefF32 {
9518                raw: core::ptr::NonNull::new_unchecked(
9519                    ffi::whiteout_m3_M3StandardMaterial_get_normalBlendFactors_at(
9520                        self.raw.as_ptr(),
9521                        index,
9522                    ),
9523                ),
9524            }))
9525        }
9526    }
9527
9528    pub fn normal_blend_factors_mut(
9529        &mut self,
9530        index: usize,
9531    ) -> Option<crate::support::RefMut<'_, AnimRefF32>> {
9532        if index >= self.normal_blend_factors_len() {
9533            return None;
9534        }
9535        // SAFETY: as above; `&mut self` guarantees exclusivity.
9536        unsafe {
9537            Some(crate::support::RefMut::new(AnimRefF32 {
9538                raw: core::ptr::NonNull::new_unchecked(
9539                    ffi::whiteout_m3_M3StandardMaterial_get_normalBlendFactors_at(
9540                        self.raw.as_ptr(),
9541                        index,
9542                    ),
9543                ),
9544            }))
9545        }
9546    }
9547
9548    /// Iterate the elements, borrowing each in turn.
9549    pub fn normal_blend_factors_iter(
9550        &self,
9551    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AnimRefF32>> {
9552        (0..self.normal_blend_factors_len())
9553            .map(move |i| self.normal_blend_factors(i).expect("index below len"))
9554    }
9555
9556    pub fn resize_normal_blend_factors(&mut self, count: usize) {
9557        // SAFETY: exclusive access, so no borrow is outstanding.
9558        unsafe {
9559            ffi::whiteout_m3_M3StandardMaterial_resize_normalBlendFactors(self.raw.as_ptr(), count)
9560        }
9561    }
9562}
9563
9564impl Default for StandardMaterial {
9565    fn default() -> Self {
9566        Self::new()
9567    }
9568}
9569
9570/// DIS_ — Displacement material (v0–v4, 68 bytes)
9571///
9572/// Applies vertex displacement via a normal map and animated strength.
9573pub struct DisplacementMaterial {
9574    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3DisplacementMaterial>,
9575}
9576
9577impl Drop for DisplacementMaterial {
9578    fn drop(&mut self) {
9579        // SAFETY: `raw` came from a native constructor and Drop runs once.
9580        unsafe { ffi::whiteout_m3_M3DisplacementMaterial_delete(self.raw.as_ptr()) }
9581    }
9582}
9583
9584impl DisplacementMaterial {
9585    /// # Safety
9586    /// `raw` must be a live handle this value takes ownership of.
9587    #[allow(dead_code)] // used by whichever methods return this type
9588    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3DisplacementMaterial) -> Option<Self> {
9589        core::ptr::NonNull::new(raw).map(|raw| DisplacementMaterial { raw })
9590    }
9591}
9592
9593// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9594// is deliberately NOT implemented — the C++ types make no documented
9595// guarantee about concurrent use, and claiming one we haven't verified
9596// would be unsound. See `@bind thread_safe` in the plan.
9597unsafe impl Send for DisplacementMaterial {}
9598
9599impl core::fmt::Debug for DisplacementMaterial {
9600    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9601        f.debug_struct("DisplacementMaterial")
9602            .finish_non_exhaustive()
9603    }
9604}
9605
9606impl DisplacementMaterial {
9607    /// # Panics
9608    /// Panics if the native allocation fails.
9609    pub fn new() -> Self {
9610        // SAFETY: the native constructor returns a live handle; a null here
9611        // means the library is unusable.
9612        unsafe {
9613            let raw = ffi::whiteout_m3_M3DisplacementMaterial_new();
9614            Self::from_raw(raw).expect("native DisplacementMaterial allocation failed")
9615        }
9616    }
9617
9618    /// Material name (`Ref<CHAR>`)
9619    pub fn name(&self) -> String {
9620        // SAFETY: the native side hands over an owned CString.
9621        unsafe {
9622            crate::support::take_string(ffi::whiteout_m3_M3DisplacementMaterial_get_name(
9623                self.raw.as_ptr(),
9624            ))
9625        }
9626    }
9627
9628    pub fn set_name(&mut self, value: &str) {
9629        let value = std::ffi::CString::new(value).unwrap_or_default();
9630        // SAFETY: the pointer outlives the call.
9631        unsafe {
9632            ffi::whiteout_m3_M3DisplacementMaterial_set_name(self.raw.as_ptr(), value.as_ptr())
9633        }
9634    }
9635
9636    /// Unknown field
9637    pub fn unknown(&self) -> u32 {
9638        // SAFETY: plain scalar read through a live handle.
9639        unsafe { ffi::whiteout_m3_M3DisplacementMaterial_get_unknown(self.raw.as_ptr()) }
9640    }
9641
9642    pub fn set_unknown(&mut self, value: u32) {
9643        // SAFETY: plain scalar write through a live handle.
9644        unsafe { ffi::whiteout_m3_M3DisplacementMaterial_set_unknown(self.raw.as_ptr(), value) }
9645    }
9646
9647    /// Animated displacement strength
9648    /// Borrows the field in place — no copy, no allocation.
9649    pub fn strength(&self) -> crate::support::Ref<'_, AnimRefF32> {
9650        // SAFETY: an interior pointer into `self`, valid for this
9651        // borrow and never freed by the `Ref`.
9652        unsafe {
9653            crate::support::Ref::new(AnimRefF32 {
9654                raw: core::ptr::NonNull::new_unchecked(
9655                    ffi::whiteout_m3_M3DisplacementMaterial_get_strength(self.raw.as_ptr()),
9656                ),
9657            })
9658        }
9659    }
9660
9661    pub fn strength_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
9662        // SAFETY: as above; `&mut self` guarantees exclusivity.
9663        unsafe {
9664            crate::support::RefMut::new(AnimRefF32 {
9665                raw: core::ptr::NonNull::new_unchecked(
9666                    ffi::whiteout_m3_M3DisplacementMaterial_get_strength(self.raw.as_ptr()),
9667                ),
9668            })
9669        }
9670    }
9671
9672    /// Render priority
9673    pub fn priority(&self) -> u32 {
9674        // SAFETY: plain scalar read through a live handle.
9675        unsafe { ffi::whiteout_m3_M3DisplacementMaterial_get_priority(self.raw.as_ptr()) }
9676    }
9677
9678    pub fn set_priority(&mut self, value: u32) {
9679        // SAFETY: plain scalar write through a live handle.
9680        unsafe { ffi::whiteout_m3_M3DisplacementMaterial_set_priority(self.raw.as_ptr(), value) }
9681    }
9682}
9683
9684impl Default for DisplacementMaterial {
9685    fn default() -> Self {
9686        Self::new()
9687    }
9688}
9689
9690/// CMS_ — Composite material section (v0, 24 bytes)
9691///
9692/// A single section within a composite material, referencing another material index with an animated blend multiplier.
9693pub struct CompositeSection {
9694    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3CompositeSection>,
9695}
9696
9697impl Drop for CompositeSection {
9698    fn drop(&mut self) {
9699        // SAFETY: `raw` came from a native constructor and Drop runs once.
9700        unsafe { ffi::whiteout_m3_M3CompositeSection_delete(self.raw.as_ptr()) }
9701    }
9702}
9703
9704impl CompositeSection {
9705    /// # Safety
9706    /// `raw` must be a live handle this value takes ownership of.
9707    #[allow(dead_code)] // used by whichever methods return this type
9708    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3CompositeSection) -> Option<Self> {
9709        core::ptr::NonNull::new(raw).map(|raw| CompositeSection { raw })
9710    }
9711}
9712
9713// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9714// is deliberately NOT implemented — the C++ types make no documented
9715// guarantee about concurrent use, and claiming one we haven't verified
9716// would be unsound. See `@bind thread_safe` in the plan.
9717unsafe impl Send for CompositeSection {}
9718
9719impl core::fmt::Debug for CompositeSection {
9720    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9721        f.debug_struct("CompositeSection").finish_non_exhaustive()
9722    }
9723}
9724
9725impl CompositeSection {
9726    /// # Panics
9727    /// Panics if the native allocation fails.
9728    pub fn new() -> Self {
9729        // SAFETY: the native constructor returns a live handle; a null here
9730        // means the library is unusable.
9731        unsafe {
9732            let raw = ffi::whiteout_m3_M3CompositeSection_new();
9733            Self::from_raw(raw).expect("native CompositeSection allocation failed")
9734        }
9735    }
9736
9737    /// Index into MATM array
9738    pub fn material_index(&self) -> u32 {
9739        // SAFETY: plain scalar read through a live handle.
9740        unsafe { ffi::whiteout_m3_M3CompositeSection_get_materialIndex(self.raw.as_ptr()) }
9741    }
9742
9743    pub fn set_material_index(&mut self, value: u32) {
9744        // SAFETY: plain scalar write through a live handle.
9745        unsafe { ffi::whiteout_m3_M3CompositeSection_set_materialIndex(self.raw.as_ptr(), value) }
9746    }
9747
9748    /// Animated blend weight
9749    /// Borrows the field in place — no copy, no allocation.
9750    pub fn map_multiplier(&self) -> crate::support::Ref<'_, AnimRefF32> {
9751        // SAFETY: an interior pointer into `self`, valid for this
9752        // borrow and never freed by the `Ref`.
9753        unsafe {
9754            crate::support::Ref::new(AnimRefF32 {
9755                raw: core::ptr::NonNull::new_unchecked(
9756                    ffi::whiteout_m3_M3CompositeSection_get_mapMultiplier(self.raw.as_ptr()),
9757                ),
9758            })
9759        }
9760    }
9761
9762    pub fn map_multiplier_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
9763        // SAFETY: as above; `&mut self` guarantees exclusivity.
9764        unsafe {
9765            crate::support::RefMut::new(AnimRefF32 {
9766                raw: core::ptr::NonNull::new_unchecked(
9767                    ffi::whiteout_m3_M3CompositeSection_get_mapMultiplier(self.raw.as_ptr()),
9768                ),
9769            })
9770        }
9771    }
9772}
9773
9774impl Default for CompositeSection {
9775    fn default() -> Self {
9776        Self::new()
9777    }
9778}
9779
9780/// CMP_ — Composite material (v0–v2, 28 bytes)
9781///
9782/// Blends multiple sub-materials via CompositeSection entries.
9783pub struct CompositeMaterial {
9784    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3CompositeMaterial>,
9785}
9786
9787impl Drop for CompositeMaterial {
9788    fn drop(&mut self) {
9789        // SAFETY: `raw` came from a native constructor and Drop runs once.
9790        unsafe { ffi::whiteout_m3_M3CompositeMaterial_delete(self.raw.as_ptr()) }
9791    }
9792}
9793
9794impl CompositeMaterial {
9795    /// # Safety
9796    /// `raw` must be a live handle this value takes ownership of.
9797    #[allow(dead_code)] // used by whichever methods return this type
9798    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3CompositeMaterial) -> Option<Self> {
9799        core::ptr::NonNull::new(raw).map(|raw| CompositeMaterial { raw })
9800    }
9801}
9802
9803// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9804// is deliberately NOT implemented — the C++ types make no documented
9805// guarantee about concurrent use, and claiming one we haven't verified
9806// would be unsound. See `@bind thread_safe` in the plan.
9807unsafe impl Send for CompositeMaterial {}
9808
9809impl core::fmt::Debug for CompositeMaterial {
9810    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9811        f.debug_struct("CompositeMaterial").finish_non_exhaustive()
9812    }
9813}
9814
9815impl CompositeMaterial {
9816    /// # Panics
9817    /// Panics if the native allocation fails.
9818    pub fn new() -> Self {
9819        // SAFETY: the native constructor returns a live handle; a null here
9820        // means the library is unusable.
9821        unsafe {
9822            let raw = ffi::whiteout_m3_M3CompositeMaterial_new();
9823            Self::from_raw(raw).expect("native CompositeMaterial allocation failed")
9824        }
9825    }
9826
9827    /// Material name (`Ref<CHAR>`)
9828    pub fn name(&self) -> String {
9829        // SAFETY: the native side hands over an owned CString.
9830        unsafe {
9831            crate::support::take_string(ffi::whiteout_m3_M3CompositeMaterial_get_name(
9832                self.raw.as_ptr(),
9833            ))
9834        }
9835    }
9836
9837    pub fn set_name(&mut self, value: &str) {
9838        let value = std::ffi::CString::new(value).unwrap_or_default();
9839        // SAFETY: the pointer outlives the call.
9840        unsafe { ffi::whiteout_m3_M3CompositeMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
9841    }
9842
9843    /// Render priority
9844    pub fn priority(&self) -> u32 {
9845        // SAFETY: plain scalar read through a live handle.
9846        unsafe { ffi::whiteout_m3_M3CompositeMaterial_get_priority(self.raw.as_ptr()) }
9847    }
9848
9849    pub fn set_priority(&mut self, value: u32) {
9850        // SAFETY: plain scalar write through a live handle.
9851        unsafe { ffi::whiteout_m3_M3CompositeMaterial_set_priority(self.raw.as_ptr(), value) }
9852    }
9853
9854    /// Sub-material sections (CMS_)
9855    pub fn sections_len(&self) -> usize {
9856        // SAFETY: scalar read through a live handle.
9857        unsafe { ffi::whiteout_m3_M3CompositeMaterial_get_sections_count(self.raw.as_ptr()) }
9858    }
9859
9860    /// Borrows element `index` in place. `None` when out of range.
9861    pub fn sections(&self, index: usize) -> Option<crate::support::Ref<'_, CompositeSection>> {
9862        if index >= self.sections_len() {
9863            return None;
9864        }
9865        // SAFETY: index checked above; the pointer is interior to `self`.
9866        unsafe {
9867            Some(crate::support::Ref::new(CompositeSection {
9868                raw: core::ptr::NonNull::new_unchecked(
9869                    ffi::whiteout_m3_M3CompositeMaterial_get_sections_at(self.raw.as_ptr(), index),
9870                ),
9871            }))
9872        }
9873    }
9874
9875    pub fn sections_mut(
9876        &mut self,
9877        index: usize,
9878    ) -> Option<crate::support::RefMut<'_, CompositeSection>> {
9879        if index >= self.sections_len() {
9880            return None;
9881        }
9882        // SAFETY: as above; `&mut self` guarantees exclusivity.
9883        unsafe {
9884            Some(crate::support::RefMut::new(CompositeSection {
9885                raw: core::ptr::NonNull::new_unchecked(
9886                    ffi::whiteout_m3_M3CompositeMaterial_get_sections_at(self.raw.as_ptr(), index),
9887                ),
9888            }))
9889        }
9890    }
9891
9892    /// Iterate the elements, borrowing each in turn.
9893    pub fn sections_iter(
9894        &self,
9895    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, CompositeSection>> {
9896        (0..self.sections_len()).map(move |i| self.sections(i).expect("index below len"))
9897    }
9898
9899    pub fn resize_sections(&mut self, count: usize) {
9900        // SAFETY: exclusive access, so no borrow is outstanding.
9901        unsafe { ffi::whiteout_m3_M3CompositeMaterial_resize_sections(self.raw.as_ptr(), count) }
9902    }
9903}
9904
9905impl Default for CompositeMaterial {
9906    fn default() -> Self {
9907        Self::new()
9908    }
9909}
9910
9911/// TER_ — Terrain material (v0–v1, 28 bytes)
9912///
9913/// Simple terrain-specific material with a single texture layer.
9914pub struct TerrainMaterial {
9915    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3TerrainMaterial>,
9916}
9917
9918impl Drop for TerrainMaterial {
9919    fn drop(&mut self) {
9920        // SAFETY: `raw` came from a native constructor and Drop runs once.
9921        unsafe { ffi::whiteout_m3_M3TerrainMaterial_delete(self.raw.as_ptr()) }
9922    }
9923}
9924
9925impl TerrainMaterial {
9926    /// # Safety
9927    /// `raw` must be a live handle this value takes ownership of.
9928    #[allow(dead_code)] // used by whichever methods return this type
9929    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3TerrainMaterial) -> Option<Self> {
9930        core::ptr::NonNull::new(raw).map(|raw| TerrainMaterial { raw })
9931    }
9932}
9933
9934// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9935// is deliberately NOT implemented — the C++ types make no documented
9936// guarantee about concurrent use, and claiming one we haven't verified
9937// would be unsound. See `@bind thread_safe` in the plan.
9938unsafe impl Send for TerrainMaterial {}
9939
9940impl core::fmt::Debug for TerrainMaterial {
9941    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9942        f.debug_struct("TerrainMaterial").finish_non_exhaustive()
9943    }
9944}
9945
9946impl TerrainMaterial {
9947    /// # Panics
9948    /// Panics if the native allocation fails.
9949    pub fn new() -> Self {
9950        // SAFETY: the native constructor returns a live handle; a null here
9951        // means the library is unusable.
9952        unsafe {
9953            let raw = ffi::whiteout_m3_M3TerrainMaterial_new();
9954            Self::from_raw(raw).expect("native TerrainMaterial allocation failed")
9955        }
9956    }
9957
9958    /// Material name (`Ref<CHAR>`)
9959    pub fn name(&self) -> String {
9960        // SAFETY: the native side hands over an owned CString.
9961        unsafe {
9962            crate::support::take_string(ffi::whiteout_m3_M3TerrainMaterial_get_name(
9963                self.raw.as_ptr(),
9964            ))
9965        }
9966    }
9967
9968    pub fn set_name(&mut self, value: &str) {
9969        let value = std::ffi::CString::new(value).unwrap_or_default();
9970        // SAFETY: the pointer outlives the call.
9971        unsafe { ffi::whiteout_m3_M3TerrainMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
9972    }
9973
9974    /// Unknown field
9975    pub fn unknown(&self) -> u32 {
9976        // SAFETY: plain scalar read through a live handle.
9977        unsafe { ffi::whiteout_m3_M3TerrainMaterial_get_unknown(self.raw.as_ptr()) }
9978    }
9979
9980    pub fn set_unknown(&mut self, value: u32) {
9981        // SAFETY: plain scalar write through a live handle.
9982        unsafe { ffi::whiteout_m3_M3TerrainMaterial_set_unknown(self.raw.as_ptr(), value) }
9983    }
9984}
9985
9986impl Default for TerrainMaterial {
9987    fn default() -> Self {
9988        Self::new()
9989    }
9990}
9991
9992/// VOL_ — Volume material (v0, 84 bytes)
9993///
9994/// Volumetric rendering material with density falloff, color map, and two noise maps for procedural volumetric effects.
9995pub struct VolumeMaterial {
9996    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3VolumeMaterial>,
9997}
9998
9999impl Drop for VolumeMaterial {
10000    fn drop(&mut self) {
10001        // SAFETY: `raw` came from a native constructor and Drop runs once.
10002        unsafe { ffi::whiteout_m3_M3VolumeMaterial_delete(self.raw.as_ptr()) }
10003    }
10004}
10005
10006impl VolumeMaterial {
10007    /// # Safety
10008    /// `raw` must be a live handle this value takes ownership of.
10009    #[allow(dead_code)] // used by whichever methods return this type
10010    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3VolumeMaterial) -> Option<Self> {
10011        core::ptr::NonNull::new(raw).map(|raw| VolumeMaterial { raw })
10012    }
10013}
10014
10015// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10016// is deliberately NOT implemented — the C++ types make no documented
10017// guarantee about concurrent use, and claiming one we haven't verified
10018// would be unsound. See `@bind thread_safe` in the plan.
10019unsafe impl Send for VolumeMaterial {}
10020
10021impl core::fmt::Debug for VolumeMaterial {
10022    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10023        f.debug_struct("VolumeMaterial").finish_non_exhaustive()
10024    }
10025}
10026
10027impl VolumeMaterial {
10028    /// # Panics
10029    /// Panics if the native allocation fails.
10030    pub fn new() -> Self {
10031        // SAFETY: the native constructor returns a live handle; a null here
10032        // means the library is unusable.
10033        unsafe {
10034            let raw = ffi::whiteout_m3_M3VolumeMaterial_new();
10035            Self::from_raw(raw).expect("native VolumeMaterial allocation failed")
10036        }
10037    }
10038
10039    /// Material name (`Ref<CHAR>`)
10040    pub fn name(&self) -> String {
10041        // SAFETY: the native side hands over an owned CString.
10042        unsafe {
10043            crate::support::take_string(ffi::whiteout_m3_M3VolumeMaterial_get_name(
10044                self.raw.as_ptr(),
10045            ))
10046        }
10047    }
10048
10049    pub fn set_name(&mut self, value: &str) {
10050        let value = std::ffi::CString::new(value).unwrap_or_default();
10051        // SAFETY: the pointer outlives the call.
10052        unsafe { ffi::whiteout_m3_M3VolumeMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
10053    }
10054
10055    /// Blend mode
10056    pub fn blend_mode(&self) -> u32 {
10057        // SAFETY: plain scalar read through a live handle.
10058        unsafe { ffi::whiteout_m3_M3VolumeMaterial_get_blendMode(self.raw.as_ptr()) }
10059    }
10060
10061    pub fn set_blend_mode(&mut self, value: u32) {
10062        // SAFETY: plain scalar write through a live handle.
10063        unsafe { ffi::whiteout_m3_M3VolumeMaterial_set_blendMode(self.raw.as_ptr(), value) }
10064    }
10065
10066    /// Density falloff type
10067    pub fn falloff_type(&self) -> VolumeFalloffType {
10068        // SAFETY: scalar read; the discriminant is validated below.
10069        unsafe { ffi::whiteout_m3_M3VolumeMaterial_get_falloffType(self.raw.as_ptr()) }
10070            .try_into()
10071            .expect("unknown enum discriminant from the native library")
10072    }
10073
10074    pub fn set_falloff_type(&mut self, value: VolumeFalloffType) {
10075        // SAFETY: scalar write through a live handle.
10076        unsafe {
10077            ffi::whiteout_m3_M3VolumeMaterial_set_falloffType(self.raw.as_ptr(), value as i32)
10078        }
10079    }
10080
10081    /// Animated density
10082    /// Borrows the field in place — no copy, no allocation.
10083    pub fn density(&self) -> crate::support::Ref<'_, AnimRefF32> {
10084        // SAFETY: an interior pointer into `self`, valid for this
10085        // borrow and never freed by the `Ref`.
10086        unsafe {
10087            crate::support::Ref::new(AnimRefF32 {
10088                raw: core::ptr::NonNull::new_unchecked(
10089                    ffi::whiteout_m3_M3VolumeMaterial_get_density(self.raw.as_ptr()),
10090                ),
10091            })
10092        }
10093    }
10094
10095    pub fn density_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10096        // SAFETY: as above; `&mut self` guarantees exclusivity.
10097        unsafe {
10098            crate::support::RefMut::new(AnimRefF32 {
10099                raw: core::ptr::NonNull::new_unchecked(
10100                    ffi::whiteout_m3_M3VolumeMaterial_get_density(self.raw.as_ptr()),
10101                ),
10102            })
10103        }
10104    }
10105
10106    /// Alpha test threshold
10107    pub fn alpha_threshold(&self) -> u32 {
10108        // SAFETY: plain scalar read through a live handle.
10109        unsafe { ffi::whiteout_m3_M3VolumeMaterial_get_alphaThreshold(self.raw.as_ptr()) }
10110    }
10111
10112    pub fn set_alpha_threshold(&mut self, value: u32) {
10113        // SAFETY: plain scalar write through a live handle.
10114        unsafe { ffi::whiteout_m3_M3VolumeMaterial_set_alphaThreshold(self.raw.as_ptr(), value) }
10115    }
10116}
10117
10118impl Default for VolumeMaterial {
10119    fn default() -> Self {
10120        Self::new()
10121    }
10122}
10123
10124/// HAI_ — Hair material (defunct, v0, 116 bytes)
10125///
10126/// Anisotropic hair rendering material with specular shift and AO. Always null in observed corpus data.
10127pub struct HairMaterial {
10128    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3HairMaterial>,
10129}
10130
10131impl Drop for HairMaterial {
10132    fn drop(&mut self) {
10133        // SAFETY: `raw` came from a native constructor and Drop runs once.
10134        unsafe { ffi::whiteout_m3_M3HairMaterial_delete(self.raw.as_ptr()) }
10135    }
10136}
10137
10138impl HairMaterial {
10139    /// # Safety
10140    /// `raw` must be a live handle this value takes ownership of.
10141    #[allow(dead_code)] // used by whichever methods return this type
10142    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3HairMaterial) -> Option<Self> {
10143        core::ptr::NonNull::new(raw).map(|raw| HairMaterial { raw })
10144    }
10145}
10146
10147// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10148// is deliberately NOT implemented — the C++ types make no documented
10149// guarantee about concurrent use, and claiming one we haven't verified
10150// would be unsound. See `@bind thread_safe` in the plan.
10151unsafe impl Send for HairMaterial {}
10152
10153impl core::fmt::Debug for HairMaterial {
10154    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10155        f.debug_struct("HairMaterial").finish_non_exhaustive()
10156    }
10157}
10158
10159impl HairMaterial {
10160    /// # Panics
10161    /// Panics if the native allocation fails.
10162    pub fn new() -> Self {
10163        // SAFETY: the native constructor returns a live handle; a null here
10164        // means the library is unusable.
10165        unsafe {
10166            let raw = ffi::whiteout_m3_M3HairMaterial_new();
10167            Self::from_raw(raw).expect("native HairMaterial allocation failed")
10168        }
10169    }
10170
10171    /// Material name (`Ref<CHAR>`)
10172    pub fn name(&self) -> String {
10173        // SAFETY: the native side hands over an owned CString.
10174        unsafe {
10175            crate::support::take_string(ffi::whiteout_m3_M3HairMaterial_get_name(self.raw.as_ptr()))
10176        }
10177    }
10178
10179    pub fn set_name(&mut self, value: &str) {
10180        let value = std::ffi::CString::new(value).unwrap_or_default();
10181        // SAFETY: the pointer outlives the call.
10182        unsafe { ffi::whiteout_m3_M3HairMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
10183    }
10184
10185    /// Primary specular shift
10186    pub fn shift_primary(&self) -> f32 {
10187        // SAFETY: plain scalar read through a live handle.
10188        unsafe { ffi::whiteout_m3_M3HairMaterial_get_shiftPrimary(self.raw.as_ptr()) }
10189    }
10190
10191    pub fn set_shift_primary(&mut self, value: f32) {
10192        // SAFETY: plain scalar write through a live handle.
10193        unsafe { ffi::whiteout_m3_M3HairMaterial_set_shiftPrimary(self.raw.as_ptr(), value) }
10194    }
10195
10196    /// Secondary specular shift
10197    pub fn shift_secondary(&self) -> f32 {
10198        // SAFETY: plain scalar read through a live handle.
10199        unsafe { ffi::whiteout_m3_M3HairMaterial_get_shiftSecondary(self.raw.as_ptr()) }
10200    }
10201
10202    pub fn set_shift_secondary(&mut self, value: f32) {
10203        // SAFETY: plain scalar write through a live handle.
10204        unsafe { ffi::whiteout_m3_M3HairMaterial_set_shiftSecondary(self.raw.as_ptr(), value) }
10205    }
10206
10207    /// Animated diffuse tint
10208    /// Borrows the field in place — no copy, no allocation.
10209    pub fn color_diffuse(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
10210        // SAFETY: an interior pointer into `self`, valid for this
10211        // borrow and never freed by the `Ref`.
10212        unsafe {
10213            crate::support::Ref::new(AnimRefM3ColorBGRA {
10214                raw: core::ptr::NonNull::new_unchecked(
10215                    ffi::whiteout_m3_M3HairMaterial_get_colorDiffuse(self.raw.as_ptr()),
10216                ),
10217            })
10218        }
10219    }
10220
10221    pub fn color_diffuse_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
10222        // SAFETY: as above; `&mut self` guarantees exclusivity.
10223        unsafe {
10224            crate::support::RefMut::new(AnimRefM3ColorBGRA {
10225                raw: core::ptr::NonNull::new_unchecked(
10226                    ffi::whiteout_m3_M3HairMaterial_get_colorDiffuse(self.raw.as_ptr()),
10227                ),
10228            })
10229        }
10230    }
10231
10232    /// Animated specular tint
10233    /// Borrows the field in place — no copy, no allocation.
10234    pub fn color_spec(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
10235        // SAFETY: an interior pointer into `self`, valid for this
10236        // borrow and never freed by the `Ref`.
10237        unsafe {
10238            crate::support::Ref::new(AnimRefM3ColorBGRA {
10239                raw: core::ptr::NonNull::new_unchecked(
10240                    ffi::whiteout_m3_M3HairMaterial_get_colorSpec(self.raw.as_ptr()),
10241                ),
10242            })
10243        }
10244    }
10245
10246    pub fn color_spec_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
10247        // SAFETY: as above; `&mut self` guarantees exclusivity.
10248        unsafe {
10249            crate::support::RefMut::new(AnimRefM3ColorBGRA {
10250                raw: core::ptr::NonNull::new_unchecked(
10251                    ffi::whiteout_m3_M3HairMaterial_get_colorSpec(self.raw.as_ptr()),
10252                ),
10253            })
10254        }
10255    }
10256
10257    /// Primary specular exponent
10258    pub fn spec_exponent_0(&self) -> f32 {
10259        // SAFETY: plain scalar read through a live handle.
10260        unsafe { ffi::whiteout_m3_M3HairMaterial_get_specExponent0(self.raw.as_ptr()) }
10261    }
10262
10263    pub fn set_spec_exponent_0(&mut self, value: f32) {
10264        // SAFETY: plain scalar write through a live handle.
10265        unsafe { ffi::whiteout_m3_M3HairMaterial_set_specExponent0(self.raw.as_ptr(), value) }
10266    }
10267
10268    /// Secondary specular exponent
10269    pub fn spec_exponent_1(&self) -> f32 {
10270        // SAFETY: plain scalar read through a live handle.
10271        unsafe { ffi::whiteout_m3_M3HairMaterial_get_specExponent1(self.raw.as_ptr()) }
10272    }
10273
10274    pub fn set_spec_exponent_1(&mut self, value: f32) {
10275        // SAFETY: plain scalar write through a live handle.
10276        unsafe { ffi::whiteout_m3_M3HairMaterial_set_specExponent1(self.raw.as_ptr(), value) }
10277    }
10278}
10279
10280impl Default for HairMaterial {
10281    fn default() -> Self {
10282        Self::new()
10283    }
10284}
10285
10286/// VON_ — Volume noise material (v0, 268 bytes)
10287///
10288/// Volumetric noise-based rendering material with animated density, falloff, scroll rate, position, scale, and rotation. Used for gas/smoke/cloud effects.
10289pub struct VolumeNoiseMaterial {
10290    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3VolumeNoiseMaterial>,
10291}
10292
10293impl Drop for VolumeNoiseMaterial {
10294    fn drop(&mut self) {
10295        // SAFETY: `raw` came from a native constructor and Drop runs once.
10296        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_delete(self.raw.as_ptr()) }
10297    }
10298}
10299
10300impl VolumeNoiseMaterial {
10301    /// # Safety
10302    /// `raw` must be a live handle this value takes ownership of.
10303    #[allow(dead_code)] // used by whichever methods return this type
10304    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3VolumeNoiseMaterial) -> Option<Self> {
10305        core::ptr::NonNull::new(raw).map(|raw| VolumeNoiseMaterial { raw })
10306    }
10307}
10308
10309// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10310// is deliberately NOT implemented — the C++ types make no documented
10311// guarantee about concurrent use, and claiming one we haven't verified
10312// would be unsound. See `@bind thread_safe` in the plan.
10313unsafe impl Send for VolumeNoiseMaterial {}
10314
10315impl core::fmt::Debug for VolumeNoiseMaterial {
10316    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10317        f.debug_struct("VolumeNoiseMaterial")
10318            .finish_non_exhaustive()
10319    }
10320}
10321
10322impl VolumeNoiseMaterial {
10323    /// # Panics
10324    /// Panics if the native allocation fails.
10325    pub fn new() -> Self {
10326        // SAFETY: the native constructor returns a live handle; a null here
10327        // means the library is unusable.
10328        unsafe {
10329            let raw = ffi::whiteout_m3_M3VolumeNoiseMaterial_new();
10330            Self::from_raw(raw).expect("native VolumeNoiseMaterial allocation failed")
10331        }
10332    }
10333
10334    /// Material name (`Ref<CHAR>`)
10335    pub fn name(&self) -> String {
10336        // SAFETY: the native side hands over an owned CString.
10337        unsafe {
10338            crate::support::take_string(ffi::whiteout_m3_M3VolumeNoiseMaterial_get_name(
10339                self.raw.as_ptr(),
10340            ))
10341        }
10342    }
10343
10344    pub fn set_name(&mut self, value: &str) {
10345        let value = std::ffi::CString::new(value).unwrap_or_default();
10346        // SAFETY: the pointer outlives the call.
10347        unsafe {
10348            ffi::whiteout_m3_M3VolumeNoiseMaterial_set_name(self.raw.as_ptr(), value.as_ptr())
10349        }
10350    }
10351
10352    /// Density falloff type
10353    pub fn falloff_type(&self) -> VolumeFalloffType {
10354        // SAFETY: scalar read; the discriminant is validated below.
10355        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_get_falloffType(self.raw.as_ptr()) }
10356            .try_into()
10357            .expect("unknown enum discriminant from the native library")
10358    }
10359
10360    pub fn set_falloff_type(&mut self, value: VolumeFalloffType) {
10361        // SAFETY: scalar write through a live handle.
10362        unsafe {
10363            ffi::whiteout_m3_M3VolumeNoiseMaterial_set_falloffType(self.raw.as_ptr(), value as i32)
10364        }
10365    }
10366
10367    /// Camera position mode (inside/outside)
10368    pub fn draw_transparency(&self) -> VolumeNoiseCameraMode {
10369        // SAFETY: scalar read; the discriminant is validated below.
10370        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_get_drawTransparency(self.raw.as_ptr()) }
10371            .try_into()
10372            .expect("unknown enum discriminant from the native library")
10373    }
10374
10375    pub fn set_draw_transparency(&mut self, value: VolumeNoiseCameraMode) {
10376        // SAFETY: scalar write through a live handle.
10377        unsafe {
10378            ffi::whiteout_m3_M3VolumeNoiseMaterial_set_drawTransparency(
10379                self.raw.as_ptr(),
10380                value as i32,
10381            )
10382        }
10383    }
10384
10385    /// Animated density
10386    /// Borrows the field in place — no copy, no allocation.
10387    pub fn density(&self) -> crate::support::Ref<'_, AnimRefF32> {
10388        // SAFETY: an interior pointer into `self`, valid for this
10389        // borrow and never freed by the `Ref`.
10390        unsafe {
10391            crate::support::Ref::new(AnimRefF32 {
10392                raw: core::ptr::NonNull::new_unchecked(
10393                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_density(self.raw.as_ptr()),
10394                ),
10395            })
10396        }
10397    }
10398
10399    pub fn density_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10400        // SAFETY: as above; `&mut self` guarantees exclusivity.
10401        unsafe {
10402            crate::support::RefMut::new(AnimRefF32 {
10403                raw: core::ptr::NonNull::new_unchecked(
10404                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_density(self.raw.as_ptr()),
10405                ),
10406            })
10407        }
10408    }
10409
10410    /// Animated near-plane clip
10411    /// Borrows the field in place — no copy, no allocation.
10412    pub fn near_plane(&self) -> crate::support::Ref<'_, AnimRefF32> {
10413        // SAFETY: an interior pointer into `self`, valid for this
10414        // borrow and never freed by the `Ref`.
10415        unsafe {
10416            crate::support::Ref::new(AnimRefF32 {
10417                raw: core::ptr::NonNull::new_unchecked(
10418                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_nearPlane(self.raw.as_ptr()),
10419                ),
10420            })
10421        }
10422    }
10423
10424    pub fn near_plane_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10425        // SAFETY: as above; `&mut self` guarantees exclusivity.
10426        unsafe {
10427            crate::support::RefMut::new(AnimRefF32 {
10428                raw: core::ptr::NonNull::new_unchecked(
10429                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_nearPlane(self.raw.as_ptr()),
10430                ),
10431            })
10432        }
10433    }
10434
10435    /// Animated falloff distance
10436    /// Borrows the field in place — no copy, no allocation.
10437    pub fn falloff(&self) -> crate::support::Ref<'_, AnimRefF32> {
10438        // SAFETY: an interior pointer into `self`, valid for this
10439        // borrow and never freed by the `Ref`.
10440        unsafe {
10441            crate::support::Ref::new(AnimRefF32 {
10442                raw: core::ptr::NonNull::new_unchecked(
10443                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_falloff(self.raw.as_ptr()),
10444                ),
10445            })
10446        }
10447    }
10448
10449    pub fn falloff_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10450        // SAFETY: as above; `&mut self` guarantees exclusivity.
10451        unsafe {
10452            crate::support::RefMut::new(AnimRefF32 {
10453                raw: core::ptr::NonNull::new_unchecked(
10454                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_falloff(self.raw.as_ptr()),
10455                ),
10456            })
10457        }
10458    }
10459
10460    /// Animated noise scroll rate
10461    /// Borrows the field in place — no copy, no allocation.
10462    pub fn scroll_rate(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
10463        // SAFETY: an interior pointer into `self`, valid for this
10464        // borrow and never freed by the `Ref`.
10465        unsafe {
10466            crate::support::Ref::new(AnimRefVector3f {
10467                raw: core::ptr::NonNull::new_unchecked(
10468                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_scrollRate(self.raw.as_ptr()),
10469                ),
10470            })
10471        }
10472    }
10473
10474    pub fn scroll_rate_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
10475        // SAFETY: as above; `&mut self` guarantees exclusivity.
10476        unsafe {
10477            crate::support::RefMut::new(AnimRefVector3f {
10478                raw: core::ptr::NonNull::new_unchecked(
10479                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_scrollRate(self.raw.as_ptr()),
10480                ),
10481            })
10482        }
10483    }
10484
10485    /// Animated volume position
10486    /// Borrows the field in place — no copy, no allocation.
10487    pub fn position(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
10488        // SAFETY: an interior pointer into `self`, valid for this
10489        // borrow and never freed by the `Ref`.
10490        unsafe {
10491            crate::support::Ref::new(AnimRefVector3f {
10492                raw: core::ptr::NonNull::new_unchecked(
10493                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_position(self.raw.as_ptr()),
10494                ),
10495            })
10496        }
10497    }
10498
10499    pub fn position_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
10500        // SAFETY: as above; `&mut self` guarantees exclusivity.
10501        unsafe {
10502            crate::support::RefMut::new(AnimRefVector3f {
10503                raw: core::ptr::NonNull::new_unchecked(
10504                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_position(self.raw.as_ptr()),
10505                ),
10506            })
10507        }
10508    }
10509
10510    /// Animated volume scale
10511    /// Borrows the field in place — no copy, no allocation.
10512    pub fn scale(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
10513        // SAFETY: an interior pointer into `self`, valid for this
10514        // borrow and never freed by the `Ref`.
10515        unsafe {
10516            crate::support::Ref::new(AnimRefVector3f {
10517                raw: core::ptr::NonNull::new_unchecked(
10518                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_scale(self.raw.as_ptr()),
10519                ),
10520            })
10521        }
10522    }
10523
10524    pub fn scale_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
10525        // SAFETY: as above; `&mut self` guarantees exclusivity.
10526        unsafe {
10527            crate::support::RefMut::new(AnimRefVector3f {
10528                raw: core::ptr::NonNull::new_unchecked(
10529                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_scale(self.raw.as_ptr()),
10530                ),
10531            })
10532        }
10533    }
10534
10535    /// Animated volume rotation
10536    /// Borrows the field in place — no copy, no allocation.
10537    pub fn rotation(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
10538        // SAFETY: an interior pointer into `self`, valid for this
10539        // borrow and never freed by the `Ref`.
10540        unsafe {
10541            crate::support::Ref::new(AnimRefVector3f {
10542                raw: core::ptr::NonNull::new_unchecked(
10543                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_rotation(self.raw.as_ptr()),
10544                ),
10545            })
10546        }
10547    }
10548
10549    pub fn rotation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
10550        // SAFETY: as above; `&mut self` guarantees exclusivity.
10551        unsafe {
10552            crate::support::RefMut::new(AnimRefVector3f {
10553                raw: core::ptr::NonNull::new_unchecked(
10554                    ffi::whiteout_m3_M3VolumeNoiseMaterial_get_rotation(self.raw.as_ptr()),
10555                ),
10556            })
10557        }
10558    }
10559
10560    /// Alpha test threshold
10561    pub fn alpha_threshold(&self) -> u32 {
10562        // SAFETY: plain scalar read through a live handle.
10563        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_get_alphaThreshold(self.raw.as_ptr()) }
10564    }
10565
10566    pub fn set_alpha_threshold(&mut self, value: u32) {
10567        // SAFETY: plain scalar write through a live handle.
10568        unsafe {
10569            ffi::whiteout_m3_M3VolumeNoiseMaterial_set_alphaThreshold(self.raw.as_ptr(), value)
10570        }
10571    }
10572
10573    /// Volume noise material flags
10574    pub fn flags(&self) -> VolumeNoiseMaterialFlag {
10575        // SAFETY: scalar read; the discriminant is validated below.
10576        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_get_flags(self.raw.as_ptr()) }
10577            .try_into()
10578            .expect("unknown enum discriminant from the native library")
10579    }
10580
10581    pub fn set_flags(&mut self, value: VolumeNoiseMaterialFlag) {
10582        // SAFETY: scalar write through a live handle.
10583        unsafe { ffi::whiteout_m3_M3VolumeNoiseMaterial_set_flags(self.raw.as_ptr(), value as i32) }
10584    }
10585}
10586
10587impl Default for VolumeNoiseMaterial {
10588    fn default() -> Self {
10589        Self::new()
10590    }
10591}
10592
10593/// CREP — Creep material (v0–v1, 28 bytes)
10594///
10595/// Material for Zerg creep rendering with a mask map and creep-low parameter.
10596pub struct CreepMaterial {
10597    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3CreepMaterial>,
10598}
10599
10600impl Drop for CreepMaterial {
10601    fn drop(&mut self) {
10602        // SAFETY: `raw` came from a native constructor and Drop runs once.
10603        unsafe { ffi::whiteout_m3_M3CreepMaterial_delete(self.raw.as_ptr()) }
10604    }
10605}
10606
10607impl CreepMaterial {
10608    /// # Safety
10609    /// `raw` must be a live handle this value takes ownership of.
10610    #[allow(dead_code)] // used by whichever methods return this type
10611    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3CreepMaterial) -> Option<Self> {
10612        core::ptr::NonNull::new(raw).map(|raw| CreepMaterial { raw })
10613    }
10614}
10615
10616// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10617// is deliberately NOT implemented — the C++ types make no documented
10618// guarantee about concurrent use, and claiming one we haven't verified
10619// would be unsound. See `@bind thread_safe` in the plan.
10620unsafe impl Send for CreepMaterial {}
10621
10622impl core::fmt::Debug for CreepMaterial {
10623    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10624        f.debug_struct("CreepMaterial").finish_non_exhaustive()
10625    }
10626}
10627
10628impl CreepMaterial {
10629    /// # Panics
10630    /// Panics if the native allocation fails.
10631    pub fn new() -> Self {
10632        // SAFETY: the native constructor returns a live handle; a null here
10633        // means the library is unusable.
10634        unsafe {
10635            let raw = ffi::whiteout_m3_M3CreepMaterial_new();
10636            Self::from_raw(raw).expect("native CreepMaterial allocation failed")
10637        }
10638    }
10639
10640    /// Material name (`Ref<CHAR>`)
10641    pub fn name(&self) -> String {
10642        // SAFETY: the native side hands over an owned CString.
10643        unsafe {
10644            crate::support::take_string(ffi::whiteout_m3_M3CreepMaterial_get_name(
10645                self.raw.as_ptr(),
10646            ))
10647        }
10648    }
10649
10650    pub fn set_name(&mut self, value: &str) {
10651        let value = std::ffi::CString::new(value).unwrap_or_default();
10652        // SAFETY: the pointer outlives the call.
10653        unsafe { ffi::whiteout_m3_M3CreepMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
10654    }
10655
10656    /// Creep low parameter
10657    pub fn creep_low(&self) -> u32 {
10658        // SAFETY: plain scalar read through a live handle.
10659        unsafe { ffi::whiteout_m3_M3CreepMaterial_get_creepLow(self.raw.as_ptr()) }
10660    }
10661
10662    pub fn set_creep_low(&mut self, value: u32) {
10663        // SAFETY: plain scalar write through a live handle.
10664        unsafe { ffi::whiteout_m3_M3CreepMaterial_set_creepLow(self.raw.as_ptr(), value) }
10665    }
10666}
10667
10668impl Default for CreepMaterial {
10669    fn default() -> Self {
10670        Self::new()
10671    }
10672}
10673
10674/// STBM — Splat terrain bake material (v0, 48 bytes)
10675///
10676/// Material for baked terrain splat rendering with diffuse, normal, and specular texture layers.
10677pub struct STBMaterial {
10678    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3STBMaterial>,
10679}
10680
10681impl Drop for STBMaterial {
10682    fn drop(&mut self) {
10683        // SAFETY: `raw` came from a native constructor and Drop runs once.
10684        unsafe { ffi::whiteout_m3_M3STBMaterial_delete(self.raw.as_ptr()) }
10685    }
10686}
10687
10688impl STBMaterial {
10689    /// # Safety
10690    /// `raw` must be a live handle this value takes ownership of.
10691    #[allow(dead_code)] // used by whichever methods return this type
10692    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3STBMaterial) -> Option<Self> {
10693        core::ptr::NonNull::new(raw).map(|raw| STBMaterial { raw })
10694    }
10695}
10696
10697// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10698// is deliberately NOT implemented — the C++ types make no documented
10699// guarantee about concurrent use, and claiming one we haven't verified
10700// would be unsound. See `@bind thread_safe` in the plan.
10701unsafe impl Send for STBMaterial {}
10702
10703impl core::fmt::Debug for STBMaterial {
10704    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10705        f.debug_struct("STBMaterial").finish_non_exhaustive()
10706    }
10707}
10708
10709impl STBMaterial {
10710    /// # Panics
10711    /// Panics if the native allocation fails.
10712    pub fn new() -> Self {
10713        // SAFETY: the native constructor returns a live handle; a null here
10714        // means the library is unusable.
10715        unsafe {
10716            let raw = ffi::whiteout_m3_M3STBMaterial_new();
10717            Self::from_raw(raw).expect("native STBMaterial allocation failed")
10718        }
10719    }
10720
10721    /// Material name (`Ref<CHAR>`)
10722    pub fn name(&self) -> String {
10723        // SAFETY: the native side hands over an owned CString.
10724        unsafe {
10725            crate::support::take_string(ffi::whiteout_m3_M3STBMaterial_get_name(self.raw.as_ptr()))
10726        }
10727    }
10728
10729    pub fn set_name(&mut self, value: &str) {
10730        let value = std::ffi::CString::new(value).unwrap_or_default();
10731        // SAFETY: the pointer outlives the call.
10732        unsafe { ffi::whiteout_m3_M3STBMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
10733    }
10734}
10735
10736impl Default for STBMaterial {
10737    fn default() -> Self {
10738        Self::new()
10739    }
10740}
10741
10742/// REF_ — Reflection material (v0–v3, 84–160 bytes)
10743///
10744/// Planar or cube-map reflection material with animated reflection/displacement strength, blur, and multiple texture layers.
10745pub struct ReflectionMaterial {
10746    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ReflectionMaterial>,
10747}
10748
10749impl Drop for ReflectionMaterial {
10750    fn drop(&mut self) {
10751        // SAFETY: `raw` came from a native constructor and Drop runs once.
10752        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_delete(self.raw.as_ptr()) }
10753    }
10754}
10755
10756impl ReflectionMaterial {
10757    /// # Safety
10758    /// `raw` must be a live handle this value takes ownership of.
10759    #[allow(dead_code)] // used by whichever methods return this type
10760    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ReflectionMaterial) -> Option<Self> {
10761        core::ptr::NonNull::new(raw).map(|raw| ReflectionMaterial { raw })
10762    }
10763}
10764
10765// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
10766// is deliberately NOT implemented — the C++ types make no documented
10767// guarantee about concurrent use, and claiming one we haven't verified
10768// would be unsound. See `@bind thread_safe` in the plan.
10769unsafe impl Send for ReflectionMaterial {}
10770
10771impl core::fmt::Debug for ReflectionMaterial {
10772    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10773        f.debug_struct("ReflectionMaterial").finish_non_exhaustive()
10774    }
10775}
10776
10777impl ReflectionMaterial {
10778    /// # Panics
10779    /// Panics if the native allocation fails.
10780    pub fn new() -> Self {
10781        // SAFETY: the native constructor returns a live handle; a null here
10782        // means the library is unusable.
10783        unsafe {
10784            let raw = ffi::whiteout_m3_M3ReflectionMaterial_new();
10785            Self::from_raw(raw).expect("native ReflectionMaterial allocation failed")
10786        }
10787    }
10788
10789    /// Material name (`Ref<CHAR>`)
10790    pub fn name(&self) -> String {
10791        // SAFETY: the native side hands over an owned CString.
10792        unsafe {
10793            crate::support::take_string(ffi::whiteout_m3_M3ReflectionMaterial_get_name(
10794                self.raw.as_ptr(),
10795            ))
10796        }
10797    }
10798
10799    pub fn set_name(&mut self, value: &str) {
10800        let value = std::ffi::CString::new(value).unwrap_or_default();
10801        // SAFETY: the pointer outlives the call.
10802        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_set_name(self.raw.as_ptr(), value.as_ptr()) }
10803    }
10804
10805    /// Unknown field
10806    pub fn unknown(&self) -> u32 {
10807        // SAFETY: plain scalar read through a live handle.
10808        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_get_unknown(self.raw.as_ptr()) }
10809    }
10810
10811    pub fn set_unknown(&mut self, value: u32) {
10812        // SAFETY: plain scalar write through a live handle.
10813        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_set_unknown(self.raw.as_ptr(), value) }
10814    }
10815
10816    /// Animated reflection strength (v2+)
10817    /// Borrows the field in place — no copy, no allocation.
10818    pub fn reflection_strength(&self) -> crate::support::Ref<'_, AnimRefF32> {
10819        // SAFETY: an interior pointer into `self`, valid for this
10820        // borrow and never freed by the `Ref`.
10821        unsafe {
10822            crate::support::Ref::new(AnimRefF32 {
10823                raw: core::ptr::NonNull::new_unchecked(
10824                    ffi::whiteout_m3_M3ReflectionMaterial_get_reflectionStrength(self.raw.as_ptr()),
10825                ),
10826            })
10827        }
10828    }
10829
10830    pub fn reflection_strength_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10831        // SAFETY: as above; `&mut self` guarantees exclusivity.
10832        unsafe {
10833            crate::support::RefMut::new(AnimRefF32 {
10834                raw: core::ptr::NonNull::new_unchecked(
10835                    ffi::whiteout_m3_M3ReflectionMaterial_get_reflectionStrength(self.raw.as_ptr()),
10836                ),
10837            })
10838        }
10839    }
10840
10841    /// Animated displacement strength (v2+)
10842    /// Borrows the field in place — no copy, no allocation.
10843    pub fn displacement_strength(&self) -> crate::support::Ref<'_, AnimRefF32> {
10844        // SAFETY: an interior pointer into `self`, valid for this
10845        // borrow and never freed by the `Ref`.
10846        unsafe {
10847            crate::support::Ref::new(AnimRefF32 {
10848                raw: core::ptr::NonNull::new_unchecked(
10849                    ffi::whiteout_m3_M3ReflectionMaterial_get_displacementStrength(
10850                        self.raw.as_ptr(),
10851                    ),
10852                ),
10853            })
10854        }
10855    }
10856
10857    pub fn displacement_strength_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10858        // SAFETY: as above; `&mut self` guarantees exclusivity.
10859        unsafe {
10860            crate::support::RefMut::new(AnimRefF32 {
10861                raw: core::ptr::NonNull::new_unchecked(
10862                    ffi::whiteout_m3_M3ReflectionMaterial_get_displacementStrength(
10863                        self.raw.as_ptr(),
10864                    ),
10865                ),
10866            })
10867        }
10868    }
10869
10870    /// Animated reflection offset (v2+)
10871    /// Borrows the field in place — no copy, no allocation.
10872    pub fn reflection_offset(&self) -> crate::support::Ref<'_, AnimRefF32> {
10873        // SAFETY: an interior pointer into `self`, valid for this
10874        // borrow and never freed by the `Ref`.
10875        unsafe {
10876            crate::support::Ref::new(AnimRefF32 {
10877                raw: core::ptr::NonNull::new_unchecked(
10878                    ffi::whiteout_m3_M3ReflectionMaterial_get_reflectionOffset(self.raw.as_ptr()),
10879                ),
10880            })
10881        }
10882    }
10883
10884    pub fn reflection_offset_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10885        // SAFETY: as above; `&mut self` guarantees exclusivity.
10886        unsafe {
10887            crate::support::RefMut::new(AnimRefF32 {
10888                raw: core::ptr::NonNull::new_unchecked(
10889                    ffi::whiteout_m3_M3ReflectionMaterial_get_reflectionOffset(self.raw.as_ptr()),
10890                ),
10891            })
10892        }
10893    }
10894
10895    /// Animated blur angle (v2+)
10896    /// Borrows the field in place — no copy, no allocation.
10897    pub fn blur_angle(&self) -> crate::support::Ref<'_, AnimRefF32> {
10898        // SAFETY: an interior pointer into `self`, valid for this
10899        // borrow and never freed by the `Ref`.
10900        unsafe {
10901            crate::support::Ref::new(AnimRefF32 {
10902                raw: core::ptr::NonNull::new_unchecked(
10903                    ffi::whiteout_m3_M3ReflectionMaterial_get_blurAngle(self.raw.as_ptr()),
10904                ),
10905            })
10906        }
10907    }
10908
10909    pub fn blur_angle_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10910        // SAFETY: as above; `&mut self` guarantees exclusivity.
10911        unsafe {
10912            crate::support::RefMut::new(AnimRefF32 {
10913                raw: core::ptr::NonNull::new_unchecked(
10914                    ffi::whiteout_m3_M3ReflectionMaterial_get_blurAngle(self.raw.as_ptr()),
10915                ),
10916            })
10917        }
10918    }
10919
10920    /// Animated max blur distance (v2+)
10921    /// Borrows the field in place — no copy, no allocation.
10922    pub fn blur_distance_max(&self) -> crate::support::Ref<'_, AnimRefF32> {
10923        // SAFETY: an interior pointer into `self`, valid for this
10924        // borrow and never freed by the `Ref`.
10925        unsafe {
10926            crate::support::Ref::new(AnimRefF32 {
10927                raw: core::ptr::NonNull::new_unchecked(
10928                    ffi::whiteout_m3_M3ReflectionMaterial_get_blurDistanceMax(self.raw.as_ptr()),
10929                ),
10930            })
10931        }
10932    }
10933
10934    pub fn blur_distance_max_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
10935        // SAFETY: as above; `&mut self` guarantees exclusivity.
10936        unsafe {
10937            crate::support::RefMut::new(AnimRefF32 {
10938                raw: core::ptr::NonNull::new_unchecked(
10939                    ffi::whiteout_m3_M3ReflectionMaterial_get_blurDistanceMax(self.raw.as_ptr()),
10940                ),
10941            })
10942        }
10943    }
10944
10945    /// Reflection flags (v2+)
10946    pub fn flags(&self) -> ReflectionMaterialFlag {
10947        // SAFETY: scalar read; a flag set accepts any bits.
10948        ReflectionMaterialFlag(unsafe {
10949            ffi::whiteout_m3_M3ReflectionMaterial_get_flags(self.raw.as_ptr())
10950        })
10951    }
10952
10953    pub fn set_flags(&mut self, value: ReflectionMaterialFlag) {
10954        // SAFETY: scalar write through a live handle.
10955        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_set_flags(self.raw.as_ptr(), value.0) }
10956    }
10957
10958    /// Index of the DataDrivenMaterial this was converted into, 0xFFFFFFFF if none (v3+). Written by the Heroes load-time conversion pass, not a material parameter; meaningless in a model that carries no MADD chunk. v3 exists only to hold it. Defaulted because an invented REF_ has no link to name, and a v3 record that says anything else points the Heroes loader at a MADD index.
10959    pub fn unknown_2(&self) -> u32 {
10960        // SAFETY: plain scalar read through a live handle.
10961        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_get_unknown2(self.raw.as_ptr()) }
10962    }
10963
10964    pub fn set_unknown_2(&mut self, value: u32) {
10965        // SAFETY: plain scalar write through a live handle.
10966        unsafe { ffi::whiteout_m3_M3ReflectionMaterial_set_unknown2(self.raw.as_ptr(), value) }
10967    }
10968}
10969
10970impl Default for ReflectionMaterial {
10971    fn default() -> Self {
10972        Self::new()
10973    }
10974}
10975
10976/// LFSB — Sub-flare element (v0–v2, 56 bytes)
10977///
10978/// A single flare element within a LensFlare material, with position, size, scale, fade, color, and offset parameters.
10979pub struct SubFlare {
10980    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3SubFlare>,
10981}
10982
10983impl Drop for SubFlare {
10984    fn drop(&mut self) {
10985        // SAFETY: `raw` came from a native constructor and Drop runs once.
10986        unsafe { ffi::whiteout_m3_M3SubFlare_delete(self.raw.as_ptr()) }
10987    }
10988}
10989
10990impl SubFlare {
10991    /// # Safety
10992    /// `raw` must be a live handle this value takes ownership of.
10993    #[allow(dead_code)] // used by whichever methods return this type
10994    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3SubFlare) -> Option<Self> {
10995        core::ptr::NonNull::new(raw).map(|raw| SubFlare { raw })
10996    }
10997}
10998
10999// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11000// is deliberately NOT implemented — the C++ types make no documented
11001// guarantee about concurrent use, and claiming one we haven't verified
11002// would be unsound. See `@bind thread_safe` in the plan.
11003unsafe impl Send for SubFlare {}
11004
11005impl core::fmt::Debug for SubFlare {
11006    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11007        f.debug_struct("SubFlare").finish_non_exhaustive()
11008    }
11009}
11010
11011impl SubFlare {
11012    /// # Panics
11013    /// Panics if the native allocation fails.
11014    pub fn new() -> Self {
11015        // SAFETY: the native constructor returns a live handle; a null here
11016        // means the library is unusable.
11017        unsafe {
11018            let raw = ffi::whiteout_m3_M3SubFlare_new();
11019            Self::from_raw(raw).expect("native SubFlare allocation failed")
11020        }
11021    }
11022
11023    /// Flare element index
11024    pub fn index(&self) -> u32 {
11025        // SAFETY: plain scalar read through a live handle.
11026        unsafe { ffi::whiteout_m3_M3SubFlare_get_index(self.raw.as_ptr()) }
11027    }
11028
11029    pub fn set_index(&mut self, value: u32) {
11030        // SAFETY: plain scalar write through a live handle.
11031        unsafe { ffi::whiteout_m3_M3SubFlare_set_index(self.raw.as_ptr(), value) }
11032    }
11033
11034    /// Position along the flare axis (0–1)
11035    pub fn position(&self) -> f32 {
11036        // SAFETY: plain scalar read through a live handle.
11037        unsafe { ffi::whiteout_m3_M3SubFlare_get_position(self.raw.as_ptr()) }
11038    }
11039
11040    pub fn set_position(&mut self, value: f32) {
11041        // SAFETY: plain scalar write through a live handle.
11042        unsafe { ffi::whiteout_m3_M3SubFlare_set_position(self.raw.as_ptr(), value) }
11043    }
11044
11045    /// Base size (width, height)
11046    pub fn size_xy(&self) -> crate::math::Vector2f {
11047        // SAFETY: the getter returns an interior pointer to a
11048        // layout-identical POD; we copy it out immediately.
11049        unsafe {
11050            *(ffi::whiteout_m3_M3SubFlare_get_sizeXY(self.raw.as_ptr())
11051                as *const crate::math::Vector2f)
11052        }
11053    }
11054
11055    pub fn set_size_xy(&mut self, value: crate::math::Vector2f) {
11056        // SAFETY: as above, in the other direction.
11057        unsafe {
11058            ffi::whiteout_m3_M3SubFlare_set_sizeXY(
11059                self.raw.as_ptr(),
11060                &value as *const crate::math::Vector2f as *const _,
11061            )
11062        }
11063    }
11064
11065    /// Scale multiplier (width, height)
11066    pub fn scale_xy(&self) -> crate::math::Vector2f {
11067        // SAFETY: the getter returns an interior pointer to a
11068        // layout-identical POD; we copy it out immediately.
11069        unsafe {
11070            *(ffi::whiteout_m3_M3SubFlare_get_scaleXY(self.raw.as_ptr())
11071                as *const crate::math::Vector2f)
11072        }
11073    }
11074
11075    pub fn set_scale_xy(&mut self, value: crate::math::Vector2f) {
11076        // SAFETY: as above, in the other direction.
11077        unsafe {
11078            ffi::whiteout_m3_M3SubFlare_set_scaleXY(
11079                self.raw.as_ptr(),
11080                &value as *const crate::math::Vector2f as *const _,
11081            )
11082        }
11083    }
11084
11085    /// Fade-in range (start, end)
11086    pub fn fade_in(&self) -> crate::math::Vector2f {
11087        // SAFETY: the getter returns an interior pointer to a
11088        // layout-identical POD; we copy it out immediately.
11089        unsafe {
11090            *(ffi::whiteout_m3_M3SubFlare_get_fadeIn(self.raw.as_ptr())
11091                as *const crate::math::Vector2f)
11092        }
11093    }
11094
11095    pub fn set_fade_in(&mut self, value: crate::math::Vector2f) {
11096        // SAFETY: as above, in the other direction.
11097        unsafe {
11098            ffi::whiteout_m3_M3SubFlare_set_fadeIn(
11099                self.raw.as_ptr(),
11100                &value as *const crate::math::Vector2f as *const _,
11101            )
11102        }
11103    }
11104
11105    /// Fade-out range (start, end)
11106    pub fn fade_out(&self) -> crate::math::Vector2f {
11107        // SAFETY: the getter returns an interior pointer to a
11108        // layout-identical POD; we copy it out immediately.
11109        unsafe {
11110            *(ffi::whiteout_m3_M3SubFlare_get_fadeOut(self.raw.as_ptr())
11111                as *const crate::math::Vector2f)
11112        }
11113    }
11114
11115    pub fn set_fade_out(&mut self, value: crate::math::Vector2f) {
11116        // SAFETY: as above, in the other direction.
11117        unsafe {
11118            ffi::whiteout_m3_M3SubFlare_set_fadeOut(
11119                self.raw.as_ptr(),
11120                &value as *const crate::math::Vector2f as *const _,
11121            )
11122        }
11123    }
11124
11125    /// Flare color and alpha
11126    /// Borrows the field in place — no copy, no allocation.
11127    pub fn color_alpha(&self) -> crate::support::Ref<'_, ColorBGRA> {
11128        // SAFETY: an interior pointer into `self`, valid for this
11129        // borrow and never freed by the `Ref`.
11130        unsafe {
11131            crate::support::Ref::new(ColorBGRA {
11132                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SubFlare_get_colorAlpha(
11133                    self.raw.as_ptr(),
11134                )),
11135            })
11136        }
11137    }
11138
11139    pub fn color_alpha_mut(&mut self) -> crate::support::RefMut<'_, ColorBGRA> {
11140        // SAFETY: as above; `&mut self` guarantees exclusivity.
11141        unsafe {
11142            crate::support::RefMut::new(ColorBGRA {
11143                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3SubFlare_get_colorAlpha(
11144                    self.raw.as_ptr(),
11145                )),
11146            })
11147        }
11148    }
11149
11150    /// Whether to face the flare center
11151    pub fn face_center(&self) -> u32 {
11152        // SAFETY: plain scalar read through a live handle.
11153        unsafe { ffi::whiteout_m3_M3SubFlare_get_faceCenter(self.raw.as_ptr()) }
11154    }
11155
11156    pub fn set_face_center(&mut self, value: u32) {
11157        // SAFETY: plain scalar write through a live handle.
11158        unsafe { ffi::whiteout_m3_M3SubFlare_set_faceCenter(self.raw.as_ptr(), value) }
11159    }
11160
11161    /// Offset from flare center
11162    pub fn offset(&self) -> crate::math::Vector2f {
11163        // SAFETY: the getter returns an interior pointer to a
11164        // layout-identical POD; we copy it out immediately.
11165        unsafe {
11166            *(ffi::whiteout_m3_M3SubFlare_get_offset(self.raw.as_ptr())
11167                as *const crate::math::Vector2f)
11168        }
11169    }
11170
11171    pub fn set_offset(&mut self, value: crate::math::Vector2f) {
11172        // SAFETY: as above, in the other direction.
11173        unsafe {
11174            ffi::whiteout_m3_M3SubFlare_set_offset(
11175                self.raw.as_ptr(),
11176                &value as *const crate::math::Vector2f as *const _,
11177            )
11178        }
11179    }
11180}
11181
11182impl Default for SubFlare {
11183    fn default() -> Self {
11184        Self::new()
11185    }
11186}
11187
11188/// LFLR — Lens flare material (v0–v3, 152 bytes)
11189///
11190/// Lens flare effect with animated intensity, color, HDR, size, sub-flare elements, and flipbook texture grid parameters.
11191pub struct LensFlare {
11192    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3LensFlare>,
11193}
11194
11195impl Drop for LensFlare {
11196    fn drop(&mut self) {
11197        // SAFETY: `raw` came from a native constructor and Drop runs once.
11198        unsafe { ffi::whiteout_m3_M3LensFlare_delete(self.raw.as_ptr()) }
11199    }
11200}
11201
11202impl LensFlare {
11203    /// # Safety
11204    /// `raw` must be a live handle this value takes ownership of.
11205    #[allow(dead_code)] // used by whichever methods return this type
11206    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3LensFlare) -> Option<Self> {
11207        core::ptr::NonNull::new(raw).map(|raw| LensFlare { raw })
11208    }
11209}
11210
11211// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11212// is deliberately NOT implemented — the C++ types make no documented
11213// guarantee about concurrent use, and claiming one we haven't verified
11214// would be unsound. See `@bind thread_safe` in the plan.
11215unsafe impl Send for LensFlare {}
11216
11217impl core::fmt::Debug for LensFlare {
11218    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11219        f.debug_struct("LensFlare").finish_non_exhaustive()
11220    }
11221}
11222
11223impl LensFlare {
11224    /// # Panics
11225    /// Panics if the native allocation fails.
11226    pub fn new() -> Self {
11227        // SAFETY: the native constructor returns a live handle; a null here
11228        // means the library is unusable.
11229        unsafe {
11230            let raw = ffi::whiteout_m3_M3LensFlare_new();
11231            Self::from_raw(raw).expect("native LensFlare allocation failed")
11232        }
11233    }
11234
11235    /// Flare name (`Ref<CHAR>`)
11236    pub fn name(&self) -> String {
11237        // SAFETY: the native side hands over an owned CString.
11238        unsafe {
11239            crate::support::take_string(ffi::whiteout_m3_M3LensFlare_get_name(self.raw.as_ptr()))
11240        }
11241    }
11242
11243    pub fn set_name(&mut self, value: &str) {
11244        let value = std::ffi::CString::new(value).unwrap_or_default();
11245        // SAFETY: the pointer outlives the call.
11246        unsafe { ffi::whiteout_m3_M3LensFlare_set_name(self.raw.as_ptr(), value.as_ptr()) }
11247    }
11248
11249    /// Sub-flare elements (LFSB)
11250    pub fn sub_flares_len(&self) -> usize {
11251        // SAFETY: scalar read through a live handle.
11252        unsafe { ffi::whiteout_m3_M3LensFlare_get_subFlares_count(self.raw.as_ptr()) }
11253    }
11254
11255    /// Borrows element `index` in place. `None` when out of range.
11256    pub fn sub_flares(&self, index: usize) -> Option<crate::support::Ref<'_, SubFlare>> {
11257        if index >= self.sub_flares_len() {
11258            return None;
11259        }
11260        // SAFETY: index checked above; the pointer is interior to `self`.
11261        unsafe {
11262            Some(crate::support::Ref::new(SubFlare {
11263                raw: core::ptr::NonNull::new_unchecked(
11264                    ffi::whiteout_m3_M3LensFlare_get_subFlares_at(self.raw.as_ptr(), index),
11265                ),
11266            }))
11267        }
11268    }
11269
11270    pub fn sub_flares_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, SubFlare>> {
11271        if index >= self.sub_flares_len() {
11272            return None;
11273        }
11274        // SAFETY: as above; `&mut self` guarantees exclusivity.
11275        unsafe {
11276            Some(crate::support::RefMut::new(SubFlare {
11277                raw: core::ptr::NonNull::new_unchecked(
11278                    ffi::whiteout_m3_M3LensFlare_get_subFlares_at(self.raw.as_ptr(), index),
11279                ),
11280            }))
11281        }
11282    }
11283
11284    /// Iterate the elements, borrowing each in turn.
11285    pub fn sub_flares_iter(
11286        &self,
11287    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SubFlare>> {
11288        (0..self.sub_flares_len()).map(move |i| self.sub_flares(i).expect("index below len"))
11289    }
11290
11291    pub fn resize_sub_flares(&mut self, count: usize) {
11292        // SAFETY: exclusive access, so no borrow is outstanding.
11293        unsafe { ffi::whiteout_m3_M3LensFlare_resize_subFlares(self.raw.as_ptr(), count) }
11294    }
11295
11296    /// Flipbook grid columns
11297    pub fn columns(&self) -> u32 {
11298        // SAFETY: plain scalar read through a live handle.
11299        unsafe { ffi::whiteout_m3_M3LensFlare_get_columns(self.raw.as_ptr()) }
11300    }
11301
11302    pub fn set_columns(&mut self, value: u32) {
11303        // SAFETY: plain scalar write through a live handle.
11304        unsafe { ffi::whiteout_m3_M3LensFlare_set_columns(self.raw.as_ptr(), value) }
11305    }
11306
11307    /// Flipbook grid rows
11308    pub fn rows(&self) -> u32 {
11309        // SAFETY: plain scalar read through a live handle.
11310        unsafe { ffi::whiteout_m3_M3LensFlare_get_rows(self.raw.as_ptr()) }
11311    }
11312
11313    pub fn set_rows(&mut self, value: u32) {
11314        // SAFETY: plain scalar write through a live handle.
11315        unsafe { ffi::whiteout_m3_M3LensFlare_set_rows(self.raw.as_ptr(), value) }
11316    }
11317
11318    /// Distance fade start
11319    pub fn distance_fade(&self) -> f32 {
11320        // SAFETY: plain scalar read through a live handle.
11321        unsafe { ffi::whiteout_m3_M3LensFlare_get_distanceFade(self.raw.as_ptr()) }
11322    }
11323
11324    pub fn set_distance_fade(&mut self, value: f32) {
11325        // SAFETY: plain scalar write through a live handle.
11326        unsafe { ffi::whiteout_m3_M3LensFlare_set_distanceFade(self.raw.as_ptr(), value) }
11327    }
11328
11329    /// Library name (`Ref<CHAR>`)
11330    pub fn lib_name(&self) -> String {
11331        // SAFETY: the native side hands over an owned CString.
11332        unsafe {
11333            crate::support::take_string(ffi::whiteout_m3_M3LensFlare_get_libName(self.raw.as_ptr()))
11334        }
11335    }
11336
11337    pub fn set_lib_name(&mut self, value: &str) {
11338        let value = std::ffi::CString::new(value).unwrap_or_default();
11339        // SAFETY: the pointer outlives the call.
11340        unsafe { ffi::whiteout_m3_M3LensFlare_set_libName(self.raw.as_ptr(), value.as_ptr()) }
11341    }
11342
11343    /// Animated intensity
11344    /// Borrows the field in place — no copy, no allocation.
11345    pub fn intensity(&self) -> crate::support::Ref<'_, AnimRefF32> {
11346        // SAFETY: an interior pointer into `self`, valid for this
11347        // borrow and never freed by the `Ref`.
11348        unsafe {
11349            crate::support::Ref::new(AnimRefF32 {
11350                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_intensity(
11351                    self.raw.as_ptr(),
11352                )),
11353            })
11354        }
11355    }
11356
11357    pub fn intensity_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
11358        // SAFETY: as above; `&mut self` guarantees exclusivity.
11359        unsafe {
11360            crate::support::RefMut::new(AnimRefF32 {
11361                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_intensity(
11362                    self.raw.as_ptr(),
11363                )),
11364            })
11365        }
11366    }
11367
11368    /// Animated color
11369    /// Borrows the field in place — no copy, no allocation.
11370    pub fn color(&self) -> crate::support::Ref<'_, AnimRefM3ColorBGRA> {
11371        // SAFETY: an interior pointer into `self`, valid for this
11372        // borrow and never freed by the `Ref`.
11373        unsafe {
11374            crate::support::Ref::new(AnimRefM3ColorBGRA {
11375                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_color(
11376                    self.raw.as_ptr(),
11377                )),
11378            })
11379        }
11380    }
11381
11382    pub fn color_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3ColorBGRA> {
11383        // SAFETY: as above; `&mut self` guarantees exclusivity.
11384        unsafe {
11385            crate::support::RefMut::new(AnimRefM3ColorBGRA {
11386                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_color(
11387                    self.raw.as_ptr(),
11388                )),
11389            })
11390        }
11391    }
11392
11393    /// Animated HDR multiplier
11394    /// Borrows the field in place — no copy, no allocation.
11395    pub fn hdr(&self) -> crate::support::Ref<'_, AnimRefF32> {
11396        // SAFETY: an interior pointer into `self`, valid for this
11397        // borrow and never freed by the `Ref`.
11398        unsafe {
11399            crate::support::Ref::new(AnimRefF32 {
11400                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_hdr(
11401                    self.raw.as_ptr(),
11402                )),
11403            })
11404        }
11405    }
11406
11407    pub fn hdr_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
11408        // SAFETY: as above; `&mut self` guarantees exclusivity.
11409        unsafe {
11410            crate::support::RefMut::new(AnimRefF32 {
11411                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_hdr(
11412                    self.raw.as_ptr(),
11413                )),
11414            })
11415        }
11416    }
11417
11418    /// Animated size
11419    /// Borrows the field in place — no copy, no allocation.
11420    pub fn size(&self) -> crate::support::Ref<'_, AnimRefF32> {
11421        // SAFETY: an interior pointer into `self`, valid for this
11422        // borrow and never freed by the `Ref`.
11423        unsafe {
11424            crate::support::Ref::new(AnimRefF32 {
11425                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_size(
11426                    self.raw.as_ptr(),
11427                )),
11428            })
11429        }
11430    }
11431
11432    pub fn size_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
11433        // SAFETY: as above; `&mut self` guarantees exclusivity.
11434        unsafe {
11435            crate::support::RefMut::new(AnimRefF32 {
11436                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3LensFlare_get_size(
11437                    self.raw.as_ptr(),
11438                )),
11439            })
11440        }
11441    }
11442}
11443
11444impl Default for LensFlare {
11445    fn default() -> Self {
11446        Self::new()
11447    }
11448}
11449
11450/// One decoded property of a data-driven material
11451///
11452/// `data` is the raw value; its shape depends on `size`: 4 = scalar (f32, u32 enum, or BGRA colour — depends on the property), 8 = `{u32 index into DataDrivenMaterial::texturePaths, u32 texture source}`, 12 = 3 floats, 16 = 4 floats, 20 = `{u32 ColorChannelSelect, f32 multiply, f32 add, f32, u16 flags}`, 32 = `{f32 offsetU/V, tilingU/V, angleU/V/W, u32 flags}`, 48 = fresnel `{u32 FresnelMode, f32 exponent, min, max, rotation, mask}`.
11453pub struct DataDrivenProperty {
11454    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3DataDrivenProperty>,
11455}
11456
11457impl Drop for DataDrivenProperty {
11458    fn drop(&mut self) {
11459        // SAFETY: `raw` came from a native constructor and Drop runs once.
11460        unsafe { ffi::whiteout_m3_M3DataDrivenProperty_delete(self.raw.as_ptr()) }
11461    }
11462}
11463
11464impl DataDrivenProperty {
11465    /// # Safety
11466    /// `raw` must be a live handle this value takes ownership of.
11467    #[allow(dead_code)] // used by whichever methods return this type
11468    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3DataDrivenProperty) -> Option<Self> {
11469        core::ptr::NonNull::new(raw).map(|raw| DataDrivenProperty { raw })
11470    }
11471}
11472
11473// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11474// is deliberately NOT implemented — the C++ types make no documented
11475// guarantee about concurrent use, and claiming one we haven't verified
11476// would be unsound. See `@bind thread_safe` in the plan.
11477unsafe impl Send for DataDrivenProperty {}
11478
11479impl core::fmt::Debug for DataDrivenProperty {
11480    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11481        f.debug_struct("DataDrivenProperty").finish_non_exhaustive()
11482    }
11483}
11484
11485impl DataDrivenProperty {
11486    /// # Panics
11487    /// Panics if the native allocation fails.
11488    pub fn new() -> Self {
11489        // SAFETY: the native constructor returns a live handle; a null here
11490        // means the library is unusable.
11491        unsafe {
11492            let raw = ffi::whiteout_m3_M3DataDrivenProperty_new();
11493            Self::from_raw(raw).expect("native DataDrivenProperty allocation failed")
11494        }
11495    }
11496
11497    /// crc32 of the property name
11498    pub fn name_hash(&self) -> u32 {
11499        // SAFETY: plain scalar read through a live handle.
11500        unsafe { ffi::whiteout_m3_M3DataDrivenProperty_get_nameHash(self.raw.as_ptr()) }
11501    }
11502
11503    pub fn set_name_hash(&mut self, value: u32) {
11504        // SAFETY: plain scalar write through a live handle.
11505        unsafe { ffi::whiteout_m3_M3DataDrivenProperty_set_nameHash(self.raw.as_ptr(), value) }
11506    }
11507
11508    /// Resolved name, empty when the hash is unknown
11509    pub fn name(&self) -> String {
11510        // SAFETY: the native side hands over an owned CString.
11511        unsafe {
11512            crate::support::take_string(ffi::whiteout_m3_M3DataDrivenProperty_get_name(
11513                self.raw.as_ptr(),
11514            ))
11515        }
11516    }
11517
11518    pub fn set_name(&mut self, value: &str) {
11519        let value = std::ffi::CString::new(value).unwrap_or_default();
11520        // SAFETY: the pointer outlives the call.
11521        unsafe { ffi::whiteout_m3_M3DataDrivenProperty_set_name(self.raw.as_ptr(), value.as_ptr()) }
11522    }
11523
11524    /// Raw value bytes
11525    /// Zero-copy view of the underlying `std::vector`.
11526    pub fn data(&self) -> &[u8] {
11527        // SAFETY: `_data`/`_count` describe one contiguous C++
11528        // allocation, borrowed for as long as `self` is.
11529        unsafe {
11530            let n = ffi::whiteout_m3_M3DataDrivenProperty_get_data_count(self.raw.as_ptr());
11531            let p = ffi::whiteout_m3_M3DataDrivenProperty_get_data_data(self.raw.as_ptr());
11532            if p.is_null() || n == 0 {
11533                &[]
11534            } else {
11535                core::slice::from_raw_parts(p, n)
11536            }
11537        }
11538    }
11539
11540    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11541    pub fn data_mut(&mut self) -> &mut [u8] {
11542        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11543        unsafe {
11544            let n = ffi::whiteout_m3_M3DataDrivenProperty_get_data_count(self.raw.as_ptr());
11545            let p =
11546                ffi::whiteout_m3_M3DataDrivenProperty_get_data_data(self.raw.as_ptr()) as *mut u8;
11547            if p.is_null() || n == 0 {
11548                &mut []
11549            } else {
11550                core::slice::from_raw_parts_mut(p, n)
11551            }
11552        }
11553    }
11554
11555    pub fn set_data(&mut self, values: &[u8]) {
11556        // SAFETY: the native side copies `values` before returning.
11557        unsafe {
11558            ffi::whiteout_m3_M3DataDrivenProperty_assign_data(
11559                self.raw.as_ptr(),
11560                values.as_ptr() as *const _,
11561                values.len(),
11562            )
11563        }
11564    }
11565
11566    pub fn resize_data(&mut self, count: usize) {
11567        // SAFETY: reallocation is safe here precisely because
11568        // `&mut self` means no slice borrow is outstanding.
11569        unsafe { ffi::whiteout_m3_M3DataDrivenProperty_resize_data(self.raw.as_ptr(), count) }
11570    }
11571}
11572
11573impl Default for DataDrivenProperty {
11574    fn default() -> Self {
11575        Self::new()
11576    }
11577}
11578
11579/// One shader fragment of a data-driven material, with its properties
11580pub struct DataDrivenGroup {
11581    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3DataDrivenGroup>,
11582}
11583
11584impl Drop for DataDrivenGroup {
11585    fn drop(&mut self) {
11586        // SAFETY: `raw` came from a native constructor and Drop runs once.
11587        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_delete(self.raw.as_ptr()) }
11588    }
11589}
11590
11591impl DataDrivenGroup {
11592    /// # Safety
11593    /// `raw` must be a live handle this value takes ownership of.
11594    #[allow(dead_code)] // used by whichever methods return this type
11595    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3DataDrivenGroup) -> Option<Self> {
11596        core::ptr::NonNull::new(raw).map(|raw| DataDrivenGroup { raw })
11597    }
11598}
11599
11600// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11601// is deliberately NOT implemented — the C++ types make no documented
11602// guarantee about concurrent use, and claiming one we haven't verified
11603// would be unsound. See `@bind thread_safe` in the plan.
11604unsafe impl Send for DataDrivenGroup {}
11605
11606impl core::fmt::Debug for DataDrivenGroup {
11607    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11608        f.debug_struct("DataDrivenGroup").finish_non_exhaustive()
11609    }
11610}
11611
11612impl DataDrivenGroup {
11613    /// # Panics
11614    /// Panics if the native allocation fails.
11615    pub fn new() -> Self {
11616        // SAFETY: the native constructor returns a live handle; a null here
11617        // means the library is unusable.
11618        unsafe {
11619            let raw = ffi::whiteout_m3_M3DataDrivenGroup_new();
11620            Self::from_raw(raw).expect("native DataDrivenGroup allocation failed")
11621        }
11622    }
11623
11624    /// crc32 of the fragment name
11625    pub fn name_hash(&self) -> u32 {
11626        // SAFETY: plain scalar read through a live handle.
11627        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_get_nameHash(self.raw.as_ptr()) }
11628    }
11629
11630    pub fn set_name_hash(&mut self, value: u32) {
11631        // SAFETY: plain scalar write through a live handle.
11632        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_set_nameHash(self.raw.as_ptr(), value) }
11633    }
11634
11635    /// Resolved name, empty when unknown
11636    pub fn name(&self) -> String {
11637        // SAFETY: the native side hands over an owned CString.
11638        unsafe {
11639            crate::support::take_string(ffi::whiteout_m3_M3DataDrivenGroup_get_name(
11640                self.raw.as_ptr(),
11641            ))
11642        }
11643    }
11644
11645    pub fn set_name(&mut self, value: &str) {
11646        let value = std::ffi::CString::new(value).unwrap_or_default();
11647        // SAFETY: the pointer outlives the call.
11648        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_set_name(self.raw.as_ptr(), value.as_ptr()) }
11649    }
11650
11651    /// Properties, in stored order
11652    pub fn properties_len(&self) -> usize {
11653        // SAFETY: scalar read through a live handle.
11654        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_get_properties_count(self.raw.as_ptr()) }
11655    }
11656
11657    /// Borrows element `index` in place. `None` when out of range.
11658    pub fn properties(&self, index: usize) -> Option<crate::support::Ref<'_, DataDrivenProperty>> {
11659        if index >= self.properties_len() {
11660            return None;
11661        }
11662        // SAFETY: index checked above; the pointer is interior to `self`.
11663        unsafe {
11664            Some(crate::support::Ref::new(DataDrivenProperty {
11665                raw: core::ptr::NonNull::new_unchecked(
11666                    ffi::whiteout_m3_M3DataDrivenGroup_get_properties_at(self.raw.as_ptr(), index),
11667                ),
11668            }))
11669        }
11670    }
11671
11672    pub fn properties_mut(
11673        &mut self,
11674        index: usize,
11675    ) -> Option<crate::support::RefMut<'_, DataDrivenProperty>> {
11676        if index >= self.properties_len() {
11677            return None;
11678        }
11679        // SAFETY: as above; `&mut self` guarantees exclusivity.
11680        unsafe {
11681            Some(crate::support::RefMut::new(DataDrivenProperty {
11682                raw: core::ptr::NonNull::new_unchecked(
11683                    ffi::whiteout_m3_M3DataDrivenGroup_get_properties_at(self.raw.as_ptr(), index),
11684                ),
11685            }))
11686        }
11687    }
11688
11689    /// Iterate the elements, borrowing each in turn.
11690    pub fn properties_iter(
11691        &self,
11692    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DataDrivenProperty>> {
11693        (0..self.properties_len()).map(move |i| self.properties(i).expect("index below len"))
11694    }
11695
11696    pub fn resize_properties(&mut self, count: usize) {
11697        // SAFETY: exclusive access, so no borrow is outstanding.
11698        unsafe { ffi::whiteout_m3_M3DataDrivenGroup_resize_properties(self.raw.as_ptr(), count) }
11699    }
11700}
11701
11702impl Default for DataDrivenGroup {
11703    fn default() -> Self {
11704        Self::new()
11705    }
11706}
11707
11708/// The decoded contents of DataDrivenMaterial::propertyBlob
11709pub struct DataDrivenProperties {
11710    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3DataDrivenProperties>,
11711}
11712
11713impl Drop for DataDrivenProperties {
11714    fn drop(&mut self) {
11715        // SAFETY: `raw` came from a native constructor and Drop runs once.
11716        unsafe { ffi::whiteout_m3_M3DataDrivenProperties_delete(self.raw.as_ptr()) }
11717    }
11718}
11719
11720impl DataDrivenProperties {
11721    /// # Safety
11722    /// `raw` must be a live handle this value takes ownership of.
11723    #[allow(dead_code)] // used by whichever methods return this type
11724    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3DataDrivenProperties) -> Option<Self> {
11725        core::ptr::NonNull::new(raw).map(|raw| DataDrivenProperties { raw })
11726    }
11727}
11728
11729// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11730// is deliberately NOT implemented — the C++ types make no documented
11731// guarantee about concurrent use, and claiming one we haven't verified
11732// would be unsound. See `@bind thread_safe` in the plan.
11733unsafe impl Send for DataDrivenProperties {}
11734
11735impl core::fmt::Debug for DataDrivenProperties {
11736    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11737        f.debug_struct("DataDrivenProperties")
11738            .finish_non_exhaustive()
11739    }
11740}
11741
11742impl DataDrivenProperties {
11743    /// # Panics
11744    /// Panics if the native allocation fails.
11745    pub fn new() -> Self {
11746        // SAFETY: the native constructor returns a live handle; a null here
11747        // means the library is unusable.
11748        unsafe {
11749            let raw = ffi::whiteout_m3_M3DataDrivenProperties_new();
11750            Self::from_raw(raw).expect("native DataDrivenProperties allocation failed")
11751        }
11752    }
11753
11754    /// Fragment groups, in stored order
11755    pub fn groups_len(&self) -> usize {
11756        // SAFETY: scalar read through a live handle.
11757        unsafe { ffi::whiteout_m3_M3DataDrivenProperties_get_groups_count(self.raw.as_ptr()) }
11758    }
11759
11760    /// Borrows element `index` in place. `None` when out of range.
11761    pub fn groups(&self, index: usize) -> Option<crate::support::Ref<'_, DataDrivenGroup>> {
11762        if index >= self.groups_len() {
11763            return None;
11764        }
11765        // SAFETY: index checked above; the pointer is interior to `self`.
11766        unsafe {
11767            Some(crate::support::Ref::new(DataDrivenGroup {
11768                raw: core::ptr::NonNull::new_unchecked(
11769                    ffi::whiteout_m3_M3DataDrivenProperties_get_groups_at(self.raw.as_ptr(), index),
11770                ),
11771            }))
11772        }
11773    }
11774
11775    pub fn groups_mut(
11776        &mut self,
11777        index: usize,
11778    ) -> Option<crate::support::RefMut<'_, DataDrivenGroup>> {
11779        if index >= self.groups_len() {
11780            return None;
11781        }
11782        // SAFETY: as above; `&mut self` guarantees exclusivity.
11783        unsafe {
11784            Some(crate::support::RefMut::new(DataDrivenGroup {
11785                raw: core::ptr::NonNull::new_unchecked(
11786                    ffi::whiteout_m3_M3DataDrivenProperties_get_groups_at(self.raw.as_ptr(), index),
11787                ),
11788            }))
11789        }
11790    }
11791
11792    /// Iterate the elements, borrowing each in turn.
11793    pub fn groups_iter(
11794        &self,
11795    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DataDrivenGroup>> {
11796        (0..self.groups_len()).map(move |i| self.groups(i).expect("index below len"))
11797    }
11798
11799    pub fn resize_groups(&mut self, count: usize) {
11800        // SAFETY: exclusive access, so no borrow is outstanding.
11801        unsafe { ffi::whiteout_m3_M3DataDrivenProperties_resize_groups(self.raw.as_ptr(), count) }
11802    }
11803}
11804
11805impl Default for DataDrivenProperties {
11806    fn default() -> Self {
11807        Self::new()
11808    }
11809}
11810
11811/// Outcome of rebuilding a StandardMaterial from a DataDrivenMaterial
11812///
11813/// Not every data-driven material has a standard equivalent: some were authored directly against the shader-graph vocabulary, and others are the converted form of a DisplacementMaterial or ReflectionMaterial. `blocker` says which.
11814///
11815/// Conversion is lossy even when it succeeds, because the forward direction is: variant fragments collapse onto one layer slot, several fragments are derived from the model rather than the material, and per-field animation links are not carried in the blob. `lossy` lists what was dropped for this material.
11816pub struct StandardMaterialConversion {
11817    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3StandardMaterialConversion>,
11818}
11819
11820impl Drop for StandardMaterialConversion {
11821    fn drop(&mut self) {
11822        // SAFETY: `raw` came from a native constructor and Drop runs once.
11823        unsafe { ffi::whiteout_m3_M3StandardMaterialConversion_delete(self.raw.as_ptr()) }
11824    }
11825}
11826
11827impl StandardMaterialConversion {
11828    /// # Safety
11829    /// `raw` must be a live handle this value takes ownership of.
11830    #[allow(dead_code)] // used by whichever methods return this type
11831    pub(crate) unsafe fn from_raw(
11832        raw: *mut ffi::whiteout_M3StandardMaterialConversion,
11833    ) -> Option<Self> {
11834        core::ptr::NonNull::new(raw).map(|raw| StandardMaterialConversion { raw })
11835    }
11836}
11837
11838// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11839// is deliberately NOT implemented — the C++ types make no documented
11840// guarantee about concurrent use, and claiming one we haven't verified
11841// would be unsound. See `@bind thread_safe` in the plan.
11842unsafe impl Send for StandardMaterialConversion {}
11843
11844impl core::fmt::Debug for StandardMaterialConversion {
11845    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11846        f.debug_struct("StandardMaterialConversion")
11847            .finish_non_exhaustive()
11848    }
11849}
11850
11851impl StandardMaterialConversion {
11852    /// # Panics
11853    /// Panics if the native allocation fails.
11854    pub fn new() -> Self {
11855        // SAFETY: the native constructor returns a live handle; a null here
11856        // means the library is unusable.
11857        unsafe {
11858            let raw = ffi::whiteout_m3_M3StandardMaterialConversion_new();
11859            Self::from_raw(raw).expect("native StandardMaterialConversion allocation failed")
11860        }
11861    }
11862
11863    /// Whether `material` was produced
11864    pub fn converted(&self) -> bool {
11865        // SAFETY: plain scalar read through a live handle.
11866        unsafe {
11867            ffi::whiteout_m3_M3StandardMaterialConversion_get_converted(self.raw.as_ptr()) != 0
11868        }
11869    }
11870
11871    pub fn set_converted(&mut self, value: bool) {
11872        // SAFETY: plain scalar write through a live handle.
11873        unsafe {
11874            ffi::whiteout_m3_M3StandardMaterialConversion_set_converted(
11875                self.raw.as_ptr(),
11876                if value { 1 } else { 0 },
11877            )
11878        }
11879    }
11880
11881    /// Why not, when `converted` is false
11882    pub fn blocker(&self) -> String {
11883        // SAFETY: the native side hands over an owned CString.
11884        unsafe {
11885            crate::support::take_string(ffi::whiteout_m3_M3StandardMaterialConversion_get_blocker(
11886                self.raw.as_ptr(),
11887            ))
11888        }
11889    }
11890
11891    pub fn set_blocker(&mut self, value: &str) {
11892        let value = std::ffi::CString::new(value).unwrap_or_default();
11893        // SAFETY: the pointer outlives the call.
11894        unsafe {
11895            ffi::whiteout_m3_M3StandardMaterialConversion_set_blocker(
11896                self.raw.as_ptr(),
11897                value.as_ptr(),
11898            )
11899        }
11900    }
11901
11902    /// Only meaningful when `converted`
11903    /// Borrows the field in place — no copy, no allocation.
11904    pub fn material(&self) -> crate::support::Ref<'_, StandardMaterial> {
11905        // SAFETY: an interior pointer into `self`, valid for this
11906        // borrow and never freed by the `Ref`.
11907        unsafe {
11908            crate::support::Ref::new(StandardMaterial {
11909                raw: core::ptr::NonNull::new_unchecked(
11910                    ffi::whiteout_m3_M3StandardMaterialConversion_get_material(self.raw.as_ptr()),
11911                ),
11912            })
11913        }
11914    }
11915
11916    pub fn material_mut(&mut self) -> crate::support::RefMut<'_, StandardMaterial> {
11917        // SAFETY: as above; `&mut self` guarantees exclusivity.
11918        unsafe {
11919            crate::support::RefMut::new(StandardMaterial {
11920                raw: core::ptr::NonNull::new_unchecked(
11921                    ffi::whiteout_m3_M3StandardMaterialConversion_get_material(self.raw.as_ptr()),
11922                ),
11923            })
11924        }
11925    }
11926}
11927
11928impl Default for StandardMaterialConversion {
11929    fn default() -> Self {
11930        Self::new()
11931    }
11932}
11933
11934/// MADD — Data-driven material (v0–v3, 140–160 bytes)
11935///
11936/// The engine's own name for this chunk is `SDataDrivenMaterialData`. It is not "additional" data: at load the renderer converts every StandardMaterial (1), DisplacementMaterial (2) and ReflectionMaterial (10) in the model into one of these and rewrites the MaterialMap to MaterialType::DataDriven, so this is the only material representation the renderer actually consumes.
11937///
11938/// `fragmentHashes` names the shader fragments the material links, in order. Concatenating `shaderType`'s token with those names gives the shader permutation name, and its crc32 is the effect-cache lookup key.
11939///
11940/// `propertyBlob` is a self-describing two-level dictionary keyed by crc32 of unprefixed names — decode it with decodeProperties().
11941///
11942/// @see M3_FILE_FORMAT_SPECIFICATION.md §11 Materials
11943pub struct DataDrivenMaterial {
11944    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3DataDrivenMaterial>,
11945}
11946
11947impl Drop for DataDrivenMaterial {
11948    fn drop(&mut self) {
11949        // SAFETY: `raw` came from a native constructor and Drop runs once.
11950        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_delete(self.raw.as_ptr()) }
11951    }
11952}
11953
11954impl DataDrivenMaterial {
11955    /// # Safety
11956    /// `raw` must be a live handle this value takes ownership of.
11957    #[allow(dead_code)] // used by whichever methods return this type
11958    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3DataDrivenMaterial) -> Option<Self> {
11959        core::ptr::NonNull::new(raw).map(|raw| DataDrivenMaterial { raw })
11960    }
11961}
11962
11963// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
11964// is deliberately NOT implemented — the C++ types make no documented
11965// guarantee about concurrent use, and claiming one we haven't verified
11966// would be unsound. See `@bind thread_safe` in the plan.
11967unsafe impl Send for DataDrivenMaterial {}
11968
11969impl core::fmt::Debug for DataDrivenMaterial {
11970    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11971        f.debug_struct("DataDrivenMaterial").finish_non_exhaustive()
11972    }
11973}
11974
11975impl DataDrivenMaterial {
11976    /// # Panics
11977    /// Panics if the native allocation fails.
11978    pub fn new() -> Self {
11979        // SAFETY: the native constructor returns a live handle; a null here
11980        // means the library is unusable.
11981        unsafe {
11982            let raw = ffi::whiteout_m3_M3DataDrivenMaterial_new();
11983            Self::from_raw(raw).expect("native DataDrivenMaterial allocation failed")
11984        }
11985    }
11986
11987    /// Material name (`Ref<CHAR>`)
11988    pub fn material_name(&self) -> String {
11989        // SAFETY: the native side hands over an owned CString.
11990        unsafe {
11991            crate::support::take_string(ffi::whiteout_m3_M3DataDrivenMaterial_get_materialName(
11992                self.raw.as_ptr(),
11993            ))
11994        }
11995    }
11996
11997    pub fn set_material_name(&mut self, value: &str) {
11998        let value = std::ffi::CString::new(value).unwrap_or_default();
11999        // SAFETY: the pointer outlives the call.
12000        unsafe {
12001            ffi::whiteout_m3_M3DataDrivenMaterial_set_materialName(
12002                self.raw.as_ptr(),
12003                value.as_ptr(),
12004            )
12005        }
12006    }
12007
12008    /// crc32 of each shader fragment name, in link order (U32_)
12009    /// Zero-copy view of the underlying `std::vector`.
12010    pub fn fragment_hashes(&self) -> &[u32] {
12011        // SAFETY: `_data`/`_count` describe one contiguous C++
12012        // allocation, borrowed for as long as `self` is.
12013        unsafe {
12014            let n =
12015                ffi::whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_count(self.raw.as_ptr());
12016            let p =
12017                ffi::whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_data(self.raw.as_ptr());
12018            if p.is_null() || n == 0 {
12019                &[]
12020            } else {
12021                core::slice::from_raw_parts(p, n)
12022            }
12023        }
12024    }
12025
12026    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
12027    pub fn fragment_hashes_mut(&mut self) -> &mut [u32] {
12028        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
12029        unsafe {
12030            let n =
12031                ffi::whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_count(self.raw.as_ptr());
12032            let p = ffi::whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_data(self.raw.as_ptr())
12033                as *mut u32;
12034            if p.is_null() || n == 0 {
12035                &mut []
12036            } else {
12037                core::slice::from_raw_parts_mut(p, n)
12038            }
12039        }
12040    }
12041
12042    pub fn set_fragment_hashes(&mut self, values: &[u32]) {
12043        // SAFETY: the native side copies `values` before returning.
12044        unsafe {
12045            ffi::whiteout_m3_M3DataDrivenMaterial_assign_fragmentHashes(
12046                self.raw.as_ptr(),
12047                values.as_ptr() as *const _,
12048                values.len(),
12049            )
12050        }
12051    }
12052
12053    pub fn resize_fragment_hashes(&mut self, count: usize) {
12054        // SAFETY: reallocation is safe here precisely because
12055        // `&mut self` means no slice borrow is outstanding.
12056        unsafe {
12057            ffi::whiteout_m3_M3DataDrivenMaterial_resize_fragmentHashes(self.raw.as_ptr(), count)
12058        }
12059    }
12060
12061    /// Secondary hash list (U32_, v2+)
12062    /// Zero-copy view of the underlying `std::vector`.
12063    pub fn extra_hashes(&self) -> &[u32] {
12064        // SAFETY: `_data`/`_count` describe one contiguous C++
12065        // allocation, borrowed for as long as `self` is.
12066        unsafe {
12067            let n = ffi::whiteout_m3_M3DataDrivenMaterial_get_extraHashes_count(self.raw.as_ptr());
12068            let p = ffi::whiteout_m3_M3DataDrivenMaterial_get_extraHashes_data(self.raw.as_ptr());
12069            if p.is_null() || n == 0 {
12070                &[]
12071            } else {
12072                core::slice::from_raw_parts(p, n)
12073            }
12074        }
12075    }
12076
12077    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
12078    pub fn extra_hashes_mut(&mut self) -> &mut [u32] {
12079        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
12080        unsafe {
12081            let n = ffi::whiteout_m3_M3DataDrivenMaterial_get_extraHashes_count(self.raw.as_ptr());
12082            let p = ffi::whiteout_m3_M3DataDrivenMaterial_get_extraHashes_data(self.raw.as_ptr())
12083                as *mut u32;
12084            if p.is_null() || n == 0 {
12085                &mut []
12086            } else {
12087                core::slice::from_raw_parts_mut(p, n)
12088            }
12089        }
12090    }
12091
12092    pub fn set_extra_hashes(&mut self, values: &[u32]) {
12093        // SAFETY: the native side copies `values` before returning.
12094        unsafe {
12095            ffi::whiteout_m3_M3DataDrivenMaterial_assign_extraHashes(
12096                self.raw.as_ptr(),
12097                values.as_ptr() as *const _,
12098                values.len(),
12099            )
12100        }
12101    }
12102
12103    pub fn resize_extra_hashes(&mut self, count: usize) {
12104        // SAFETY: reallocation is safe here precisely because
12105        // `&mut self` means no slice borrow is outstanding.
12106        unsafe {
12107            ffi::whiteout_m3_M3DataDrivenMaterial_resize_extraHashes(self.raw.as_ptr(), count)
12108        }
12109    }
12110
12111    /// Property dictionary (`Ref<CHAR>`)
12112    /// Zero-copy view of the underlying `std::vector`.
12113    pub fn property_blob(&self) -> &[u8] {
12114        // SAFETY: `_data`/`_count` describe one contiguous C++
12115        // allocation, borrowed for as long as `self` is.
12116        unsafe {
12117            let n = ffi::whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_count(self.raw.as_ptr());
12118            let p = ffi::whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_data(self.raw.as_ptr());
12119            if p.is_null() || n == 0 {
12120                &[]
12121            } else {
12122                core::slice::from_raw_parts(p, n)
12123            }
12124        }
12125    }
12126
12127    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
12128    pub fn property_blob_mut(&mut self) -> &mut [u8] {
12129        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
12130        unsafe {
12131            let n = ffi::whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_count(self.raw.as_ptr());
12132            let p = ffi::whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_data(self.raw.as_ptr())
12133                as *mut u8;
12134            if p.is_null() || n == 0 {
12135                &mut []
12136            } else {
12137                core::slice::from_raw_parts_mut(p, n)
12138            }
12139        }
12140    }
12141
12142    pub fn set_property_blob(&mut self, values: &[u8]) {
12143        // SAFETY: the native side copies `values` before returning.
12144        unsafe {
12145            ffi::whiteout_m3_M3DataDrivenMaterial_assign_propertyBlob(
12146                self.raw.as_ptr(),
12147                values.as_ptr() as *const _,
12148                values.len(),
12149            )
12150        }
12151    }
12152
12153    pub fn resize_property_blob(&mut self, count: usize) {
12154        // SAFETY: reallocation is safe here precisely because
12155        // `&mut self` means no slice borrow is outstanding.
12156        unsafe {
12157            ffi::whiteout_m3_M3DataDrivenMaterial_resize_propertyBlob(self.raw.as_ptr(), count)
12158        }
12159    }
12160
12161    /// 1.0, 1.5 or 2.0 across the corpus
12162    pub fn unknown_108(&self) -> f32 {
12163        // SAFETY: plain scalar read through a live handle.
12164        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown108(self.raw.as_ptr()) }
12165    }
12166
12167    pub fn set_unknown_108(&mut self, value: f32) {
12168        // SAFETY: plain scalar write through a live handle.
12169        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown108(self.raw.as_ptr(), value) }
12170    }
12171
12172    /// 1.0 in every known record
12173    pub fn unknown_112(&self) -> f32 {
12174        // SAFETY: plain scalar read through a live handle.
12175        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown112(self.raw.as_ptr()) }
12176    }
12177
12178    pub fn set_unknown_112(&mut self, value: f32) {
12179        // SAFETY: plain scalar write through a live handle.
12180        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown112(self.raw.as_ptr(), value) }
12181    }
12182
12183    pub fn unknown_116(&self) -> f32 {
12184        // SAFETY: plain scalar read through a live handle.
12185        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown116(self.raw.as_ptr()) }
12186    }
12187
12188    pub fn set_unknown_116(&mut self, value: f32) {
12189        // SAFETY: plain scalar write through a live handle.
12190        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown116(self.raw.as_ptr(), value) }
12191    }
12192
12193    /// crc32 of the shader permutation name; 0 = compute it at load
12194    pub fn effect_name_hash(&self) -> u32 {
12195        // SAFETY: plain scalar read through a live handle.
12196        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_effectNameHash(self.raw.as_ptr()) }
12197    }
12198
12199    pub fn set_effect_name_hash(&mut self, value: u32) {
12200        // SAFETY: plain scalar write through a live handle.
12201        unsafe {
12202            ffi::whiteout_m3_M3DataDrivenMaterial_set_effectNameHash(self.raw.as_ptr(), value)
12203        }
12204    }
12205
12206    pub fn unknown_124(&self) -> u32 {
12207        // SAFETY: plain scalar read through a live handle.
12208        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown124(self.raw.as_ptr()) }
12209    }
12210
12211    pub fn set_unknown_124(&mut self, value: u32) {
12212        // SAFETY: plain scalar write through a live handle.
12213        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown124(self.raw.as_ptr(), value) }
12214    }
12215
12216    /// Zero in every known record
12217    pub fn padding_128(&self) -> u32 {
12218        // SAFETY: plain scalar read through a live handle.
12219        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_padding128(self.raw.as_ptr()) }
12220    }
12221
12222    pub fn set_padding_128(&mut self, value: u32) {
12223        // SAFETY: plain scalar write through a live handle.
12224        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_padding128(self.raw.as_ptr(), value) }
12225    }
12226
12227    pub fn unknown_132(&self) -> i32 {
12228        // SAFETY: plain scalar read through a live handle.
12229        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown132(self.raw.as_ptr()) }
12230    }
12231
12232    pub fn set_unknown_132(&mut self, value: i32) {
12233        // SAFETY: plain scalar write through a live handle.
12234        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown132(self.raw.as_ptr(), value) }
12235    }
12236
12237    /// Packed bit field
12238    pub fn unknown_136(&self) -> u32 {
12239        // SAFETY: plain scalar read through a live handle.
12240        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown136(self.raw.as_ptr()) }
12241    }
12242
12243    pub fn set_unknown_136(&mut self, value: u32) {
12244        // SAFETY: plain scalar write through a live handle.
12245        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown136(self.raw.as_ptr(), value) }
12246    }
12247
12248    pub fn unknown_140(&self) -> u32 {
12249        // SAFETY: plain scalar read through a live handle.
12250        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown140(self.raw.as_ptr()) }
12251    }
12252
12253    pub fn set_unknown_140(&mut self, value: u32) {
12254        // SAFETY: plain scalar write through a live handle.
12255        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown140(self.raw.as_ptr(), value) }
12256    }
12257
12258    pub fn unknown_144(&self) -> u32 {
12259        // SAFETY: plain scalar read through a live handle.
12260        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown144(self.raw.as_ptr()) }
12261    }
12262
12263    pub fn set_unknown_144(&mut self, value: u32) {
12264        // SAFETY: plain scalar write through a live handle.
12265        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown144(self.raw.as_ptr(), value) }
12266    }
12267
12268    pub fn unknown_148(&self) -> u8 {
12269        // SAFETY: plain scalar read through a live handle.
12270        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown148(self.raw.as_ptr()) }
12271    }
12272
12273    pub fn set_unknown_148(&mut self, value: u8) {
12274        // SAFETY: plain scalar write through a live handle.
12275        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown148(self.raw.as_ptr(), value) }
12276    }
12277
12278    /// Derived cache the loader recomputes; do not trust over the blob
12279    pub fn alpha_fresnel_flags(&self) -> u8 {
12280        // SAFETY: plain scalar read through a live handle.
12281        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_alphaFresnelFlags(self.raw.as_ptr()) }
12282    }
12283
12284    pub fn set_alpha_fresnel_flags(&mut self, value: u8) {
12285        // SAFETY: plain scalar write through a live handle.
12286        unsafe {
12287            ffi::whiteout_m3_M3DataDrivenMaterial_set_alphaFresnelFlags(self.raw.as_ptr(), value)
12288        }
12289    }
12290
12291    /// Shader family prefix for the permutation name
12292    pub fn shader_type(&self) -> MaterialShaderType {
12293        // SAFETY: scalar read; the discriminant is validated below.
12294        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_shaderType(self.raw.as_ptr()) }
12295            .try_into()
12296            .expect("unknown enum discriminant from the native library")
12297    }
12298
12299    pub fn set_shader_type(&mut self, value: MaterialShaderType) {
12300        // SAFETY: scalar write through a live handle.
12301        unsafe {
12302            ffi::whiteout_m3_M3DataDrivenMaterial_set_shaderType(self.raw.as_ptr(), value as i32)
12303        }
12304    }
12305
12306    pub fn unknown_151(&self) -> u8 {
12307        // SAFETY: plain scalar read through a live handle.
12308        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_unknown151(self.raw.as_ptr()) }
12309    }
12310
12311    pub fn set_unknown_151(&mut self, value: u8) {
12312        // SAFETY: plain scalar write through a live handle.
12313        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_set_unknown151(self.raw.as_ptr(), value) }
12314    }
12315
12316    /// Second permutation hash, 0xFFFFFFFF = none (v3+)
12317    pub fn effect_name_hash_2(&self) -> u32 {
12318        // SAFETY: plain scalar read through a live handle.
12319        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_effectNameHash2(self.raw.as_ptr()) }
12320    }
12321
12322    pub fn set_effect_name_hash_2(&mut self, value: u32) {
12323        // SAFETY: plain scalar write through a live handle.
12324        unsafe {
12325            ffi::whiteout_m3_M3DataDrivenMaterial_set_effectNameHash2(self.raw.as_ptr(), value)
12326        }
12327    }
12328
12329    /// Third permutation hash, 0xFFFFFFFF = none (v3+)
12330    pub fn effect_name_hash_3(&self) -> u32 {
12331        // SAFETY: plain scalar read through a live handle.
12332        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_get_effectNameHash3(self.raw.as_ptr()) }
12333    }
12334
12335    pub fn set_effect_name_hash_3(&mut self, value: u32) {
12336        // SAFETY: plain scalar write through a live handle.
12337        unsafe {
12338            ffi::whiteout_m3_M3DataDrivenMaterial_set_effectNameHash3(self.raw.as_ptr(), value)
12339        }
12340    }
12341
12342    /// Decode propertyBlob into fragment groups and named properties
12343    pub fn decode_properties(&self) -> Option<DataDrivenProperties> {
12344        // SAFETY: handle is live for the duration of the call.
12345        unsafe {
12346            DataDrivenProperties::from_raw(ffi::whiteout_m3_M3DataDrivenMaterial_decodeProperties(
12347                self.raw.as_ptr(),
12348            ))
12349        }
12350    }
12351
12352    /// Rebuild the StandardMaterial this was converted from, where possible
12353    ///
12354    /// The engine only converts in the other direction, and does so lossily, so this reverses what it can and reports the rest. See StandardMaterialConversion.
12355    pub fn to_standard_material(&self) -> Option<StandardMaterialConversion> {
12356        // SAFETY: handle is live for the duration of the call.
12357        unsafe {
12358            StandardMaterialConversion::from_raw(
12359                ffi::whiteout_m3_M3DataDrivenMaterial_toStandardMaterial(self.raw.as_ptr()),
12360            )
12361        }
12362    }
12363
12364    /// Best-effort StandardMaterial for a material that has no exact one
12365    ///
12366    /// toStandardMaterial() refuses shader-graph materials, which were authored in the node editor and never had a StandardMaterial form. This infers one anyway, from the node types, the per-node names in extraHashes, and the texture filenames. The blob stores nodes but not the edges between them, so the graph topology cannot be recovered and the result is a likeness, not a conversion — `lossy` always says so. Materials that are already fixed-function are forwarded to toStandardMaterial() unchanged.
12367    pub fn approximate_standard_material(&self) -> Option<StandardMaterialConversion> {
12368        // SAFETY: handle is live for the duration of the call.
12369        unsafe {
12370            StandardMaterialConversion::from_raw(
12371                ffi::whiteout_m3_M3DataDrivenMaterial_approximateStandardMaterial(
12372                    self.raw.as_ptr(),
12373                ),
12374            )
12375        }
12376    }
12377
12378    pub fn version(&self) -> i32 {
12379        // SAFETY: handle is live for the duration of the call.
12380        unsafe { ffi::whiteout_m3_M3DataDrivenMaterial_getVersion(self.raw.as_ptr()) }
12381    }
12382
12383    pub fn set_version(&mut self, new_version: i32) -> bool {
12384        // SAFETY: handle is live for the duration of the call.
12385        unsafe {
12386            ffi::whiteout_m3_M3DataDrivenMaterial_setVersion(self.raw.as_ptr(), new_version) != 0
12387        }
12388    }
12389
12390    pub fn force_version(&mut self, new_version: i32) {
12391        // SAFETY: handle is live for the duration of the call.
12392        unsafe {
12393            ffi::whiteout_m3_M3DataDrivenMaterial_forceVersion(self.raw.as_ptr(), new_version);
12394        }
12395    }
12396}
12397
12398impl Default for DataDrivenMaterial {
12399    fn default() -> Self {
12400        Self::new()
12401    }
12402}
12403
12404/// BONE — Skeleton bone (v0–v1, 160 bytes)
12405///
12406/// Each bone has a parent index, animated position/rotation/scale/visibility, and flags controlling inheritance, billboard mode, and IK.
12407pub struct Bone {
12408    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Bone>,
12409}
12410
12411impl Drop for Bone {
12412    fn drop(&mut self) {
12413        // SAFETY: `raw` came from a native constructor and Drop runs once.
12414        unsafe { ffi::whiteout_m3_M3Bone_delete(self.raw.as_ptr()) }
12415    }
12416}
12417
12418impl Bone {
12419    /// # Safety
12420    /// `raw` must be a live handle this value takes ownership of.
12421    #[allow(dead_code)] // used by whichever methods return this type
12422    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Bone) -> Option<Self> {
12423        core::ptr::NonNull::new(raw).map(|raw| Bone { raw })
12424    }
12425}
12426
12427// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12428// is deliberately NOT implemented — the C++ types make no documented
12429// guarantee about concurrent use, and claiming one we haven't verified
12430// would be unsound. See `@bind thread_safe` in the plan.
12431unsafe impl Send for Bone {}
12432
12433impl core::fmt::Debug for Bone {
12434    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12435        f.debug_struct("Bone").finish_non_exhaustive()
12436    }
12437}
12438
12439impl Bone {
12440    /// # Panics
12441    /// Panics if the native allocation fails.
12442    pub fn new() -> Self {
12443        // SAFETY: the native constructor returns a live handle; a null here
12444        // means the library is unusable.
12445        unsafe {
12446            let raw = ffi::whiteout_m3_M3Bone_new();
12447            Self::from_raw(raw).expect("native Bone allocation failed")
12448        }
12449    }
12450
12451    /// Unknown field
12452    pub fn unknown(&self) -> u32 {
12453        // SAFETY: plain scalar read through a live handle.
12454        unsafe { ffi::whiteout_m3_M3Bone_get_unknown(self.raw.as_ptr()) }
12455    }
12456
12457    pub fn set_unknown(&mut self, value: u32) {
12458        // SAFETY: plain scalar write through a live handle.
12459        unsafe { ffi::whiteout_m3_M3Bone_set_unknown(self.raw.as_ptr(), value) }
12460    }
12461
12462    /// Bone name (`Ref<CHAR>`)
12463    pub fn name(&self) -> String {
12464        // SAFETY: the native side hands over an owned CString.
12465        unsafe { crate::support::take_string(ffi::whiteout_m3_M3Bone_get_name(self.raw.as_ptr())) }
12466    }
12467
12468    pub fn set_name(&mut self, value: &str) {
12469        let value = std::ffi::CString::new(value).unwrap_or_default();
12470        // SAFETY: the pointer outlives the call.
12471        unsafe { ffi::whiteout_m3_M3Bone_set_name(self.raw.as_ptr(), value.as_ptr()) }
12472    }
12473
12474    /// Bone flags (inherit, billboard, IK, skin)
12475    pub fn flags(&self) -> BoneFlag {
12476        // SAFETY: scalar read; a flag set accepts any bits.
12477        BoneFlag(unsafe { ffi::whiteout_m3_M3Bone_get_flags(self.raw.as_ptr()) })
12478    }
12479
12480    pub fn set_flags(&mut self, value: BoneFlag) {
12481        // SAFETY: scalar write through a live handle.
12482        unsafe { ffi::whiteout_m3_M3Bone_set_flags(self.raw.as_ptr(), value.0) }
12483    }
12484
12485    /// Parent bone index (0xFFFF = root)
12486    pub fn parent_index(&self) -> u16 {
12487        // SAFETY: plain scalar read through a live handle.
12488        unsafe { ffi::whiteout_m3_M3Bone_get_parentIndex(self.raw.as_ptr()) }
12489    }
12490
12491    pub fn set_parent_index(&mut self, value: u16) {
12492        // SAFETY: plain scalar write through a live handle.
12493        unsafe { ffi::whiteout_m3_M3Bone_set_parentIndex(self.raw.as_ptr(), value) }
12494    }
12495
12496    /// Alignment padding
12497    pub fn padding(&self) -> u16 {
12498        // SAFETY: plain scalar read through a live handle.
12499        unsafe { ffi::whiteout_m3_M3Bone_get_padding(self.raw.as_ptr()) }
12500    }
12501
12502    pub fn set_padding(&mut self, value: u16) {
12503        // SAFETY: plain scalar write through a live handle.
12504        unsafe { ffi::whiteout_m3_M3Bone_set_padding(self.raw.as_ptr(), value) }
12505    }
12506
12507    /// Animated translation (36 bytes)
12508    /// Borrows the field in place — no copy, no allocation.
12509    pub fn position(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
12510        // SAFETY: an interior pointer into `self`, valid for this
12511        // borrow and never freed by the `Ref`.
12512        unsafe {
12513            crate::support::Ref::new(AnimRefVector3f {
12514                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_position(
12515                    self.raw.as_ptr(),
12516                )),
12517            })
12518        }
12519    }
12520
12521    pub fn position_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
12522        // SAFETY: as above; `&mut self` guarantees exclusivity.
12523        unsafe {
12524            crate::support::RefMut::new(AnimRefVector3f {
12525                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_position(
12526                    self.raw.as_ptr(),
12527                )),
12528            })
12529        }
12530    }
12531
12532    /// Animated rotation (44 bytes)
12533    /// Borrows the field in place — no copy, no allocation.
12534    pub fn rotation(&self) -> crate::support::Ref<'_, AnimRefQuaternion> {
12535        // SAFETY: an interior pointer into `self`, valid for this
12536        // borrow and never freed by the `Ref`.
12537        unsafe {
12538            crate::support::Ref::new(AnimRefQuaternion {
12539                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_rotation(
12540                    self.raw.as_ptr(),
12541                )),
12542            })
12543        }
12544    }
12545
12546    pub fn rotation_mut(&mut self) -> crate::support::RefMut<'_, AnimRefQuaternion> {
12547        // SAFETY: as above; `&mut self` guarantees exclusivity.
12548        unsafe {
12549            crate::support::RefMut::new(AnimRefQuaternion {
12550                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_rotation(
12551                    self.raw.as_ptr(),
12552                )),
12553            })
12554        }
12555    }
12556
12557    /// Animated scale (36 bytes)
12558    /// Borrows the field in place — no copy, no allocation.
12559    pub fn scale(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
12560        // SAFETY: an interior pointer into `self`, valid for this
12561        // borrow and never freed by the `Ref`.
12562        unsafe {
12563            crate::support::Ref::new(AnimRefVector3f {
12564                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_scale(
12565                    self.raw.as_ptr(),
12566                )),
12567            })
12568        }
12569    }
12570
12571    pub fn scale_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
12572        // SAFETY: as above; `&mut self` guarantees exclusivity.
12573        unsafe {
12574            crate::support::RefMut::new(AnimRefVector3f {
12575                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_scale(
12576                    self.raw.as_ptr(),
12577                )),
12578            })
12579        }
12580    }
12581
12582    /// Animated visibility flag (20 bytes)
12583    /// Borrows the field in place — no copy, no allocation.
12584    pub fn visibility(&self) -> crate::support::Ref<'_, AnimRefU32> {
12585        // SAFETY: an interior pointer into `self`, valid for this
12586        // borrow and never freed by the `Ref`.
12587        unsafe {
12588            crate::support::Ref::new(AnimRefU32 {
12589                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_visibility(
12590                    self.raw.as_ptr(),
12591                )),
12592            })
12593        }
12594    }
12595
12596    pub fn visibility_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
12597        // SAFETY: as above; `&mut self` guarantees exclusivity.
12598        unsafe {
12599            crate::support::RefMut::new(AnimRefU32 {
12600                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Bone_get_visibility(
12601                    self.raw.as_ptr(),
12602                )),
12603            })
12604        }
12605    }
12606}
12607
12608impl Default for Bone {
12609    fn default() -> Self {
12610        Self::new()
12611    }
12612}
12613
12614/// REGN — Region / submesh (v0–v5, 48 bytes)
12615///
12616/// Describes a contiguous range of vertices and indices forming a submesh, with bone lookup info for skinning and UV scale/offset for texturing.
12617pub struct Region {
12618    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Region>,
12619}
12620
12621impl Drop for Region {
12622    fn drop(&mut self) {
12623        // SAFETY: `raw` came from a native constructor and Drop runs once.
12624        unsafe { ffi::whiteout_m3_M3Region_delete(self.raw.as_ptr()) }
12625    }
12626}
12627
12628impl Region {
12629    /// # Safety
12630    /// `raw` must be a live handle this value takes ownership of.
12631    #[allow(dead_code)] // used by whichever methods return this type
12632    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Region) -> Option<Self> {
12633        core::ptr::NonNull::new(raw).map(|raw| Region { raw })
12634    }
12635}
12636
12637// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12638// is deliberately NOT implemented — the C++ types make no documented
12639// guarantee about concurrent use, and claiming one we haven't verified
12640// would be unsound. See `@bind thread_safe` in the plan.
12641unsafe impl Send for Region {}
12642
12643impl core::fmt::Debug for Region {
12644    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12645        f.debug_struct("Region").finish_non_exhaustive()
12646    }
12647}
12648
12649impl Region {
12650    /// # Panics
12651    /// Panics if the native allocation fails.
12652    pub fn new() -> Self {
12653        // SAFETY: the native constructor returns a live handle; a null here
12654        // means the library is unusable.
12655        unsafe {
12656            let raw = ffi::whiteout_m3_M3Region_new();
12657            Self::from_raw(raw).expect("native Region allocation failed")
12658        }
12659    }
12660
12661    /// Region index
12662    pub fn index(&self) -> u32 {
12663        // SAFETY: plain scalar read through a live handle.
12664        unsafe { ffi::whiteout_m3_M3Region_get_index(self.raw.as_ptr()) }
12665    }
12666
12667    pub fn set_index(&mut self, value: u32) {
12668        // SAFETY: plain scalar write through a live handle.
12669        unsafe { ffi::whiteout_m3_M3Region_set_index(self.raw.as_ptr(), value) }
12670    }
12671
12672    /// Unknown field
12673    pub fn unknown(&self) -> u32 {
12674        // SAFETY: plain scalar read through a live handle.
12675        unsafe { ffi::whiteout_m3_M3Region_get_unknown(self.raw.as_ptr()) }
12676    }
12677
12678    pub fn set_unknown(&mut self, value: u32) {
12679        // SAFETY: plain scalar write through a live handle.
12680        unsafe { ffi::whiteout_m3_M3Region_set_unknown(self.raw.as_ptr(), value) }
12681    }
12682
12683    /// First vertex in the vertex buffer
12684    pub fn first_vertex(&self) -> u32 {
12685        // SAFETY: plain scalar read through a live handle.
12686        unsafe { ffi::whiteout_m3_M3Region_get_firstVertex(self.raw.as_ptr()) }
12687    }
12688
12689    pub fn set_first_vertex(&mut self, value: u32) {
12690        // SAFETY: plain scalar write through a live handle.
12691        unsafe { ffi::whiteout_m3_M3Region_set_firstVertex(self.raw.as_ptr(), value) }
12692    }
12693
12694    /// Number of vertices
12695    pub fn vertex_count(&self) -> u32 {
12696        // SAFETY: plain scalar read through a live handle.
12697        unsafe { ffi::whiteout_m3_M3Region_get_vertexCount(self.raw.as_ptr()) }
12698    }
12699
12700    pub fn set_vertex_count(&mut self, value: u32) {
12701        // SAFETY: plain scalar write through a live handle.
12702        unsafe { ffi::whiteout_m3_M3Region_set_vertexCount(self.raw.as_ptr(), value) }
12703    }
12704
12705    /// First index in the index buffer
12706    pub fn first_index(&self) -> u32 {
12707        // SAFETY: plain scalar read through a live handle.
12708        unsafe { ffi::whiteout_m3_M3Region_get_firstIndex(self.raw.as_ptr()) }
12709    }
12710
12711    pub fn set_first_index(&mut self, value: u32) {
12712        // SAFETY: plain scalar write through a live handle.
12713        unsafe { ffi::whiteout_m3_M3Region_set_firstIndex(self.raw.as_ptr(), value) }
12714    }
12715
12716    /// Number of indices (triangles × 3)
12717    pub fn index_count(&self) -> u32 {
12718        // SAFETY: plain scalar read through a live handle.
12719        unsafe { ffi::whiteout_m3_M3Region_get_indexCount(self.raw.as_ptr()) }
12720    }
12721
12722    pub fn set_index_count(&mut self, value: u32) {
12723        // SAFETY: plain scalar write through a live handle.
12724        unsafe { ffi::whiteout_m3_M3Region_set_indexCount(self.raw.as_ptr(), value) }
12725    }
12726
12727    /// Repeats boneLookupCount (874 of 874 shipped regions)
12728    pub fn unknown_2(&self) -> u16 {
12729        // SAFETY: plain scalar read through a live handle.
12730        unsafe { ffi::whiteout_m3_M3Region_get_unknown2(self.raw.as_ptr()) }
12731    }
12732
12733    pub fn set_unknown_2(&mut self, value: u16) {
12734        // SAFETY: plain scalar write through a live handle.
12735        unsafe { ffi::whiteout_m3_M3Region_set_unknown2(self.raw.as_ptr(), value) }
12736    }
12737
12738    /// First entry in bone lookup table
12739    pub fn first_bone_lookup(&self) -> u16 {
12740        // SAFETY: plain scalar read through a live handle.
12741        unsafe { ffi::whiteout_m3_M3Region_get_firstBoneLookup(self.raw.as_ptr()) }
12742    }
12743
12744    pub fn set_first_bone_lookup(&mut self, value: u16) {
12745        // SAFETY: plain scalar write through a live handle.
12746        unsafe { ffi::whiteout_m3_M3Region_set_firstBoneLookup(self.raw.as_ptr(), value) }
12747    }
12748
12749    /// Number of bone lookup entries
12750    pub fn bone_lookup_count(&self) -> u16 {
12751        // SAFETY: plain scalar read through a live handle.
12752        unsafe { ffi::whiteout_m3_M3Region_get_boneLookupCount(self.raw.as_ptr()) }
12753    }
12754
12755    pub fn set_bone_lookup_count(&mut self, value: u16) {
12756        // SAFETY: plain scalar write through a live handle.
12757        unsafe { ffi::whiteout_m3_M3Region_set_boneLookupCount(self.raw.as_ptr(), value) }
12758    }
12759
12760    /// Alignment padding
12761    pub fn padding(&self) -> u16 {
12762        // SAFETY: plain scalar read through a live handle.
12763        unsafe { ffi::whiteout_m3_M3Region_get_padding(self.raw.as_ptr()) }
12764    }
12765
12766    pub fn set_padding(&mut self, value: u16) {
12767        // SAFETY: plain scalar write through a live handle.
12768        unsafe { ffi::whiteout_m3_M3Region_set_padding(self.raw.as_ptr(), value) }
12769    }
12770
12771    /// Number of bone weight pairs per vertex
12772    pub fn bone_weight_pairs(&self) -> u8 {
12773        // SAFETY: plain scalar read through a live handle.
12774        unsafe { ffi::whiteout_m3_M3Region_get_boneWeightPairs(self.raw.as_ptr()) }
12775    }
12776
12777    pub fn set_bone_weight_pairs(&mut self, value: u8) {
12778        // SAFETY: plain scalar write through a live handle.
12779        unsafe { ffi::whiteout_m3_M3Region_set_boneWeightPairs(self.raw.as_ptr(), value) }
12780    }
12781
12782    /// Number of bone index pairs per vertex
12783    pub fn bone_index_pairs(&self) -> u8 {
12784        // SAFETY: plain scalar read through a live handle.
12785        unsafe { ffi::whiteout_m3_M3Region_get_boneIndexPairs(self.raw.as_ptr()) }
12786    }
12787
12788    pub fn set_bone_index_pairs(&mut self, value: u8) {
12789        // SAFETY: plain scalar write through a live handle.
12790        unsafe { ffi::whiteout_m3_M3Region_set_boneIndexPairs(self.raw.as_ptr(), value) }
12791    }
12792
12793    /// Root bone for this region
12794    pub fn root_bone(&self) -> u16 {
12795        // SAFETY: plain scalar read through a live handle.
12796        unsafe { ffi::whiteout_m3_M3Region_get_rootBone(self.raw.as_ptr()) }
12797    }
12798
12799    pub fn set_root_bone(&mut self, value: u16) {
12800        // SAFETY: plain scalar write through a live handle.
12801        unsafe { ffi::whiteout_m3_M3Region_set_rootBone(self.raw.as_ptr(), value) }
12802    }
12803
12804    /// Region flags (hidden, cloth, etc.)
12805    pub fn flags(&self) -> RegionFlag {
12806        // SAFETY: scalar read; a flag set accepts any bits.
12807        RegionFlag(unsafe { ffi::whiteout_m3_M3Region_get_flags(self.raw.as_ptr()) })
12808    }
12809
12810    pub fn set_flags(&mut self, value: RegionFlag) {
12811        // SAFETY: scalar write through a live handle.
12812        unsafe { ffi::whiteout_m3_M3Region_set_flags(self.raw.as_ptr(), value.0) }
12813    }
12814
12815    /// UV coordinate scale factor
12816    pub fn uv_scale(&self) -> f32 {
12817        // SAFETY: plain scalar read through a live handle.
12818        unsafe { ffi::whiteout_m3_M3Region_get_uvScale(self.raw.as_ptr()) }
12819    }
12820
12821    pub fn set_uv_scale(&mut self, value: f32) {
12822        // SAFETY: plain scalar write through a live handle.
12823        unsafe { ffi::whiteout_m3_M3Region_set_uvScale(self.raw.as_ptr(), value) }
12824    }
12825
12826    /// UV coordinate offset
12827    pub fn uv_offset(&self) -> f32 {
12828        // SAFETY: plain scalar read through a live handle.
12829        unsafe { ffi::whiteout_m3_M3Region_get_uvOffset(self.raw.as_ptr()) }
12830    }
12831
12832    pub fn set_uv_offset(&mut self, value: f32) {
12833        // SAFETY: plain scalar write through a live handle.
12834        unsafe { ffi::whiteout_m3_M3Region_set_uvOffset(self.raw.as_ptr(), value) }
12835    }
12836}
12837
12838impl Default for Region {
12839    fn default() -> Self {
12840        Self::new()
12841    }
12842}
12843
12844/// BAT_ — Batch / draw call (v0–v1, 14 bytes)
12845///
12846/// Associates a Region with a material for rendering. Multiple batches may reference the same region with different materials.
12847pub struct Batch {
12848    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Batch>,
12849}
12850
12851impl Drop for Batch {
12852    fn drop(&mut self) {
12853        // SAFETY: `raw` came from a native constructor and Drop runs once.
12854        unsafe { ffi::whiteout_m3_M3Batch_delete(self.raw.as_ptr()) }
12855    }
12856}
12857
12858impl Batch {
12859    /// # Safety
12860    /// `raw` must be a live handle this value takes ownership of.
12861    #[allow(dead_code)] // used by whichever methods return this type
12862    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Batch) -> Option<Self> {
12863        core::ptr::NonNull::new(raw).map(|raw| Batch { raw })
12864    }
12865}
12866
12867// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12868// is deliberately NOT implemented — the C++ types make no documented
12869// guarantee about concurrent use, and claiming one we haven't verified
12870// would be unsound. See `@bind thread_safe` in the plan.
12871unsafe impl Send for Batch {}
12872
12873impl core::fmt::Debug for Batch {
12874    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12875        f.debug_struct("Batch").finish_non_exhaustive()
12876    }
12877}
12878
12879impl Batch {
12880    /// # Panics
12881    /// Panics if the native allocation fails.
12882    pub fn new() -> Self {
12883        // SAFETY: the native constructor returns a live handle; a null here
12884        // means the library is unusable.
12885        unsafe {
12886            let raw = ffi::whiteout_m3_M3Batch_new();
12887            Self::from_raw(raw).expect("native Batch allocation failed")
12888        }
12889    }
12890
12891    /// Unknown field
12892    pub fn unknown(&self) -> u32 {
12893        // SAFETY: plain scalar read through a live handle.
12894        unsafe { ffi::whiteout_m3_M3Batch_get_unknown(self.raw.as_ptr()) }
12895    }
12896
12897    pub fn set_unknown(&mut self, value: u32) {
12898        // SAFETY: plain scalar write through a live handle.
12899        unsafe { ffi::whiteout_m3_M3Batch_set_unknown(self.raw.as_ptr(), value) }
12900    }
12901
12902    /// Index into REGN array
12903    pub fn region_index(&self) -> u16 {
12904        // SAFETY: plain scalar read through a live handle.
12905        unsafe { ffi::whiteout_m3_M3Batch_get_regionIndex(self.raw.as_ptr()) }
12906    }
12907
12908    pub fn set_region_index(&mut self, value: u16) {
12909        // SAFETY: plain scalar write through a live handle.
12910        unsafe { ffi::whiteout_m3_M3Batch_set_regionIndex(self.raw.as_ptr(), value) }
12911    }
12912
12913    /// Unknown field
12914    pub fn unknown_2(&self) -> u32 {
12915        // SAFETY: plain scalar read through a live handle.
12916        unsafe { ffi::whiteout_m3_M3Batch_get_unknown2(self.raw.as_ptr()) }
12917    }
12918
12919    pub fn set_unknown_2(&mut self, value: u32) {
12920        // SAFETY: plain scalar write through a live handle.
12921        unsafe { ffi::whiteout_m3_M3Batch_set_unknown2(self.raw.as_ptr(), value) }
12922    }
12923
12924    /// Index into MATM material map array
12925    pub fn material_index(&self) -> u16 {
12926        // SAFETY: plain scalar read through a live handle.
12927        unsafe { ffi::whiteout_m3_M3Batch_get_materialIndex(self.raw.as_ptr()) }
12928    }
12929
12930    pub fn set_material_index(&mut self, value: u16) {
12931        // SAFETY: plain scalar write through a live handle.
12932        unsafe { ffi::whiteout_m3_M3Batch_set_materialIndex(self.raw.as_ptr(), value) }
12933    }
12934
12935    /// Bone whose animated visibility gates this batch's draw (0xFFFF = always drawn). Misnamed — it is a bone index, not a count: the engine's submit loop reads it and skips the batch when that bone is invisible.
12936    pub fn bone_count(&self) -> u16 {
12937        // SAFETY: plain scalar read through a live handle.
12938        unsafe { ffi::whiteout_m3_M3Batch_get_boneCount(self.raw.as_ptr()) }
12939    }
12940
12941    pub fn set_bone_count(&mut self, value: u16) {
12942        // SAFETY: plain scalar write through a live handle.
12943        unsafe { ffi::whiteout_m3_M3Batch_set_boneCount(self.raw.as_ptr(), value) }
12944    }
12945}
12946
12947impl Default for Batch {
12948    fn default() -> Self {
12949        Self::new()
12950    }
12951}
12952
12953/// MSEC — Mesh section bounds (v0–v1, 80 bytes)
12954///
12955/// Per-node animated bounding extent used for culling and LOD.
12956pub struct MeshSection {
12957    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3MeshSection>,
12958}
12959
12960impl Drop for MeshSection {
12961    fn drop(&mut self) {
12962        // SAFETY: `raw` came from a native constructor and Drop runs once.
12963        unsafe { ffi::whiteout_m3_M3MeshSection_delete(self.raw.as_ptr()) }
12964    }
12965}
12966
12967impl MeshSection {
12968    /// # Safety
12969    /// `raw` must be a live handle this value takes ownership of.
12970    #[allow(dead_code)] // used by whichever methods return this type
12971    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3MeshSection) -> Option<Self> {
12972        core::ptr::NonNull::new(raw).map(|raw| MeshSection { raw })
12973    }
12974}
12975
12976// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12977// is deliberately NOT implemented — the C++ types make no documented
12978// guarantee about concurrent use, and claiming one we haven't verified
12979// would be unsound. See `@bind thread_safe` in the plan.
12980unsafe impl Send for MeshSection {}
12981
12982impl core::fmt::Debug for MeshSection {
12983    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12984        f.debug_struct("MeshSection").finish_non_exhaustive()
12985    }
12986}
12987
12988impl MeshSection {
12989    /// # Panics
12990    /// Panics if the native allocation fails.
12991    pub fn new() -> Self {
12992        // SAFETY: the native constructor returns a live handle; a null here
12993        // means the library is unusable.
12994        unsafe {
12995            let raw = ffi::whiteout_m3_M3MeshSection_new();
12996            Self::from_raw(raw).expect("native MeshSection allocation failed")
12997        }
12998    }
12999
13000    /// Index into BONE array
13001    pub fn node_index(&self) -> u32 {
13002        // SAFETY: plain scalar read through a live handle.
13003        unsafe { ffi::whiteout_m3_M3MeshSection_get_nodeIndex(self.raw.as_ptr()) }
13004    }
13005
13006    pub fn set_node_index(&mut self, value: u32) {
13007        // SAFETY: plain scalar write through a live handle.
13008        unsafe { ffi::whiteout_m3_M3MeshSection_set_nodeIndex(self.raw.as_ptr(), value) }
13009    }
13010
13011    /// Animated bounding volume (76 bytes)
13012    /// Borrows the field in place — no copy, no allocation.
13013    pub fn bounds(&self) -> crate::support::Ref<'_, AnimRefM3Extent> {
13014        // SAFETY: an interior pointer into `self`, valid for this
13015        // borrow and never freed by the `Ref`.
13016        unsafe {
13017            crate::support::Ref::new(AnimRefM3Extent {
13018                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3MeshSection_get_bounds(
13019                    self.raw.as_ptr(),
13020                )),
13021            })
13022        }
13023    }
13024
13025    pub fn bounds_mut(&mut self) -> crate::support::RefMut<'_, AnimRefM3Extent> {
13026        // SAFETY: as above; `&mut self` guarantees exclusivity.
13027        unsafe {
13028            crate::support::RefMut::new(AnimRefM3Extent {
13029                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3MeshSection_get_bounds(
13030                    self.raw.as_ptr(),
13031                )),
13032            })
13033        }
13034    }
13035}
13036
13037impl Default for MeshSection {
13038    fn default() -> Self {
13039        Self::new()
13040    }
13041}
13042
13043/// DIV_ — Mesh division (v0–v2, 52 bytes)
13044///
13045/// Top-level mesh container grouping face indices, regions, batches, and mesh sections. Most models have a single division.
13046pub struct MeshDivision {
13047    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3MeshDivision>,
13048}
13049
13050impl Drop for MeshDivision {
13051    fn drop(&mut self) {
13052        // SAFETY: `raw` came from a native constructor and Drop runs once.
13053        unsafe { ffi::whiteout_m3_M3MeshDivision_delete(self.raw.as_ptr()) }
13054    }
13055}
13056
13057impl MeshDivision {
13058    /// # Safety
13059    /// `raw` must be a live handle this value takes ownership of.
13060    #[allow(dead_code)] // used by whichever methods return this type
13061    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3MeshDivision) -> Option<Self> {
13062        core::ptr::NonNull::new(raw).map(|raw| MeshDivision { raw })
13063    }
13064}
13065
13066// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13067// is deliberately NOT implemented — the C++ types make no documented
13068// guarantee about concurrent use, and claiming one we haven't verified
13069// would be unsound. See `@bind thread_safe` in the plan.
13070unsafe impl Send for MeshDivision {}
13071
13072impl core::fmt::Debug for MeshDivision {
13073    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13074        f.debug_struct("MeshDivision").finish_non_exhaustive()
13075    }
13076}
13077
13078impl MeshDivision {
13079    /// # Panics
13080    /// Panics if the native allocation fails.
13081    pub fn new() -> Self {
13082        // SAFETY: the native constructor returns a live handle; a null here
13083        // means the library is unusable.
13084        unsafe {
13085            let raw = ffi::whiteout_m3_M3MeshDivision_new();
13086            Self::from_raw(raw).expect("native MeshDivision allocation failed")
13087        }
13088    }
13089
13090    /// Triangle indices (U16_)
13091    /// Zero-copy view of the underlying `std::vector`.
13092    pub fn faces(&self) -> &[u16] {
13093        // SAFETY: `_data`/`_count` describe one contiguous C++
13094        // allocation, borrowed for as long as `self` is.
13095        unsafe {
13096            let n = ffi::whiteout_m3_M3MeshDivision_get_faces_count(self.raw.as_ptr());
13097            let p = ffi::whiteout_m3_M3MeshDivision_get_faces_data(self.raw.as_ptr());
13098            if p.is_null() || n == 0 {
13099                &[]
13100            } else {
13101                core::slice::from_raw_parts(p, n)
13102            }
13103        }
13104    }
13105
13106    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13107    pub fn faces_mut(&mut self) -> &mut [u16] {
13108        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13109        unsafe {
13110            let n = ffi::whiteout_m3_M3MeshDivision_get_faces_count(self.raw.as_ptr());
13111            let p = ffi::whiteout_m3_M3MeshDivision_get_faces_data(self.raw.as_ptr()) as *mut u16;
13112            if p.is_null() || n == 0 {
13113                &mut []
13114            } else {
13115                core::slice::from_raw_parts_mut(p, n)
13116            }
13117        }
13118    }
13119
13120    pub fn set_faces(&mut self, values: &[u16]) {
13121        // SAFETY: the native side copies `values` before returning.
13122        unsafe {
13123            ffi::whiteout_m3_M3MeshDivision_assign_faces(
13124                self.raw.as_ptr(),
13125                values.as_ptr() as *const _,
13126                values.len(),
13127            )
13128        }
13129    }
13130
13131    pub fn resize_faces(&mut self, count: usize) {
13132        // SAFETY: reallocation is safe here precisely because
13133        // `&mut self` means no slice borrow is outstanding.
13134        unsafe { ffi::whiteout_m3_M3MeshDivision_resize_faces(self.raw.as_ptr(), count) }
13135    }
13136
13137    /// Regions / submeshes (REGN)
13138    pub fn regions_len(&self) -> usize {
13139        // SAFETY: scalar read through a live handle.
13140        unsafe { ffi::whiteout_m3_M3MeshDivision_get_regions_count(self.raw.as_ptr()) }
13141    }
13142
13143    /// Borrows element `index` in place. `None` when out of range.
13144    pub fn regions(&self, index: usize) -> Option<crate::support::Ref<'_, Region>> {
13145        if index >= self.regions_len() {
13146            return None;
13147        }
13148        // SAFETY: index checked above; the pointer is interior to `self`.
13149        unsafe {
13150            Some(crate::support::Ref::new(Region {
13151                raw: core::ptr::NonNull::new_unchecked(
13152                    ffi::whiteout_m3_M3MeshDivision_get_regions_at(self.raw.as_ptr(), index),
13153                ),
13154            }))
13155        }
13156    }
13157
13158    pub fn regions_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Region>> {
13159        if index >= self.regions_len() {
13160            return None;
13161        }
13162        // SAFETY: as above; `&mut self` guarantees exclusivity.
13163        unsafe {
13164            Some(crate::support::RefMut::new(Region {
13165                raw: core::ptr::NonNull::new_unchecked(
13166                    ffi::whiteout_m3_M3MeshDivision_get_regions_at(self.raw.as_ptr(), index),
13167                ),
13168            }))
13169        }
13170    }
13171
13172    /// Iterate the elements, borrowing each in turn.
13173    pub fn regions_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Region>> {
13174        (0..self.regions_len()).map(move |i| self.regions(i).expect("index below len"))
13175    }
13176
13177    pub fn resize_regions(&mut self, count: usize) {
13178        // SAFETY: exclusive access, so no borrow is outstanding.
13179        unsafe { ffi::whiteout_m3_M3MeshDivision_resize_regions(self.raw.as_ptr(), count) }
13180    }
13181
13182    /// Draw call batches (BAT_)
13183    pub fn batches_len(&self) -> usize {
13184        // SAFETY: scalar read through a live handle.
13185        unsafe { ffi::whiteout_m3_M3MeshDivision_get_batches_count(self.raw.as_ptr()) }
13186    }
13187
13188    /// Borrows element `index` in place. `None` when out of range.
13189    pub fn batches(&self, index: usize) -> Option<crate::support::Ref<'_, Batch>> {
13190        if index >= self.batches_len() {
13191            return None;
13192        }
13193        // SAFETY: index checked above; the pointer is interior to `self`.
13194        unsafe {
13195            Some(crate::support::Ref::new(Batch {
13196                raw: core::ptr::NonNull::new_unchecked(
13197                    ffi::whiteout_m3_M3MeshDivision_get_batches_at(self.raw.as_ptr(), index),
13198                ),
13199            }))
13200        }
13201    }
13202
13203    pub fn batches_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Batch>> {
13204        if index >= self.batches_len() {
13205            return None;
13206        }
13207        // SAFETY: as above; `&mut self` guarantees exclusivity.
13208        unsafe {
13209            Some(crate::support::RefMut::new(Batch {
13210                raw: core::ptr::NonNull::new_unchecked(
13211                    ffi::whiteout_m3_M3MeshDivision_get_batches_at(self.raw.as_ptr(), index),
13212                ),
13213            }))
13214        }
13215    }
13216
13217    /// Iterate the elements, borrowing each in turn.
13218    pub fn batches_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Batch>> {
13219        (0..self.batches_len()).map(move |i| self.batches(i).expect("index below len"))
13220    }
13221
13222    pub fn resize_batches(&mut self, count: usize) {
13223        // SAFETY: exclusive access, so no borrow is outstanding.
13224        unsafe { ffi::whiteout_m3_M3MeshDivision_resize_batches(self.raw.as_ptr(), count) }
13225    }
13226
13227    /// Per-node mesh section bounds (MSEC)
13228    pub fn msec_len(&self) -> usize {
13229        // SAFETY: scalar read through a live handle.
13230        unsafe { ffi::whiteout_m3_M3MeshDivision_get_msec_count(self.raw.as_ptr()) }
13231    }
13232
13233    /// Borrows element `index` in place. `None` when out of range.
13234    pub fn msec(&self, index: usize) -> Option<crate::support::Ref<'_, MeshSection>> {
13235        if index >= self.msec_len() {
13236            return None;
13237        }
13238        // SAFETY: index checked above; the pointer is interior to `self`.
13239        unsafe {
13240            Some(crate::support::Ref::new(MeshSection {
13241                raw: core::ptr::NonNull::new_unchecked(
13242                    ffi::whiteout_m3_M3MeshDivision_get_msec_at(self.raw.as_ptr(), index),
13243                ),
13244            }))
13245        }
13246    }
13247
13248    pub fn msec_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, MeshSection>> {
13249        if index >= self.msec_len() {
13250            return None;
13251        }
13252        // SAFETY: as above; `&mut self` guarantees exclusivity.
13253        unsafe {
13254            Some(crate::support::RefMut::new(MeshSection {
13255                raw: core::ptr::NonNull::new_unchecked(
13256                    ffi::whiteout_m3_M3MeshDivision_get_msec_at(self.raw.as_ptr(), index),
13257                ),
13258            }))
13259        }
13260    }
13261
13262    /// Iterate the elements, borrowing each in turn.
13263    pub fn msec_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, MeshSection>> {
13264        (0..self.msec_len()).map(move |i| self.msec(i).expect("index below len"))
13265    }
13266
13267    pub fn resize_msec(&mut self, count: usize) {
13268        // SAFETY: exclusive access, so no borrow is outstanding.
13269        unsafe { ffi::whiteout_m3_M3MeshDivision_resize_msec(self.raw.as_ptr(), count) }
13270    }
13271
13272    /// Instance count
13273    pub fn instances(&self) -> u32 {
13274        // SAFETY: plain scalar read through a live handle.
13275        unsafe { ffi::whiteout_m3_M3MeshDivision_get_instances(self.raw.as_ptr()) }
13276    }
13277
13278    pub fn set_instances(&mut self, value: u32) {
13279        // SAFETY: plain scalar write through a live handle.
13280        unsafe { ffi::whiteout_m3_M3MeshDivision_set_instances(self.raw.as_ptr(), value) }
13281    }
13282}
13283
13284impl Default for MeshDivision {
13285    fn default() -> Self {
13286        Self::new()
13287    }
13288}
13289
13290/// IREF — Initial reference / inverse bind-pose (v0, 64 bytes)
13291///
13292/// Stores the 4×4 inverse bind-pose matrix for a bone, used to transform vertices from model space into bone-local space for skinning.
13293pub struct InitialReference {
13294    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3InitialReference>,
13295}
13296
13297impl Drop for InitialReference {
13298    fn drop(&mut self) {
13299        // SAFETY: `raw` came from a native constructor and Drop runs once.
13300        unsafe { ffi::whiteout_m3_M3InitialReference_delete(self.raw.as_ptr()) }
13301    }
13302}
13303
13304impl InitialReference {
13305    /// # Safety
13306    /// `raw` must be a live handle this value takes ownership of.
13307    #[allow(dead_code)] // used by whichever methods return this type
13308    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3InitialReference) -> Option<Self> {
13309        core::ptr::NonNull::new(raw).map(|raw| InitialReference { raw })
13310    }
13311}
13312
13313// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13314// is deliberately NOT implemented — the C++ types make no documented
13315// guarantee about concurrent use, and claiming one we haven't verified
13316// would be unsound. See `@bind thread_safe` in the plan.
13317unsafe impl Send for InitialReference {}
13318
13319impl core::fmt::Debug for InitialReference {
13320    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13321        f.debug_struct("InitialReference").finish_non_exhaustive()
13322    }
13323}
13324
13325impl InitialReference {
13326    /// # Panics
13327    /// Panics if the native allocation fails.
13328    pub fn new() -> Self {
13329        // SAFETY: the native constructor returns a live handle; a null here
13330        // means the library is unusable.
13331        unsafe {
13332            let raw = ffi::whiteout_m3_M3InitialReference_new();
13333            Self::from_raw(raw).expect("native InitialReference allocation failed")
13334        }
13335    }
13336}
13337
13338impl Default for InitialReference {
13339    fn default() -> Self {
13340        Self::new()
13341    }
13342}
13343
13344/// ATT_ — Attachment point (v0–v1, 20 bytes)
13345///
13346/// Named bone location used by the engine to attach effects, weapons, or other models to specific skeleton bones.
13347pub struct AttachmentPoint {
13348    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AttachmentPoint>,
13349}
13350
13351impl Drop for AttachmentPoint {
13352    fn drop(&mut self) {
13353        // SAFETY: `raw` came from a native constructor and Drop runs once.
13354        unsafe { ffi::whiteout_m3_M3AttachmentPoint_delete(self.raw.as_ptr()) }
13355    }
13356}
13357
13358impl AttachmentPoint {
13359    /// # Safety
13360    /// `raw` must be a live handle this value takes ownership of.
13361    #[allow(dead_code)] // used by whichever methods return this type
13362    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AttachmentPoint) -> Option<Self> {
13363        core::ptr::NonNull::new(raw).map(|raw| AttachmentPoint { raw })
13364    }
13365}
13366
13367// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13368// is deliberately NOT implemented — the C++ types make no documented
13369// guarantee about concurrent use, and claiming one we haven't verified
13370// would be unsound. See `@bind thread_safe` in the plan.
13371unsafe impl Send for AttachmentPoint {}
13372
13373impl core::fmt::Debug for AttachmentPoint {
13374    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13375        f.debug_struct("AttachmentPoint").finish_non_exhaustive()
13376    }
13377}
13378
13379impl AttachmentPoint {
13380    /// # Panics
13381    /// Panics if the native allocation fails.
13382    pub fn new() -> Self {
13383        // SAFETY: the native constructor returns a live handle; a null here
13384        // means the library is unusable.
13385        unsafe {
13386            let raw = ffi::whiteout_m3_M3AttachmentPoint_new();
13387            Self::from_raw(raw).expect("native AttachmentPoint allocation failed")
13388        }
13389    }
13390
13391    /// Unknown field
13392    pub fn unknown(&self) -> u32 {
13393        // SAFETY: plain scalar read through a live handle.
13394        unsafe { ffi::whiteout_m3_M3AttachmentPoint_get_unknown(self.raw.as_ptr()) }
13395    }
13396
13397    pub fn set_unknown(&mut self, value: u32) {
13398        // SAFETY: plain scalar write through a live handle.
13399        unsafe { ffi::whiteout_m3_M3AttachmentPoint_set_unknown(self.raw.as_ptr(), value) }
13400    }
13401
13402    /// Attachment point name (`Ref<CHAR>`)
13403    pub fn name(&self) -> String {
13404        // SAFETY: the native side hands over an owned CString.
13405        unsafe {
13406            crate::support::take_string(ffi::whiteout_m3_M3AttachmentPoint_get_name(
13407                self.raw.as_ptr(),
13408            ))
13409        }
13410    }
13411
13412    pub fn set_name(&mut self, value: &str) {
13413        let value = std::ffi::CString::new(value).unwrap_or_default();
13414        // SAFETY: the pointer outlives the call.
13415        unsafe { ffi::whiteout_m3_M3AttachmentPoint_set_name(self.raw.as_ptr(), value.as_ptr()) }
13416    }
13417
13418    /// Index into BONE array
13419    pub fn bone_index(&self) -> u32 {
13420        // SAFETY: plain scalar read through a live handle.
13421        unsafe { ffi::whiteout_m3_M3AttachmentPoint_get_boneIndex(self.raw.as_ptr()) }
13422    }
13423
13424    pub fn set_bone_index(&mut self, value: u32) {
13425        // SAFETY: plain scalar write through a live handle.
13426        unsafe { ffi::whiteout_m3_M3AttachmentPoint_set_boneIndex(self.raw.as_ptr(), value) }
13427    }
13428}
13429
13430impl Default for AttachmentPoint {
13431    fn default() -> Self {
13432        Self::new()
13433    }
13434}
13435
13436/// SSGS — Hit-test shape (v0–v1, 108 bytes)
13437///
13438/// Defines a collision / selection volume (box, sphere, capsule, cylinder, or mesh) attached to a bone. Used for both tight and fuzzy hit testing.
13439pub struct HitTestShape {
13440    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3HitTestShape>,
13441}
13442
13443impl Drop for HitTestShape {
13444    fn drop(&mut self) {
13445        // SAFETY: `raw` came from a native constructor and Drop runs once.
13446        unsafe { ffi::whiteout_m3_M3HitTestShape_delete(self.raw.as_ptr()) }
13447    }
13448}
13449
13450impl HitTestShape {
13451    /// # Safety
13452    /// `raw` must be a live handle this value takes ownership of.
13453    #[allow(dead_code)] // used by whichever methods return this type
13454    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3HitTestShape) -> Option<Self> {
13455        core::ptr::NonNull::new(raw).map(|raw| HitTestShape { raw })
13456    }
13457}
13458
13459// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13460// is deliberately NOT implemented — the C++ types make no documented
13461// guarantee about concurrent use, and claiming one we haven't verified
13462// would be unsound. See `@bind thread_safe` in the plan.
13463unsafe impl Send for HitTestShape {}
13464
13465impl core::fmt::Debug for HitTestShape {
13466    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13467        f.debug_struct("HitTestShape").finish_non_exhaustive()
13468    }
13469}
13470
13471impl HitTestShape {
13472    /// # Panics
13473    /// Panics if the native allocation fails.
13474    pub fn new() -> Self {
13475        // SAFETY: the native constructor returns a live handle; a null here
13476        // means the library is unusable.
13477        unsafe {
13478            let raw = ffi::whiteout_m3_M3HitTestShape_new();
13479            Self::from_raw(raw).expect("native HitTestShape allocation failed")
13480        }
13481    }
13482
13483    /// Shape type (box/sphere/capsule/cylinder/mesh). Defaulted because a conversion builds `MODL.tightHitTestObject` without ever assigning it, and an indeterminate enum wrote junk shape types into every export (`reference_m3_layer_stack_junk`, the same defect one field over). Sphere is what 2,222 of 2,448 shipped models state.
13484    pub fn shape_type(&self) -> HitTestShapeType {
13485        // SAFETY: scalar read; the discriminant is validated below.
13486        unsafe { ffi::whiteout_m3_M3HitTestShape_get_shapeType(self.raw.as_ptr()) }
13487            .try_into()
13488            .expect("unknown enum discriminant from the native library")
13489    }
13490
13491    pub fn set_shape_type(&mut self, value: HitTestShapeType) {
13492        // SAFETY: scalar write through a live handle.
13493        unsafe { ffi::whiteout_m3_M3HitTestShape_set_shapeType(self.raw.as_ptr(), value as i32) }
13494    }
13495
13496    /// Index into BONE array
13497    pub fn bone_index(&self) -> u16 {
13498        // SAFETY: plain scalar read through a live handle.
13499        unsafe { ffi::whiteout_m3_M3HitTestShape_get_boneIndex(self.raw.as_ptr()) }
13500    }
13501
13502    pub fn set_bone_index(&mut self, value: u16) {
13503        // SAFETY: plain scalar write through a live handle.
13504        unsafe { ffi::whiteout_m3_M3HitTestShape_set_boneIndex(self.raw.as_ptr(), value) }
13505    }
13506
13507    /// Alignment padding
13508    pub fn padding(&self) -> u16 {
13509        // SAFETY: plain scalar read through a live handle.
13510        unsafe { ffi::whiteout_m3_M3HitTestShape_get_padding(self.raw.as_ptr()) }
13511    }
13512
13513    pub fn set_padding(&mut self, value: u16) {
13514        // SAFETY: plain scalar write through a live handle.
13515        unsafe { ffi::whiteout_m3_M3HitTestShape_set_padding(self.raw.as_ptr(), value) }
13516    }
13517
13518    /// Mesh vertex positions (VEC3, mesh type only)
13519    /// Zero-copy view of the underlying `std::vector`.
13520    pub fn vertex_positions(&self) -> &[crate::math::Vector3f] {
13521        // SAFETY: `_data`/`_count` describe one contiguous C++
13522        // allocation, borrowed for as long as `self` is.
13523        unsafe {
13524            let n = ffi::whiteout_m3_M3HitTestShape_get_vertexPositions_count(self.raw.as_ptr());
13525            let p = ffi::whiteout_m3_M3HitTestShape_get_vertexPositions_data(self.raw.as_ptr())
13526                as *const crate::math::Vector3f;
13527            if p.is_null() || n == 0 {
13528                &[]
13529            } else {
13530                core::slice::from_raw_parts(p, n)
13531            }
13532        }
13533    }
13534
13535    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13536    pub fn vertex_positions_mut(&mut self) -> &mut [crate::math::Vector3f] {
13537        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13538        unsafe {
13539            let n = ffi::whiteout_m3_M3HitTestShape_get_vertexPositions_count(self.raw.as_ptr());
13540            let p = ffi::whiteout_m3_M3HitTestShape_get_vertexPositions_data(self.raw.as_ptr())
13541                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
13542            if p.is_null() || n == 0 {
13543                &mut []
13544            } else {
13545                core::slice::from_raw_parts_mut(p, n)
13546            }
13547        }
13548    }
13549
13550    pub fn set_vertex_positions(&mut self, values: &[crate::math::Vector3f]) {
13551        // SAFETY: the native side copies `values` before returning.
13552        unsafe {
13553            ffi::whiteout_m3_M3HitTestShape_assign_vertexPositions(
13554                self.raw.as_ptr(),
13555                values.as_ptr() as *const _,
13556                values.len(),
13557            )
13558        }
13559    }
13560
13561    pub fn resize_vertex_positions(&mut self, count: usize) {
13562        // SAFETY: reallocation is safe here precisely because
13563        // `&mut self` means no slice borrow is outstanding.
13564        unsafe { ffi::whiteout_m3_M3HitTestShape_resize_vertexPositions(self.raw.as_ptr(), count) }
13565    }
13566
13567    /// Mesh triangle indices (U16_, mesh type only)
13568    /// Zero-copy view of the underlying `std::vector`.
13569    pub fn face_indices(&self) -> &[u16] {
13570        // SAFETY: `_data`/`_count` describe one contiguous C++
13571        // allocation, borrowed for as long as `self` is.
13572        unsafe {
13573            let n = ffi::whiteout_m3_M3HitTestShape_get_faceIndices_count(self.raw.as_ptr());
13574            let p = ffi::whiteout_m3_M3HitTestShape_get_faceIndices_data(self.raw.as_ptr());
13575            if p.is_null() || n == 0 {
13576                &[]
13577            } else {
13578                core::slice::from_raw_parts(p, n)
13579            }
13580        }
13581    }
13582
13583    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13584    pub fn face_indices_mut(&mut self) -> &mut [u16] {
13585        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13586        unsafe {
13587            let n = ffi::whiteout_m3_M3HitTestShape_get_faceIndices_count(self.raw.as_ptr());
13588            let p =
13589                ffi::whiteout_m3_M3HitTestShape_get_faceIndices_data(self.raw.as_ptr()) as *mut u16;
13590            if p.is_null() || n == 0 {
13591                &mut []
13592            } else {
13593                core::slice::from_raw_parts_mut(p, n)
13594            }
13595        }
13596    }
13597
13598    pub fn set_face_indices(&mut self, values: &[u16]) {
13599        // SAFETY: the native side copies `values` before returning.
13600        unsafe {
13601            ffi::whiteout_m3_M3HitTestShape_assign_faceIndices(
13602                self.raw.as_ptr(),
13603                values.as_ptr() as *const _,
13604                values.len(),
13605            )
13606        }
13607    }
13608
13609    pub fn resize_face_indices(&mut self, count: usize) {
13610        // SAFETY: reallocation is safe here precisely because
13611        // `&mut self` means no slice borrow is outstanding.
13612        unsafe { ffi::whiteout_m3_M3HitTestShape_resize_faceIndices(self.raw.as_ptr(), count) }
13613    }
13614
13615    /// X dimension (radius for sphere/capsule)
13616    pub fn size_x(&self) -> f32 {
13617        // SAFETY: plain scalar read through a live handle.
13618        unsafe { ffi::whiteout_m3_M3HitTestShape_get_sizeX(self.raw.as_ptr()) }
13619    }
13620
13621    pub fn set_size_x(&mut self, value: f32) {
13622        // SAFETY: plain scalar write through a live handle.
13623        unsafe { ffi::whiteout_m3_M3HitTestShape_set_sizeX(self.raw.as_ptr(), value) }
13624    }
13625
13626    /// Y dimension (height for capsule/cylinder)
13627    pub fn size_y(&self) -> f32 {
13628        // SAFETY: plain scalar read through a live handle.
13629        unsafe { ffi::whiteout_m3_M3HitTestShape_get_sizeY(self.raw.as_ptr()) }
13630    }
13631
13632    pub fn set_size_y(&mut self, value: f32) {
13633        // SAFETY: plain scalar write through a live handle.
13634        unsafe { ffi::whiteout_m3_M3HitTestShape_set_sizeY(self.raw.as_ptr(), value) }
13635    }
13636
13637    /// Z dimension
13638    pub fn size_z(&self) -> f32 {
13639        // SAFETY: plain scalar read through a live handle.
13640        unsafe { ffi::whiteout_m3_M3HitTestShape_get_sizeZ(self.raw.as_ptr()) }
13641    }
13642
13643    pub fn set_size_z(&mut self, value: f32) {
13644        // SAFETY: plain scalar write through a live handle.
13645        unsafe { ffi::whiteout_m3_M3HitTestShape_set_sizeZ(self.raw.as_ptr(), value) }
13646    }
13647}
13648
13649impl Default for HitTestShape {
13650    fn default() -> Self {
13651        Self::new()
13652    }
13653}
13654
13655/// ATVL — Attachment volume (v0, 116 bytes)
13656///
13657/// Like HitTestShape but with two bone indices for attachment-point volumes.
13658pub struct AttachmentVolume {
13659    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AttachmentVolume>,
13660}
13661
13662impl Drop for AttachmentVolume {
13663    fn drop(&mut self) {
13664        // SAFETY: `raw` came from a native constructor and Drop runs once.
13665        unsafe { ffi::whiteout_m3_M3AttachmentVolume_delete(self.raw.as_ptr()) }
13666    }
13667}
13668
13669impl AttachmentVolume {
13670    /// # Safety
13671    /// `raw` must be a live handle this value takes ownership of.
13672    #[allow(dead_code)] // used by whichever methods return this type
13673    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AttachmentVolume) -> Option<Self> {
13674        core::ptr::NonNull::new(raw).map(|raw| AttachmentVolume { raw })
13675    }
13676}
13677
13678// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13679// is deliberately NOT implemented — the C++ types make no documented
13680// guarantee about concurrent use, and claiming one we haven't verified
13681// would be unsound. See `@bind thread_safe` in the plan.
13682unsafe impl Send for AttachmentVolume {}
13683
13684impl core::fmt::Debug for AttachmentVolume {
13685    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13686        f.debug_struct("AttachmentVolume").finish_non_exhaustive()
13687    }
13688}
13689
13690impl AttachmentVolume {
13691    /// # Panics
13692    /// Panics if the native allocation fails.
13693    pub fn new() -> Self {
13694        // SAFETY: the native constructor returns a live handle; a null here
13695        // means the library is unusable.
13696        unsafe {
13697            let raw = ffi::whiteout_m3_M3AttachmentVolume_new();
13698            Self::from_raw(raw).expect("native AttachmentVolume allocation failed")
13699        }
13700    }
13701
13702    /// First bone index
13703    pub fn bone_1(&self) -> u32 {
13704        // SAFETY: plain scalar read through a live handle.
13705        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_bone1(self.raw.as_ptr()) }
13706    }
13707
13708    pub fn set_bone_1(&mut self, value: u32) {
13709        // SAFETY: plain scalar write through a live handle.
13710        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_bone1(self.raw.as_ptr(), value) }
13711    }
13712
13713    /// Second bone index
13714    pub fn bone_2(&self) -> u32 {
13715        // SAFETY: plain scalar read through a live handle.
13716        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_bone2(self.raw.as_ptr()) }
13717    }
13718
13719    pub fn set_bone_2(&mut self, value: u32) {
13720        // SAFETY: plain scalar write through a live handle.
13721        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_bone2(self.raw.as_ptr(), value) }
13722    }
13723
13724    /// Shape type
13725    pub fn shape_type(&self) -> HitTestShapeType {
13726        // SAFETY: scalar read; the discriminant is validated below.
13727        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_shapeType(self.raw.as_ptr()) }
13728            .try_into()
13729            .expect("unknown enum discriminant from the native library")
13730    }
13731
13732    pub fn set_shape_type(&mut self, value: HitTestShapeType) {
13733        // SAFETY: scalar write through a live handle.
13734        unsafe {
13735            ffi::whiteout_m3_M3AttachmentVolume_set_shapeType(self.raw.as_ptr(), value as i32)
13736        }
13737    }
13738
13739    /// Primary bone index
13740    pub fn bone_index(&self) -> u16 {
13741        // SAFETY: plain scalar read through a live handle.
13742        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_boneIndex(self.raw.as_ptr()) }
13743    }
13744
13745    pub fn set_bone_index(&mut self, value: u16) {
13746        // SAFETY: plain scalar write through a live handle.
13747        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_boneIndex(self.raw.as_ptr(), value) }
13748    }
13749
13750    /// Alignment padding
13751    pub fn padding(&self) -> u16 {
13752        // SAFETY: plain scalar read through a live handle.
13753        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_padding(self.raw.as_ptr()) }
13754    }
13755
13756    pub fn set_padding(&mut self, value: u16) {
13757        // SAFETY: plain scalar write through a live handle.
13758        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_padding(self.raw.as_ptr(), value) }
13759    }
13760
13761    /// Mesh vertex positions (VEC3)
13762    /// Zero-copy view of the underlying `std::vector`.
13763    pub fn vertex_positions(&self) -> &[crate::math::Vector3f] {
13764        // SAFETY: `_data`/`_count` describe one contiguous C++
13765        // allocation, borrowed for as long as `self` is.
13766        unsafe {
13767            let n =
13768                ffi::whiteout_m3_M3AttachmentVolume_get_vertexPositions_count(self.raw.as_ptr());
13769            let p = ffi::whiteout_m3_M3AttachmentVolume_get_vertexPositions_data(self.raw.as_ptr())
13770                as *const crate::math::Vector3f;
13771            if p.is_null() || n == 0 {
13772                &[]
13773            } else {
13774                core::slice::from_raw_parts(p, n)
13775            }
13776        }
13777    }
13778
13779    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13780    pub fn vertex_positions_mut(&mut self) -> &mut [crate::math::Vector3f] {
13781        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13782        unsafe {
13783            let n =
13784                ffi::whiteout_m3_M3AttachmentVolume_get_vertexPositions_count(self.raw.as_ptr());
13785            let p = ffi::whiteout_m3_M3AttachmentVolume_get_vertexPositions_data(self.raw.as_ptr())
13786                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
13787            if p.is_null() || n == 0 {
13788                &mut []
13789            } else {
13790                core::slice::from_raw_parts_mut(p, n)
13791            }
13792        }
13793    }
13794
13795    pub fn set_vertex_positions(&mut self, values: &[crate::math::Vector3f]) {
13796        // SAFETY: the native side copies `values` before returning.
13797        unsafe {
13798            ffi::whiteout_m3_M3AttachmentVolume_assign_vertexPositions(
13799                self.raw.as_ptr(),
13800                values.as_ptr() as *const _,
13801                values.len(),
13802            )
13803        }
13804    }
13805
13806    pub fn resize_vertex_positions(&mut self, count: usize) {
13807        // SAFETY: reallocation is safe here precisely because
13808        // `&mut self` means no slice borrow is outstanding.
13809        unsafe {
13810            ffi::whiteout_m3_M3AttachmentVolume_resize_vertexPositions(self.raw.as_ptr(), count)
13811        }
13812    }
13813
13814    /// Mesh triangle indices (U16_)
13815    /// Zero-copy view of the underlying `std::vector`.
13816    pub fn face_indices(&self) -> &[u16] {
13817        // SAFETY: `_data`/`_count` describe one contiguous C++
13818        // allocation, borrowed for as long as `self` is.
13819        unsafe {
13820            let n = ffi::whiteout_m3_M3AttachmentVolume_get_faceIndices_count(self.raw.as_ptr());
13821            let p = ffi::whiteout_m3_M3AttachmentVolume_get_faceIndices_data(self.raw.as_ptr());
13822            if p.is_null() || n == 0 {
13823                &[]
13824            } else {
13825                core::slice::from_raw_parts(p, n)
13826            }
13827        }
13828    }
13829
13830    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13831    pub fn face_indices_mut(&mut self) -> &mut [u16] {
13832        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13833        unsafe {
13834            let n = ffi::whiteout_m3_M3AttachmentVolume_get_faceIndices_count(self.raw.as_ptr());
13835            let p = ffi::whiteout_m3_M3AttachmentVolume_get_faceIndices_data(self.raw.as_ptr())
13836                as *mut u16;
13837            if p.is_null() || n == 0 {
13838                &mut []
13839            } else {
13840                core::slice::from_raw_parts_mut(p, n)
13841            }
13842        }
13843    }
13844
13845    pub fn set_face_indices(&mut self, values: &[u16]) {
13846        // SAFETY: the native side copies `values` before returning.
13847        unsafe {
13848            ffi::whiteout_m3_M3AttachmentVolume_assign_faceIndices(
13849                self.raw.as_ptr(),
13850                values.as_ptr() as *const _,
13851                values.len(),
13852            )
13853        }
13854    }
13855
13856    pub fn resize_face_indices(&mut self, count: usize) {
13857        // SAFETY: reallocation is safe here precisely because
13858        // `&mut self` means no slice borrow is outstanding.
13859        unsafe { ffi::whiteout_m3_M3AttachmentVolume_resize_faceIndices(self.raw.as_ptr(), count) }
13860    }
13861
13862    /// X dimension
13863    pub fn size_x(&self) -> f32 {
13864        // SAFETY: plain scalar read through a live handle.
13865        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_sizeX(self.raw.as_ptr()) }
13866    }
13867
13868    pub fn set_size_x(&mut self, value: f32) {
13869        // SAFETY: plain scalar write through a live handle.
13870        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_sizeX(self.raw.as_ptr(), value) }
13871    }
13872
13873    /// Y dimension
13874    pub fn size_y(&self) -> f32 {
13875        // SAFETY: plain scalar read through a live handle.
13876        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_sizeY(self.raw.as_ptr()) }
13877    }
13878
13879    pub fn set_size_y(&mut self, value: f32) {
13880        // SAFETY: plain scalar write through a live handle.
13881        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_sizeY(self.raw.as_ptr(), value) }
13882    }
13883
13884    /// Z dimension
13885    pub fn size_z(&self) -> f32 {
13886        // SAFETY: plain scalar read through a live handle.
13887        unsafe { ffi::whiteout_m3_M3AttachmentVolume_get_sizeZ(self.raw.as_ptr()) }
13888    }
13889
13890    pub fn set_size_z(&mut self, value: f32) {
13891        // SAFETY: plain scalar write through a live handle.
13892        unsafe { ffi::whiteout_m3_M3AttachmentVolume_set_sizeZ(self.raw.as_ptr(), value) }
13893    }
13894}
13895
13896impl Default for AttachmentVolume {
13897    fn default() -> Self {
13898        Self::new()
13899    }
13900}
13901
13902/// TRGD — Trigger data (v0, 24 bytes)
13903///
13904/// Named trigger with associated data indices for gameplay events.
13905pub struct TriggerData {
13906    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3TriggerData>,
13907}
13908
13909impl Drop for TriggerData {
13910    fn drop(&mut self) {
13911        // SAFETY: `raw` came from a native constructor and Drop runs once.
13912        unsafe { ffi::whiteout_m3_M3TriggerData_delete(self.raw.as_ptr()) }
13913    }
13914}
13915
13916impl TriggerData {
13917    /// # Safety
13918    /// `raw` must be a live handle this value takes ownership of.
13919    #[allow(dead_code)] // used by whichever methods return this type
13920    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3TriggerData) -> Option<Self> {
13921        core::ptr::NonNull::new(raw).map(|raw| TriggerData { raw })
13922    }
13923}
13924
13925// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13926// is deliberately NOT implemented — the C++ types make no documented
13927// guarantee about concurrent use, and claiming one we haven't verified
13928// would be unsound. See `@bind thread_safe` in the plan.
13929unsafe impl Send for TriggerData {}
13930
13931impl core::fmt::Debug for TriggerData {
13932    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13933        f.debug_struct("TriggerData").finish_non_exhaustive()
13934    }
13935}
13936
13937impl TriggerData {
13938    /// # Panics
13939    /// Panics if the native allocation fails.
13940    pub fn new() -> Self {
13941        // SAFETY: the native constructor returns a live handle; a null here
13942        // means the library is unusable.
13943        unsafe {
13944            let raw = ffi::whiteout_m3_M3TriggerData_new();
13945            Self::from_raw(raw).expect("native TriggerData allocation failed")
13946        }
13947    }
13948
13949    /// Data index array (U32_)
13950    /// Zero-copy view of the underlying `std::vector`.
13951    pub fn data_indices(&self) -> &[u32] {
13952        // SAFETY: `_data`/`_count` describe one contiguous C++
13953        // allocation, borrowed for as long as `self` is.
13954        unsafe {
13955            let n = ffi::whiteout_m3_M3TriggerData_get_dataIndices_count(self.raw.as_ptr());
13956            let p = ffi::whiteout_m3_M3TriggerData_get_dataIndices_data(self.raw.as_ptr());
13957            if p.is_null() || n == 0 {
13958                &[]
13959            } else {
13960                core::slice::from_raw_parts(p, n)
13961            }
13962        }
13963    }
13964
13965    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
13966    pub fn data_indices_mut(&mut self) -> &mut [u32] {
13967        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
13968        unsafe {
13969            let n = ffi::whiteout_m3_M3TriggerData_get_dataIndices_count(self.raw.as_ptr());
13970            let p =
13971                ffi::whiteout_m3_M3TriggerData_get_dataIndices_data(self.raw.as_ptr()) as *mut u32;
13972            if p.is_null() || n == 0 {
13973                &mut []
13974            } else {
13975                core::slice::from_raw_parts_mut(p, n)
13976            }
13977        }
13978    }
13979
13980    pub fn set_data_indices(&mut self, values: &[u32]) {
13981        // SAFETY: the native side copies `values` before returning.
13982        unsafe {
13983            ffi::whiteout_m3_M3TriggerData_assign_dataIndices(
13984                self.raw.as_ptr(),
13985                values.as_ptr() as *const _,
13986                values.len(),
13987            )
13988        }
13989    }
13990
13991    pub fn resize_data_indices(&mut self, count: usize) {
13992        // SAFETY: reallocation is safe here precisely because
13993        // `&mut self` means no slice borrow is outstanding.
13994        unsafe { ffi::whiteout_m3_M3TriggerData_resize_dataIndices(self.raw.as_ptr(), count) }
13995    }
13996
13997    /// Trigger name (`Ref<CHAR>`)
13998    pub fn name(&self) -> String {
13999        // SAFETY: the native side hands over an owned CString.
14000        unsafe {
14001            crate::support::take_string(ffi::whiteout_m3_M3TriggerData_get_name(self.raw.as_ptr()))
14002        }
14003    }
14004
14005    pub fn set_name(&mut self, value: &str) {
14006        let value = std::ffi::CString::new(value).unwrap_or_default();
14007        // SAFETY: the pointer outlives the call.
14008        unsafe { ffi::whiteout_m3_M3TriggerData_set_name(self.raw.as_ptr(), value.as_ptr()) }
14009    }
14010}
14011
14012impl Default for TriggerData {
14013    fn default() -> Self {
14014        Self::new()
14015    }
14016}
14017
14018/// PATU — Turret behavior (v0–v4, 152 bytes)
14019///
14020/// Configures turret rotation constraints for a bone with yaw/pitch limits, weights, and an optional main-turret flag.
14021pub struct TurretBehavior {
14022    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3TurretBehavior>,
14023}
14024
14025impl Drop for TurretBehavior {
14026    fn drop(&mut self) {
14027        // SAFETY: `raw` came from a native constructor and Drop runs once.
14028        unsafe { ffi::whiteout_m3_M3TurretBehavior_delete(self.raw.as_ptr()) }
14029    }
14030}
14031
14032impl TurretBehavior {
14033    /// # Safety
14034    /// `raw` must be a live handle this value takes ownership of.
14035    #[allow(dead_code)] // used by whichever methods return this type
14036    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3TurretBehavior) -> Option<Self> {
14037        core::ptr::NonNull::new(raw).map(|raw| TurretBehavior { raw })
14038    }
14039}
14040
14041// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14042// is deliberately NOT implemented — the C++ types make no documented
14043// guarantee about concurrent use, and claiming one we haven't verified
14044// would be unsound. See `@bind thread_safe` in the plan.
14045unsafe impl Send for TurretBehavior {}
14046
14047impl core::fmt::Debug for TurretBehavior {
14048    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14049        f.debug_struct("TurretBehavior").finish_non_exhaustive()
14050    }
14051}
14052
14053impl TurretBehavior {
14054    /// # Panics
14055    /// Panics if the native allocation fails.
14056    pub fn new() -> Self {
14057        // SAFETY: the native constructor returns a live handle; a null here
14058        // means the library is unusable.
14059        unsafe {
14060            let raw = ffi::whiteout_m3_M3TurretBehavior_new();
14061            Self::from_raw(raw).expect("native TurretBehavior allocation failed")
14062        }
14063    }
14064
14065    /// Unknown vector 1
14066    pub fn unknown_1(&self) -> crate::math::Vector4f {
14067        // SAFETY: the getter returns an interior pointer to a
14068        // layout-identical POD; we copy it out immediately.
14069        unsafe {
14070            *(ffi::whiteout_m3_M3TurretBehavior_get_unknown1(self.raw.as_ptr())
14071                as *const crate::math::Vector4f)
14072        }
14073    }
14074
14075    pub fn set_unknown_1(&mut self, value: crate::math::Vector4f) {
14076        // SAFETY: as above, in the other direction.
14077        unsafe {
14078            ffi::whiteout_m3_M3TurretBehavior_set_unknown1(
14079                self.raw.as_ptr(),
14080                &value as *const crate::math::Vector4f as *const _,
14081            )
14082        }
14083    }
14084
14085    /// Unknown vector 2
14086    pub fn unknown_2(&self) -> crate::math::Vector4f {
14087        // SAFETY: the getter returns an interior pointer to a
14088        // layout-identical POD; we copy it out immediately.
14089        unsafe {
14090            *(ffi::whiteout_m3_M3TurretBehavior_get_unknown2(self.raw.as_ptr())
14091                as *const crate::math::Vector4f)
14092        }
14093    }
14094
14095    pub fn set_unknown_2(&mut self, value: crate::math::Vector4f) {
14096        // SAFETY: as above, in the other direction.
14097        unsafe {
14098            ffi::whiteout_m3_M3TurretBehavior_set_unknown2(
14099                self.raw.as_ptr(),
14100                &value as *const crate::math::Vector4f as *const _,
14101            )
14102        }
14103    }
14104
14105    /// Index into BONE array
14106    pub fn bone_index(&self) -> u16 {
14107        // SAFETY: plain scalar read through a live handle.
14108        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_boneIndex(self.raw.as_ptr()) }
14109    }
14110
14111    pub fn set_bone_index(&mut self, value: u16) {
14112        // SAFETY: plain scalar write through a live handle.
14113        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_boneIndex(self.raw.as_ptr(), value) }
14114    }
14115
14116    /// Non-zero if this is the main turret
14117    pub fn use_as_main_turret(&self) -> u8 {
14118        // SAFETY: plain scalar read through a live handle.
14119        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_useAsMainTurret(self.raw.as_ptr()) }
14120    }
14121
14122    pub fn set_use_as_main_turret(&mut self, value: u8) {
14123        // SAFETY: plain scalar write through a live handle.
14124        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_useAsMainTurret(self.raw.as_ptr(), value) }
14125    }
14126
14127    /// Turret group identifier
14128    pub fn turret_group_id(&self) -> u8 {
14129        // SAFETY: plain scalar read through a live handle.
14130        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_turretGroupId(self.raw.as_ptr()) }
14131    }
14132
14133    pub fn set_turret_group_id(&mut self, value: u8) {
14134        // SAFETY: plain scalar write through a live handle.
14135        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_turretGroupId(self.raw.as_ptr(), value) }
14136    }
14137
14138    /// Enable yaw limits
14139    pub fn yaw_limited(&self) -> u32 {
14140        // SAFETY: plain scalar read through a live handle.
14141        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_yawLimited(self.raw.as_ptr()) }
14142    }
14143
14144    pub fn set_yaw_limited(&mut self, value: u32) {
14145        // SAFETY: plain scalar write through a live handle.
14146        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_yawLimited(self.raw.as_ptr(), value) }
14147    }
14148
14149    /// Minimum yaw angle (radians)
14150    pub fn yaw_min(&self) -> f32 {
14151        // SAFETY: plain scalar read through a live handle.
14152        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_yawMin(self.raw.as_ptr()) }
14153    }
14154
14155    pub fn set_yaw_min(&mut self, value: f32) {
14156        // SAFETY: plain scalar write through a live handle.
14157        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_yawMin(self.raw.as_ptr(), value) }
14158    }
14159
14160    /// Maximum yaw angle (radians)
14161    pub fn yaw_max(&self) -> f32 {
14162        // SAFETY: plain scalar read through a live handle.
14163        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_yawMax(self.raw.as_ptr()) }
14164    }
14165
14166    pub fn set_yaw_max(&mut self, value: f32) {
14167        // SAFETY: plain scalar write through a live handle.
14168        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_yawMax(self.raw.as_ptr(), value) }
14169    }
14170
14171    /// Yaw rotation weight
14172    pub fn yaw_weight(&self) -> f32 {
14173        // SAFETY: plain scalar read through a live handle.
14174        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_yawWeight(self.raw.as_ptr()) }
14175    }
14176
14177    pub fn set_yaw_weight(&mut self, value: f32) {
14178        // SAFETY: plain scalar write through a live handle.
14179        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_yawWeight(self.raw.as_ptr(), value) }
14180    }
14181
14182    /// Enable pitch limits
14183    pub fn pitch_limited(&self) -> u32 {
14184        // SAFETY: plain scalar read through a live handle.
14185        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_pitchLimited(self.raw.as_ptr()) }
14186    }
14187
14188    pub fn set_pitch_limited(&mut self, value: u32) {
14189        // SAFETY: plain scalar write through a live handle.
14190        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_pitchLimited(self.raw.as_ptr(), value) }
14191    }
14192
14193    /// Minimum pitch angle (radians)
14194    pub fn pitch_min(&self) -> f32 {
14195        // SAFETY: plain scalar read through a live handle.
14196        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_pitchMin(self.raw.as_ptr()) }
14197    }
14198
14199    pub fn set_pitch_min(&mut self, value: f32) {
14200        // SAFETY: plain scalar write through a live handle.
14201        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_pitchMin(self.raw.as_ptr(), value) }
14202    }
14203
14204    /// Maximum pitch angle (radians)
14205    pub fn pitch_max(&self) -> f32 {
14206        // SAFETY: plain scalar read through a live handle.
14207        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_pitchMax(self.raw.as_ptr()) }
14208    }
14209
14210    pub fn set_pitch_max(&mut self, value: f32) {
14211        // SAFETY: plain scalar write through a live handle.
14212        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_pitchMax(self.raw.as_ptr(), value) }
14213    }
14214
14215    /// Pitch rotation weight
14216    pub fn pitch_weight(&self) -> f32 {
14217        // SAFETY: plain scalar read through a live handle.
14218        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_pitchWeight(self.raw.as_ptr()) }
14219    }
14220
14221    pub fn set_pitch_weight(&mut self, value: f32) {
14222        // SAFETY: plain scalar write through a live handle.
14223        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_pitchWeight(self.raw.as_ptr(), value) }
14224    }
14225
14226    /// Unknown field
14227    pub fn unknown_3(&self) -> f32 {
14228        // SAFETY: plain scalar read through a live handle.
14229        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_unknown3(self.raw.as_ptr()) }
14230    }
14231
14232    pub fn set_unknown_3(&mut self, value: f32) {
14233        // SAFETY: plain scalar write through a live handle.
14234        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_unknown3(self.raw.as_ptr(), value) }
14235    }
14236
14237    /// Unknown field
14238    pub fn unknown_4(&self) -> f32 {
14239        // SAFETY: plain scalar read through a live handle.
14240        unsafe { ffi::whiteout_m3_M3TurretBehavior_get_unknown4(self.raw.as_ptr()) }
14241    }
14242
14243    pub fn set_unknown_4(&mut self, value: f32) {
14244        // SAFETY: plain scalar write through a live handle.
14245        unsafe { ffi::whiteout_m3_M3TurretBehavior_set_unknown4(self.raw.as_ptr(), value) }
14246    }
14247
14248    /// Offset from main bone
14249    pub fn main_bone_offset(&self) -> crate::math::Vector3f {
14250        // SAFETY: the getter returns an interior pointer to a
14251        // layout-identical POD; we copy it out immediately.
14252        unsafe {
14253            *(ffi::whiteout_m3_M3TurretBehavior_get_mainBoneOffset(self.raw.as_ptr())
14254                as *const crate::math::Vector3f)
14255        }
14256    }
14257
14258    pub fn set_main_bone_offset(&mut self, value: crate::math::Vector3f) {
14259        // SAFETY: as above, in the other direction.
14260        unsafe {
14261            ffi::whiteout_m3_M3TurretBehavior_set_mainBoneOffset(
14262                self.raw.as_ptr(),
14263                &value as *const crate::math::Vector3f as *const _,
14264            )
14265        }
14266    }
14267}
14268
14269impl Default for TurretBehavior {
14270    fn default() -> Self {
14271        Self::new()
14272    }
14273}
14274
14275/// BBSC — Billboard behavior (v0, 48 bytes)
14276///
14277/// Turns one bone to face the camera. The only source of billboarding there is: `BoneFlag::Billboard1/2` are set on no bone in the whole corpus.
14278///
14279/// StarCraft II applies these at draw time, per view, from `sub_10290A890` — `CBBSolver::Solve` is a stub — and writes the bone's *local* rotation, so the subtree follows.
14280pub struct BillboardBehavior {
14281    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3BillboardBehavior>,
14282}
14283
14284impl Drop for BillboardBehavior {
14285    fn drop(&mut self) {
14286        // SAFETY: `raw` came from a native constructor and Drop runs once.
14287        unsafe { ffi::whiteout_m3_M3BillboardBehavior_delete(self.raw.as_ptr()) }
14288    }
14289}
14290
14291impl BillboardBehavior {
14292    /// # Safety
14293    /// `raw` must be a live handle this value takes ownership of.
14294    #[allow(dead_code)] // used by whichever methods return this type
14295    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3BillboardBehavior) -> Option<Self> {
14296        core::ptr::NonNull::new(raw).map(|raw| BillboardBehavior { raw })
14297    }
14298}
14299
14300// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14301// is deliberately NOT implemented — the C++ types make no documented
14302// guarantee about concurrent use, and claiming one we haven't verified
14303// would be unsound. See `@bind thread_safe` in the plan.
14304unsafe impl Send for BillboardBehavior {}
14305
14306impl core::fmt::Debug for BillboardBehavior {
14307    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14308        f.debug_struct("BillboardBehavior").finish_non_exhaustive()
14309    }
14310}
14311
14312impl BillboardBehavior {
14313    /// # Panics
14314    /// Panics if the native allocation fails.
14315    pub fn new() -> Self {
14316        // SAFETY: the native constructor returns a live handle; a null here
14317        // means the library is unusable.
14318        unsafe {
14319            let raw = ffi::whiteout_m3_M3BillboardBehavior_new();
14320            Self::from_raw(raw).expect("native BillboardBehavior allocation failed")
14321        }
14322    }
14323
14324    /// Dependent bone indices (U16_). Empty in every shipped record; the engine never reads them
14325    /// Zero-copy view of the underlying `std::vector`.
14326    pub fn dependents(&self) -> &[u16] {
14327        // SAFETY: `_data`/`_count` describe one contiguous C++
14328        // allocation, borrowed for as long as `self` is.
14329        unsafe {
14330            let n = ffi::whiteout_m3_M3BillboardBehavior_get_dependents_count(self.raw.as_ptr());
14331            let p = ffi::whiteout_m3_M3BillboardBehavior_get_dependents_data(self.raw.as_ptr());
14332            if p.is_null() || n == 0 {
14333                &[]
14334            } else {
14335                core::slice::from_raw_parts(p, n)
14336            }
14337        }
14338    }
14339
14340    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14341    pub fn dependents_mut(&mut self) -> &mut [u16] {
14342        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14343        unsafe {
14344            let n = ffi::whiteout_m3_M3BillboardBehavior_get_dependents_count(self.raw.as_ptr());
14345            let p = ffi::whiteout_m3_M3BillboardBehavior_get_dependents_data(self.raw.as_ptr())
14346                as *mut u16;
14347            if p.is_null() || n == 0 {
14348                &mut []
14349            } else {
14350                core::slice::from_raw_parts_mut(p, n)
14351            }
14352        }
14353    }
14354
14355    pub fn set_dependents(&mut self, values: &[u16]) {
14356        // SAFETY: the native side copies `values` before returning.
14357        unsafe {
14358            ffi::whiteout_m3_M3BillboardBehavior_assign_dependents(
14359                self.raw.as_ptr(),
14360                values.as_ptr() as *const _,
14361                values.len(),
14362            )
14363        }
14364    }
14365
14366    pub fn resize_dependents(&mut self, count: usize) {
14367        // SAFETY: reallocation is safe here precisely because
14368        // `&mut self` means no slice borrow is outstanding.
14369        unsafe { ffi::whiteout_m3_M3BillboardBehavior_resize_dependents(self.raw.as_ptr(), count) }
14370    }
14371
14372    /// Index into BONE array
14373    pub fn bone_index(&self) -> u16 {
14374        // SAFETY: plain scalar read through a live handle.
14375        unsafe { ffi::whiteout_m3_M3BillboardBehavior_get_boneIndex(self.raw.as_ptr()) }
14376    }
14377
14378    pub fn set_bone_index(&mut self, value: u16) {
14379        // SAFETY: plain scalar write through a live handle.
14380        unsafe { ffi::whiteout_m3_M3BillboardBehavior_set_boneIndex(self.raw.as_ptr(), value) }
14381    }
14382
14383    /// Which axes may turn — see BillboardType
14384    pub fn billboard_type(&self) -> u8 {
14385        // SAFETY: plain scalar read through a live handle.
14386        unsafe { ffi::whiteout_m3_M3BillboardBehavior_get_billboardType(self.raw.as_ptr()) }
14387    }
14388
14389    pub fn set_billboard_type(&mut self, value: u8) {
14390        // SAFETY: plain scalar write through a live handle.
14391        unsafe { ffi::whiteout_m3_M3BillboardBehavior_set_billboardType(self.raw.as_ptr(), value) }
14392    }
14393
14394    /// Non-zero: aim from this bone at the eye. Zero: aim along the camera's view direction instead, so every such bone shares one orientation
14395    pub fn camera_look_at(&self) -> u8 {
14396        // SAFETY: plain scalar read through a live handle.
14397        unsafe { ffi::whiteout_m3_M3BillboardBehavior_get_cameraLookAt(self.raw.as_ptr()) }
14398    }
14399
14400    pub fn set_camera_look_at(&mut self, value: u8) {
14401        // SAFETY: plain scalar write through a live handle.
14402        unsafe { ffi::whiteout_m3_M3BillboardBehavior_set_cameraLookAt(self.raw.as_ptr(), value) }
14403    }
14404
14405    /// MISNAMED: not a direction. A rotation applied *before* the billboard basis, and only by the axis-locked types 0/1/2
14406    pub fn up(&self) -> crate::math::Quaternion {
14407        // SAFETY: the getter returns an interior pointer to a
14408        // layout-identical POD; we copy it out immediately.
14409        unsafe {
14410            *(ffi::whiteout_m3_M3BillboardBehavior_get_up(self.raw.as_ptr())
14411                as *const crate::math::Quaternion)
14412        }
14413    }
14414
14415    pub fn set_up(&mut self, value: crate::math::Quaternion) {
14416        // SAFETY: as above, in the other direction.
14417        unsafe {
14418            ffi::whiteout_m3_M3BillboardBehavior_set_up(
14419                self.raw.as_ptr(),
14420                &value as *const crate::math::Quaternion as *const _,
14421            )
14422        }
14423    }
14424
14425    /// MISNAMED likewise: the same kind of pre-rotation, taken only by type 6, and only on a bone whose parent is another bone. Types 3/4/5 take neither
14426    pub fn forward(&self) -> crate::math::Quaternion {
14427        // SAFETY: the getter returns an interior pointer to a
14428        // layout-identical POD; we copy it out immediately.
14429        unsafe {
14430            *(ffi::whiteout_m3_M3BillboardBehavior_get_forward(self.raw.as_ptr())
14431                as *const crate::math::Quaternion)
14432        }
14433    }
14434
14435    pub fn set_forward(&mut self, value: crate::math::Quaternion) {
14436        // SAFETY: as above, in the other direction.
14437        unsafe {
14438            ffi::whiteout_m3_M3BillboardBehavior_set_forward(
14439                self.raw.as_ptr(),
14440                &value as *const crate::math::Quaternion as *const _,
14441            )
14442        }
14443    }
14444}
14445
14446impl Default for BillboardBehavior {
14447    fn default() -> Self {
14448        Self::new()
14449    }
14450}
14451
14452/// IKJT — IK joint (v0, 32 bytes)
14453///
14454/// Inverse kinematics joint with raycast up/down range, max speed, and goal threshold for terrain-following or foot-planting.
14455pub struct IKJoint {
14456    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3IKJoint>,
14457}
14458
14459impl Drop for IKJoint {
14460    fn drop(&mut self) {
14461        // SAFETY: `raw` came from a native constructor and Drop runs once.
14462        unsafe { ffi::whiteout_m3_M3IKJoint_delete(self.raw.as_ptr()) }
14463    }
14464}
14465
14466impl IKJoint {
14467    /// # Safety
14468    /// `raw` must be a live handle this value takes ownership of.
14469    #[allow(dead_code)] // used by whichever methods return this type
14470    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3IKJoint) -> Option<Self> {
14471        core::ptr::NonNull::new(raw).map(|raw| IKJoint { raw })
14472    }
14473}
14474
14475// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14476// is deliberately NOT implemented — the C++ types make no documented
14477// guarantee about concurrent use, and claiming one we haven't verified
14478// would be unsound. See `@bind thread_safe` in the plan.
14479unsafe impl Send for IKJoint {}
14480
14481impl core::fmt::Debug for IKJoint {
14482    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14483        f.debug_struct("IKJoint").finish_non_exhaustive()
14484    }
14485}
14486
14487impl IKJoint {
14488    /// # Panics
14489    /// Panics if the native allocation fails.
14490    pub fn new() -> Self {
14491        // SAFETY: the native constructor returns a live handle; a null here
14492        // means the library is unusable.
14493        unsafe {
14494            let raw = ffi::whiteout_m3_M3IKJoint_new();
14495            Self::from_raw(raw).expect("native IKJoint allocation failed")
14496        }
14497    }
14498
14499    /// Dependent bone indices (U16_)
14500    /// Zero-copy view of the underlying `std::vector`.
14501    pub fn dependents(&self) -> &[u16] {
14502        // SAFETY: `_data`/`_count` describe one contiguous C++
14503        // allocation, borrowed for as long as `self` is.
14504        unsafe {
14505            let n = ffi::whiteout_m3_M3IKJoint_get_dependents_count(self.raw.as_ptr());
14506            let p = ffi::whiteout_m3_M3IKJoint_get_dependents_data(self.raw.as_ptr());
14507            if p.is_null() || n == 0 {
14508                &[]
14509            } else {
14510                core::slice::from_raw_parts(p, n)
14511            }
14512        }
14513    }
14514
14515    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14516    pub fn dependents_mut(&mut self) -> &mut [u16] {
14517        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14518        unsafe {
14519            let n = ffi::whiteout_m3_M3IKJoint_get_dependents_count(self.raw.as_ptr());
14520            let p = ffi::whiteout_m3_M3IKJoint_get_dependents_data(self.raw.as_ptr()) as *mut u16;
14521            if p.is_null() || n == 0 {
14522                &mut []
14523            } else {
14524                core::slice::from_raw_parts_mut(p, n)
14525            }
14526        }
14527    }
14528
14529    pub fn set_dependents(&mut self, values: &[u16]) {
14530        // SAFETY: the native side copies `values` before returning.
14531        unsafe {
14532            ffi::whiteout_m3_M3IKJoint_assign_dependents(
14533                self.raw.as_ptr(),
14534                values.as_ptr() as *const _,
14535                values.len(),
14536            )
14537        }
14538    }
14539
14540    pub fn resize_dependents(&mut self, count: usize) {
14541        // SAFETY: reallocation is safe here precisely because
14542        // `&mut self` means no slice borrow is outstanding.
14543        unsafe { ffi::whiteout_m3_M3IKJoint_resize_dependents(self.raw.as_ptr(), count) }
14544    }
14545
14546    /// First bone index
14547    pub fn bone_index_1(&self) -> u16 {
14548        // SAFETY: plain scalar read through a live handle.
14549        unsafe { ffi::whiteout_m3_M3IKJoint_get_boneIndex1(self.raw.as_ptr()) }
14550    }
14551
14552    pub fn set_bone_index_1(&mut self, value: u16) {
14553        // SAFETY: plain scalar write through a live handle.
14554        unsafe { ffi::whiteout_m3_M3IKJoint_set_boneIndex1(self.raw.as_ptr(), value) }
14555    }
14556
14557    /// Second bone index
14558    pub fn bone_index_2(&self) -> u16 {
14559        // SAFETY: plain scalar read through a live handle.
14560        unsafe { ffi::whiteout_m3_M3IKJoint_get_boneIndex2(self.raw.as_ptr()) }
14561    }
14562
14563    pub fn set_bone_index_2(&mut self, value: u16) {
14564        // SAFETY: plain scalar write through a live handle.
14565        unsafe { ffi::whiteout_m3_M3IKJoint_set_boneIndex2(self.raw.as_ptr(), value) }
14566    }
14567
14568    /// Raycast upward distance (positive; shipped 1.5 / 3.0)
14569    pub fn raycast_up(&self) -> f32 {
14570        // SAFETY: plain scalar read through a live handle.
14571        unsafe { ffi::whiteout_m3_M3IKJoint_get_raycastUp(self.raw.as_ptr()) }
14572    }
14573
14574    pub fn set_raycast_up(&mut self, value: f32) {
14575        // SAFETY: plain scalar write through a live handle.
14576        unsafe { ffi::whiteout_m3_M3IKJoint_set_raycastUp(self.raw.as_ptr(), value) }
14577    }
14578
14579    /// Raycast downward offset, SIGNED (shipped -4.0 / -3.0): the surface window is [z + raycastDown, z + raycastUp]
14580    pub fn raycast_down(&self) -> f32 {
14581        // SAFETY: plain scalar read through a live handle.
14582        unsafe { ffi::whiteout_m3_M3IKJoint_get_raycastDown(self.raw.as_ptr()) }
14583    }
14584
14585    pub fn set_raycast_down(&mut self, value: f32) {
14586        // SAFETY: plain scalar write through a live handle.
14587        unsafe { ffi::whiteout_m3_M3IKJoint_set_raycastDown(self.raw.as_ptr(), value) }
14588    }
14589
14590    /// Maximum IK solving speed
14591    pub fn max_speed(&self) -> f32 {
14592        // SAFETY: plain scalar read through a live handle.
14593        unsafe { ffi::whiteout_m3_M3IKJoint_get_maxSpeed(self.raw.as_ptr()) }
14594    }
14595
14596    pub fn set_max_speed(&mut self, value: f32) {
14597        // SAFETY: plain scalar write through a live handle.
14598        unsafe { ffi::whiteout_m3_M3IKJoint_set_maxSpeed(self.raw.as_ptr(), value) }
14599    }
14600
14601    /// Goal distance threshold
14602    pub fn goal_threshold(&self) -> f32 {
14603        // SAFETY: plain scalar read through a live handle.
14604        unsafe { ffi::whiteout_m3_M3IKJoint_get_goalThreshold(self.raw.as_ptr()) }
14605    }
14606
14607    pub fn set_goal_threshold(&mut self, value: f32) {
14608        // SAFETY: plain scalar write through a live handle.
14609        unsafe { ffi::whiteout_m3_M3IKJoint_set_goalThreshold(self.raw.as_ptr(), value) }
14610    }
14611}
14612
14613impl Default for IKJoint {
14614    fn default() -> Self {
14615        Self::new()
14616    }
14617}
14618
14619/// IK2J — Two-joint IK solver (v0, 48 bytes)
14620///
14621/// Classic two-bone IK (e.g. elbow/knee) with hinge axis, angle limits, and search range for target acquisition.
14622pub struct IKTwoJoint {
14623    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3IKTwoJoint>,
14624}
14625
14626impl Drop for IKTwoJoint {
14627    fn drop(&mut self) {
14628        // SAFETY: `raw` came from a native constructor and Drop runs once.
14629        unsafe { ffi::whiteout_m3_M3IKTwoJoint_delete(self.raw.as_ptr()) }
14630    }
14631}
14632
14633impl IKTwoJoint {
14634    /// # Safety
14635    /// `raw` must be a live handle this value takes ownership of.
14636    #[allow(dead_code)] // used by whichever methods return this type
14637    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3IKTwoJoint) -> Option<Self> {
14638        core::ptr::NonNull::new(raw).map(|raw| IKTwoJoint { raw })
14639    }
14640}
14641
14642// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14643// is deliberately NOT implemented — the C++ types make no documented
14644// guarantee about concurrent use, and claiming one we haven't verified
14645// would be unsound. See `@bind thread_safe` in the plan.
14646unsafe impl Send for IKTwoJoint {}
14647
14648impl core::fmt::Debug for IKTwoJoint {
14649    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14650        f.debug_struct("IKTwoJoint").finish_non_exhaustive()
14651    }
14652}
14653
14654impl IKTwoJoint {
14655    /// # Panics
14656    /// Panics if the native allocation fails.
14657    pub fn new() -> Self {
14658        // SAFETY: the native constructor returns a live handle; a null here
14659        // means the library is unusable.
14660        unsafe {
14661            let raw = ffi::whiteout_m3_M3IKTwoJoint_new();
14662            Self::from_raw(raw).expect("native IKTwoJoint allocation failed")
14663        }
14664    }
14665
14666    /// Dependent bone indices (U16_)
14667    /// Zero-copy view of the underlying `std::vector`.
14668    pub fn dependents(&self) -> &[u16] {
14669        // SAFETY: `_data`/`_count` describe one contiguous C++
14670        // allocation, borrowed for as long as `self` is.
14671        unsafe {
14672            let n = ffi::whiteout_m3_M3IKTwoJoint_get_dependents_count(self.raw.as_ptr());
14673            let p = ffi::whiteout_m3_M3IKTwoJoint_get_dependents_data(self.raw.as_ptr());
14674            if p.is_null() || n == 0 {
14675                &[]
14676            } else {
14677                core::slice::from_raw_parts(p, n)
14678            }
14679        }
14680    }
14681
14682    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14683    pub fn dependents_mut(&mut self) -> &mut [u16] {
14684        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14685        unsafe {
14686            let n = ffi::whiteout_m3_M3IKTwoJoint_get_dependents_count(self.raw.as_ptr());
14687            let p =
14688                ffi::whiteout_m3_M3IKTwoJoint_get_dependents_data(self.raw.as_ptr()) as *mut u16;
14689            if p.is_null() || n == 0 {
14690                &mut []
14691            } else {
14692                core::slice::from_raw_parts_mut(p, n)
14693            }
14694        }
14695    }
14696
14697    pub fn set_dependents(&mut self, values: &[u16]) {
14698        // SAFETY: the native side copies `values` before returning.
14699        unsafe {
14700            ffi::whiteout_m3_M3IKTwoJoint_assign_dependents(
14701                self.raw.as_ptr(),
14702                values.as_ptr() as *const _,
14703                values.len(),
14704            )
14705        }
14706    }
14707
14708    pub fn resize_dependents(&mut self, count: usize) {
14709        // SAFETY: reallocation is safe here precisely because
14710        // `&mut self` means no slice borrow is outstanding.
14711        unsafe { ffi::whiteout_m3_M3IKTwoJoint_resize_dependents(self.raw.as_ptr(), count) }
14712    }
14713
14714    /// Base bone (e.g. upper arm/thigh)
14715    pub fn bone_base(&self) -> u16 {
14716        // SAFETY: plain scalar read through a live handle.
14717        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_boneBase(self.raw.as_ptr()) }
14718    }
14719
14720    pub fn set_bone_base(&mut self, value: u16) {
14721        // SAFETY: plain scalar write through a live handle.
14722        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_boneBase(self.raw.as_ptr(), value) }
14723    }
14724
14725    /// Target bone (e.g. forearm/shin)
14726    pub fn bone_target(&self) -> u16 {
14727        // SAFETY: plain scalar read through a live handle.
14728        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_boneTarget(self.raw.as_ptr()) }
14729    }
14730
14731    pub fn set_bone_target(&mut self, value: u16) {
14732        // SAFETY: plain scalar write through a live handle.
14733        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_boneTarget(self.raw.as_ptr(), value) }
14734    }
14735
14736    /// End effector bone (e.g. hand/foot)
14737    pub fn bone_end(&self) -> u16 {
14738        // SAFETY: plain scalar read through a live handle.
14739        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_boneEnd(self.raw.as_ptr()) }
14740    }
14741
14742    pub fn set_bone_end(&mut self, value: u16) {
14743        // SAFETY: plain scalar write through a live handle.
14744        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_boneEnd(self.raw.as_ptr(), value) }
14745    }
14746
14747    /// Alignment padding
14748    pub fn padding(&self) -> u16 {
14749        // SAFETY: plain scalar read through a live handle.
14750        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_padding(self.raw.as_ptr()) }
14751    }
14752
14753    pub fn set_padding(&mut self, value: u16) {
14754        // SAFETY: plain scalar write through a live handle.
14755        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_padding(self.raw.as_ptr(), value) }
14756    }
14757
14758    /// Hinge rotation axis
14759    pub fn hinge_axis(&self) -> crate::math::Vector3f {
14760        // SAFETY: the getter returns an interior pointer to a
14761        // layout-identical POD; we copy it out immediately.
14762        unsafe {
14763            *(ffi::whiteout_m3_M3IKTwoJoint_get_hingeAxis(self.raw.as_ptr())
14764                as *const crate::math::Vector3f)
14765        }
14766    }
14767
14768    pub fn set_hinge_axis(&mut self, value: crate::math::Vector3f) {
14769        // SAFETY: as above, in the other direction.
14770        unsafe {
14771            ffi::whiteout_m3_M3IKTwoJoint_set_hingeAxis(
14772                self.raw.as_ptr(),
14773                &value as *const crate::math::Vector3f as *const _,
14774            )
14775        }
14776    }
14777
14778    /// Maximum inner angle
14779    pub fn max_angle_inner(&self) -> f32 {
14780        // SAFETY: plain scalar read through a live handle.
14781        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_maxAngleInner(self.raw.as_ptr()) }
14782    }
14783
14784    pub fn set_max_angle_inner(&mut self, value: f32) {
14785        // SAFETY: plain scalar write through a live handle.
14786        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_maxAngleInner(self.raw.as_ptr(), value) }
14787    }
14788
14789    /// Maximum outer angle
14790    pub fn max_angle_outer(&self) -> f32 {
14791        // SAFETY: plain scalar read through a live handle.
14792        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_maxAngleOuter(self.raw.as_ptr()) }
14793    }
14794
14795    pub fn set_max_angle_outer(&mut self, value: f32) {
14796        // SAFETY: plain scalar write through a live handle.
14797        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_maxAngleOuter(self.raw.as_ptr(), value) }
14798    }
14799
14800    /// Search range upward
14801    pub fn search_up(&self) -> f32 {
14802        // SAFETY: plain scalar read through a live handle.
14803        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_searchUp(self.raw.as_ptr()) }
14804    }
14805
14806    pub fn set_search_up(&mut self, value: f32) {
14807        // SAFETY: plain scalar write through a live handle.
14808        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_searchUp(self.raw.as_ptr(), value) }
14809    }
14810
14811    /// Search range downward
14812    pub fn search_down(&self) -> f32 {
14813        // SAFETY: plain scalar read through a live handle.
14814        unsafe { ffi::whiteout_m3_M3IKTwoJoint_get_searchDown(self.raw.as_ptr()) }
14815    }
14816
14817    pub fn set_search_down(&mut self, value: f32) {
14818        // SAFETY: plain scalar write through a live handle.
14819        unsafe { ffi::whiteout_m3_M3IKTwoJoint_set_searchDown(self.raw.as_ptr(), value) }
14820    }
14821}
14822
14823impl Default for IKTwoJoint {
14824    fn default() -> Self {
14825        Self::new()
14826    }
14827}
14828
14829/// IKCC — CCD IK solver (v0, 24 bytes)
14830///
14831/// Cyclic Coordinate Descent IK solver with base/target bones and vertical search range.
14832pub struct IKCCD {
14833    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3IKCCD>,
14834}
14835
14836impl Drop for IKCCD {
14837    fn drop(&mut self) {
14838        // SAFETY: `raw` came from a native constructor and Drop runs once.
14839        unsafe { ffi::whiteout_m3_M3IKCCD_delete(self.raw.as_ptr()) }
14840    }
14841}
14842
14843impl IKCCD {
14844    /// # Safety
14845    /// `raw` must be a live handle this value takes ownership of.
14846    #[allow(dead_code)] // used by whichever methods return this type
14847    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3IKCCD) -> Option<Self> {
14848        core::ptr::NonNull::new(raw).map(|raw| IKCCD { raw })
14849    }
14850}
14851
14852// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14853// is deliberately NOT implemented — the C++ types make no documented
14854// guarantee about concurrent use, and claiming one we haven't verified
14855// would be unsound. See `@bind thread_safe` in the plan.
14856unsafe impl Send for IKCCD {}
14857
14858impl core::fmt::Debug for IKCCD {
14859    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14860        f.debug_struct("IKCCD").finish_non_exhaustive()
14861    }
14862}
14863
14864impl IKCCD {
14865    /// # Panics
14866    /// Panics if the native allocation fails.
14867    pub fn new() -> Self {
14868        // SAFETY: the native constructor returns a live handle; a null here
14869        // means the library is unusable.
14870        unsafe {
14871            let raw = ffi::whiteout_m3_M3IKCCD_new();
14872            Self::from_raw(raw).expect("native IKCCD allocation failed")
14873        }
14874    }
14875
14876    /// Dependent bone indices (U16_)
14877    /// Zero-copy view of the underlying `std::vector`.
14878    pub fn dependents(&self) -> &[u16] {
14879        // SAFETY: `_data`/`_count` describe one contiguous C++
14880        // allocation, borrowed for as long as `self` is.
14881        unsafe {
14882            let n = ffi::whiteout_m3_M3IKCCD_get_dependents_count(self.raw.as_ptr());
14883            let p = ffi::whiteout_m3_M3IKCCD_get_dependents_data(self.raw.as_ptr());
14884            if p.is_null() || n == 0 {
14885                &[]
14886            } else {
14887                core::slice::from_raw_parts(p, n)
14888            }
14889        }
14890    }
14891
14892    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14893    pub fn dependents_mut(&mut self) -> &mut [u16] {
14894        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14895        unsafe {
14896            let n = ffi::whiteout_m3_M3IKCCD_get_dependents_count(self.raw.as_ptr());
14897            let p = ffi::whiteout_m3_M3IKCCD_get_dependents_data(self.raw.as_ptr()) as *mut u16;
14898            if p.is_null() || n == 0 {
14899                &mut []
14900            } else {
14901                core::slice::from_raw_parts_mut(p, n)
14902            }
14903        }
14904    }
14905
14906    pub fn set_dependents(&mut self, values: &[u16]) {
14907        // SAFETY: the native side copies `values` before returning.
14908        unsafe {
14909            ffi::whiteout_m3_M3IKCCD_assign_dependents(
14910                self.raw.as_ptr(),
14911                values.as_ptr() as *const _,
14912                values.len(),
14913            )
14914        }
14915    }
14916
14917    pub fn resize_dependents(&mut self, count: usize) {
14918        // SAFETY: reallocation is safe here precisely because
14919        // `&mut self` means no slice borrow is outstanding.
14920        unsafe { ffi::whiteout_m3_M3IKCCD_resize_dependents(self.raw.as_ptr(), count) }
14921    }
14922
14923    /// Base bone index
14924    pub fn bone_base(&self) -> u16 {
14925        // SAFETY: plain scalar read through a live handle.
14926        unsafe { ffi::whiteout_m3_M3IKCCD_get_boneBase(self.raw.as_ptr()) }
14927    }
14928
14929    pub fn set_bone_base(&mut self, value: u16) {
14930        // SAFETY: plain scalar write through a live handle.
14931        unsafe { ffi::whiteout_m3_M3IKCCD_set_boneBase(self.raw.as_ptr(), value) }
14932    }
14933
14934    /// Target bone index
14935    pub fn bone_target(&self) -> u16 {
14936        // SAFETY: plain scalar read through a live handle.
14937        unsafe { ffi::whiteout_m3_M3IKCCD_get_boneTarget(self.raw.as_ptr()) }
14938    }
14939
14940    pub fn set_bone_target(&mut self, value: u16) {
14941        // SAFETY: plain scalar write through a live handle.
14942        unsafe { ffi::whiteout_m3_M3IKCCD_set_boneTarget(self.raw.as_ptr(), value) }
14943    }
14944
14945    /// Search range upward
14946    pub fn search_up(&self) -> f32 {
14947        // SAFETY: plain scalar read through a live handle.
14948        unsafe { ffi::whiteout_m3_M3IKCCD_get_searchUp(self.raw.as_ptr()) }
14949    }
14950
14951    pub fn set_search_up(&mut self, value: f32) {
14952        // SAFETY: plain scalar write through a live handle.
14953        unsafe { ffi::whiteout_m3_M3IKCCD_set_searchUp(self.raw.as_ptr(), value) }
14954    }
14955
14956    /// Search range downward
14957    pub fn search_down(&self) -> f32 {
14958        // SAFETY: plain scalar read through a live handle.
14959        unsafe { ffi::whiteout_m3_M3IKCCD_get_searchDown(self.raw.as_ptr()) }
14960    }
14961
14962    pub fn set_search_down(&mut self, value: f32) {
14963        // SAFETY: plain scalar write through a live handle.
14964        unsafe { ffi::whiteout_m3_M3IKCCD_set_searchDown(self.raw.as_ptr(), value) }
14965    }
14966}
14967
14968impl Default for IKCCD {
14969    fn default() -> Self {
14970        Self::new()
14971    }
14972}
14973
14974/// PAOB — One-bone IK solver (v0, 24 bytes)
14975///
14976/// Simple single-bone orientation solver with angle limit and fallback bone.
14977pub struct OneBoneSolver {
14978    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3OneBoneSolver>,
14979}
14980
14981impl Drop for OneBoneSolver {
14982    fn drop(&mut self) {
14983        // SAFETY: `raw` came from a native constructor and Drop runs once.
14984        unsafe { ffi::whiteout_m3_M3OneBoneSolver_delete(self.raw.as_ptr()) }
14985    }
14986}
14987
14988impl OneBoneSolver {
14989    /// # Safety
14990    /// `raw` must be a live handle this value takes ownership of.
14991    #[allow(dead_code)] // used by whichever methods return this type
14992    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3OneBoneSolver) -> Option<Self> {
14993        core::ptr::NonNull::new(raw).map(|raw| OneBoneSolver { raw })
14994    }
14995}
14996
14997// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14998// is deliberately NOT implemented — the C++ types make no documented
14999// guarantee about concurrent use, and claiming one we haven't verified
15000// would be unsound. See `@bind thread_safe` in the plan.
15001unsafe impl Send for OneBoneSolver {}
15002
15003impl core::fmt::Debug for OneBoneSolver {
15004    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15005        f.debug_struct("OneBoneSolver").finish_non_exhaustive()
15006    }
15007}
15008
15009impl OneBoneSolver {
15010    /// # Panics
15011    /// Panics if the native allocation fails.
15012    pub fn new() -> Self {
15013        // SAFETY: the native constructor returns a live handle; a null here
15014        // means the library is unusable.
15015        unsafe {
15016            let raw = ffi::whiteout_m3_M3OneBoneSolver_new();
15017            Self::from_raw(raw).expect("native OneBoneSolver allocation failed")
15018        }
15019    }
15020
15021    /// Dependent bone indices (U16_)
15022    /// Zero-copy view of the underlying `std::vector`.
15023    pub fn dependents(&self) -> &[u16] {
15024        // SAFETY: `_data`/`_count` describe one contiguous C++
15025        // allocation, borrowed for as long as `self` is.
15026        unsafe {
15027            let n = ffi::whiteout_m3_M3OneBoneSolver_get_dependents_count(self.raw.as_ptr());
15028            let p = ffi::whiteout_m3_M3OneBoneSolver_get_dependents_data(self.raw.as_ptr());
15029            if p.is_null() || n == 0 {
15030                &[]
15031            } else {
15032                core::slice::from_raw_parts(p, n)
15033            }
15034        }
15035    }
15036
15037    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
15038    pub fn dependents_mut(&mut self) -> &mut [u16] {
15039        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
15040        unsafe {
15041            let n = ffi::whiteout_m3_M3OneBoneSolver_get_dependents_count(self.raw.as_ptr());
15042            let p =
15043                ffi::whiteout_m3_M3OneBoneSolver_get_dependents_data(self.raw.as_ptr()) as *mut u16;
15044            if p.is_null() || n == 0 {
15045                &mut []
15046            } else {
15047                core::slice::from_raw_parts_mut(p, n)
15048            }
15049        }
15050    }
15051
15052    pub fn set_dependents(&mut self, values: &[u16]) {
15053        // SAFETY: the native side copies `values` before returning.
15054        unsafe {
15055            ffi::whiteout_m3_M3OneBoneSolver_assign_dependents(
15056                self.raw.as_ptr(),
15057                values.as_ptr() as *const _,
15058                values.len(),
15059            )
15060        }
15061    }
15062
15063    pub fn resize_dependents(&mut self, count: usize) {
15064        // SAFETY: reallocation is safe here precisely because
15065        // `&mut self` means no slice borrow is outstanding.
15066        unsafe { ffi::whiteout_m3_M3OneBoneSolver_resize_dependents(self.raw.as_ptr(), count) }
15067    }
15068
15069    /// Primary bone index
15070    pub fn bone(&self) -> u16 {
15071        // SAFETY: plain scalar read through a live handle.
15072        unsafe { ffi::whiteout_m3_M3OneBoneSolver_get_bone(self.raw.as_ptr()) }
15073    }
15074
15075    pub fn set_bone(&mut self, value: u16) {
15076        // SAFETY: plain scalar write through a live handle.
15077        unsafe { ffi::whiteout_m3_M3OneBoneSolver_set_bone(self.raw.as_ptr(), value) }
15078    }
15079
15080    /// Fallback bone index
15081    pub fn bone_fallback(&self) -> u16 {
15082        // SAFETY: plain scalar read through a live handle.
15083        unsafe { ffi::whiteout_m3_M3OneBoneSolver_get_boneFallback(self.raw.as_ptr()) }
15084    }
15085
15086    pub fn set_bone_fallback(&mut self, value: u16) {
15087        // SAFETY: plain scalar write through a live handle.
15088        unsafe { ffi::whiteout_m3_M3OneBoneSolver_set_boneFallback(self.raw.as_ptr(), value) }
15089    }
15090
15091    /// Maximum rotation angle
15092    pub fn max_angle(&self) -> f32 {
15093        // SAFETY: plain scalar read through a live handle.
15094        unsafe { ffi::whiteout_m3_M3OneBoneSolver_get_maxAngle(self.raw.as_ptr()) }
15095    }
15096
15097    pub fn set_max_angle(&mut self, value: f32) {
15098        // SAFETY: plain scalar write through a live handle.
15099        unsafe { ffi::whiteout_m3_M3OneBoneSolver_set_maxAngle(self.raw.as_ptr(), value) }
15100    }
15101}
15102
15103impl Default for OneBoneSolver {
15104    fn default() -> Self {
15105        Self::new()
15106    }
15107}
15108
15109/// SHBX — Shadow box (v0, 64 bytes)
15110///
15111/// Axis-aligned shadow volume defined by a 4×4 transform matrix.
15112pub struct ShadowBox {
15113    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ShadowBox>,
15114}
15115
15116impl Drop for ShadowBox {
15117    fn drop(&mut self) {
15118        // SAFETY: `raw` came from a native constructor and Drop runs once.
15119        unsafe { ffi::whiteout_m3_M3ShadowBox_delete(self.raw.as_ptr()) }
15120    }
15121}
15122
15123impl ShadowBox {
15124    /// # Safety
15125    /// `raw` must be a live handle this value takes ownership of.
15126    #[allow(dead_code)] // used by whichever methods return this type
15127    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ShadowBox) -> Option<Self> {
15128        core::ptr::NonNull::new(raw).map(|raw| ShadowBox { raw })
15129    }
15130}
15131
15132// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15133// is deliberately NOT implemented — the C++ types make no documented
15134// guarantee about concurrent use, and claiming one we haven't verified
15135// would be unsound. See `@bind thread_safe` in the plan.
15136unsafe impl Send for ShadowBox {}
15137
15138impl core::fmt::Debug for ShadowBox {
15139    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15140        f.debug_struct("ShadowBox").finish_non_exhaustive()
15141    }
15142}
15143
15144impl ShadowBox {
15145    /// # Panics
15146    /// Panics if the native allocation fails.
15147    pub fn new() -> Self {
15148        // SAFETY: the native constructor returns a live handle; a null here
15149        // means the library is unusable.
15150        unsafe {
15151            let raw = ffi::whiteout_m3_M3ShadowBox_new();
15152            Self::from_raw(raw).expect("native ShadowBox allocation failed")
15153        }
15154    }
15155}
15156
15157impl Default for ShadowBox {
15158    fn default() -> Self {
15159        Self::new()
15160    }
15161}
15162
15163/// VVOL — View volume (v0, 40 bytes)
15164///
15165/// Animated visibility volume bound to a bone, used for culling decisions.
15166pub struct ViewVolume {
15167    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ViewVolume>,
15168}
15169
15170impl Drop for ViewVolume {
15171    fn drop(&mut self) {
15172        // SAFETY: `raw` came from a native constructor and Drop runs once.
15173        unsafe { ffi::whiteout_m3_M3ViewVolume_delete(self.raw.as_ptr()) }
15174    }
15175}
15176
15177impl ViewVolume {
15178    /// # Safety
15179    /// `raw` must be a live handle this value takes ownership of.
15180    #[allow(dead_code)] // used by whichever methods return this type
15181    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ViewVolume) -> Option<Self> {
15182        core::ptr::NonNull::new(raw).map(|raw| ViewVolume { raw })
15183    }
15184}
15185
15186// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15187// is deliberately NOT implemented — the C++ types make no documented
15188// guarantee about concurrent use, and claiming one we haven't verified
15189// would be unsound. See `@bind thread_safe` in the plan.
15190unsafe impl Send for ViewVolume {}
15191
15192impl core::fmt::Debug for ViewVolume {
15193    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15194        f.debug_struct("ViewVolume").finish_non_exhaustive()
15195    }
15196}
15197
15198impl ViewVolume {
15199    /// # Panics
15200    /// Panics if the native allocation fails.
15201    pub fn new() -> Self {
15202        // SAFETY: the native constructor returns a live handle; a null here
15203        // means the library is unusable.
15204        unsafe {
15205            let raw = ffi::whiteout_m3_M3ViewVolume_new();
15206            Self::from_raw(raw).expect("native ViewVolume allocation failed")
15207        }
15208    }
15209
15210    /// Index into BONE array
15211    pub fn node_index(&self) -> u32 {
15212        // SAFETY: plain scalar read through a live handle.
15213        unsafe { ffi::whiteout_m3_M3ViewVolume_get_nodeIndex(self.raw.as_ptr()) }
15214    }
15215
15216    pub fn set_node_index(&mut self, value: u32) {
15217        // SAFETY: plain scalar write through a live handle.
15218        unsafe { ffi::whiteout_m3_M3ViewVolume_set_nodeIndex(self.raw.as_ptr(), value) }
15219    }
15220
15221    /// Animated half-extents (36 bytes)
15222    /// Borrows the field in place — no copy, no allocation.
15223    pub fn size(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
15224        // SAFETY: an interior pointer into `self`, valid for this
15225        // borrow and never freed by the `Ref`.
15226        unsafe {
15227            crate::support::Ref::new(AnimRefVector3f {
15228                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3ViewVolume_get_size(
15229                    self.raw.as_ptr(),
15230                )),
15231            })
15232        }
15233    }
15234
15235    pub fn size_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
15236        // SAFETY: as above; `&mut self` guarantees exclusivity.
15237        unsafe {
15238            crate::support::RefMut::new(AnimRefVector3f {
15239                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3ViewVolume_get_size(
15240                    self.raw.as_ptr(),
15241                )),
15242            })
15243        }
15244    }
15245}
15246
15247impl Default for ViewVolume {
15248    fn default() -> Self {
15249        Self::new()
15250    }
15251}
15252
15253/// TMD_ — Trailing model (v0–v1, defunct)
15254///
15255/// Legacy trailing model data. Observed in older files but no longer actively used by the engine.
15256pub struct TrailingModel {
15257    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3TrailingModel>,
15258}
15259
15260impl Drop for TrailingModel {
15261    fn drop(&mut self) {
15262        // SAFETY: `raw` came from a native constructor and Drop runs once.
15263        unsafe { ffi::whiteout_m3_M3TrailingModel_delete(self.raw.as_ptr()) }
15264    }
15265}
15266
15267impl TrailingModel {
15268    /// # Safety
15269    /// `raw` must be a live handle this value takes ownership of.
15270    #[allow(dead_code)] // used by whichever methods return this type
15271    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3TrailingModel) -> Option<Self> {
15272        core::ptr::NonNull::new(raw).map(|raw| TrailingModel { raw })
15273    }
15274}
15275
15276// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15277// is deliberately NOT implemented — the C++ types make no documented
15278// guarantee about concurrent use, and claiming one we haven't verified
15279// would be unsound. See `@bind thread_safe` in the plan.
15280unsafe impl Send for TrailingModel {}
15281
15282impl core::fmt::Debug for TrailingModel {
15283    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15284        f.debug_struct("TrailingModel").finish_non_exhaustive()
15285    }
15286}
15287
15288impl TrailingModel {
15289    /// # Panics
15290    /// Panics if the native allocation fails.
15291    pub fn new() -> Self {
15292        // SAFETY: the native constructor returns a live handle; a null here
15293        // means the library is unusable.
15294        unsafe {
15295            let raw = ffi::whiteout_m3_M3TrailingModel_new();
15296            Self::from_raw(raw).expect("native TrailingModel allocation failed")
15297        }
15298    }
15299
15300    /// Control vectors (VEC3)
15301    /// Zero-copy view of the underlying `std::vector`.
15302    pub fn vectors(&self) -> &[crate::math::Vector3f] {
15303        // SAFETY: `_data`/`_count` describe one contiguous C++
15304        // allocation, borrowed for as long as `self` is.
15305        unsafe {
15306            let n = ffi::whiteout_m3_M3TrailingModel_get_vectors_count(self.raw.as_ptr());
15307            let p = ffi::whiteout_m3_M3TrailingModel_get_vectors_data(self.raw.as_ptr())
15308                as *const crate::math::Vector3f;
15309            if p.is_null() || n == 0 {
15310                &[]
15311            } else {
15312                core::slice::from_raw_parts(p, n)
15313            }
15314        }
15315    }
15316
15317    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
15318    pub fn vectors_mut(&mut self) -> &mut [crate::math::Vector3f] {
15319        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
15320        unsafe {
15321            let n = ffi::whiteout_m3_M3TrailingModel_get_vectors_count(self.raw.as_ptr());
15322            let p = ffi::whiteout_m3_M3TrailingModel_get_vectors_data(self.raw.as_ptr())
15323                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
15324            if p.is_null() || n == 0 {
15325                &mut []
15326            } else {
15327                core::slice::from_raw_parts_mut(p, n)
15328            }
15329        }
15330    }
15331
15332    pub fn set_vectors(&mut self, values: &[crate::math::Vector3f]) {
15333        // SAFETY: the native side copies `values` before returning.
15334        unsafe {
15335            ffi::whiteout_m3_M3TrailingModel_assign_vectors(
15336                self.raw.as_ptr(),
15337                values.as_ptr() as *const _,
15338                values.len(),
15339            )
15340        }
15341    }
15342
15343    pub fn resize_vectors(&mut self, count: usize) {
15344        // SAFETY: reallocation is safe here precisely because
15345        // `&mut self` means no slice borrow is outstanding.
15346        unsafe { ffi::whiteout_m3_M3TrailingModel_resize_vectors(self.raw.as_ptr(), count) }
15347    }
15348
15349    /// Parameter 0 (observed: 5.0)
15350    pub fn param_0(&self) -> f32 {
15351        // SAFETY: plain scalar read through a live handle.
15352        unsafe { ffi::whiteout_m3_M3TrailingModel_get_param0(self.raw.as_ptr()) }
15353    }
15354
15355    pub fn set_param_0(&mut self, value: f32) {
15356        // SAFETY: plain scalar write through a live handle.
15357        unsafe { ffi::whiteout_m3_M3TrailingModel_set_param0(self.raw.as_ptr(), value) }
15358    }
15359
15360    /// Parameter 1 (observed: 1.0)
15361    pub fn param_1(&self) -> f32 {
15362        // SAFETY: plain scalar read through a live handle.
15363        unsafe { ffi::whiteout_m3_M3TrailingModel_get_param1(self.raw.as_ptr()) }
15364    }
15365
15366    pub fn set_param_1(&mut self, value: f32) {
15367        // SAFETY: plain scalar write through a live handle.
15368        unsafe { ffi::whiteout_m3_M3TrailingModel_set_param1(self.raw.as_ptr(), value) }
15369    }
15370
15371    /// Animated float 0 (init 0.5)
15372    /// Borrows the field in place — no copy, no allocation.
15373    pub fn anim_float_0(&self) -> crate::support::Ref<'_, AnimRefF32> {
15374        // SAFETY: an interior pointer into `self`, valid for this
15375        // borrow and never freed by the `Ref`.
15376        unsafe {
15377            crate::support::Ref::new(AnimRefF32 {
15378                raw: core::ptr::NonNull::new_unchecked(
15379                    ffi::whiteout_m3_M3TrailingModel_get_animFloat0(self.raw.as_ptr()),
15380                ),
15381            })
15382        }
15383    }
15384
15385    pub fn anim_float_0_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15386        // SAFETY: as above; `&mut self` guarantees exclusivity.
15387        unsafe {
15388            crate::support::RefMut::new(AnimRefF32 {
15389                raw: core::ptr::NonNull::new_unchecked(
15390                    ffi::whiteout_m3_M3TrailingModel_get_animFloat0(self.raw.as_ptr()),
15391                ),
15392            })
15393        }
15394    }
15395
15396    /// Animated float 1 (init 1.0)
15397    /// Borrows the field in place — no copy, no allocation.
15398    pub fn anim_float_1(&self) -> crate::support::Ref<'_, AnimRefF32> {
15399        // SAFETY: an interior pointer into `self`, valid for this
15400        // borrow and never freed by the `Ref`.
15401        unsafe {
15402            crate::support::Ref::new(AnimRefF32 {
15403                raw: core::ptr::NonNull::new_unchecked(
15404                    ffi::whiteout_m3_M3TrailingModel_get_animFloat1(self.raw.as_ptr()),
15405                ),
15406            })
15407        }
15408    }
15409
15410    pub fn anim_float_1_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15411        // SAFETY: as above; `&mut self` guarantees exclusivity.
15412        unsafe {
15413            crate::support::RefMut::new(AnimRefF32 {
15414                raw: core::ptr::NonNull::new_unchecked(
15415                    ffi::whiteout_m3_M3TrailingModel_get_animFloat1(self.raw.as_ptr()),
15416                ),
15417            })
15418        }
15419    }
15420
15421    /// Flag (observed: 1)
15422    pub fn flag(&self) -> u32 {
15423        // SAFETY: plain scalar read through a live handle.
15424        unsafe { ffi::whiteout_m3_M3TrailingModel_get_flag(self.raw.as_ptr()) }
15425    }
15426
15427    pub fn set_flag(&mut self, value: u32) {
15428        // SAFETY: plain scalar write through a live handle.
15429        unsafe { ffi::whiteout_m3_M3TrailingModel_set_flag(self.raw.as_ptr(), value) }
15430    }
15431
15432    /// Reserved
15433    pub fn reserved_0(&self) -> u32 {
15434        // SAFETY: plain scalar read through a live handle.
15435        unsafe { ffi::whiteout_m3_M3TrailingModel_get_reserved0(self.raw.as_ptr()) }
15436    }
15437
15438    pub fn set_reserved_0(&mut self, value: u32) {
15439        // SAFETY: plain scalar write through a live handle.
15440        unsafe { ffi::whiteout_m3_M3TrailingModel_set_reserved0(self.raw.as_ptr(), value) }
15441    }
15442
15443    /// Reserved
15444    pub fn reserved_1(&self) -> u32 {
15445        // SAFETY: plain scalar read through a live handle.
15446        unsafe { ffi::whiteout_m3_M3TrailingModel_get_reserved1(self.raw.as_ptr()) }
15447    }
15448
15449    pub fn set_reserved_1(&mut self, value: u32) {
15450        // SAFETY: plain scalar write through a live handle.
15451        unsafe { ffi::whiteout_m3_M3TrailingModel_set_reserved1(self.raw.as_ptr(), value) }
15452    }
15453}
15454
15455impl Default for TrailingModel {
15456    fn default() -> Self {
15457        Self::new()
15458    }
15459}
15460
15461/// FOR_ — Force field (v0–v2, 104 bytes)
15462///
15463/// Applies radial, wind, or explosion forces to particles and ribbons within an influence volume shape (sphere, cylinder, box, hemisphere).
15464pub struct Force {
15465    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Force>,
15466}
15467
15468impl Drop for Force {
15469    fn drop(&mut self) {
15470        // SAFETY: `raw` came from a native constructor and Drop runs once.
15471        unsafe { ffi::whiteout_m3_M3Force_delete(self.raw.as_ptr()) }
15472    }
15473}
15474
15475impl Force {
15476    /// # Safety
15477    /// `raw` must be a live handle this value takes ownership of.
15478    #[allow(dead_code)] // used by whichever methods return this type
15479    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Force) -> Option<Self> {
15480        core::ptr::NonNull::new(raw).map(|raw| Force { raw })
15481    }
15482}
15483
15484// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15485// is deliberately NOT implemented — the C++ types make no documented
15486// guarantee about concurrent use, and claiming one we haven't verified
15487// would be unsound. See `@bind thread_safe` in the plan.
15488unsafe impl Send for Force {}
15489
15490impl core::fmt::Debug for Force {
15491    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15492        f.debug_struct("Force").finish_non_exhaustive()
15493    }
15494}
15495
15496impl Force {
15497    /// # Panics
15498    /// Panics if the native allocation fails.
15499    pub fn new() -> Self {
15500        // SAFETY: the native constructor returns a live handle; a null here
15501        // means the library is unusable.
15502        unsafe {
15503            let raw = ffi::whiteout_m3_M3Force_new();
15504            Self::from_raw(raw).expect("native Force allocation failed")
15505        }
15506    }
15507
15508    /// Force influence type (radial/wind/explosion)
15509    pub fn force_type(&self) -> ForceType {
15510        // SAFETY: scalar read; the discriminant is validated below.
15511        unsafe { ffi::whiteout_m3_M3Force_get_forceType(self.raw.as_ptr()) }
15512            .try_into()
15513            .expect("unknown enum discriminant from the native library")
15514    }
15515
15516    pub fn set_force_type(&mut self, value: ForceType) {
15517        // SAFETY: scalar write through a live handle.
15518        unsafe { ffi::whiteout_m3_M3Force_set_forceType(self.raw.as_ptr(), value as i32) }
15519    }
15520
15521    /// Influence volume shape
15522    pub fn force_shape(&self) -> ForceShape {
15523        // SAFETY: scalar read; the discriminant is validated below.
15524        unsafe { ffi::whiteout_m3_M3Force_get_forceShape(self.raw.as_ptr()) }
15525            .try_into()
15526            .expect("unknown enum discriminant from the native library")
15527    }
15528
15529    pub fn set_force_shape(&mut self, value: ForceShape) {
15530        // SAFETY: scalar write through a live handle.
15531        unsafe { ffi::whiteout_m3_M3Force_set_forceShape(self.raw.as_ptr(), value as i32) }
15532    }
15533
15534    /// Unknown field
15535    pub fn unknown(&self) -> u32 {
15536        // SAFETY: plain scalar read through a live handle.
15537        unsafe { ffi::whiteout_m3_M3Force_get_unknown(self.raw.as_ptr()) }
15538    }
15539
15540    pub fn set_unknown(&mut self, value: u32) {
15541        // SAFETY: plain scalar write through a live handle.
15542        unsafe { ffi::whiteout_m3_M3Force_set_unknown(self.raw.as_ptr(), value) }
15543    }
15544
15545    /// Index into BONE array
15546    pub fn bone_index(&self) -> u32 {
15547        // SAFETY: plain scalar read through a live handle.
15548        unsafe { ffi::whiteout_m3_M3Force_get_boneIndex(self.raw.as_ptr()) }
15549    }
15550
15551    pub fn set_bone_index(&mut self, value: u32) {
15552        // SAFETY: plain scalar write through a live handle.
15553        unsafe { ffi::whiteout_m3_M3Force_set_boneIndex(self.raw.as_ptr(), value) }
15554    }
15555
15556    /// Force flags (falloff, height gradient, unbounded)
15557    pub fn flags(&self) -> ForceFlag {
15558        // SAFETY: scalar read; a flag set accepts any bits.
15559        ForceFlag(unsafe { ffi::whiteout_m3_M3Force_get_flags(self.raw.as_ptr()) })
15560    }
15561
15562    pub fn set_flags(&mut self, value: ForceFlag) {
15563        // SAFETY: scalar write through a live handle.
15564        unsafe { ffi::whiteout_m3_M3Force_set_flags(self.raw.as_ptr(), value.0) }
15565    }
15566
15567    /// Local channel bitmask
15568    pub fn local_channels(&self) -> u32 {
15569        // SAFETY: plain scalar read through a live handle.
15570        unsafe { ffi::whiteout_m3_M3Force_get_localChannels(self.raw.as_ptr()) }
15571    }
15572
15573    pub fn set_local_channels(&mut self, value: u32) {
15574        // SAFETY: plain scalar write through a live handle.
15575        unsafe { ffi::whiteout_m3_M3Force_set_localChannels(self.raw.as_ptr(), value) }
15576    }
15577
15578    /// Animated force strength
15579    /// Borrows the field in place — no copy, no allocation.
15580    pub fn strength(&self) -> crate::support::Ref<'_, AnimRefF32> {
15581        // SAFETY: an interior pointer into `self`, valid for this
15582        // borrow and never freed by the `Ref`.
15583        unsafe {
15584            crate::support::Ref::new(AnimRefF32 {
15585                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_strength(
15586                    self.raw.as_ptr(),
15587                )),
15588            })
15589        }
15590    }
15591
15592    pub fn strength_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15593        // SAFETY: as above; `&mut self` guarantees exclusivity.
15594        unsafe {
15595            crate::support::RefMut::new(AnimRefF32 {
15596                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_strength(
15597                    self.raw.as_ptr(),
15598                )),
15599            })
15600        }
15601    }
15602
15603    /// Animated influence width
15604    /// Borrows the field in place — no copy, no allocation.
15605    pub fn width(&self) -> crate::support::Ref<'_, AnimRefF32> {
15606        // SAFETY: an interior pointer into `self`, valid for this
15607        // borrow and never freed by the `Ref`.
15608        unsafe {
15609            crate::support::Ref::new(AnimRefF32 {
15610                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_width(
15611                    self.raw.as_ptr(),
15612                )),
15613            })
15614        }
15615    }
15616
15617    pub fn width_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15618        // SAFETY: as above; `&mut self` guarantees exclusivity.
15619        unsafe {
15620            crate::support::RefMut::new(AnimRefF32 {
15621                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_width(
15622                    self.raw.as_ptr(),
15623                )),
15624            })
15625        }
15626    }
15627
15628    /// Animated influence height
15629    /// Borrows the field in place — no copy, no allocation.
15630    pub fn height(&self) -> crate::support::Ref<'_, AnimRefF32> {
15631        // SAFETY: an interior pointer into `self`, valid for this
15632        // borrow and never freed by the `Ref`.
15633        unsafe {
15634            crate::support::Ref::new(AnimRefF32 {
15635                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_height(
15636                    self.raw.as_ptr(),
15637                )),
15638            })
15639        }
15640    }
15641
15642    pub fn height_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15643        // SAFETY: as above; `&mut self` guarantees exclusivity.
15644        unsafe {
15645            crate::support::RefMut::new(AnimRefF32 {
15646                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_height(
15647                    self.raw.as_ptr(),
15648                )),
15649            })
15650        }
15651    }
15652
15653    /// Animated influence length
15654    /// Borrows the field in place — no copy, no allocation.
15655    pub fn length(&self) -> crate::support::Ref<'_, AnimRefF32> {
15656        // SAFETY: an interior pointer into `self`, valid for this
15657        // borrow and never freed by the `Ref`.
15658        unsafe {
15659            crate::support::Ref::new(AnimRefF32 {
15660                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_length(
15661                    self.raw.as_ptr(),
15662                )),
15663            })
15664        }
15665    }
15666
15667    pub fn length_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15668        // SAFETY: as above; `&mut self` guarantees exclusivity.
15669        unsafe {
15670            crate::support::RefMut::new(AnimRefF32 {
15671                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Force_get_length(
15672                    self.raw.as_ptr(),
15673                )),
15674            })
15675        }
15676    }
15677}
15678
15679impl Default for Force {
15680    fn default() -> Self {
15681        Self::new()
15682    }
15683}
15684
15685/// WRP_ — Warp field (v0–v1, 132 bytes)
15686///
15687/// Warps particle/ribbon trajectories with animated radius, height, and angular/axial/radial strength components.
15688pub struct Warp {
15689    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Warp>,
15690}
15691
15692impl Drop for Warp {
15693    fn drop(&mut self) {
15694        // SAFETY: `raw` came from a native constructor and Drop runs once.
15695        unsafe { ffi::whiteout_m3_M3Warp_delete(self.raw.as_ptr()) }
15696    }
15697}
15698
15699impl Warp {
15700    /// # Safety
15701    /// `raw` must be a live handle this value takes ownership of.
15702    #[allow(dead_code)] // used by whichever methods return this type
15703    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Warp) -> Option<Self> {
15704        core::ptr::NonNull::new(raw).map(|raw| Warp { raw })
15705    }
15706}
15707
15708// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15709// is deliberately NOT implemented — the C++ types make no documented
15710// guarantee about concurrent use, and claiming one we haven't verified
15711// would be unsound. See `@bind thread_safe` in the plan.
15712unsafe impl Send for Warp {}
15713
15714impl core::fmt::Debug for Warp {
15715    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15716        f.debug_struct("Warp").finish_non_exhaustive()
15717    }
15718}
15719
15720impl Warp {
15721    /// # Panics
15722    /// Panics if the native allocation fails.
15723    pub fn new() -> Self {
15724        // SAFETY: the native constructor returns a live handle; a null here
15725        // means the library is unusable.
15726        unsafe {
15727            let raw = ffi::whiteout_m3_M3Warp_new();
15728            Self::from_raw(raw).expect("native Warp allocation failed")
15729        }
15730    }
15731
15732    /// Warp type
15733    pub fn warp_type(&self) -> u32 {
15734        // SAFETY: plain scalar read through a live handle.
15735        unsafe { ffi::whiteout_m3_M3Warp_get_warpType(self.raw.as_ptr()) }
15736    }
15737
15738    pub fn set_warp_type(&mut self, value: u32) {
15739        // SAFETY: plain scalar write through a live handle.
15740        unsafe { ffi::whiteout_m3_M3Warp_set_warpType(self.raw.as_ptr(), value) }
15741    }
15742
15743    /// Index into BONE array
15744    pub fn bone_index(&self) -> u32 {
15745        // SAFETY: plain scalar read through a live handle.
15746        unsafe { ffi::whiteout_m3_M3Warp_get_boneIndex(self.raw.as_ptr()) }
15747    }
15748
15749    pub fn set_bone_index(&mut self, value: u32) {
15750        // SAFETY: plain scalar write through a live handle.
15751        unsafe { ffi::whiteout_m3_M3Warp_set_boneIndex(self.raw.as_ptr(), value) }
15752    }
15753
15754    /// Unknown field
15755    pub fn unknown(&self) -> u32 {
15756        // SAFETY: plain scalar read through a live handle.
15757        unsafe { ffi::whiteout_m3_M3Warp_get_unknown(self.raw.as_ptr()) }
15758    }
15759
15760    pub fn set_unknown(&mut self, value: u32) {
15761        // SAFETY: plain scalar write through a live handle.
15762        unsafe { ffi::whiteout_m3_M3Warp_set_unknown(self.raw.as_ptr(), value) }
15763    }
15764
15765    /// Animated warp radius
15766    /// Borrows the field in place — no copy, no allocation.
15767    pub fn radius(&self) -> crate::support::Ref<'_, AnimRefF32> {
15768        // SAFETY: an interior pointer into `self`, valid for this
15769        // borrow and never freed by the `Ref`.
15770        unsafe {
15771            crate::support::Ref::new(AnimRefF32 {
15772                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_radius(
15773                    self.raw.as_ptr(),
15774                )),
15775            })
15776        }
15777    }
15778
15779    pub fn radius_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15780        // SAFETY: as above; `&mut self` guarantees exclusivity.
15781        unsafe {
15782            crate::support::RefMut::new(AnimRefF32 {
15783                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_radius(
15784                    self.raw.as_ptr(),
15785                )),
15786            })
15787        }
15788    }
15789
15790    /// Animated warp height
15791    /// Borrows the field in place — no copy, no allocation.
15792    pub fn height(&self) -> crate::support::Ref<'_, AnimRefF32> {
15793        // SAFETY: an interior pointer into `self`, valid for this
15794        // borrow and never freed by the `Ref`.
15795        unsafe {
15796            crate::support::Ref::new(AnimRefF32 {
15797                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_height(
15798                    self.raw.as_ptr(),
15799                )),
15800            })
15801        }
15802    }
15803
15804    pub fn height_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15805        // SAFETY: as above; `&mut self` guarantees exclusivity.
15806        unsafe {
15807            crate::support::RefMut::new(AnimRefF32 {
15808                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_height(
15809                    self.raw.as_ptr(),
15810                )),
15811            })
15812        }
15813    }
15814
15815    /// Animated warp strength
15816    /// Borrows the field in place — no copy, no allocation.
15817    pub fn strength(&self) -> crate::support::Ref<'_, AnimRefF32> {
15818        // SAFETY: an interior pointer into `self`, valid for this
15819        // borrow and never freed by the `Ref`.
15820        unsafe {
15821            crate::support::Ref::new(AnimRefF32 {
15822                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_strength(
15823                    self.raw.as_ptr(),
15824                )),
15825            })
15826        }
15827    }
15828
15829    pub fn strength_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15830        // SAFETY: as above; `&mut self` guarantees exclusivity.
15831        unsafe {
15832            crate::support::RefMut::new(AnimRefF32 {
15833                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_strength(
15834                    self.raw.as_ptr(),
15835                )),
15836            })
15837        }
15838    }
15839
15840    /// Animated angular component
15841    /// Borrows the field in place — no copy, no allocation.
15842    pub fn angular(&self) -> crate::support::Ref<'_, AnimRefF32> {
15843        // SAFETY: an interior pointer into `self`, valid for this
15844        // borrow and never freed by the `Ref`.
15845        unsafe {
15846            crate::support::Ref::new(AnimRefF32 {
15847                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_angular(
15848                    self.raw.as_ptr(),
15849                )),
15850            })
15851        }
15852    }
15853
15854    pub fn angular_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15855        // SAFETY: as above; `&mut self` guarantees exclusivity.
15856        unsafe {
15857            crate::support::RefMut::new(AnimRefF32 {
15858                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_angular(
15859                    self.raw.as_ptr(),
15860                )),
15861            })
15862        }
15863    }
15864
15865    /// Animated axial component
15866    /// Borrows the field in place — no copy, no allocation.
15867    pub fn axial(&self) -> crate::support::Ref<'_, AnimRefF32> {
15868        // SAFETY: an interior pointer into `self`, valid for this
15869        // borrow and never freed by the `Ref`.
15870        unsafe {
15871            crate::support::Ref::new(AnimRefF32 {
15872                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_axial(
15873                    self.raw.as_ptr(),
15874                )),
15875            })
15876        }
15877    }
15878
15879    pub fn axial_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15880        // SAFETY: as above; `&mut self` guarantees exclusivity.
15881        unsafe {
15882            crate::support::RefMut::new(AnimRefF32 {
15883                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_axial(
15884                    self.raw.as_ptr(),
15885                )),
15886            })
15887        }
15888    }
15889
15890    /// Animated radial component
15891    /// Borrows the field in place — no copy, no allocation.
15892    pub fn radial(&self) -> crate::support::Ref<'_, AnimRefF32> {
15893        // SAFETY: an interior pointer into `self`, valid for this
15894        // borrow and never freed by the `Ref`.
15895        unsafe {
15896            crate::support::Ref::new(AnimRefF32 {
15897                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_radial(
15898                    self.raw.as_ptr(),
15899                )),
15900            })
15901        }
15902    }
15903
15904    pub fn radial_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
15905        // SAFETY: as above; `&mut self` guarantees exclusivity.
15906        unsafe {
15907            crate::support::RefMut::new(AnimRefF32 {
15908                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Warp_get_radial(
15909                    self.raw.as_ptr(),
15910                )),
15911            })
15912        }
15913    }
15914}
15915
15916impl Default for Warp {
15917    fn default() -> Self {
15918        Self::new()
15919    }
15920}
15921
15922/// DMSE — Convex hull half-edge (v0, 4 bytes)
15923///
15924/// Half-edge connectivity for PHSH convex hull shapes (shapeType = 4). Entries are stored in consecutive twin pairs (forward 0x01 / reverse 0xFF). The nextAroundVertex field chains half-edges into closed per-vertex rings.
15925pub struct ConvexHullHalfEdge {
15926    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ConvexHullHalfEdge>,
15927}
15928
15929impl Drop for ConvexHullHalfEdge {
15930    fn drop(&mut self) {
15931        // SAFETY: `raw` came from a native constructor and Drop runs once.
15932        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_delete(self.raw.as_ptr()) }
15933    }
15934}
15935
15936impl ConvexHullHalfEdge {
15937    /// # Safety
15938    /// `raw` must be a live handle this value takes ownership of.
15939    #[allow(dead_code)] // used by whichever methods return this type
15940    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ConvexHullHalfEdge) -> Option<Self> {
15941        core::ptr::NonNull::new(raw).map(|raw| ConvexHullHalfEdge { raw })
15942    }
15943}
15944
15945// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
15946// is deliberately NOT implemented — the C++ types make no documented
15947// guarantee about concurrent use, and claiming one we haven't verified
15948// would be unsound. See `@bind thread_safe` in the plan.
15949unsafe impl Send for ConvexHullHalfEdge {}
15950
15951impl core::fmt::Debug for ConvexHullHalfEdge {
15952    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
15953        f.debug_struct("ConvexHullHalfEdge").finish_non_exhaustive()
15954    }
15955}
15956
15957impl ConvexHullHalfEdge {
15958    /// # Panics
15959    /// Panics if the native allocation fails.
15960    pub fn new() -> Self {
15961        // SAFETY: the native constructor returns a live handle; a null here
15962        // means the library is unusable.
15963        unsafe {
15964            let raw = ffi::whiteout_m3_M3ConvexHullHalfEdge_new();
15965            Self::from_raw(raw).expect("native ConvexHullHalfEdge allocation failed")
15966        }
15967    }
15968
15969    /// 0x01 = forward, 0xFF = reverse (twin)
15970    pub fn type_(&self) -> u8 {
15971        // SAFETY: plain scalar read through a live handle.
15972        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_get_type(self.raw.as_ptr()) }
15973    }
15974
15975    pub fn set_type_(&mut self, value: u8) {
15976        // SAFETY: plain scalar write through a live handle.
15977        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_set_type(self.raw.as_ptr(), value) }
15978    }
15979
15980    /// Face this half-edge borders
15981    pub fn face_index(&self) -> u8 {
15982        // SAFETY: plain scalar read through a live handle.
15983        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_get_faceIndex(self.raw.as_ptr()) }
15984    }
15985
15986    pub fn set_face_index(&mut self, value: u8) {
15987        // SAFETY: plain scalar write through a live handle.
15988        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_set_faceIndex(self.raw.as_ptr(), value) }
15989    }
15990
15991    /// Target vertex of this half-edge
15992    pub fn vertex_index(&self) -> u8 {
15993        // SAFETY: plain scalar read through a live handle.
15994        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_get_vertexIndex(self.raw.as_ptr()) }
15995    }
15996
15997    pub fn set_vertex_index(&mut self, value: u8) {
15998        // SAFETY: plain scalar write through a live handle.
15999        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_set_vertexIndex(self.raw.as_ptr(), value) }
16000    }
16001
16002    /// Next half-edge around the same vertex
16003    pub fn next_around_vertex(&self) -> u8 {
16004        // SAFETY: plain scalar read through a live handle.
16005        unsafe { ffi::whiteout_m3_M3ConvexHullHalfEdge_get_nextAroundVertex(self.raw.as_ptr()) }
16006    }
16007
16008    pub fn set_next_around_vertex(&mut self, value: u8) {
16009        // SAFETY: plain scalar write through a live handle.
16010        unsafe {
16011            ffi::whiteout_m3_M3ConvexHullHalfEdge_set_nextAroundVertex(self.raw.as_ptr(), value)
16012        }
16013    }
16014}
16015
16016impl Default for ConvexHullHalfEdge {
16017    fn default() -> Self {
16018        Self::new()
16019    }
16020}
16021
16022/// DMMN — Physics mesh BVH node (v0: 12 bytes, v1: 8 bytes)
16023///
16024/// DMMN entries form a linearized k-DOP Bounding Volume Hierarchy (BVH) tree for concave mesh collision. The entry count is always odd: n = 2*n_leaves - 1.
16025///
16026/// **Tree structure** — right-skewed binary tree stored in DFS preorder: - Array layout: (INT_0, LEAF_1), (INT_2, LEAF_3), ..., LEAF_{n-1} - Even indices 0..n-3: internal nodes - Odd indices 1..n-2: leaf nodes - Last index n-1: leaf node - Each internal node 2k: left child = leaf 2k+1, right child = node 2k+2
16027///
16028/// **v0** (Havok-era, 12 bytes per node) — stores only the slab normal direction as a plain Vector3f. No quantized slab bounds are present; the tree topology and bounding-slab directions are identical to v1, but distance culling relies on the runtime computing slab projections against meshBoundsCenter/Extent. Only 3 files in the corpus use v0 (all with PHSH v2).
16029///
16030/// **v1** (Domino physics, 8 bytes per node) — octahedral-encoded normal + quantized slab bounds: - i16 octX, octY: octahedral-mapped slab normal (snorm16 pair) - u16 slabMin, slabMax: quantized bounding-slab distances along the normal - Internal nodes: slabMax != 0; leaf sentinel: slabMax == 0 (except the last node, which may have slabMax != 0 despite being a leaf)
16031///
16032/// **Quantization** (v1, universally confirmed across 468 corpus files): - Per-axis step: tol_i = extent_i / 32767 - Projected step: tol_proj = dot(tolerance, |normal|) - Slab values quantized as: q = round(projection / tol_proj) - Root node slab range approaches [-32767, +32767] (full AABB)
16033///
16034/// Internal nodes use one slab direction; their paired leaf uses a DIFFERENT slab direction, forming a 2-DOP bound per primitive group. Most trees (391/468) use multiple slab normals across internal levels for tighter culling.
16035///
16036/// PHSH meshTreeDepth gives the tree height (longest root-to-leaf path in nodes).
16037pub struct PhysicsMeshBvhNode {
16038    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsMeshBvhNode>,
16039}
16040
16041impl Drop for PhysicsMeshBvhNode {
16042    fn drop(&mut self) {
16043        // SAFETY: `raw` came from a native constructor and Drop runs once.
16044        unsafe { ffi::whiteout_m3_M3PhysicsMeshBvhNode_delete(self.raw.as_ptr()) }
16045    }
16046}
16047
16048impl PhysicsMeshBvhNode {
16049    /// # Safety
16050    /// `raw` must be a live handle this value takes ownership of.
16051    #[allow(dead_code)] // used by whichever methods return this type
16052    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsMeshBvhNode) -> Option<Self> {
16053        core::ptr::NonNull::new(raw).map(|raw| PhysicsMeshBvhNode { raw })
16054    }
16055}
16056
16057// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
16058// is deliberately NOT implemented — the C++ types make no documented
16059// guarantee about concurrent use, and claiming one we haven't verified
16060// would be unsound. See `@bind thread_safe` in the plan.
16061unsafe impl Send for PhysicsMeshBvhNode {}
16062
16063impl core::fmt::Debug for PhysicsMeshBvhNode {
16064    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16065        f.debug_struct("PhysicsMeshBvhNode").finish_non_exhaustive()
16066    }
16067}
16068
16069impl PhysicsMeshBvhNode {
16070    /// # Panics
16071    /// Panics if the native allocation fails.
16072    pub fn new() -> Self {
16073        // SAFETY: the native constructor returns a live handle; a null here
16074        // means the library is unusable.
16075        unsafe {
16076            let raw = ffi::whiteout_m3_M3PhysicsMeshBvhNode_new();
16077            Self::from_raw(raw).expect("native PhysicsMeshBvhNode allocation failed")
16078        }
16079    }
16080}
16081
16082impl Default for PhysicsMeshBvhNode {
16083    fn default() -> Self {
16084        Self::new()
16085    }
16086}
16087
16088/// DMMT — Physics mesh triangle (v0, 28 bytes)
16089pub struct PhysicsMeshTriangle {
16090    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsMeshTriangle>,
16091}
16092
16093impl Drop for PhysicsMeshTriangle {
16094    fn drop(&mut self) {
16095        // SAFETY: `raw` came from a native constructor and Drop runs once.
16096        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_delete(self.raw.as_ptr()) }
16097    }
16098}
16099
16100impl PhysicsMeshTriangle {
16101    /// # Safety
16102    /// `raw` must be a live handle this value takes ownership of.
16103    #[allow(dead_code)] // used by whichever methods return this type
16104    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsMeshTriangle) -> Option<Self> {
16105        core::ptr::NonNull::new(raw).map(|raw| PhysicsMeshTriangle { raw })
16106    }
16107}
16108
16109// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
16110// is deliberately NOT implemented — the C++ types make no documented
16111// guarantee about concurrent use, and claiming one we haven't verified
16112// would be unsound. See `@bind thread_safe` in the plan.
16113unsafe impl Send for PhysicsMeshTriangle {}
16114
16115impl core::fmt::Debug for PhysicsMeshTriangle {
16116    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16117        f.debug_struct("PhysicsMeshTriangle")
16118            .finish_non_exhaustive()
16119    }
16120}
16121
16122impl PhysicsMeshTriangle {
16123    /// # Panics
16124    /// Panics if the native allocation fails.
16125    pub fn new() -> Self {
16126        // SAFETY: the native constructor returns a live handle; a null here
16127        // means the library is unusable.
16128        unsafe {
16129            let raw = ffi::whiteout_m3_M3PhysicsMeshTriangle_new();
16130            Self::from_raw(raw).expect("native PhysicsMeshTriangle allocation failed")
16131        }
16132    }
16133
16134    /// First vertex index
16135    pub fn vertex_index_0(&self) -> u32 {
16136        // SAFETY: plain scalar read through a live handle.
16137        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex0(self.raw.as_ptr()) }
16138    }
16139
16140    pub fn set_vertex_index_0(&mut self, value: u32) {
16141        // SAFETY: plain scalar write through a live handle.
16142        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex0(self.raw.as_ptr(), value) }
16143    }
16144
16145    /// Second vertex index
16146    pub fn vertex_index_1(&self) -> u32 {
16147        // SAFETY: plain scalar read through a live handle.
16148        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex1(self.raw.as_ptr()) }
16149    }
16150
16151    pub fn set_vertex_index_1(&mut self, value: u32) {
16152        // SAFETY: plain scalar write through a live handle.
16153        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex1(self.raw.as_ptr(), value) }
16154    }
16155
16156    /// Third vertex index
16157    pub fn vertex_index_2(&self) -> u32 {
16158        // SAFETY: plain scalar read through a live handle.
16159        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex2(self.raw.as_ptr()) }
16160    }
16161
16162    pub fn set_vertex_index_2(&mut self, value: u32) {
16163        // SAFETY: plain scalar write through a live handle.
16164        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex2(self.raw.as_ptr(), value) }
16165    }
16166
16167    /// First edge index
16168    pub fn edge_index_0(&self) -> u32 {
16169        // SAFETY: plain scalar read through a live handle.
16170        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex0(self.raw.as_ptr()) }
16171    }
16172
16173    pub fn set_edge_index_0(&mut self, value: u32) {
16174        // SAFETY: plain scalar write through a live handle.
16175        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex0(self.raw.as_ptr(), value) }
16176    }
16177
16178    /// Second edge index
16179    pub fn edge_index_1(&self) -> u32 {
16180        // SAFETY: plain scalar read through a live handle.
16181        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex1(self.raw.as_ptr()) }
16182    }
16183
16184    pub fn set_edge_index_1(&mut self, value: u32) {
16185        // SAFETY: plain scalar write through a live handle.
16186        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex1(self.raw.as_ptr(), value) }
16187    }
16188
16189    /// Third edge index
16190    pub fn edge_index_2(&self) -> u32 {
16191        // SAFETY: plain scalar read through a live handle.
16192        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex2(self.raw.as_ptr()) }
16193    }
16194
16195    pub fn set_edge_index_2(&mut self, value: u32) {
16196        // SAFETY: plain scalar write through a live handle.
16197        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex2(self.raw.as_ptr(), value) }
16198    }
16199
16200    /// Reserved
16201    pub fn reserved(&self) -> u16 {
16202        // SAFETY: plain scalar read through a live handle.
16203        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_reserved(self.raw.as_ptr()) }
16204    }
16205
16206    pub fn set_reserved(&mut self, value: u16) {
16207        // SAFETY: plain scalar write through a live handle.
16208        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_reserved(self.raw.as_ptr(), value) }
16209    }
16210
16211    /// Triangle flags
16212    pub fn flags(&self) -> u16 {
16213        // SAFETY: plain scalar read through a live handle.
16214        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_get_flags(self.raw.as_ptr()) }
16215    }
16216
16217    pub fn set_flags(&mut self, value: u16) {
16218        // SAFETY: plain scalar write through a live handle.
16219        unsafe { ffi::whiteout_m3_M3PhysicsMeshTriangle_set_flags(self.raw.as_ptr(), value) }
16220    }
16221}
16222
16223impl Default for PhysicsMeshTriangle {
16224    fn default() -> Self {
16225        Self::new()
16226    }
16227}
16228
16229/// DMME — Physics mesh edge (v0, 20 bytes)
16230pub struct PhysicsMeshEdge {
16231    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsMeshEdge>,
16232}
16233
16234impl Drop for PhysicsMeshEdge {
16235    fn drop(&mut self) {
16236        // SAFETY: `raw` came from a native constructor and Drop runs once.
16237        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_delete(self.raw.as_ptr()) }
16238    }
16239}
16240
16241impl PhysicsMeshEdge {
16242    /// # Safety
16243    /// `raw` must be a live handle this value takes ownership of.
16244    #[allow(dead_code)] // used by whichever methods return this type
16245    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsMeshEdge) -> Option<Self> {
16246        core::ptr::NonNull::new(raw).map(|raw| PhysicsMeshEdge { raw })
16247    }
16248}
16249
16250// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
16251// is deliberately NOT implemented — the C++ types make no documented
16252// guarantee about concurrent use, and claiming one we haven't verified
16253// would be unsound. See `@bind thread_safe` in the plan.
16254unsafe impl Send for PhysicsMeshEdge {}
16255
16256impl core::fmt::Debug for PhysicsMeshEdge {
16257    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16258        f.debug_struct("PhysicsMeshEdge").finish_non_exhaustive()
16259    }
16260}
16261
16262impl PhysicsMeshEdge {
16263    /// # Panics
16264    /// Panics if the native allocation fails.
16265    pub fn new() -> Self {
16266        // SAFETY: the native constructor returns a live handle; a null here
16267        // means the library is unusable.
16268        unsafe {
16269            let raw = ffi::whiteout_m3_M3PhysicsMeshEdge_new();
16270            Self::from_raw(raw).expect("native PhysicsMeshEdge allocation failed")
16271        }
16272    }
16273
16274    /// Edge type
16275    pub fn edge_type(&self) -> u32 {
16276        // SAFETY: plain scalar read through a live handle.
16277        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_get_edgeType(self.raw.as_ptr()) }
16278    }
16279
16280    pub fn set_edge_type(&mut self, value: u32) {
16281        // SAFETY: plain scalar write through a live handle.
16282        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_set_edgeType(self.raw.as_ptr(), value) }
16283    }
16284
16285    /// First vertex index
16286    pub fn vertex_a(&self) -> u32 {
16287        // SAFETY: plain scalar read through a live handle.
16288        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_get_vertexA(self.raw.as_ptr()) }
16289    }
16290
16291    pub fn set_vertex_a(&mut self, value: u32) {
16292        // SAFETY: plain scalar write through a live handle.
16293        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_set_vertexA(self.raw.as_ptr(), value) }
16294    }
16295
16296    /// Second vertex index
16297    pub fn vertex_b(&self) -> u32 {
16298        // SAFETY: plain scalar read through a live handle.
16299        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_get_vertexB(self.raw.as_ptr()) }
16300    }
16301
16302    pub fn set_vertex_b(&mut self, value: u32) {
16303        // SAFETY: plain scalar write through a live handle.
16304        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_set_vertexB(self.raw.as_ptr(), value) }
16305    }
16306
16307    /// First adjacent face
16308    pub fn face_a(&self) -> u32 {
16309        // SAFETY: plain scalar read through a live handle.
16310        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_get_faceA(self.raw.as_ptr()) }
16311    }
16312
16313    pub fn set_face_a(&mut self, value: u32) {
16314        // SAFETY: plain scalar write through a live handle.
16315        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_set_faceA(self.raw.as_ptr(), value) }
16316    }
16317
16318    /// Second adjacent face
16319    pub fn face_b(&self) -> u32 {
16320        // SAFETY: plain scalar read through a live handle.
16321        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_get_faceB(self.raw.as_ptr()) }
16322    }
16323
16324    pub fn set_face_b(&mut self, value: u32) {
16325        // SAFETY: plain scalar write through a live handle.
16326        unsafe { ffi::whiteout_m3_M3PhysicsMeshEdge_set_faceB(self.raw.as_ptr(), value) }
16327    }
16328}
16329
16330impl Default for PhysicsMeshEdge {
16331    fn default() -> Self {
16332        Self::new()
16333    }
16334}
16335
16336/// PHSH — Physics shape (v0–v3, 132/292/300 bytes)
16337///
16338/// The 300-byte v3 layout is a three-part union. Bytes 0–79 are the common header. Bytes 80–103 hold shape dimensions for simple shapes (0–3) or are zero for complex shapes. Bytes 80–183 form the convex hull section (shapeType 4); bytes 184–299 form the mesh section (shapeType 5).
16339///
16340/// v2 shares the v3 layout through the hull section but has a shorter mesh section (292 bytes total): bounds/tolerance, four legacy geometry refs, then a 6-dword tail (unknown, vertexCount, faceCount, 2× unknown, treeDepth) — verified against the SC2 client's version-upgrade copier.
16341pub struct PhysicsShape {
16342    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsShape>,
16343}
16344
16345impl Drop for PhysicsShape {
16346    fn drop(&mut self) {
16347        // SAFETY: `raw` came from a native constructor and Drop runs once.
16348        unsafe { ffi::whiteout_m3_M3PhysicsShape_delete(self.raw.as_ptr()) }
16349    }
16350}
16351
16352impl PhysicsShape {
16353    /// # Safety
16354    /// `raw` must be a live handle this value takes ownership of.
16355    #[allow(dead_code)] // used by whichever methods return this type
16356    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsShape) -> Option<Self> {
16357        core::ptr::NonNull::new(raw).map(|raw| PhysicsShape { raw })
16358    }
16359}
16360
16361// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
16362// is deliberately NOT implemented — the C++ types make no documented
16363// guarantee about concurrent use, and claiming one we haven't verified
16364// would be unsound. See `@bind thread_safe` in the plan.
16365unsafe impl Send for PhysicsShape {}
16366
16367impl core::fmt::Debug for PhysicsShape {
16368    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16369        f.debug_struct("PhysicsShape").finish_non_exhaustive()
16370    }
16371}
16372
16373impl PhysicsShape {
16374    /// # Panics
16375    /// Panics if the native allocation fails.
16376    pub fn new() -> Self {
16377        // SAFETY: the native constructor returns a live handle; a null here
16378        // means the library is unusable.
16379        unsafe {
16380            let raw = ffi::whiteout_m3_M3PhysicsShape_new();
16381            Self::from_raw(raw).expect("native PhysicsShape allocation failed")
16382        }
16383    }
16384
16385    /// Havok convex radius (v1 only, ≈ 0.019685)
16386    pub fn collision_margin(&self) -> f32 {
16387        // SAFETY: plain scalar read through a live handle.
16388        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_collisionMargin(self.raw.as_ptr()) }
16389    }
16390
16391    pub fn set_collision_margin(&mut self, value: f32) {
16392        // SAFETY: plain scalar write through a live handle.
16393        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_collisionMargin(self.raw.as_ptr(), value) }
16394    }
16395
16396    /// Shape type (box/sphere/capsule/cylinder/hull/mesh)
16397    pub fn shape_type(&self) -> PhysicsShapeType {
16398        // SAFETY: scalar read; the discriminant is validated below.
16399        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_shapeType(self.raw.as_ptr()) }
16400            .try_into()
16401            .expect("unknown enum discriminant from the native library")
16402    }
16403
16404    pub fn set_shape_type(&mut self, value: PhysicsShapeType) {
16405        // SAFETY: scalar write through a live handle.
16406        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_shapeType(self.raw.as_ptr(), value as i32) }
16407    }
16408
16409    /// Legacy sizes (v1 only, zero for shapeType 4–5)
16410    pub fn old_sizes(&self) -> crate::math::Vector3f {
16411        // SAFETY: the getter returns an interior pointer to a
16412        // layout-identical POD; we copy it out immediately.
16413        unsafe {
16414            *(ffi::whiteout_m3_M3PhysicsShape_get_oldSizes(self.raw.as_ptr())
16415                as *const crate::math::Vector3f)
16416        }
16417    }
16418
16419    pub fn set_old_sizes(&mut self, value: crate::math::Vector3f) {
16420        // SAFETY: as above, in the other direction.
16421        unsafe {
16422            ffi::whiteout_m3_M3PhysicsShape_set_oldSizes(
16423                self.raw.as_ptr(),
16424                &value as *const crate::math::Vector3f as *const _,
16425            )
16426        }
16427    }
16428
16429    /// Shape dimensions (v2+, zero for complex shapes)
16430    pub fn shape_dimensions(&self) -> crate::math::Vector3f {
16431        // SAFETY: the getter returns an interior pointer to a
16432        // layout-identical POD; we copy it out immediately.
16433        unsafe {
16434            *(ffi::whiteout_m3_M3PhysicsShape_get_shapeDimensions(self.raw.as_ptr())
16435                as *const crate::math::Vector3f)
16436        }
16437    }
16438
16439    pub fn set_shape_dimensions(&mut self, value: crate::math::Vector3f) {
16440        // SAFETY: as above, in the other direction.
16441        unsafe {
16442            ffi::whiteout_m3_M3PhysicsShape_set_shapeDimensions(
16443                self.raw.as_ptr(),
16444                &value as *const crate::math::Vector3f as *const _,
16445            )
16446        }
16447    }
16448
16449    /// Per-face unit normals (VEC3)
16450    /// Zero-copy view of the underlying `std::vector`.
16451    pub fn hull_face_normals(&self) -> &[crate::math::Vector3f] {
16452        // SAFETY: `_data`/`_count` describe one contiguous C++
16453        // allocation, borrowed for as long as `self` is.
16454        unsafe {
16455            let n = ffi::whiteout_m3_M3PhysicsShape_get_hullFaceNormals_count(self.raw.as_ptr());
16456            let p = ffi::whiteout_m3_M3PhysicsShape_get_hullFaceNormals_data(self.raw.as_ptr())
16457                as *const crate::math::Vector3f;
16458            if p.is_null() || n == 0 {
16459                &[]
16460            } else {
16461                core::slice::from_raw_parts(p, n)
16462            }
16463        }
16464    }
16465
16466    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
16467    pub fn hull_face_normals_mut(&mut self) -> &mut [crate::math::Vector3f] {
16468        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
16469        unsafe {
16470            let n = ffi::whiteout_m3_M3PhysicsShape_get_hullFaceNormals_count(self.raw.as_ptr());
16471            let p = ffi::whiteout_m3_M3PhysicsShape_get_hullFaceNormals_data(self.raw.as_ptr())
16472                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
16473            if p.is_null() || n == 0 {
16474                &mut []
16475            } else {
16476                core::slice::from_raw_parts_mut(p, n)
16477            }
16478        }
16479    }
16480
16481    pub fn set_hull_face_normals(&mut self, values: &[crate::math::Vector3f]) {
16482        // SAFETY: the native side copies `values` before returning.
16483        unsafe {
16484            ffi::whiteout_m3_M3PhysicsShape_assign_hullFaceNormals(
16485                self.raw.as_ptr(),
16486                values.as_ptr() as *const _,
16487                values.len(),
16488            )
16489        }
16490    }
16491
16492    pub fn resize_hull_face_normals(&mut self, count: usize) {
16493        // SAFETY: reallocation is safe here precisely because
16494        // `&mut self` means no slice borrow is outstanding.
16495        unsafe { ffi::whiteout_m3_M3PhysicsShape_resize_hullFaceNormals(self.raw.as_ptr(), count) }
16496    }
16497
16498    /// Vertex positions, w=0 (VEC4)
16499    /// Zero-copy view of the underlying `std::vector`.
16500    pub fn hull_vertex_positions(&self) -> &[crate::math::Vector4f] {
16501        // SAFETY: `_data`/`_count` describe one contiguous C++
16502        // allocation, borrowed for as long as `self` is.
16503        unsafe {
16504            let n =
16505                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexPositions_count(self.raw.as_ptr());
16506            let p = ffi::whiteout_m3_M3PhysicsShape_get_hullVertexPositions_data(self.raw.as_ptr())
16507                as *const crate::math::Vector4f;
16508            if p.is_null() || n == 0 {
16509                &[]
16510            } else {
16511                core::slice::from_raw_parts(p, n)
16512            }
16513        }
16514    }
16515
16516    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
16517    pub fn hull_vertex_positions_mut(&mut self) -> &mut [crate::math::Vector4f] {
16518        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
16519        unsafe {
16520            let n =
16521                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexPositions_count(self.raw.as_ptr());
16522            let p = ffi::whiteout_m3_M3PhysicsShape_get_hullVertexPositions_data(self.raw.as_ptr())
16523                as *const crate::math::Vector4f as *mut crate::math::Vector4f;
16524            if p.is_null() || n == 0 {
16525                &mut []
16526            } else {
16527                core::slice::from_raw_parts_mut(p, n)
16528            }
16529        }
16530    }
16531
16532    pub fn set_hull_vertex_positions(&mut self, values: &[crate::math::Vector4f]) {
16533        // SAFETY: the native side copies `values` before returning.
16534        unsafe {
16535            ffi::whiteout_m3_M3PhysicsShape_assign_hullVertexPositions(
16536                self.raw.as_ptr(),
16537                values.as_ptr() as *const _,
16538                values.len(),
16539            )
16540        }
16541    }
16542
16543    pub fn resize_hull_vertex_positions(&mut self, count: usize) {
16544        // SAFETY: reallocation is safe here precisely because
16545        // `&mut self` means no slice borrow is outstanding.
16546        unsafe {
16547            ffi::whiteout_m3_M3PhysicsShape_resize_hullVertexPositions(self.raw.as_ptr(), count)
16548        }
16549    }
16550
16551    /// Half-edge table (DMSE)
16552    pub fn hull_half_edges_len(&self) -> usize {
16553        // SAFETY: scalar read through a live handle.
16554        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullHalfEdges_count(self.raw.as_ptr()) }
16555    }
16556
16557    /// Borrows element `index` in place. `None` when out of range.
16558    pub fn hull_half_edges(
16559        &self,
16560        index: usize,
16561    ) -> Option<crate::support::Ref<'_, ConvexHullHalfEdge>> {
16562        if index >= self.hull_half_edges_len() {
16563            return None;
16564        }
16565        // SAFETY: index checked above; the pointer is interior to `self`.
16566        unsafe {
16567            Some(crate::support::Ref::new(ConvexHullHalfEdge {
16568                raw: core::ptr::NonNull::new_unchecked(
16569                    ffi::whiteout_m3_M3PhysicsShape_get_hullHalfEdges_at(self.raw.as_ptr(), index),
16570                ),
16571            }))
16572        }
16573    }
16574
16575    pub fn hull_half_edges_mut(
16576        &mut self,
16577        index: usize,
16578    ) -> Option<crate::support::RefMut<'_, ConvexHullHalfEdge>> {
16579        if index >= self.hull_half_edges_len() {
16580            return None;
16581        }
16582        // SAFETY: as above; `&mut self` guarantees exclusivity.
16583        unsafe {
16584            Some(crate::support::RefMut::new(ConvexHullHalfEdge {
16585                raw: core::ptr::NonNull::new_unchecked(
16586                    ffi::whiteout_m3_M3PhysicsShape_get_hullHalfEdges_at(self.raw.as_ptr(), index),
16587                ),
16588            }))
16589        }
16590    }
16591
16592    /// Iterate the elements, borrowing each in turn.
16593    pub fn hull_half_edges_iter(
16594        &self,
16595    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ConvexHullHalfEdge>> {
16596        (0..self.hull_half_edges_len())
16597            .map(move |i| self.hull_half_edges(i).expect("index below len"))
16598    }
16599
16600    pub fn resize_hull_half_edges(&mut self, count: usize) {
16601        // SAFETY: exclusive access, so no borrow is outstanding.
16602        unsafe { ffi::whiteout_m3_M3PhysicsShape_resize_hullHalfEdges(self.raw.as_ptr(), count) }
16603    }
16604
16605    /// One face index per vertex (U8__)
16606    /// Zero-copy view of the underlying `std::vector`.
16607    pub fn hull_vertex_face_indices(&self) -> &[u8] {
16608        // SAFETY: `_data`/`_count` describe one contiguous C++
16609        // allocation, borrowed for as long as `self` is.
16610        unsafe {
16611            let n =
16612                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_count(self.raw.as_ptr());
16613            let p =
16614                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_data(self.raw.as_ptr());
16615            if p.is_null() || n == 0 {
16616                &[]
16617            } else {
16618                core::slice::from_raw_parts(p, n)
16619            }
16620        }
16621    }
16622
16623    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
16624    pub fn hull_vertex_face_indices_mut(&mut self) -> &mut [u8] {
16625        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
16626        unsafe {
16627            let n =
16628                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_count(self.raw.as_ptr());
16629            let p =
16630                ffi::whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_data(self.raw.as_ptr())
16631                    as *mut u8;
16632            if p.is_null() || n == 0 {
16633                &mut []
16634            } else {
16635                core::slice::from_raw_parts_mut(p, n)
16636            }
16637        }
16638    }
16639
16640    pub fn set_hull_vertex_face_indices(&mut self, values: &[u8]) {
16641        // SAFETY: the native side copies `values` before returning.
16642        unsafe {
16643            ffi::whiteout_m3_M3PhysicsShape_assign_hullVertexFaceIndices(
16644                self.raw.as_ptr(),
16645                values.as_ptr() as *const _,
16646                values.len(),
16647            )
16648        }
16649    }
16650
16651    pub fn resize_hull_vertex_face_indices(&mut self, count: usize) {
16652        // SAFETY: reallocation is safe here precisely because
16653        // `&mut self` means no slice borrow is outstanding.
16654        unsafe {
16655            ffi::whiteout_m3_M3PhysicsShape_resize_hullVertexFaceIndices(self.raw.as_ptr(), count)
16656        }
16657    }
16658
16659    /// Hull centroid
16660    pub fn hull_center(&self) -> crate::math::Vector3f {
16661        // SAFETY: the getter returns an interior pointer to a
16662        // layout-identical POD; we copy it out immediately.
16663        unsafe {
16664            *(ffi::whiteout_m3_M3PhysicsShape_get_hullCenter(self.raw.as_ptr())
16665                as *const crate::math::Vector3f)
16666        }
16667    }
16668
16669    pub fn set_hull_center(&mut self, value: crate::math::Vector3f) {
16670        // SAFETY: as above, in the other direction.
16671        unsafe {
16672            ffi::whiteout_m3_M3PhysicsShape_set_hullCenter(
16673                self.raw.as_ptr(),
16674                &value as *const crate::math::Vector3f as *const _,
16675            )
16676        }
16677    }
16678
16679    /// Number of face normals
16680    pub fn hull_face_normal_count(&self) -> u32 {
16681        // SAFETY: plain scalar read through a live handle.
16682        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullFaceNormalCount(self.raw.as_ptr()) }
16683    }
16684
16685    pub fn set_hull_face_normal_count(&mut self, value: u32) {
16686        // SAFETY: plain scalar write through a live handle.
16687        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_hullFaceNormalCount(self.raw.as_ptr(), value) }
16688    }
16689
16690    /// Number of vertices
16691    pub fn hull_vertex_count(&self) -> u32 {
16692        // SAFETY: plain scalar read through a live handle.
16693        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullVertexCount(self.raw.as_ptr()) }
16694    }
16695
16696    pub fn set_hull_vertex_count(&mut self, value: u32) {
16697        // SAFETY: plain scalar write through a live handle.
16698        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_hullVertexCount(self.raw.as_ptr(), value) }
16699    }
16700
16701    /// Number of half-edges
16702    pub fn hull_half_edge_count(&self) -> u32 {
16703        // SAFETY: plain scalar read through a live handle.
16704        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullHalfEdgeCount(self.raw.as_ptr()) }
16705    }
16706
16707    pub fn set_hull_half_edge_count(&mut self, value: u32) {
16708        // SAFETY: plain scalar write through a live handle.
16709        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_hullHalfEdgeCount(self.raw.as_ptr(), value) }
16710    }
16711
16712    /// Unknown hull parameter 0
16713    pub fn hull_unknown_0(&self) -> f32 {
16714        // SAFETY: plain scalar read through a live handle.
16715        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullUnknown0(self.raw.as_ptr()) }
16716    }
16717
16718    pub fn set_hull_unknown_0(&mut self, value: f32) {
16719        // SAFETY: plain scalar write through a live handle.
16720        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_hullUnknown0(self.raw.as_ptr(), value) }
16721    }
16722
16723    /// Unknown hull parameter 1
16724    pub fn hull_unknown_1(&self) -> f32 {
16725        // SAFETY: plain scalar read through a live handle.
16726        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_hullUnknown1(self.raw.as_ptr()) }
16727    }
16728
16729    pub fn set_hull_unknown_1(&mut self, value: f32) {
16730        // SAFETY: plain scalar write through a live handle.
16731        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_hullUnknown1(self.raw.as_ptr(), value) }
16732    }
16733
16734    /// BVH tree nodes (DMMN)
16735    pub fn mesh_bvh_nodes_len(&self) -> usize {
16736        // SAFETY: scalar read through a live handle.
16737        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshBvhNodes_count(self.raw.as_ptr()) }
16738    }
16739
16740    /// Borrows element `index` in place. `None` when out of range.
16741    pub fn mesh_bvh_nodes(
16742        &self,
16743        index: usize,
16744    ) -> Option<crate::support::Ref<'_, PhysicsMeshBvhNode>> {
16745        if index >= self.mesh_bvh_nodes_len() {
16746            return None;
16747        }
16748        // SAFETY: index checked above; the pointer is interior to `self`.
16749        unsafe {
16750            Some(crate::support::Ref::new(PhysicsMeshBvhNode {
16751                raw: core::ptr::NonNull::new_unchecked(
16752                    ffi::whiteout_m3_M3PhysicsShape_get_meshBvhNodes_at(self.raw.as_ptr(), index),
16753                ),
16754            }))
16755        }
16756    }
16757
16758    pub fn mesh_bvh_nodes_mut(
16759        &mut self,
16760        index: usize,
16761    ) -> Option<crate::support::RefMut<'_, PhysicsMeshBvhNode>> {
16762        if index >= self.mesh_bvh_nodes_len() {
16763            return None;
16764        }
16765        // SAFETY: as above; `&mut self` guarantees exclusivity.
16766        unsafe {
16767            Some(crate::support::RefMut::new(PhysicsMeshBvhNode {
16768                raw: core::ptr::NonNull::new_unchecked(
16769                    ffi::whiteout_m3_M3PhysicsShape_get_meshBvhNodes_at(self.raw.as_ptr(), index),
16770                ),
16771            }))
16772        }
16773    }
16774
16775    /// Iterate the elements, borrowing each in turn.
16776    pub fn mesh_bvh_nodes_iter(
16777        &self,
16778    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsMeshBvhNode>> {
16779        (0..self.mesh_bvh_nodes_len())
16780            .map(move |i| self.mesh_bvh_nodes(i).expect("index below len"))
16781    }
16782
16783    pub fn resize_mesh_bvh_nodes(&mut self, count: usize) {
16784        // SAFETY: exclusive access, so no borrow is outstanding.
16785        unsafe { ffi::whiteout_m3_M3PhysicsShape_resize_meshBvhNodes(self.raw.as_ptr(), count) }
16786    }
16787
16788    /// Vertex positions, w=0 (VEC4)
16789    /// Zero-copy view of the underlying `std::vector`.
16790    pub fn mesh_vertex_positions(&self) -> &[crate::math::Vector4f] {
16791        // SAFETY: `_data`/`_count` describe one contiguous C++
16792        // allocation, borrowed for as long as `self` is.
16793        unsafe {
16794            let n =
16795                ffi::whiteout_m3_M3PhysicsShape_get_meshVertexPositions_count(self.raw.as_ptr());
16796            let p = ffi::whiteout_m3_M3PhysicsShape_get_meshVertexPositions_data(self.raw.as_ptr())
16797                as *const crate::math::Vector4f;
16798            if p.is_null() || n == 0 {
16799                &[]
16800            } else {
16801                core::slice::from_raw_parts(p, n)
16802            }
16803        }
16804    }
16805
16806    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
16807    pub fn mesh_vertex_positions_mut(&mut self) -> &mut [crate::math::Vector4f] {
16808        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
16809        unsafe {
16810            let n =
16811                ffi::whiteout_m3_M3PhysicsShape_get_meshVertexPositions_count(self.raw.as_ptr());
16812            let p = ffi::whiteout_m3_M3PhysicsShape_get_meshVertexPositions_data(self.raw.as_ptr())
16813                as *const crate::math::Vector4f as *mut crate::math::Vector4f;
16814            if p.is_null() || n == 0 {
16815                &mut []
16816            } else {
16817                core::slice::from_raw_parts_mut(p, n)
16818            }
16819        }
16820    }
16821
16822    pub fn set_mesh_vertex_positions(&mut self, values: &[crate::math::Vector4f]) {
16823        // SAFETY: the native side copies `values` before returning.
16824        unsafe {
16825            ffi::whiteout_m3_M3PhysicsShape_assign_meshVertexPositions(
16826                self.raw.as_ptr(),
16827                values.as_ptr() as *const _,
16828                values.len(),
16829            )
16830        }
16831    }
16832
16833    pub fn resize_mesh_vertex_positions(&mut self, count: usize) {
16834        // SAFETY: reallocation is safe here precisely because
16835        // `&mut self` means no slice borrow is outstanding.
16836        unsafe {
16837            ffi::whiteout_m3_M3PhysicsShape_resize_meshVertexPositions(self.raw.as_ptr(), count)
16838        }
16839    }
16840
16841    /// AABB center in model space (quantization grid origin)
16842    pub fn mesh_bounds_center(&self) -> crate::math::Vector3f {
16843        // SAFETY: the getter returns an interior pointer to a
16844        // layout-identical POD; we copy it out immediately.
16845        unsafe {
16846            *(ffi::whiteout_m3_M3PhysicsShape_get_meshBoundsCenter(self.raw.as_ptr())
16847                as *const crate::math::Vector3f)
16848        }
16849    }
16850
16851    pub fn set_mesh_bounds_center(&mut self, value: crate::math::Vector3f) {
16852        // SAFETY: as above, in the other direction.
16853        unsafe {
16854            ffi::whiteout_m3_M3PhysicsShape_set_meshBoundsCenter(
16855                self.raw.as_ptr(),
16856                &value as *const crate::math::Vector3f as *const _,
16857            )
16858        }
16859    }
16860
16861    /// AABB half-extents (quantization range: tolerance = extent / 32767)
16862    pub fn mesh_bounds_extent(&self) -> crate::math::Vector3f {
16863        // SAFETY: the getter returns an interior pointer to a
16864        // layout-identical POD; we copy it out immediately.
16865        unsafe {
16866            *(ffi::whiteout_m3_M3PhysicsShape_get_meshBoundsExtent(self.raw.as_ptr())
16867                as *const crate::math::Vector3f)
16868        }
16869    }
16870
16871    pub fn set_mesh_bounds_extent(&mut self, value: crate::math::Vector3f) {
16872        // SAFETY: as above, in the other direction.
16873        unsafe {
16874            ffi::whiteout_m3_M3PhysicsShape_set_meshBoundsExtent(
16875                self.raw.as_ptr(),
16876                &value as *const crate::math::Vector3f as *const _,
16877            )
16878        }
16879    }
16880
16881    /// Per-axis quantization step (= extent / 32767)
16882    pub fn mesh_tolerance(&self) -> crate::math::Vector3f {
16883        // SAFETY: the getter returns an interior pointer to a
16884        // layout-identical POD; we copy it out immediately.
16885        unsafe {
16886            *(ffi::whiteout_m3_M3PhysicsShape_get_meshTolerance(self.raw.as_ptr())
16887                as *const crate::math::Vector3f)
16888        }
16889    }
16890
16891    pub fn set_mesh_tolerance(&mut self, value: crate::math::Vector3f) {
16892        // SAFETY: as above, in the other direction.
16893        unsafe {
16894            ffi::whiteout_m3_M3PhysicsShape_set_meshTolerance(
16895                self.raw.as_ptr(),
16896                &value as *const crate::math::Vector3f as *const _,
16897            )
16898        }
16899    }
16900
16901    /// Number of mesh normals
16902    pub fn mesh_normal_count(&self) -> u32 {
16903        // SAFETY: plain scalar read through a live handle.
16904        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshNormalCount(self.raw.as_ptr()) }
16905    }
16906
16907    pub fn set_mesh_normal_count(&mut self, value: u32) {
16908        // SAFETY: plain scalar write through a live handle.
16909        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshNormalCount(self.raw.as_ptr(), value) }
16910    }
16911
16912    /// Number of mesh vertices
16913    pub fn mesh_vertex_count(&self) -> u32 {
16914        // SAFETY: plain scalar read through a live handle.
16915        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshVertexCount(self.raw.as_ptr()) }
16916    }
16917
16918    pub fn set_mesh_vertex_count(&mut self, value: u32) {
16919        // SAFETY: plain scalar write through a live handle.
16920        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshVertexCount(self.raw.as_ptr(), value) }
16921    }
16922
16923    /// MT16 face count (0 when MT32)
16924    pub fn mesh_face_index_16_count(&self) -> u32 {
16925        // SAFETY: plain scalar read through a live handle.
16926        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshFaceIndex16Count(self.raw.as_ptr()) }
16927    }
16928
16929    pub fn set_mesh_face_index_16_count(&mut self, value: u32) {
16930        // SAFETY: plain scalar write through a live handle.
16931        unsafe {
16932            ffi::whiteout_m3_M3PhysicsShape_set_meshFaceIndex16Count(self.raw.as_ptr(), value)
16933        }
16934    }
16935
16936    /// MT32 face count (0 when MT16)
16937    pub fn mesh_face_index_32_count(&self) -> u32 {
16938        // SAFETY: plain scalar read through a live handle.
16939        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshFaceIndex32Count(self.raw.as_ptr()) }
16940    }
16941
16942    pub fn set_mesh_face_index_32_count(&mut self, value: u32) {
16943        // SAFETY: plain scalar write through a live handle.
16944        unsafe {
16945            ffi::whiteout_m3_M3PhysicsShape_set_meshFaceIndex32Count(self.raw.as_ptr(), value)
16946        }
16947    }
16948
16949    /// Unknown mesh parameter
16950    pub fn mesh_unknown_1(&self) -> u32 {
16951        // SAFETY: plain scalar read through a live handle.
16952        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshUnknown1(self.raw.as_ptr()) }
16953    }
16954
16955    pub fn set_mesh_unknown_1(&mut self, value: u32) {
16956        // SAFETY: plain scalar write through a live handle.
16957        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshUnknown1(self.raw.as_ptr(), value) }
16958    }
16959
16960    /// Reserved (always 0)
16961    pub fn mesh_reserved(&self) -> u32 {
16962        // SAFETY: plain scalar read through a live handle.
16963        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshReserved(self.raw.as_ptr()) }
16964    }
16965
16966    pub fn set_mesh_reserved(&mut self, value: u32) {
16967        // SAFETY: plain scalar write through a live handle.
16968        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshReserved(self.raw.as_ptr(), value) }
16969    }
16970
16971    /// BVH tree height (root-to-leaf path length, 1–12)
16972    pub fn mesh_tree_depth(&self) -> u32 {
16973        // SAFETY: plain scalar read through a live handle.
16974        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshTreeDepth(self.raw.as_ptr()) }
16975    }
16976
16977    pub fn set_mesh_tree_depth(&mut self, value: u32) {
16978        // SAFETY: plain scalar write through a live handle.
16979        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshTreeDepth(self.raw.as_ptr(), value) }
16980    }
16981
16982    /// Collision margin (MT16: small float; MT32: 0.0)
16983    pub fn mesh_collision_margin(&self) -> f32 {
16984        // SAFETY: plain scalar read through a live handle.
16985        unsafe { ffi::whiteout_m3_M3PhysicsShape_get_meshCollisionMargin(self.raw.as_ptr()) }
16986    }
16987
16988    pub fn set_mesh_collision_margin(&mut self, value: f32) {
16989        // SAFETY: plain scalar write through a live handle.
16990        unsafe { ffi::whiteout_m3_M3PhysicsShape_set_meshCollisionMargin(self.raw.as_ptr(), value) }
16991    }
16992}
16993
16994impl Default for PhysicsShape {
16995    fn default() -> Self {
16996        Self::new()
16997    }
16998}
16999
17000/// PHRB — Rigid body (v2–v4, 56–104 bytes)
17001///
17002/// Havok rigid body with density, friction, restitution, damping, gravity scale, and collision shape references.
17003pub struct RigidBody {
17004    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3RigidBody>,
17005}
17006
17007impl Drop for RigidBody {
17008    fn drop(&mut self) {
17009        // SAFETY: `raw` came from a native constructor and Drop runs once.
17010        unsafe { ffi::whiteout_m3_M3RigidBody_delete(self.raw.as_ptr()) }
17011    }
17012}
17013
17014impl RigidBody {
17015    /// # Safety
17016    /// `raw` must be a live handle this value takes ownership of.
17017    #[allow(dead_code)] // used by whichever methods return this type
17018    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3RigidBody) -> Option<Self> {
17019        core::ptr::NonNull::new(raw).map(|raw| RigidBody { raw })
17020    }
17021}
17022
17023// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17024// is deliberately NOT implemented — the C++ types make no documented
17025// guarantee about concurrent use, and claiming one we haven't verified
17026// would be unsound. See `@bind thread_safe` in the plan.
17027unsafe impl Send for RigidBody {}
17028
17029impl core::fmt::Debug for RigidBody {
17030    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17031        f.debug_struct("RigidBody").finish_non_exhaustive()
17032    }
17033}
17034
17035impl RigidBody {
17036    /// # Panics
17037    /// Panics if the native allocation fails.
17038    pub fn new() -> Self {
17039        // SAFETY: the native constructor returns a live handle; a null here
17040        // means the library is unusable.
17041        unsafe {
17042            let raw = ffi::whiteout_m3_M3RigidBody_new();
17043            Self::from_raw(raw).expect("native RigidBody allocation failed")
17044        }
17045    }
17046
17047    /// Simulation mode (v3+)
17048    pub fn simulation_type(&self) -> u16 {
17049        // SAFETY: plain scalar read through a live handle.
17050        unsafe { ffi::whiteout_m3_M3RigidBody_get_simulationType(self.raw.as_ptr()) }
17051    }
17052
17053    pub fn set_simulation_type(&mut self, value: u16) {
17054        // SAFETY: plain scalar write through a live handle.
17055        unsafe { ffi::whiteout_m3_M3RigidBody_set_simulationType(self.raw.as_ptr(), value) }
17056    }
17057
17058    /// Parent bone index
17059    pub fn parent_bone_index(&self) -> u16 {
17060        // SAFETY: plain scalar read through a live handle.
17061        unsafe { ffi::whiteout_m3_M3RigidBody_get_parentBoneIndex(self.raw.as_ptr()) }
17062    }
17063
17064    pub fn set_parent_bone_index(&mut self, value: u16) {
17065        // SAFETY: plain scalar write through a live handle.
17066        unsafe { ffi::whiteout_m3_M3RigidBody_set_parentBoneIndex(self.raw.as_ptr(), value) }
17067    }
17068
17069    /// Engine-specific body type (v3+)
17070    pub fn physics_type(&self) -> u32 {
17071        // SAFETY: plain scalar read through a live handle.
17072        unsafe { ffi::whiteout_m3_M3RigidBody_get_physicsType(self.raw.as_ptr()) }
17073    }
17074
17075    pub fn set_physics_type(&mut self, value: u32) {
17076        // SAFETY: plain scalar write through a live handle.
17077        unsafe { ffi::whiteout_m3_M3RigidBody_set_physicsType(self.raw.as_ptr(), value) }
17078    }
17079
17080    /// Body density
17081    pub fn density(&self) -> f32 {
17082        // SAFETY: plain scalar read through a live handle.
17083        unsafe { ffi::whiteout_m3_M3RigidBody_get_density(self.raw.as_ptr()) }
17084    }
17085
17086    pub fn set_density(&mut self, value: f32) {
17087        // SAFETY: plain scalar write through a live handle.
17088        unsafe { ffi::whiteout_m3_M3RigidBody_set_density(self.raw.as_ptr(), value) }
17089    }
17090
17091    /// Surface friction
17092    pub fn friction(&self) -> f32 {
17093        // SAFETY: plain scalar read through a live handle.
17094        unsafe { ffi::whiteout_m3_M3RigidBody_get_friction(self.raw.as_ptr()) }
17095    }
17096
17097    pub fn set_friction(&mut self, value: f32) {
17098        // SAFETY: plain scalar write through a live handle.
17099        unsafe { ffi::whiteout_m3_M3RigidBody_set_friction(self.raw.as_ptr(), value) }
17100    }
17101
17102    /// Elasticity / bounciness
17103    pub fn restitution(&self) -> f32 {
17104        // SAFETY: plain scalar read through a live handle.
17105        unsafe { ffi::whiteout_m3_M3RigidBody_get_restitution(self.raw.as_ptr()) }
17106    }
17107
17108    pub fn set_restitution(&mut self, value: f32) {
17109        // SAFETY: plain scalar write through a live handle.
17110        unsafe { ffi::whiteout_m3_M3RigidBody_set_restitution(self.raw.as_ptr(), value) }
17111    }
17112
17113    /// Linear velocity damping
17114    pub fn linear_damping(&self) -> f32 {
17115        // SAFETY: plain scalar read through a live handle.
17116        unsafe { ffi::whiteout_m3_M3RigidBody_get_linearDamping(self.raw.as_ptr()) }
17117    }
17118
17119    pub fn set_linear_damping(&mut self, value: f32) {
17120        // SAFETY: plain scalar write through a live handle.
17121        unsafe { ffi::whiteout_m3_M3RigidBody_set_linearDamping(self.raw.as_ptr(), value) }
17122    }
17123
17124    /// Angular velocity damping
17125    pub fn angular_damping(&self) -> f32 {
17126        // SAFETY: plain scalar read through a live handle.
17127        unsafe { ffi::whiteout_m3_M3RigidBody_get_angularDamping(self.raw.as_ptr()) }
17128    }
17129
17130    pub fn set_angular_damping(&mut self, value: f32) {
17131        // SAFETY: plain scalar write through a live handle.
17132        unsafe { ffi::whiteout_m3_M3RigidBody_set_angularDamping(self.raw.as_ptr(), value) }
17133    }
17134
17135    /// Gravity influence scale
17136    pub fn gravity_scale(&self) -> f32 {
17137        // SAFETY: plain scalar read through a live handle.
17138        unsafe { ffi::whiteout_m3_M3RigidBody_get_gravityScale(self.raw.as_ptr()) }
17139    }
17140
17141    pub fn set_gravity_scale(&mut self, value: f32) {
17142        // SAFETY: plain scalar write through a live handle.
17143        unsafe { ffi::whiteout_m3_M3RigidBody_set_gravityScale(self.raw.as_ptr(), value) }
17144    }
17145
17146    /// Animated dynamic state (v4+)
17147    /// Borrows the field in place — no copy, no allocation.
17148    pub fn dynamic_state(&self) -> crate::support::Ref<'_, AnimRefU32> {
17149        // SAFETY: an interior pointer into `self`, valid for this
17150        // borrow and never freed by the `Ref`.
17151        unsafe {
17152            crate::support::Ref::new(AnimRefU32 {
17153                raw: core::ptr::NonNull::new_unchecked(
17154                    ffi::whiteout_m3_M3RigidBody_get_dynamicState(self.raw.as_ptr()),
17155                ),
17156            })
17157        }
17158    }
17159
17160    pub fn dynamic_state_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
17161        // SAFETY: as above; `&mut self` guarantees exclusivity.
17162        unsafe {
17163            crate::support::RefMut::new(AnimRefU32 {
17164                raw: core::ptr::NonNull::new_unchecked(
17165                    ffi::whiteout_m3_M3RigidBody_get_dynamicState(self.raw.as_ptr()),
17166                ),
17167            })
17168        }
17169    }
17170
17171    /// Dynamic blend-out duration (v4+)
17172    pub fn dynamic_blend_out(&self) -> f32 {
17173        // SAFETY: plain scalar read through a live handle.
17174        unsafe { ffi::whiteout_m3_M3RigidBody_get_dynamicBlendOut(self.raw.as_ptr()) }
17175    }
17176
17177    pub fn set_dynamic_blend_out(&mut self, value: f32) {
17178        // SAFETY: plain scalar write through a live handle.
17179        unsafe { ffi::whiteout_m3_M3RigidBody_set_dynamicBlendOut(self.raw.as_ptr(), value) }
17180    }
17181
17182    /// Collision shapes (PHSH)
17183    pub fn rigid_body_shape_len(&self) -> usize {
17184        // SAFETY: scalar read through a live handle.
17185        unsafe { ffi::whiteout_m3_M3RigidBody_get_rigidBodyShape_count(self.raw.as_ptr()) }
17186    }
17187
17188    /// Borrows element `index` in place. `None` when out of range.
17189    pub fn rigid_body_shape(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsShape>> {
17190        if index >= self.rigid_body_shape_len() {
17191            return None;
17192        }
17193        // SAFETY: index checked above; the pointer is interior to `self`.
17194        unsafe {
17195            Some(crate::support::Ref::new(PhysicsShape {
17196                raw: core::ptr::NonNull::new_unchecked(
17197                    ffi::whiteout_m3_M3RigidBody_get_rigidBodyShape_at(self.raw.as_ptr(), index),
17198                ),
17199            }))
17200        }
17201    }
17202
17203    pub fn rigid_body_shape_mut(
17204        &mut self,
17205        index: usize,
17206    ) -> Option<crate::support::RefMut<'_, PhysicsShape>> {
17207        if index >= self.rigid_body_shape_len() {
17208            return None;
17209        }
17210        // SAFETY: as above; `&mut self` guarantees exclusivity.
17211        unsafe {
17212            Some(crate::support::RefMut::new(PhysicsShape {
17213                raw: core::ptr::NonNull::new_unchecked(
17214                    ffi::whiteout_m3_M3RigidBody_get_rigidBodyShape_at(self.raw.as_ptr(), index),
17215                ),
17216            }))
17217        }
17218    }
17219
17220    /// Iterate the elements, borrowing each in turn.
17221    pub fn rigid_body_shape_iter(
17222        &self,
17223    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsShape>> {
17224        (0..self.rigid_body_shape_len())
17225            .map(move |i| self.rigid_body_shape(i).expect("index below len"))
17226    }
17227
17228    pub fn resize_rigid_body_shape(&mut self, count: usize) {
17229        // SAFETY: exclusive access, so no borrow is outstanding.
17230        unsafe { ffi::whiteout_m3_M3RigidBody_resize_rigidBodyShape(self.raw.as_ptr(), count) }
17231    }
17232
17233    /// Rigid body flags
17234    pub fn flags(&self) -> RigidBodyFlag {
17235        // SAFETY: scalar read; a flag set accepts any bits.
17236        RigidBodyFlag(unsafe { ffi::whiteout_m3_M3RigidBody_get_flags(self.raw.as_ptr()) })
17237    }
17238
17239    pub fn set_flags(&mut self, value: RigidBodyFlag) {
17240        // SAFETY: scalar write through a live handle.
17241        unsafe { ffi::whiteout_m3_M3RigidBody_set_flags(self.raw.as_ptr(), value.0) }
17242    }
17243
17244    /// Local force channel bitmask
17245    pub fn local_forces(&self) -> u16 {
17246        // SAFETY: plain scalar read through a live handle.
17247        unsafe { ffi::whiteout_m3_M3RigidBody_get_localForces(self.raw.as_ptr()) }
17248    }
17249
17250    pub fn set_local_forces(&mut self, value: u16) {
17251        // SAFETY: plain scalar write through a live handle.
17252        unsafe { ffi::whiteout_m3_M3RigidBody_set_localForces(self.raw.as_ptr(), value) }
17253    }
17254
17255    /// World force channel bitmask
17256    pub fn world_forces(&self) -> u16 {
17257        // SAFETY: plain scalar read through a live handle.
17258        unsafe { ffi::whiteout_m3_M3RigidBody_get_worldForces(self.raw.as_ptr()) }
17259    }
17260
17261    pub fn set_world_forces(&mut self, value: u16) {
17262        // SAFETY: plain scalar write through a live handle.
17263        unsafe { ffi::whiteout_m3_M3RigidBody_set_worldForces(self.raw.as_ptr(), value) }
17264    }
17265
17266    /// Simulation priority
17267    pub fn priority(&self) -> u32 {
17268        // SAFETY: plain scalar read through a live handle.
17269        unsafe { ffi::whiteout_m3_M3RigidBody_get_priority(self.raw.as_ptr()) }
17270    }
17271
17272    pub fn set_priority(&mut self, value: u32) {
17273        // SAFETY: plain scalar write through a live handle.
17274        unsafe { ffi::whiteout_m3_M3RigidBody_set_priority(self.raw.as_ptr(), value) }
17275    }
17276}
17277
17278impl Default for RigidBody {
17279    fn default() -> Self {
17280        Self::new()
17281    }
17282}
17283
17284/// PHYJ — Physics joint (v0, 180 bytes)
17285///
17286/// Connects two rigid bodies with limit, friction, and break-threshold parameters.
17287pub struct PhysicsJoint {
17288    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsJoint>,
17289}
17290
17291impl Drop for PhysicsJoint {
17292    fn drop(&mut self) {
17293        // SAFETY: `raw` came from a native constructor and Drop runs once.
17294        unsafe { ffi::whiteout_m3_M3PhysicsJoint_delete(self.raw.as_ptr()) }
17295    }
17296}
17297
17298impl PhysicsJoint {
17299    /// # Safety
17300    /// `raw` must be a live handle this value takes ownership of.
17301    #[allow(dead_code)] // used by whichever methods return this type
17302    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsJoint) -> Option<Self> {
17303        core::ptr::NonNull::new(raw).map(|raw| PhysicsJoint { raw })
17304    }
17305}
17306
17307// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17308// is deliberately NOT implemented — the C++ types make no documented
17309// guarantee about concurrent use, and claiming one we haven't verified
17310// would be unsound. See `@bind thread_safe` in the plan.
17311unsafe impl Send for PhysicsJoint {}
17312
17313impl core::fmt::Debug for PhysicsJoint {
17314    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17315        f.debug_struct("PhysicsJoint").finish_non_exhaustive()
17316    }
17317}
17318
17319impl PhysicsJoint {
17320    /// # Panics
17321    /// Panics if the native allocation fails.
17322    pub fn new() -> Self {
17323        // SAFETY: the native constructor returns a live handle; a null here
17324        // means the library is unusable.
17325        unsafe {
17326            let raw = ffi::whiteout_m3_M3PhysicsJoint_new();
17327            Self::from_raw(raw).expect("native PhysicsJoint allocation failed")
17328        }
17329    }
17330
17331    /// Joint type
17332    pub fn joint_type(&self) -> u32 {
17333        // SAFETY: plain scalar read through a live handle.
17334        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_jointType(self.raw.as_ptr()) }
17335    }
17336
17337    pub fn set_joint_type(&mut self, value: u32) {
17338        // SAFETY: plain scalar write through a live handle.
17339        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_jointType(self.raw.as_ptr(), value) }
17340    }
17341
17342    /// First bone index
17343    pub fn bone_index_1(&self) -> u32 {
17344        // SAFETY: plain scalar read through a live handle.
17345        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_boneIndex1(self.raw.as_ptr()) }
17346    }
17347
17348    pub fn set_bone_index_1(&mut self, value: u32) {
17349        // SAFETY: plain scalar write through a live handle.
17350        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_boneIndex1(self.raw.as_ptr(), value) }
17351    }
17352
17353    /// Second bone index
17354    pub fn bone_index_2(&self) -> u32 {
17355        // SAFETY: plain scalar read through a live handle.
17356        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_boneIndex2(self.raw.as_ptr()) }
17357    }
17358
17359    pub fn set_bone_index_2(&mut self, value: u32) {
17360        // SAFETY: plain scalar write through a live handle.
17361        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_boneIndex2(self.raw.as_ptr(), value) }
17362    }
17363
17364    /// Enable angular limits
17365    pub fn enable_limits(&self) -> u32 {
17366        // SAFETY: plain scalar read through a live handle.
17367        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_enableLimits(self.raw.as_ptr()) }
17368    }
17369
17370    pub fn set_enable_limits(&mut self, value: u32) {
17371        // SAFETY: plain scalar write through a live handle.
17372        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_enableLimits(self.raw.as_ptr(), value) }
17373    }
17374
17375    /// Minimum limit angle
17376    pub fn limit_min(&self) -> f32 {
17377        // SAFETY: plain scalar read through a live handle.
17378        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_limitMin(self.raw.as_ptr()) }
17379    }
17380
17381    pub fn set_limit_min(&mut self, value: f32) {
17382        // SAFETY: plain scalar write through a live handle.
17383        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_limitMin(self.raw.as_ptr(), value) }
17384    }
17385
17386    /// Maximum limit angle
17387    pub fn limit_max(&self) -> f32 {
17388        // SAFETY: plain scalar read through a live handle.
17389        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_limitMax(self.raw.as_ptr()) }
17390    }
17391
17392    pub fn set_limit_max(&mut self, value: f32) {
17393        // SAFETY: plain scalar write through a live handle.
17394        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_limitMax(self.raw.as_ptr(), value) }
17395    }
17396
17397    /// Cone constraint angle
17398    pub fn cone_angle(&self) -> f32 {
17399        // SAFETY: plain scalar read through a live handle.
17400        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_coneAngle(self.raw.as_ptr()) }
17401    }
17402
17403    pub fn set_cone_angle(&mut self, value: f32) {
17404        // SAFETY: plain scalar write through a live handle.
17405        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_coneAngle(self.raw.as_ptr(), value) }
17406    }
17407
17408    /// Enable joint friction
17409    pub fn enable_friction(&self) -> u32 {
17410        // SAFETY: plain scalar read through a live handle.
17411        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_enableFriction(self.raw.as_ptr()) }
17412    }
17413
17414    pub fn set_enable_friction(&mut self, value: u32) {
17415        // SAFETY: plain scalar write through a live handle.
17416        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_enableFriction(self.raw.as_ptr(), value) }
17417    }
17418
17419    /// Friction coefficient
17420    pub fn friction(&self) -> f32 {
17421        // SAFETY: plain scalar read through a live handle.
17422        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_friction(self.raw.as_ptr()) }
17423    }
17424
17425    pub fn set_friction(&mut self, value: f32) {
17426        // SAFETY: plain scalar write through a live handle.
17427        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_friction(self.raw.as_ptr(), value) }
17428    }
17429
17430    /// Damping ratio
17431    pub fn damping_ratio(&self) -> f32 {
17432        // SAFETY: plain scalar read through a live handle.
17433        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_dampingRatio(self.raw.as_ptr()) }
17434    }
17435
17436    pub fn set_damping_ratio(&mut self, value: f32) {
17437        // SAFETY: plain scalar write through a live handle.
17438        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_dampingRatio(self.raw.as_ptr(), value) }
17439    }
17440
17441    /// Angular frequency
17442    pub fn angular_frequency(&self) -> f32 {
17443        // SAFETY: plain scalar read through a live handle.
17444        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_angularFrequency(self.raw.as_ptr()) }
17445    }
17446
17447    pub fn set_angular_frequency(&mut self, value: f32) {
17448        // SAFETY: plain scalar write through a live handle.
17449        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_angularFrequency(self.raw.as_ptr(), value) }
17450    }
17451
17452    /// Force threshold to break joint
17453    pub fn break_threshold(&self) -> f32 {
17454        // SAFETY: plain scalar read through a live handle.
17455        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_breakThreshold(self.raw.as_ptr()) }
17456    }
17457
17458    pub fn set_break_threshold(&mut self, value: f32) {
17459        // SAFETY: plain scalar write through a live handle.
17460        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_breakThreshold(self.raw.as_ptr(), value) }
17461    }
17462
17463    /// Enable shape constraint
17464    pub fn enable_shape(&self) -> u8 {
17465        // SAFETY: plain scalar read through a live handle.
17466        unsafe { ffi::whiteout_m3_M3PhysicsJoint_get_enableShape(self.raw.as_ptr()) }
17467    }
17468
17469    pub fn set_enable_shape(&mut self, value: u8) {
17470        // SAFETY: plain scalar write through a live handle.
17471        unsafe { ffi::whiteout_m3_M3PhysicsJoint_set_enableShape(self.raw.as_ptr(), value) }
17472    }
17473}
17474
17475impl Default for PhysicsJoint {
17476    fn default() -> Self {
17477        Self::new()
17478    }
17479}
17480
17481/// PHCT — Physics constraint (v0, 24 bytes)
17482///
17483/// Constrains two rigid bodies with break-force threshold.
17484pub struct PhysicsConstraint {
17485    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3PhysicsConstraint>,
17486}
17487
17488impl Drop for PhysicsConstraint {
17489    fn drop(&mut self) {
17490        // SAFETY: `raw` came from a native constructor and Drop runs once.
17491        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_delete(self.raw.as_ptr()) }
17492    }
17493}
17494
17495impl PhysicsConstraint {
17496    /// # Safety
17497    /// `raw` must be a live handle this value takes ownership of.
17498    #[allow(dead_code)] // used by whichever methods return this type
17499    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3PhysicsConstraint) -> Option<Self> {
17500        core::ptr::NonNull::new(raw).map(|raw| PhysicsConstraint { raw })
17501    }
17502}
17503
17504// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17505// is deliberately NOT implemented — the C++ types make no documented
17506// guarantee about concurrent use, and claiming one we haven't verified
17507// would be unsound. See `@bind thread_safe` in the plan.
17508unsafe impl Send for PhysicsConstraint {}
17509
17510impl core::fmt::Debug for PhysicsConstraint {
17511    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17512        f.debug_struct("PhysicsConstraint").finish_non_exhaustive()
17513    }
17514}
17515
17516impl PhysicsConstraint {
17517    /// # Panics
17518    /// Panics if the native allocation fails.
17519    pub fn new() -> Self {
17520        // SAFETY: the native constructor returns a live handle; a null here
17521        // means the library is unusable.
17522        unsafe {
17523            let raw = ffi::whiteout_m3_M3PhysicsConstraint_new();
17524            Self::from_raw(raw).expect("native PhysicsConstraint allocation failed")
17525        }
17526    }
17527
17528    /// Dependent bone indices (U16_)
17529    /// Zero-copy view of the underlying `std::vector`.
17530    pub fn dependents(&self) -> &[u16] {
17531        // SAFETY: `_data`/`_count` describe one contiguous C++
17532        // allocation, borrowed for as long as `self` is.
17533        unsafe {
17534            let n = ffi::whiteout_m3_M3PhysicsConstraint_get_dependents_count(self.raw.as_ptr());
17535            let p = ffi::whiteout_m3_M3PhysicsConstraint_get_dependents_data(self.raw.as_ptr());
17536            if p.is_null() || n == 0 {
17537                &[]
17538            } else {
17539                core::slice::from_raw_parts(p, n)
17540            }
17541        }
17542    }
17543
17544    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
17545    pub fn dependents_mut(&mut self) -> &mut [u16] {
17546        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
17547        unsafe {
17548            let n = ffi::whiteout_m3_M3PhysicsConstraint_get_dependents_count(self.raw.as_ptr());
17549            let p = ffi::whiteout_m3_M3PhysicsConstraint_get_dependents_data(self.raw.as_ptr())
17550                as *mut u16;
17551            if p.is_null() || n == 0 {
17552                &mut []
17553            } else {
17554                core::slice::from_raw_parts_mut(p, n)
17555            }
17556        }
17557    }
17558
17559    pub fn set_dependents(&mut self, values: &[u16]) {
17560        // SAFETY: the native side copies `values` before returning.
17561        unsafe {
17562            ffi::whiteout_m3_M3PhysicsConstraint_assign_dependents(
17563                self.raw.as_ptr(),
17564                values.as_ptr() as *const _,
17565                values.len(),
17566            )
17567        }
17568    }
17569
17570    pub fn resize_dependents(&mut self, count: usize) {
17571        // SAFETY: reallocation is safe here precisely because
17572        // `&mut self` means no slice borrow is outstanding.
17573        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_resize_dependents(self.raw.as_ptr(), count) }
17574    }
17575
17576    /// First rigid body index
17577    pub fn rigid_body_1(&self) -> u16 {
17578        // SAFETY: plain scalar read through a live handle.
17579        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_get_rigidBody1(self.raw.as_ptr()) }
17580    }
17581
17582    pub fn set_rigid_body_1(&mut self, value: u16) {
17583        // SAFETY: plain scalar write through a live handle.
17584        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_set_rigidBody1(self.raw.as_ptr(), value) }
17585    }
17586
17587    /// Second rigid body index
17588    pub fn rigid_body_2(&self) -> u16 {
17589        // SAFETY: plain scalar read through a live handle.
17590        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_get_rigidBody2(self.raw.as_ptr()) }
17591    }
17592
17593    pub fn set_rigid_body_2(&mut self, value: u16) {
17594        // SAFETY: plain scalar write through a live handle.
17595        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_set_rigidBody2(self.raw.as_ptr(), value) }
17596    }
17597
17598    /// Force required to break constraint
17599    pub fn break_force(&self) -> f32 {
17600        // SAFETY: plain scalar read through a live handle.
17601        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_get_breakForce(self.raw.as_ptr()) }
17602    }
17603
17604    pub fn set_break_force(&mut self, value: f32) {
17605        // SAFETY: plain scalar write through a live handle.
17606        unsafe { ffi::whiteout_m3_M3PhysicsConstraint_set_breakForce(self.raw.as_ptr(), value) }
17607    }
17608}
17609
17610impl Default for PhysicsConstraint {
17611    fn default() -> Self {
17612        Self::new()
17613    }
17614}
17615
17616/// PHCC — Cloth collider (v0, 76 bytes)
17617///
17618/// Capsule-shaped collider used by cloth simulation.
17619pub struct ClothCollider {
17620    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ClothCollider>,
17621}
17622
17623impl Drop for ClothCollider {
17624    fn drop(&mut self) {
17625        // SAFETY: `raw` came from a native constructor and Drop runs once.
17626        unsafe { ffi::whiteout_m3_M3ClothCollider_delete(self.raw.as_ptr()) }
17627    }
17628}
17629
17630impl ClothCollider {
17631    /// # Safety
17632    /// `raw` must be a live handle this value takes ownership of.
17633    #[allow(dead_code)] // used by whichever methods return this type
17634    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ClothCollider) -> Option<Self> {
17635        core::ptr::NonNull::new(raw).map(|raw| ClothCollider { raw })
17636    }
17637}
17638
17639// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17640// is deliberately NOT implemented — the C++ types make no documented
17641// guarantee about concurrent use, and claiming one we haven't verified
17642// would be unsound. See `@bind thread_safe` in the plan.
17643unsafe impl Send for ClothCollider {}
17644
17645impl core::fmt::Debug for ClothCollider {
17646    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17647        f.debug_struct("ClothCollider").finish_non_exhaustive()
17648    }
17649}
17650
17651impl ClothCollider {
17652    /// # Panics
17653    /// Panics if the native allocation fails.
17654    pub fn new() -> Self {
17655        // SAFETY: the native constructor returns a live handle; a null here
17656        // means the library is unusable.
17657        unsafe {
17658            let raw = ffi::whiteout_m3_M3ClothCollider_new();
17659            Self::from_raw(raw).expect("native ClothCollider allocation failed")
17660        }
17661    }
17662
17663    /// Capsule radius
17664    pub fn radius(&self) -> f32 {
17665        // SAFETY: plain scalar read through a live handle.
17666        unsafe { ffi::whiteout_m3_M3ClothCollider_get_radius(self.raw.as_ptr()) }
17667    }
17668
17669    pub fn set_radius(&mut self, value: f32) {
17670        // SAFETY: plain scalar write through a live handle.
17671        unsafe { ffi::whiteout_m3_M3ClothCollider_set_radius(self.raw.as_ptr(), value) }
17672    }
17673
17674    /// Capsule height
17675    pub fn height(&self) -> f32 {
17676        // SAFETY: plain scalar read through a live handle.
17677        unsafe { ffi::whiteout_m3_M3ClothCollider_get_height(self.raw.as_ptr()) }
17678    }
17679
17680    pub fn set_height(&mut self, value: f32) {
17681        // SAFETY: plain scalar write through a live handle.
17682        unsafe { ffi::whiteout_m3_M3ClothCollider_set_height(self.raw.as_ptr(), value) }
17683    }
17684
17685    /// Alignment padding
17686    pub fn padding(&self) -> u32 {
17687        // SAFETY: plain scalar read through a live handle.
17688        unsafe { ffi::whiteout_m3_M3ClothCollider_get_padding(self.raw.as_ptr()) }
17689    }
17690
17691    pub fn set_padding(&mut self, value: u32) {
17692        // SAFETY: plain scalar write through a live handle.
17693        unsafe { ffi::whiteout_m3_M3ClothCollider_set_padding(self.raw.as_ptr(), value) }
17694    }
17695}
17696
17697impl Default for ClothCollider {
17698    fn default() -> Self {
17699        Self::new()
17700    }
17701}
17702
17703/// PHAC — Cloth proxy (v0, 32 bytes)
17704///
17705/// Maps cloth vertices to proxy geometry for collision.
17706pub struct ClothProxy {
17707    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ClothProxy>,
17708}
17709
17710impl Drop for ClothProxy {
17711    fn drop(&mut self) {
17712        // SAFETY: `raw` came from a native constructor and Drop runs once.
17713        unsafe { ffi::whiteout_m3_M3ClothProxy_delete(self.raw.as_ptr()) }
17714    }
17715}
17716
17717impl ClothProxy {
17718    /// # Safety
17719    /// `raw` must be a live handle this value takes ownership of.
17720    #[allow(dead_code)] // used by whichever methods return this type
17721    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ClothProxy) -> Option<Self> {
17722        core::ptr::NonNull::new(raw).map(|raw| ClothProxy { raw })
17723    }
17724}
17725
17726// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17727// is deliberately NOT implemented — the C++ types make no documented
17728// guarantee about concurrent use, and claiming one we haven't verified
17729// would be unsound. See `@bind thread_safe` in the plan.
17730unsafe impl Send for ClothProxy {}
17731
17732impl core::fmt::Debug for ClothProxy {
17733    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17734        f.debug_struct("ClothProxy").finish_non_exhaustive()
17735    }
17736}
17737
17738impl ClothProxy {
17739    /// # Panics
17740    /// Panics if the native allocation fails.
17741    pub fn new() -> Self {
17742        // SAFETY: the native constructor returns a live handle; a null here
17743        // means the library is unusable.
17744        unsafe {
17745            let raw = ffi::whiteout_m3_M3ClothProxy_new();
17746            Self::from_raw(raw).expect("native ClothProxy allocation failed")
17747        }
17748    }
17749
17750    /// Proxy mesh index
17751    pub fn proxy_index(&self) -> u32 {
17752        // SAFETY: plain scalar read through a live handle.
17753        unsafe { ffi::whiteout_m3_M3ClothProxy_get_proxyIndex(self.raw.as_ptr()) }
17754    }
17755
17756    pub fn set_proxy_index(&mut self, value: u32) {
17757        // SAFETY: plain scalar write through a live handle.
17758        unsafe { ffi::whiteout_m3_M3ClothProxy_set_proxyIndex(self.raw.as_ptr(), value) }
17759    }
17760
17761    /// Cloth mesh index
17762    pub fn cloth_index(&self) -> u32 {
17763        // SAFETY: plain scalar read through a live handle.
17764        unsafe { ffi::whiteout_m3_M3ClothProxy_get_clothIndex(self.raw.as_ptr()) }
17765    }
17766
17767    pub fn set_cloth_index(&mut self, value: u32) {
17768        // SAFETY: plain scalar write through a live handle.
17769        unsafe { ffi::whiteout_m3_M3ClothProxy_set_clothIndex(self.raw.as_ptr(), value) }
17770    }
17771
17772    /// Proxy vertex data (U64_)
17773    /// Zero-copy view of the underlying `std::vector`.
17774    pub fn proxy_vertices(&self) -> &[u64] {
17775        // SAFETY: `_data`/`_count` describe one contiguous C++
17776        // allocation, borrowed for as long as `self` is.
17777        unsafe {
17778            let n = ffi::whiteout_m3_M3ClothProxy_get_proxyVertices_count(self.raw.as_ptr());
17779            let p = ffi::whiteout_m3_M3ClothProxy_get_proxyVertices_data(self.raw.as_ptr());
17780            if p.is_null() || n == 0 {
17781                &[]
17782            } else {
17783                core::slice::from_raw_parts(p, n)
17784            }
17785        }
17786    }
17787
17788    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
17789    pub fn proxy_vertices_mut(&mut self) -> &mut [u64] {
17790        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
17791        unsafe {
17792            let n = ffi::whiteout_m3_M3ClothProxy_get_proxyVertices_count(self.raw.as_ptr());
17793            let p =
17794                ffi::whiteout_m3_M3ClothProxy_get_proxyVertices_data(self.raw.as_ptr()) as *mut u64;
17795            if p.is_null() || n == 0 {
17796                &mut []
17797            } else {
17798                core::slice::from_raw_parts_mut(p, n)
17799            }
17800        }
17801    }
17802
17803    pub fn set_proxy_vertices(&mut self, values: &[u64]) {
17804        // SAFETY: the native side copies `values` before returning.
17805        unsafe {
17806            ffi::whiteout_m3_M3ClothProxy_assign_proxyVertices(
17807                self.raw.as_ptr(),
17808                values.as_ptr() as *const _,
17809                values.len(),
17810            )
17811        }
17812    }
17813
17814    pub fn resize_proxy_vertices(&mut self, count: usize) {
17815        // SAFETY: reallocation is safe here precisely because
17816        // `&mut self` means no slice borrow is outstanding.
17817        unsafe { ffi::whiteout_m3_M3ClothProxy_resize_proxyVertices(self.raw.as_ptr(), count) }
17818    }
17819
17820    /// Proxy blend weights (U32_)
17821    /// Zero-copy view of the underlying `std::vector`.
17822    pub fn proxy_weights(&self) -> &[u32] {
17823        // SAFETY: `_data`/`_count` describe one contiguous C++
17824        // allocation, borrowed for as long as `self` is.
17825        unsafe {
17826            let n = ffi::whiteout_m3_M3ClothProxy_get_proxyWeights_count(self.raw.as_ptr());
17827            let p = ffi::whiteout_m3_M3ClothProxy_get_proxyWeights_data(self.raw.as_ptr());
17828            if p.is_null() || n == 0 {
17829                &[]
17830            } else {
17831                core::slice::from_raw_parts(p, n)
17832            }
17833        }
17834    }
17835
17836    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
17837    pub fn proxy_weights_mut(&mut self) -> &mut [u32] {
17838        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
17839        unsafe {
17840            let n = ffi::whiteout_m3_M3ClothProxy_get_proxyWeights_count(self.raw.as_ptr());
17841            let p =
17842                ffi::whiteout_m3_M3ClothProxy_get_proxyWeights_data(self.raw.as_ptr()) as *mut u32;
17843            if p.is_null() || n == 0 {
17844                &mut []
17845            } else {
17846                core::slice::from_raw_parts_mut(p, n)
17847            }
17848        }
17849    }
17850
17851    pub fn set_proxy_weights(&mut self, values: &[u32]) {
17852        // SAFETY: the native side copies `values` before returning.
17853        unsafe {
17854            ffi::whiteout_m3_M3ClothProxy_assign_proxyWeights(
17855                self.raw.as_ptr(),
17856                values.as_ptr() as *const _,
17857                values.len(),
17858            )
17859        }
17860    }
17861
17862    pub fn resize_proxy_weights(&mut self, count: usize) {
17863        // SAFETY: reallocation is safe here precisely because
17864        // `&mut self` means no slice borrow is outstanding.
17865        unsafe { ffi::whiteout_m3_M3ClothProxy_resize_proxyWeights(self.raw.as_ptr(), count) }
17866    }
17867}
17868
17869impl Default for ClothProxy {
17870    fn default() -> Self {
17871        Self::new()
17872    }
17873}
17874
17875/// PHCL — Cloth physics (v0–v4, 192 bytes)
17876///
17877/// Full cloth simulation configuration: skin bone binding, stiffness parameters, damping, wind/explosion/gravity scales, colliders, and proxies. Added in MODL v28.
17878pub struct ClothPhysics {
17879    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3ClothPhysics>,
17880}
17881
17882impl Drop for ClothPhysics {
17883    fn drop(&mut self) {
17884        // SAFETY: `raw` came from a native constructor and Drop runs once.
17885        unsafe { ffi::whiteout_m3_M3ClothPhysics_delete(self.raw.as_ptr()) }
17886    }
17887}
17888
17889impl ClothPhysics {
17890    /// # Safety
17891    /// `raw` must be a live handle this value takes ownership of.
17892    #[allow(dead_code)] // used by whichever methods return this type
17893    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3ClothPhysics) -> Option<Self> {
17894        core::ptr::NonNull::new(raw).map(|raw| ClothPhysics { raw })
17895    }
17896}
17897
17898// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
17899// is deliberately NOT implemented — the C++ types make no documented
17900// guarantee about concurrent use, and claiming one we haven't verified
17901// would be unsound. See `@bind thread_safe` in the plan.
17902unsafe impl Send for ClothPhysics {}
17903
17904impl core::fmt::Debug for ClothPhysics {
17905    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17906        f.debug_struct("ClothPhysics").finish_non_exhaustive()
17907    }
17908}
17909
17910impl ClothPhysics {
17911    /// # Panics
17912    /// Panics if the native allocation fails.
17913    pub fn new() -> Self {
17914        // SAFETY: the native constructor returns a live handle; a null here
17915        // means the library is unusable.
17916        unsafe {
17917            let raw = ffi::whiteout_m3_M3ClothPhysics_new();
17918            Self::from_raw(raw).expect("native ClothPhysics allocation failed")
17919        }
17920    }
17921
17922    /// Number of cloth mesh sections
17923    pub fn cloth_mesh_count(&self) -> u32 {
17924        // SAFETY: plain scalar read through a live handle.
17925        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_clothMeshCount(self.raw.as_ptr()) }
17926    }
17927
17928    pub fn set_cloth_mesh_count(&mut self, value: u32) {
17929        // SAFETY: plain scalar write through a live handle.
17930        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_clothMeshCount(self.raw.as_ptr(), value) }
17931    }
17932
17933    /// Number of skin bones
17934    pub fn skin_bone_count(&self) -> u32 {
17935        // SAFETY: plain scalar read through a live handle.
17936        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_skinBoneCount(self.raw.as_ptr()) }
17937    }
17938
17939    pub fn set_skin_bone_count(&mut self, value: u32) {
17940        // SAFETY: plain scalar write through a live handle.
17941        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_skinBoneCount(self.raw.as_ptr(), value) }
17942    }
17943
17944    /// Skin bone indices (U16_)
17945    /// Zero-copy view of the underlying `std::vector`.
17946    pub fn skin_bones(&self) -> &[u16] {
17947        // SAFETY: `_data`/`_count` describe one contiguous C++
17948        // allocation, borrowed for as long as `self` is.
17949        unsafe {
17950            let n = ffi::whiteout_m3_M3ClothPhysics_get_skinBones_count(self.raw.as_ptr());
17951            let p = ffi::whiteout_m3_M3ClothPhysics_get_skinBones_data(self.raw.as_ptr());
17952            if p.is_null() || n == 0 {
17953                &[]
17954            } else {
17955                core::slice::from_raw_parts(p, n)
17956            }
17957        }
17958    }
17959
17960    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
17961    pub fn skin_bones_mut(&mut self) -> &mut [u16] {
17962        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
17963        unsafe {
17964            let n = ffi::whiteout_m3_M3ClothPhysics_get_skinBones_count(self.raw.as_ptr());
17965            let p =
17966                ffi::whiteout_m3_M3ClothPhysics_get_skinBones_data(self.raw.as_ptr()) as *mut u16;
17967            if p.is_null() || n == 0 {
17968                &mut []
17969            } else {
17970                core::slice::from_raw_parts_mut(p, n)
17971            }
17972        }
17973    }
17974
17975    pub fn set_skin_bones(&mut self, values: &[u16]) {
17976        // SAFETY: the native side copies `values` before returning.
17977        unsafe {
17978            ffi::whiteout_m3_M3ClothPhysics_assign_skinBones(
17979                self.raw.as_ptr(),
17980                values.as_ptr() as *const _,
17981                values.len(),
17982            )
17983        }
17984    }
17985
17986    pub fn resize_skin_bones(&mut self, count: usize) {
17987        // SAFETY: reallocation is safe here precisely because
17988        // `&mut self` means no slice borrow is outstanding.
17989        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_skinBones(self.raw.as_ptr(), count) }
17990    }
17991
17992    /// Per-vertex simulation enable flags (U8__)
17993    /// Zero-copy view of the underlying `std::vector`.
17994    pub fn sim_enabled(&self) -> &[u8] {
17995        // SAFETY: `_data`/`_count` describe one contiguous C++
17996        // allocation, borrowed for as long as `self` is.
17997        unsafe {
17998            let n = ffi::whiteout_m3_M3ClothPhysics_get_simEnabled_count(self.raw.as_ptr());
17999            let p = ffi::whiteout_m3_M3ClothPhysics_get_simEnabled_data(self.raw.as_ptr());
18000            if p.is_null() || n == 0 {
18001                &[]
18002            } else {
18003                core::slice::from_raw_parts(p, n)
18004            }
18005        }
18006    }
18007
18008    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
18009    pub fn sim_enabled_mut(&mut self) -> &mut [u8] {
18010        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
18011        unsafe {
18012            let n = ffi::whiteout_m3_M3ClothPhysics_get_simEnabled_count(self.raw.as_ptr());
18013            let p =
18014                ffi::whiteout_m3_M3ClothPhysics_get_simEnabled_data(self.raw.as_ptr()) as *mut u8;
18015            if p.is_null() || n == 0 {
18016                &mut []
18017            } else {
18018                core::slice::from_raw_parts_mut(p, n)
18019            }
18020        }
18021    }
18022
18023    pub fn set_sim_enabled(&mut self, values: &[u8]) {
18024        // SAFETY: the native side copies `values` before returning.
18025        unsafe {
18026            ffi::whiteout_m3_M3ClothPhysics_assign_simEnabled(
18027                self.raw.as_ptr(),
18028                values.as_ptr() as *const _,
18029                values.len(),
18030            )
18031        }
18032    }
18033
18034    pub fn resize_sim_enabled(&mut self, count: usize) {
18035        // SAFETY: reallocation is safe here precisely because
18036        // `&mut self` means no slice borrow is outstanding.
18037        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_simEnabled(self.raw.as_ptr(), count) }
18038    }
18039
18040    /// Per-vertex bone indices (U32_)
18041    /// Zero-copy view of the underlying `std::vector`.
18042    pub fn vertex_bones(&self) -> &[u32] {
18043        // SAFETY: `_data`/`_count` describe one contiguous C++
18044        // allocation, borrowed for as long as `self` is.
18045        unsafe {
18046            let n = ffi::whiteout_m3_M3ClothPhysics_get_vertexBones_count(self.raw.as_ptr());
18047            let p = ffi::whiteout_m3_M3ClothPhysics_get_vertexBones_data(self.raw.as_ptr());
18048            if p.is_null() || n == 0 {
18049                &[]
18050            } else {
18051                core::slice::from_raw_parts(p, n)
18052            }
18053        }
18054    }
18055
18056    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
18057    pub fn vertex_bones_mut(&mut self) -> &mut [u32] {
18058        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
18059        unsafe {
18060            let n = ffi::whiteout_m3_M3ClothPhysics_get_vertexBones_count(self.raw.as_ptr());
18061            let p =
18062                ffi::whiteout_m3_M3ClothPhysics_get_vertexBones_data(self.raw.as_ptr()) as *mut u32;
18063            if p.is_null() || n == 0 {
18064                &mut []
18065            } else {
18066                core::slice::from_raw_parts_mut(p, n)
18067            }
18068        }
18069    }
18070
18071    pub fn set_vertex_bones(&mut self, values: &[u32]) {
18072        // SAFETY: the native side copies `values` before returning.
18073        unsafe {
18074            ffi::whiteout_m3_M3ClothPhysics_assign_vertexBones(
18075                self.raw.as_ptr(),
18076                values.as_ptr() as *const _,
18077                values.len(),
18078            )
18079        }
18080    }
18081
18082    pub fn resize_vertex_bones(&mut self, count: usize) {
18083        // SAFETY: reallocation is safe here precisely because
18084        // `&mut self` means no slice borrow is outstanding.
18085        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_vertexBones(self.raw.as_ptr(), count) }
18086    }
18087
18088    /// Per-vertex bone weights (U32_)
18089    /// Zero-copy view of the underlying `std::vector`.
18090    pub fn vertex_weights(&self) -> &[u32] {
18091        // SAFETY: `_data`/`_count` describe one contiguous C++
18092        // allocation, borrowed for as long as `self` is.
18093        unsafe {
18094            let n = ffi::whiteout_m3_M3ClothPhysics_get_vertexWeights_count(self.raw.as_ptr());
18095            let p = ffi::whiteout_m3_M3ClothPhysics_get_vertexWeights_data(self.raw.as_ptr());
18096            if p.is_null() || n == 0 {
18097                &[]
18098            } else {
18099                core::slice::from_raw_parts(p, n)
18100            }
18101        }
18102    }
18103
18104    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
18105    pub fn vertex_weights_mut(&mut self) -> &mut [u32] {
18106        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
18107        unsafe {
18108            let n = ffi::whiteout_m3_M3ClothPhysics_get_vertexWeights_count(self.raw.as_ptr());
18109            let p = ffi::whiteout_m3_M3ClothPhysics_get_vertexWeights_data(self.raw.as_ptr())
18110                as *mut u32;
18111            if p.is_null() || n == 0 {
18112                &mut []
18113            } else {
18114                core::slice::from_raw_parts_mut(p, n)
18115            }
18116        }
18117    }
18118
18119    pub fn set_vertex_weights(&mut self, values: &[u32]) {
18120        // SAFETY: the native side copies `values` before returning.
18121        unsafe {
18122            ffi::whiteout_m3_M3ClothPhysics_assign_vertexWeights(
18123                self.raw.as_ptr(),
18124                values.as_ptr() as *const _,
18125                values.len(),
18126            )
18127        }
18128    }
18129
18130    pub fn resize_vertex_weights(&mut self, count: usize) {
18131        // SAFETY: reallocation is safe here precisely because
18132        // `&mut self` means no slice borrow is outstanding.
18133        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_vertexWeights(self.raw.as_ptr(), count) }
18134    }
18135
18136    /// Cloth colliders (PHCC)
18137    pub fn colliders_len(&self) -> usize {
18138        // SAFETY: scalar read through a live handle.
18139        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_colliders_count(self.raw.as_ptr()) }
18140    }
18141
18142    /// Borrows element `index` in place. `None` when out of range.
18143    pub fn colliders(&self, index: usize) -> Option<crate::support::Ref<'_, ClothCollider>> {
18144        if index >= self.colliders_len() {
18145            return None;
18146        }
18147        // SAFETY: index checked above; the pointer is interior to `self`.
18148        unsafe {
18149            Some(crate::support::Ref::new(ClothCollider {
18150                raw: core::ptr::NonNull::new_unchecked(
18151                    ffi::whiteout_m3_M3ClothPhysics_get_colliders_at(self.raw.as_ptr(), index),
18152                ),
18153            }))
18154        }
18155    }
18156
18157    pub fn colliders_mut(
18158        &mut self,
18159        index: usize,
18160    ) -> Option<crate::support::RefMut<'_, ClothCollider>> {
18161        if index >= self.colliders_len() {
18162            return None;
18163        }
18164        // SAFETY: as above; `&mut self` guarantees exclusivity.
18165        unsafe {
18166            Some(crate::support::RefMut::new(ClothCollider {
18167                raw: core::ptr::NonNull::new_unchecked(
18168                    ffi::whiteout_m3_M3ClothPhysics_get_colliders_at(self.raw.as_ptr(), index),
18169                ),
18170            }))
18171        }
18172    }
18173
18174    /// Iterate the elements, borrowing each in turn.
18175    pub fn colliders_iter(
18176        &self,
18177    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ClothCollider>> {
18178        (0..self.colliders_len()).map(move |i| self.colliders(i).expect("index below len"))
18179    }
18180
18181    pub fn resize_colliders(&mut self, count: usize) {
18182        // SAFETY: exclusive access, so no borrow is outstanding.
18183        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_colliders(self.raw.as_ptr(), count) }
18184    }
18185
18186    /// Cloth proxies (PHAC)
18187    pub fn proxies_len(&self) -> usize {
18188        // SAFETY: scalar read through a live handle.
18189        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_proxies_count(self.raw.as_ptr()) }
18190    }
18191
18192    /// Borrows element `index` in place. `None` when out of range.
18193    pub fn proxies(&self, index: usize) -> Option<crate::support::Ref<'_, ClothProxy>> {
18194        if index >= self.proxies_len() {
18195            return None;
18196        }
18197        // SAFETY: index checked above; the pointer is interior to `self`.
18198        unsafe {
18199            Some(crate::support::Ref::new(ClothProxy {
18200                raw: core::ptr::NonNull::new_unchecked(
18201                    ffi::whiteout_m3_M3ClothPhysics_get_proxies_at(self.raw.as_ptr(), index),
18202                ),
18203            }))
18204        }
18205    }
18206
18207    pub fn proxies_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, ClothProxy>> {
18208        if index >= self.proxies_len() {
18209            return None;
18210        }
18211        // SAFETY: as above; `&mut self` guarantees exclusivity.
18212        unsafe {
18213            Some(crate::support::RefMut::new(ClothProxy {
18214                raw: core::ptr::NonNull::new_unchecked(
18215                    ffi::whiteout_m3_M3ClothPhysics_get_proxies_at(self.raw.as_ptr(), index),
18216                ),
18217            }))
18218        }
18219    }
18220
18221    /// Iterate the elements, borrowing each in turn.
18222    pub fn proxies_iter(
18223        &self,
18224    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ClothProxy>> {
18225        (0..self.proxies_len()).map(move |i| self.proxies(i).expect("index below len"))
18226    }
18227
18228    pub fn resize_proxies(&mut self, count: usize) {
18229        // SAFETY: exclusive access, so no borrow is outstanding.
18230        unsafe { ffi::whiteout_m3_M3ClothPhysics_resize_proxies(self.raw.as_ptr(), count) }
18231    }
18232
18233    /// Cloth density
18234    pub fn density(&self) -> f32 {
18235        // SAFETY: plain scalar read through a live handle.
18236        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_density(self.raw.as_ptr()) }
18237    }
18238
18239    pub fn set_density(&mut self, value: f32) {
18240        // SAFETY: plain scalar write through a live handle.
18241        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_density(self.raw.as_ptr(), value) }
18242    }
18243
18244    /// Tracking factor
18245    pub fn tracking(&self) -> f32 {
18246        // SAFETY: plain scalar read through a live handle.
18247        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_tracking(self.raw.as_ptr()) }
18248    }
18249
18250    pub fn set_tracking(&mut self, value: f32) {
18251        // SAFETY: plain scalar write through a live handle.
18252        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_tracking(self.raw.as_ptr(), value) }
18253    }
18254
18255    /// Stretch stiffness
18256    pub fn stretch_stiffness(&self) -> f32 {
18257        // SAFETY: plain scalar read through a live handle.
18258        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_stretchStiffness(self.raw.as_ptr()) }
18259    }
18260
18261    pub fn set_stretch_stiffness(&mut self, value: f32) {
18262        // SAFETY: plain scalar write through a live handle.
18263        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_stretchStiffness(self.raw.as_ptr(), value) }
18264    }
18265
18266    /// Horizontal stiffness
18267    pub fn horizontal_stiffness(&self) -> f32 {
18268        // SAFETY: plain scalar read through a live handle.
18269        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_horizontalStiffness(self.raw.as_ptr()) }
18270    }
18271
18272    pub fn set_horizontal_stiffness(&mut self, value: f32) {
18273        // SAFETY: plain scalar write through a live handle.
18274        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_horizontalStiffness(self.raw.as_ptr(), value) }
18275    }
18276
18277    /// Bending stiffness
18278    pub fn bending_stiffness(&self) -> f32 {
18279        // SAFETY: plain scalar read through a live handle.
18280        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_bendingStiffness(self.raw.as_ptr()) }
18281    }
18282
18283    pub fn set_bending_stiffness(&mut self, value: f32) {
18284        // SAFETY: plain scalar write through a live handle.
18285        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_bendingStiffness(self.raw.as_ptr(), value) }
18286    }
18287
18288    /// Damping coefficient
18289    pub fn damping(&self) -> f32 {
18290        // SAFETY: plain scalar read through a live handle.
18291        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_damping(self.raw.as_ptr()) }
18292    }
18293
18294    pub fn set_damping(&mut self, value: f32) {
18295        // SAFETY: plain scalar write through a live handle.
18296        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_damping(self.raw.as_ptr(), value) }
18297    }
18298
18299    /// Friction coefficient
18300    pub fn friction(&self) -> f32 {
18301        // SAFETY: plain scalar read through a live handle.
18302        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_friction(self.raw.as_ptr()) }
18303    }
18304
18305    pub fn set_friction(&mut self, value: f32) {
18306        // SAFETY: plain scalar write through a live handle.
18307        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_friction(self.raw.as_ptr(), value) }
18308    }
18309
18310    /// Gravity influence
18311    pub fn gravity(&self) -> f32 {
18312        // SAFETY: plain scalar read through a live handle.
18313        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_gravity(self.raw.as_ptr()) }
18314    }
18315
18316    pub fn set_gravity(&mut self, value: f32) {
18317        // SAFETY: plain scalar write through a live handle.
18318        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_gravity(self.raw.as_ptr(), value) }
18319    }
18320
18321    /// Explosion force scale
18322    pub fn explosion_scale(&self) -> f32 {
18323        // SAFETY: plain scalar read through a live handle.
18324        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_explosionScale(self.raw.as_ptr()) }
18325    }
18326
18327    pub fn set_explosion_scale(&mut self, value: f32) {
18328        // SAFETY: plain scalar write through a live handle.
18329        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_explosionScale(self.raw.as_ptr(), value) }
18330    }
18331
18332    /// Wind force scale
18333    pub fn wind_scale(&self) -> f32 {
18334        // SAFETY: plain scalar read through a live handle.
18335        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_windScale(self.raw.as_ptr()) }
18336    }
18337
18338    pub fn set_wind_scale(&mut self, value: f32) {
18339        // SAFETY: plain scalar write through a live handle.
18340        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_windScale(self.raw.as_ptr(), value) }
18341    }
18342
18343    /// Shear stiffness
18344    pub fn shear_stiffness(&self) -> f32 {
18345        // SAFETY: plain scalar read through a live handle.
18346        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_shearStiffness(self.raw.as_ptr()) }
18347    }
18348
18349    pub fn set_shear_stiffness(&mut self, value: f32) {
18350        // SAFETY: plain scalar write through a live handle.
18351        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_shearStiffness(self.raw.as_ptr(), value) }
18352    }
18353
18354    /// Drag factor
18355    pub fn drag_factor(&self) -> f32 {
18356        // SAFETY: plain scalar read through a live handle.
18357        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_dragFactor(self.raw.as_ptr()) }
18358    }
18359
18360    pub fn set_drag_factor(&mut self, value: f32) {
18361        // SAFETY: plain scalar write through a live handle.
18362        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_dragFactor(self.raw.as_ptr(), value) }
18363    }
18364
18365    /// Lift factor (v4+)
18366    pub fn lift_factor(&self) -> f32 {
18367        // SAFETY: plain scalar read through a live handle.
18368        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_liftFactor(self.raw.as_ptr()) }
18369    }
18370
18371    pub fn set_lift_factor(&mut self, value: f32) {
18372        // SAFETY: plain scalar write through a live handle.
18373        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_liftFactor(self.raw.as_ptr(), value) }
18374    }
18375
18376    /// Sphere collider stiffness (v4+)
18377    pub fn sphere_stiffness(&self) -> f32 {
18378        // SAFETY: plain scalar read through a live handle.
18379        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_sphereStiffness(self.raw.as_ptr()) }
18380    }
18381
18382    pub fn set_sphere_stiffness(&mut self, value: f32) {
18383        // SAFETY: plain scalar write through a live handle.
18384        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_sphereStiffness(self.raw.as_ptr(), value) }
18385    }
18386
18387    /// Flatten mode (v4+)
18388    pub fn flatten(&self) -> u32 {
18389        // SAFETY: plain scalar read through a live handle.
18390        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_flatten(self.raw.as_ptr()) }
18391    }
18392
18393    pub fn set_flatten(&mut self, value: u32) {
18394        // SAFETY: plain scalar write through a live handle.
18395        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_flatten(self.raw.as_ptr(), value) }
18396    }
18397
18398    /// Animated active state
18399    /// Borrows the field in place — no copy, no allocation.
18400    pub fn active(&self) -> crate::support::Ref<'_, AnimRefU32> {
18401        // SAFETY: an interior pointer into `self`, valid for this
18402        // borrow and never freed by the `Ref`.
18403        unsafe {
18404            crate::support::Ref::new(AnimRefU32 {
18405                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3ClothPhysics_get_active(
18406                    self.raw.as_ptr(),
18407                )),
18408            })
18409        }
18410    }
18411
18412    pub fn active_mut(&mut self) -> crate::support::RefMut<'_, AnimRefU32> {
18413        // SAFETY: as above; `&mut self` guarantees exclusivity.
18414        unsafe {
18415            crate::support::RefMut::new(AnimRefU32 {
18416                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3ClothPhysics_get_active(
18417                    self.raw.as_ptr(),
18418                )),
18419            })
18420        }
18421    }
18422
18423    /// Use skin mesh for collision
18424    pub fn use_skin_collision(&self) -> u32 {
18425        // SAFETY: plain scalar read through a live handle.
18426        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_useSkinCollision(self.raw.as_ptr()) }
18427    }
18428
18429    pub fn set_use_skin_collision(&mut self, value: u32) {
18430        // SAFETY: plain scalar write through a live handle.
18431        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_useSkinCollision(self.raw.as_ptr(), value) }
18432    }
18433
18434    /// Skin collision offset
18435    pub fn skin_offset(&self) -> f32 {
18436        // SAFETY: plain scalar read through a live handle.
18437        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_skinOffset(self.raw.as_ptr()) }
18438    }
18439
18440    pub fn set_skin_offset(&mut self, value: f32) {
18441        // SAFETY: plain scalar write through a live handle.
18442        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_skinOffset(self.raw.as_ptr(), value) }
18443    }
18444
18445    /// Skin collision exponent
18446    pub fn skin_exponent(&self) -> f32 {
18447        // SAFETY: plain scalar read through a live handle.
18448        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_skinExponent(self.raw.as_ptr()) }
18449    }
18450
18451    pub fn set_skin_exponent(&mut self, value: f32) {
18452        // SAFETY: plain scalar write through a live handle.
18453        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_skinExponent(self.raw.as_ptr(), value) }
18454    }
18455
18456    /// Skin collision stiffness
18457    pub fn skin_stiffness(&self) -> f32 {
18458        // SAFETY: plain scalar read through a live handle.
18459        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_skinStiffness(self.raw.as_ptr()) }
18460    }
18461
18462    pub fn set_skin_stiffness(&mut self, value: f32) {
18463        // SAFETY: plain scalar write through a live handle.
18464        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_skinStiffness(self.raw.as_ptr(), value) }
18465    }
18466
18467    /// Local force channel bitmask
18468    pub fn local_channels(&self) -> u32 {
18469        // SAFETY: plain scalar read through a live handle.
18470        unsafe { ffi::whiteout_m3_M3ClothPhysics_get_localChannels(self.raw.as_ptr()) }
18471    }
18472
18473    pub fn set_local_channels(&mut self, value: u32) {
18474        // SAFETY: plain scalar write through a live handle.
18475        unsafe { ffi::whiteout_m3_M3ClothPhysics_set_localChannels(self.raw.as_ptr(), value) }
18476    }
18477
18478    /// Local wind direction and magnitude
18479    pub fn local_wind(&self) -> crate::math::Vector3f {
18480        // SAFETY: the getter returns an interior pointer to a
18481        // layout-identical POD; we copy it out immediately.
18482        unsafe {
18483            *(ffi::whiteout_m3_M3ClothPhysics_get_localWind(self.raw.as_ptr())
18484                as *const crate::math::Vector3f)
18485        }
18486    }
18487
18488    pub fn set_local_wind(&mut self, value: crate::math::Vector3f) {
18489        // SAFETY: as above, in the other direction.
18490        unsafe {
18491            ffi::whiteout_m3_M3ClothPhysics_set_localWind(
18492                self.raw.as_ptr(),
18493                &value as *const crate::math::Vector3f as *const _,
18494            )
18495        }
18496    }
18497}
18498
18499impl Default for ClothPhysics {
18500    fn default() -> Self {
18501        Self::new()
18502    }
18503}
18504
18505/// LITE — Light source (v0–v7, 212 bytes)
18506///
18507/// Omni, spot, or directional light with animated diffuse/specular colors, intensity, decay, attenuation start/end, and spot-light hot-spot/falloff.
18508pub struct Light {
18509    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Light>,
18510}
18511
18512impl Drop for Light {
18513    fn drop(&mut self) {
18514        // SAFETY: `raw` came from a native constructor and Drop runs once.
18515        unsafe { ffi::whiteout_m3_M3Light_delete(self.raw.as_ptr()) }
18516    }
18517}
18518
18519impl Light {
18520    /// # Safety
18521    /// `raw` must be a live handle this value takes ownership of.
18522    #[allow(dead_code)] // used by whichever methods return this type
18523    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Light) -> Option<Self> {
18524        core::ptr::NonNull::new(raw).map(|raw| Light { raw })
18525    }
18526}
18527
18528// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
18529// is deliberately NOT implemented — the C++ types make no documented
18530// guarantee about concurrent use, and claiming one we haven't verified
18531// would be unsound. See `@bind thread_safe` in the plan.
18532unsafe impl Send for Light {}
18533
18534impl core::fmt::Debug for Light {
18535    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18536        f.debug_struct("Light").finish_non_exhaustive()
18537    }
18538}
18539
18540impl Light {
18541    /// # Panics
18542    /// Panics if the native allocation fails.
18543    pub fn new() -> Self {
18544        // SAFETY: the native constructor returns a live handle; a null here
18545        // means the library is unusable.
18546        unsafe {
18547            let raw = ffi::whiteout_m3_M3Light_new();
18548            Self::from_raw(raw).expect("native Light allocation failed")
18549        }
18550    }
18551
18552    /// Light type (omni/spot/directional)
18553    pub fn light_type(&self) -> LightType {
18554        // SAFETY: scalar read; the discriminant is validated below.
18555        unsafe { ffi::whiteout_m3_M3Light_get_lightType(self.raw.as_ptr()) }
18556            .try_into()
18557            .expect("unknown enum discriminant from the native library")
18558    }
18559
18560    pub fn set_light_type(&mut self, value: LightType) {
18561        // SAFETY: scalar write through a live handle.
18562        unsafe { ffi::whiteout_m3_M3Light_set_lightType(self.raw.as_ptr(), value as i32) }
18563    }
18564
18565    /// Index into BONE array
18566    pub fn bone_index(&self) -> u16 {
18567        // SAFETY: plain scalar read through a live handle.
18568        unsafe { ffi::whiteout_m3_M3Light_get_boneIndex(self.raw.as_ptr()) }
18569    }
18570
18571    pub fn set_bone_index(&mut self, value: u16) {
18572        // SAFETY: plain scalar write through a live handle.
18573        unsafe { ffi::whiteout_m3_M3Light_set_boneIndex(self.raw.as_ptr(), value) }
18574    }
18575
18576    /// Light flags (shadows, specular, AO, etc.)
18577    pub fn flags(&self) -> LightFlag {
18578        // SAFETY: scalar read; a flag set accepts any bits.
18579        LightFlag(unsafe { ffi::whiteout_m3_M3Light_get_flags(self.raw.as_ptr()) })
18580    }
18581
18582    pub fn set_flags(&mut self, value: LightFlag) {
18583        // SAFETY: scalar write through a live handle.
18584        unsafe { ffi::whiteout_m3_M3Light_set_flags(self.raw.as_ptr(), value.0) }
18585    }
18586
18587    /// LOD cut-off level
18588    pub fn lod_cut(&self) -> u32 {
18589        // SAFETY: plain scalar read through a live handle.
18590        unsafe { ffi::whiteout_m3_M3Light_get_lodCut(self.raw.as_ptr()) }
18591    }
18592
18593    pub fn set_lod_cut(&mut self, value: u32) {
18594        // SAFETY: plain scalar write through a live handle.
18595        unsafe { ffi::whiteout_m3_M3Light_set_lodCut(self.raw.as_ptr(), value) }
18596    }
18597
18598    /// Shadow LOD cut-off level
18599    pub fn shadow_lod_cut(&self) -> u32 {
18600        // SAFETY: plain scalar read through a live handle.
18601        unsafe { ffi::whiteout_m3_M3Light_get_shadowLodCut(self.raw.as_ptr()) }
18602    }
18603
18604    pub fn set_shadow_lod_cut(&mut self, value: u32) {
18605        // SAFETY: plain scalar write through a live handle.
18606        unsafe { ffi::whiteout_m3_M3Light_set_shadowLodCut(self.raw.as_ptr(), value) }
18607    }
18608
18609    /// Animated diffuse color (RGB)
18610    /// Borrows the field in place — no copy, no allocation.
18611    pub fn diffuse_color(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
18612        // SAFETY: an interior pointer into `self`, valid for this
18613        // borrow and never freed by the `Ref`.
18614        unsafe {
18615            crate::support::Ref::new(AnimRefVector3f {
18616                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_diffuseColor(
18617                    self.raw.as_ptr(),
18618                )),
18619            })
18620        }
18621    }
18622
18623    pub fn diffuse_color_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
18624        // SAFETY: as above; `&mut self` guarantees exclusivity.
18625        unsafe {
18626            crate::support::RefMut::new(AnimRefVector3f {
18627                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_diffuseColor(
18628                    self.raw.as_ptr(),
18629                )),
18630            })
18631        }
18632    }
18633
18634    /// Animated intensity multiplier
18635    /// Borrows the field in place — no copy, no allocation.
18636    pub fn intensity_multiplier(&self) -> crate::support::Ref<'_, AnimRefF32> {
18637        // SAFETY: an interior pointer into `self`, valid for this
18638        // borrow and never freed by the `Ref`.
18639        unsafe {
18640            crate::support::Ref::new(AnimRefF32 {
18641                raw: core::ptr::NonNull::new_unchecked(
18642                    ffi::whiteout_m3_M3Light_get_intensityMultiplier(self.raw.as_ptr()),
18643                ),
18644            })
18645        }
18646    }
18647
18648    pub fn intensity_multiplier_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18649        // SAFETY: as above; `&mut self` guarantees exclusivity.
18650        unsafe {
18651            crate::support::RefMut::new(AnimRefF32 {
18652                raw: core::ptr::NonNull::new_unchecked(
18653                    ffi::whiteout_m3_M3Light_get_intensityMultiplier(self.raw.as_ptr()),
18654                ),
18655            })
18656        }
18657    }
18658
18659    /// Animated specular color (RGB)
18660    /// Borrows the field in place — no copy, no allocation.
18661    pub fn specular_color(&self) -> crate::support::Ref<'_, AnimRefVector3f> {
18662        // SAFETY: an interior pointer into `self`, valid for this
18663        // borrow and never freed by the `Ref`.
18664        unsafe {
18665            crate::support::Ref::new(AnimRefVector3f {
18666                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_specularColor(
18667                    self.raw.as_ptr(),
18668                )),
18669            })
18670        }
18671    }
18672
18673    pub fn specular_color_mut(&mut self) -> crate::support::RefMut<'_, AnimRefVector3f> {
18674        // SAFETY: as above; `&mut self` guarantees exclusivity.
18675        unsafe {
18676            crate::support::RefMut::new(AnimRefVector3f {
18677                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_specularColor(
18678                    self.raw.as_ptr(),
18679                )),
18680            })
18681        }
18682    }
18683
18684    /// Animated specular multiplier
18685    /// Borrows the field in place — no copy, no allocation.
18686    pub fn specular_multiplier(&self) -> crate::support::Ref<'_, AnimRefF32> {
18687        // SAFETY: an interior pointer into `self`, valid for this
18688        // borrow and never freed by the `Ref`.
18689        unsafe {
18690            crate::support::Ref::new(AnimRefF32 {
18691                raw: core::ptr::NonNull::new_unchecked(
18692                    ffi::whiteout_m3_M3Light_get_specularMultiplier(self.raw.as_ptr()),
18693                ),
18694            })
18695        }
18696    }
18697
18698    pub fn specular_multiplier_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18699        // SAFETY: as above; `&mut self` guarantees exclusivity.
18700        unsafe {
18701            crate::support::RefMut::new(AnimRefF32 {
18702                raw: core::ptr::NonNull::new_unchecked(
18703                    ffi::whiteout_m3_M3Light_get_specularMultiplier(self.raw.as_ptr()),
18704                ),
18705            })
18706        }
18707    }
18708
18709    /// Animated distance decay exponent
18710    /// Borrows the field in place — no copy, no allocation.
18711    pub fn decay(&self) -> crate::support::Ref<'_, AnimRefF32> {
18712        // SAFETY: an interior pointer into `self`, valid for this
18713        // borrow and never freed by the `Ref`.
18714        unsafe {
18715            crate::support::Ref::new(AnimRefF32 {
18716                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_decay(
18717                    self.raw.as_ptr(),
18718                )),
18719            })
18720        }
18721    }
18722
18723    pub fn decay_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18724        // SAFETY: as above; `&mut self` guarantees exclusivity.
18725        unsafe {
18726            crate::support::RefMut::new(AnimRefF32 {
18727                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_decay(
18728                    self.raw.as_ptr(),
18729                )),
18730            })
18731        }
18732    }
18733
18734    /// Attenuation end distance
18735    pub fn attenuation_end(&self) -> f32 {
18736        // SAFETY: plain scalar read through a live handle.
18737        unsafe { ffi::whiteout_m3_M3Light_get_attenuationEnd(self.raw.as_ptr()) }
18738    }
18739
18740    pub fn set_attenuation_end(&mut self, value: f32) {
18741        // SAFETY: plain scalar write through a live handle.
18742        unsafe { ffi::whiteout_m3_M3Light_set_attenuationEnd(self.raw.as_ptr(), value) }
18743    }
18744
18745    /// Animated attenuation start distance
18746    /// Borrows the field in place — no copy, no allocation.
18747    pub fn attenuation_start(&self) -> crate::support::Ref<'_, AnimRefF32> {
18748        // SAFETY: an interior pointer into `self`, valid for this
18749        // borrow and never freed by the `Ref`.
18750        unsafe {
18751            crate::support::Ref::new(AnimRefF32 {
18752                raw: core::ptr::NonNull::new_unchecked(
18753                    ffi::whiteout_m3_M3Light_get_attenuationStart(self.raw.as_ptr()),
18754                ),
18755            })
18756        }
18757    }
18758
18759    pub fn attenuation_start_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18760        // SAFETY: as above; `&mut self` guarantees exclusivity.
18761        unsafe {
18762            crate::support::RefMut::new(AnimRefF32 {
18763                raw: core::ptr::NonNull::new_unchecked(
18764                    ffi::whiteout_m3_M3Light_get_attenuationStart(self.raw.as_ptr()),
18765                ),
18766            })
18767        }
18768    }
18769
18770    /// Animated spot inner cone angle
18771    /// Borrows the field in place — no copy, no allocation.
18772    pub fn hot_spot(&self) -> crate::support::Ref<'_, AnimRefF32> {
18773        // SAFETY: an interior pointer into `self`, valid for this
18774        // borrow and never freed by the `Ref`.
18775        unsafe {
18776            crate::support::Ref::new(AnimRefF32 {
18777                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_hotSpot(
18778                    self.raw.as_ptr(),
18779                )),
18780            })
18781        }
18782    }
18783
18784    pub fn hot_spot_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18785        // SAFETY: as above; `&mut self` guarantees exclusivity.
18786        unsafe {
18787            crate::support::RefMut::new(AnimRefF32 {
18788                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_hotSpot(
18789                    self.raw.as_ptr(),
18790                )),
18791            })
18792        }
18793    }
18794
18795    /// Animated spot outer cone falloff
18796    /// Borrows the field in place — no copy, no allocation.
18797    pub fn falloff(&self) -> crate::support::Ref<'_, AnimRefF32> {
18798        // SAFETY: an interior pointer into `self`, valid for this
18799        // borrow and never freed by the `Ref`.
18800        unsafe {
18801            crate::support::Ref::new(AnimRefF32 {
18802                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_falloff(
18803                    self.raw.as_ptr(),
18804                )),
18805            })
18806        }
18807    }
18808
18809    pub fn falloff_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18810        // SAFETY: as above; `&mut self` guarantees exclusivity.
18811        unsafe {
18812            crate::support::RefMut::new(AnimRefF32 {
18813                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Light_get_falloff(
18814                    self.raw.as_ptr(),
18815                )),
18816            })
18817        }
18818    }
18819}
18820
18821impl Default for Light {
18822    fn default() -> Self {
18823        Self::new()
18824    }
18825}
18826
18827/// CAM_ — Camera (v2–v5, 144–264 bytes)
18828///
18829/// Bone-attached camera with animated FOV, clip planes, shadow clip distance, depth-of-field parameters, and version-dependent bokeh settings.
18830pub struct Camera {
18831    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Camera>,
18832}
18833
18834impl Drop for Camera {
18835    fn drop(&mut self) {
18836        // SAFETY: `raw` came from a native constructor and Drop runs once.
18837        unsafe { ffi::whiteout_m3_M3Camera_delete(self.raw.as_ptr()) }
18838    }
18839}
18840
18841impl Camera {
18842    /// # Safety
18843    /// `raw` must be a live handle this value takes ownership of.
18844    #[allow(dead_code)] // used by whichever methods return this type
18845    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Camera) -> Option<Self> {
18846        core::ptr::NonNull::new(raw).map(|raw| Camera { raw })
18847    }
18848}
18849
18850// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
18851// is deliberately NOT implemented — the C++ types make no documented
18852// guarantee about concurrent use, and claiming one we haven't verified
18853// would be unsound. See `@bind thread_safe` in the plan.
18854unsafe impl Send for Camera {}
18855
18856impl core::fmt::Debug for Camera {
18857    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18858        f.debug_struct("Camera").finish_non_exhaustive()
18859    }
18860}
18861
18862impl Camera {
18863    /// # Panics
18864    /// Panics if the native allocation fails.
18865    pub fn new() -> Self {
18866        // SAFETY: the native constructor returns a live handle; a null here
18867        // means the library is unusable.
18868        unsafe {
18869            let raw = ffi::whiteout_m3_M3Camera_new();
18870            Self::from_raw(raw).expect("native Camera allocation failed")
18871        }
18872    }
18873
18874    /// Index into BONE array
18875    pub fn bone_index(&self) -> u32 {
18876        // SAFETY: plain scalar read through a live handle.
18877        unsafe { ffi::whiteout_m3_M3Camera_get_boneIndex(self.raw.as_ptr()) }
18878    }
18879
18880    pub fn set_bone_index(&mut self, value: u32) {
18881        // SAFETY: plain scalar write through a live handle.
18882        unsafe { ffi::whiteout_m3_M3Camera_set_boneIndex(self.raw.as_ptr(), value) }
18883    }
18884
18885    /// Camera name (`Ref<CHAR>`)
18886    pub fn name(&self) -> String {
18887        // SAFETY: the native side hands over an owned CString.
18888        unsafe {
18889            crate::support::take_string(ffi::whiteout_m3_M3Camera_get_name(self.raw.as_ptr()))
18890        }
18891    }
18892
18893    pub fn set_name(&mut self, value: &str) {
18894        let value = std::ffi::CString::new(value).unwrap_or_default();
18895        // SAFETY: the pointer outlives the call.
18896        unsafe { ffi::whiteout_m3_M3Camera_set_name(self.raw.as_ptr(), value.as_ptr()) }
18897    }
18898
18899    /// Animated FOV in radians (v2+)
18900    /// Borrows the field in place — no copy, no allocation.
18901    pub fn field_of_view(&self) -> crate::support::Ref<'_, AnimRefF32> {
18902        // SAFETY: an interior pointer into `self`, valid for this
18903        // borrow and never freed by the `Ref`.
18904        unsafe {
18905            crate::support::Ref::new(AnimRefF32 {
18906                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_fieldOfView(
18907                    self.raw.as_ptr(),
18908                )),
18909            })
18910        }
18911    }
18912
18913    pub fn field_of_view_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18914        // SAFETY: as above; `&mut self` guarantees exclusivity.
18915        unsafe {
18916            crate::support::RefMut::new(AnimRefF32 {
18917                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_fieldOfView(
18918                    self.raw.as_ptr(),
18919                )),
18920            })
18921        }
18922    }
18923
18924    /// Use vertical FOV (0 or 1, v2+)
18925    pub fn use_vertical_fov(&self) -> u32 {
18926        // SAFETY: plain scalar read through a live handle.
18927        unsafe { ffi::whiteout_m3_M3Camera_get_useVerticalFOV(self.raw.as_ptr()) }
18928    }
18929
18930    pub fn set_use_vertical_fov(&mut self, value: u32) {
18931        // SAFETY: plain scalar write through a live handle.
18932        unsafe { ffi::whiteout_m3_M3Camera_set_useVerticalFOV(self.raw.as_ptr(), value) }
18933    }
18934
18935    /// DOF type (v5 only, default 3)
18936    pub fn dof_type(&self) -> u32 {
18937        // SAFETY: plain scalar read through a live handle.
18938        unsafe { ffi::whiteout_m3_M3Camera_get_dofType(self.raw.as_ptr()) }
18939    }
18940
18941    pub fn set_dof_type(&mut self, value: u32) {
18942        // SAFETY: plain scalar write through a live handle.
18943        unsafe { ffi::whiteout_m3_M3Camera_set_dofType(self.raw.as_ptr(), value) }
18944    }
18945
18946    /// Animated far clip plane (v3+)
18947    /// Borrows the field in place — no copy, no allocation.
18948    pub fn far_clip(&self) -> crate::support::Ref<'_, AnimRefF32> {
18949        // SAFETY: an interior pointer into `self`, valid for this
18950        // borrow and never freed by the `Ref`.
18951        unsafe {
18952            crate::support::Ref::new(AnimRefF32 {
18953                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_farClip(
18954                    self.raw.as_ptr(),
18955                )),
18956            })
18957        }
18958    }
18959
18960    pub fn far_clip_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18961        // SAFETY: as above; `&mut self` guarantees exclusivity.
18962        unsafe {
18963            crate::support::RefMut::new(AnimRefF32 {
18964                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_farClip(
18965                    self.raw.as_ptr(),
18966                )),
18967            })
18968        }
18969    }
18970
18971    /// Animated near clip plane (v3+)
18972    /// Borrows the field in place — no copy, no allocation.
18973    pub fn near_clip(&self) -> crate::support::Ref<'_, AnimRefF32> {
18974        // SAFETY: an interior pointer into `self`, valid for this
18975        // borrow and never freed by the `Ref`.
18976        unsafe {
18977            crate::support::Ref::new(AnimRefF32 {
18978                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_nearClip(
18979                    self.raw.as_ptr(),
18980                )),
18981            })
18982        }
18983    }
18984
18985    pub fn near_clip_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
18986        // SAFETY: as above; `&mut self` guarantees exclusivity.
18987        unsafe {
18988            crate::support::RefMut::new(AnimRefF32 {
18989                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_nearClip(
18990                    self.raw.as_ptr(),
18991                )),
18992            })
18993        }
18994    }
18995
18996    /// Animated shadow clip distance (v2+)
18997    /// Borrows the field in place — no copy, no allocation.
18998    pub fn shadow_clip_distance(&self) -> crate::support::Ref<'_, AnimRefF32> {
18999        // SAFETY: an interior pointer into `self`, valid for this
19000        // borrow and never freed by the `Ref`.
19001        unsafe {
19002            crate::support::Ref::new(AnimRefF32 {
19003                raw: core::ptr::NonNull::new_unchecked(
19004                    ffi::whiteout_m3_M3Camera_get_shadowClipDistance(self.raw.as_ptr()),
19005                ),
19006            })
19007        }
19008    }
19009
19010    pub fn shadow_clip_distance_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19011        // SAFETY: as above; `&mut self` guarantees exclusivity.
19012        unsafe {
19013            crate::support::RefMut::new(AnimRefF32 {
19014                raw: core::ptr::NonNull::new_unchecked(
19015                    ffi::whiteout_m3_M3Camera_get_shadowClipDistance(self.raw.as_ptr()),
19016                ),
19017            })
19018        }
19019    }
19020
19021    /// Animated DOF focal point distance (v2+)
19022    /// Borrows the field in place — no copy, no allocation.
19023    pub fn focus_distance(&self) -> crate::support::Ref<'_, AnimRefF32> {
19024        // SAFETY: an interior pointer into `self`, valid for this
19025        // borrow and never freed by the `Ref`.
19026        unsafe {
19027            crate::support::Ref::new(AnimRefF32 {
19028                raw: core::ptr::NonNull::new_unchecked(
19029                    ffi::whiteout_m3_M3Camera_get_focusDistance(self.raw.as_ptr()),
19030                ),
19031            })
19032        }
19033    }
19034
19035    pub fn focus_distance_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19036        // SAFETY: as above; `&mut self` guarantees exclusivity.
19037        unsafe {
19038            crate::support::RefMut::new(AnimRefF32 {
19039                raw: core::ptr::NonNull::new_unchecked(
19040                    ffi::whiteout_m3_M3Camera_get_focusDistance(self.raw.as_ptr()),
19041                ),
19042            })
19043        }
19044    }
19045
19046    /// Animated DOF far focus range (v2+)
19047    /// Borrows the field in place — no copy, no allocation.
19048    pub fn far_focus_range(&self) -> crate::support::Ref<'_, AnimRefF32> {
19049        // SAFETY: an interior pointer into `self`, valid for this
19050        // borrow and never freed by the `Ref`.
19051        unsafe {
19052            crate::support::Ref::new(AnimRefF32 {
19053                raw: core::ptr::NonNull::new_unchecked(
19054                    ffi::whiteout_m3_M3Camera_get_farFocusRange(self.raw.as_ptr()),
19055                ),
19056            })
19057        }
19058    }
19059
19060    pub fn far_focus_range_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19061        // SAFETY: as above; `&mut self` guarantees exclusivity.
19062        unsafe {
19063            crate::support::RefMut::new(AnimRefF32 {
19064                raw: core::ptr::NonNull::new_unchecked(
19065                    ffi::whiteout_m3_M3Camera_get_farFocusRange(self.raw.as_ptr()),
19066                ),
19067            })
19068        }
19069    }
19070
19071    /// Animated DOF near focus range (v2+)
19072    /// Borrows the field in place — no copy, no allocation.
19073    pub fn near_focus_range(&self) -> crate::support::Ref<'_, AnimRefF32> {
19074        // SAFETY: an interior pointer into `self`, valid for this
19075        // borrow and never freed by the `Ref`.
19076        unsafe {
19077            crate::support::Ref::new(AnimRefF32 {
19078                raw: core::ptr::NonNull::new_unchecked(
19079                    ffi::whiteout_m3_M3Camera_get_nearFocusRange(self.raw.as_ptr()),
19080                ),
19081            })
19082        }
19083    }
19084
19085    pub fn near_focus_range_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19086        // SAFETY: as above; `&mut self` guarantees exclusivity.
19087        unsafe {
19088            crate::support::RefMut::new(AnimRefF32 {
19089                raw: core::ptr::NonNull::new_unchecked(
19090                    ffi::whiteout_m3_M3Camera_get_nearFocusRange(self.raw.as_ptr()),
19091                ),
19092            })
19093        }
19094    }
19095
19096    /// Animated near falloff start (v4+)
19097    /// Borrows the field in place — no copy, no allocation.
19098    pub fn near_falloff_start(&self) -> crate::support::Ref<'_, AnimRefF32> {
19099        // SAFETY: an interior pointer into `self`, valid for this
19100        // borrow and never freed by the `Ref`.
19101        unsafe {
19102            crate::support::Ref::new(AnimRefF32 {
19103                raw: core::ptr::NonNull::new_unchecked(
19104                    ffi::whiteout_m3_M3Camera_get_nearFalloffStart(self.raw.as_ptr()),
19105                ),
19106            })
19107        }
19108    }
19109
19110    pub fn near_falloff_start_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19111        // SAFETY: as above; `&mut self` guarantees exclusivity.
19112        unsafe {
19113            crate::support::RefMut::new(AnimRefF32 {
19114                raw: core::ptr::NonNull::new_unchecked(
19115                    ffi::whiteout_m3_M3Camera_get_nearFalloffStart(self.raw.as_ptr()),
19116                ),
19117            })
19118        }
19119    }
19120
19121    /// Animated near falloff end (v4+)
19122    /// Borrows the field in place — no copy, no allocation.
19123    pub fn near_falloff_end(&self) -> crate::support::Ref<'_, AnimRefF32> {
19124        // SAFETY: an interior pointer into `self`, valid for this
19125        // borrow and never freed by the `Ref`.
19126        unsafe {
19127            crate::support::Ref::new(AnimRefF32 {
19128                raw: core::ptr::NonNull::new_unchecked(
19129                    ffi::whiteout_m3_M3Camera_get_nearFalloffEnd(self.raw.as_ptr()),
19130                ),
19131            })
19132        }
19133    }
19134
19135    pub fn near_falloff_end_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19136        // SAFETY: as above; `&mut self` guarantees exclusivity.
19137        unsafe {
19138            crate::support::RefMut::new(AnimRefF32 {
19139                raw: core::ptr::NonNull::new_unchecked(
19140                    ffi::whiteout_m3_M3Camera_get_nearFalloffEnd(self.raw.as_ptr()),
19141                ),
19142            })
19143        }
19144    }
19145
19146    /// Animated DOF strength (v2+)
19147    /// Borrows the field in place — no copy, no allocation.
19148    pub fn dof_amount(&self) -> crate::support::Ref<'_, AnimRefF32> {
19149        // SAFETY: an interior pointer into `self`, valid for this
19150        // borrow and never freed by the `Ref`.
19151        unsafe {
19152            crate::support::Ref::new(AnimRefF32 {
19153                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_dofAmount(
19154                    self.raw.as_ptr(),
19155                )),
19156            })
19157        }
19158    }
19159
19160    pub fn dof_amount_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19161        // SAFETY: as above; `&mut self` guarantees exclusivity.
19162        unsafe {
19163            crate::support::RefMut::new(AnimRefF32 {
19164                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_dofAmount(
19165                    self.raw.as_ptr(),
19166                )),
19167            })
19168        }
19169    }
19170
19171    /// Animated bokeh f-stop (v5+)
19172    /// Borrows the field in place — no copy, no allocation.
19173    pub fn bokeh_f_stop(&self) -> crate::support::Ref<'_, AnimRefF32> {
19174        // SAFETY: an interior pointer into `self`, valid for this
19175        // borrow and never freed by the `Ref`.
19176        unsafe {
19177            crate::support::Ref::new(AnimRefF32 {
19178                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_bokehFStop(
19179                    self.raw.as_ptr(),
19180                )),
19181            })
19182        }
19183    }
19184
19185    pub fn bokeh_f_stop_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19186        // SAFETY: as above; `&mut self` guarantees exclusivity.
19187        unsafe {
19188            crate::support::RefMut::new(AnimRefF32 {
19189                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Camera_get_bokehFStop(
19190                    self.raw.as_ptr(),
19191                )),
19192            })
19193        }
19194    }
19195
19196    /// Animated bokeh max CoC diameter (v5+)
19197    /// Borrows the field in place — no copy, no allocation.
19198    pub fn bokeh_max_co_c_diameter(&self) -> crate::support::Ref<'_, AnimRefF32> {
19199        // SAFETY: an interior pointer into `self`, valid for this
19200        // borrow and never freed by the `Ref`.
19201        unsafe {
19202            crate::support::Ref::new(AnimRefF32 {
19203                raw: core::ptr::NonNull::new_unchecked(
19204                    ffi::whiteout_m3_M3Camera_get_bokehMaxCoCDiameter(self.raw.as_ptr()),
19205                ),
19206            })
19207        }
19208    }
19209
19210    pub fn bokeh_max_co_c_diameter_mut(&mut self) -> crate::support::RefMut<'_, AnimRefF32> {
19211        // SAFETY: as above; `&mut self` guarantees exclusivity.
19212        unsafe {
19213            crate::support::RefMut::new(AnimRefF32 {
19214                raw: core::ptr::NonNull::new_unchecked(
19215                    ffi::whiteout_m3_M3Camera_get_bokehMaxCoCDiameter(self.raw.as_ptr()),
19216                ),
19217            })
19218        }
19219    }
19220}
19221
19222impl Default for Camera {
19223    fn default() -> Self {
19224        Self::new()
19225    }
19226}
19227
19228/// MODL — Model root chunk (v23–v30, 784–868 bytes)
19229///
19230/// The root of all model data. Contains `Ref<T>` fields pointing to every sub-chunk in the file: skeleton, mesh, materials, particles, physics, etc. The preamble (bytes 0x000–0x0E3) is identical across all versions; version-dependent material and physics references follow at 0x0E4+.
19231///
19232/// Version history: - v23 (784 bytes): Base release layout - v24 (+ikCCD): 796 bytes - v25 (+volumeNoiseMaterials): 808 bytes - v26 (+stbMaterials): 820 bytes - v28 (+reflectionMaterials, +clothPhysics): 844 bytes - v29 (+lensFlareMaterials): 856 bytes - v30 (+dataDrivenMaterials): 868 bytes
19233pub struct Model {
19234    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Model>,
19235}
19236
19237impl Drop for Model {
19238    fn drop(&mut self) {
19239        // SAFETY: `raw` came from a native constructor and Drop runs once.
19240        unsafe { ffi::whiteout_m3_M3Model_delete(self.raw.as_ptr()) }
19241    }
19242}
19243
19244impl Model {
19245    /// # Safety
19246    /// `raw` must be a live handle this value takes ownership of.
19247    #[allow(dead_code)] // used by whichever methods return this type
19248    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Model) -> Option<Self> {
19249        core::ptr::NonNull::new(raw).map(|raw| Model { raw })
19250    }
19251}
19252
19253// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
19254// is deliberately NOT implemented — the C++ types make no documented
19255// guarantee about concurrent use, and claiming one we haven't verified
19256// would be unsound. See `@bind thread_safe` in the plan.
19257unsafe impl Send for Model {}
19258
19259impl core::fmt::Debug for Model {
19260    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19261        f.debug_struct("Model").finish_non_exhaustive()
19262    }
19263}
19264
19265impl Model {
19266    /// # Panics
19267    /// Panics if the native allocation fails.
19268    pub fn new() -> Self {
19269        // SAFETY: the native constructor returns a live handle; a null here
19270        // means the library is unusable.
19271        unsafe {
19272            let raw = ffi::whiteout_m3_M3Model_new();
19273            Self::from_raw(raw).expect("native Model allocation failed")
19274        }
19275    }
19276
19277    /// Model file path (`Ref<CHAR>`)
19278    pub fn name(&self) -> String {
19279        // SAFETY: the native side hands over an owned CString.
19280        unsafe { crate::support::take_string(ffi::whiteout_m3_M3Model_get_name(self.raw.as_ptr())) }
19281    }
19282
19283    pub fn set_name(&mut self, value: &str) {
19284        let value = std::ffi::CString::new(value).unwrap_or_default();
19285        // SAFETY: the pointer outlives the call.
19286        unsafe { ffi::whiteout_m3_M3Model_set_name(self.raw.as_ptr(), value.as_ptr()) }
19287    }
19288
19289    /// Not `None`: only 21 of the corpus's 56,146 models leave this at zero. These three are latches saying "this work is already done, do not redo it", and the converter does all three -- it sorts every `STC_`'s animIds, states `kAnimRefBound` on every bound AnimRef, and derives every `BONE.flags` from those (`m3_anim::SolveBoneAnimFlags`). The rest of the shipped bits are left clear so the editor recomputes them. A parsed or restored model overwrites this wholesale.
19290    pub fn flags(&self) -> ModelFlag {
19291        // SAFETY: scalar read; a flag set accepts any bits.
19292        ModelFlag(unsafe { ffi::whiteout_m3_M3Model_get_flags(self.raw.as_ptr()) })
19293    }
19294
19295    pub fn set_flags(&mut self, value: ModelFlag) {
19296        // SAFETY: scalar write through a live handle.
19297        unsafe { ffi::whiteout_m3_M3Model_set_flags(self.raw.as_ptr(), value.0) }
19298    }
19299
19300    /// Animation sequences (SEQS)
19301    pub fn sequences_len(&self) -> usize {
19302        // SAFETY: scalar read through a live handle.
19303        unsafe { ffi::whiteout_m3_M3Model_get_sequences_count(self.raw.as_ptr()) }
19304    }
19305
19306    /// Borrows element `index` in place. `None` when out of range.
19307    pub fn sequences(&self, index: usize) -> Option<crate::support::Ref<'_, Sequence>> {
19308        if index >= self.sequences_len() {
19309            return None;
19310        }
19311        // SAFETY: index checked above; the pointer is interior to `self`.
19312        unsafe {
19313            Some(crate::support::Ref::new(Sequence {
19314                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_sequences_at(
19315                    self.raw.as_ptr(),
19316                    index,
19317                )),
19318            }))
19319        }
19320    }
19321
19322    pub fn sequences_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Sequence>> {
19323        if index >= self.sequences_len() {
19324            return None;
19325        }
19326        // SAFETY: as above; `&mut self` guarantees exclusivity.
19327        unsafe {
19328            Some(crate::support::RefMut::new(Sequence {
19329                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_sequences_at(
19330                    self.raw.as_ptr(),
19331                    index,
19332                )),
19333            }))
19334        }
19335    }
19336
19337    /// Iterate the elements, borrowing each in turn.
19338    pub fn sequences_iter(
19339        &self,
19340    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Sequence>> {
19341        (0..self.sequences_len()).map(move |i| self.sequences(i).expect("index below len"))
19342    }
19343
19344    pub fn resize_sequences(&mut self, count: usize) {
19345        // SAFETY: exclusive access, so no borrow is outstanding.
19346        unsafe { ffi::whiteout_m3_M3Model_resize_sequences(self.raw.as_ptr(), count) }
19347    }
19348
19349    /// Sub-track containers (STC_) with keyframe refs
19350    pub fn sub_track_collections_len(&self) -> usize {
19351        // SAFETY: scalar read through a live handle.
19352        unsafe { ffi::whiteout_m3_M3Model_get_subTrackCollections_count(self.raw.as_ptr()) }
19353    }
19354
19355    /// Borrows element `index` in place. `None` when out of range.
19356    pub fn sub_track_collections(
19357        &self,
19358        index: usize,
19359    ) -> Option<crate::support::Ref<'_, SubTrackContainer>> {
19360        if index >= self.sub_track_collections_len() {
19361            return None;
19362        }
19363        // SAFETY: index checked above; the pointer is interior to `self`.
19364        unsafe {
19365            Some(crate::support::Ref::new(SubTrackContainer {
19366                raw: core::ptr::NonNull::new_unchecked(
19367                    ffi::whiteout_m3_M3Model_get_subTrackCollections_at(self.raw.as_ptr(), index),
19368                ),
19369            }))
19370        }
19371    }
19372
19373    pub fn sub_track_collections_mut(
19374        &mut self,
19375        index: usize,
19376    ) -> Option<crate::support::RefMut<'_, SubTrackContainer>> {
19377        if index >= self.sub_track_collections_len() {
19378            return None;
19379        }
19380        // SAFETY: as above; `&mut self` guarantees exclusivity.
19381        unsafe {
19382            Some(crate::support::RefMut::new(SubTrackContainer {
19383                raw: core::ptr::NonNull::new_unchecked(
19384                    ffi::whiteout_m3_M3Model_get_subTrackCollections_at(self.raw.as_ptr(), index),
19385                ),
19386            }))
19387        }
19388    }
19389
19390    /// Iterate the elements, borrowing each in turn.
19391    pub fn sub_track_collections_iter(
19392        &self,
19393    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SubTrackContainer>> {
19394        (0..self.sub_track_collections_len())
19395            .map(move |i| self.sub_track_collections(i).expect("index below len"))
19396    }
19397
19398    pub fn resize_sub_track_collections(&mut self, count: usize) {
19399        // SAFETY: exclusive access, so no borrow is outstanding.
19400        unsafe { ffi::whiteout_m3_M3Model_resize_subTrackCollections(self.raw.as_ptr(), count) }
19401    }
19402
19403    /// Animation groups (STG_)
19404    pub fn animation_groups_len(&self) -> usize {
19405        // SAFETY: scalar read through a live handle.
19406        unsafe { ffi::whiteout_m3_M3Model_get_animationGroups_count(self.raw.as_ptr()) }
19407    }
19408
19409    /// Borrows element `index` in place. `None` when out of range.
19410    pub fn animation_groups(
19411        &self,
19412        index: usize,
19413    ) -> Option<crate::support::Ref<'_, AnimationGroup>> {
19414        if index >= self.animation_groups_len() {
19415            return None;
19416        }
19417        // SAFETY: index checked above; the pointer is interior to `self`.
19418        unsafe {
19419            Some(crate::support::Ref::new(AnimationGroup {
19420                raw: core::ptr::NonNull::new_unchecked(
19421                    ffi::whiteout_m3_M3Model_get_animationGroups_at(self.raw.as_ptr(), index),
19422                ),
19423            }))
19424        }
19425    }
19426
19427    pub fn animation_groups_mut(
19428        &mut self,
19429        index: usize,
19430    ) -> Option<crate::support::RefMut<'_, AnimationGroup>> {
19431        if index >= self.animation_groups_len() {
19432            return None;
19433        }
19434        // SAFETY: as above; `&mut self` guarantees exclusivity.
19435        unsafe {
19436            Some(crate::support::RefMut::new(AnimationGroup {
19437                raw: core::ptr::NonNull::new_unchecked(
19438                    ffi::whiteout_m3_M3Model_get_animationGroups_at(self.raw.as_ptr(), index),
19439                ),
19440            }))
19441        }
19442    }
19443
19444    /// Iterate the elements, borrowing each in turn.
19445    pub fn animation_groups_iter(
19446        &self,
19447    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AnimationGroup>> {
19448        (0..self.animation_groups_len())
19449            .map(move |i| self.animation_groups(i).expect("index below len"))
19450    }
19451
19452    pub fn resize_animation_groups(&mut self, count: usize) {
19453        // SAFETY: exclusive access, so no borrow is outstanding.
19454        unsafe { ffi::whiteout_m3_M3Model_resize_animationGroups(self.raw.as_ptr(), count) }
19455    }
19456
19457    /// Bone animation sets (BSET, always null)
19458    pub fn bone_animation_sets_len(&self) -> usize {
19459        // SAFETY: scalar read through a live handle.
19460        unsafe { ffi::whiteout_m3_M3Model_get_boneAnimationSets_count(self.raw.as_ptr()) }
19461    }
19462
19463    /// Borrows element `index` in place. `None` when out of range.
19464    pub fn bone_animation_sets(
19465        &self,
19466        index: usize,
19467    ) -> Option<crate::support::Ref<'_, BoneAnimationSet>> {
19468        if index >= self.bone_animation_sets_len() {
19469            return None;
19470        }
19471        // SAFETY: index checked above; the pointer is interior to `self`.
19472        unsafe {
19473            Some(crate::support::Ref::new(BoneAnimationSet {
19474                raw: core::ptr::NonNull::new_unchecked(
19475                    ffi::whiteout_m3_M3Model_get_boneAnimationSets_at(self.raw.as_ptr(), index),
19476                ),
19477            }))
19478        }
19479    }
19480
19481    pub fn bone_animation_sets_mut(
19482        &mut self,
19483        index: usize,
19484    ) -> Option<crate::support::RefMut<'_, BoneAnimationSet>> {
19485        if index >= self.bone_animation_sets_len() {
19486            return None;
19487        }
19488        // SAFETY: as above; `&mut self` guarantees exclusivity.
19489        unsafe {
19490            Some(crate::support::RefMut::new(BoneAnimationSet {
19491                raw: core::ptr::NonNull::new_unchecked(
19492                    ffi::whiteout_m3_M3Model_get_boneAnimationSets_at(self.raw.as_ptr(), index),
19493                ),
19494            }))
19495        }
19496    }
19497
19498    /// Iterate the elements, borrowing each in turn.
19499    pub fn bone_animation_sets_iter(
19500        &self,
19501    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, BoneAnimationSet>> {
19502        (0..self.bone_animation_sets_len())
19503            .map(move |i| self.bone_animation_sets(i).expect("index below len"))
19504    }
19505
19506    pub fn resize_bone_animation_sets(&mut self, count: usize) {
19507        // SAFETY: exclusive access, so no borrow is outstanding.
19508        unsafe { ffi::whiteout_m3_M3Model_resize_boneAnimationSets(self.raw.as_ptr(), count) }
19509    }
19510
19511    /// Always 0
19512    pub fn animation_split_count(&self) -> u32 {
19513        // SAFETY: plain scalar read through a live handle.
19514        unsafe { ffi::whiteout_m3_M3Model_get_animationSplitCount(self.raw.as_ptr()) }
19515    }
19516
19517    pub fn set_animation_split_count(&mut self, value: u32) {
19518        // SAFETY: plain scalar write through a live handle.
19519        unsafe { ffi::whiteout_m3_M3Model_set_animationSplitCount(self.raw.as_ptr(), value) }
19520    }
19521
19522    /// Animation states (STS_)
19523    pub fn animation_states_len(&self) -> usize {
19524        // SAFETY: scalar read through a live handle.
19525        unsafe { ffi::whiteout_m3_M3Model_get_animationStates_count(self.raw.as_ptr()) }
19526    }
19527
19528    /// Borrows element `index` in place. `None` when out of range.
19529    pub fn animation_states(
19530        &self,
19531        index: usize,
19532    ) -> Option<crate::support::Ref<'_, AnimationState>> {
19533        if index >= self.animation_states_len() {
19534            return None;
19535        }
19536        // SAFETY: index checked above; the pointer is interior to `self`.
19537        unsafe {
19538            Some(crate::support::Ref::new(AnimationState {
19539                raw: core::ptr::NonNull::new_unchecked(
19540                    ffi::whiteout_m3_M3Model_get_animationStates_at(self.raw.as_ptr(), index),
19541                ),
19542            }))
19543        }
19544    }
19545
19546    pub fn animation_states_mut(
19547        &mut self,
19548        index: usize,
19549    ) -> Option<crate::support::RefMut<'_, AnimationState>> {
19550        if index >= self.animation_states_len() {
19551            return None;
19552        }
19553        // SAFETY: as above; `&mut self` guarantees exclusivity.
19554        unsafe {
19555            Some(crate::support::RefMut::new(AnimationState {
19556                raw: core::ptr::NonNull::new_unchecked(
19557                    ffi::whiteout_m3_M3Model_get_animationStates_at(self.raw.as_ptr(), index),
19558                ),
19559            }))
19560        }
19561    }
19562
19563    /// Iterate the elements, borrowing each in turn.
19564    pub fn animation_states_iter(
19565        &self,
19566    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AnimationState>> {
19567        (0..self.animation_states_len())
19568            .map(move |i| self.animation_states(i).expect("index below len"))
19569    }
19570
19571    pub fn resize_animation_states(&mut self, count: usize) {
19572        // SAFETY: exclusive access, so no borrow is outstanding.
19573        unsafe { ffi::whiteout_m3_M3Model_resize_animationStates(self.raw.as_ptr(), count) }
19574    }
19575
19576    /// Skeleton bones (BONE)
19577    pub fn bones_len(&self) -> usize {
19578        // SAFETY: scalar read through a live handle.
19579        unsafe { ffi::whiteout_m3_M3Model_get_bones_count(self.raw.as_ptr()) }
19580    }
19581
19582    /// Borrows element `index` in place. `None` when out of range.
19583    pub fn bones(&self, index: usize) -> Option<crate::support::Ref<'_, Bone>> {
19584        if index >= self.bones_len() {
19585            return None;
19586        }
19587        // SAFETY: index checked above; the pointer is interior to `self`.
19588        unsafe {
19589            Some(crate::support::Ref::new(Bone {
19590                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_bones_at(
19591                    self.raw.as_ptr(),
19592                    index,
19593                )),
19594            }))
19595        }
19596    }
19597
19598    pub fn bones_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Bone>> {
19599        if index >= self.bones_len() {
19600            return None;
19601        }
19602        // SAFETY: as above; `&mut self` guarantees exclusivity.
19603        unsafe {
19604            Some(crate::support::RefMut::new(Bone {
19605                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_bones_at(
19606                    self.raw.as_ptr(),
19607                    index,
19608                )),
19609            }))
19610        }
19611    }
19612
19613    /// Iterate the elements, borrowing each in turn.
19614    pub fn bones_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Bone>> {
19615        (0..self.bones_len()).map(move |i| self.bones(i).expect("index below len"))
19616    }
19617
19618    pub fn resize_bones(&mut self, count: usize) {
19619        // SAFETY: exclusive access, so no borrow is outstanding.
19620        unsafe { ffi::whiteout_m3_M3Model_resize_bones(self.raw.as_ptr(), count) }
19621    }
19622
19623    /// Number of bones affecting skin
19624    pub fn skin_bone_count(&self) -> u32 {
19625        // SAFETY: plain scalar read through a live handle.
19626        unsafe { ffi::whiteout_m3_M3Model_get_skinBoneCount(self.raw.as_ptr()) }
19627    }
19628
19629    pub fn set_skin_bone_count(&mut self, value: u32) {
19630        // SAFETY: plain scalar write through a live handle.
19631        unsafe { ffi::whiteout_m3_M3Model_set_skinBoneCount(self.raw.as_ptr(), value) }
19632    }
19633
19634    /// Mesh divisions (DIV_: faces, regions, batches)
19635    pub fn divisions_len(&self) -> usize {
19636        // SAFETY: scalar read through a live handle.
19637        unsafe { ffi::whiteout_m3_M3Model_get_divisions_count(self.raw.as_ptr()) }
19638    }
19639
19640    /// Borrows element `index` in place. `None` when out of range.
19641    pub fn divisions(&self, index: usize) -> Option<crate::support::Ref<'_, MeshDivision>> {
19642        if index >= self.divisions_len() {
19643            return None;
19644        }
19645        // SAFETY: index checked above; the pointer is interior to `self`.
19646        unsafe {
19647            Some(crate::support::Ref::new(MeshDivision {
19648                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_divisions_at(
19649                    self.raw.as_ptr(),
19650                    index,
19651                )),
19652            }))
19653        }
19654    }
19655
19656    pub fn divisions_mut(
19657        &mut self,
19658        index: usize,
19659    ) -> Option<crate::support::RefMut<'_, MeshDivision>> {
19660        if index >= self.divisions_len() {
19661            return None;
19662        }
19663        // SAFETY: as above; `&mut self` guarantees exclusivity.
19664        unsafe {
19665            Some(crate::support::RefMut::new(MeshDivision {
19666                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_divisions_at(
19667                    self.raw.as_ptr(),
19668                    index,
19669                )),
19670            }))
19671        }
19672    }
19673
19674    /// Iterate the elements, borrowing each in turn.
19675    pub fn divisions_iter(
19676        &self,
19677    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, MeshDivision>> {
19678        (0..self.divisions_len()).map(move |i| self.divisions(i).expect("index below len"))
19679    }
19680
19681    pub fn resize_divisions(&mut self, count: usize) {
19682        // SAFETY: exclusive access, so no borrow is outstanding.
19683        unsafe { ffi::whiteout_m3_M3Model_resize_divisions(self.raw.as_ptr(), count) }
19684    }
19685
19686    /// Bone index remap table (U16_)
19687    /// Zero-copy view of the underlying `std::vector`.
19688    pub fn bone_lookup(&self) -> &[u16] {
19689        // SAFETY: `_data`/`_count` describe one contiguous C++
19690        // allocation, borrowed for as long as `self` is.
19691        unsafe {
19692            let n = ffi::whiteout_m3_M3Model_get_boneLookup_count(self.raw.as_ptr());
19693            let p = ffi::whiteout_m3_M3Model_get_boneLookup_data(self.raw.as_ptr());
19694            if p.is_null() || n == 0 {
19695                &[]
19696            } else {
19697                core::slice::from_raw_parts(p, n)
19698            }
19699        }
19700    }
19701
19702    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
19703    pub fn bone_lookup_mut(&mut self) -> &mut [u16] {
19704        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
19705        unsafe {
19706            let n = ffi::whiteout_m3_M3Model_get_boneLookup_count(self.raw.as_ptr());
19707            let p = ffi::whiteout_m3_M3Model_get_boneLookup_data(self.raw.as_ptr()) as *mut u16;
19708            if p.is_null() || n == 0 {
19709                &mut []
19710            } else {
19711                core::slice::from_raw_parts_mut(p, n)
19712            }
19713        }
19714    }
19715
19716    pub fn set_bone_lookup(&mut self, values: &[u16]) {
19717        // SAFETY: the native side copies `values` before returning.
19718        unsafe {
19719            ffi::whiteout_m3_M3Model_assign_boneLookup(
19720                self.raw.as_ptr(),
19721                values.as_ptr() as *const _,
19722                values.len(),
19723            )
19724        }
19725    }
19726
19727    pub fn resize_bone_lookup(&mut self, count: usize) {
19728        // SAFETY: reallocation is safe here precisely because
19729        // `&mut self` means no slice borrow is outstanding.
19730        unsafe { ffi::whiteout_m3_M3Model_resize_boneLookup(self.raw.as_ptr(), count) }
19731    }
19732
19733    /// Model bounding volume
19734    /// Borrows the field in place — no copy, no allocation.
19735    pub fn bounds(&self) -> crate::support::Ref<'_, Extent> {
19736        // SAFETY: an interior pointer into `self`, valid for this
19737        // borrow and never freed by the `Ref`.
19738        unsafe {
19739            crate::support::Ref::new(Extent {
19740                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_bounds(
19741                    self.raw.as_ptr(),
19742                )),
19743            })
19744        }
19745    }
19746
19747    pub fn bounds_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
19748        // SAFETY: as above; `&mut self` guarantees exclusivity.
19749        unsafe {
19750            crate::support::RefMut::new(Extent {
19751                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_bounds(
19752                    self.raw.as_ptr(),
19753                )),
19754            })
19755        }
19756    }
19757
19758    /// Collision bounding volume
19759    /// Borrows the field in place — no copy, no allocation.
19760    pub fn collision_bounds(&self) -> crate::support::Ref<'_, Extent> {
19761        // SAFETY: an interior pointer into `self`, valid for this
19762        // borrow and never freed by the `Ref`.
19763        unsafe {
19764            crate::support::Ref::new(Extent {
19765                raw: core::ptr::NonNull::new_unchecked(
19766                    ffi::whiteout_m3_M3Model_get_collisionBounds(self.raw.as_ptr()),
19767                ),
19768            })
19769        }
19770    }
19771
19772    pub fn collision_bounds_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
19773        // SAFETY: as above; `&mut self` guarantees exclusivity.
19774        unsafe {
19775            crate::support::RefMut::new(Extent {
19776                raw: core::ptr::NonNull::new_unchecked(
19777                    ffi::whiteout_m3_M3Model_get_collisionBounds(self.raw.as_ptr()),
19778                ),
19779            })
19780        }
19781    }
19782
19783    /// Collision triangle indices (U16_)
19784    /// Zero-copy view of the underlying `std::vector`.
19785    pub fn collision_faces(&self) -> &[u16] {
19786        // SAFETY: `_data`/`_count` describe one contiguous C++
19787        // allocation, borrowed for as long as `self` is.
19788        unsafe {
19789            let n = ffi::whiteout_m3_M3Model_get_collisionFaces_count(self.raw.as_ptr());
19790            let p = ffi::whiteout_m3_M3Model_get_collisionFaces_data(self.raw.as_ptr());
19791            if p.is_null() || n == 0 {
19792                &[]
19793            } else {
19794                core::slice::from_raw_parts(p, n)
19795            }
19796        }
19797    }
19798
19799    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
19800    pub fn collision_faces_mut(&mut self) -> &mut [u16] {
19801        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
19802        unsafe {
19803            let n = ffi::whiteout_m3_M3Model_get_collisionFaces_count(self.raw.as_ptr());
19804            let p = ffi::whiteout_m3_M3Model_get_collisionFaces_data(self.raw.as_ptr()) as *mut u16;
19805            if p.is_null() || n == 0 {
19806                &mut []
19807            } else {
19808                core::slice::from_raw_parts_mut(p, n)
19809            }
19810        }
19811    }
19812
19813    pub fn set_collision_faces(&mut self, values: &[u16]) {
19814        // SAFETY: the native side copies `values` before returning.
19815        unsafe {
19816            ffi::whiteout_m3_M3Model_assign_collisionFaces(
19817                self.raw.as_ptr(),
19818                values.as_ptr() as *const _,
19819                values.len(),
19820            )
19821        }
19822    }
19823
19824    pub fn resize_collision_faces(&mut self, count: usize) {
19825        // SAFETY: reallocation is safe here precisely because
19826        // `&mut self` means no slice borrow is outstanding.
19827        unsafe { ffi::whiteout_m3_M3Model_resize_collisionFaces(self.raw.as_ptr(), count) }
19828    }
19829
19830    /// Collision vertex positions (VEC3)
19831    /// Zero-copy view of the underlying `std::vector`.
19832    pub fn collision_verts(&self) -> &[crate::math::Vector3f] {
19833        // SAFETY: `_data`/`_count` describe one contiguous C++
19834        // allocation, borrowed for as long as `self` is.
19835        unsafe {
19836            let n = ffi::whiteout_m3_M3Model_get_collisionVerts_count(self.raw.as_ptr());
19837            let p = ffi::whiteout_m3_M3Model_get_collisionVerts_data(self.raw.as_ptr())
19838                as *const crate::math::Vector3f;
19839            if p.is_null() || n == 0 {
19840                &[]
19841            } else {
19842                core::slice::from_raw_parts(p, n)
19843            }
19844        }
19845    }
19846
19847    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
19848    pub fn collision_verts_mut(&mut self) -> &mut [crate::math::Vector3f] {
19849        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
19850        unsafe {
19851            let n = ffi::whiteout_m3_M3Model_get_collisionVerts_count(self.raw.as_ptr());
19852            let p = ffi::whiteout_m3_M3Model_get_collisionVerts_data(self.raw.as_ptr())
19853                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
19854            if p.is_null() || n == 0 {
19855                &mut []
19856            } else {
19857                core::slice::from_raw_parts_mut(p, n)
19858            }
19859        }
19860    }
19861
19862    pub fn set_collision_verts(&mut self, values: &[crate::math::Vector3f]) {
19863        // SAFETY: the native side copies `values` before returning.
19864        unsafe {
19865            ffi::whiteout_m3_M3Model_assign_collisionVerts(
19866                self.raw.as_ptr(),
19867                values.as_ptr() as *const _,
19868                values.len(),
19869            )
19870        }
19871    }
19872
19873    pub fn resize_collision_verts(&mut self, count: usize) {
19874        // SAFETY: reallocation is safe here precisely because
19875        // `&mut self` means no slice borrow is outstanding.
19876        unsafe { ffi::whiteout_m3_M3Model_resize_collisionVerts(self.raw.as_ptr(), count) }
19877    }
19878
19879    /// Collision face normals (VEC3)
19880    /// Zero-copy view of the underlying `std::vector`.
19881    pub fn collision_normals(&self) -> &[crate::math::Vector3f] {
19882        // SAFETY: `_data`/`_count` describe one contiguous C++
19883        // allocation, borrowed for as long as `self` is.
19884        unsafe {
19885            let n = ffi::whiteout_m3_M3Model_get_collisionNormals_count(self.raw.as_ptr());
19886            let p = ffi::whiteout_m3_M3Model_get_collisionNormals_data(self.raw.as_ptr())
19887                as *const crate::math::Vector3f;
19888            if p.is_null() || n == 0 {
19889                &[]
19890            } else {
19891                core::slice::from_raw_parts(p, n)
19892            }
19893        }
19894    }
19895
19896    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
19897    pub fn collision_normals_mut(&mut self) -> &mut [crate::math::Vector3f] {
19898        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
19899        unsafe {
19900            let n = ffi::whiteout_m3_M3Model_get_collisionNormals_count(self.raw.as_ptr());
19901            let p = ffi::whiteout_m3_M3Model_get_collisionNormals_data(self.raw.as_ptr())
19902                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
19903            if p.is_null() || n == 0 {
19904                &mut []
19905            } else {
19906                core::slice::from_raw_parts_mut(p, n)
19907            }
19908        }
19909    }
19910
19911    pub fn set_collision_normals(&mut self, values: &[crate::math::Vector3f]) {
19912        // SAFETY: the native side copies `values` before returning.
19913        unsafe {
19914            ffi::whiteout_m3_M3Model_assign_collisionNormals(
19915                self.raw.as_ptr(),
19916                values.as_ptr() as *const _,
19917                values.len(),
19918            )
19919        }
19920    }
19921
19922    pub fn resize_collision_normals(&mut self, count: usize) {
19923        // SAFETY: reallocation is safe here precisely because
19924        // `&mut self` means no slice borrow is outstanding.
19925        unsafe { ffi::whiteout_m3_M3Model_resize_collisionNormals(self.raw.as_ptr(), count) }
19926    }
19927
19928    /// Named bone locations (ATT_)
19929    pub fn attachment_points_len(&self) -> usize {
19930        // SAFETY: scalar read through a live handle.
19931        unsafe { ffi::whiteout_m3_M3Model_get_attachmentPoints_count(self.raw.as_ptr()) }
19932    }
19933
19934    /// Borrows element `index` in place. `None` when out of range.
19935    pub fn attachment_points(
19936        &self,
19937        index: usize,
19938    ) -> Option<crate::support::Ref<'_, AttachmentPoint>> {
19939        if index >= self.attachment_points_len() {
19940            return None;
19941        }
19942        // SAFETY: index checked above; the pointer is interior to `self`.
19943        unsafe {
19944            Some(crate::support::Ref::new(AttachmentPoint {
19945                raw: core::ptr::NonNull::new_unchecked(
19946                    ffi::whiteout_m3_M3Model_get_attachmentPoints_at(self.raw.as_ptr(), index),
19947                ),
19948            }))
19949        }
19950    }
19951
19952    pub fn attachment_points_mut(
19953        &mut self,
19954        index: usize,
19955    ) -> Option<crate::support::RefMut<'_, AttachmentPoint>> {
19956        if index >= self.attachment_points_len() {
19957            return None;
19958        }
19959        // SAFETY: as above; `&mut self` guarantees exclusivity.
19960        unsafe {
19961            Some(crate::support::RefMut::new(AttachmentPoint {
19962                raw: core::ptr::NonNull::new_unchecked(
19963                    ffi::whiteout_m3_M3Model_get_attachmentPoints_at(self.raw.as_ptr(), index),
19964                ),
19965            }))
19966        }
19967    }
19968
19969    /// Iterate the elements, borrowing each in turn.
19970    pub fn attachment_points_iter(
19971        &self,
19972    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AttachmentPoint>> {
19973        (0..self.attachment_points_len())
19974            .map(move |i| self.attachment_points(i).expect("index below len"))
19975    }
19976
19977    pub fn resize_attachment_points(&mut self, count: usize) {
19978        // SAFETY: exclusive access, so no borrow is outstanding.
19979        unsafe { ffi::whiteout_m3_M3Model_resize_attachmentPoints(self.raw.as_ptr(), count) }
19980    }
19981
19982    /// Attachment point addon indices (U16_)
19983    /// Zero-copy view of the underlying `std::vector`.
19984    pub fn attachment_point_addons(&self) -> &[u16] {
19985        // SAFETY: `_data`/`_count` describe one contiguous C++
19986        // allocation, borrowed for as long as `self` is.
19987        unsafe {
19988            let n = ffi::whiteout_m3_M3Model_get_attachmentPointAddons_count(self.raw.as_ptr());
19989            let p = ffi::whiteout_m3_M3Model_get_attachmentPointAddons_data(self.raw.as_ptr());
19990            if p.is_null() || n == 0 {
19991                &[]
19992            } else {
19993                core::slice::from_raw_parts(p, n)
19994            }
19995        }
19996    }
19997
19998    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
19999    pub fn attachment_point_addons_mut(&mut self) -> &mut [u16] {
20000        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
20001        unsafe {
20002            let n = ffi::whiteout_m3_M3Model_get_attachmentPointAddons_count(self.raw.as_ptr());
20003            let p = ffi::whiteout_m3_M3Model_get_attachmentPointAddons_data(self.raw.as_ptr())
20004                as *mut u16;
20005            if p.is_null() || n == 0 {
20006                &mut []
20007            } else {
20008                core::slice::from_raw_parts_mut(p, n)
20009            }
20010        }
20011    }
20012
20013    pub fn set_attachment_point_addons(&mut self, values: &[u16]) {
20014        // SAFETY: the native side copies `values` before returning.
20015        unsafe {
20016            ffi::whiteout_m3_M3Model_assign_attachmentPointAddons(
20017                self.raw.as_ptr(),
20018                values.as_ptr() as *const _,
20019                values.len(),
20020            )
20021        }
20022    }
20023
20024    pub fn resize_attachment_point_addons(&mut self, count: usize) {
20025        // SAFETY: reallocation is safe here precisely because
20026        // `&mut self` means no slice borrow is outstanding.
20027        unsafe { ffi::whiteout_m3_M3Model_resize_attachmentPointAddons(self.raw.as_ptr(), count) }
20028    }
20029
20030    /// Lights (LITE)
20031    pub fn lights_len(&self) -> usize {
20032        // SAFETY: scalar read through a live handle.
20033        unsafe { ffi::whiteout_m3_M3Model_get_lights_count(self.raw.as_ptr()) }
20034    }
20035
20036    /// Borrows element `index` in place. `None` when out of range.
20037    pub fn lights(&self, index: usize) -> Option<crate::support::Ref<'_, Light>> {
20038        if index >= self.lights_len() {
20039            return None;
20040        }
20041        // SAFETY: index checked above; the pointer is interior to `self`.
20042        unsafe {
20043            Some(crate::support::Ref::new(Light {
20044                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_lights_at(
20045                    self.raw.as_ptr(),
20046                    index,
20047                )),
20048            }))
20049        }
20050    }
20051
20052    pub fn lights_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Light>> {
20053        if index >= self.lights_len() {
20054            return None;
20055        }
20056        // SAFETY: as above; `&mut self` guarantees exclusivity.
20057        unsafe {
20058            Some(crate::support::RefMut::new(Light {
20059                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_lights_at(
20060                    self.raw.as_ptr(),
20061                    index,
20062                )),
20063            }))
20064        }
20065    }
20066
20067    /// Iterate the elements, borrowing each in turn.
20068    pub fn lights_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Light>> {
20069        (0..self.lights_len()).map(move |i| self.lights(i).expect("index below len"))
20070    }
20071
20072    pub fn resize_lights(&mut self, count: usize) {
20073        // SAFETY: exclusive access, so no borrow is outstanding.
20074        unsafe { ffi::whiteout_m3_M3Model_resize_lights(self.raw.as_ptr(), count) }
20075    }
20076
20077    /// Shadow boxes (SHBX)
20078    pub fn shadow_boxes_len(&self) -> usize {
20079        // SAFETY: scalar read through a live handle.
20080        unsafe { ffi::whiteout_m3_M3Model_get_shadowBoxes_count(self.raw.as_ptr()) }
20081    }
20082
20083    /// Borrows element `index` in place. `None` when out of range.
20084    pub fn shadow_boxes(&self, index: usize) -> Option<crate::support::Ref<'_, ShadowBox>> {
20085        if index >= self.shadow_boxes_len() {
20086            return None;
20087        }
20088        // SAFETY: index checked above; the pointer is interior to `self`.
20089        unsafe {
20090            Some(crate::support::Ref::new(ShadowBox {
20091                raw: core::ptr::NonNull::new_unchecked(
20092                    ffi::whiteout_m3_M3Model_get_shadowBoxes_at(self.raw.as_ptr(), index),
20093                ),
20094            }))
20095        }
20096    }
20097
20098    pub fn shadow_boxes_mut(
20099        &mut self,
20100        index: usize,
20101    ) -> Option<crate::support::RefMut<'_, ShadowBox>> {
20102        if index >= self.shadow_boxes_len() {
20103            return None;
20104        }
20105        // SAFETY: as above; `&mut self` guarantees exclusivity.
20106        unsafe {
20107            Some(crate::support::RefMut::new(ShadowBox {
20108                raw: core::ptr::NonNull::new_unchecked(
20109                    ffi::whiteout_m3_M3Model_get_shadowBoxes_at(self.raw.as_ptr(), index),
20110                ),
20111            }))
20112        }
20113    }
20114
20115    /// Iterate the elements, borrowing each in turn.
20116    pub fn shadow_boxes_iter(
20117        &self,
20118    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ShadowBox>> {
20119        (0..self.shadow_boxes_len()).map(move |i| self.shadow_boxes(i).expect("index below len"))
20120    }
20121
20122    pub fn resize_shadow_boxes(&mut self, count: usize) {
20123        // SAFETY: exclusive access, so no borrow is outstanding.
20124        unsafe { ffi::whiteout_m3_M3Model_resize_shadowBoxes(self.raw.as_ptr(), count) }
20125    }
20126
20127    /// Cameras (CAM_)
20128    pub fn cameras_len(&self) -> usize {
20129        // SAFETY: scalar read through a live handle.
20130        unsafe { ffi::whiteout_m3_M3Model_get_cameras_count(self.raw.as_ptr()) }
20131    }
20132
20133    /// Borrows element `index` in place. `None` when out of range.
20134    pub fn cameras(&self, index: usize) -> Option<crate::support::Ref<'_, Camera>> {
20135        if index >= self.cameras_len() {
20136            return None;
20137        }
20138        // SAFETY: index checked above; the pointer is interior to `self`.
20139        unsafe {
20140            Some(crate::support::Ref::new(Camera {
20141                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_cameras_at(
20142                    self.raw.as_ptr(),
20143                    index,
20144                )),
20145            }))
20146        }
20147    }
20148
20149    pub fn cameras_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Camera>> {
20150        if index >= self.cameras_len() {
20151            return None;
20152        }
20153        // SAFETY: as above; `&mut self` guarantees exclusivity.
20154        unsafe {
20155            Some(crate::support::RefMut::new(Camera {
20156                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_cameras_at(
20157                    self.raw.as_ptr(),
20158                    index,
20159                )),
20160            }))
20161        }
20162    }
20163
20164    /// Iterate the elements, borrowing each in turn.
20165    pub fn cameras_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Camera>> {
20166        (0..self.cameras_len()).map(move |i| self.cameras(i).expect("index below len"))
20167    }
20168
20169    pub fn resize_cameras(&mut self, count: usize) {
20170        // SAFETY: exclusive access, so no borrow is outstanding.
20171        unsafe { ffi::whiteout_m3_M3Model_resize_cameras(self.raw.as_ptr(), count) }
20172    }
20173
20174    /// Camera addon indices (U16_)
20175    /// Zero-copy view of the underlying `std::vector`.
20176    pub fn cameras_addons(&self) -> &[u16] {
20177        // SAFETY: `_data`/`_count` describe one contiguous C++
20178        // allocation, borrowed for as long as `self` is.
20179        unsafe {
20180            let n = ffi::whiteout_m3_M3Model_get_camerasAddons_count(self.raw.as_ptr());
20181            let p = ffi::whiteout_m3_M3Model_get_camerasAddons_data(self.raw.as_ptr());
20182            if p.is_null() || n == 0 {
20183                &[]
20184            } else {
20185                core::slice::from_raw_parts(p, n)
20186            }
20187        }
20188    }
20189
20190    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
20191    pub fn cameras_addons_mut(&mut self) -> &mut [u16] {
20192        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
20193        unsafe {
20194            let n = ffi::whiteout_m3_M3Model_get_camerasAddons_count(self.raw.as_ptr());
20195            let p = ffi::whiteout_m3_M3Model_get_camerasAddons_data(self.raw.as_ptr()) as *mut u16;
20196            if p.is_null() || n == 0 {
20197                &mut []
20198            } else {
20199                core::slice::from_raw_parts_mut(p, n)
20200            }
20201        }
20202    }
20203
20204    pub fn set_cameras_addons(&mut self, values: &[u16]) {
20205        // SAFETY: the native side copies `values` before returning.
20206        unsafe {
20207            ffi::whiteout_m3_M3Model_assign_camerasAddons(
20208                self.raw.as_ptr(),
20209                values.as_ptr() as *const _,
20210                values.len(),
20211            )
20212        }
20213    }
20214
20215    pub fn resize_cameras_addons(&mut self, count: usize) {
20216        // SAFETY: reallocation is safe here precisely because
20217        // `&mut self` means no slice borrow is outstanding.
20218        unsafe { ffi::whiteout_m3_M3Model_resize_camerasAddons(self.raw.as_ptr(), count) }
20219    }
20220
20221    /// Material type+index maps (MATM)
20222    pub fn material_maps_len(&self) -> usize {
20223        // SAFETY: scalar read through a live handle.
20224        unsafe { ffi::whiteout_m3_M3Model_get_materialMaps_count(self.raw.as_ptr()) }
20225    }
20226
20227    /// Borrows element `index` in place. `None` when out of range.
20228    pub fn material_maps(&self, index: usize) -> Option<crate::support::Ref<'_, MaterialMap>> {
20229        if index >= self.material_maps_len() {
20230            return None;
20231        }
20232        // SAFETY: index checked above; the pointer is interior to `self`.
20233        unsafe {
20234            Some(crate::support::Ref::new(MaterialMap {
20235                raw: core::ptr::NonNull::new_unchecked(
20236                    ffi::whiteout_m3_M3Model_get_materialMaps_at(self.raw.as_ptr(), index),
20237                ),
20238            }))
20239        }
20240    }
20241
20242    pub fn material_maps_mut(
20243        &mut self,
20244        index: usize,
20245    ) -> Option<crate::support::RefMut<'_, MaterialMap>> {
20246        if index >= self.material_maps_len() {
20247            return None;
20248        }
20249        // SAFETY: as above; `&mut self` guarantees exclusivity.
20250        unsafe {
20251            Some(crate::support::RefMut::new(MaterialMap {
20252                raw: core::ptr::NonNull::new_unchecked(
20253                    ffi::whiteout_m3_M3Model_get_materialMaps_at(self.raw.as_ptr(), index),
20254                ),
20255            }))
20256        }
20257    }
20258
20259    /// Iterate the elements, borrowing each in turn.
20260    pub fn material_maps_iter(
20261        &self,
20262    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, MaterialMap>> {
20263        (0..self.material_maps_len()).map(move |i| self.material_maps(i).expect("index below len"))
20264    }
20265
20266    pub fn resize_material_maps(&mut self, count: usize) {
20267        // SAFETY: exclusive access, so no borrow is outstanding.
20268        unsafe { ffi::whiteout_m3_M3Model_resize_materialMaps(self.raw.as_ptr(), count) }
20269    }
20270
20271    /// Standard materials (MAT_)
20272    pub fn standard_materials_len(&self) -> usize {
20273        // SAFETY: scalar read through a live handle.
20274        unsafe { ffi::whiteout_m3_M3Model_get_standardMaterials_count(self.raw.as_ptr()) }
20275    }
20276
20277    /// Borrows element `index` in place. `None` when out of range.
20278    pub fn standard_materials(
20279        &self,
20280        index: usize,
20281    ) -> Option<crate::support::Ref<'_, StandardMaterial>> {
20282        if index >= self.standard_materials_len() {
20283            return None;
20284        }
20285        // SAFETY: index checked above; the pointer is interior to `self`.
20286        unsafe {
20287            Some(crate::support::Ref::new(StandardMaterial {
20288                raw: core::ptr::NonNull::new_unchecked(
20289                    ffi::whiteout_m3_M3Model_get_standardMaterials_at(self.raw.as_ptr(), index),
20290                ),
20291            }))
20292        }
20293    }
20294
20295    pub fn standard_materials_mut(
20296        &mut self,
20297        index: usize,
20298    ) -> Option<crate::support::RefMut<'_, StandardMaterial>> {
20299        if index >= self.standard_materials_len() {
20300            return None;
20301        }
20302        // SAFETY: as above; `&mut self` guarantees exclusivity.
20303        unsafe {
20304            Some(crate::support::RefMut::new(StandardMaterial {
20305                raw: core::ptr::NonNull::new_unchecked(
20306                    ffi::whiteout_m3_M3Model_get_standardMaterials_at(self.raw.as_ptr(), index),
20307                ),
20308            }))
20309        }
20310    }
20311
20312    /// Iterate the elements, borrowing each in turn.
20313    pub fn standard_materials_iter(
20314        &self,
20315    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, StandardMaterial>> {
20316        (0..self.standard_materials_len())
20317            .map(move |i| self.standard_materials(i).expect("index below len"))
20318    }
20319
20320    pub fn resize_standard_materials(&mut self, count: usize) {
20321        // SAFETY: exclusive access, so no borrow is outstanding.
20322        unsafe { ffi::whiteout_m3_M3Model_resize_standardMaterials(self.raw.as_ptr(), count) }
20323    }
20324
20325    /// Displacement materials (DIS_)
20326    pub fn displacement_materials_len(&self) -> usize {
20327        // SAFETY: scalar read through a live handle.
20328        unsafe { ffi::whiteout_m3_M3Model_get_displacementMaterials_count(self.raw.as_ptr()) }
20329    }
20330
20331    /// Borrows element `index` in place. `None` when out of range.
20332    pub fn displacement_materials(
20333        &self,
20334        index: usize,
20335    ) -> Option<crate::support::Ref<'_, DisplacementMaterial>> {
20336        if index >= self.displacement_materials_len() {
20337            return None;
20338        }
20339        // SAFETY: index checked above; the pointer is interior to `self`.
20340        unsafe {
20341            Some(crate::support::Ref::new(DisplacementMaterial {
20342                raw: core::ptr::NonNull::new_unchecked(
20343                    ffi::whiteout_m3_M3Model_get_displacementMaterials_at(self.raw.as_ptr(), index),
20344                ),
20345            }))
20346        }
20347    }
20348
20349    pub fn displacement_materials_mut(
20350        &mut self,
20351        index: usize,
20352    ) -> Option<crate::support::RefMut<'_, DisplacementMaterial>> {
20353        if index >= self.displacement_materials_len() {
20354            return None;
20355        }
20356        // SAFETY: as above; `&mut self` guarantees exclusivity.
20357        unsafe {
20358            Some(crate::support::RefMut::new(DisplacementMaterial {
20359                raw: core::ptr::NonNull::new_unchecked(
20360                    ffi::whiteout_m3_M3Model_get_displacementMaterials_at(self.raw.as_ptr(), index),
20361                ),
20362            }))
20363        }
20364    }
20365
20366    /// Iterate the elements, borrowing each in turn.
20367    pub fn displacement_materials_iter(
20368        &self,
20369    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DisplacementMaterial>> {
20370        (0..self.displacement_materials_len())
20371            .map(move |i| self.displacement_materials(i).expect("index below len"))
20372    }
20373
20374    pub fn resize_displacement_materials(&mut self, count: usize) {
20375        // SAFETY: exclusive access, so no borrow is outstanding.
20376        unsafe { ffi::whiteout_m3_M3Model_resize_displacementMaterials(self.raw.as_ptr(), count) }
20377    }
20378
20379    /// Composite materials (CMP_)
20380    pub fn composite_materials_len(&self) -> usize {
20381        // SAFETY: scalar read through a live handle.
20382        unsafe { ffi::whiteout_m3_M3Model_get_compositeMaterials_count(self.raw.as_ptr()) }
20383    }
20384
20385    /// Borrows element `index` in place. `None` when out of range.
20386    pub fn composite_materials(
20387        &self,
20388        index: usize,
20389    ) -> Option<crate::support::Ref<'_, CompositeMaterial>> {
20390        if index >= self.composite_materials_len() {
20391            return None;
20392        }
20393        // SAFETY: index checked above; the pointer is interior to `self`.
20394        unsafe {
20395            Some(crate::support::Ref::new(CompositeMaterial {
20396                raw: core::ptr::NonNull::new_unchecked(
20397                    ffi::whiteout_m3_M3Model_get_compositeMaterials_at(self.raw.as_ptr(), index),
20398                ),
20399            }))
20400        }
20401    }
20402
20403    pub fn composite_materials_mut(
20404        &mut self,
20405        index: usize,
20406    ) -> Option<crate::support::RefMut<'_, CompositeMaterial>> {
20407        if index >= self.composite_materials_len() {
20408            return None;
20409        }
20410        // SAFETY: as above; `&mut self` guarantees exclusivity.
20411        unsafe {
20412            Some(crate::support::RefMut::new(CompositeMaterial {
20413                raw: core::ptr::NonNull::new_unchecked(
20414                    ffi::whiteout_m3_M3Model_get_compositeMaterials_at(self.raw.as_ptr(), index),
20415                ),
20416            }))
20417        }
20418    }
20419
20420    /// Iterate the elements, borrowing each in turn.
20421    pub fn composite_materials_iter(
20422        &self,
20423    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, CompositeMaterial>> {
20424        (0..self.composite_materials_len())
20425            .map(move |i| self.composite_materials(i).expect("index below len"))
20426    }
20427
20428    pub fn resize_composite_materials(&mut self, count: usize) {
20429        // SAFETY: exclusive access, so no borrow is outstanding.
20430        unsafe { ffi::whiteout_m3_M3Model_resize_compositeMaterials(self.raw.as_ptr(), count) }
20431    }
20432
20433    /// Terrain materials (TER_)
20434    pub fn terrain_materials_len(&self) -> usize {
20435        // SAFETY: scalar read through a live handle.
20436        unsafe { ffi::whiteout_m3_M3Model_get_terrainMaterials_count(self.raw.as_ptr()) }
20437    }
20438
20439    /// Borrows element `index` in place. `None` when out of range.
20440    pub fn terrain_materials(
20441        &self,
20442        index: usize,
20443    ) -> Option<crate::support::Ref<'_, TerrainMaterial>> {
20444        if index >= self.terrain_materials_len() {
20445            return None;
20446        }
20447        // SAFETY: index checked above; the pointer is interior to `self`.
20448        unsafe {
20449            Some(crate::support::Ref::new(TerrainMaterial {
20450                raw: core::ptr::NonNull::new_unchecked(
20451                    ffi::whiteout_m3_M3Model_get_terrainMaterials_at(self.raw.as_ptr(), index),
20452                ),
20453            }))
20454        }
20455    }
20456
20457    pub fn terrain_materials_mut(
20458        &mut self,
20459        index: usize,
20460    ) -> Option<crate::support::RefMut<'_, TerrainMaterial>> {
20461        if index >= self.terrain_materials_len() {
20462            return None;
20463        }
20464        // SAFETY: as above; `&mut self` guarantees exclusivity.
20465        unsafe {
20466            Some(crate::support::RefMut::new(TerrainMaterial {
20467                raw: core::ptr::NonNull::new_unchecked(
20468                    ffi::whiteout_m3_M3Model_get_terrainMaterials_at(self.raw.as_ptr(), index),
20469                ),
20470            }))
20471        }
20472    }
20473
20474    /// Iterate the elements, borrowing each in turn.
20475    pub fn terrain_materials_iter(
20476        &self,
20477    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TerrainMaterial>> {
20478        (0..self.terrain_materials_len())
20479            .map(move |i| self.terrain_materials(i).expect("index below len"))
20480    }
20481
20482    pub fn resize_terrain_materials(&mut self, count: usize) {
20483        // SAFETY: exclusive access, so no borrow is outstanding.
20484        unsafe { ffi::whiteout_m3_M3Model_resize_terrainMaterials(self.raw.as_ptr(), count) }
20485    }
20486
20487    /// Volume materials (VOL_)
20488    pub fn volume_materials_len(&self) -> usize {
20489        // SAFETY: scalar read through a live handle.
20490        unsafe { ffi::whiteout_m3_M3Model_get_volumeMaterials_count(self.raw.as_ptr()) }
20491    }
20492
20493    /// Borrows element `index` in place. `None` when out of range.
20494    pub fn volume_materials(
20495        &self,
20496        index: usize,
20497    ) -> Option<crate::support::Ref<'_, VolumeMaterial>> {
20498        if index >= self.volume_materials_len() {
20499            return None;
20500        }
20501        // SAFETY: index checked above; the pointer is interior to `self`.
20502        unsafe {
20503            Some(crate::support::Ref::new(VolumeMaterial {
20504                raw: core::ptr::NonNull::new_unchecked(
20505                    ffi::whiteout_m3_M3Model_get_volumeMaterials_at(self.raw.as_ptr(), index),
20506                ),
20507            }))
20508        }
20509    }
20510
20511    pub fn volume_materials_mut(
20512        &mut self,
20513        index: usize,
20514    ) -> Option<crate::support::RefMut<'_, VolumeMaterial>> {
20515        if index >= self.volume_materials_len() {
20516            return None;
20517        }
20518        // SAFETY: as above; `&mut self` guarantees exclusivity.
20519        unsafe {
20520            Some(crate::support::RefMut::new(VolumeMaterial {
20521                raw: core::ptr::NonNull::new_unchecked(
20522                    ffi::whiteout_m3_M3Model_get_volumeMaterials_at(self.raw.as_ptr(), index),
20523                ),
20524            }))
20525        }
20526    }
20527
20528    /// Iterate the elements, borrowing each in turn.
20529    pub fn volume_materials_iter(
20530        &self,
20531    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, VolumeMaterial>> {
20532        (0..self.volume_materials_len())
20533            .map(move |i| self.volume_materials(i).expect("index below len"))
20534    }
20535
20536    pub fn resize_volume_materials(&mut self, count: usize) {
20537        // SAFETY: exclusive access, so no borrow is outstanding.
20538        unsafe { ffi::whiteout_m3_M3Model_resize_volumeMaterials(self.raw.as_ptr(), count) }
20539    }
20540
20541    /// Hair materials (HAI_, defunct — always null)
20542    pub fn hair_materials_len(&self) -> usize {
20543        // SAFETY: scalar read through a live handle.
20544        unsafe { ffi::whiteout_m3_M3Model_get_hairMaterials_count(self.raw.as_ptr()) }
20545    }
20546
20547    /// Borrows element `index` in place. `None` when out of range.
20548    pub fn hair_materials(&self, index: usize) -> Option<crate::support::Ref<'_, HairMaterial>> {
20549        if index >= self.hair_materials_len() {
20550            return None;
20551        }
20552        // SAFETY: index checked above; the pointer is interior to `self`.
20553        unsafe {
20554            Some(crate::support::Ref::new(HairMaterial {
20555                raw: core::ptr::NonNull::new_unchecked(
20556                    ffi::whiteout_m3_M3Model_get_hairMaterials_at(self.raw.as_ptr(), index),
20557                ),
20558            }))
20559        }
20560    }
20561
20562    pub fn hair_materials_mut(
20563        &mut self,
20564        index: usize,
20565    ) -> Option<crate::support::RefMut<'_, HairMaterial>> {
20566        if index >= self.hair_materials_len() {
20567            return None;
20568        }
20569        // SAFETY: as above; `&mut self` guarantees exclusivity.
20570        unsafe {
20571            Some(crate::support::RefMut::new(HairMaterial {
20572                raw: core::ptr::NonNull::new_unchecked(
20573                    ffi::whiteout_m3_M3Model_get_hairMaterials_at(self.raw.as_ptr(), index),
20574                ),
20575            }))
20576        }
20577    }
20578
20579    /// Iterate the elements, borrowing each in turn.
20580    pub fn hair_materials_iter(
20581        &self,
20582    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, HairMaterial>> {
20583        (0..self.hair_materials_len())
20584            .map(move |i| self.hair_materials(i).expect("index below len"))
20585    }
20586
20587    pub fn resize_hair_materials(&mut self, count: usize) {
20588        // SAFETY: exclusive access, so no borrow is outstanding.
20589        unsafe { ffi::whiteout_m3_M3Model_resize_hairMaterials(self.raw.as_ptr(), count) }
20590    }
20591
20592    /// Creep materials (CREP)
20593    pub fn creep_materials_len(&self) -> usize {
20594        // SAFETY: scalar read through a live handle.
20595        unsafe { ffi::whiteout_m3_M3Model_get_creepMaterials_count(self.raw.as_ptr()) }
20596    }
20597
20598    /// Borrows element `index` in place. `None` when out of range.
20599    pub fn creep_materials(&self, index: usize) -> Option<crate::support::Ref<'_, CreepMaterial>> {
20600        if index >= self.creep_materials_len() {
20601            return None;
20602        }
20603        // SAFETY: index checked above; the pointer is interior to `self`.
20604        unsafe {
20605            Some(crate::support::Ref::new(CreepMaterial {
20606                raw: core::ptr::NonNull::new_unchecked(
20607                    ffi::whiteout_m3_M3Model_get_creepMaterials_at(self.raw.as_ptr(), index),
20608                ),
20609            }))
20610        }
20611    }
20612
20613    pub fn creep_materials_mut(
20614        &mut self,
20615        index: usize,
20616    ) -> Option<crate::support::RefMut<'_, CreepMaterial>> {
20617        if index >= self.creep_materials_len() {
20618            return None;
20619        }
20620        // SAFETY: as above; `&mut self` guarantees exclusivity.
20621        unsafe {
20622            Some(crate::support::RefMut::new(CreepMaterial {
20623                raw: core::ptr::NonNull::new_unchecked(
20624                    ffi::whiteout_m3_M3Model_get_creepMaterials_at(self.raw.as_ptr(), index),
20625                ),
20626            }))
20627        }
20628    }
20629
20630    /// Iterate the elements, borrowing each in turn.
20631    pub fn creep_materials_iter(
20632        &self,
20633    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, CreepMaterial>> {
20634        (0..self.creep_materials_len())
20635            .map(move |i| self.creep_materials(i).expect("index below len"))
20636    }
20637
20638    pub fn resize_creep_materials(&mut self, count: usize) {
20639        // SAFETY: exclusive access, so no borrow is outstanding.
20640        unsafe { ffi::whiteout_m3_M3Model_resize_creepMaterials(self.raw.as_ptr(), count) }
20641    }
20642
20643    /// Volume noise materials (VON_, v25+)
20644    pub fn volume_noise_materials_len(&self) -> usize {
20645        // SAFETY: scalar read through a live handle.
20646        unsafe { ffi::whiteout_m3_M3Model_get_volumeNoiseMaterials_count(self.raw.as_ptr()) }
20647    }
20648
20649    /// Borrows element `index` in place. `None` when out of range.
20650    pub fn volume_noise_materials(
20651        &self,
20652        index: usize,
20653    ) -> Option<crate::support::Ref<'_, VolumeNoiseMaterial>> {
20654        if index >= self.volume_noise_materials_len() {
20655            return None;
20656        }
20657        // SAFETY: index checked above; the pointer is interior to `self`.
20658        unsafe {
20659            Some(crate::support::Ref::new(VolumeNoiseMaterial {
20660                raw: core::ptr::NonNull::new_unchecked(
20661                    ffi::whiteout_m3_M3Model_get_volumeNoiseMaterials_at(self.raw.as_ptr(), index),
20662                ),
20663            }))
20664        }
20665    }
20666
20667    pub fn volume_noise_materials_mut(
20668        &mut self,
20669        index: usize,
20670    ) -> Option<crate::support::RefMut<'_, VolumeNoiseMaterial>> {
20671        if index >= self.volume_noise_materials_len() {
20672            return None;
20673        }
20674        // SAFETY: as above; `&mut self` guarantees exclusivity.
20675        unsafe {
20676            Some(crate::support::RefMut::new(VolumeNoiseMaterial {
20677                raw: core::ptr::NonNull::new_unchecked(
20678                    ffi::whiteout_m3_M3Model_get_volumeNoiseMaterials_at(self.raw.as_ptr(), index),
20679                ),
20680            }))
20681        }
20682    }
20683
20684    /// Iterate the elements, borrowing each in turn.
20685    pub fn volume_noise_materials_iter(
20686        &self,
20687    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, VolumeNoiseMaterial>> {
20688        (0..self.volume_noise_materials_len())
20689            .map(move |i| self.volume_noise_materials(i).expect("index below len"))
20690    }
20691
20692    pub fn resize_volume_noise_materials(&mut self, count: usize) {
20693        // SAFETY: exclusive access, so no borrow is outstanding.
20694        unsafe { ffi::whiteout_m3_M3Model_resize_volumeNoiseMaterials(self.raw.as_ptr(), count) }
20695    }
20696
20697    /// Splat terrain bake materials (STBM, v26+)
20698    pub fn stb_materials_len(&self) -> usize {
20699        // SAFETY: scalar read through a live handle.
20700        unsafe { ffi::whiteout_m3_M3Model_get_stbMaterials_count(self.raw.as_ptr()) }
20701    }
20702
20703    /// Borrows element `index` in place. `None` when out of range.
20704    pub fn stb_materials(&self, index: usize) -> Option<crate::support::Ref<'_, STBMaterial>> {
20705        if index >= self.stb_materials_len() {
20706            return None;
20707        }
20708        // SAFETY: index checked above; the pointer is interior to `self`.
20709        unsafe {
20710            Some(crate::support::Ref::new(STBMaterial {
20711                raw: core::ptr::NonNull::new_unchecked(
20712                    ffi::whiteout_m3_M3Model_get_stbMaterials_at(self.raw.as_ptr(), index),
20713                ),
20714            }))
20715        }
20716    }
20717
20718    pub fn stb_materials_mut(
20719        &mut self,
20720        index: usize,
20721    ) -> Option<crate::support::RefMut<'_, STBMaterial>> {
20722        if index >= self.stb_materials_len() {
20723            return None;
20724        }
20725        // SAFETY: as above; `&mut self` guarantees exclusivity.
20726        unsafe {
20727            Some(crate::support::RefMut::new(STBMaterial {
20728                raw: core::ptr::NonNull::new_unchecked(
20729                    ffi::whiteout_m3_M3Model_get_stbMaterials_at(self.raw.as_ptr(), index),
20730                ),
20731            }))
20732        }
20733    }
20734
20735    /// Iterate the elements, borrowing each in turn.
20736    pub fn stb_materials_iter(
20737        &self,
20738    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, STBMaterial>> {
20739        (0..self.stb_materials_len()).map(move |i| self.stb_materials(i).expect("index below len"))
20740    }
20741
20742    pub fn resize_stb_materials(&mut self, count: usize) {
20743        // SAFETY: exclusive access, so no borrow is outstanding.
20744        unsafe { ffi::whiteout_m3_M3Model_resize_stbMaterials(self.raw.as_ptr(), count) }
20745    }
20746
20747    /// Reflection materials (REF_, v28+)
20748    pub fn reflection_materials_len(&self) -> usize {
20749        // SAFETY: scalar read through a live handle.
20750        unsafe { ffi::whiteout_m3_M3Model_get_reflectionMaterials_count(self.raw.as_ptr()) }
20751    }
20752
20753    /// Borrows element `index` in place. `None` when out of range.
20754    pub fn reflection_materials(
20755        &self,
20756        index: usize,
20757    ) -> Option<crate::support::Ref<'_, ReflectionMaterial>> {
20758        if index >= self.reflection_materials_len() {
20759            return None;
20760        }
20761        // SAFETY: index checked above; the pointer is interior to `self`.
20762        unsafe {
20763            Some(crate::support::Ref::new(ReflectionMaterial {
20764                raw: core::ptr::NonNull::new_unchecked(
20765                    ffi::whiteout_m3_M3Model_get_reflectionMaterials_at(self.raw.as_ptr(), index),
20766                ),
20767            }))
20768        }
20769    }
20770
20771    pub fn reflection_materials_mut(
20772        &mut self,
20773        index: usize,
20774    ) -> Option<crate::support::RefMut<'_, ReflectionMaterial>> {
20775        if index >= self.reflection_materials_len() {
20776            return None;
20777        }
20778        // SAFETY: as above; `&mut self` guarantees exclusivity.
20779        unsafe {
20780            Some(crate::support::RefMut::new(ReflectionMaterial {
20781                raw: core::ptr::NonNull::new_unchecked(
20782                    ffi::whiteout_m3_M3Model_get_reflectionMaterials_at(self.raw.as_ptr(), index),
20783                ),
20784            }))
20785        }
20786    }
20787
20788    /// Iterate the elements, borrowing each in turn.
20789    pub fn reflection_materials_iter(
20790        &self,
20791    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ReflectionMaterial>> {
20792        (0..self.reflection_materials_len())
20793            .map(move |i| self.reflection_materials(i).expect("index below len"))
20794    }
20795
20796    pub fn resize_reflection_materials(&mut self, count: usize) {
20797        // SAFETY: exclusive access, so no borrow is outstanding.
20798        unsafe { ffi::whiteout_m3_M3Model_resize_reflectionMaterials(self.raw.as_ptr(), count) }
20799    }
20800
20801    /// Lens flare materials (LFLR, v29+)
20802    pub fn lens_flare_materials_len(&self) -> usize {
20803        // SAFETY: scalar read through a live handle.
20804        unsafe { ffi::whiteout_m3_M3Model_get_lensFlareMaterials_count(self.raw.as_ptr()) }
20805    }
20806
20807    /// Borrows element `index` in place. `None` when out of range.
20808    pub fn lens_flare_materials(&self, index: usize) -> Option<crate::support::Ref<'_, LensFlare>> {
20809        if index >= self.lens_flare_materials_len() {
20810            return None;
20811        }
20812        // SAFETY: index checked above; the pointer is interior to `self`.
20813        unsafe {
20814            Some(crate::support::Ref::new(LensFlare {
20815                raw: core::ptr::NonNull::new_unchecked(
20816                    ffi::whiteout_m3_M3Model_get_lensFlareMaterials_at(self.raw.as_ptr(), index),
20817                ),
20818            }))
20819        }
20820    }
20821
20822    pub fn lens_flare_materials_mut(
20823        &mut self,
20824        index: usize,
20825    ) -> Option<crate::support::RefMut<'_, LensFlare>> {
20826        if index >= self.lens_flare_materials_len() {
20827            return None;
20828        }
20829        // SAFETY: as above; `&mut self` guarantees exclusivity.
20830        unsafe {
20831            Some(crate::support::RefMut::new(LensFlare {
20832                raw: core::ptr::NonNull::new_unchecked(
20833                    ffi::whiteout_m3_M3Model_get_lensFlareMaterials_at(self.raw.as_ptr(), index),
20834                ),
20835            }))
20836        }
20837    }
20838
20839    /// Iterate the elements, borrowing each in turn.
20840    pub fn lens_flare_materials_iter(
20841        &self,
20842    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, LensFlare>> {
20843        (0..self.lens_flare_materials_len())
20844            .map(move |i| self.lens_flare_materials(i).expect("index below len"))
20845    }
20846
20847    pub fn resize_lens_flare_materials(&mut self, count: usize) {
20848        // SAFETY: exclusive access, so no borrow is outstanding.
20849        unsafe { ffi::whiteout_m3_M3Model_resize_lensFlareMaterials(self.raw.as_ptr(), count) }
20850    }
20851
20852    /// Data-driven materials (MADD, v30+)
20853    pub fn data_driven_materials_len(&self) -> usize {
20854        // SAFETY: scalar read through a live handle.
20855        unsafe { ffi::whiteout_m3_M3Model_get_dataDrivenMaterials_count(self.raw.as_ptr()) }
20856    }
20857
20858    /// Borrows element `index` in place. `None` when out of range.
20859    pub fn data_driven_materials(
20860        &self,
20861        index: usize,
20862    ) -> Option<crate::support::Ref<'_, DataDrivenMaterial>> {
20863        if index >= self.data_driven_materials_len() {
20864            return None;
20865        }
20866        // SAFETY: index checked above; the pointer is interior to `self`.
20867        unsafe {
20868            Some(crate::support::Ref::new(DataDrivenMaterial {
20869                raw: core::ptr::NonNull::new_unchecked(
20870                    ffi::whiteout_m3_M3Model_get_dataDrivenMaterials_at(self.raw.as_ptr(), index),
20871                ),
20872            }))
20873        }
20874    }
20875
20876    pub fn data_driven_materials_mut(
20877        &mut self,
20878        index: usize,
20879    ) -> Option<crate::support::RefMut<'_, DataDrivenMaterial>> {
20880        if index >= self.data_driven_materials_len() {
20881            return None;
20882        }
20883        // SAFETY: as above; `&mut self` guarantees exclusivity.
20884        unsafe {
20885            Some(crate::support::RefMut::new(DataDrivenMaterial {
20886                raw: core::ptr::NonNull::new_unchecked(
20887                    ffi::whiteout_m3_M3Model_get_dataDrivenMaterials_at(self.raw.as_ptr(), index),
20888                ),
20889            }))
20890        }
20891    }
20892
20893    /// Iterate the elements, borrowing each in turn.
20894    pub fn data_driven_materials_iter(
20895        &self,
20896    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DataDrivenMaterial>> {
20897        (0..self.data_driven_materials_len())
20898            .map(move |i| self.data_driven_materials(i).expect("index below len"))
20899    }
20900
20901    pub fn resize_data_driven_materials(&mut self, count: usize) {
20902        // SAFETY: exclusive access, so no borrow is outstanding.
20903        unsafe { ffi::whiteout_m3_M3Model_resize_dataDrivenMaterials(self.raw.as_ptr(), count) }
20904    }
20905
20906    /// Particle emitters (PAR_)
20907    pub fn particle_emitters_len(&self) -> usize {
20908        // SAFETY: scalar read through a live handle.
20909        unsafe { ffi::whiteout_m3_M3Model_get_particleEmitters_count(self.raw.as_ptr()) }
20910    }
20911
20912    /// Borrows element `index` in place. `None` when out of range.
20913    pub fn particle_emitters(
20914        &self,
20915        index: usize,
20916    ) -> Option<crate::support::Ref<'_, ParticleEmitter>> {
20917        if index >= self.particle_emitters_len() {
20918            return None;
20919        }
20920        // SAFETY: index checked above; the pointer is interior to `self`.
20921        unsafe {
20922            Some(crate::support::Ref::new(ParticleEmitter {
20923                raw: core::ptr::NonNull::new_unchecked(
20924                    ffi::whiteout_m3_M3Model_get_particleEmitters_at(self.raw.as_ptr(), index),
20925                ),
20926            }))
20927        }
20928    }
20929
20930    pub fn particle_emitters_mut(
20931        &mut self,
20932        index: usize,
20933    ) -> Option<crate::support::RefMut<'_, ParticleEmitter>> {
20934        if index >= self.particle_emitters_len() {
20935            return None;
20936        }
20937        // SAFETY: as above; `&mut self` guarantees exclusivity.
20938        unsafe {
20939            Some(crate::support::RefMut::new(ParticleEmitter {
20940                raw: core::ptr::NonNull::new_unchecked(
20941                    ffi::whiteout_m3_M3Model_get_particleEmitters_at(self.raw.as_ptr(), index),
20942                ),
20943            }))
20944        }
20945    }
20946
20947    /// Iterate the elements, borrowing each in turn.
20948    pub fn particle_emitters_iter(
20949        &self,
20950    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ParticleEmitter>> {
20951        (0..self.particle_emitters_len())
20952            .map(move |i| self.particle_emitters(i).expect("index below len"))
20953    }
20954
20955    pub fn resize_particle_emitters(&mut self, count: usize) {
20956        // SAFETY: exclusive access, so no borrow is outstanding.
20957        unsafe { ffi::whiteout_m3_M3Model_resize_particleEmitters(self.raw.as_ptr(), count) }
20958    }
20959
20960    /// Particle emitter copies (PARC)
20961    pub fn particle_emitter_copies_len(&self) -> usize {
20962        // SAFETY: scalar read through a live handle.
20963        unsafe { ffi::whiteout_m3_M3Model_get_particleEmitterCopies_count(self.raw.as_ptr()) }
20964    }
20965
20966    /// Borrows element `index` in place. `None` when out of range.
20967    pub fn particle_emitter_copies(
20968        &self,
20969        index: usize,
20970    ) -> Option<crate::support::Ref<'_, ParticleEmitterCopy>> {
20971        if index >= self.particle_emitter_copies_len() {
20972            return None;
20973        }
20974        // SAFETY: index checked above; the pointer is interior to `self`.
20975        unsafe {
20976            Some(crate::support::Ref::new(ParticleEmitterCopy {
20977                raw: core::ptr::NonNull::new_unchecked(
20978                    ffi::whiteout_m3_M3Model_get_particleEmitterCopies_at(self.raw.as_ptr(), index),
20979                ),
20980            }))
20981        }
20982    }
20983
20984    pub fn particle_emitter_copies_mut(
20985        &mut self,
20986        index: usize,
20987    ) -> Option<crate::support::RefMut<'_, ParticleEmitterCopy>> {
20988        if index >= self.particle_emitter_copies_len() {
20989            return None;
20990        }
20991        // SAFETY: as above; `&mut self` guarantees exclusivity.
20992        unsafe {
20993            Some(crate::support::RefMut::new(ParticleEmitterCopy {
20994                raw: core::ptr::NonNull::new_unchecked(
20995                    ffi::whiteout_m3_M3Model_get_particleEmitterCopies_at(self.raw.as_ptr(), index),
20996                ),
20997            }))
20998        }
20999    }
21000
21001    /// Iterate the elements, borrowing each in turn.
21002    pub fn particle_emitter_copies_iter(
21003        &self,
21004    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ParticleEmitterCopy>> {
21005        (0..self.particle_emitter_copies_len())
21006            .map(move |i| self.particle_emitter_copies(i).expect("index below len"))
21007    }
21008
21009    pub fn resize_particle_emitter_copies(&mut self, count: usize) {
21010        // SAFETY: exclusive access, so no borrow is outstanding.
21011        unsafe { ffi::whiteout_m3_M3Model_resize_particleEmitterCopies(self.raw.as_ptr(), count) }
21012    }
21013
21014    /// Ribbon emitters (RIB_)
21015    pub fn ribbon_emitters_len(&self) -> usize {
21016        // SAFETY: scalar read through a live handle.
21017        unsafe { ffi::whiteout_m3_M3Model_get_ribbonEmitters_count(self.raw.as_ptr()) }
21018    }
21019
21020    /// Borrows element `index` in place. `None` when out of range.
21021    pub fn ribbon_emitters(&self, index: usize) -> Option<crate::support::Ref<'_, RibbonEmitter>> {
21022        if index >= self.ribbon_emitters_len() {
21023            return None;
21024        }
21025        // SAFETY: index checked above; the pointer is interior to `self`.
21026        unsafe {
21027            Some(crate::support::Ref::new(RibbonEmitter {
21028                raw: core::ptr::NonNull::new_unchecked(
21029                    ffi::whiteout_m3_M3Model_get_ribbonEmitters_at(self.raw.as_ptr(), index),
21030                ),
21031            }))
21032        }
21033    }
21034
21035    pub fn ribbon_emitters_mut(
21036        &mut self,
21037        index: usize,
21038    ) -> Option<crate::support::RefMut<'_, RibbonEmitter>> {
21039        if index >= self.ribbon_emitters_len() {
21040            return None;
21041        }
21042        // SAFETY: as above; `&mut self` guarantees exclusivity.
21043        unsafe {
21044            Some(crate::support::RefMut::new(RibbonEmitter {
21045                raw: core::ptr::NonNull::new_unchecked(
21046                    ffi::whiteout_m3_M3Model_get_ribbonEmitters_at(self.raw.as_ptr(), index),
21047                ),
21048            }))
21049        }
21050    }
21051
21052    /// Iterate the elements, borrowing each in turn.
21053    pub fn ribbon_emitters_iter(
21054        &self,
21055    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, RibbonEmitter>> {
21056        (0..self.ribbon_emitters_len())
21057            .map(move |i| self.ribbon_emitters(i).expect("index below len"))
21058    }
21059
21060    pub fn resize_ribbon_emitters(&mut self, count: usize) {
21061        // SAFETY: exclusive access, so no borrow is outstanding.
21062        unsafe { ffi::whiteout_m3_M3Model_resize_ribbonEmitters(self.raw.as_ptr(), count) }
21063    }
21064
21065    /// Projectors / decals (PROJ)
21066    pub fn projections_len(&self) -> usize {
21067        // SAFETY: scalar read through a live handle.
21068        unsafe { ffi::whiteout_m3_M3Model_get_projections_count(self.raw.as_ptr()) }
21069    }
21070
21071    /// Borrows element `index` in place. `None` when out of range.
21072    pub fn projections(&self, index: usize) -> Option<crate::support::Ref<'_, Projector>> {
21073        if index >= self.projections_len() {
21074            return None;
21075        }
21076        // SAFETY: index checked above; the pointer is interior to `self`.
21077        unsafe {
21078            Some(crate::support::Ref::new(Projector {
21079                raw: core::ptr::NonNull::new_unchecked(
21080                    ffi::whiteout_m3_M3Model_get_projections_at(self.raw.as_ptr(), index),
21081                ),
21082            }))
21083        }
21084    }
21085
21086    pub fn projections_mut(
21087        &mut self,
21088        index: usize,
21089    ) -> Option<crate::support::RefMut<'_, Projector>> {
21090        if index >= self.projections_len() {
21091            return None;
21092        }
21093        // SAFETY: as above; `&mut self` guarantees exclusivity.
21094        unsafe {
21095            Some(crate::support::RefMut::new(Projector {
21096                raw: core::ptr::NonNull::new_unchecked(
21097                    ffi::whiteout_m3_M3Model_get_projections_at(self.raw.as_ptr(), index),
21098                ),
21099            }))
21100        }
21101    }
21102
21103    /// Iterate the elements, borrowing each in turn.
21104    pub fn projections_iter(
21105        &self,
21106    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Projector>> {
21107        (0..self.projections_len()).map(move |i| self.projections(i).expect("index below len"))
21108    }
21109
21110    pub fn resize_projections(&mut self, count: usize) {
21111        // SAFETY: exclusive access, so no borrow is outstanding.
21112        unsafe { ffi::whiteout_m3_M3Model_resize_projections(self.raw.as_ptr(), count) }
21113    }
21114
21115    /// Forces (FOR_)
21116    pub fn forces_len(&self) -> usize {
21117        // SAFETY: scalar read through a live handle.
21118        unsafe { ffi::whiteout_m3_M3Model_get_forces_count(self.raw.as_ptr()) }
21119    }
21120
21121    /// Borrows element `index` in place. `None` when out of range.
21122    pub fn forces(&self, index: usize) -> Option<crate::support::Ref<'_, Force>> {
21123        if index >= self.forces_len() {
21124            return None;
21125        }
21126        // SAFETY: index checked above; the pointer is interior to `self`.
21127        unsafe {
21128            Some(crate::support::Ref::new(Force {
21129                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_forces_at(
21130                    self.raw.as_ptr(),
21131                    index,
21132                )),
21133            }))
21134        }
21135    }
21136
21137    pub fn forces_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Force>> {
21138        if index >= self.forces_len() {
21139            return None;
21140        }
21141        // SAFETY: as above; `&mut self` guarantees exclusivity.
21142        unsafe {
21143            Some(crate::support::RefMut::new(Force {
21144                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_forces_at(
21145                    self.raw.as_ptr(),
21146                    index,
21147                )),
21148            }))
21149        }
21150    }
21151
21152    /// Iterate the elements, borrowing each in turn.
21153    pub fn forces_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Force>> {
21154        (0..self.forces_len()).map(move |i| self.forces(i).expect("index below len"))
21155    }
21156
21157    pub fn resize_forces(&mut self, count: usize) {
21158        // SAFETY: exclusive access, so no borrow is outstanding.
21159        unsafe { ffi::whiteout_m3_M3Model_resize_forces(self.raw.as_ptr(), count) }
21160    }
21161
21162    /// Warps (WRP_)
21163    pub fn warps_len(&self) -> usize {
21164        // SAFETY: scalar read through a live handle.
21165        unsafe { ffi::whiteout_m3_M3Model_get_warps_count(self.raw.as_ptr()) }
21166    }
21167
21168    /// Borrows element `index` in place. `None` when out of range.
21169    pub fn warps(&self, index: usize) -> Option<crate::support::Ref<'_, Warp>> {
21170        if index >= self.warps_len() {
21171            return None;
21172        }
21173        // SAFETY: index checked above; the pointer is interior to `self`.
21174        unsafe {
21175            Some(crate::support::Ref::new(Warp {
21176                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_warps_at(
21177                    self.raw.as_ptr(),
21178                    index,
21179                )),
21180            }))
21181        }
21182    }
21183
21184    pub fn warps_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Warp>> {
21185        if index >= self.warps_len() {
21186            return None;
21187        }
21188        // SAFETY: as above; `&mut self` guarantees exclusivity.
21189        unsafe {
21190            Some(crate::support::RefMut::new(Warp {
21191                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_warps_at(
21192                    self.raw.as_ptr(),
21193                    index,
21194                )),
21195            }))
21196        }
21197    }
21198
21199    /// Iterate the elements, borrowing each in turn.
21200    pub fn warps_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Warp>> {
21201        (0..self.warps_len()).map(move |i| self.warps(i).expect("index below len"))
21202    }
21203
21204    pub fn resize_warps(&mut self, count: usize) {
21205        // SAFETY: exclusive access, so no borrow is outstanding.
21206        unsafe { ffi::whiteout_m3_M3Model_resize_warps(self.raw.as_ptr(), count) }
21207    }
21208
21209    /// View volumes (VVOL)
21210    pub fn view_volumes_len(&self) -> usize {
21211        // SAFETY: scalar read through a live handle.
21212        unsafe { ffi::whiteout_m3_M3Model_get_viewVolumes_count(self.raw.as_ptr()) }
21213    }
21214
21215    /// Borrows element `index` in place. `None` when out of range.
21216    pub fn view_volumes(&self, index: usize) -> Option<crate::support::Ref<'_, ViewVolume>> {
21217        if index >= self.view_volumes_len() {
21218            return None;
21219        }
21220        // SAFETY: index checked above; the pointer is interior to `self`.
21221        unsafe {
21222            Some(crate::support::Ref::new(ViewVolume {
21223                raw: core::ptr::NonNull::new_unchecked(
21224                    ffi::whiteout_m3_M3Model_get_viewVolumes_at(self.raw.as_ptr(), index),
21225                ),
21226            }))
21227        }
21228    }
21229
21230    pub fn view_volumes_mut(
21231        &mut self,
21232        index: usize,
21233    ) -> Option<crate::support::RefMut<'_, ViewVolume>> {
21234        if index >= self.view_volumes_len() {
21235            return None;
21236        }
21237        // SAFETY: as above; `&mut self` guarantees exclusivity.
21238        unsafe {
21239            Some(crate::support::RefMut::new(ViewVolume {
21240                raw: core::ptr::NonNull::new_unchecked(
21241                    ffi::whiteout_m3_M3Model_get_viewVolumes_at(self.raw.as_ptr(), index),
21242                ),
21243            }))
21244        }
21245    }
21246
21247    /// Iterate the elements, borrowing each in turn.
21248    pub fn view_volumes_iter(
21249        &self,
21250    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ViewVolume>> {
21251        (0..self.view_volumes_len()).map(move |i| self.view_volumes(i).expect("index below len"))
21252    }
21253
21254    pub fn resize_view_volumes(&mut self, count: usize) {
21255        // SAFETY: exclusive access, so no borrow is outstanding.
21256        unsafe { ffi::whiteout_m3_M3Model_resize_viewVolumes(self.raw.as_ptr(), count) }
21257    }
21258
21259    /// Rigid bodies (PHRB)
21260    pub fn rigid_bodies_len(&self) -> usize {
21261        // SAFETY: scalar read through a live handle.
21262        unsafe { ffi::whiteout_m3_M3Model_get_rigidBodies_count(self.raw.as_ptr()) }
21263    }
21264
21265    /// Borrows element `index` in place. `None` when out of range.
21266    pub fn rigid_bodies(&self, index: usize) -> Option<crate::support::Ref<'_, RigidBody>> {
21267        if index >= self.rigid_bodies_len() {
21268            return None;
21269        }
21270        // SAFETY: index checked above; the pointer is interior to `self`.
21271        unsafe {
21272            Some(crate::support::Ref::new(RigidBody {
21273                raw: core::ptr::NonNull::new_unchecked(
21274                    ffi::whiteout_m3_M3Model_get_rigidBodies_at(self.raw.as_ptr(), index),
21275                ),
21276            }))
21277        }
21278    }
21279
21280    pub fn rigid_bodies_mut(
21281        &mut self,
21282        index: usize,
21283    ) -> Option<crate::support::RefMut<'_, RigidBody>> {
21284        if index >= self.rigid_bodies_len() {
21285            return None;
21286        }
21287        // SAFETY: as above; `&mut self` guarantees exclusivity.
21288        unsafe {
21289            Some(crate::support::RefMut::new(RigidBody {
21290                raw: core::ptr::NonNull::new_unchecked(
21291                    ffi::whiteout_m3_M3Model_get_rigidBodies_at(self.raw.as_ptr(), index),
21292                ),
21293            }))
21294        }
21295    }
21296
21297    /// Iterate the elements, borrowing each in turn.
21298    pub fn rigid_bodies_iter(
21299        &self,
21300    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, RigidBody>> {
21301        (0..self.rigid_bodies_len()).map(move |i| self.rigid_bodies(i).expect("index below len"))
21302    }
21303
21304    pub fn resize_rigid_bodies(&mut self, count: usize) {
21305        // SAFETY: exclusive access, so no borrow is outstanding.
21306        unsafe { ffi::whiteout_m3_M3Model_resize_rigidBodies(self.raw.as_ptr(), count) }
21307    }
21308
21309    /// Physics constraints (PHCT)
21310    pub fn physics_constraints_len(&self) -> usize {
21311        // SAFETY: scalar read through a live handle.
21312        unsafe { ffi::whiteout_m3_M3Model_get_physicsConstraints_count(self.raw.as_ptr()) }
21313    }
21314
21315    /// Borrows element `index` in place. `None` when out of range.
21316    pub fn physics_constraints(
21317        &self,
21318        index: usize,
21319    ) -> Option<crate::support::Ref<'_, PhysicsConstraint>> {
21320        if index >= self.physics_constraints_len() {
21321            return None;
21322        }
21323        // SAFETY: index checked above; the pointer is interior to `self`.
21324        unsafe {
21325            Some(crate::support::Ref::new(PhysicsConstraint {
21326                raw: core::ptr::NonNull::new_unchecked(
21327                    ffi::whiteout_m3_M3Model_get_physicsConstraints_at(self.raw.as_ptr(), index),
21328                ),
21329            }))
21330        }
21331    }
21332
21333    pub fn physics_constraints_mut(
21334        &mut self,
21335        index: usize,
21336    ) -> Option<crate::support::RefMut<'_, PhysicsConstraint>> {
21337        if index >= self.physics_constraints_len() {
21338            return None;
21339        }
21340        // SAFETY: as above; `&mut self` guarantees exclusivity.
21341        unsafe {
21342            Some(crate::support::RefMut::new(PhysicsConstraint {
21343                raw: core::ptr::NonNull::new_unchecked(
21344                    ffi::whiteout_m3_M3Model_get_physicsConstraints_at(self.raw.as_ptr(), index),
21345                ),
21346            }))
21347        }
21348    }
21349
21350    /// Iterate the elements, borrowing each in turn.
21351    pub fn physics_constraints_iter(
21352        &self,
21353    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsConstraint>> {
21354        (0..self.physics_constraints_len())
21355            .map(move |i| self.physics_constraints(i).expect("index below len"))
21356    }
21357
21358    pub fn resize_physics_constraints(&mut self, count: usize) {
21359        // SAFETY: exclusive access, so no borrow is outstanding.
21360        unsafe { ffi::whiteout_m3_M3Model_resize_physicsConstraints(self.raw.as_ptr(), count) }
21361    }
21362
21363    /// Physics joints (PHYJ)
21364    pub fn physics_joints_len(&self) -> usize {
21365        // SAFETY: scalar read through a live handle.
21366        unsafe { ffi::whiteout_m3_M3Model_get_physicsJoints_count(self.raw.as_ptr()) }
21367    }
21368
21369    /// Borrows element `index` in place. `None` when out of range.
21370    pub fn physics_joints(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsJoint>> {
21371        if index >= self.physics_joints_len() {
21372            return None;
21373        }
21374        // SAFETY: index checked above; the pointer is interior to `self`.
21375        unsafe {
21376            Some(crate::support::Ref::new(PhysicsJoint {
21377                raw: core::ptr::NonNull::new_unchecked(
21378                    ffi::whiteout_m3_M3Model_get_physicsJoints_at(self.raw.as_ptr(), index),
21379                ),
21380            }))
21381        }
21382    }
21383
21384    pub fn physics_joints_mut(
21385        &mut self,
21386        index: usize,
21387    ) -> Option<crate::support::RefMut<'_, PhysicsJoint>> {
21388        if index >= self.physics_joints_len() {
21389            return None;
21390        }
21391        // SAFETY: as above; `&mut self` guarantees exclusivity.
21392        unsafe {
21393            Some(crate::support::RefMut::new(PhysicsJoint {
21394                raw: core::ptr::NonNull::new_unchecked(
21395                    ffi::whiteout_m3_M3Model_get_physicsJoints_at(self.raw.as_ptr(), index),
21396                ),
21397            }))
21398        }
21399    }
21400
21401    /// Iterate the elements, borrowing each in turn.
21402    pub fn physics_joints_iter(
21403        &self,
21404    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsJoint>> {
21405        (0..self.physics_joints_len())
21406            .map(move |i| self.physics_joints(i).expect("index below len"))
21407    }
21408
21409    pub fn resize_physics_joints(&mut self, count: usize) {
21410        // SAFETY: exclusive access, so no borrow is outstanding.
21411        unsafe { ffi::whiteout_m3_M3Model_resize_physicsJoints(self.raw.as_ptr(), count) }
21412    }
21413
21414    /// Cloth physics (PHCL, v28+)
21415    pub fn cloth_physics_len(&self) -> usize {
21416        // SAFETY: scalar read through a live handle.
21417        unsafe { ffi::whiteout_m3_M3Model_get_clothPhysics_count(self.raw.as_ptr()) }
21418    }
21419
21420    /// Borrows element `index` in place. `None` when out of range.
21421    pub fn cloth_physics(&self, index: usize) -> Option<crate::support::Ref<'_, ClothPhysics>> {
21422        if index >= self.cloth_physics_len() {
21423            return None;
21424        }
21425        // SAFETY: index checked above; the pointer is interior to `self`.
21426        unsafe {
21427            Some(crate::support::Ref::new(ClothPhysics {
21428                raw: core::ptr::NonNull::new_unchecked(
21429                    ffi::whiteout_m3_M3Model_get_clothPhysics_at(self.raw.as_ptr(), index),
21430                ),
21431            }))
21432        }
21433    }
21434
21435    pub fn cloth_physics_mut(
21436        &mut self,
21437        index: usize,
21438    ) -> Option<crate::support::RefMut<'_, ClothPhysics>> {
21439        if index >= self.cloth_physics_len() {
21440            return None;
21441        }
21442        // SAFETY: as above; `&mut self` guarantees exclusivity.
21443        unsafe {
21444            Some(crate::support::RefMut::new(ClothPhysics {
21445                raw: core::ptr::NonNull::new_unchecked(
21446                    ffi::whiteout_m3_M3Model_get_clothPhysics_at(self.raw.as_ptr(), index),
21447                ),
21448            }))
21449        }
21450    }
21451
21452    /// Iterate the elements, borrowing each in turn.
21453    pub fn cloth_physics_iter(
21454        &self,
21455    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ClothPhysics>> {
21456        (0..self.cloth_physics_len()).map(move |i| self.cloth_physics(i).expect("index below len"))
21457    }
21458
21459    pub fn resize_cloth_physics(&mut self, count: usize) {
21460        // SAFETY: exclusive access, so no borrow is outstanding.
21461        unsafe { ffi::whiteout_m3_M3Model_resize_clothPhysics(self.raw.as_ptr(), count) }
21462    }
21463
21464    /// Two-joint IK solvers (IK2J)
21465    pub fn ik_two_joints_len(&self) -> usize {
21466        // SAFETY: scalar read through a live handle.
21467        unsafe { ffi::whiteout_m3_M3Model_get_ikTwoJoints_count(self.raw.as_ptr()) }
21468    }
21469
21470    /// Borrows element `index` in place. `None` when out of range.
21471    pub fn ik_two_joints(&self, index: usize) -> Option<crate::support::Ref<'_, IKTwoJoint>> {
21472        if index >= self.ik_two_joints_len() {
21473            return None;
21474        }
21475        // SAFETY: index checked above; the pointer is interior to `self`.
21476        unsafe {
21477            Some(crate::support::Ref::new(IKTwoJoint {
21478                raw: core::ptr::NonNull::new_unchecked(
21479                    ffi::whiteout_m3_M3Model_get_ikTwoJoints_at(self.raw.as_ptr(), index),
21480                ),
21481            }))
21482        }
21483    }
21484
21485    pub fn ik_two_joints_mut(
21486        &mut self,
21487        index: usize,
21488    ) -> Option<crate::support::RefMut<'_, IKTwoJoint>> {
21489        if index >= self.ik_two_joints_len() {
21490            return None;
21491        }
21492        // SAFETY: as above; `&mut self` guarantees exclusivity.
21493        unsafe {
21494            Some(crate::support::RefMut::new(IKTwoJoint {
21495                raw: core::ptr::NonNull::new_unchecked(
21496                    ffi::whiteout_m3_M3Model_get_ikTwoJoints_at(self.raw.as_ptr(), index),
21497                ),
21498            }))
21499        }
21500    }
21501
21502    /// Iterate the elements, borrowing each in turn.
21503    pub fn ik_two_joints_iter(
21504        &self,
21505    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, IKTwoJoint>> {
21506        (0..self.ik_two_joints_len()).map(move |i| self.ik_two_joints(i).expect("index below len"))
21507    }
21508
21509    pub fn resize_ik_two_joints(&mut self, count: usize) {
21510        // SAFETY: exclusive access, so no borrow is outstanding.
21511        unsafe { ffi::whiteout_m3_M3Model_resize_ikTwoJoints(self.raw.as_ptr(), count) }
21512    }
21513
21514    /// CCD IK solvers (IKCC, v24+)
21515    pub fn ik_ccd_len(&self) -> usize {
21516        // SAFETY: scalar read through a live handle.
21517        unsafe { ffi::whiteout_m3_M3Model_get_ikCCD_count(self.raw.as_ptr()) }
21518    }
21519
21520    /// Borrows element `index` in place. `None` when out of range.
21521    pub fn ik_ccd(&self, index: usize) -> Option<crate::support::Ref<'_, IKCCD>> {
21522        if index >= self.ik_ccd_len() {
21523            return None;
21524        }
21525        // SAFETY: index checked above; the pointer is interior to `self`.
21526        unsafe {
21527            Some(crate::support::Ref::new(IKCCD {
21528                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_ikCCD_at(
21529                    self.raw.as_ptr(),
21530                    index,
21531                )),
21532            }))
21533        }
21534    }
21535
21536    pub fn ik_ccd_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, IKCCD>> {
21537        if index >= self.ik_ccd_len() {
21538            return None;
21539        }
21540        // SAFETY: as above; `&mut self` guarantees exclusivity.
21541        unsafe {
21542            Some(crate::support::RefMut::new(IKCCD {
21543                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_ikCCD_at(
21544                    self.raw.as_ptr(),
21545                    index,
21546                )),
21547            }))
21548        }
21549    }
21550
21551    /// Iterate the elements, borrowing each in turn.
21552    pub fn ik_ccd_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, IKCCD>> {
21553        (0..self.ik_ccd_len()).map(move |i| self.ik_ccd(i).expect("index below len"))
21554    }
21555
21556    pub fn resize_ik_ccd(&mut self, count: usize) {
21557        // SAFETY: exclusive access, so no borrow is outstanding.
21558        unsafe { ffi::whiteout_m3_M3Model_resize_ikCCD(self.raw.as_ptr(), count) }
21559    }
21560
21561    /// IK joints (IKJT)
21562    pub fn ik_joints_len(&self) -> usize {
21563        // SAFETY: scalar read through a live handle.
21564        unsafe { ffi::whiteout_m3_M3Model_get_ikJoints_count(self.raw.as_ptr()) }
21565    }
21566
21567    /// Borrows element `index` in place. `None` when out of range.
21568    pub fn ik_joints(&self, index: usize) -> Option<crate::support::Ref<'_, IKJoint>> {
21569        if index >= self.ik_joints_len() {
21570            return None;
21571        }
21572        // SAFETY: index checked above; the pointer is interior to `self`.
21573        unsafe {
21574            Some(crate::support::Ref::new(IKJoint {
21575                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_ikJoints_at(
21576                    self.raw.as_ptr(),
21577                    index,
21578                )),
21579            }))
21580        }
21581    }
21582
21583    pub fn ik_joints_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, IKJoint>> {
21584        if index >= self.ik_joints_len() {
21585            return None;
21586        }
21587        // SAFETY: as above; `&mut self` guarantees exclusivity.
21588        unsafe {
21589            Some(crate::support::RefMut::new(IKJoint {
21590                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m3_M3Model_get_ikJoints_at(
21591                    self.raw.as_ptr(),
21592                    index,
21593                )),
21594            }))
21595        }
21596    }
21597
21598    /// Iterate the elements, borrowing each in turn.
21599    pub fn ik_joints_iter(
21600        &self,
21601    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, IKJoint>> {
21602        (0..self.ik_joints_len()).map(move |i| self.ik_joints(i).expect("index below len"))
21603    }
21604
21605    pub fn resize_ik_joints(&mut self, count: usize) {
21606        // SAFETY: exclusive access, so no borrow is outstanding.
21607        unsafe { ffi::whiteout_m3_M3Model_resize_ikJoints(self.raw.as_ptr(), count) }
21608    }
21609
21610    /// One-bone IK solvers (PAOB)
21611    pub fn one_bone_solvers_len(&self) -> usize {
21612        // SAFETY: scalar read through a live handle.
21613        unsafe { ffi::whiteout_m3_M3Model_get_oneBoneSolvers_count(self.raw.as_ptr()) }
21614    }
21615
21616    /// Borrows element `index` in place. `None` when out of range.
21617    pub fn one_bone_solvers(&self, index: usize) -> Option<crate::support::Ref<'_, OneBoneSolver>> {
21618        if index >= self.one_bone_solvers_len() {
21619            return None;
21620        }
21621        // SAFETY: index checked above; the pointer is interior to `self`.
21622        unsafe {
21623            Some(crate::support::Ref::new(OneBoneSolver {
21624                raw: core::ptr::NonNull::new_unchecked(
21625                    ffi::whiteout_m3_M3Model_get_oneBoneSolvers_at(self.raw.as_ptr(), index),
21626                ),
21627            }))
21628        }
21629    }
21630
21631    pub fn one_bone_solvers_mut(
21632        &mut self,
21633        index: usize,
21634    ) -> Option<crate::support::RefMut<'_, OneBoneSolver>> {
21635        if index >= self.one_bone_solvers_len() {
21636            return None;
21637        }
21638        // SAFETY: as above; `&mut self` guarantees exclusivity.
21639        unsafe {
21640            Some(crate::support::RefMut::new(OneBoneSolver {
21641                raw: core::ptr::NonNull::new_unchecked(
21642                    ffi::whiteout_m3_M3Model_get_oneBoneSolvers_at(self.raw.as_ptr(), index),
21643                ),
21644            }))
21645        }
21646    }
21647
21648    /// Iterate the elements, borrowing each in turn.
21649    pub fn one_bone_solvers_iter(
21650        &self,
21651    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, OneBoneSolver>> {
21652        (0..self.one_bone_solvers_len())
21653            .map(move |i| self.one_bone_solvers(i).expect("index below len"))
21654    }
21655
21656    pub fn resize_one_bone_solvers(&mut self, count: usize) {
21657        // SAFETY: exclusive access, so no borrow is outstanding.
21658        unsafe { ffi::whiteout_m3_M3Model_resize_oneBoneSolvers(self.raw.as_ptr(), count) }
21659    }
21660
21661    /// Turret behaviors (PATU)
21662    pub fn turret_behaviors_len(&self) -> usize {
21663        // SAFETY: scalar read through a live handle.
21664        unsafe { ffi::whiteout_m3_M3Model_get_turretBehaviors_count(self.raw.as_ptr()) }
21665    }
21666
21667    /// Borrows element `index` in place. `None` when out of range.
21668    pub fn turret_behaviors(
21669        &self,
21670        index: usize,
21671    ) -> Option<crate::support::Ref<'_, TurretBehavior>> {
21672        if index >= self.turret_behaviors_len() {
21673            return None;
21674        }
21675        // SAFETY: index checked above; the pointer is interior to `self`.
21676        unsafe {
21677            Some(crate::support::Ref::new(TurretBehavior {
21678                raw: core::ptr::NonNull::new_unchecked(
21679                    ffi::whiteout_m3_M3Model_get_turretBehaviors_at(self.raw.as_ptr(), index),
21680                ),
21681            }))
21682        }
21683    }
21684
21685    pub fn turret_behaviors_mut(
21686        &mut self,
21687        index: usize,
21688    ) -> Option<crate::support::RefMut<'_, TurretBehavior>> {
21689        if index >= self.turret_behaviors_len() {
21690            return None;
21691        }
21692        // SAFETY: as above; `&mut self` guarantees exclusivity.
21693        unsafe {
21694            Some(crate::support::RefMut::new(TurretBehavior {
21695                raw: core::ptr::NonNull::new_unchecked(
21696                    ffi::whiteout_m3_M3Model_get_turretBehaviors_at(self.raw.as_ptr(), index),
21697                ),
21698            }))
21699        }
21700    }
21701
21702    /// Iterate the elements, borrowing each in turn.
21703    pub fn turret_behaviors_iter(
21704        &self,
21705    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TurretBehavior>> {
21706        (0..self.turret_behaviors_len())
21707            .map(move |i| self.turret_behaviors(i).expect("index below len"))
21708    }
21709
21710    pub fn resize_turret_behaviors(&mut self, count: usize) {
21711        // SAFETY: exclusive access, so no borrow is outstanding.
21712        unsafe { ffi::whiteout_m3_M3Model_resize_turretBehaviors(self.raw.as_ptr(), count) }
21713    }
21714
21715    /// Trigger data (TRGD)
21716    pub fn trigger_data_len(&self) -> usize {
21717        // SAFETY: scalar read through a live handle.
21718        unsafe { ffi::whiteout_m3_M3Model_get_triggerData_count(self.raw.as_ptr()) }
21719    }
21720
21721    /// Borrows element `index` in place. `None` when out of range.
21722    pub fn trigger_data(&self, index: usize) -> Option<crate::support::Ref<'_, TriggerData>> {
21723        if index >= self.trigger_data_len() {
21724            return None;
21725        }
21726        // SAFETY: index checked above; the pointer is interior to `self`.
21727        unsafe {
21728            Some(crate::support::Ref::new(TriggerData {
21729                raw: core::ptr::NonNull::new_unchecked(
21730                    ffi::whiteout_m3_M3Model_get_triggerData_at(self.raw.as_ptr(), index),
21731                ),
21732            }))
21733        }
21734    }
21735
21736    pub fn trigger_data_mut(
21737        &mut self,
21738        index: usize,
21739    ) -> Option<crate::support::RefMut<'_, TriggerData>> {
21740        if index >= self.trigger_data_len() {
21741            return None;
21742        }
21743        // SAFETY: as above; `&mut self` guarantees exclusivity.
21744        unsafe {
21745            Some(crate::support::RefMut::new(TriggerData {
21746                raw: core::ptr::NonNull::new_unchecked(
21747                    ffi::whiteout_m3_M3Model_get_triggerData_at(self.raw.as_ptr(), index),
21748                ),
21749            }))
21750        }
21751    }
21752
21753    /// Iterate the elements, borrowing each in turn.
21754    pub fn trigger_data_iter(
21755        &self,
21756    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TriggerData>> {
21757        (0..self.trigger_data_len()).map(move |i| self.trigger_data(i).expect("index below len"))
21758    }
21759
21760    pub fn resize_trigger_data(&mut self, count: usize) {
21761        // SAFETY: exclusive access, so no borrow is outstanding.
21762        unsafe { ffi::whiteout_m3_M3Model_resize_triggerData(self.raw.as_ptr(), count) }
21763    }
21764
21765    /// Inverse bind-pose matrices (IREF)
21766    pub fn initial_reference_len(&self) -> usize {
21767        // SAFETY: scalar read through a live handle.
21768        unsafe { ffi::whiteout_m3_M3Model_get_initialReference_count(self.raw.as_ptr()) }
21769    }
21770
21771    /// Borrows element `index` in place. `None` when out of range.
21772    pub fn initial_reference(
21773        &self,
21774        index: usize,
21775    ) -> Option<crate::support::Ref<'_, InitialReference>> {
21776        if index >= self.initial_reference_len() {
21777            return None;
21778        }
21779        // SAFETY: index checked above; the pointer is interior to `self`.
21780        unsafe {
21781            Some(crate::support::Ref::new(InitialReference {
21782                raw: core::ptr::NonNull::new_unchecked(
21783                    ffi::whiteout_m3_M3Model_get_initialReference_at(self.raw.as_ptr(), index),
21784                ),
21785            }))
21786        }
21787    }
21788
21789    pub fn initial_reference_mut(
21790        &mut self,
21791        index: usize,
21792    ) -> Option<crate::support::RefMut<'_, InitialReference>> {
21793        if index >= self.initial_reference_len() {
21794            return None;
21795        }
21796        // SAFETY: as above; `&mut self` guarantees exclusivity.
21797        unsafe {
21798            Some(crate::support::RefMut::new(InitialReference {
21799                raw: core::ptr::NonNull::new_unchecked(
21800                    ffi::whiteout_m3_M3Model_get_initialReference_at(self.raw.as_ptr(), index),
21801                ),
21802            }))
21803        }
21804    }
21805
21806    /// Iterate the elements, borrowing each in turn.
21807    pub fn initial_reference_iter(
21808        &self,
21809    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, InitialReference>> {
21810        (0..self.initial_reference_len())
21811            .map(move |i| self.initial_reference(i).expect("index below len"))
21812    }
21813
21814    pub fn resize_initial_reference(&mut self, count: usize) {
21815        // SAFETY: exclusive access, so no borrow is outstanding.
21816        unsafe { ffi::whiteout_m3_M3Model_resize_initialReference(self.raw.as_ptr(), count) }
21817    }
21818
21819    /// Tight hit-test shape (SSGS, inline)
21820    /// Borrows the field in place — no copy, no allocation.
21821    pub fn tight_hit_test_object(&self) -> crate::support::Ref<'_, HitTestShape> {
21822        // SAFETY: an interior pointer into `self`, valid for this
21823        // borrow and never freed by the `Ref`.
21824        unsafe {
21825            crate::support::Ref::new(HitTestShape {
21826                raw: core::ptr::NonNull::new_unchecked(
21827                    ffi::whiteout_m3_M3Model_get_tightHitTestObject(self.raw.as_ptr()),
21828                ),
21829            })
21830        }
21831    }
21832
21833    pub fn tight_hit_test_object_mut(&mut self) -> crate::support::RefMut<'_, HitTestShape> {
21834        // SAFETY: as above; `&mut self` guarantees exclusivity.
21835        unsafe {
21836            crate::support::RefMut::new(HitTestShape {
21837                raw: core::ptr::NonNull::new_unchecked(
21838                    ffi::whiteout_m3_M3Model_get_tightHitTestObject(self.raw.as_ptr()),
21839                ),
21840            })
21841        }
21842    }
21843
21844    /// Fuzzy hit-test shapes (SSGS)
21845    pub fn fuzzy_hit_test_objects_len(&self) -> usize {
21846        // SAFETY: scalar read through a live handle.
21847        unsafe { ffi::whiteout_m3_M3Model_get_fuzzyHitTestObjects_count(self.raw.as_ptr()) }
21848    }
21849
21850    /// Borrows element `index` in place. `None` when out of range.
21851    pub fn fuzzy_hit_test_objects(
21852        &self,
21853        index: usize,
21854    ) -> Option<crate::support::Ref<'_, HitTestShape>> {
21855        if index >= self.fuzzy_hit_test_objects_len() {
21856            return None;
21857        }
21858        // SAFETY: index checked above; the pointer is interior to `self`.
21859        unsafe {
21860            Some(crate::support::Ref::new(HitTestShape {
21861                raw: core::ptr::NonNull::new_unchecked(
21862                    ffi::whiteout_m3_M3Model_get_fuzzyHitTestObjects_at(self.raw.as_ptr(), index),
21863                ),
21864            }))
21865        }
21866    }
21867
21868    pub fn fuzzy_hit_test_objects_mut(
21869        &mut self,
21870        index: usize,
21871    ) -> Option<crate::support::RefMut<'_, HitTestShape>> {
21872        if index >= self.fuzzy_hit_test_objects_len() {
21873            return None;
21874        }
21875        // SAFETY: as above; `&mut self` guarantees exclusivity.
21876        unsafe {
21877            Some(crate::support::RefMut::new(HitTestShape {
21878                raw: core::ptr::NonNull::new_unchecked(
21879                    ffi::whiteout_m3_M3Model_get_fuzzyHitTestObjects_at(self.raw.as_ptr(), index),
21880                ),
21881            }))
21882        }
21883    }
21884
21885    /// Iterate the elements, borrowing each in turn.
21886    pub fn fuzzy_hit_test_objects_iter(
21887        &self,
21888    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, HitTestShape>> {
21889        (0..self.fuzzy_hit_test_objects_len())
21890            .map(move |i| self.fuzzy_hit_test_objects(i).expect("index below len"))
21891    }
21892
21893    pub fn resize_fuzzy_hit_test_objects(&mut self, count: usize) {
21894        // SAFETY: exclusive access, so no borrow is outstanding.
21895        unsafe { ffi::whiteout_m3_M3Model_resize_fuzzyHitTestObjects(self.raw.as_ptr(), count) }
21896    }
21897
21898    /// Attachment volumes (ATVL)
21899    pub fn attachment_volumes_len(&self) -> usize {
21900        // SAFETY: scalar read through a live handle.
21901        unsafe { ffi::whiteout_m3_M3Model_get_attachmentVolumes_count(self.raw.as_ptr()) }
21902    }
21903
21904    /// Borrows element `index` in place. `None` when out of range.
21905    pub fn attachment_volumes(
21906        &self,
21907        index: usize,
21908    ) -> Option<crate::support::Ref<'_, AttachmentVolume>> {
21909        if index >= self.attachment_volumes_len() {
21910            return None;
21911        }
21912        // SAFETY: index checked above; the pointer is interior to `self`.
21913        unsafe {
21914            Some(crate::support::Ref::new(AttachmentVolume {
21915                raw: core::ptr::NonNull::new_unchecked(
21916                    ffi::whiteout_m3_M3Model_get_attachmentVolumes_at(self.raw.as_ptr(), index),
21917                ),
21918            }))
21919        }
21920    }
21921
21922    pub fn attachment_volumes_mut(
21923        &mut self,
21924        index: usize,
21925    ) -> Option<crate::support::RefMut<'_, AttachmentVolume>> {
21926        if index >= self.attachment_volumes_len() {
21927            return None;
21928        }
21929        // SAFETY: as above; `&mut self` guarantees exclusivity.
21930        unsafe {
21931            Some(crate::support::RefMut::new(AttachmentVolume {
21932                raw: core::ptr::NonNull::new_unchecked(
21933                    ffi::whiteout_m3_M3Model_get_attachmentVolumes_at(self.raw.as_ptr(), index),
21934                ),
21935            }))
21936        }
21937    }
21938
21939    /// Iterate the elements, borrowing each in turn.
21940    pub fn attachment_volumes_iter(
21941        &self,
21942    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AttachmentVolume>> {
21943        (0..self.attachment_volumes_len())
21944            .map(move |i| self.attachment_volumes(i).expect("index below len"))
21945    }
21946
21947    pub fn resize_attachment_volumes(&mut self, count: usize) {
21948        // SAFETY: exclusive access, so no borrow is outstanding.
21949        unsafe { ffi::whiteout_m3_M3Model_resize_attachmentVolumes(self.raw.as_ptr(), count) }
21950    }
21951
21952    /// Attachment volume addon 0 (U16_)
21953    /// Zero-copy view of the underlying `std::vector`.
21954    pub fn attachment_volumes_addon_0(&self) -> &[u16] {
21955        // SAFETY: `_data`/`_count` describe one contiguous C++
21956        // allocation, borrowed for as long as `self` is.
21957        unsafe {
21958            let n = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon0_count(self.raw.as_ptr());
21959            let p = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon0_data(self.raw.as_ptr());
21960            if p.is_null() || n == 0 {
21961                &[]
21962            } else {
21963                core::slice::from_raw_parts(p, n)
21964            }
21965        }
21966    }
21967
21968    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
21969    pub fn attachment_volumes_addon_0_mut(&mut self) -> &mut [u16] {
21970        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
21971        unsafe {
21972            let n = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon0_count(self.raw.as_ptr());
21973            let p = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon0_data(self.raw.as_ptr())
21974                as *mut u16;
21975            if p.is_null() || n == 0 {
21976                &mut []
21977            } else {
21978                core::slice::from_raw_parts_mut(p, n)
21979            }
21980        }
21981    }
21982
21983    pub fn set_attachment_volumes_addon_0(&mut self, values: &[u16]) {
21984        // SAFETY: the native side copies `values` before returning.
21985        unsafe {
21986            ffi::whiteout_m3_M3Model_assign_attachmentVolumesAddon0(
21987                self.raw.as_ptr(),
21988                values.as_ptr() as *const _,
21989                values.len(),
21990            )
21991        }
21992    }
21993
21994    pub fn resize_attachment_volumes_addon_0(&mut self, count: usize) {
21995        // SAFETY: reallocation is safe here precisely because
21996        // `&mut self` means no slice borrow is outstanding.
21997        unsafe { ffi::whiteout_m3_M3Model_resize_attachmentVolumesAddon0(self.raw.as_ptr(), count) }
21998    }
21999
22000    /// Attachment volume addon 1 (U16_)
22001    /// Zero-copy view of the underlying `std::vector`.
22002    pub fn attachment_volumes_addon_1(&self) -> &[u16] {
22003        // SAFETY: `_data`/`_count` describe one contiguous C++
22004        // allocation, borrowed for as long as `self` is.
22005        unsafe {
22006            let n = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon1_count(self.raw.as_ptr());
22007            let p = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon1_data(self.raw.as_ptr());
22008            if p.is_null() || n == 0 {
22009                &[]
22010            } else {
22011                core::slice::from_raw_parts(p, n)
22012            }
22013        }
22014    }
22015
22016    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
22017    pub fn attachment_volumes_addon_1_mut(&mut self) -> &mut [u16] {
22018        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
22019        unsafe {
22020            let n = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon1_count(self.raw.as_ptr());
22021            let p = ffi::whiteout_m3_M3Model_get_attachmentVolumesAddon1_data(self.raw.as_ptr())
22022                as *mut u16;
22023            if p.is_null() || n == 0 {
22024                &mut []
22025            } else {
22026                core::slice::from_raw_parts_mut(p, n)
22027            }
22028        }
22029    }
22030
22031    pub fn set_attachment_volumes_addon_1(&mut self, values: &[u16]) {
22032        // SAFETY: the native side copies `values` before returning.
22033        unsafe {
22034            ffi::whiteout_m3_M3Model_assign_attachmentVolumesAddon1(
22035                self.raw.as_ptr(),
22036                values.as_ptr() as *const _,
22037                values.len(),
22038            )
22039        }
22040    }
22041
22042    pub fn resize_attachment_volumes_addon_1(&mut self, count: usize) {
22043        // SAFETY: reallocation is safe here precisely because
22044        // `&mut self` means no slice borrow is outstanding.
22045        unsafe { ffi::whiteout_m3_M3Model_resize_attachmentVolumesAddon1(self.raw.as_ptr(), count) }
22046    }
22047
22048    /// Billboard behaviors (BBSC)
22049    pub fn billboard_behaviors_len(&self) -> usize {
22050        // SAFETY: scalar read through a live handle.
22051        unsafe { ffi::whiteout_m3_M3Model_get_billboardBehaviors_count(self.raw.as_ptr()) }
22052    }
22053
22054    /// Borrows element `index` in place. `None` when out of range.
22055    pub fn billboard_behaviors(
22056        &self,
22057        index: usize,
22058    ) -> Option<crate::support::Ref<'_, BillboardBehavior>> {
22059        if index >= self.billboard_behaviors_len() {
22060            return None;
22061        }
22062        // SAFETY: index checked above; the pointer is interior to `self`.
22063        unsafe {
22064            Some(crate::support::Ref::new(BillboardBehavior {
22065                raw: core::ptr::NonNull::new_unchecked(
22066                    ffi::whiteout_m3_M3Model_get_billboardBehaviors_at(self.raw.as_ptr(), index),
22067                ),
22068            }))
22069        }
22070    }
22071
22072    pub fn billboard_behaviors_mut(
22073        &mut self,
22074        index: usize,
22075    ) -> Option<crate::support::RefMut<'_, BillboardBehavior>> {
22076        if index >= self.billboard_behaviors_len() {
22077            return None;
22078        }
22079        // SAFETY: as above; `&mut self` guarantees exclusivity.
22080        unsafe {
22081            Some(crate::support::RefMut::new(BillboardBehavior {
22082                raw: core::ptr::NonNull::new_unchecked(
22083                    ffi::whiteout_m3_M3Model_get_billboardBehaviors_at(self.raw.as_ptr(), index),
22084                ),
22085            }))
22086        }
22087    }
22088
22089    /// Iterate the elements, borrowing each in turn.
22090    pub fn billboard_behaviors_iter(
22091        &self,
22092    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, BillboardBehavior>> {
22093        (0..self.billboard_behaviors_len())
22094            .map(move |i| self.billboard_behaviors(i).expect("index below len"))
22095    }
22096
22097    pub fn resize_billboard_behaviors(&mut self, count: usize) {
22098        // SAFETY: exclusive access, so no borrow is outstanding.
22099        unsafe { ffi::whiteout_m3_M3Model_resize_billboardBehaviors(self.raw.as_ptr(), count) }
22100    }
22101
22102    /// Trailing models (TMD_, defunct)
22103    pub fn trailing_models_len(&self) -> usize {
22104        // SAFETY: scalar read through a live handle.
22105        unsafe { ffi::whiteout_m3_M3Model_get_trailingModels_count(self.raw.as_ptr()) }
22106    }
22107
22108    /// Borrows element `index` in place. `None` when out of range.
22109    pub fn trailing_models(&self, index: usize) -> Option<crate::support::Ref<'_, TrailingModel>> {
22110        if index >= self.trailing_models_len() {
22111            return None;
22112        }
22113        // SAFETY: index checked above; the pointer is interior to `self`.
22114        unsafe {
22115            Some(crate::support::Ref::new(TrailingModel {
22116                raw: core::ptr::NonNull::new_unchecked(
22117                    ffi::whiteout_m3_M3Model_get_trailingModels_at(self.raw.as_ptr(), index),
22118                ),
22119            }))
22120        }
22121    }
22122
22123    pub fn trailing_models_mut(
22124        &mut self,
22125        index: usize,
22126    ) -> Option<crate::support::RefMut<'_, TrailingModel>> {
22127        if index >= self.trailing_models_len() {
22128            return None;
22129        }
22130        // SAFETY: as above; `&mut self` guarantees exclusivity.
22131        unsafe {
22132            Some(crate::support::RefMut::new(TrailingModel {
22133                raw: core::ptr::NonNull::new_unchecked(
22134                    ffi::whiteout_m3_M3Model_get_trailingModels_at(self.raw.as_ptr(), index),
22135                ),
22136            }))
22137        }
22138    }
22139
22140    /// Iterate the elements, borrowing each in turn.
22141    pub fn trailing_models_iter(
22142        &self,
22143    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TrailingModel>> {
22144        (0..self.trailing_models_len())
22145            .map(move |i| self.trailing_models(i).expect("index below len"))
22146    }
22147
22148    pub fn resize_trailing_models(&mut self, count: usize) {
22149        // SAFETY: exclusive access, so no borrow is outstanding.
22150        unsafe { ffi::whiteout_m3_M3Model_resize_trailingModels(self.raw.as_ptr(), count) }
22151    }
22152
22153    /// Hash for .m3a animation file binding
22154    pub fn m_3a_anim_hash(&self) -> u32 {
22155        // SAFETY: plain scalar read through a live handle.
22156        unsafe { ffi::whiteout_m3_M3Model_get_m3aAnimHash(self.raw.as_ptr()) }
22157    }
22158
22159    pub fn set_m_3a_anim_hash(&mut self, value: u32) {
22160        // SAFETY: plain scalar write through a live handle.
22161        unsafe { ffi::whiteout_m3_M3Model_set_m3aAnimHash(self.raw.as_ptr(), value) }
22162    }
22163
22164    /// Additional .m3a hashes (U32_)
22165    /// Zero-copy view of the underlying `std::vector`.
22166    pub fn m_3a_anim_hashes(&self) -> &[u32] {
22167        // SAFETY: `_data`/`_count` describe one contiguous C++
22168        // allocation, borrowed for as long as `self` is.
22169        unsafe {
22170            let n = ffi::whiteout_m3_M3Model_get_m3aAnimHashes_count(self.raw.as_ptr());
22171            let p = ffi::whiteout_m3_M3Model_get_m3aAnimHashes_data(self.raw.as_ptr());
22172            if p.is_null() || n == 0 {
22173                &[]
22174            } else {
22175                core::slice::from_raw_parts(p, n)
22176            }
22177        }
22178    }
22179
22180    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
22181    pub fn m_3a_anim_hashes_mut(&mut self) -> &mut [u32] {
22182        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
22183        unsafe {
22184            let n = ffi::whiteout_m3_M3Model_get_m3aAnimHashes_count(self.raw.as_ptr());
22185            let p = ffi::whiteout_m3_M3Model_get_m3aAnimHashes_data(self.raw.as_ptr()) as *mut u32;
22186            if p.is_null() || n == 0 {
22187                &mut []
22188            } else {
22189                core::slice::from_raw_parts_mut(p, n)
22190            }
22191        }
22192    }
22193
22194    pub fn set_m_3a_anim_hashes(&mut self, values: &[u32]) {
22195        // SAFETY: the native side copies `values` before returning.
22196        unsafe {
22197            ffi::whiteout_m3_M3Model_assign_m3aAnimHashes(
22198                self.raw.as_ptr(),
22199                values.as_ptr() as *const _,
22200                values.len(),
22201            )
22202        }
22203    }
22204
22205    pub fn resize_m_3a_anim_hashes(&mut self, count: usize) {
22206        // SAFETY: reallocation is safe here precisely because
22207        // `&mut self` means no slice borrow is outstanding.
22208        unsafe { ffi::whiteout_m3_M3Model_resize_m3aAnimHashes(self.raw.as_ptr(), count) }
22209    }
22210}
22211
22212impl Default for Model {
22213    fn default() -> Self {
22214        Self::new()
22215    }
22216}
22217
22218/// Parser for M3 model files
22219///
22220/// The Parser reads binary M3 files and converts them into the Model structure. It supports multiple parsing modes for error handling.
22221///
22222/// Uses the PImpl (Pointer to Implementation) idiom to hide implementation details.
22223pub struct Parser {
22224    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Parser>,
22225}
22226
22227impl Drop for Parser {
22228    fn drop(&mut self) {
22229        // SAFETY: `raw` came from a native constructor and Drop runs once.
22230        unsafe { ffi::whiteout_m3_M3Parser_delete(self.raw.as_ptr()) }
22231    }
22232}
22233
22234impl Parser {
22235    /// # Safety
22236    /// `raw` must be a live handle this value takes ownership of.
22237    #[allow(dead_code)] // used by whichever methods return this type
22238    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Parser) -> Option<Self> {
22239        core::ptr::NonNull::new(raw).map(|raw| Parser { raw })
22240    }
22241}
22242
22243// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22244// is deliberately NOT implemented — the C++ types make no documented
22245// guarantee about concurrent use, and claiming one we haven't verified
22246// would be unsound. See `@bind thread_safe` in the plan.
22247unsafe impl Send for Parser {}
22248
22249impl core::fmt::Debug for Parser {
22250    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22251        f.debug_struct("Parser").finish_non_exhaustive()
22252    }
22253}
22254
22255impl Parser {
22256    /// # Panics
22257    /// Panics if the native allocation fails.
22258    pub fn new() -> Self {
22259        // SAFETY: the native constructor returns a live handle; a null here
22260        // means the library is unusable.
22261        unsafe {
22262            let raw = ffi::whiteout_m3_M3Parser_new();
22263            Self::from_raw(raw).expect("native Parser allocation failed")
22264        }
22265    }
22266
22267    /// Parse an M3 file from disk @param filePath Path to the M3 file @return Parsed M3 model data @throws std::runtime_error If file cannot be opened or parsing fails in strict mode
22268    pub fn parse_file(&mut self, file_path: &str) -> Option<Model> {
22269        let file_path_cstr = std::ffi::CString::new(file_path).unwrap_or_default();
22270        // SAFETY: handle is live for the duration of the call.
22271        unsafe {
22272            Model::from_raw(ffi::whiteout_m3_M3Parser_parse(
22273                self.raw.as_ptr(),
22274                file_path_cstr.as_ptr(),
22275            ))
22276        }
22277    }
22278
22279    /// Parse an M3 file from memory buffer @param buffer Memory buffer containing M3 data @return Parsed M3 model data @throws std::runtime_error If parsing fails in strict mode
22280    pub fn parse(&mut self, buffer: &[u8]) -> Option<Model> {
22281        // SAFETY: handle is live for the duration of the call.
22282        unsafe {
22283            Model::from_raw(ffi::whiteout_m3_M3Parser_parse_buffer(
22284                self.raw.as_ptr(),
22285                buffer.as_ptr(),
22286                buffer.len(),
22287            ))
22288        }
22289    }
22290
22291    /// Check if parsing encountered any issues @return True if there were warnings or recoverable errors
22292    pub fn has_issues(&self) -> bool {
22293        // SAFETY: handle is live for the duration of the call.
22294        unsafe { ffi::whiteout_m3_M3Parser_hasIssues(self.raw.as_ptr()) != 0 }
22295    }
22296
22297    /// Get list of issues encountered during parsing @return Vector of issue description strings
22298    pub fn issues(&self) -> Vec<String> {
22299        // SAFETY: index stays below the reported count.
22300        unsafe {
22301            let n = ffi::whiteout_m3_M3Parser_getIssues_count(self.raw.as_ptr());
22302            (0..n)
22303                .map(|i| {
22304                    crate::support::take_string(ffi::whiteout_m3_M3Parser_getIssues_at(
22305                        self.raw.as_ptr(),
22306                        i,
22307                    ))
22308                })
22309                .collect()
22310        }
22311    }
22312}
22313
22314impl Default for Parser {
22315    fn default() -> Self {
22316        Self::new()
22317    }
22318}
22319
22320/// Writer for M3 model files
22321///
22322/// Writes Model structures to disk in binary M3 format. Uses the PImpl (Pointer to Implementation) idiom to hide implementation details.
22323pub struct Writer {
22324    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3Writer>,
22325}
22326
22327impl Drop for Writer {
22328    fn drop(&mut self) {
22329        // SAFETY: `raw` came from a native constructor and Drop runs once.
22330        unsafe { ffi::whiteout_m3_M3Writer_delete(self.raw.as_ptr()) }
22331    }
22332}
22333
22334impl Writer {
22335    /// # Safety
22336    /// `raw` must be a live handle this value takes ownership of.
22337    #[allow(dead_code)] // used by whichever methods return this type
22338    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3Writer) -> Option<Self> {
22339        core::ptr::NonNull::new(raw).map(|raw| Writer { raw })
22340    }
22341}
22342
22343// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22344// is deliberately NOT implemented — the C++ types make no documented
22345// guarantee about concurrent use, and claiming one we haven't verified
22346// would be unsound. See `@bind thread_safe` in the plan.
22347unsafe impl Send for Writer {}
22348
22349impl core::fmt::Debug for Writer {
22350    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22351        f.debug_struct("Writer").finish_non_exhaustive()
22352    }
22353}
22354
22355impl Writer {
22356    /// # Panics
22357    /// Panics if the native allocation fails.
22358    pub fn new() -> Self {
22359        // SAFETY: the native constructor returns a live handle; a null here
22360        // means the library is unusable.
22361        unsafe {
22362            let raw = ffi::whiteout_m3_M3Writer_new();
22363            Self::from_raw(raw).expect("native Writer allocation failed")
22364        }
22365    }
22366
22367    /// Write an M3 model to a file on disk @param filePath Output file path @param model Model data to serialize @throws std::runtime_error If file cannot be created or writing fails
22368    pub fn write_file(&mut self, file_path: &str, model: &Model) {
22369        let file_path_cstr = std::ffi::CString::new(file_path).unwrap_or_default();
22370        // SAFETY: handle is live for the duration of the call.
22371        unsafe {
22372            ffi::whiteout_m3_M3Writer_write(
22373                self.raw.as_ptr(),
22374                file_path_cstr.as_ptr(),
22375                model.raw.as_ptr(),
22376            );
22377        }
22378    }
22379
22380    /// Write an M3 model to a byte buffer @param model Model data to serialize @return Byte buffer containing the M3 file data
22381    pub fn write(&mut self, model: &Model) -> Bytes {
22382        // SAFETY: handle is live for the duration of the call.
22383        unsafe {
22384            Bytes::from_raw(ffi::whiteout_m3_M3Writer_write_model(
22385                self.raw.as_ptr(),
22386                model.raw.as_ptr(),
22387            ))
22388            .unwrap_or_else(Bytes::empty)
22389        }
22390    }
22391}
22392
22393impl Default for Writer {
22394    fn default() -> Self {
22395        Self::new()
22396    }
22397}
22398
22399/// Animatable reference holding a default value and animation link
22400///
22401/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
22402///
22403/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
22404pub struct AnimRefF32 {
22405    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefF32>,
22406}
22407
22408impl Drop for AnimRefF32 {
22409    fn drop(&mut self) {
22410        // SAFETY: `raw` came from a native constructor and Drop runs once.
22411        unsafe { ffi::whiteout_m3_M3AnimRefF32_delete(self.raw.as_ptr()) }
22412    }
22413}
22414
22415impl AnimRefF32 {
22416    /// # Safety
22417    /// `raw` must be a live handle this value takes ownership of.
22418    #[allow(dead_code)] // used by whichever methods return this type
22419    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefF32) -> Option<Self> {
22420        core::ptr::NonNull::new(raw).map(|raw| AnimRefF32 { raw })
22421    }
22422}
22423
22424// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22425// is deliberately NOT implemented — the C++ types make no documented
22426// guarantee about concurrent use, and claiming one we haven't verified
22427// would be unsound. See `@bind thread_safe` in the plan.
22428unsafe impl Send for AnimRefF32 {}
22429
22430impl core::fmt::Debug for AnimRefF32 {
22431    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22432        f.debug_struct("AnimRefF32").finish_non_exhaustive()
22433    }
22434}
22435
22436impl AnimRefF32 {
22437    /// # Panics
22438    /// Panics if the native allocation fails.
22439    pub fn new() -> Self {
22440        // SAFETY: the native constructor returns a live handle; a null here
22441        // means the library is unusable.
22442        unsafe {
22443            let raw = ffi::whiteout_m3_M3AnimRefF32_new();
22444            Self::from_raw(raw).expect("native AnimRefF32 allocation failed")
22445        }
22446    }
22447
22448    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
22449    pub fn interp_type(&self) -> u16 {
22450        // SAFETY: plain scalar read through a live handle.
22451        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_interpType(self.raw.as_ptr()) }
22452    }
22453
22454    pub fn set_interp_type(&mut self, value: u16) {
22455        // SAFETY: plain scalar write through a live handle.
22456        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_interpType(self.raw.as_ptr(), value) }
22457    }
22458
22459    /// Animation flags
22460    pub fn flags(&self) -> u16 {
22461        // SAFETY: plain scalar read through a live handle.
22462        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_flags(self.raw.as_ptr()) }
22463    }
22464
22465    pub fn set_flags(&mut self, value: u16) {
22466        // SAFETY: plain scalar write through a live handle.
22467        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_flags(self.raw.as_ptr(), value) }
22468    }
22469
22470    /// Animation identifier (links to STC animation data; 0=not animated)
22471    pub fn anim_id(&self) -> u32 {
22472        // SAFETY: plain scalar read through a live handle.
22473        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_animId(self.raw.as_ptr()) }
22474    }
22475
22476    pub fn set_anim_id(&mut self, value: u32) {
22477        // SAFETY: plain scalar write through a live handle.
22478        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_animId(self.raw.as_ptr(), value) }
22479    }
22480
22481    /// Initial/default value (used when not animated)
22482    pub fn init_value(&self) -> f32 {
22483        // SAFETY: plain scalar read through a live handle.
22484        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_initValue(self.raw.as_ptr()) }
22485    }
22486
22487    pub fn set_init_value(&mut self, value: f32) {
22488        // SAFETY: plain scalar write through a live handle.
22489        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_initValue(self.raw.as_ptr(), value) }
22490    }
22491
22492    /// Null/reset value
22493    pub fn null_value(&self) -> f32 {
22494        // SAFETY: plain scalar read through a live handle.
22495        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_nullValue(self.raw.as_ptr()) }
22496    }
22497
22498    pub fn set_null_value(&mut self, value: f32) {
22499        // SAFETY: plain scalar write through a live handle.
22500        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_nullValue(self.raw.as_ptr(), value) }
22501    }
22502
22503    /// Typically -1
22504    pub fn unused(&self) -> i32 {
22505        // SAFETY: plain scalar read through a live handle.
22506        unsafe { ffi::whiteout_m3_M3AnimRefF32_get_unused(self.raw.as_ptr()) }
22507    }
22508
22509    pub fn set_unused(&mut self, value: i32) {
22510        // SAFETY: plain scalar write through a live handle.
22511        unsafe { ffi::whiteout_m3_M3AnimRefF32_set_unused(self.raw.as_ptr(), value) }
22512    }
22513}
22514
22515impl Default for AnimRefF32 {
22516    fn default() -> Self {
22517        Self::new()
22518    }
22519}
22520
22521/// Animatable reference holding a default value and animation link
22522///
22523/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
22524///
22525/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
22526pub struct AnimRefVector3f {
22527    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefVector3f>,
22528}
22529
22530impl Drop for AnimRefVector3f {
22531    fn drop(&mut self) {
22532        // SAFETY: `raw` came from a native constructor and Drop runs once.
22533        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_delete(self.raw.as_ptr()) }
22534    }
22535}
22536
22537impl AnimRefVector3f {
22538    /// # Safety
22539    /// `raw` must be a live handle this value takes ownership of.
22540    #[allow(dead_code)] // used by whichever methods return this type
22541    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefVector3f) -> Option<Self> {
22542        core::ptr::NonNull::new(raw).map(|raw| AnimRefVector3f { raw })
22543    }
22544}
22545
22546// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22547// is deliberately NOT implemented — the C++ types make no documented
22548// guarantee about concurrent use, and claiming one we haven't verified
22549// would be unsound. See `@bind thread_safe` in the plan.
22550unsafe impl Send for AnimRefVector3f {}
22551
22552impl core::fmt::Debug for AnimRefVector3f {
22553    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22554        f.debug_struct("AnimRefVector3f").finish_non_exhaustive()
22555    }
22556}
22557
22558impl AnimRefVector3f {
22559    /// # Panics
22560    /// Panics if the native allocation fails.
22561    pub fn new() -> Self {
22562        // SAFETY: the native constructor returns a live handle; a null here
22563        // means the library is unusable.
22564        unsafe {
22565            let raw = ffi::whiteout_m3_M3AnimRefVector3f_new();
22566            Self::from_raw(raw).expect("native AnimRefVector3f allocation failed")
22567        }
22568    }
22569
22570    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
22571    pub fn interp_type(&self) -> u16 {
22572        // SAFETY: plain scalar read through a live handle.
22573        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_get_interpType(self.raw.as_ptr()) }
22574    }
22575
22576    pub fn set_interp_type(&mut self, value: u16) {
22577        // SAFETY: plain scalar write through a live handle.
22578        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_set_interpType(self.raw.as_ptr(), value) }
22579    }
22580
22581    /// Animation flags
22582    pub fn flags(&self) -> u16 {
22583        // SAFETY: plain scalar read through a live handle.
22584        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_get_flags(self.raw.as_ptr()) }
22585    }
22586
22587    pub fn set_flags(&mut self, value: u16) {
22588        // SAFETY: plain scalar write through a live handle.
22589        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_set_flags(self.raw.as_ptr(), value) }
22590    }
22591
22592    /// Animation identifier (links to STC animation data; 0=not animated)
22593    pub fn anim_id(&self) -> u32 {
22594        // SAFETY: plain scalar read through a live handle.
22595        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_get_animId(self.raw.as_ptr()) }
22596    }
22597
22598    pub fn set_anim_id(&mut self, value: u32) {
22599        // SAFETY: plain scalar write through a live handle.
22600        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_set_animId(self.raw.as_ptr(), value) }
22601    }
22602
22603    /// Initial/default value (used when not animated)
22604    pub fn init_value(&self) -> crate::math::Vector3f {
22605        // SAFETY: the getter returns an interior pointer to a
22606        // layout-identical POD; we copy it out immediately.
22607        unsafe {
22608            *(ffi::whiteout_m3_M3AnimRefVector3f_get_initValue(self.raw.as_ptr())
22609                as *const crate::math::Vector3f)
22610        }
22611    }
22612
22613    pub fn set_init_value(&mut self, value: crate::math::Vector3f) {
22614        // SAFETY: as above, in the other direction.
22615        unsafe {
22616            ffi::whiteout_m3_M3AnimRefVector3f_set_initValue(
22617                self.raw.as_ptr(),
22618                &value as *const crate::math::Vector3f as *const _,
22619            )
22620        }
22621    }
22622
22623    /// Null/reset value
22624    pub fn null_value(&self) -> crate::math::Vector3f {
22625        // SAFETY: the getter returns an interior pointer to a
22626        // layout-identical POD; we copy it out immediately.
22627        unsafe {
22628            *(ffi::whiteout_m3_M3AnimRefVector3f_get_nullValue(self.raw.as_ptr())
22629                as *const crate::math::Vector3f)
22630        }
22631    }
22632
22633    pub fn set_null_value(&mut self, value: crate::math::Vector3f) {
22634        // SAFETY: as above, in the other direction.
22635        unsafe {
22636            ffi::whiteout_m3_M3AnimRefVector3f_set_nullValue(
22637                self.raw.as_ptr(),
22638                &value as *const crate::math::Vector3f as *const _,
22639            )
22640        }
22641    }
22642
22643    /// Typically -1
22644    pub fn unused(&self) -> i32 {
22645        // SAFETY: plain scalar read through a live handle.
22646        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_get_unused(self.raw.as_ptr()) }
22647    }
22648
22649    pub fn set_unused(&mut self, value: i32) {
22650        // SAFETY: plain scalar write through a live handle.
22651        unsafe { ffi::whiteout_m3_M3AnimRefVector3f_set_unused(self.raw.as_ptr(), value) }
22652    }
22653}
22654
22655impl Default for AnimRefVector3f {
22656    fn default() -> Self {
22657        Self::new()
22658    }
22659}
22660
22661/// Animatable reference holding a default value and animation link
22662///
22663/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
22664///
22665/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
22666pub struct AnimRefM3ColorBGRA {
22667    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefM3ColorBGRA>,
22668}
22669
22670impl Drop for AnimRefM3ColorBGRA {
22671    fn drop(&mut self) {
22672        // SAFETY: `raw` came from a native constructor and Drop runs once.
22673        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_delete(self.raw.as_ptr()) }
22674    }
22675}
22676
22677impl AnimRefM3ColorBGRA {
22678    /// # Safety
22679    /// `raw` must be a live handle this value takes ownership of.
22680    #[allow(dead_code)] // used by whichever methods return this type
22681    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefM3ColorBGRA) -> Option<Self> {
22682        core::ptr::NonNull::new(raw).map(|raw| AnimRefM3ColorBGRA { raw })
22683    }
22684}
22685
22686// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22687// is deliberately NOT implemented — the C++ types make no documented
22688// guarantee about concurrent use, and claiming one we haven't verified
22689// would be unsound. See `@bind thread_safe` in the plan.
22690unsafe impl Send for AnimRefM3ColorBGRA {}
22691
22692impl core::fmt::Debug for AnimRefM3ColorBGRA {
22693    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22694        f.debug_struct("AnimRefM3ColorBGRA").finish_non_exhaustive()
22695    }
22696}
22697
22698impl AnimRefM3ColorBGRA {
22699    /// # Panics
22700    /// Panics if the native allocation fails.
22701    pub fn new() -> Self {
22702        // SAFETY: the native constructor returns a live handle; a null here
22703        // means the library is unusable.
22704        unsafe {
22705            let raw = ffi::whiteout_m3_M3AnimRefM3ColorBGRA_new();
22706            Self::from_raw(raw).expect("native AnimRefM3ColorBGRA allocation failed")
22707        }
22708    }
22709
22710    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
22711    pub fn interp_type(&self) -> u16 {
22712        // SAFETY: plain scalar read through a live handle.
22713        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_interpType(self.raw.as_ptr()) }
22714    }
22715
22716    pub fn set_interp_type(&mut self, value: u16) {
22717        // SAFETY: plain scalar write through a live handle.
22718        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_set_interpType(self.raw.as_ptr(), value) }
22719    }
22720
22721    /// Animation flags
22722    pub fn flags(&self) -> u16 {
22723        // SAFETY: plain scalar read through a live handle.
22724        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_flags(self.raw.as_ptr()) }
22725    }
22726
22727    pub fn set_flags(&mut self, value: u16) {
22728        // SAFETY: plain scalar write through a live handle.
22729        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_set_flags(self.raw.as_ptr(), value) }
22730    }
22731
22732    /// Animation identifier (links to STC animation data; 0=not animated)
22733    pub fn anim_id(&self) -> u32 {
22734        // SAFETY: plain scalar read through a live handle.
22735        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_animId(self.raw.as_ptr()) }
22736    }
22737
22738    pub fn set_anim_id(&mut self, value: u32) {
22739        // SAFETY: plain scalar write through a live handle.
22740        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_set_animId(self.raw.as_ptr(), value) }
22741    }
22742
22743    /// Initial/default value (used when not animated)
22744    /// Borrows the field in place — no copy, no allocation.
22745    pub fn init_value(&self) -> crate::support::Ref<'_, ColorBGRA> {
22746        // SAFETY: an interior pointer into `self`, valid for this
22747        // borrow and never freed by the `Ref`.
22748        unsafe {
22749            crate::support::Ref::new(ColorBGRA {
22750                raw: core::ptr::NonNull::new_unchecked(
22751                    ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_initValue(self.raw.as_ptr()),
22752                ),
22753            })
22754        }
22755    }
22756
22757    pub fn init_value_mut(&mut self) -> crate::support::RefMut<'_, ColorBGRA> {
22758        // SAFETY: as above; `&mut self` guarantees exclusivity.
22759        unsafe {
22760            crate::support::RefMut::new(ColorBGRA {
22761                raw: core::ptr::NonNull::new_unchecked(
22762                    ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_initValue(self.raw.as_ptr()),
22763                ),
22764            })
22765        }
22766    }
22767
22768    /// Null/reset value
22769    /// Borrows the field in place — no copy, no allocation.
22770    pub fn null_value(&self) -> crate::support::Ref<'_, ColorBGRA> {
22771        // SAFETY: an interior pointer into `self`, valid for this
22772        // borrow and never freed by the `Ref`.
22773        unsafe {
22774            crate::support::Ref::new(ColorBGRA {
22775                raw: core::ptr::NonNull::new_unchecked(
22776                    ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_nullValue(self.raw.as_ptr()),
22777                ),
22778            })
22779        }
22780    }
22781
22782    pub fn null_value_mut(&mut self) -> crate::support::RefMut<'_, ColorBGRA> {
22783        // SAFETY: as above; `&mut self` guarantees exclusivity.
22784        unsafe {
22785            crate::support::RefMut::new(ColorBGRA {
22786                raw: core::ptr::NonNull::new_unchecked(
22787                    ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_nullValue(self.raw.as_ptr()),
22788                ),
22789            })
22790        }
22791    }
22792
22793    /// Typically -1
22794    pub fn unused(&self) -> i32 {
22795        // SAFETY: plain scalar read through a live handle.
22796        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_get_unused(self.raw.as_ptr()) }
22797    }
22798
22799    pub fn set_unused(&mut self, value: i32) {
22800        // SAFETY: plain scalar write through a live handle.
22801        unsafe { ffi::whiteout_m3_M3AnimRefM3ColorBGRA_set_unused(self.raw.as_ptr(), value) }
22802    }
22803}
22804
22805impl Default for AnimRefM3ColorBGRA {
22806    fn default() -> Self {
22807        Self::new()
22808    }
22809}
22810
22811/// Animatable reference holding a default value and animation link
22812///
22813/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
22814///
22815/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
22816pub struct AnimRefU16 {
22817    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefU16>,
22818}
22819
22820impl Drop for AnimRefU16 {
22821    fn drop(&mut self) {
22822        // SAFETY: `raw` came from a native constructor and Drop runs once.
22823        unsafe { ffi::whiteout_m3_M3AnimRefU16_delete(self.raw.as_ptr()) }
22824    }
22825}
22826
22827impl AnimRefU16 {
22828    /// # Safety
22829    /// `raw` must be a live handle this value takes ownership of.
22830    #[allow(dead_code)] // used by whichever methods return this type
22831    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefU16) -> Option<Self> {
22832        core::ptr::NonNull::new(raw).map(|raw| AnimRefU16 { raw })
22833    }
22834}
22835
22836// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22837// is deliberately NOT implemented — the C++ types make no documented
22838// guarantee about concurrent use, and claiming one we haven't verified
22839// would be unsound. See `@bind thread_safe` in the plan.
22840unsafe impl Send for AnimRefU16 {}
22841
22842impl core::fmt::Debug for AnimRefU16 {
22843    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22844        f.debug_struct("AnimRefU16").finish_non_exhaustive()
22845    }
22846}
22847
22848impl AnimRefU16 {
22849    /// # Panics
22850    /// Panics if the native allocation fails.
22851    pub fn new() -> Self {
22852        // SAFETY: the native constructor returns a live handle; a null here
22853        // means the library is unusable.
22854        unsafe {
22855            let raw = ffi::whiteout_m3_M3AnimRefU16_new();
22856            Self::from_raw(raw).expect("native AnimRefU16 allocation failed")
22857        }
22858    }
22859
22860    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
22861    pub fn interp_type(&self) -> u16 {
22862        // SAFETY: plain scalar read through a live handle.
22863        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_interpType(self.raw.as_ptr()) }
22864    }
22865
22866    pub fn set_interp_type(&mut self, value: u16) {
22867        // SAFETY: plain scalar write through a live handle.
22868        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_interpType(self.raw.as_ptr(), value) }
22869    }
22870
22871    /// Animation flags
22872    pub fn flags(&self) -> u16 {
22873        // SAFETY: plain scalar read through a live handle.
22874        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_flags(self.raw.as_ptr()) }
22875    }
22876
22877    pub fn set_flags(&mut self, value: u16) {
22878        // SAFETY: plain scalar write through a live handle.
22879        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_flags(self.raw.as_ptr(), value) }
22880    }
22881
22882    /// Animation identifier (links to STC animation data; 0=not animated)
22883    pub fn anim_id(&self) -> u32 {
22884        // SAFETY: plain scalar read through a live handle.
22885        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_animId(self.raw.as_ptr()) }
22886    }
22887
22888    pub fn set_anim_id(&mut self, value: u32) {
22889        // SAFETY: plain scalar write through a live handle.
22890        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_animId(self.raw.as_ptr(), value) }
22891    }
22892
22893    /// Initial/default value (used when not animated)
22894    pub fn init_value(&self) -> u16 {
22895        // SAFETY: plain scalar read through a live handle.
22896        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_initValue(self.raw.as_ptr()) }
22897    }
22898
22899    pub fn set_init_value(&mut self, value: u16) {
22900        // SAFETY: plain scalar write through a live handle.
22901        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_initValue(self.raw.as_ptr(), value) }
22902    }
22903
22904    /// Null/reset value
22905    pub fn null_value(&self) -> u16 {
22906        // SAFETY: plain scalar read through a live handle.
22907        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_nullValue(self.raw.as_ptr()) }
22908    }
22909
22910    pub fn set_null_value(&mut self, value: u16) {
22911        // SAFETY: plain scalar write through a live handle.
22912        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_nullValue(self.raw.as_ptr(), value) }
22913    }
22914
22915    /// Typically -1
22916    pub fn unused(&self) -> i32 {
22917        // SAFETY: plain scalar read through a live handle.
22918        unsafe { ffi::whiteout_m3_M3AnimRefU16_get_unused(self.raw.as_ptr()) }
22919    }
22920
22921    pub fn set_unused(&mut self, value: i32) {
22922        // SAFETY: plain scalar write through a live handle.
22923        unsafe { ffi::whiteout_m3_M3AnimRefU16_set_unused(self.raw.as_ptr(), value) }
22924    }
22925}
22926
22927impl Default for AnimRefU16 {
22928    fn default() -> Self {
22929        Self::new()
22930    }
22931}
22932
22933/// Animatable reference holding a default value and animation link
22934///
22935/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
22936///
22937/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
22938pub struct AnimRefVector2f {
22939    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefVector2f>,
22940}
22941
22942impl Drop for AnimRefVector2f {
22943    fn drop(&mut self) {
22944        // SAFETY: `raw` came from a native constructor and Drop runs once.
22945        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_delete(self.raw.as_ptr()) }
22946    }
22947}
22948
22949impl AnimRefVector2f {
22950    /// # Safety
22951    /// `raw` must be a live handle this value takes ownership of.
22952    #[allow(dead_code)] // used by whichever methods return this type
22953    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefVector2f) -> Option<Self> {
22954        core::ptr::NonNull::new(raw).map(|raw| AnimRefVector2f { raw })
22955    }
22956}
22957
22958// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
22959// is deliberately NOT implemented — the C++ types make no documented
22960// guarantee about concurrent use, and claiming one we haven't verified
22961// would be unsound. See `@bind thread_safe` in the plan.
22962unsafe impl Send for AnimRefVector2f {}
22963
22964impl core::fmt::Debug for AnimRefVector2f {
22965    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22966        f.debug_struct("AnimRefVector2f").finish_non_exhaustive()
22967    }
22968}
22969
22970impl AnimRefVector2f {
22971    /// # Panics
22972    /// Panics if the native allocation fails.
22973    pub fn new() -> Self {
22974        // SAFETY: the native constructor returns a live handle; a null here
22975        // means the library is unusable.
22976        unsafe {
22977            let raw = ffi::whiteout_m3_M3AnimRefVector2f_new();
22978            Self::from_raw(raw).expect("native AnimRefVector2f allocation failed")
22979        }
22980    }
22981
22982    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
22983    pub fn interp_type(&self) -> u16 {
22984        // SAFETY: plain scalar read through a live handle.
22985        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_get_interpType(self.raw.as_ptr()) }
22986    }
22987
22988    pub fn set_interp_type(&mut self, value: u16) {
22989        // SAFETY: plain scalar write through a live handle.
22990        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_set_interpType(self.raw.as_ptr(), value) }
22991    }
22992
22993    /// Animation flags
22994    pub fn flags(&self) -> u16 {
22995        // SAFETY: plain scalar read through a live handle.
22996        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_get_flags(self.raw.as_ptr()) }
22997    }
22998
22999    pub fn set_flags(&mut self, value: u16) {
23000        // SAFETY: plain scalar write through a live handle.
23001        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_set_flags(self.raw.as_ptr(), value) }
23002    }
23003
23004    /// Animation identifier (links to STC animation data; 0=not animated)
23005    pub fn anim_id(&self) -> u32 {
23006        // SAFETY: plain scalar read through a live handle.
23007        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_get_animId(self.raw.as_ptr()) }
23008    }
23009
23010    pub fn set_anim_id(&mut self, value: u32) {
23011        // SAFETY: plain scalar write through a live handle.
23012        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_set_animId(self.raw.as_ptr(), value) }
23013    }
23014
23015    /// Initial/default value (used when not animated)
23016    pub fn init_value(&self) -> crate::math::Vector2f {
23017        // SAFETY: the getter returns an interior pointer to a
23018        // layout-identical POD; we copy it out immediately.
23019        unsafe {
23020            *(ffi::whiteout_m3_M3AnimRefVector2f_get_initValue(self.raw.as_ptr())
23021                as *const crate::math::Vector2f)
23022        }
23023    }
23024
23025    pub fn set_init_value(&mut self, value: crate::math::Vector2f) {
23026        // SAFETY: as above, in the other direction.
23027        unsafe {
23028            ffi::whiteout_m3_M3AnimRefVector2f_set_initValue(
23029                self.raw.as_ptr(),
23030                &value as *const crate::math::Vector2f as *const _,
23031            )
23032        }
23033    }
23034
23035    /// Null/reset value
23036    pub fn null_value(&self) -> crate::math::Vector2f {
23037        // SAFETY: the getter returns an interior pointer to a
23038        // layout-identical POD; we copy it out immediately.
23039        unsafe {
23040            *(ffi::whiteout_m3_M3AnimRefVector2f_get_nullValue(self.raw.as_ptr())
23041                as *const crate::math::Vector2f)
23042        }
23043    }
23044
23045    pub fn set_null_value(&mut self, value: crate::math::Vector2f) {
23046        // SAFETY: as above, in the other direction.
23047        unsafe {
23048            ffi::whiteout_m3_M3AnimRefVector2f_set_nullValue(
23049                self.raw.as_ptr(),
23050                &value as *const crate::math::Vector2f as *const _,
23051            )
23052        }
23053    }
23054
23055    /// Typically -1
23056    pub fn unused(&self) -> i32 {
23057        // SAFETY: plain scalar read through a live handle.
23058        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_get_unused(self.raw.as_ptr()) }
23059    }
23060
23061    pub fn set_unused(&mut self, value: i32) {
23062        // SAFETY: plain scalar write through a live handle.
23063        unsafe { ffi::whiteout_m3_M3AnimRefVector2f_set_unused(self.raw.as_ptr(), value) }
23064    }
23065}
23066
23067impl Default for AnimRefVector2f {
23068    fn default() -> Self {
23069        Self::new()
23070    }
23071}
23072
23073/// Animatable reference holding a default value and animation link
23074///
23075/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
23076///
23077/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
23078pub struct AnimRefU32 {
23079    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefU32>,
23080}
23081
23082impl Drop for AnimRefU32 {
23083    fn drop(&mut self) {
23084        // SAFETY: `raw` came from a native constructor and Drop runs once.
23085        unsafe { ffi::whiteout_m3_M3AnimRefU32_delete(self.raw.as_ptr()) }
23086    }
23087}
23088
23089impl AnimRefU32 {
23090    /// # Safety
23091    /// `raw` must be a live handle this value takes ownership of.
23092    #[allow(dead_code)] // used by whichever methods return this type
23093    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefU32) -> Option<Self> {
23094        core::ptr::NonNull::new(raw).map(|raw| AnimRefU32 { raw })
23095    }
23096}
23097
23098// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
23099// is deliberately NOT implemented — the C++ types make no documented
23100// guarantee about concurrent use, and claiming one we haven't verified
23101// would be unsound. See `@bind thread_safe` in the plan.
23102unsafe impl Send for AnimRefU32 {}
23103
23104impl core::fmt::Debug for AnimRefU32 {
23105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23106        f.debug_struct("AnimRefU32").finish_non_exhaustive()
23107    }
23108}
23109
23110impl AnimRefU32 {
23111    /// # Panics
23112    /// Panics if the native allocation fails.
23113    pub fn new() -> Self {
23114        // SAFETY: the native constructor returns a live handle; a null here
23115        // means the library is unusable.
23116        unsafe {
23117            let raw = ffi::whiteout_m3_M3AnimRefU32_new();
23118            Self::from_raw(raw).expect("native AnimRefU32 allocation failed")
23119        }
23120    }
23121
23122    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
23123    pub fn interp_type(&self) -> u16 {
23124        // SAFETY: plain scalar read through a live handle.
23125        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_interpType(self.raw.as_ptr()) }
23126    }
23127
23128    pub fn set_interp_type(&mut self, value: u16) {
23129        // SAFETY: plain scalar write through a live handle.
23130        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_interpType(self.raw.as_ptr(), value) }
23131    }
23132
23133    /// Animation flags
23134    pub fn flags(&self) -> u16 {
23135        // SAFETY: plain scalar read through a live handle.
23136        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_flags(self.raw.as_ptr()) }
23137    }
23138
23139    pub fn set_flags(&mut self, value: u16) {
23140        // SAFETY: plain scalar write through a live handle.
23141        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_flags(self.raw.as_ptr(), value) }
23142    }
23143
23144    /// Animation identifier (links to STC animation data; 0=not animated)
23145    pub fn anim_id(&self) -> u32 {
23146        // SAFETY: plain scalar read through a live handle.
23147        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_animId(self.raw.as_ptr()) }
23148    }
23149
23150    pub fn set_anim_id(&mut self, value: u32) {
23151        // SAFETY: plain scalar write through a live handle.
23152        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_animId(self.raw.as_ptr(), value) }
23153    }
23154
23155    /// Initial/default value (used when not animated)
23156    pub fn init_value(&self) -> u32 {
23157        // SAFETY: plain scalar read through a live handle.
23158        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_initValue(self.raw.as_ptr()) }
23159    }
23160
23161    pub fn set_init_value(&mut self, value: u32) {
23162        // SAFETY: plain scalar write through a live handle.
23163        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_initValue(self.raw.as_ptr(), value) }
23164    }
23165
23166    /// Null/reset value
23167    pub fn null_value(&self) -> u32 {
23168        // SAFETY: plain scalar read through a live handle.
23169        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_nullValue(self.raw.as_ptr()) }
23170    }
23171
23172    pub fn set_null_value(&mut self, value: u32) {
23173        // SAFETY: plain scalar write through a live handle.
23174        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_nullValue(self.raw.as_ptr(), value) }
23175    }
23176
23177    /// Typically -1
23178    pub fn unused(&self) -> i32 {
23179        // SAFETY: plain scalar read through a live handle.
23180        unsafe { ffi::whiteout_m3_M3AnimRefU32_get_unused(self.raw.as_ptr()) }
23181    }
23182
23183    pub fn set_unused(&mut self, value: i32) {
23184        // SAFETY: plain scalar write through a live handle.
23185        unsafe { ffi::whiteout_m3_M3AnimRefU32_set_unused(self.raw.as_ptr(), value) }
23186    }
23187}
23188
23189impl Default for AnimRefU32 {
23190    fn default() -> Self {
23191        Self::new()
23192    }
23193}
23194
23195/// Animatable reference holding a default value and animation link
23196///
23197/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
23198///
23199/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
23200pub struct AnimRefQuaternion {
23201    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefQuaternion>,
23202}
23203
23204impl Drop for AnimRefQuaternion {
23205    fn drop(&mut self) {
23206        // SAFETY: `raw` came from a native constructor and Drop runs once.
23207        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_delete(self.raw.as_ptr()) }
23208    }
23209}
23210
23211impl AnimRefQuaternion {
23212    /// # Safety
23213    /// `raw` must be a live handle this value takes ownership of.
23214    #[allow(dead_code)] // used by whichever methods return this type
23215    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefQuaternion) -> Option<Self> {
23216        core::ptr::NonNull::new(raw).map(|raw| AnimRefQuaternion { raw })
23217    }
23218}
23219
23220// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
23221// is deliberately NOT implemented — the C++ types make no documented
23222// guarantee about concurrent use, and claiming one we haven't verified
23223// would be unsound. See `@bind thread_safe` in the plan.
23224unsafe impl Send for AnimRefQuaternion {}
23225
23226impl core::fmt::Debug for AnimRefQuaternion {
23227    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23228        f.debug_struct("AnimRefQuaternion").finish_non_exhaustive()
23229    }
23230}
23231
23232impl AnimRefQuaternion {
23233    /// # Panics
23234    /// Panics if the native allocation fails.
23235    pub fn new() -> Self {
23236        // SAFETY: the native constructor returns a live handle; a null here
23237        // means the library is unusable.
23238        unsafe {
23239            let raw = ffi::whiteout_m3_M3AnimRefQuaternion_new();
23240            Self::from_raw(raw).expect("native AnimRefQuaternion allocation failed")
23241        }
23242    }
23243
23244    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
23245    pub fn interp_type(&self) -> u16 {
23246        // SAFETY: plain scalar read through a live handle.
23247        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_get_interpType(self.raw.as_ptr()) }
23248    }
23249
23250    pub fn set_interp_type(&mut self, value: u16) {
23251        // SAFETY: plain scalar write through a live handle.
23252        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_set_interpType(self.raw.as_ptr(), value) }
23253    }
23254
23255    /// Animation flags
23256    pub fn flags(&self) -> u16 {
23257        // SAFETY: plain scalar read through a live handle.
23258        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_get_flags(self.raw.as_ptr()) }
23259    }
23260
23261    pub fn set_flags(&mut self, value: u16) {
23262        // SAFETY: plain scalar write through a live handle.
23263        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_set_flags(self.raw.as_ptr(), value) }
23264    }
23265
23266    /// Animation identifier (links to STC animation data; 0=not animated)
23267    pub fn anim_id(&self) -> u32 {
23268        // SAFETY: plain scalar read through a live handle.
23269        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_get_animId(self.raw.as_ptr()) }
23270    }
23271
23272    pub fn set_anim_id(&mut self, value: u32) {
23273        // SAFETY: plain scalar write through a live handle.
23274        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_set_animId(self.raw.as_ptr(), value) }
23275    }
23276
23277    /// Initial/default value (used when not animated)
23278    pub fn init_value(&self) -> crate::math::Quaternion {
23279        // SAFETY: the getter returns an interior pointer to a
23280        // layout-identical POD; we copy it out immediately.
23281        unsafe {
23282            *(ffi::whiteout_m3_M3AnimRefQuaternion_get_initValue(self.raw.as_ptr())
23283                as *const crate::math::Quaternion)
23284        }
23285    }
23286
23287    pub fn set_init_value(&mut self, value: crate::math::Quaternion) {
23288        // SAFETY: as above, in the other direction.
23289        unsafe {
23290            ffi::whiteout_m3_M3AnimRefQuaternion_set_initValue(
23291                self.raw.as_ptr(),
23292                &value as *const crate::math::Quaternion as *const _,
23293            )
23294        }
23295    }
23296
23297    /// Null/reset value
23298    pub fn null_value(&self) -> crate::math::Quaternion {
23299        // SAFETY: the getter returns an interior pointer to a
23300        // layout-identical POD; we copy it out immediately.
23301        unsafe {
23302            *(ffi::whiteout_m3_M3AnimRefQuaternion_get_nullValue(self.raw.as_ptr())
23303                as *const crate::math::Quaternion)
23304        }
23305    }
23306
23307    pub fn set_null_value(&mut self, value: crate::math::Quaternion) {
23308        // SAFETY: as above, in the other direction.
23309        unsafe {
23310            ffi::whiteout_m3_M3AnimRefQuaternion_set_nullValue(
23311                self.raw.as_ptr(),
23312                &value as *const crate::math::Quaternion as *const _,
23313            )
23314        }
23315    }
23316
23317    /// Typically -1
23318    pub fn unused(&self) -> i32 {
23319        // SAFETY: plain scalar read through a live handle.
23320        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_get_unused(self.raw.as_ptr()) }
23321    }
23322
23323    pub fn set_unused(&mut self, value: i32) {
23324        // SAFETY: plain scalar write through a live handle.
23325        unsafe { ffi::whiteout_m3_M3AnimRefQuaternion_set_unused(self.raw.as_ptr(), value) }
23326    }
23327}
23328
23329impl Default for AnimRefQuaternion {
23330    fn default() -> Self {
23331        Self::new()
23332    }
23333}
23334
23335/// Animatable reference holding a default value and animation link
23336///
23337/// Holds both a constant default value and a link to keyframed animation data. If animId == 0, the property is not animated — use initValue as a constant. Otherwise, resolve through STC_.animIds to locate keyframe data. Total size depends on sizeof(T): 12 + 2*sizeof(T) + 4 bytes.
23338///
23339/// @tparam T The value type (f32, Vector3f, Quaternion, ColorBGRA, Extent, etc.)
23340pub struct AnimRefM3Extent {
23341    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M3AnimRefM3Extent>,
23342}
23343
23344impl Drop for AnimRefM3Extent {
23345    fn drop(&mut self) {
23346        // SAFETY: `raw` came from a native constructor and Drop runs once.
23347        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_delete(self.raw.as_ptr()) }
23348    }
23349}
23350
23351impl AnimRefM3Extent {
23352    /// # Safety
23353    /// `raw` must be a live handle this value takes ownership of.
23354    #[allow(dead_code)] // used by whichever methods return this type
23355    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M3AnimRefM3Extent) -> Option<Self> {
23356        core::ptr::NonNull::new(raw).map(|raw| AnimRefM3Extent { raw })
23357    }
23358}
23359
23360// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
23361// is deliberately NOT implemented — the C++ types make no documented
23362// guarantee about concurrent use, and claiming one we haven't verified
23363// would be unsound. See `@bind thread_safe` in the plan.
23364unsafe impl Send for AnimRefM3Extent {}
23365
23366impl core::fmt::Debug for AnimRefM3Extent {
23367    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23368        f.debug_struct("AnimRefM3Extent").finish_non_exhaustive()
23369    }
23370}
23371
23372impl AnimRefM3Extent {
23373    /// # Panics
23374    /// Panics if the native allocation fails.
23375    pub fn new() -> Self {
23376        // SAFETY: the native constructor returns a live handle; a null here
23377        // means the library is unusable.
23378        unsafe {
23379            let raw = ffi::whiteout_m3_M3AnimRefM3Extent_new();
23380            Self::from_raw(raw).expect("native AnimRefM3Extent allocation failed")
23381        }
23382    }
23383
23384    /// Interpolation: 0=none/step, 1=linear, 2=hermite, 3=bezier
23385    pub fn interp_type(&self) -> u16 {
23386        // SAFETY: plain scalar read through a live handle.
23387        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_get_interpType(self.raw.as_ptr()) }
23388    }
23389
23390    pub fn set_interp_type(&mut self, value: u16) {
23391        // SAFETY: plain scalar write through a live handle.
23392        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_set_interpType(self.raw.as_ptr(), value) }
23393    }
23394
23395    /// Animation flags
23396    pub fn flags(&self) -> u16 {
23397        // SAFETY: plain scalar read through a live handle.
23398        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_get_flags(self.raw.as_ptr()) }
23399    }
23400
23401    pub fn set_flags(&mut self, value: u16) {
23402        // SAFETY: plain scalar write through a live handle.
23403        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_set_flags(self.raw.as_ptr(), value) }
23404    }
23405
23406    /// Animation identifier (links to STC animation data; 0=not animated)
23407    pub fn anim_id(&self) -> u32 {
23408        // SAFETY: plain scalar read through a live handle.
23409        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_get_animId(self.raw.as_ptr()) }
23410    }
23411
23412    pub fn set_anim_id(&mut self, value: u32) {
23413        // SAFETY: plain scalar write through a live handle.
23414        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_set_animId(self.raw.as_ptr(), value) }
23415    }
23416
23417    /// Initial/default value (used when not animated)
23418    /// Borrows the field in place — no copy, no allocation.
23419    pub fn init_value(&self) -> crate::support::Ref<'_, Extent> {
23420        // SAFETY: an interior pointer into `self`, valid for this
23421        // borrow and never freed by the `Ref`.
23422        unsafe {
23423            crate::support::Ref::new(Extent {
23424                raw: core::ptr::NonNull::new_unchecked(
23425                    ffi::whiteout_m3_M3AnimRefM3Extent_get_initValue(self.raw.as_ptr()),
23426                ),
23427            })
23428        }
23429    }
23430
23431    pub fn init_value_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
23432        // SAFETY: as above; `&mut self` guarantees exclusivity.
23433        unsafe {
23434            crate::support::RefMut::new(Extent {
23435                raw: core::ptr::NonNull::new_unchecked(
23436                    ffi::whiteout_m3_M3AnimRefM3Extent_get_initValue(self.raw.as_ptr()),
23437                ),
23438            })
23439        }
23440    }
23441
23442    /// Null/reset value
23443    /// Borrows the field in place — no copy, no allocation.
23444    pub fn null_value(&self) -> crate::support::Ref<'_, Extent> {
23445        // SAFETY: an interior pointer into `self`, valid for this
23446        // borrow and never freed by the `Ref`.
23447        unsafe {
23448            crate::support::Ref::new(Extent {
23449                raw: core::ptr::NonNull::new_unchecked(
23450                    ffi::whiteout_m3_M3AnimRefM3Extent_get_nullValue(self.raw.as_ptr()),
23451                ),
23452            })
23453        }
23454    }
23455
23456    pub fn null_value_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
23457        // SAFETY: as above; `&mut self` guarantees exclusivity.
23458        unsafe {
23459            crate::support::RefMut::new(Extent {
23460                raw: core::ptr::NonNull::new_unchecked(
23461                    ffi::whiteout_m3_M3AnimRefM3Extent_get_nullValue(self.raw.as_ptr()),
23462                ),
23463            })
23464        }
23465    }
23466
23467    /// Typically -1
23468    pub fn unused(&self) -> i32 {
23469        // SAFETY: plain scalar read through a live handle.
23470        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_get_unused(self.raw.as_ptr()) }
23471    }
23472
23473    pub fn set_unused(&mut self, value: i32) {
23474        // SAFETY: plain scalar write through a live handle.
23475        unsafe { ffi::whiteout_m3_M3AnimRefM3Extent_set_unused(self.raw.as_ptr(), value) }
23476    }
23477}
23478
23479impl Default for AnimRefM3Extent {
23480    fn default() -> Self {
23481        Self::new()
23482    }
23483}
23484
23485#[doc(hidden)]
23486pub mod ffi {
23487    #![allow(missing_debug_implementations)]
23488
23489    #[allow(unused_imports)]
23490    use crate::support::{RawBytes, RawCString};
23491
23492    #[repr(C)]
23493    pub struct whiteout_M3ColorBGRA {
23494        _private: [u8; 0],
23495    }
23496    #[repr(C)]
23497    pub struct whiteout_M3ColorBGR {
23498        _private: [u8; 0],
23499    }
23500    #[repr(C)]
23501    pub struct whiteout_M3Extent {
23502        _private: [u8; 0],
23503    }
23504    #[repr(C)]
23505    pub struct whiteout_M3Event {
23506        _private: [u8; 0],
23507    }
23508    #[repr(C)]
23509    pub struct whiteout_M3Sequence {
23510        _private: [u8; 0],
23511    }
23512    #[repr(C)]
23513    pub struct whiteout_M3SubTrackContainer {
23514        _private: [u8; 0],
23515    }
23516    #[repr(C)]
23517    pub struct whiteout_M3AnimationGroup {
23518        _private: [u8; 0],
23519    }
23520    #[repr(C)]
23521    pub struct whiteout_M3AnimationState {
23522        _private: [u8; 0],
23523    }
23524    #[repr(C)]
23525    pub struct whiteout_M3BoneAnimationSet {
23526        _private: [u8; 0],
23527    }
23528    #[repr(C)]
23529    pub struct whiteout_M3ParticleEmitter {
23530        _private: [u8; 0],
23531    }
23532    #[repr(C)]
23533    pub struct whiteout_M3ParticleEmitterCopy {
23534        _private: [u8; 0],
23535    }
23536    #[repr(C)]
23537    pub struct whiteout_M3SplineRibbon {
23538        _private: [u8; 0],
23539    }
23540    #[repr(C)]
23541    pub struct whiteout_M3RibbonEmitter {
23542        _private: [u8; 0],
23543    }
23544    #[repr(C)]
23545    pub struct whiteout_M3Projector {
23546        _private: [u8; 0],
23547    }
23548    #[repr(C)]
23549    pub struct whiteout_M3MaterialMap {
23550        _private: [u8; 0],
23551    }
23552    #[repr(C)]
23553    pub struct whiteout_M3TextureLayer {
23554        _private: [u8; 0],
23555    }
23556    #[repr(C)]
23557    pub struct whiteout_M3StandardMaterial {
23558        _private: [u8; 0],
23559    }
23560    #[repr(C)]
23561    pub struct whiteout_M3DisplacementMaterial {
23562        _private: [u8; 0],
23563    }
23564    #[repr(C)]
23565    pub struct whiteout_M3CompositeSection {
23566        _private: [u8; 0],
23567    }
23568    #[repr(C)]
23569    pub struct whiteout_M3CompositeMaterial {
23570        _private: [u8; 0],
23571    }
23572    #[repr(C)]
23573    pub struct whiteout_M3TerrainMaterial {
23574        _private: [u8; 0],
23575    }
23576    #[repr(C)]
23577    pub struct whiteout_M3VolumeMaterial {
23578        _private: [u8; 0],
23579    }
23580    #[repr(C)]
23581    pub struct whiteout_M3HairMaterial {
23582        _private: [u8; 0],
23583    }
23584    #[repr(C)]
23585    pub struct whiteout_M3VolumeNoiseMaterial {
23586        _private: [u8; 0],
23587    }
23588    #[repr(C)]
23589    pub struct whiteout_M3CreepMaterial {
23590        _private: [u8; 0],
23591    }
23592    #[repr(C)]
23593    pub struct whiteout_M3STBMaterial {
23594        _private: [u8; 0],
23595    }
23596    #[repr(C)]
23597    pub struct whiteout_M3ReflectionMaterial {
23598        _private: [u8; 0],
23599    }
23600    #[repr(C)]
23601    pub struct whiteout_M3SubFlare {
23602        _private: [u8; 0],
23603    }
23604    #[repr(C)]
23605    pub struct whiteout_M3LensFlare {
23606        _private: [u8; 0],
23607    }
23608    #[repr(C)]
23609    pub struct whiteout_M3DataDrivenProperty {
23610        _private: [u8; 0],
23611    }
23612    #[repr(C)]
23613    pub struct whiteout_M3DataDrivenGroup {
23614        _private: [u8; 0],
23615    }
23616    #[repr(C)]
23617    pub struct whiteout_M3DataDrivenProperties {
23618        _private: [u8; 0],
23619    }
23620    #[repr(C)]
23621    pub struct whiteout_M3StandardMaterialConversion {
23622        _private: [u8; 0],
23623    }
23624    #[repr(C)]
23625    pub struct whiteout_M3DataDrivenMaterial {
23626        _private: [u8; 0],
23627    }
23628    #[repr(C)]
23629    pub struct whiteout_M3Bone {
23630        _private: [u8; 0],
23631    }
23632    #[repr(C)]
23633    pub struct whiteout_M3Region {
23634        _private: [u8; 0],
23635    }
23636    #[repr(C)]
23637    pub struct whiteout_M3Batch {
23638        _private: [u8; 0],
23639    }
23640    #[repr(C)]
23641    pub struct whiteout_M3MeshSection {
23642        _private: [u8; 0],
23643    }
23644    #[repr(C)]
23645    pub struct whiteout_M3MeshDivision {
23646        _private: [u8; 0],
23647    }
23648    #[repr(C)]
23649    pub struct whiteout_M3InitialReference {
23650        _private: [u8; 0],
23651    }
23652    #[repr(C)]
23653    pub struct whiteout_M3AttachmentPoint {
23654        _private: [u8; 0],
23655    }
23656    #[repr(C)]
23657    pub struct whiteout_M3HitTestShape {
23658        _private: [u8; 0],
23659    }
23660    #[repr(C)]
23661    pub struct whiteout_M3AttachmentVolume {
23662        _private: [u8; 0],
23663    }
23664    #[repr(C)]
23665    pub struct whiteout_M3TriggerData {
23666        _private: [u8; 0],
23667    }
23668    #[repr(C)]
23669    pub struct whiteout_M3TurretBehavior {
23670        _private: [u8; 0],
23671    }
23672    #[repr(C)]
23673    pub struct whiteout_M3BillboardBehavior {
23674        _private: [u8; 0],
23675    }
23676    #[repr(C)]
23677    pub struct whiteout_M3IKJoint {
23678        _private: [u8; 0],
23679    }
23680    #[repr(C)]
23681    pub struct whiteout_M3IKTwoJoint {
23682        _private: [u8; 0],
23683    }
23684    #[repr(C)]
23685    pub struct whiteout_M3IKCCD {
23686        _private: [u8; 0],
23687    }
23688    #[repr(C)]
23689    pub struct whiteout_M3OneBoneSolver {
23690        _private: [u8; 0],
23691    }
23692    #[repr(C)]
23693    pub struct whiteout_M3ShadowBox {
23694        _private: [u8; 0],
23695    }
23696    #[repr(C)]
23697    pub struct whiteout_M3ViewVolume {
23698        _private: [u8; 0],
23699    }
23700    #[repr(C)]
23701    pub struct whiteout_M3TrailingModel {
23702        _private: [u8; 0],
23703    }
23704    #[repr(C)]
23705    pub struct whiteout_M3Force {
23706        _private: [u8; 0],
23707    }
23708    #[repr(C)]
23709    pub struct whiteout_M3Warp {
23710        _private: [u8; 0],
23711    }
23712    #[repr(C)]
23713    pub struct whiteout_M3ConvexHullHalfEdge {
23714        _private: [u8; 0],
23715    }
23716    #[repr(C)]
23717    pub struct whiteout_M3PhysicsMeshBvhNode {
23718        _private: [u8; 0],
23719    }
23720    #[repr(C)]
23721    pub struct whiteout_M3PhysicsMeshTriangle {
23722        _private: [u8; 0],
23723    }
23724    #[repr(C)]
23725    pub struct whiteout_M3PhysicsMeshEdge {
23726        _private: [u8; 0],
23727    }
23728    #[repr(C)]
23729    pub struct whiteout_M3PhysicsShape {
23730        _private: [u8; 0],
23731    }
23732    #[repr(C)]
23733    pub struct whiteout_M3RigidBody {
23734        _private: [u8; 0],
23735    }
23736    #[repr(C)]
23737    pub struct whiteout_M3PhysicsJoint {
23738        _private: [u8; 0],
23739    }
23740    #[repr(C)]
23741    pub struct whiteout_M3PhysicsConstraint {
23742        _private: [u8; 0],
23743    }
23744    #[repr(C)]
23745    pub struct whiteout_M3ClothCollider {
23746        _private: [u8; 0],
23747    }
23748    #[repr(C)]
23749    pub struct whiteout_M3ClothProxy {
23750        _private: [u8; 0],
23751    }
23752    #[repr(C)]
23753    pub struct whiteout_M3ClothPhysics {
23754        _private: [u8; 0],
23755    }
23756    #[repr(C)]
23757    pub struct whiteout_M3Light {
23758        _private: [u8; 0],
23759    }
23760    #[repr(C)]
23761    pub struct whiteout_M3Camera {
23762        _private: [u8; 0],
23763    }
23764    #[repr(C)]
23765    pub struct whiteout_M3Model {
23766        _private: [u8; 0],
23767    }
23768    #[repr(C)]
23769    pub struct whiteout_M3Parser {
23770        _private: [u8; 0],
23771    }
23772    #[repr(C)]
23773    pub struct whiteout_M3Writer {
23774        _private: [u8; 0],
23775    }
23776    #[repr(C)]
23777    pub struct whiteout_M3AnimRefF32 {
23778        _private: [u8; 0],
23779    }
23780    #[repr(C)]
23781    pub struct whiteout_M3AnimRefVector3f {
23782        _private: [u8; 0],
23783    }
23784    #[repr(C)]
23785    pub struct whiteout_M3AnimRefM3ColorBGRA {
23786        _private: [u8; 0],
23787    }
23788    #[repr(C)]
23789    pub struct whiteout_M3AnimRefU16 {
23790        _private: [u8; 0],
23791    }
23792    #[repr(C)]
23793    pub struct whiteout_M3AnimRefVector2f {
23794        _private: [u8; 0],
23795    }
23796    #[repr(C)]
23797    pub struct whiteout_M3AnimRefU32 {
23798        _private: [u8; 0],
23799    }
23800    #[repr(C)]
23801    pub struct whiteout_M3AnimRefQuaternion {
23802        _private: [u8; 0],
23803    }
23804    #[repr(C)]
23805    pub struct whiteout_M3AnimRefM3Extent {
23806        _private: [u8; 0],
23807    }
23808
23809    extern "C" {
23810        // ColorBGRA
23811        pub fn whiteout_m3_M3ColorBGRA_new() -> *mut whiteout_M3ColorBGRA;
23812        pub fn whiteout_m3_M3ColorBGRA_delete(self_: *mut whiteout_M3ColorBGRA);
23813        pub fn whiteout_m3_M3ColorBGRA_get_b(self_: *mut whiteout_M3ColorBGRA) -> u8;
23814        pub fn whiteout_m3_M3ColorBGRA_set_b(self_: *mut whiteout_M3ColorBGRA, value: u8);
23815        pub fn whiteout_m3_M3ColorBGRA_get_g(self_: *mut whiteout_M3ColorBGRA) -> u8;
23816        pub fn whiteout_m3_M3ColorBGRA_set_g(self_: *mut whiteout_M3ColorBGRA, value: u8);
23817        pub fn whiteout_m3_M3ColorBGRA_get_r(self_: *mut whiteout_M3ColorBGRA) -> u8;
23818        pub fn whiteout_m3_M3ColorBGRA_set_r(self_: *mut whiteout_M3ColorBGRA, value: u8);
23819        pub fn whiteout_m3_M3ColorBGRA_get_a(self_: *mut whiteout_M3ColorBGRA) -> u8;
23820        pub fn whiteout_m3_M3ColorBGRA_set_a(self_: *mut whiteout_M3ColorBGRA, value: u8);
23821        // ColorBGR
23822        pub fn whiteout_m3_M3ColorBGR_new() -> *mut whiteout_M3ColorBGR;
23823        pub fn whiteout_m3_M3ColorBGR_delete(self_: *mut whiteout_M3ColorBGR);
23824        pub fn whiteout_m3_M3ColorBGR_get_b(self_: *mut whiteout_M3ColorBGR) -> u8;
23825        pub fn whiteout_m3_M3ColorBGR_set_b(self_: *mut whiteout_M3ColorBGR, value: u8);
23826        pub fn whiteout_m3_M3ColorBGR_get_g(self_: *mut whiteout_M3ColorBGR) -> u8;
23827        pub fn whiteout_m3_M3ColorBGR_set_g(self_: *mut whiteout_M3ColorBGR, value: u8);
23828        pub fn whiteout_m3_M3ColorBGR_get_r(self_: *mut whiteout_M3ColorBGR) -> u8;
23829        pub fn whiteout_m3_M3ColorBGR_set_r(self_: *mut whiteout_M3ColorBGR, value: u8);
23830        // Extent
23831        pub fn whiteout_m3_M3Extent_new() -> *mut whiteout_M3Extent;
23832        pub fn whiteout_m3_M3Extent_delete(self_: *mut whiteout_M3Extent);
23833        pub fn whiteout_m3_M3Extent_get_min(
23834            self_: *mut whiteout_M3Extent,
23835        ) -> *mut core::ffi::c_void;
23836        pub fn whiteout_m3_M3Extent_set_min(
23837            self_: *mut whiteout_M3Extent,
23838            value: *const core::ffi::c_void,
23839        );
23840        pub fn whiteout_m3_M3Extent_get_max(
23841            self_: *mut whiteout_M3Extent,
23842        ) -> *mut core::ffi::c_void;
23843        pub fn whiteout_m3_M3Extent_set_max(
23844            self_: *mut whiteout_M3Extent,
23845            value: *const core::ffi::c_void,
23846        );
23847        pub fn whiteout_m3_M3Extent_get_radius(self_: *mut whiteout_M3Extent) -> f32;
23848        pub fn whiteout_m3_M3Extent_set_radius(self_: *mut whiteout_M3Extent, value: f32);
23849        // Event
23850        pub fn whiteout_m3_M3Event_new() -> *mut whiteout_M3Event;
23851        pub fn whiteout_m3_M3Event_delete(self_: *mut whiteout_M3Event);
23852        pub fn whiteout_m3_M3Event_get_name(self_: *mut whiteout_M3Event) -> RawCString;
23853        pub fn whiteout_m3_M3Event_set_name(
23854            self_: *mut whiteout_M3Event,
23855            value: *const core::ffi::c_char,
23856        );
23857        pub fn whiteout_m3_M3Event_get_unknown(self_: *mut whiteout_M3Event) -> u32;
23858        pub fn whiteout_m3_M3Event_set_unknown(self_: *mut whiteout_M3Event, value: u32);
23859        pub fn whiteout_m3_M3Event_get_boneIndex(self_: *mut whiteout_M3Event) -> u16;
23860        pub fn whiteout_m3_M3Event_set_boneIndex(self_: *mut whiteout_M3Event, value: u16);
23861        pub fn whiteout_m3_M3Event_get_padding(self_: *mut whiteout_M3Event) -> u16;
23862        pub fn whiteout_m3_M3Event_set_padding(self_: *mut whiteout_M3Event, value: u16);
23863        pub fn whiteout_m3_M3Event_get_eventType(self_: *mut whiteout_M3Event) -> u32;
23864        pub fn whiteout_m3_M3Event_set_eventType(self_: *mut whiteout_M3Event, value: u32);
23865        pub fn whiteout_m3_M3Event_get_optionString(self_: *mut whiteout_M3Event) -> RawCString;
23866        pub fn whiteout_m3_M3Event_set_optionString(
23867            self_: *mut whiteout_M3Event,
23868            value: *const core::ffi::c_char,
23869        );
23870        pub fn whiteout_m3_M3Event_get_rttChannelIndex(self_: *mut whiteout_M3Event) -> u32;
23871        pub fn whiteout_m3_M3Event_set_rttChannelIndex(self_: *mut whiteout_M3Event, value: u32);
23872        pub fn whiteout_m3_M3Event_get_extraParameter(self_: *mut whiteout_M3Event) -> u32;
23873        pub fn whiteout_m3_M3Event_set_extraParameter(self_: *mut whiteout_M3Event, value: u32);
23874        // Sequence
23875        pub fn whiteout_m3_M3Sequence_new() -> *mut whiteout_M3Sequence;
23876        pub fn whiteout_m3_M3Sequence_delete(self_: *mut whiteout_M3Sequence);
23877        pub fn whiteout_m3_M3Sequence_get_id(self_: *mut whiteout_M3Sequence) -> i32;
23878        pub fn whiteout_m3_M3Sequence_set_id(self_: *mut whiteout_M3Sequence, value: i32);
23879        pub fn whiteout_m3_M3Sequence_get_index(self_: *mut whiteout_M3Sequence) -> i32;
23880        pub fn whiteout_m3_M3Sequence_set_index(self_: *mut whiteout_M3Sequence, value: i32);
23881        pub fn whiteout_m3_M3Sequence_get_name(self_: *mut whiteout_M3Sequence) -> RawCString;
23882        pub fn whiteout_m3_M3Sequence_set_name(
23883            self_: *mut whiteout_M3Sequence,
23884            value: *const core::ffi::c_char,
23885        );
23886        pub fn whiteout_m3_M3Sequence_get_startFrame(self_: *mut whiteout_M3Sequence) -> u32;
23887        pub fn whiteout_m3_M3Sequence_set_startFrame(self_: *mut whiteout_M3Sequence, value: u32);
23888        pub fn whiteout_m3_M3Sequence_get_endFrame(self_: *mut whiteout_M3Sequence) -> u32;
23889        pub fn whiteout_m3_M3Sequence_set_endFrame(self_: *mut whiteout_M3Sequence, value: u32);
23890        pub fn whiteout_m3_M3Sequence_get_moveSpeed(self_: *mut whiteout_M3Sequence) -> f32;
23891        pub fn whiteout_m3_M3Sequence_set_moveSpeed(self_: *mut whiteout_M3Sequence, value: f32);
23892        pub fn whiteout_m3_M3Sequence_get_flags(self_: *mut whiteout_M3Sequence) -> i32;
23893        pub fn whiteout_m3_M3Sequence_set_flags(self_: *mut whiteout_M3Sequence, value: i32);
23894        pub fn whiteout_m3_M3Sequence_get_frequency(self_: *mut whiteout_M3Sequence) -> u32;
23895        pub fn whiteout_m3_M3Sequence_set_frequency(self_: *mut whiteout_M3Sequence, value: u32);
23896        pub fn whiteout_m3_M3Sequence_get_replayStart(self_: *mut whiteout_M3Sequence) -> u32;
23897        pub fn whiteout_m3_M3Sequence_set_replayStart(self_: *mut whiteout_M3Sequence, value: u32);
23898        pub fn whiteout_m3_M3Sequence_get_replayEnd(self_: *mut whiteout_M3Sequence) -> u32;
23899        pub fn whiteout_m3_M3Sequence_set_replayEnd(self_: *mut whiteout_M3Sequence, value: u32);
23900        pub fn whiteout_m3_M3Sequence_get_blendTime(self_: *mut whiteout_M3Sequence) -> u32;
23901        pub fn whiteout_m3_M3Sequence_set_blendTime(self_: *mut whiteout_M3Sequence, value: u32);
23902        pub fn whiteout_m3_M3Sequence_get_bounds(
23903            self_: *mut whiteout_M3Sequence,
23904        ) -> *mut whiteout_M3Extent;
23905        pub fn whiteout_m3_M3Sequence_set_bounds(
23906            self_: *mut whiteout_M3Sequence,
23907            value: *const whiteout_M3Extent,
23908        );
23909        pub fn whiteout_m3_M3Sequence_get_animationSets_count(
23910            self_: *mut whiteout_M3Sequence,
23911        ) -> usize;
23912        pub fn whiteout_m3_M3Sequence_resize_animationSets(
23913            self_: *mut whiteout_M3Sequence,
23914            count: usize,
23915        );
23916        pub fn whiteout_m3_M3Sequence_get_animationSets_data(
23917            self_: *mut whiteout_M3Sequence,
23918        ) -> *const u8;
23919        pub fn whiteout_m3_M3Sequence_assign_animationSets(
23920            self_: *mut whiteout_M3Sequence,
23921            data: *const u8,
23922            count: usize,
23923        );
23924        // SubTrackContainer
23925        pub fn whiteout_m3_M3SubTrackContainer_new() -> *mut whiteout_M3SubTrackContainer;
23926        pub fn whiteout_m3_M3SubTrackContainer_delete(self_: *mut whiteout_M3SubTrackContainer);
23927        pub fn whiteout_m3_M3SubTrackContainer_get_name(
23928            self_: *mut whiteout_M3SubTrackContainer,
23929        ) -> RawCString;
23930        pub fn whiteout_m3_M3SubTrackContainer_set_name(
23931            self_: *mut whiteout_M3SubTrackContainer,
23932            value: *const core::ffi::c_char,
23933        );
23934        pub fn whiteout_m3_M3SubTrackContainer_get_runsConcurrent(
23935            self_: *mut whiteout_M3SubTrackContainer,
23936        ) -> u16;
23937        pub fn whiteout_m3_M3SubTrackContainer_set_runsConcurrent(
23938            self_: *mut whiteout_M3SubTrackContainer,
23939            value: u16,
23940        );
23941        pub fn whiteout_m3_M3SubTrackContainer_get_animPriority(
23942            self_: *mut whiteout_M3SubTrackContainer,
23943        ) -> u16;
23944        pub fn whiteout_m3_M3SubTrackContainer_set_animPriority(
23945            self_: *mut whiteout_M3SubTrackContainer,
23946            value: u16,
23947        );
23948        pub fn whiteout_m3_M3SubTrackContainer_get_animationStateIndex(
23949            self_: *mut whiteout_M3SubTrackContainer,
23950        ) -> u16;
23951        pub fn whiteout_m3_M3SubTrackContainer_set_animationStateIndex(
23952            self_: *mut whiteout_M3SubTrackContainer,
23953            value: u16,
23954        );
23955        pub fn whiteout_m3_M3SubTrackContainer_get_animationStateIndexCopy(
23956            self_: *mut whiteout_M3SubTrackContainer,
23957        ) -> u16;
23958        pub fn whiteout_m3_M3SubTrackContainer_set_animationStateIndexCopy(
23959            self_: *mut whiteout_M3SubTrackContainer,
23960            value: u16,
23961        );
23962        pub fn whiteout_m3_M3SubTrackContainer_get_animIds_count(
23963            self_: *mut whiteout_M3SubTrackContainer,
23964        ) -> usize;
23965        pub fn whiteout_m3_M3SubTrackContainer_resize_animIds(
23966            self_: *mut whiteout_M3SubTrackContainer,
23967            count: usize,
23968        );
23969        pub fn whiteout_m3_M3SubTrackContainer_get_animIds_data(
23970            self_: *mut whiteout_M3SubTrackContainer,
23971        ) -> *const u32;
23972        pub fn whiteout_m3_M3SubTrackContainer_assign_animIds(
23973            self_: *mut whiteout_M3SubTrackContainer,
23974            data: *const u32,
23975            count: usize,
23976        );
23977        pub fn whiteout_m3_M3SubTrackContainer_get_animRefs_count(
23978            self_: *mut whiteout_M3SubTrackContainer,
23979        ) -> usize;
23980        pub fn whiteout_m3_M3SubTrackContainer_resize_animRefs(
23981            self_: *mut whiteout_M3SubTrackContainer,
23982            count: usize,
23983        );
23984        pub fn whiteout_m3_M3SubTrackContainer_get_animRefs_data(
23985            self_: *mut whiteout_M3SubTrackContainer,
23986        ) -> *const u32;
23987        pub fn whiteout_m3_M3SubTrackContainer_assign_animRefs(
23988            self_: *mut whiteout_M3SubTrackContainer,
23989            data: *const u32,
23990            count: usize,
23991        );
23992        pub fn whiteout_m3_M3SubTrackContainer_get_unknown(
23993            self_: *mut whiteout_M3SubTrackContainer,
23994        ) -> u32;
23995        pub fn whiteout_m3_M3SubTrackContainer_set_unknown(
23996            self_: *mut whiteout_M3SubTrackContainer,
23997            value: u32,
23998        );
23999        // AnimationGroup
24000        pub fn whiteout_m3_M3AnimationGroup_new() -> *mut whiteout_M3AnimationGroup;
24001        pub fn whiteout_m3_M3AnimationGroup_delete(self_: *mut whiteout_M3AnimationGroup);
24002        pub fn whiteout_m3_M3AnimationGroup_get_name(
24003            self_: *mut whiteout_M3AnimationGroup,
24004        ) -> RawCString;
24005        pub fn whiteout_m3_M3AnimationGroup_set_name(
24006            self_: *mut whiteout_M3AnimationGroup,
24007            value: *const core::ffi::c_char,
24008        );
24009        pub fn whiteout_m3_M3AnimationGroup_get_subtrackIndices_count(
24010            self_: *mut whiteout_M3AnimationGroup,
24011        ) -> usize;
24012        pub fn whiteout_m3_M3AnimationGroup_resize_subtrackIndices(
24013            self_: *mut whiteout_M3AnimationGroup,
24014            count: usize,
24015        );
24016        pub fn whiteout_m3_M3AnimationGroup_get_subtrackIndices_data(
24017            self_: *mut whiteout_M3AnimationGroup,
24018        ) -> *const u32;
24019        pub fn whiteout_m3_M3AnimationGroup_assign_subtrackIndices(
24020            self_: *mut whiteout_M3AnimationGroup,
24021            data: *const u32,
24022            count: usize,
24023        );
24024        // AnimationState
24025        pub fn whiteout_m3_M3AnimationState_new() -> *mut whiteout_M3AnimationState;
24026        pub fn whiteout_m3_M3AnimationState_delete(self_: *mut whiteout_M3AnimationState);
24027        pub fn whiteout_m3_M3AnimationState_get_animIds_count(
24028            self_: *mut whiteout_M3AnimationState,
24029        ) -> usize;
24030        pub fn whiteout_m3_M3AnimationState_resize_animIds(
24031            self_: *mut whiteout_M3AnimationState,
24032            count: usize,
24033        );
24034        pub fn whiteout_m3_M3AnimationState_get_animIds_data(
24035            self_: *mut whiteout_M3AnimationState,
24036        ) -> *const u32;
24037        pub fn whiteout_m3_M3AnimationState_assign_animIds(
24038            self_: *mut whiteout_M3AnimationState,
24039            data: *const u32,
24040            count: usize,
24041        );
24042        pub fn whiteout_m3_M3AnimationState_unknown_size() -> usize;
24043        pub fn whiteout_m3_M3AnimationState_get_unknown_at(
24044            self_: *mut whiteout_M3AnimationState,
24045            index: usize,
24046        ) -> u8;
24047        pub fn whiteout_m3_M3AnimationState_set_unknown_at(
24048            self_: *mut whiteout_M3AnimationState,
24049            index: usize,
24050            value: u8,
24051        );
24052        // BoneAnimationSet
24053        pub fn whiteout_m3_M3BoneAnimationSet_new() -> *mut whiteout_M3BoneAnimationSet;
24054        pub fn whiteout_m3_M3BoneAnimationSet_delete(self_: *mut whiteout_M3BoneAnimationSet);
24055        pub fn whiteout_m3_M3BoneAnimationSet_get_animationSequenceIndex(
24056            self_: *mut whiteout_M3BoneAnimationSet,
24057        ) -> u16;
24058        pub fn whiteout_m3_M3BoneAnimationSet_set_animationSequenceIndex(
24059            self_: *mut whiteout_M3BoneAnimationSet,
24060            value: u16,
24061        );
24062        pub fn whiteout_m3_M3BoneAnimationSet_get_fallbackSequenceIndex(
24063            self_: *mut whiteout_M3BoneAnimationSet,
24064        ) -> u16;
24065        pub fn whiteout_m3_M3BoneAnimationSet_set_fallbackSequenceIndex(
24066            self_: *mut whiteout_M3BoneAnimationSet,
24067            value: u16,
24068        );
24069        pub fn whiteout_m3_M3BoneAnimationSet_get_name(
24070            self_: *mut whiteout_M3BoneAnimationSet,
24071        ) -> RawCString;
24072        pub fn whiteout_m3_M3BoneAnimationSet_set_name(
24073            self_: *mut whiteout_M3BoneAnimationSet,
24074            value: *const core::ffi::c_char,
24075        );
24076        pub fn whiteout_m3_M3BoneAnimationSet_get_splitItems_count(
24077            self_: *mut whiteout_M3BoneAnimationSet,
24078        ) -> usize;
24079        pub fn whiteout_m3_M3BoneAnimationSet_resize_splitItems(
24080            self_: *mut whiteout_M3BoneAnimationSet,
24081            count: usize,
24082        );
24083        pub fn whiteout_m3_M3BoneAnimationSet_get_splitItems_data(
24084            self_: *mut whiteout_M3BoneAnimationSet,
24085        ) -> *const u16;
24086        pub fn whiteout_m3_M3BoneAnimationSet_assign_splitItems(
24087            self_: *mut whiteout_M3BoneAnimationSet,
24088            data: *const u16,
24089            count: usize,
24090        );
24091        // ParticleEmitter
24092        pub fn whiteout_m3_M3ParticleEmitter_new() -> *mut whiteout_M3ParticleEmitter;
24093        pub fn whiteout_m3_M3ParticleEmitter_delete(self_: *mut whiteout_M3ParticleEmitter);
24094        pub fn whiteout_m3_M3ParticleEmitter_get_boneIndex(
24095            self_: *mut whiteout_M3ParticleEmitter,
24096        ) -> u32;
24097        pub fn whiteout_m3_M3ParticleEmitter_set_boneIndex(
24098            self_: *mut whiteout_M3ParticleEmitter,
24099            value: u32,
24100        );
24101        pub fn whiteout_m3_M3ParticleEmitter_get_materialIndex(
24102            self_: *mut whiteout_M3ParticleEmitter,
24103        ) -> u32;
24104        pub fn whiteout_m3_M3ParticleEmitter_set_materialIndex(
24105            self_: *mut whiteout_M3ParticleEmitter,
24106            value: u32,
24107        );
24108        pub fn whiteout_m3_M3ParticleEmitter_get_additionalFlags(
24109            self_: *mut whiteout_M3ParticleEmitter,
24110        ) -> i32;
24111        pub fn whiteout_m3_M3ParticleEmitter_set_additionalFlags(
24112            self_: *mut whiteout_M3ParticleEmitter,
24113            value: i32,
24114        );
24115        pub fn whiteout_m3_M3ParticleEmitter_get_initialSpeed(
24116            self_: *mut whiteout_M3ParticleEmitter,
24117        ) -> *mut whiteout_M3AnimRefF32;
24118        pub fn whiteout_m3_M3ParticleEmitter_set_initialSpeed(
24119            self_: *mut whiteout_M3ParticleEmitter,
24120            value: *const whiteout_M3AnimRefF32,
24121        );
24122        pub fn whiteout_m3_M3ParticleEmitter_get_initialSpeedRandom(
24123            self_: *mut whiteout_M3ParticleEmitter,
24124        ) -> *mut whiteout_M3AnimRefF32;
24125        pub fn whiteout_m3_M3ParticleEmitter_set_initialSpeedRandom(
24126            self_: *mut whiteout_M3ParticleEmitter,
24127            value: *const whiteout_M3AnimRefF32,
24128        );
24129        pub fn whiteout_m3_M3ParticleEmitter_get_initialYaw(
24130            self_: *mut whiteout_M3ParticleEmitter,
24131        ) -> *mut whiteout_M3AnimRefF32;
24132        pub fn whiteout_m3_M3ParticleEmitter_set_initialYaw(
24133            self_: *mut whiteout_M3ParticleEmitter,
24134            value: *const whiteout_M3AnimRefF32,
24135        );
24136        pub fn whiteout_m3_M3ParticleEmitter_get_initialPitch(
24137            self_: *mut whiteout_M3ParticleEmitter,
24138        ) -> *mut whiteout_M3AnimRefF32;
24139        pub fn whiteout_m3_M3ParticleEmitter_set_initialPitch(
24140            self_: *mut whiteout_M3ParticleEmitter,
24141            value: *const whiteout_M3AnimRefF32,
24142        );
24143        pub fn whiteout_m3_M3ParticleEmitter_get_initialHorizontal(
24144            self_: *mut whiteout_M3ParticleEmitter,
24145        ) -> *mut whiteout_M3AnimRefF32;
24146        pub fn whiteout_m3_M3ParticleEmitter_set_initialHorizontal(
24147            self_: *mut whiteout_M3ParticleEmitter,
24148            value: *const whiteout_M3AnimRefF32,
24149        );
24150        pub fn whiteout_m3_M3ParticleEmitter_get_initialVertical(
24151            self_: *mut whiteout_M3ParticleEmitter,
24152        ) -> *mut whiteout_M3AnimRefF32;
24153        pub fn whiteout_m3_M3ParticleEmitter_set_initialVertical(
24154            self_: *mut whiteout_M3ParticleEmitter,
24155            value: *const whiteout_M3AnimRefF32,
24156        );
24157        pub fn whiteout_m3_M3ParticleEmitter_get_lifetime(
24158            self_: *mut whiteout_M3ParticleEmitter,
24159        ) -> *mut whiteout_M3AnimRefF32;
24160        pub fn whiteout_m3_M3ParticleEmitter_set_lifetime(
24161            self_: *mut whiteout_M3ParticleEmitter,
24162            value: *const whiteout_M3AnimRefF32,
24163        );
24164        pub fn whiteout_m3_M3ParticleEmitter_get_lifetimeRandom(
24165            self_: *mut whiteout_M3ParticleEmitter,
24166        ) -> *mut whiteout_M3AnimRefF32;
24167        pub fn whiteout_m3_M3ParticleEmitter_set_lifetimeRandom(
24168            self_: *mut whiteout_M3ParticleEmitter,
24169            value: *const whiteout_M3AnimRefF32,
24170        );
24171        pub fn whiteout_m3_M3ParticleEmitter_get_killRadius(
24172            self_: *mut whiteout_M3ParticleEmitter,
24173        ) -> f32;
24174        pub fn whiteout_m3_M3ParticleEmitter_set_killRadius(
24175            self_: *mut whiteout_M3ParticleEmitter,
24176            value: f32,
24177        );
24178        pub fn whiteout_m3_M3ParticleEmitter_get_gravityX(
24179            self_: *mut whiteout_M3ParticleEmitter,
24180        ) -> u32;
24181        pub fn whiteout_m3_M3ParticleEmitter_set_gravityX(
24182            self_: *mut whiteout_M3ParticleEmitter,
24183            value: u32,
24184        );
24185        pub fn whiteout_m3_M3ParticleEmitter_get_gravityY(
24186            self_: *mut whiteout_M3ParticleEmitter,
24187        ) -> u32;
24188        pub fn whiteout_m3_M3ParticleEmitter_set_gravityY(
24189            self_: *mut whiteout_M3ParticleEmitter,
24190            value: u32,
24191        );
24192        pub fn whiteout_m3_M3ParticleEmitter_get_gravity(
24193            self_: *mut whiteout_M3ParticleEmitter,
24194        ) -> f32;
24195        pub fn whiteout_m3_M3ParticleEmitter_set_gravity(
24196            self_: *mut whiteout_M3ParticleEmitter,
24197            value: f32,
24198        );
24199        pub fn whiteout_m3_M3ParticleEmitter_get_sizeMidTime(
24200            self_: *mut whiteout_M3ParticleEmitter,
24201        ) -> f32;
24202        pub fn whiteout_m3_M3ParticleEmitter_set_sizeMidTime(
24203            self_: *mut whiteout_M3ParticleEmitter,
24204            value: f32,
24205        );
24206        pub fn whiteout_m3_M3ParticleEmitter_get_colorMidTime(
24207            self_: *mut whiteout_M3ParticleEmitter,
24208        ) -> f32;
24209        pub fn whiteout_m3_M3ParticleEmitter_set_colorMidTime(
24210            self_: *mut whiteout_M3ParticleEmitter,
24211            value: f32,
24212        );
24213        pub fn whiteout_m3_M3ParticleEmitter_get_alphaMidTime(
24214            self_: *mut whiteout_M3ParticleEmitter,
24215        ) -> f32;
24216        pub fn whiteout_m3_M3ParticleEmitter_set_alphaMidTime(
24217            self_: *mut whiteout_M3ParticleEmitter,
24218            value: f32,
24219        );
24220        pub fn whiteout_m3_M3ParticleEmitter_get_rotationMidTime(
24221            self_: *mut whiteout_M3ParticleEmitter,
24222        ) -> f32;
24223        pub fn whiteout_m3_M3ParticleEmitter_set_rotationMidTime(
24224            self_: *mut whiteout_M3ParticleEmitter,
24225            value: f32,
24226        );
24227        pub fn whiteout_m3_M3ParticleEmitter_get_sizeMidHoldTime(
24228            self_: *mut whiteout_M3ParticleEmitter,
24229        ) -> f32;
24230        pub fn whiteout_m3_M3ParticleEmitter_set_sizeMidHoldTime(
24231            self_: *mut whiteout_M3ParticleEmitter,
24232            value: f32,
24233        );
24234        pub fn whiteout_m3_M3ParticleEmitter_get_colorMidHoldTime(
24235            self_: *mut whiteout_M3ParticleEmitter,
24236        ) -> f32;
24237        pub fn whiteout_m3_M3ParticleEmitter_set_colorMidHoldTime(
24238            self_: *mut whiteout_M3ParticleEmitter,
24239            value: f32,
24240        );
24241        pub fn whiteout_m3_M3ParticleEmitter_get_alphaMidHoldTime(
24242            self_: *mut whiteout_M3ParticleEmitter,
24243        ) -> f32;
24244        pub fn whiteout_m3_M3ParticleEmitter_set_alphaMidHoldTime(
24245            self_: *mut whiteout_M3ParticleEmitter,
24246            value: f32,
24247        );
24248        pub fn whiteout_m3_M3ParticleEmitter_get_rotationMidHoldTime(
24249            self_: *mut whiteout_M3ParticleEmitter,
24250        ) -> f32;
24251        pub fn whiteout_m3_M3ParticleEmitter_set_rotationMidHoldTime(
24252            self_: *mut whiteout_M3ParticleEmitter,
24253            value: f32,
24254        );
24255        pub fn whiteout_m3_M3ParticleEmitter_get_sizeAnimation(
24256            self_: *mut whiteout_M3ParticleEmitter,
24257        ) -> *mut whiteout_M3AnimRefVector3f;
24258        pub fn whiteout_m3_M3ParticleEmitter_set_sizeAnimation(
24259            self_: *mut whiteout_M3ParticleEmitter,
24260            value: *const whiteout_M3AnimRefVector3f,
24261        );
24262        pub fn whiteout_m3_M3ParticleEmitter_get_rotationAnimation(
24263            self_: *mut whiteout_M3ParticleEmitter,
24264        ) -> *mut whiteout_M3AnimRefVector3f;
24265        pub fn whiteout_m3_M3ParticleEmitter_set_rotationAnimation(
24266            self_: *mut whiteout_M3ParticleEmitter,
24267            value: *const whiteout_M3AnimRefVector3f,
24268        );
24269        pub fn whiteout_m3_M3ParticleEmitter_get_colorStart(
24270            self_: *mut whiteout_M3ParticleEmitter,
24271        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24272        pub fn whiteout_m3_M3ParticleEmitter_set_colorStart(
24273            self_: *mut whiteout_M3ParticleEmitter,
24274            value: *const whiteout_M3AnimRefM3ColorBGRA,
24275        );
24276        pub fn whiteout_m3_M3ParticleEmitter_get_colorMid(
24277            self_: *mut whiteout_M3ParticleEmitter,
24278        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24279        pub fn whiteout_m3_M3ParticleEmitter_set_colorMid(
24280            self_: *mut whiteout_M3ParticleEmitter,
24281            value: *const whiteout_M3AnimRefM3ColorBGRA,
24282        );
24283        pub fn whiteout_m3_M3ParticleEmitter_get_colorEnd(
24284            self_: *mut whiteout_M3ParticleEmitter,
24285        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24286        pub fn whiteout_m3_M3ParticleEmitter_set_colorEnd(
24287            self_: *mut whiteout_M3ParticleEmitter,
24288            value: *const whiteout_M3AnimRefM3ColorBGRA,
24289        );
24290        pub fn whiteout_m3_M3ParticleEmitter_get_drag(
24291            self_: *mut whiteout_M3ParticleEmitter,
24292        ) -> f32;
24293        pub fn whiteout_m3_M3ParticleEmitter_set_drag(
24294            self_: *mut whiteout_M3ParticleEmitter,
24295            value: f32,
24296        );
24297        pub fn whiteout_m3_M3ParticleEmitter_get_mass(
24298            self_: *mut whiteout_M3ParticleEmitter,
24299        ) -> f32;
24300        pub fn whiteout_m3_M3ParticleEmitter_set_mass(
24301            self_: *mut whiteout_M3ParticleEmitter,
24302            value: f32,
24303        );
24304        pub fn whiteout_m3_M3ParticleEmitter_get_massRandom(
24305            self_: *mut whiteout_M3ParticleEmitter,
24306        ) -> f32;
24307        pub fn whiteout_m3_M3ParticleEmitter_set_massRandom(
24308            self_: *mut whiteout_M3ParticleEmitter,
24309            value: f32,
24310        );
24311        pub fn whiteout_m3_M3ParticleEmitter_get_massSizeMultiplier(
24312            self_: *mut whiteout_M3ParticleEmitter,
24313        ) -> f32;
24314        pub fn whiteout_m3_M3ParticleEmitter_set_massSizeMultiplier(
24315            self_: *mut whiteout_M3ParticleEmitter,
24316            value: f32,
24317        );
24318        pub fn whiteout_m3_M3ParticleEmitter_get_localForces(
24319            self_: *mut whiteout_M3ParticleEmitter,
24320        ) -> u16;
24321        pub fn whiteout_m3_M3ParticleEmitter_set_localForces(
24322            self_: *mut whiteout_M3ParticleEmitter,
24323            value: u16,
24324        );
24325        pub fn whiteout_m3_M3ParticleEmitter_get_worldForces(
24326            self_: *mut whiteout_M3ParticleEmitter,
24327        ) -> u16;
24328        pub fn whiteout_m3_M3ParticleEmitter_set_worldForces(
24329            self_: *mut whiteout_M3ParticleEmitter,
24330            value: u16,
24331        );
24332        pub fn whiteout_m3_M3ParticleEmitter_get_localForcesFallback(
24333            self_: *mut whiteout_M3ParticleEmitter,
24334        ) -> u16;
24335        pub fn whiteout_m3_M3ParticleEmitter_set_localForcesFallback(
24336            self_: *mut whiteout_M3ParticleEmitter,
24337            value: u16,
24338        );
24339        pub fn whiteout_m3_M3ParticleEmitter_get_worldForcesFallback(
24340            self_: *mut whiteout_M3ParticleEmitter,
24341        ) -> u16;
24342        pub fn whiteout_m3_M3ParticleEmitter_set_worldForcesFallback(
24343            self_: *mut whiteout_M3ParticleEmitter,
24344            value: u16,
24345        );
24346        pub fn whiteout_m3_M3ParticleEmitter_get_worldForcesMassMultiplier(
24347            self_: *mut whiteout_M3ParticleEmitter,
24348        ) -> f32;
24349        pub fn whiteout_m3_M3ParticleEmitter_set_worldForcesMassMultiplier(
24350            self_: *mut whiteout_M3ParticleEmitter,
24351            value: f32,
24352        );
24353        pub fn whiteout_m3_M3ParticleEmitter_get_noiseAmplitude(
24354            self_: *mut whiteout_M3ParticleEmitter,
24355        ) -> f32;
24356        pub fn whiteout_m3_M3ParticleEmitter_set_noiseAmplitude(
24357            self_: *mut whiteout_M3ParticleEmitter,
24358            value: f32,
24359        );
24360        pub fn whiteout_m3_M3ParticleEmitter_get_noiseFrequency(
24361            self_: *mut whiteout_M3ParticleEmitter,
24362        ) -> f32;
24363        pub fn whiteout_m3_M3ParticleEmitter_set_noiseFrequency(
24364            self_: *mut whiteout_M3ParticleEmitter,
24365            value: f32,
24366        );
24367        pub fn whiteout_m3_M3ParticleEmitter_get_noiseCoherence(
24368            self_: *mut whiteout_M3ParticleEmitter,
24369        ) -> f32;
24370        pub fn whiteout_m3_M3ParticleEmitter_set_noiseCoherence(
24371            self_: *mut whiteout_M3ParticleEmitter,
24372            value: f32,
24373        );
24374        pub fn whiteout_m3_M3ParticleEmitter_get_noiseEdge(
24375            self_: *mut whiteout_M3ParticleEmitter,
24376        ) -> f32;
24377        pub fn whiteout_m3_M3ParticleEmitter_set_noiseEdge(
24378            self_: *mut whiteout_M3ParticleEmitter,
24379            value: f32,
24380        );
24381        pub fn whiteout_m3_M3ParticleEmitter_get_indexPlusLength(
24382            self_: *mut whiteout_M3ParticleEmitter,
24383        ) -> u32;
24384        pub fn whiteout_m3_M3ParticleEmitter_set_indexPlusLength(
24385            self_: *mut whiteout_M3ParticleEmitter,
24386            value: u32,
24387        );
24388        pub fn whiteout_m3_M3ParticleEmitter_get_maxParticles(
24389            self_: *mut whiteout_M3ParticleEmitter,
24390        ) -> u32;
24391        pub fn whiteout_m3_M3ParticleEmitter_set_maxParticles(
24392            self_: *mut whiteout_M3ParticleEmitter,
24393            value: u32,
24394        );
24395        pub fn whiteout_m3_M3ParticleEmitter_get_emissionRate(
24396            self_: *mut whiteout_M3ParticleEmitter,
24397        ) -> *mut whiteout_M3AnimRefF32;
24398        pub fn whiteout_m3_M3ParticleEmitter_set_emissionRate(
24399            self_: *mut whiteout_M3ParticleEmitter,
24400            value: *const whiteout_M3AnimRefF32,
24401        );
24402        pub fn whiteout_m3_M3ParticleEmitter_get_emitterShape(
24403            self_: *mut whiteout_M3ParticleEmitter,
24404        ) -> i32;
24405        pub fn whiteout_m3_M3ParticleEmitter_set_emitterShape(
24406            self_: *mut whiteout_M3ParticleEmitter,
24407            value: i32,
24408        );
24409        pub fn whiteout_m3_M3ParticleEmitter_get_shapeOuter(
24410            self_: *mut whiteout_M3ParticleEmitter,
24411        ) -> *mut whiteout_M3AnimRefVector3f;
24412        pub fn whiteout_m3_M3ParticleEmitter_set_shapeOuter(
24413            self_: *mut whiteout_M3ParticleEmitter,
24414            value: *const whiteout_M3AnimRefVector3f,
24415        );
24416        pub fn whiteout_m3_M3ParticleEmitter_get_shapeInner(
24417            self_: *mut whiteout_M3ParticleEmitter,
24418        ) -> *mut whiteout_M3AnimRefVector3f;
24419        pub fn whiteout_m3_M3ParticleEmitter_set_shapeInner(
24420            self_: *mut whiteout_M3ParticleEmitter,
24421            value: *const whiteout_M3AnimRefVector3f,
24422        );
24423        pub fn whiteout_m3_M3ParticleEmitter_get_outerRadius(
24424            self_: *mut whiteout_M3ParticleEmitter,
24425        ) -> *mut whiteout_M3AnimRefF32;
24426        pub fn whiteout_m3_M3ParticleEmitter_set_outerRadius(
24427            self_: *mut whiteout_M3ParticleEmitter,
24428            value: *const whiteout_M3AnimRefF32,
24429        );
24430        pub fn whiteout_m3_M3ParticleEmitter_get_innerRadius(
24431            self_: *mut whiteout_M3ParticleEmitter,
24432        ) -> *mut whiteout_M3AnimRefF32;
24433        pub fn whiteout_m3_M3ParticleEmitter_set_innerRadius(
24434            self_: *mut whiteout_M3ParticleEmitter,
24435            value: *const whiteout_M3AnimRefF32,
24436        );
24437        pub fn whiteout_m3_M3ParticleEmitter_get_shapeRegions_count(
24438            self_: *mut whiteout_M3ParticleEmitter,
24439        ) -> usize;
24440        pub fn whiteout_m3_M3ParticleEmitter_resize_shapeRegions(
24441            self_: *mut whiteout_M3ParticleEmitter,
24442            count: usize,
24443        );
24444        pub fn whiteout_m3_M3ParticleEmitter_get_shapeRegions_data(
24445            self_: *mut whiteout_M3ParticleEmitter,
24446        ) -> *const u32;
24447        pub fn whiteout_m3_M3ParticleEmitter_assign_shapeRegions(
24448            self_: *mut whiteout_M3ParticleEmitter,
24449            data: *const u32,
24450            count: usize,
24451        );
24452        pub fn whiteout_m3_M3ParticleEmitter_get_velocityType(
24453            self_: *mut whiteout_M3ParticleEmitter,
24454        ) -> u32;
24455        pub fn whiteout_m3_M3ParticleEmitter_set_velocityType(
24456            self_: *mut whiteout_M3ParticleEmitter,
24457            value: u32,
24458        );
24459        pub fn whiteout_m3_M3ParticleEmitter_get_sizeRandomEnable(
24460            self_: *mut whiteout_M3ParticleEmitter,
24461        ) -> u32;
24462        pub fn whiteout_m3_M3ParticleEmitter_set_sizeRandomEnable(
24463            self_: *mut whiteout_M3ParticleEmitter,
24464            value: u32,
24465        );
24466        pub fn whiteout_m3_M3ParticleEmitter_get_sizeRandomAnimation(
24467            self_: *mut whiteout_M3ParticleEmitter,
24468        ) -> *mut whiteout_M3AnimRefVector3f;
24469        pub fn whiteout_m3_M3ParticleEmitter_set_sizeRandomAnimation(
24470            self_: *mut whiteout_M3ParticleEmitter,
24471            value: *const whiteout_M3AnimRefVector3f,
24472        );
24473        pub fn whiteout_m3_M3ParticleEmitter_get_rotationRandomEnable(
24474            self_: *mut whiteout_M3ParticleEmitter,
24475        ) -> u32;
24476        pub fn whiteout_m3_M3ParticleEmitter_set_rotationRandomEnable(
24477            self_: *mut whiteout_M3ParticleEmitter,
24478            value: u32,
24479        );
24480        pub fn whiteout_m3_M3ParticleEmitter_get_rotationRandomAnimation(
24481            self_: *mut whiteout_M3ParticleEmitter,
24482        ) -> *mut whiteout_M3AnimRefVector3f;
24483        pub fn whiteout_m3_M3ParticleEmitter_set_rotationRandomAnimation(
24484            self_: *mut whiteout_M3ParticleEmitter,
24485            value: *const whiteout_M3AnimRefVector3f,
24486        );
24487        pub fn whiteout_m3_M3ParticleEmitter_get_colorRandomEnable(
24488            self_: *mut whiteout_M3ParticleEmitter,
24489        ) -> u32;
24490        pub fn whiteout_m3_M3ParticleEmitter_set_colorRandomEnable(
24491            self_: *mut whiteout_M3ParticleEmitter,
24492            value: u32,
24493        );
24494        pub fn whiteout_m3_M3ParticleEmitter_get_colorStartRandom(
24495            self_: *mut whiteout_M3ParticleEmitter,
24496        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24497        pub fn whiteout_m3_M3ParticleEmitter_set_colorStartRandom(
24498            self_: *mut whiteout_M3ParticleEmitter,
24499            value: *const whiteout_M3AnimRefM3ColorBGRA,
24500        );
24501        pub fn whiteout_m3_M3ParticleEmitter_get_colorMidRandom(
24502            self_: *mut whiteout_M3ParticleEmitter,
24503        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24504        pub fn whiteout_m3_M3ParticleEmitter_set_colorMidRandom(
24505            self_: *mut whiteout_M3ParticleEmitter,
24506            value: *const whiteout_M3AnimRefM3ColorBGRA,
24507        );
24508        pub fn whiteout_m3_M3ParticleEmitter_get_colorEndRandom(
24509            self_: *mut whiteout_M3ParticleEmitter,
24510        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
24511        pub fn whiteout_m3_M3ParticleEmitter_set_colorEndRandom(
24512            self_: *mut whiteout_M3ParticleEmitter,
24513            value: *const whiteout_M3AnimRefM3ColorBGRA,
24514        );
24515        pub fn whiteout_m3_M3ParticleEmitter_get_alphaRandomEnable(
24516            self_: *mut whiteout_M3ParticleEmitter,
24517        ) -> u32;
24518        pub fn whiteout_m3_M3ParticleEmitter_set_alphaRandomEnable(
24519            self_: *mut whiteout_M3ParticleEmitter,
24520            value: u32,
24521        );
24522        pub fn whiteout_m3_M3ParticleEmitter_get_squirtAmount(
24523            self_: *mut whiteout_M3ParticleEmitter,
24524        ) -> *mut whiteout_M3AnimRefU16;
24525        pub fn whiteout_m3_M3ParticleEmitter_set_squirtAmount(
24526            self_: *mut whiteout_M3ParticleEmitter,
24527            value: *const whiteout_M3AnimRefU16,
24528        );
24529        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookStartInitIndex(
24530            self_: *mut whiteout_M3ParticleEmitter,
24531        ) -> u8;
24532        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookStartInitIndex(
24533            self_: *mut whiteout_M3ParticleEmitter,
24534            value: u8,
24535        );
24536        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookStartStopIndex(
24537            self_: *mut whiteout_M3ParticleEmitter,
24538        ) -> u8;
24539        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookStartStopIndex(
24540            self_: *mut whiteout_M3ParticleEmitter,
24541            value: u8,
24542        );
24543        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookEndInitIndex(
24544            self_: *mut whiteout_M3ParticleEmitter,
24545        ) -> u8;
24546        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookEndInitIndex(
24547            self_: *mut whiteout_M3ParticleEmitter,
24548            value: u8,
24549        );
24550        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookEndStopIndex(
24551            self_: *mut whiteout_M3ParticleEmitter,
24552        ) -> u8;
24553        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookEndStopIndex(
24554            self_: *mut whiteout_M3ParticleEmitter,
24555            value: u8,
24556        );
24557        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookMidTime(
24558            self_: *mut whiteout_M3ParticleEmitter,
24559        ) -> f32;
24560        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookMidTime(
24561            self_: *mut whiteout_M3ParticleEmitter,
24562            value: f32,
24563        );
24564        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookColumns(
24565            self_: *mut whiteout_M3ParticleEmitter,
24566        ) -> u16;
24567        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookColumns(
24568            self_: *mut whiteout_M3ParticleEmitter,
24569            value: u16,
24570        );
24571        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookRows(
24572            self_: *mut whiteout_M3ParticleEmitter,
24573        ) -> u16;
24574        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookRows(
24575            self_: *mut whiteout_M3ParticleEmitter,
24576            value: u16,
24577        );
24578        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookColumnFraction(
24579            self_: *mut whiteout_M3ParticleEmitter,
24580        ) -> f32;
24581        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookColumnFraction(
24582            self_: *mut whiteout_M3ParticleEmitter,
24583            value: f32,
24584        );
24585        pub fn whiteout_m3_M3ParticleEmitter_get_flipbookRowFraction(
24586            self_: *mut whiteout_M3ParticleEmitter,
24587        ) -> f32;
24588        pub fn whiteout_m3_M3ParticleEmitter_set_flipbookRowFraction(
24589            self_: *mut whiteout_M3ParticleEmitter,
24590            value: f32,
24591        );
24592        pub fn whiteout_m3_M3ParticleEmitter_get_bounce(
24593            self_: *mut whiteout_M3ParticleEmitter,
24594        ) -> f32;
24595        pub fn whiteout_m3_M3ParticleEmitter_set_bounce(
24596            self_: *mut whiteout_M3ParticleEmitter,
24597            value: f32,
24598        );
24599        pub fn whiteout_m3_M3ParticleEmitter_get_friction(
24600            self_: *mut whiteout_M3ParticleEmitter,
24601        ) -> f32;
24602        pub fn whiteout_m3_M3ParticleEmitter_set_friction(
24603            self_: *mut whiteout_M3ParticleEmitter,
24604            value: f32,
24605        );
24606        pub fn whiteout_m3_M3ParticleEmitter_get_collisionSpawnIndex(
24607            self_: *mut whiteout_M3ParticleEmitter,
24608        ) -> i32;
24609        pub fn whiteout_m3_M3ParticleEmitter_set_collisionSpawnIndex(
24610            self_: *mut whiteout_M3ParticleEmitter,
24611            value: i32,
24612        );
24613        pub fn whiteout_m3_M3ParticleEmitter_get_collisionSpawnMin(
24614            self_: *mut whiteout_M3ParticleEmitter,
24615        ) -> u32;
24616        pub fn whiteout_m3_M3ParticleEmitter_set_collisionSpawnMin(
24617            self_: *mut whiteout_M3ParticleEmitter,
24618            value: u32,
24619        );
24620        pub fn whiteout_m3_M3ParticleEmitter_get_collisionSpawnMax(
24621            self_: *mut whiteout_M3ParticleEmitter,
24622        ) -> u32;
24623        pub fn whiteout_m3_M3ParticleEmitter_set_collisionSpawnMax(
24624            self_: *mut whiteout_M3ParticleEmitter,
24625            value: u32,
24626        );
24627        pub fn whiteout_m3_M3ParticleEmitter_get_collisionSpawnChance(
24628            self_: *mut whiteout_M3ParticleEmitter,
24629        ) -> f32;
24630        pub fn whiteout_m3_M3ParticleEmitter_set_collisionSpawnChance(
24631            self_: *mut whiteout_M3ParticleEmitter,
24632            value: f32,
24633        );
24634        pub fn whiteout_m3_M3ParticleEmitter_get_collisionSpawnEnergy(
24635            self_: *mut whiteout_M3ParticleEmitter,
24636        ) -> f32;
24637        pub fn whiteout_m3_M3ParticleEmitter_set_collisionSpawnEnergy(
24638            self_: *mut whiteout_M3ParticleEmitter,
24639            value: f32,
24640        );
24641        pub fn whiteout_m3_M3ParticleEmitter_get_collisionDieBounce(
24642            self_: *mut whiteout_M3ParticleEmitter,
24643        ) -> u32;
24644        pub fn whiteout_m3_M3ParticleEmitter_set_collisionDieBounce(
24645            self_: *mut whiteout_M3ParticleEmitter,
24646            value: u32,
24647        );
24648        pub fn whiteout_m3_M3ParticleEmitter_get_instanceType(
24649            self_: *mut whiteout_M3ParticleEmitter,
24650        ) -> i32;
24651        pub fn whiteout_m3_M3ParticleEmitter_set_instanceType(
24652            self_: *mut whiteout_M3ParticleEmitter,
24653            value: i32,
24654        );
24655        pub fn whiteout_m3_M3ParticleEmitter_get_tailLength(
24656            self_: *mut whiteout_M3ParticleEmitter,
24657        ) -> f32;
24658        pub fn whiteout_m3_M3ParticleEmitter_set_tailLength(
24659            self_: *mut whiteout_M3ParticleEmitter,
24660            value: f32,
24661        );
24662        pub fn whiteout_m3_M3ParticleEmitter_get_instanceAngle(
24663            self_: *mut whiteout_M3ParticleEmitter,
24664        ) -> *mut core::ffi::c_void;
24665        pub fn whiteout_m3_M3ParticleEmitter_set_instanceAngle(
24666            self_: *mut whiteout_M3ParticleEmitter,
24667            value: *const core::ffi::c_void,
24668        );
24669        pub fn whiteout_m3_M3ParticleEmitter_get_instanceDistance(
24670            self_: *mut whiteout_M3ParticleEmitter,
24671        ) -> f32;
24672        pub fn whiteout_m3_M3ParticleEmitter_set_instanceDistance(
24673            self_: *mut whiteout_M3ParticleEmitter,
24674            value: f32,
24675        );
24676        pub fn whiteout_m3_M3ParticleEmitter_get_pitchType(
24677            self_: *mut whiteout_M3ParticleEmitter,
24678        ) -> u32;
24679        pub fn whiteout_m3_M3ParticleEmitter_set_pitchType(
24680            self_: *mut whiteout_M3ParticleEmitter,
24681            value: u32,
24682        );
24683        pub fn whiteout_m3_M3ParticleEmitter_get_pitchAmplitude(
24684            self_: *mut whiteout_M3ParticleEmitter,
24685        ) -> *mut whiteout_M3AnimRefF32;
24686        pub fn whiteout_m3_M3ParticleEmitter_set_pitchAmplitude(
24687            self_: *mut whiteout_M3ParticleEmitter,
24688            value: *const whiteout_M3AnimRefF32,
24689        );
24690        pub fn whiteout_m3_M3ParticleEmitter_get_pitchFrequency(
24691            self_: *mut whiteout_M3ParticleEmitter,
24692        ) -> *mut whiteout_M3AnimRefF32;
24693        pub fn whiteout_m3_M3ParticleEmitter_set_pitchFrequency(
24694            self_: *mut whiteout_M3ParticleEmitter,
24695            value: *const whiteout_M3AnimRefF32,
24696        );
24697        pub fn whiteout_m3_M3ParticleEmitter_get_yawType(
24698            self_: *mut whiteout_M3ParticleEmitter,
24699        ) -> u32;
24700        pub fn whiteout_m3_M3ParticleEmitter_set_yawType(
24701            self_: *mut whiteout_M3ParticleEmitter,
24702            value: u32,
24703        );
24704        pub fn whiteout_m3_M3ParticleEmitter_get_yawAmplitude(
24705            self_: *mut whiteout_M3ParticleEmitter,
24706        ) -> *mut whiteout_M3AnimRefF32;
24707        pub fn whiteout_m3_M3ParticleEmitter_set_yawAmplitude(
24708            self_: *mut whiteout_M3ParticleEmitter,
24709            value: *const whiteout_M3AnimRefF32,
24710        );
24711        pub fn whiteout_m3_M3ParticleEmitter_get_yawFrequency(
24712            self_: *mut whiteout_M3ParticleEmitter,
24713        ) -> *mut whiteout_M3AnimRefF32;
24714        pub fn whiteout_m3_M3ParticleEmitter_set_yawFrequency(
24715            self_: *mut whiteout_M3ParticleEmitter,
24716            value: *const whiteout_M3AnimRefF32,
24717        );
24718        pub fn whiteout_m3_M3ParticleEmitter_get_speedType(
24719            self_: *mut whiteout_M3ParticleEmitter,
24720        ) -> u32;
24721        pub fn whiteout_m3_M3ParticleEmitter_set_speedType(
24722            self_: *mut whiteout_M3ParticleEmitter,
24723            value: u32,
24724        );
24725        pub fn whiteout_m3_M3ParticleEmitter_get_speedAmplitude(
24726            self_: *mut whiteout_M3ParticleEmitter,
24727        ) -> *mut whiteout_M3AnimRefF32;
24728        pub fn whiteout_m3_M3ParticleEmitter_set_speedAmplitude(
24729            self_: *mut whiteout_M3ParticleEmitter,
24730            value: *const whiteout_M3AnimRefF32,
24731        );
24732        pub fn whiteout_m3_M3ParticleEmitter_get_speedFrequency(
24733            self_: *mut whiteout_M3ParticleEmitter,
24734        ) -> *mut whiteout_M3AnimRefF32;
24735        pub fn whiteout_m3_M3ParticleEmitter_set_speedFrequency(
24736            self_: *mut whiteout_M3ParticleEmitter,
24737            value: *const whiteout_M3AnimRefF32,
24738        );
24739        pub fn whiteout_m3_M3ParticleEmitter_get_sizeType(
24740            self_: *mut whiteout_M3ParticleEmitter,
24741        ) -> u32;
24742        pub fn whiteout_m3_M3ParticleEmitter_set_sizeType(
24743            self_: *mut whiteout_M3ParticleEmitter,
24744            value: u32,
24745        );
24746        pub fn whiteout_m3_M3ParticleEmitter_get_sizeAmplitude(
24747            self_: *mut whiteout_M3ParticleEmitter,
24748        ) -> *mut whiteout_M3AnimRefF32;
24749        pub fn whiteout_m3_M3ParticleEmitter_set_sizeAmplitude(
24750            self_: *mut whiteout_M3ParticleEmitter,
24751            value: *const whiteout_M3AnimRefF32,
24752        );
24753        pub fn whiteout_m3_M3ParticleEmitter_get_sizeFrequency(
24754            self_: *mut whiteout_M3ParticleEmitter,
24755        ) -> *mut whiteout_M3AnimRefF32;
24756        pub fn whiteout_m3_M3ParticleEmitter_set_sizeFrequency(
24757            self_: *mut whiteout_M3ParticleEmitter,
24758            value: *const whiteout_M3AnimRefF32,
24759        );
24760        pub fn whiteout_m3_M3ParticleEmitter_get_alphaType(
24761            self_: *mut whiteout_M3ParticleEmitter,
24762        ) -> u32;
24763        pub fn whiteout_m3_M3ParticleEmitter_set_alphaType(
24764            self_: *mut whiteout_M3ParticleEmitter,
24765            value: u32,
24766        );
24767        pub fn whiteout_m3_M3ParticleEmitter_get_alphaAmplitude(
24768            self_: *mut whiteout_M3ParticleEmitter,
24769        ) -> *mut whiteout_M3AnimRefF32;
24770        pub fn whiteout_m3_M3ParticleEmitter_set_alphaAmplitude(
24771            self_: *mut whiteout_M3ParticleEmitter,
24772            value: *const whiteout_M3AnimRefF32,
24773        );
24774        pub fn whiteout_m3_M3ParticleEmitter_get_alphaFrequency(
24775            self_: *mut whiteout_M3ParticleEmitter,
24776        ) -> *mut whiteout_M3AnimRefF32;
24777        pub fn whiteout_m3_M3ParticleEmitter_set_alphaFrequency(
24778            self_: *mut whiteout_M3ParticleEmitter,
24779            value: *const whiteout_M3AnimRefF32,
24780        );
24781        pub fn whiteout_m3_M3ParticleEmitter_get_colorType(
24782            self_: *mut whiteout_M3ParticleEmitter,
24783        ) -> u32;
24784        pub fn whiteout_m3_M3ParticleEmitter_set_colorType(
24785            self_: *mut whiteout_M3ParticleEmitter,
24786            value: u32,
24787        );
24788        pub fn whiteout_m3_M3ParticleEmitter_get_colorAmplitude(
24789            self_: *mut whiteout_M3ParticleEmitter,
24790        ) -> *mut whiteout_M3AnimRefF32;
24791        pub fn whiteout_m3_M3ParticleEmitter_set_colorAmplitude(
24792            self_: *mut whiteout_M3ParticleEmitter,
24793            value: *const whiteout_M3AnimRefF32,
24794        );
24795        pub fn whiteout_m3_M3ParticleEmitter_get_colorFrequency(
24796            self_: *mut whiteout_M3ParticleEmitter,
24797        ) -> *mut whiteout_M3AnimRefF32;
24798        pub fn whiteout_m3_M3ParticleEmitter_set_colorFrequency(
24799            self_: *mut whiteout_M3ParticleEmitter,
24800            value: *const whiteout_M3AnimRefF32,
24801        );
24802        pub fn whiteout_m3_M3ParticleEmitter_get_rotationType(
24803            self_: *mut whiteout_M3ParticleEmitter,
24804        ) -> u32;
24805        pub fn whiteout_m3_M3ParticleEmitter_set_rotationType(
24806            self_: *mut whiteout_M3ParticleEmitter,
24807            value: u32,
24808        );
24809        pub fn whiteout_m3_M3ParticleEmitter_get_rotationAmplitude(
24810            self_: *mut whiteout_M3ParticleEmitter,
24811        ) -> *mut whiteout_M3AnimRefF32;
24812        pub fn whiteout_m3_M3ParticleEmitter_set_rotationAmplitude(
24813            self_: *mut whiteout_M3ParticleEmitter,
24814            value: *const whiteout_M3AnimRefF32,
24815        );
24816        pub fn whiteout_m3_M3ParticleEmitter_get_rotationFrequency(
24817            self_: *mut whiteout_M3ParticleEmitter,
24818        ) -> *mut whiteout_M3AnimRefF32;
24819        pub fn whiteout_m3_M3ParticleEmitter_set_rotationFrequency(
24820            self_: *mut whiteout_M3ParticleEmitter,
24821            value: *const whiteout_M3AnimRefF32,
24822        );
24823        pub fn whiteout_m3_M3ParticleEmitter_get_horizontalType(
24824            self_: *mut whiteout_M3ParticleEmitter,
24825        ) -> u32;
24826        pub fn whiteout_m3_M3ParticleEmitter_set_horizontalType(
24827            self_: *mut whiteout_M3ParticleEmitter,
24828            value: u32,
24829        );
24830        pub fn whiteout_m3_M3ParticleEmitter_get_horizontalAmplitude(
24831            self_: *mut whiteout_M3ParticleEmitter,
24832        ) -> *mut whiteout_M3AnimRefF32;
24833        pub fn whiteout_m3_M3ParticleEmitter_set_horizontalAmplitude(
24834            self_: *mut whiteout_M3ParticleEmitter,
24835            value: *const whiteout_M3AnimRefF32,
24836        );
24837        pub fn whiteout_m3_M3ParticleEmitter_get_horizontalFrequency(
24838            self_: *mut whiteout_M3ParticleEmitter,
24839        ) -> *mut whiteout_M3AnimRefF32;
24840        pub fn whiteout_m3_M3ParticleEmitter_set_horizontalFrequency(
24841            self_: *mut whiteout_M3ParticleEmitter,
24842            value: *const whiteout_M3AnimRefF32,
24843        );
24844        pub fn whiteout_m3_M3ParticleEmitter_get_verticalType(
24845            self_: *mut whiteout_M3ParticleEmitter,
24846        ) -> u32;
24847        pub fn whiteout_m3_M3ParticleEmitter_set_verticalType(
24848            self_: *mut whiteout_M3ParticleEmitter,
24849            value: u32,
24850        );
24851        pub fn whiteout_m3_M3ParticleEmitter_get_verticalAmplitude(
24852            self_: *mut whiteout_M3ParticleEmitter,
24853        ) -> *mut whiteout_M3AnimRefF32;
24854        pub fn whiteout_m3_M3ParticleEmitter_set_verticalAmplitude(
24855            self_: *mut whiteout_M3ParticleEmitter,
24856            value: *const whiteout_M3AnimRefF32,
24857        );
24858        pub fn whiteout_m3_M3ParticleEmitter_get_verticalFrequency(
24859            self_: *mut whiteout_M3ParticleEmitter,
24860        ) -> *mut whiteout_M3AnimRefF32;
24861        pub fn whiteout_m3_M3ParticleEmitter_set_verticalFrequency(
24862            self_: *mut whiteout_M3ParticleEmitter,
24863            value: *const whiteout_M3AnimRefF32,
24864        );
24865        pub fn whiteout_m3_M3ParticleEmitter_get_particleVelocity(
24866            self_: *mut whiteout_M3ParticleEmitter,
24867        ) -> *mut whiteout_M3AnimRefF32;
24868        pub fn whiteout_m3_M3ParticleEmitter_set_particleVelocity(
24869            self_: *mut whiteout_M3ParticleEmitter,
24870            value: *const whiteout_M3AnimRefF32,
24871        );
24872        pub fn whiteout_m3_M3ParticleEmitter_get_phaseShift(
24873            self_: *mut whiteout_M3ParticleEmitter,
24874        ) -> *mut whiteout_M3AnimRefF32;
24875        pub fn whiteout_m3_M3ParticleEmitter_set_phaseShift(
24876            self_: *mut whiteout_M3ParticleEmitter,
24877            value: *const whiteout_M3AnimRefF32,
24878        );
24879        pub fn whiteout_m3_M3ParticleEmitter_get_flags(
24880            self_: *mut whiteout_M3ParticleEmitter,
24881        ) -> i32;
24882        pub fn whiteout_m3_M3ParticleEmitter_set_flags(
24883            self_: *mut whiteout_M3ParticleEmitter,
24884            value: i32,
24885        );
24886        pub fn whiteout_m3_M3ParticleEmitter_get_rotationFlags(
24887            self_: *mut whiteout_M3ParticleEmitter,
24888        ) -> i32;
24889        pub fn whiteout_m3_M3ParticleEmitter_set_rotationFlags(
24890            self_: *mut whiteout_M3ParticleEmitter,
24891            value: i32,
24892        );
24893        pub fn whiteout_m3_M3ParticleEmitter_get_colorSmoothing(
24894            self_: *mut whiteout_M3ParticleEmitter,
24895        ) -> i32;
24896        pub fn whiteout_m3_M3ParticleEmitter_set_colorSmoothing(
24897            self_: *mut whiteout_M3ParticleEmitter,
24898            value: i32,
24899        );
24900        pub fn whiteout_m3_M3ParticleEmitter_get_sizeSmoothing(
24901            self_: *mut whiteout_M3ParticleEmitter,
24902        ) -> i32;
24903        pub fn whiteout_m3_M3ParticleEmitter_set_sizeSmoothing(
24904            self_: *mut whiteout_M3ParticleEmitter,
24905            value: i32,
24906        );
24907        pub fn whiteout_m3_M3ParticleEmitter_get_rotationSmoothing(
24908            self_: *mut whiteout_M3ParticleEmitter,
24909        ) -> i32;
24910        pub fn whiteout_m3_M3ParticleEmitter_set_rotationSmoothing(
24911            self_: *mut whiteout_M3ParticleEmitter,
24912            value: i32,
24913        );
24914        pub fn whiteout_m3_M3ParticleEmitter_get_alphaThreshold(
24915            self_: *mut whiteout_M3ParticleEmitter,
24916        ) -> *mut whiteout_M3AnimRefF32;
24917        pub fn whiteout_m3_M3ParticleEmitter_set_alphaThreshold(
24918            self_: *mut whiteout_M3ParticleEmitter,
24919            value: *const whiteout_M3AnimRefF32,
24920        );
24921        pub fn whiteout_m3_M3ParticleEmitter_get_uvOffset(
24922            self_: *mut whiteout_M3ParticleEmitter,
24923        ) -> *mut whiteout_M3AnimRefVector2f;
24924        pub fn whiteout_m3_M3ParticleEmitter_set_uvOffset(
24925            self_: *mut whiteout_M3ParticleEmitter,
24926            value: *const whiteout_M3AnimRefVector2f,
24927        );
24928        pub fn whiteout_m3_M3ParticleEmitter_get_uvAngle(
24929            self_: *mut whiteout_M3ParticleEmitter,
24930        ) -> *mut whiteout_M3AnimRefVector3f;
24931        pub fn whiteout_m3_M3ParticleEmitter_set_uvAngle(
24932            self_: *mut whiteout_M3ParticleEmitter,
24933            value: *const whiteout_M3AnimRefVector3f,
24934        );
24935        pub fn whiteout_m3_M3ParticleEmitter_get_uvTiling(
24936            self_: *mut whiteout_M3ParticleEmitter,
24937        ) -> *mut whiteout_M3AnimRefVector2f;
24938        pub fn whiteout_m3_M3ParticleEmitter_set_uvTiling(
24939            self_: *mut whiteout_M3ParticleEmitter,
24940            value: *const whiteout_M3AnimRefVector2f,
24941        );
24942        pub fn whiteout_m3_M3ParticleEmitter_get_splineLineData_count(
24943            self_: *mut whiteout_M3ParticleEmitter,
24944        ) -> usize;
24945        pub fn whiteout_m3_M3ParticleEmitter_resize_splineLineData(
24946            self_: *mut whiteout_M3ParticleEmitter,
24947            count: usize,
24948        );
24949        pub fn whiteout_m3_M3ParticleEmitter_get_splineLineData_at(
24950            self_: *mut whiteout_M3ParticleEmitter,
24951            index: usize,
24952        ) -> *mut whiteout_M3AnimRefVector3f;
24953        pub fn whiteout_m3_M3ParticleEmitter_get_windMultiplier(
24954            self_: *mut whiteout_M3ParticleEmitter,
24955        ) -> f32;
24956        pub fn whiteout_m3_M3ParticleEmitter_set_windMultiplier(
24957            self_: *mut whiteout_M3ParticleEmitter,
24958            value: f32,
24959        );
24960        pub fn whiteout_m3_M3ParticleEmitter_get_lodReduce(
24961            self_: *mut whiteout_M3ParticleEmitter,
24962        ) -> u32;
24963        pub fn whiteout_m3_M3ParticleEmitter_set_lodReduce(
24964            self_: *mut whiteout_M3ParticleEmitter,
24965            value: u32,
24966        );
24967        pub fn whiteout_m3_M3ParticleEmitter_get_lodCut(
24968            self_: *mut whiteout_M3ParticleEmitter,
24969        ) -> u32;
24970        pub fn whiteout_m3_M3ParticleEmitter_set_lodCut(
24971            self_: *mut whiteout_M3ParticleEmitter,
24972            value: u32,
24973        );
24974        pub fn whiteout_m3_M3ParticleEmitter_get_lowerBound(
24975            self_: *mut whiteout_M3ParticleEmitter,
24976        ) -> *mut whiteout_M3AnimRefF32;
24977        pub fn whiteout_m3_M3ParticleEmitter_set_lowerBound(
24978            self_: *mut whiteout_M3ParticleEmitter,
24979            value: *const whiteout_M3AnimRefF32,
24980        );
24981        pub fn whiteout_m3_M3ParticleEmitter_get_upperBound(
24982            self_: *mut whiteout_M3ParticleEmitter,
24983        ) -> *mut whiteout_M3AnimRefF32;
24984        pub fn whiteout_m3_M3ParticleEmitter_set_upperBound(
24985            self_: *mut whiteout_M3ParticleEmitter,
24986            value: *const whiteout_M3AnimRefF32,
24987        );
24988        pub fn whiteout_m3_M3ParticleEmitter_get_trailLinkIndex(
24989            self_: *mut whiteout_M3ParticleEmitter,
24990        ) -> i32;
24991        pub fn whiteout_m3_M3ParticleEmitter_set_trailLinkIndex(
24992            self_: *mut whiteout_M3ParticleEmitter,
24993            value: i32,
24994        );
24995        pub fn whiteout_m3_M3ParticleEmitter_get_trailChance(
24996            self_: *mut whiteout_M3ParticleEmitter,
24997        ) -> f32;
24998        pub fn whiteout_m3_M3ParticleEmitter_set_trailChance(
24999            self_: *mut whiteout_M3ParticleEmitter,
25000            value: f32,
25001        );
25002        pub fn whiteout_m3_M3ParticleEmitter_get_trailEmissionRate(
25003            self_: *mut whiteout_M3ParticleEmitter,
25004        ) -> *mut whiteout_M3AnimRefF32;
25005        pub fn whiteout_m3_M3ParticleEmitter_set_trailEmissionRate(
25006            self_: *mut whiteout_M3ParticleEmitter,
25007            value: *const whiteout_M3AnimRefF32,
25008        );
25009        pub fn whiteout_m3_M3ParticleEmitter_get_splatProjectionIndex(
25010            self_: *mut whiteout_M3ParticleEmitter,
25011        ) -> i32;
25012        pub fn whiteout_m3_M3ParticleEmitter_set_splatProjectionIndex(
25013            self_: *mut whiteout_M3ParticleEmitter,
25014            value: i32,
25015        );
25016        pub fn whiteout_m3_M3ParticleEmitter_get_splatChance(
25017            self_: *mut whiteout_M3ParticleEmitter,
25018        ) -> f32;
25019        pub fn whiteout_m3_M3ParticleEmitter_set_splatChance(
25020            self_: *mut whiteout_M3ParticleEmitter,
25021            value: f32,
25022        );
25023        pub fn whiteout_m3_M3ParticleEmitter_get_copyIndices_count(
25024            self_: *mut whiteout_M3ParticleEmitter,
25025        ) -> usize;
25026        pub fn whiteout_m3_M3ParticleEmitter_resize_copyIndices(
25027            self_: *mut whiteout_M3ParticleEmitter,
25028            count: usize,
25029        );
25030        pub fn whiteout_m3_M3ParticleEmitter_get_copyIndices_data(
25031            self_: *mut whiteout_M3ParticleEmitter,
25032        ) -> *const u32;
25033        pub fn whiteout_m3_M3ParticleEmitter_assign_copyIndices(
25034            self_: *mut whiteout_M3ParticleEmitter,
25035            data: *const u32,
25036            count: usize,
25037        );
25038        pub fn whiteout_m3_M3ParticleEmitter_get_spawnRibbonOnBounceChance(
25039            self_: *mut whiteout_M3ParticleEmitter,
25040        ) -> f32;
25041        pub fn whiteout_m3_M3ParticleEmitter_set_spawnRibbonOnBounceChance(
25042            self_: *mut whiteout_M3ParticleEmitter,
25043            value: f32,
25044        );
25045        pub fn whiteout_m3_M3ParticleEmitter_get_ribbonLinkIndex(
25046            self_: *mut whiteout_M3ParticleEmitter,
25047        ) -> i32;
25048        pub fn whiteout_m3_M3ParticleEmitter_set_ribbonLinkIndex(
25049            self_: *mut whiteout_M3ParticleEmitter,
25050            value: i32,
25051        );
25052        // ParticleEmitterCopy
25053        pub fn whiteout_m3_M3ParticleEmitterCopy_new() -> *mut whiteout_M3ParticleEmitterCopy;
25054        pub fn whiteout_m3_M3ParticleEmitterCopy_delete(self_: *mut whiteout_M3ParticleEmitterCopy);
25055        pub fn whiteout_m3_M3ParticleEmitterCopy_get_emissionRate(
25056            self_: *mut whiteout_M3ParticleEmitterCopy,
25057        ) -> *mut whiteout_M3AnimRefF32;
25058        pub fn whiteout_m3_M3ParticleEmitterCopy_set_emissionRate(
25059            self_: *mut whiteout_M3ParticleEmitterCopy,
25060            value: *const whiteout_M3AnimRefF32,
25061        );
25062        pub fn whiteout_m3_M3ParticleEmitterCopy_get_squirtAmount(
25063            self_: *mut whiteout_M3ParticleEmitterCopy,
25064        ) -> *mut whiteout_M3AnimRefU16;
25065        pub fn whiteout_m3_M3ParticleEmitterCopy_set_squirtAmount(
25066            self_: *mut whiteout_M3ParticleEmitterCopy,
25067            value: *const whiteout_M3AnimRefU16,
25068        );
25069        pub fn whiteout_m3_M3ParticleEmitterCopy_get_boneIndex(
25070            self_: *mut whiteout_M3ParticleEmitterCopy,
25071        ) -> u32;
25072        pub fn whiteout_m3_M3ParticleEmitterCopy_set_boneIndex(
25073            self_: *mut whiteout_M3ParticleEmitterCopy,
25074            value: u32,
25075        );
25076        // SplineRibbon
25077        pub fn whiteout_m3_M3SplineRibbon_new() -> *mut whiteout_M3SplineRibbon;
25078        pub fn whiteout_m3_M3SplineRibbon_delete(self_: *mut whiteout_M3SplineRibbon);
25079        pub fn whiteout_m3_M3SplineRibbon_get_emissionOffset(
25080            self_: *mut whiteout_M3SplineRibbon,
25081        ) -> *mut core::ffi::c_void;
25082        pub fn whiteout_m3_M3SplineRibbon_set_emissionOffset(
25083            self_: *mut whiteout_M3SplineRibbon,
25084            value: *const core::ffi::c_void,
25085        );
25086        pub fn whiteout_m3_M3SplineRibbon_get_emissionVector(
25087            self_: *mut whiteout_M3SplineRibbon,
25088        ) -> *mut core::ffi::c_void;
25089        pub fn whiteout_m3_M3SplineRibbon_set_emissionVector(
25090            self_: *mut whiteout_M3SplineRibbon,
25091            value: *const core::ffi::c_void,
25092        );
25093        pub fn whiteout_m3_M3SplineRibbon_get_velocity(
25094            self_: *mut whiteout_M3SplineRibbon,
25095        ) -> *mut whiteout_M3AnimRefF32;
25096        pub fn whiteout_m3_M3SplineRibbon_set_velocity(
25097            self_: *mut whiteout_M3SplineRibbon,
25098            value: *const whiteout_M3AnimRefF32,
25099        );
25100        pub fn whiteout_m3_M3SplineRibbon_get_reserved(self_: *mut whiteout_M3SplineRibbon) -> u32;
25101        pub fn whiteout_m3_M3SplineRibbon_set_reserved(
25102            self_: *mut whiteout_M3SplineRibbon,
25103            value: u32,
25104        );
25105        pub fn whiteout_m3_M3SplineRibbon_get_boneIndex(self_: *mut whiteout_M3SplineRibbon)
25106            -> u32;
25107        pub fn whiteout_m3_M3SplineRibbon_set_boneIndex(
25108            self_: *mut whiteout_M3SplineRibbon,
25109            value: u32,
25110        );
25111        pub fn whiteout_m3_M3SplineRibbon_get_velocityBaseFactor(
25112            self_: *mut whiteout_M3SplineRibbon,
25113        ) -> *mut whiteout_M3AnimRefF32;
25114        pub fn whiteout_m3_M3SplineRibbon_set_velocityBaseFactor(
25115            self_: *mut whiteout_M3SplineRibbon,
25116            value: *const whiteout_M3AnimRefF32,
25117        );
25118        pub fn whiteout_m3_M3SplineRibbon_get_velocityEndFactor(
25119            self_: *mut whiteout_M3SplineRibbon,
25120        ) -> *mut whiteout_M3AnimRefF32;
25121        pub fn whiteout_m3_M3SplineRibbon_set_velocityEndFactor(
25122            self_: *mut whiteout_M3SplineRibbon,
25123            value: *const whiteout_M3AnimRefF32,
25124        );
25125        pub fn whiteout_m3_M3SplineRibbon_get_yawType(self_: *mut whiteout_M3SplineRibbon) -> u32;
25126        pub fn whiteout_m3_M3SplineRibbon_set_yawType(
25127            self_: *mut whiteout_M3SplineRibbon,
25128            value: u32,
25129        );
25130        pub fn whiteout_m3_M3SplineRibbon_get_yawAmplitude(
25131            self_: *mut whiteout_M3SplineRibbon,
25132        ) -> *mut whiteout_M3AnimRefF32;
25133        pub fn whiteout_m3_M3SplineRibbon_set_yawAmplitude(
25134            self_: *mut whiteout_M3SplineRibbon,
25135            value: *const whiteout_M3AnimRefF32,
25136        );
25137        pub fn whiteout_m3_M3SplineRibbon_get_yawFrequency(
25138            self_: *mut whiteout_M3SplineRibbon,
25139        ) -> *mut whiteout_M3AnimRefF32;
25140        pub fn whiteout_m3_M3SplineRibbon_set_yawFrequency(
25141            self_: *mut whiteout_M3SplineRibbon,
25142            value: *const whiteout_M3AnimRefF32,
25143        );
25144        pub fn whiteout_m3_M3SplineRibbon_get_pitchType(self_: *mut whiteout_M3SplineRibbon)
25145            -> u32;
25146        pub fn whiteout_m3_M3SplineRibbon_set_pitchType(
25147            self_: *mut whiteout_M3SplineRibbon,
25148            value: u32,
25149        );
25150        pub fn whiteout_m3_M3SplineRibbon_get_pitchAmplitude(
25151            self_: *mut whiteout_M3SplineRibbon,
25152        ) -> *mut whiteout_M3AnimRefF32;
25153        pub fn whiteout_m3_M3SplineRibbon_set_pitchAmplitude(
25154            self_: *mut whiteout_M3SplineRibbon,
25155            value: *const whiteout_M3AnimRefF32,
25156        );
25157        pub fn whiteout_m3_M3SplineRibbon_get_pitchFrequency(
25158            self_: *mut whiteout_M3SplineRibbon,
25159        ) -> *mut whiteout_M3AnimRefF32;
25160        pub fn whiteout_m3_M3SplineRibbon_set_pitchFrequency(
25161            self_: *mut whiteout_M3SplineRibbon,
25162            value: *const whiteout_M3AnimRefF32,
25163        );
25164        pub fn whiteout_m3_M3SplineRibbon_get_velocityType(
25165            self_: *mut whiteout_M3SplineRibbon,
25166        ) -> u32;
25167        pub fn whiteout_m3_M3SplineRibbon_set_velocityType(
25168            self_: *mut whiteout_M3SplineRibbon,
25169            value: u32,
25170        );
25171        pub fn whiteout_m3_M3SplineRibbon_get_velocityAmplitude(
25172            self_: *mut whiteout_M3SplineRibbon,
25173        ) -> *mut whiteout_M3AnimRefF32;
25174        pub fn whiteout_m3_M3SplineRibbon_set_velocityAmplitude(
25175            self_: *mut whiteout_M3SplineRibbon,
25176            value: *const whiteout_M3AnimRefF32,
25177        );
25178        pub fn whiteout_m3_M3SplineRibbon_get_velocityFrequency(
25179            self_: *mut whiteout_M3SplineRibbon,
25180        ) -> *mut whiteout_M3AnimRefF32;
25181        pub fn whiteout_m3_M3SplineRibbon_set_velocityFrequency(
25182            self_: *mut whiteout_M3SplineRibbon,
25183            value: *const whiteout_M3AnimRefF32,
25184        );
25185        pub fn whiteout_m3_M3SplineRibbon_get_yaw(
25186            self_: *mut whiteout_M3SplineRibbon,
25187        ) -> *mut whiteout_M3AnimRefF32;
25188        pub fn whiteout_m3_M3SplineRibbon_set_yaw(
25189            self_: *mut whiteout_M3SplineRibbon,
25190            value: *const whiteout_M3AnimRefF32,
25191        );
25192        pub fn whiteout_m3_M3SplineRibbon_get_pitch(
25193            self_: *mut whiteout_M3SplineRibbon,
25194        ) -> *mut whiteout_M3AnimRefF32;
25195        pub fn whiteout_m3_M3SplineRibbon_set_pitch(
25196            self_: *mut whiteout_M3SplineRibbon,
25197            value: *const whiteout_M3AnimRefF32,
25198        );
25199        pub fn whiteout_m3_M3SplineRibbon_get_emissionVectorNormFactor(
25200            self_: *mut whiteout_M3SplineRibbon,
25201        ) -> f32;
25202        pub fn whiteout_m3_M3SplineRibbon_set_emissionVectorNormFactor(
25203            self_: *mut whiteout_M3SplineRibbon,
25204            value: f32,
25205        );
25206        pub fn whiteout_m3_M3SplineRibbon_get_velocityNormFactor(
25207            self_: *mut whiteout_M3SplineRibbon,
25208        ) -> f32;
25209        pub fn whiteout_m3_M3SplineRibbon_set_velocityNormFactor(
25210            self_: *mut whiteout_M3SplineRibbon,
25211            value: f32,
25212        );
25213        // RibbonEmitter
25214        pub fn whiteout_m3_M3RibbonEmitter_new() -> *mut whiteout_M3RibbonEmitter;
25215        pub fn whiteout_m3_M3RibbonEmitter_delete(self_: *mut whiteout_M3RibbonEmitter);
25216        pub fn whiteout_m3_M3RibbonEmitter_get_boneIndex(
25217            self_: *mut whiteout_M3RibbonEmitter,
25218        ) -> u16;
25219        pub fn whiteout_m3_M3RibbonEmitter_set_boneIndex(
25220            self_: *mut whiteout_M3RibbonEmitter,
25221            value: u16,
25222        );
25223        pub fn whiteout_m3_M3RibbonEmitter_get_boneIndexFallback(
25224            self_: *mut whiteout_M3RibbonEmitter,
25225        ) -> u16;
25226        pub fn whiteout_m3_M3RibbonEmitter_set_boneIndexFallback(
25227            self_: *mut whiteout_M3RibbonEmitter,
25228            value: u16,
25229        );
25230        pub fn whiteout_m3_M3RibbonEmitter_get_materialIndex(
25231            self_: *mut whiteout_M3RibbonEmitter,
25232        ) -> u32;
25233        pub fn whiteout_m3_M3RibbonEmitter_set_materialIndex(
25234            self_: *mut whiteout_M3RibbonEmitter,
25235            value: u32,
25236        );
25237        pub fn whiteout_m3_M3RibbonEmitter_get_additionalFlags(
25238            self_: *mut whiteout_M3RibbonEmitter,
25239        ) -> i32;
25240        pub fn whiteout_m3_M3RibbonEmitter_set_additionalFlags(
25241            self_: *mut whiteout_M3RibbonEmitter,
25242            value: i32,
25243        );
25244        pub fn whiteout_m3_M3RibbonEmitter_get_initialSpeed(
25245            self_: *mut whiteout_M3RibbonEmitter,
25246        ) -> *mut whiteout_M3AnimRefF32;
25247        pub fn whiteout_m3_M3RibbonEmitter_set_initialSpeed(
25248            self_: *mut whiteout_M3RibbonEmitter,
25249            value: *const whiteout_M3AnimRefF32,
25250        );
25251        pub fn whiteout_m3_M3RibbonEmitter_get_initialSpeedRandom(
25252            self_: *mut whiteout_M3RibbonEmitter,
25253        ) -> *mut whiteout_M3AnimRefF32;
25254        pub fn whiteout_m3_M3RibbonEmitter_set_initialSpeedRandom(
25255            self_: *mut whiteout_M3RibbonEmitter,
25256            value: *const whiteout_M3AnimRefF32,
25257        );
25258        pub fn whiteout_m3_M3RibbonEmitter_get_initialYaw(
25259            self_: *mut whiteout_M3RibbonEmitter,
25260        ) -> *mut whiteout_M3AnimRefF32;
25261        pub fn whiteout_m3_M3RibbonEmitter_set_initialYaw(
25262            self_: *mut whiteout_M3RibbonEmitter,
25263            value: *const whiteout_M3AnimRefF32,
25264        );
25265        pub fn whiteout_m3_M3RibbonEmitter_get_initialPitch(
25266            self_: *mut whiteout_M3RibbonEmitter,
25267        ) -> *mut whiteout_M3AnimRefF32;
25268        pub fn whiteout_m3_M3RibbonEmitter_set_initialPitch(
25269            self_: *mut whiteout_M3RibbonEmitter,
25270            value: *const whiteout_M3AnimRefF32,
25271        );
25272        pub fn whiteout_m3_M3RibbonEmitter_get_initialHorizontal(
25273            self_: *mut whiteout_M3RibbonEmitter,
25274        ) -> *mut whiteout_M3AnimRefF32;
25275        pub fn whiteout_m3_M3RibbonEmitter_set_initialHorizontal(
25276            self_: *mut whiteout_M3RibbonEmitter,
25277            value: *const whiteout_M3AnimRefF32,
25278        );
25279        pub fn whiteout_m3_M3RibbonEmitter_get_initialVertical(
25280            self_: *mut whiteout_M3RibbonEmitter,
25281        ) -> *mut whiteout_M3AnimRefF32;
25282        pub fn whiteout_m3_M3RibbonEmitter_set_initialVertical(
25283            self_: *mut whiteout_M3RibbonEmitter,
25284            value: *const whiteout_M3AnimRefF32,
25285        );
25286        pub fn whiteout_m3_M3RibbonEmitter_get_lifetime(
25287            self_: *mut whiteout_M3RibbonEmitter,
25288        ) -> *mut whiteout_M3AnimRefF32;
25289        pub fn whiteout_m3_M3RibbonEmitter_set_lifetime(
25290            self_: *mut whiteout_M3RibbonEmitter,
25291            value: *const whiteout_M3AnimRefF32,
25292        );
25293        pub fn whiteout_m3_M3RibbonEmitter_get_lifetimeRandom(
25294            self_: *mut whiteout_M3RibbonEmitter,
25295        ) -> *mut whiteout_M3AnimRefF32;
25296        pub fn whiteout_m3_M3RibbonEmitter_set_lifetimeRandom(
25297            self_: *mut whiteout_M3RibbonEmitter,
25298            value: *const whiteout_M3AnimRefF32,
25299        );
25300        pub fn whiteout_m3_M3RibbonEmitter_get_killRadius(
25301            self_: *mut whiteout_M3RibbonEmitter,
25302        ) -> u32;
25303        pub fn whiteout_m3_M3RibbonEmitter_set_killRadius(
25304            self_: *mut whiteout_M3RibbonEmitter,
25305            value: u32,
25306        );
25307        pub fn whiteout_m3_M3RibbonEmitter_get_gravityX(
25308            self_: *mut whiteout_M3RibbonEmitter,
25309        ) -> f32;
25310        pub fn whiteout_m3_M3RibbonEmitter_set_gravityX(
25311            self_: *mut whiteout_M3RibbonEmitter,
25312            value: f32,
25313        );
25314        pub fn whiteout_m3_M3RibbonEmitter_get_gravityY(
25315            self_: *mut whiteout_M3RibbonEmitter,
25316        ) -> f32;
25317        pub fn whiteout_m3_M3RibbonEmitter_set_gravityY(
25318            self_: *mut whiteout_M3RibbonEmitter,
25319            value: f32,
25320        );
25321        pub fn whiteout_m3_M3RibbonEmitter_get_gravity(self_: *mut whiteout_M3RibbonEmitter)
25322            -> f32;
25323        pub fn whiteout_m3_M3RibbonEmitter_set_gravity(
25324            self_: *mut whiteout_M3RibbonEmitter,
25325            value: f32,
25326        );
25327        pub fn whiteout_m3_M3RibbonEmitter_get_sizeMidTime(
25328            self_: *mut whiteout_M3RibbonEmitter,
25329        ) -> f32;
25330        pub fn whiteout_m3_M3RibbonEmitter_set_sizeMidTime(
25331            self_: *mut whiteout_M3RibbonEmitter,
25332            value: f32,
25333        );
25334        pub fn whiteout_m3_M3RibbonEmitter_get_colorMidTime(
25335            self_: *mut whiteout_M3RibbonEmitter,
25336        ) -> f32;
25337        pub fn whiteout_m3_M3RibbonEmitter_set_colorMidTime(
25338            self_: *mut whiteout_M3RibbonEmitter,
25339            value: f32,
25340        );
25341        pub fn whiteout_m3_M3RibbonEmitter_get_alphaMidTime(
25342            self_: *mut whiteout_M3RibbonEmitter,
25343        ) -> f32;
25344        pub fn whiteout_m3_M3RibbonEmitter_set_alphaMidTime(
25345            self_: *mut whiteout_M3RibbonEmitter,
25346            value: f32,
25347        );
25348        pub fn whiteout_m3_M3RibbonEmitter_get_rotationMidTime(
25349            self_: *mut whiteout_M3RibbonEmitter,
25350        ) -> f32;
25351        pub fn whiteout_m3_M3RibbonEmitter_set_rotationMidTime(
25352            self_: *mut whiteout_M3RibbonEmitter,
25353            value: f32,
25354        );
25355        pub fn whiteout_m3_M3RibbonEmitter_get_sizeMidHoldTime(
25356            self_: *mut whiteout_M3RibbonEmitter,
25357        ) -> f32;
25358        pub fn whiteout_m3_M3RibbonEmitter_set_sizeMidHoldTime(
25359            self_: *mut whiteout_M3RibbonEmitter,
25360            value: f32,
25361        );
25362        pub fn whiteout_m3_M3RibbonEmitter_get_colorMidHoldTime(
25363            self_: *mut whiteout_M3RibbonEmitter,
25364        ) -> f32;
25365        pub fn whiteout_m3_M3RibbonEmitter_set_colorMidHoldTime(
25366            self_: *mut whiteout_M3RibbonEmitter,
25367            value: f32,
25368        );
25369        pub fn whiteout_m3_M3RibbonEmitter_get_alphaMidHoldTime(
25370            self_: *mut whiteout_M3RibbonEmitter,
25371        ) -> f32;
25372        pub fn whiteout_m3_M3RibbonEmitter_set_alphaMidHoldTime(
25373            self_: *mut whiteout_M3RibbonEmitter,
25374            value: f32,
25375        );
25376        pub fn whiteout_m3_M3RibbonEmitter_get_rotationMidHoldTime(
25377            self_: *mut whiteout_M3RibbonEmitter,
25378        ) -> f32;
25379        pub fn whiteout_m3_M3RibbonEmitter_set_rotationMidHoldTime(
25380            self_: *mut whiteout_M3RibbonEmitter,
25381            value: f32,
25382        );
25383        pub fn whiteout_m3_M3RibbonEmitter_get_sizeAnimation(
25384            self_: *mut whiteout_M3RibbonEmitter,
25385        ) -> *mut whiteout_M3AnimRefVector3f;
25386        pub fn whiteout_m3_M3RibbonEmitter_set_sizeAnimation(
25387            self_: *mut whiteout_M3RibbonEmitter,
25388            value: *const whiteout_M3AnimRefVector3f,
25389        );
25390        pub fn whiteout_m3_M3RibbonEmitter_get_rotationAnimation(
25391            self_: *mut whiteout_M3RibbonEmitter,
25392        ) -> *mut whiteout_M3AnimRefVector3f;
25393        pub fn whiteout_m3_M3RibbonEmitter_set_rotationAnimation(
25394            self_: *mut whiteout_M3RibbonEmitter,
25395            value: *const whiteout_M3AnimRefVector3f,
25396        );
25397        pub fn whiteout_m3_M3RibbonEmitter_get_colorStart(
25398            self_: *mut whiteout_M3RibbonEmitter,
25399        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
25400        pub fn whiteout_m3_M3RibbonEmitter_set_colorStart(
25401            self_: *mut whiteout_M3RibbonEmitter,
25402            value: *const whiteout_M3AnimRefM3ColorBGRA,
25403        );
25404        pub fn whiteout_m3_M3RibbonEmitter_get_colorMid(
25405            self_: *mut whiteout_M3RibbonEmitter,
25406        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
25407        pub fn whiteout_m3_M3RibbonEmitter_set_colorMid(
25408            self_: *mut whiteout_M3RibbonEmitter,
25409            value: *const whiteout_M3AnimRefM3ColorBGRA,
25410        );
25411        pub fn whiteout_m3_M3RibbonEmitter_get_colorEnd(
25412            self_: *mut whiteout_M3RibbonEmitter,
25413        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
25414        pub fn whiteout_m3_M3RibbonEmitter_set_colorEnd(
25415            self_: *mut whiteout_M3RibbonEmitter,
25416            value: *const whiteout_M3AnimRefM3ColorBGRA,
25417        );
25418        pub fn whiteout_m3_M3RibbonEmitter_get_drag(self_: *mut whiteout_M3RibbonEmitter) -> f32;
25419        pub fn whiteout_m3_M3RibbonEmitter_set_drag(
25420            self_: *mut whiteout_M3RibbonEmitter,
25421            value: f32,
25422        );
25423        pub fn whiteout_m3_M3RibbonEmitter_get_mass(self_: *mut whiteout_M3RibbonEmitter) -> f32;
25424        pub fn whiteout_m3_M3RibbonEmitter_set_mass(
25425            self_: *mut whiteout_M3RibbonEmitter,
25426            value: f32,
25427        );
25428        pub fn whiteout_m3_M3RibbonEmitter_get_massRandom(
25429            self_: *mut whiteout_M3RibbonEmitter,
25430        ) -> f32;
25431        pub fn whiteout_m3_M3RibbonEmitter_set_massRandom(
25432            self_: *mut whiteout_M3RibbonEmitter,
25433            value: f32,
25434        );
25435        pub fn whiteout_m3_M3RibbonEmitter_get_massSizeMultiplier(
25436            self_: *mut whiteout_M3RibbonEmitter,
25437        ) -> f32;
25438        pub fn whiteout_m3_M3RibbonEmitter_set_massSizeMultiplier(
25439            self_: *mut whiteout_M3RibbonEmitter,
25440            value: f32,
25441        );
25442        pub fn whiteout_m3_M3RibbonEmitter_get_localForces(
25443            self_: *mut whiteout_M3RibbonEmitter,
25444        ) -> u16;
25445        pub fn whiteout_m3_M3RibbonEmitter_set_localForces(
25446            self_: *mut whiteout_M3RibbonEmitter,
25447            value: u16,
25448        );
25449        pub fn whiteout_m3_M3RibbonEmitter_get_worldForces(
25450            self_: *mut whiteout_M3RibbonEmitter,
25451        ) -> u16;
25452        pub fn whiteout_m3_M3RibbonEmitter_set_worldForces(
25453            self_: *mut whiteout_M3RibbonEmitter,
25454            value: u16,
25455        );
25456        pub fn whiteout_m3_M3RibbonEmitter_get_localForcesFallback(
25457            self_: *mut whiteout_M3RibbonEmitter,
25458        ) -> u16;
25459        pub fn whiteout_m3_M3RibbonEmitter_set_localForcesFallback(
25460            self_: *mut whiteout_M3RibbonEmitter,
25461            value: u16,
25462        );
25463        pub fn whiteout_m3_M3RibbonEmitter_get_worldForcesFallback(
25464            self_: *mut whiteout_M3RibbonEmitter,
25465        ) -> u16;
25466        pub fn whiteout_m3_M3RibbonEmitter_set_worldForcesFallback(
25467            self_: *mut whiteout_M3RibbonEmitter,
25468            value: u16,
25469        );
25470        pub fn whiteout_m3_M3RibbonEmitter_get_worldForcesMassMultiplier(
25471            self_: *mut whiteout_M3RibbonEmitter,
25472        ) -> f32;
25473        pub fn whiteout_m3_M3RibbonEmitter_set_worldForcesMassMultiplier(
25474            self_: *mut whiteout_M3RibbonEmitter,
25475            value: f32,
25476        );
25477        pub fn whiteout_m3_M3RibbonEmitter_get_noiseAmplitude(
25478            self_: *mut whiteout_M3RibbonEmitter,
25479        ) -> f32;
25480        pub fn whiteout_m3_M3RibbonEmitter_set_noiseAmplitude(
25481            self_: *mut whiteout_M3RibbonEmitter,
25482            value: f32,
25483        );
25484        pub fn whiteout_m3_M3RibbonEmitter_get_noiseFrequency(
25485            self_: *mut whiteout_M3RibbonEmitter,
25486        ) -> f32;
25487        pub fn whiteout_m3_M3RibbonEmitter_set_noiseFrequency(
25488            self_: *mut whiteout_M3RibbonEmitter,
25489            value: f32,
25490        );
25491        pub fn whiteout_m3_M3RibbonEmitter_get_noiseCoherence(
25492            self_: *mut whiteout_M3RibbonEmitter,
25493        ) -> f32;
25494        pub fn whiteout_m3_M3RibbonEmitter_set_noiseCoherence(
25495            self_: *mut whiteout_M3RibbonEmitter,
25496            value: f32,
25497        );
25498        pub fn whiteout_m3_M3RibbonEmitter_get_noiseEdge(
25499            self_: *mut whiteout_M3RibbonEmitter,
25500        ) -> f32;
25501        pub fn whiteout_m3_M3RibbonEmitter_set_noiseEdge(
25502            self_: *mut whiteout_M3RibbonEmitter,
25503            value: f32,
25504        );
25505        pub fn whiteout_m3_M3RibbonEmitter_get_indexPlusLength(
25506            self_: *mut whiteout_M3RibbonEmitter,
25507        ) -> u32;
25508        pub fn whiteout_m3_M3RibbonEmitter_set_indexPlusLength(
25509            self_: *mut whiteout_M3RibbonEmitter,
25510            value: u32,
25511        );
25512        pub fn whiteout_m3_M3RibbonEmitter_get_emitterShape(
25513            self_: *mut whiteout_M3RibbonEmitter,
25514        ) -> u32;
25515        pub fn whiteout_m3_M3RibbonEmitter_set_emitterShape(
25516            self_: *mut whiteout_M3RibbonEmitter,
25517            value: u32,
25518        );
25519        pub fn whiteout_m3_M3RibbonEmitter_get_ribbonType(
25520            self_: *mut whiteout_M3RibbonEmitter,
25521        ) -> i32;
25522        pub fn whiteout_m3_M3RibbonEmitter_set_ribbonType(
25523            self_: *mut whiteout_M3RibbonEmitter,
25524            value: i32,
25525        );
25526        pub fn whiteout_m3_M3RibbonEmitter_get_divisions(
25527            self_: *mut whiteout_M3RibbonEmitter,
25528        ) -> f32;
25529        pub fn whiteout_m3_M3RibbonEmitter_set_divisions(
25530            self_: *mut whiteout_M3RibbonEmitter,
25531            value: f32,
25532        );
25533        pub fn whiteout_m3_M3RibbonEmitter_get_edges(self_: *mut whiteout_M3RibbonEmitter) -> u32;
25534        pub fn whiteout_m3_M3RibbonEmitter_set_edges(
25535            self_: *mut whiteout_M3RibbonEmitter,
25536            value: u32,
25537        );
25538        pub fn whiteout_m3_M3RibbonEmitter_get_innerRadius(
25539            self_: *mut whiteout_M3RibbonEmitter,
25540        ) -> f32;
25541        pub fn whiteout_m3_M3RibbonEmitter_set_innerRadius(
25542            self_: *mut whiteout_M3RibbonEmitter,
25543            value: f32,
25544        );
25545        pub fn whiteout_m3_M3RibbonEmitter_get_maxLength(
25546            self_: *mut whiteout_M3RibbonEmitter,
25547        ) -> *mut whiteout_M3AnimRefF32;
25548        pub fn whiteout_m3_M3RibbonEmitter_set_maxLength(
25549            self_: *mut whiteout_M3RibbonEmitter,
25550            value: *const whiteout_M3AnimRefF32,
25551        );
25552        pub fn whiteout_m3_M3RibbonEmitter_get_splineRibbons_count(
25553            self_: *mut whiteout_M3RibbonEmitter,
25554        ) -> usize;
25555        pub fn whiteout_m3_M3RibbonEmitter_resize_splineRibbons(
25556            self_: *mut whiteout_M3RibbonEmitter,
25557            count: usize,
25558        );
25559        pub fn whiteout_m3_M3RibbonEmitter_get_splineRibbons_at(
25560            self_: *mut whiteout_M3RibbonEmitter,
25561            index: usize,
25562        ) -> *mut whiteout_M3SplineRibbon;
25563        pub fn whiteout_m3_M3RibbonEmitter_get_active(
25564            self_: *mut whiteout_M3RibbonEmitter,
25565        ) -> *mut whiteout_M3AnimRefU32;
25566        pub fn whiteout_m3_M3RibbonEmitter_set_active(
25567            self_: *mut whiteout_M3RibbonEmitter,
25568            value: *const whiteout_M3AnimRefU32,
25569        );
25570        pub fn whiteout_m3_M3RibbonEmitter_get_flags(self_: *mut whiteout_M3RibbonEmitter) -> i32;
25571        pub fn whiteout_m3_M3RibbonEmitter_set_flags(
25572            self_: *mut whiteout_M3RibbonEmitter,
25573            value: i32,
25574        );
25575        pub fn whiteout_m3_M3RibbonEmitter_get_sizeSmoothing(
25576            self_: *mut whiteout_M3RibbonEmitter,
25577        ) -> i32;
25578        pub fn whiteout_m3_M3RibbonEmitter_set_sizeSmoothing(
25579            self_: *mut whiteout_M3RibbonEmitter,
25580            value: i32,
25581        );
25582        pub fn whiteout_m3_M3RibbonEmitter_get_colorSmoothing(
25583            self_: *mut whiteout_M3RibbonEmitter,
25584        ) -> i32;
25585        pub fn whiteout_m3_M3RibbonEmitter_set_colorSmoothing(
25586            self_: *mut whiteout_M3RibbonEmitter,
25587            value: i32,
25588        );
25589        pub fn whiteout_m3_M3RibbonEmitter_get_friction(
25590            self_: *mut whiteout_M3RibbonEmitter,
25591        ) -> f32;
25592        pub fn whiteout_m3_M3RibbonEmitter_set_friction(
25593            self_: *mut whiteout_M3RibbonEmitter,
25594            value: f32,
25595        );
25596        pub fn whiteout_m3_M3RibbonEmitter_get_bounce(self_: *mut whiteout_M3RibbonEmitter) -> f32;
25597        pub fn whiteout_m3_M3RibbonEmitter_set_bounce(
25598            self_: *mut whiteout_M3RibbonEmitter,
25599            value: f32,
25600        );
25601        pub fn whiteout_m3_M3RibbonEmitter_get_lodReduce(
25602            self_: *mut whiteout_M3RibbonEmitter,
25603        ) -> u32;
25604        pub fn whiteout_m3_M3RibbonEmitter_set_lodReduce(
25605            self_: *mut whiteout_M3RibbonEmitter,
25606            value: u32,
25607        );
25608        pub fn whiteout_m3_M3RibbonEmitter_get_lodCut(self_: *mut whiteout_M3RibbonEmitter) -> u32;
25609        pub fn whiteout_m3_M3RibbonEmitter_set_lodCut(
25610            self_: *mut whiteout_M3RibbonEmitter,
25611            value: u32,
25612        );
25613        pub fn whiteout_m3_M3RibbonEmitter_get_yawType(self_: *mut whiteout_M3RibbonEmitter)
25614            -> u32;
25615        pub fn whiteout_m3_M3RibbonEmitter_set_yawType(
25616            self_: *mut whiteout_M3RibbonEmitter,
25617            value: u32,
25618        );
25619        pub fn whiteout_m3_M3RibbonEmitter_get_yawAmplitude(
25620            self_: *mut whiteout_M3RibbonEmitter,
25621        ) -> *mut whiteout_M3AnimRefF32;
25622        pub fn whiteout_m3_M3RibbonEmitter_set_yawAmplitude(
25623            self_: *mut whiteout_M3RibbonEmitter,
25624            value: *const whiteout_M3AnimRefF32,
25625        );
25626        pub fn whiteout_m3_M3RibbonEmitter_get_yawFrequency(
25627            self_: *mut whiteout_M3RibbonEmitter,
25628        ) -> *mut whiteout_M3AnimRefF32;
25629        pub fn whiteout_m3_M3RibbonEmitter_set_yawFrequency(
25630            self_: *mut whiteout_M3RibbonEmitter,
25631            value: *const whiteout_M3AnimRefF32,
25632        );
25633        pub fn whiteout_m3_M3RibbonEmitter_get_pitchType(
25634            self_: *mut whiteout_M3RibbonEmitter,
25635        ) -> u32;
25636        pub fn whiteout_m3_M3RibbonEmitter_set_pitchType(
25637            self_: *mut whiteout_M3RibbonEmitter,
25638            value: u32,
25639        );
25640        pub fn whiteout_m3_M3RibbonEmitter_get_pitchAmplitude(
25641            self_: *mut whiteout_M3RibbonEmitter,
25642        ) -> *mut whiteout_M3AnimRefF32;
25643        pub fn whiteout_m3_M3RibbonEmitter_set_pitchAmplitude(
25644            self_: *mut whiteout_M3RibbonEmitter,
25645            value: *const whiteout_M3AnimRefF32,
25646        );
25647        pub fn whiteout_m3_M3RibbonEmitter_get_pitchFrequency(
25648            self_: *mut whiteout_M3RibbonEmitter,
25649        ) -> *mut whiteout_M3AnimRefF32;
25650        pub fn whiteout_m3_M3RibbonEmitter_set_pitchFrequency(
25651            self_: *mut whiteout_M3RibbonEmitter,
25652            value: *const whiteout_M3AnimRefF32,
25653        );
25654        pub fn whiteout_m3_M3RibbonEmitter_get_speedType(
25655            self_: *mut whiteout_M3RibbonEmitter,
25656        ) -> u32;
25657        pub fn whiteout_m3_M3RibbonEmitter_set_speedType(
25658            self_: *mut whiteout_M3RibbonEmitter,
25659            value: u32,
25660        );
25661        pub fn whiteout_m3_M3RibbonEmitter_get_speedAmplitude(
25662            self_: *mut whiteout_M3RibbonEmitter,
25663        ) -> *mut whiteout_M3AnimRefF32;
25664        pub fn whiteout_m3_M3RibbonEmitter_set_speedAmplitude(
25665            self_: *mut whiteout_M3RibbonEmitter,
25666            value: *const whiteout_M3AnimRefF32,
25667        );
25668        pub fn whiteout_m3_M3RibbonEmitter_get_speedFrequency(
25669            self_: *mut whiteout_M3RibbonEmitter,
25670        ) -> *mut whiteout_M3AnimRefF32;
25671        pub fn whiteout_m3_M3RibbonEmitter_set_speedFrequency(
25672            self_: *mut whiteout_M3RibbonEmitter,
25673            value: *const whiteout_M3AnimRefF32,
25674        );
25675        pub fn whiteout_m3_M3RibbonEmitter_get_sizeType(
25676            self_: *mut whiteout_M3RibbonEmitter,
25677        ) -> u32;
25678        pub fn whiteout_m3_M3RibbonEmitter_set_sizeType(
25679            self_: *mut whiteout_M3RibbonEmitter,
25680            value: u32,
25681        );
25682        pub fn whiteout_m3_M3RibbonEmitter_get_sizeAmplitude(
25683            self_: *mut whiteout_M3RibbonEmitter,
25684        ) -> *mut whiteout_M3AnimRefF32;
25685        pub fn whiteout_m3_M3RibbonEmitter_set_sizeAmplitude(
25686            self_: *mut whiteout_M3RibbonEmitter,
25687            value: *const whiteout_M3AnimRefF32,
25688        );
25689        pub fn whiteout_m3_M3RibbonEmitter_get_sizeFrequency(
25690            self_: *mut whiteout_M3RibbonEmitter,
25691        ) -> *mut whiteout_M3AnimRefF32;
25692        pub fn whiteout_m3_M3RibbonEmitter_set_sizeFrequency(
25693            self_: *mut whiteout_M3RibbonEmitter,
25694            value: *const whiteout_M3AnimRefF32,
25695        );
25696        pub fn whiteout_m3_M3RibbonEmitter_get_alphaType(
25697            self_: *mut whiteout_M3RibbonEmitter,
25698        ) -> u32;
25699        pub fn whiteout_m3_M3RibbonEmitter_set_alphaType(
25700            self_: *mut whiteout_M3RibbonEmitter,
25701            value: u32,
25702        );
25703        pub fn whiteout_m3_M3RibbonEmitter_get_alphaAmplitude(
25704            self_: *mut whiteout_M3RibbonEmitter,
25705        ) -> *mut whiteout_M3AnimRefF32;
25706        pub fn whiteout_m3_M3RibbonEmitter_set_alphaAmplitude(
25707            self_: *mut whiteout_M3RibbonEmitter,
25708            value: *const whiteout_M3AnimRefF32,
25709        );
25710        pub fn whiteout_m3_M3RibbonEmitter_get_alphaFrequency(
25711            self_: *mut whiteout_M3RibbonEmitter,
25712        ) -> *mut whiteout_M3AnimRefF32;
25713        pub fn whiteout_m3_M3RibbonEmitter_set_alphaFrequency(
25714            self_: *mut whiteout_M3RibbonEmitter,
25715            value: *const whiteout_M3AnimRefF32,
25716        );
25717        pub fn whiteout_m3_M3RibbonEmitter_get_particleVelocity(
25718            self_: *mut whiteout_M3RibbonEmitter,
25719        ) -> *mut whiteout_M3AnimRefF32;
25720        pub fn whiteout_m3_M3RibbonEmitter_set_particleVelocity(
25721            self_: *mut whiteout_M3RibbonEmitter,
25722            value: *const whiteout_M3AnimRefF32,
25723        );
25724        pub fn whiteout_m3_M3RibbonEmitter_get_overlay(
25725            self_: *mut whiteout_M3RibbonEmitter,
25726        ) -> *mut whiteout_M3AnimRefF32;
25727        pub fn whiteout_m3_M3RibbonEmitter_set_overlay(
25728            self_: *mut whiteout_M3RibbonEmitter,
25729            value: *const whiteout_M3AnimRefF32,
25730        );
25731        // Projector
25732        pub fn whiteout_m3_M3Projector_new() -> *mut whiteout_M3Projector;
25733        pub fn whiteout_m3_M3Projector_delete(self_: *mut whiteout_M3Projector);
25734        pub fn whiteout_m3_M3Projector_get_projectionType(self_: *mut whiteout_M3Projector) -> i32;
25735        pub fn whiteout_m3_M3Projector_set_projectionType(
25736            self_: *mut whiteout_M3Projector,
25737            value: i32,
25738        );
25739        pub fn whiteout_m3_M3Projector_get_bone(self_: *mut whiteout_M3Projector) -> u32;
25740        pub fn whiteout_m3_M3Projector_set_bone(self_: *mut whiteout_M3Projector, value: u32);
25741        pub fn whiteout_m3_M3Projector_get_materialReferenceIndex(
25742            self_: *mut whiteout_M3Projector,
25743        ) -> u32;
25744        pub fn whiteout_m3_M3Projector_set_materialReferenceIndex(
25745            self_: *mut whiteout_M3Projector,
25746            value: u32,
25747        );
25748        pub fn whiteout_m3_M3Projector_get_offset(
25749            self_: *mut whiteout_M3Projector,
25750        ) -> *mut whiteout_M3AnimRefVector3f;
25751        pub fn whiteout_m3_M3Projector_set_offset(
25752            self_: *mut whiteout_M3Projector,
25753            value: *const whiteout_M3AnimRefVector3f,
25754        );
25755        pub fn whiteout_m3_M3Projector_get_pitch(
25756            self_: *mut whiteout_M3Projector,
25757        ) -> *mut whiteout_M3AnimRefF32;
25758        pub fn whiteout_m3_M3Projector_set_pitch(
25759            self_: *mut whiteout_M3Projector,
25760            value: *const whiteout_M3AnimRefF32,
25761        );
25762        pub fn whiteout_m3_M3Projector_get_yaw(
25763            self_: *mut whiteout_M3Projector,
25764        ) -> *mut whiteout_M3AnimRefF32;
25765        pub fn whiteout_m3_M3Projector_set_yaw(
25766            self_: *mut whiteout_M3Projector,
25767            value: *const whiteout_M3AnimRefF32,
25768        );
25769        pub fn whiteout_m3_M3Projector_get_roll(
25770            self_: *mut whiteout_M3Projector,
25771        ) -> *mut whiteout_M3AnimRefF32;
25772        pub fn whiteout_m3_M3Projector_set_roll(
25773            self_: *mut whiteout_M3Projector,
25774            value: *const whiteout_M3AnimRefF32,
25775        );
25776        pub fn whiteout_m3_M3Projector_get_fieldOfView(
25777            self_: *mut whiteout_M3Projector,
25778        ) -> *mut whiteout_M3AnimRefF32;
25779        pub fn whiteout_m3_M3Projector_set_fieldOfView(
25780            self_: *mut whiteout_M3Projector,
25781            value: *const whiteout_M3AnimRefF32,
25782        );
25783        pub fn whiteout_m3_M3Projector_get_aspectRatio(
25784            self_: *mut whiteout_M3Projector,
25785        ) -> *mut whiteout_M3AnimRefF32;
25786        pub fn whiteout_m3_M3Projector_set_aspectRatio(
25787            self_: *mut whiteout_M3Projector,
25788            value: *const whiteout_M3AnimRefF32,
25789        );
25790        pub fn whiteout_m3_M3Projector_get_near(
25791            self_: *mut whiteout_M3Projector,
25792        ) -> *mut whiteout_M3AnimRefF32;
25793        pub fn whiteout_m3_M3Projector_set_near(
25794            self_: *mut whiteout_M3Projector,
25795            value: *const whiteout_M3AnimRefF32,
25796        );
25797        pub fn whiteout_m3_M3Projector_get_far(
25798            self_: *mut whiteout_M3Projector,
25799        ) -> *mut whiteout_M3AnimRefF32;
25800        pub fn whiteout_m3_M3Projector_set_far(
25801            self_: *mut whiteout_M3Projector,
25802            value: *const whiteout_M3AnimRefF32,
25803        );
25804        pub fn whiteout_m3_M3Projector_get_boxOffsetZBottom(
25805            self_: *mut whiteout_M3Projector,
25806        ) -> *mut whiteout_M3AnimRefF32;
25807        pub fn whiteout_m3_M3Projector_set_boxOffsetZBottom(
25808            self_: *mut whiteout_M3Projector,
25809            value: *const whiteout_M3AnimRefF32,
25810        );
25811        pub fn whiteout_m3_M3Projector_get_boxOffsetZTop(
25812            self_: *mut whiteout_M3Projector,
25813        ) -> *mut whiteout_M3AnimRefF32;
25814        pub fn whiteout_m3_M3Projector_set_boxOffsetZTop(
25815            self_: *mut whiteout_M3Projector,
25816            value: *const whiteout_M3AnimRefF32,
25817        );
25818        pub fn whiteout_m3_M3Projector_get_boxOffsetXLeft(
25819            self_: *mut whiteout_M3Projector,
25820        ) -> *mut whiteout_M3AnimRefF32;
25821        pub fn whiteout_m3_M3Projector_set_boxOffsetXLeft(
25822            self_: *mut whiteout_M3Projector,
25823            value: *const whiteout_M3AnimRefF32,
25824        );
25825        pub fn whiteout_m3_M3Projector_get_boxOffsetXRight(
25826            self_: *mut whiteout_M3Projector,
25827        ) -> *mut whiteout_M3AnimRefF32;
25828        pub fn whiteout_m3_M3Projector_set_boxOffsetXRight(
25829            self_: *mut whiteout_M3Projector,
25830            value: *const whiteout_M3AnimRefF32,
25831        );
25832        pub fn whiteout_m3_M3Projector_get_boxOffsetYFront(
25833            self_: *mut whiteout_M3Projector,
25834        ) -> *mut whiteout_M3AnimRefF32;
25835        pub fn whiteout_m3_M3Projector_set_boxOffsetYFront(
25836            self_: *mut whiteout_M3Projector,
25837            value: *const whiteout_M3AnimRefF32,
25838        );
25839        pub fn whiteout_m3_M3Projector_get_boxOffsetYBack(
25840            self_: *mut whiteout_M3Projector,
25841        ) -> *mut whiteout_M3AnimRefF32;
25842        pub fn whiteout_m3_M3Projector_set_boxOffsetYBack(
25843            self_: *mut whiteout_M3Projector,
25844            value: *const whiteout_M3AnimRefF32,
25845        );
25846        pub fn whiteout_m3_M3Projector_get_falloff(self_: *mut whiteout_M3Projector) -> f32;
25847        pub fn whiteout_m3_M3Projector_set_falloff(self_: *mut whiteout_M3Projector, value: f32);
25848        pub fn whiteout_m3_M3Projector_get_alphaInit(self_: *mut whiteout_M3Projector) -> f32;
25849        pub fn whiteout_m3_M3Projector_set_alphaInit(self_: *mut whiteout_M3Projector, value: f32);
25850        pub fn whiteout_m3_M3Projector_get_alphaMid(self_: *mut whiteout_M3Projector) -> f32;
25851        pub fn whiteout_m3_M3Projector_set_alphaMid(self_: *mut whiteout_M3Projector, value: f32);
25852        pub fn whiteout_m3_M3Projector_get_alphaEnd(self_: *mut whiteout_M3Projector) -> f32;
25853        pub fn whiteout_m3_M3Projector_set_alphaEnd(self_: *mut whiteout_M3Projector, value: f32);
25854        pub fn whiteout_m3_M3Projector_get_lifetimeAttack(self_: *mut whiteout_M3Projector) -> f32;
25855        pub fn whiteout_m3_M3Projector_set_lifetimeAttack(
25856            self_: *mut whiteout_M3Projector,
25857            value: f32,
25858        );
25859        pub fn whiteout_m3_M3Projector_get_lifetimeAttackTo(
25860            self_: *mut whiteout_M3Projector,
25861        ) -> f32;
25862        pub fn whiteout_m3_M3Projector_set_lifetimeAttackTo(
25863            self_: *mut whiteout_M3Projector,
25864            value: f32,
25865        );
25866        pub fn whiteout_m3_M3Projector_get_lifetimeHold(self_: *mut whiteout_M3Projector) -> f32;
25867        pub fn whiteout_m3_M3Projector_set_lifetimeHold(
25868            self_: *mut whiteout_M3Projector,
25869            value: f32,
25870        );
25871        pub fn whiteout_m3_M3Projector_get_lifetimeHoldTo(self_: *mut whiteout_M3Projector) -> f32;
25872        pub fn whiteout_m3_M3Projector_set_lifetimeHoldTo(
25873            self_: *mut whiteout_M3Projector,
25874            value: f32,
25875        );
25876        pub fn whiteout_m3_M3Projector_get_lifetimeDecay(self_: *mut whiteout_M3Projector) -> f32;
25877        pub fn whiteout_m3_M3Projector_set_lifetimeDecay(
25878            self_: *mut whiteout_M3Projector,
25879            value: f32,
25880        );
25881        pub fn whiteout_m3_M3Projector_get_lifetimeDecayTo(self_: *mut whiteout_M3Projector)
25882            -> f32;
25883        pub fn whiteout_m3_M3Projector_set_lifetimeDecayTo(
25884            self_: *mut whiteout_M3Projector,
25885            value: f32,
25886        );
25887        pub fn whiteout_m3_M3Projector_get_attenuationDistance(
25888            self_: *mut whiteout_M3Projector,
25889        ) -> f32;
25890        pub fn whiteout_m3_M3Projector_set_attenuationDistance(
25891            self_: *mut whiteout_M3Projector,
25892            value: f32,
25893        );
25894        pub fn whiteout_m3_M3Projector_get_active(
25895            self_: *mut whiteout_M3Projector,
25896        ) -> *mut whiteout_M3AnimRefU32;
25897        pub fn whiteout_m3_M3Projector_set_active(
25898            self_: *mut whiteout_M3Projector,
25899            value: *const whiteout_M3AnimRefU32,
25900        );
25901        pub fn whiteout_m3_M3Projector_get_layer(self_: *mut whiteout_M3Projector) -> u32;
25902        pub fn whiteout_m3_M3Projector_set_layer(self_: *mut whiteout_M3Projector, value: u32);
25903        pub fn whiteout_m3_M3Projector_get_lodReduce(self_: *mut whiteout_M3Projector) -> u32;
25904        pub fn whiteout_m3_M3Projector_set_lodReduce(self_: *mut whiteout_M3Projector, value: u32);
25905        pub fn whiteout_m3_M3Projector_get_lodCut(self_: *mut whiteout_M3Projector) -> u32;
25906        pub fn whiteout_m3_M3Projector_set_lodCut(self_: *mut whiteout_M3Projector, value: u32);
25907        pub fn whiteout_m3_M3Projector_get_flags(self_: *mut whiteout_M3Projector) -> i32;
25908        pub fn whiteout_m3_M3Projector_set_flags(self_: *mut whiteout_M3Projector, value: i32);
25909        // MaterialMap
25910        pub fn whiteout_m3_M3MaterialMap_new() -> *mut whiteout_M3MaterialMap;
25911        pub fn whiteout_m3_M3MaterialMap_delete(self_: *mut whiteout_M3MaterialMap);
25912        pub fn whiteout_m3_M3MaterialMap_get_materialType(
25913            self_: *mut whiteout_M3MaterialMap,
25914        ) -> i32;
25915        pub fn whiteout_m3_M3MaterialMap_set_materialType(
25916            self_: *mut whiteout_M3MaterialMap,
25917            value: i32,
25918        );
25919        pub fn whiteout_m3_M3MaterialMap_get_materialIndex(
25920            self_: *mut whiteout_M3MaterialMap,
25921        ) -> u32;
25922        pub fn whiteout_m3_M3MaterialMap_set_materialIndex(
25923            self_: *mut whiteout_M3MaterialMap,
25924            value: u32,
25925        );
25926        // TextureLayer
25927        pub fn whiteout_m3_M3TextureLayer_new() -> *mut whiteout_M3TextureLayer;
25928        pub fn whiteout_m3_M3TextureLayer_delete(self_: *mut whiteout_M3TextureLayer);
25929        pub fn whiteout_m3_M3TextureLayer_get_id(self_: *mut whiteout_M3TextureLayer) -> u32;
25930        pub fn whiteout_m3_M3TextureLayer_set_id(self_: *mut whiteout_M3TextureLayer, value: u32);
25931        pub fn whiteout_m3_M3TextureLayer_get_texturePath(
25932            self_: *mut whiteout_M3TextureLayer,
25933        ) -> RawCString;
25934        pub fn whiteout_m3_M3TextureLayer_set_texturePath(
25935            self_: *mut whiteout_M3TextureLayer,
25936            value: *const core::ffi::c_char,
25937        );
25938        pub fn whiteout_m3_M3TextureLayer_get_color(
25939            self_: *mut whiteout_M3TextureLayer,
25940        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
25941        pub fn whiteout_m3_M3TextureLayer_set_color(
25942            self_: *mut whiteout_M3TextureLayer,
25943            value: *const whiteout_M3AnimRefM3ColorBGRA,
25944        );
25945        pub fn whiteout_m3_M3TextureLayer_get_flags(self_: *mut whiteout_M3TextureLayer) -> i32;
25946        pub fn whiteout_m3_M3TextureLayer_set_flags(
25947            self_: *mut whiteout_M3TextureLayer,
25948            value: i32,
25949        );
25950        pub fn whiteout_m3_M3TextureLayer_get_uvMapping(self_: *mut whiteout_M3TextureLayer)
25951            -> i32;
25952        pub fn whiteout_m3_M3TextureLayer_set_uvMapping(
25953            self_: *mut whiteout_M3TextureLayer,
25954            value: i32,
25955        );
25956        pub fn whiteout_m3_M3TextureLayer_get_colorType(self_: *mut whiteout_M3TextureLayer)
25957            -> i32;
25958        pub fn whiteout_m3_M3TextureLayer_set_colorType(
25959            self_: *mut whiteout_M3TextureLayer,
25960            value: i32,
25961        );
25962        pub fn whiteout_m3_M3TextureLayer_get_rgbMultiply(
25963            self_: *mut whiteout_M3TextureLayer,
25964        ) -> *mut whiteout_M3AnimRefF32;
25965        pub fn whiteout_m3_M3TextureLayer_set_rgbMultiply(
25966            self_: *mut whiteout_M3TextureLayer,
25967            value: *const whiteout_M3AnimRefF32,
25968        );
25969        pub fn whiteout_m3_M3TextureLayer_get_rgbAdd(
25970            self_: *mut whiteout_M3TextureLayer,
25971        ) -> *mut whiteout_M3AnimRefF32;
25972        pub fn whiteout_m3_M3TextureLayer_set_rgbAdd(
25973            self_: *mut whiteout_M3TextureLayer,
25974            value: *const whiteout_M3AnimRefF32,
25975        );
25976        pub fn whiteout_m3_M3TextureLayer_get_pocTexture(
25977            self_: *mut whiteout_M3TextureLayer,
25978        ) -> u32;
25979        pub fn whiteout_m3_M3TextureLayer_set_pocTexture(
25980            self_: *mut whiteout_M3TextureLayer,
25981            value: u32,
25982        );
25983        pub fn whiteout_m3_M3TextureLayer_get_noiseAmplitude(
25984            self_: *mut whiteout_M3TextureLayer,
25985        ) -> f32;
25986        pub fn whiteout_m3_M3TextureLayer_set_noiseAmplitude(
25987            self_: *mut whiteout_M3TextureLayer,
25988            value: f32,
25989        );
25990        pub fn whiteout_m3_M3TextureLayer_get_noiseFrequency(
25991            self_: *mut whiteout_M3TextureLayer,
25992        ) -> f32;
25993        pub fn whiteout_m3_M3TextureLayer_set_noiseFrequency(
25994            self_: *mut whiteout_M3TextureLayer,
25995            value: f32,
25996        );
25997        pub fn whiteout_m3_M3TextureLayer_get_textureSource(
25998            self_: *mut whiteout_M3TextureLayer,
25999        ) -> u32;
26000        pub fn whiteout_m3_M3TextureLayer_set_textureSource(
26001            self_: *mut whiteout_M3TextureLayer,
26002            value: u32,
26003        );
26004        pub fn whiteout_m3_M3TextureLayer_get_aviFrameRate(
26005            self_: *mut whiteout_M3TextureLayer,
26006        ) -> u32;
26007        pub fn whiteout_m3_M3TextureLayer_set_aviFrameRate(
26008            self_: *mut whiteout_M3TextureLayer,
26009            value: u32,
26010        );
26011        pub fn whiteout_m3_M3TextureLayer_get_aviStart(self_: *mut whiteout_M3TextureLayer) -> u32;
26012        pub fn whiteout_m3_M3TextureLayer_set_aviStart(
26013            self_: *mut whiteout_M3TextureLayer,
26014            value: u32,
26015        );
26016        pub fn whiteout_m3_M3TextureLayer_get_aviStop(self_: *mut whiteout_M3TextureLayer) -> u32;
26017        pub fn whiteout_m3_M3TextureLayer_set_aviStop(
26018            self_: *mut whiteout_M3TextureLayer,
26019            value: u32,
26020        );
26021        pub fn whiteout_m3_M3TextureLayer_get_aviLoop(self_: *mut whiteout_M3TextureLayer) -> u32;
26022        pub fn whiteout_m3_M3TextureLayer_set_aviLoop(
26023            self_: *mut whiteout_M3TextureLayer,
26024            value: u32,
26025        );
26026        pub fn whiteout_m3_M3TextureLayer_get_aviSync(self_: *mut whiteout_M3TextureLayer) -> u32;
26027        pub fn whiteout_m3_M3TextureLayer_set_aviSync(
26028            self_: *mut whiteout_M3TextureLayer,
26029            value: u32,
26030        );
26031        pub fn whiteout_m3_M3TextureLayer_get_aviPlay(
26032            self_: *mut whiteout_M3TextureLayer,
26033        ) -> *mut whiteout_M3AnimRefU32;
26034        pub fn whiteout_m3_M3TextureLayer_set_aviPlay(
26035            self_: *mut whiteout_M3TextureLayer,
26036            value: *const whiteout_M3AnimRefU32,
26037        );
26038        pub fn whiteout_m3_M3TextureLayer_get_aviRestart(
26039            self_: *mut whiteout_M3TextureLayer,
26040        ) -> *mut whiteout_M3AnimRefU32;
26041        pub fn whiteout_m3_M3TextureLayer_set_aviRestart(
26042            self_: *mut whiteout_M3TextureLayer,
26043            value: *const whiteout_M3AnimRefU32,
26044        );
26045        pub fn whiteout_m3_M3TextureLayer_get_flipbookRows(
26046            self_: *mut whiteout_M3TextureLayer,
26047        ) -> u32;
26048        pub fn whiteout_m3_M3TextureLayer_set_flipbookRows(
26049            self_: *mut whiteout_M3TextureLayer,
26050            value: u32,
26051        );
26052        pub fn whiteout_m3_M3TextureLayer_get_flipbookColumns(
26053            self_: *mut whiteout_M3TextureLayer,
26054        ) -> u32;
26055        pub fn whiteout_m3_M3TextureLayer_set_flipbookColumns(
26056            self_: *mut whiteout_M3TextureLayer,
26057            value: u32,
26058        );
26059        pub fn whiteout_m3_M3TextureLayer_get_currentFrame(
26060            self_: *mut whiteout_M3TextureLayer,
26061        ) -> *mut whiteout_M3AnimRefU16;
26062        pub fn whiteout_m3_M3TextureLayer_set_currentFrame(
26063            self_: *mut whiteout_M3TextureLayer,
26064            value: *const whiteout_M3AnimRefU16,
26065        );
26066        pub fn whiteout_m3_M3TextureLayer_get_uvOffset(
26067            self_: *mut whiteout_M3TextureLayer,
26068        ) -> *mut whiteout_M3AnimRefVector2f;
26069        pub fn whiteout_m3_M3TextureLayer_set_uvOffset(
26070            self_: *mut whiteout_M3TextureLayer,
26071            value: *const whiteout_M3AnimRefVector2f,
26072        );
26073        pub fn whiteout_m3_M3TextureLayer_get_uvAngle(
26074            self_: *mut whiteout_M3TextureLayer,
26075        ) -> *mut whiteout_M3AnimRefVector3f;
26076        pub fn whiteout_m3_M3TextureLayer_set_uvAngle(
26077            self_: *mut whiteout_M3TextureLayer,
26078            value: *const whiteout_M3AnimRefVector3f,
26079        );
26080        pub fn whiteout_m3_M3TextureLayer_get_uvTiling(
26081            self_: *mut whiteout_M3TextureLayer,
26082        ) -> *mut whiteout_M3AnimRefVector2f;
26083        pub fn whiteout_m3_M3TextureLayer_set_uvTiling(
26084            self_: *mut whiteout_M3TextureLayer,
26085            value: *const whiteout_M3AnimRefVector2f,
26086        );
26087        pub fn whiteout_m3_M3TextureLayer_get_wOffset(
26088            self_: *mut whiteout_M3TextureLayer,
26089        ) -> *mut whiteout_M3AnimRefF32;
26090        pub fn whiteout_m3_M3TextureLayer_set_wOffset(
26091            self_: *mut whiteout_M3TextureLayer,
26092            value: *const whiteout_M3AnimRefF32,
26093        );
26094        pub fn whiteout_m3_M3TextureLayer_get_wTiling(
26095            self_: *mut whiteout_M3TextureLayer,
26096        ) -> *mut whiteout_M3AnimRefF32;
26097        pub fn whiteout_m3_M3TextureLayer_set_wTiling(
26098            self_: *mut whiteout_M3TextureLayer,
26099            value: *const whiteout_M3AnimRefF32,
26100        );
26101        pub fn whiteout_m3_M3TextureLayer_get_mapAlpha(
26102            self_: *mut whiteout_M3TextureLayer,
26103        ) -> *mut whiteout_M3AnimRefF32;
26104        pub fn whiteout_m3_M3TextureLayer_set_mapAlpha(
26105            self_: *mut whiteout_M3TextureLayer,
26106            value: *const whiteout_M3AnimRefF32,
26107        );
26108        pub fn whiteout_m3_M3TextureLayer_get_triplanarOffset(
26109            self_: *mut whiteout_M3TextureLayer,
26110        ) -> *mut whiteout_M3AnimRefVector3f;
26111        pub fn whiteout_m3_M3TextureLayer_set_triplanarOffset(
26112            self_: *mut whiteout_M3TextureLayer,
26113            value: *const whiteout_M3AnimRefVector3f,
26114        );
26115        pub fn whiteout_m3_M3TextureLayer_get_triplanarScale(
26116            self_: *mut whiteout_M3TextureLayer,
26117        ) -> *mut whiteout_M3AnimRefVector3f;
26118        pub fn whiteout_m3_M3TextureLayer_set_triplanarScale(
26119            self_: *mut whiteout_M3TextureLayer,
26120            value: *const whiteout_M3AnimRefVector3f,
26121        );
26122        pub fn whiteout_m3_M3TextureLayer_get_uvSourceRelated(
26123            self_: *mut whiteout_M3TextureLayer,
26124        ) -> u32;
26125        pub fn whiteout_m3_M3TextureLayer_set_uvSourceRelated(
26126            self_: *mut whiteout_M3TextureLayer,
26127            value: u32,
26128        );
26129        pub fn whiteout_m3_M3TextureLayer_get_fresnelMode(
26130            self_: *mut whiteout_M3TextureLayer,
26131        ) -> i32;
26132        pub fn whiteout_m3_M3TextureLayer_set_fresnelMode(
26133            self_: *mut whiteout_M3TextureLayer,
26134            value: i32,
26135        );
26136        pub fn whiteout_m3_M3TextureLayer_get_fresnelExponent(
26137            self_: *mut whiteout_M3TextureLayer,
26138        ) -> f32;
26139        pub fn whiteout_m3_M3TextureLayer_set_fresnelExponent(
26140            self_: *mut whiteout_M3TextureLayer,
26141            value: f32,
26142        );
26143        pub fn whiteout_m3_M3TextureLayer_get_fresnelMin(
26144            self_: *mut whiteout_M3TextureLayer,
26145        ) -> f32;
26146        pub fn whiteout_m3_M3TextureLayer_set_fresnelMin(
26147            self_: *mut whiteout_M3TextureLayer,
26148            value: f32,
26149        );
26150        pub fn whiteout_m3_M3TextureLayer_get_fresnelMax(
26151            self_: *mut whiteout_M3TextureLayer,
26152        ) -> f32;
26153        pub fn whiteout_m3_M3TextureLayer_set_fresnelMax(
26154            self_: *mut whiteout_M3TextureLayer,
26155            value: f32,
26156        );
26157        pub fn whiteout_m3_M3TextureLayer_get_fresnelTranslation(
26158            self_: *mut whiteout_M3TextureLayer,
26159        ) -> *mut core::ffi::c_void;
26160        pub fn whiteout_m3_M3TextureLayer_set_fresnelTranslation(
26161            self_: *mut whiteout_M3TextureLayer,
26162            value: *const core::ffi::c_void,
26163        );
26164        pub fn whiteout_m3_M3TextureLayer_get_fresnelMask(
26165            self_: *mut whiteout_M3TextureLayer,
26166        ) -> *mut core::ffi::c_void;
26167        pub fn whiteout_m3_M3TextureLayer_set_fresnelMask(
26168            self_: *mut whiteout_M3TextureLayer,
26169            value: *const core::ffi::c_void,
26170        );
26171        pub fn whiteout_m3_M3TextureLayer_get_fresnelRotation(
26172            self_: *mut whiteout_M3TextureLayer,
26173        ) -> *mut core::ffi::c_void;
26174        pub fn whiteout_m3_M3TextureLayer_set_fresnelRotation(
26175            self_: *mut whiteout_M3TextureLayer,
26176            value: *const core::ffi::c_void,
26177        );
26178        pub fn whiteout_m3_M3TextureLayer_get_uvDensity(self_: *mut whiteout_M3TextureLayer)
26179            -> u32;
26180        pub fn whiteout_m3_M3TextureLayer_set_uvDensity(
26181            self_: *mut whiteout_M3TextureLayer,
26182            value: u32,
26183        );
26184        // StandardMaterial
26185        pub fn whiteout_m3_M3StandardMaterial_new() -> *mut whiteout_M3StandardMaterial;
26186        pub fn whiteout_m3_M3StandardMaterial_delete(self_: *mut whiteout_M3StandardMaterial);
26187        pub fn whiteout_m3_M3StandardMaterial_get_name(
26188            self_: *mut whiteout_M3StandardMaterial,
26189        ) -> RawCString;
26190        pub fn whiteout_m3_M3StandardMaterial_set_name(
26191            self_: *mut whiteout_M3StandardMaterial,
26192            value: *const core::ffi::c_char,
26193        );
26194        pub fn whiteout_m3_M3StandardMaterial_get_additionalFlags(
26195            self_: *mut whiteout_M3StandardMaterial,
26196        ) -> i32;
26197        pub fn whiteout_m3_M3StandardMaterial_set_additionalFlags(
26198            self_: *mut whiteout_M3StandardMaterial,
26199            value: i32,
26200        );
26201        pub fn whiteout_m3_M3StandardMaterial_get_flags(
26202            self_: *mut whiteout_M3StandardMaterial,
26203        ) -> i32;
26204        pub fn whiteout_m3_M3StandardMaterial_set_flags(
26205            self_: *mut whiteout_M3StandardMaterial,
26206            value: i32,
26207        );
26208        pub fn whiteout_m3_M3StandardMaterial_get_blendMode(
26209            self_: *mut whiteout_M3StandardMaterial,
26210        ) -> i32;
26211        pub fn whiteout_m3_M3StandardMaterial_set_blendMode(
26212            self_: *mut whiteout_M3StandardMaterial,
26213            value: i32,
26214        );
26215        pub fn whiteout_m3_M3StandardMaterial_get_priority(
26216            self_: *mut whiteout_M3StandardMaterial,
26217        ) -> i32;
26218        pub fn whiteout_m3_M3StandardMaterial_set_priority(
26219            self_: *mut whiteout_M3StandardMaterial,
26220            value: i32,
26221        );
26222        pub fn whiteout_m3_M3StandardMaterial_get_rttChannels(
26223            self_: *mut whiteout_M3StandardMaterial,
26224        ) -> u32;
26225        pub fn whiteout_m3_M3StandardMaterial_set_rttChannels(
26226            self_: *mut whiteout_M3StandardMaterial,
26227            value: u32,
26228        );
26229        pub fn whiteout_m3_M3StandardMaterial_get_specularExponent(
26230            self_: *mut whiteout_M3StandardMaterial,
26231        ) -> f32;
26232        pub fn whiteout_m3_M3StandardMaterial_set_specularExponent(
26233            self_: *mut whiteout_M3StandardMaterial,
26234            value: f32,
26235        );
26236        pub fn whiteout_m3_M3StandardMaterial_get_depthBlendFalloff(
26237            self_: *mut whiteout_M3StandardMaterial,
26238        ) -> f32;
26239        pub fn whiteout_m3_M3StandardMaterial_set_depthBlendFalloff(
26240            self_: *mut whiteout_M3StandardMaterial,
26241            value: f32,
26242        );
26243        pub fn whiteout_m3_M3StandardMaterial_get_alphaTestThreshold(
26244            self_: *mut whiteout_M3StandardMaterial,
26245        ) -> u32;
26246        pub fn whiteout_m3_M3StandardMaterial_set_alphaTestThreshold(
26247            self_: *mut whiteout_M3StandardMaterial,
26248            value: u32,
26249        );
26250        pub fn whiteout_m3_M3StandardMaterial_get_hdrSpecularMultiplier(
26251            self_: *mut whiteout_M3StandardMaterial,
26252        ) -> f32;
26253        pub fn whiteout_m3_M3StandardMaterial_set_hdrSpecularMultiplier(
26254            self_: *mut whiteout_M3StandardMaterial,
26255            value: f32,
26256        );
26257        pub fn whiteout_m3_M3StandardMaterial_get_hdrEmissiveMultiplier(
26258            self_: *mut whiteout_M3StandardMaterial,
26259        ) -> f32;
26260        pub fn whiteout_m3_M3StandardMaterial_set_hdrEmissiveMultiplier(
26261            self_: *mut whiteout_M3StandardMaterial,
26262            value: f32,
26263        );
26264        pub fn whiteout_m3_M3StandardMaterial_get_hdrEnvironmentConstant(
26265            self_: *mut whiteout_M3StandardMaterial,
26266        ) -> f32;
26267        pub fn whiteout_m3_M3StandardMaterial_set_hdrEnvironmentConstant(
26268            self_: *mut whiteout_M3StandardMaterial,
26269            value: f32,
26270        );
26271        pub fn whiteout_m3_M3StandardMaterial_get_hdrEnvironmentDiffuse(
26272            self_: *mut whiteout_M3StandardMaterial,
26273        ) -> f32;
26274        pub fn whiteout_m3_M3StandardMaterial_set_hdrEnvironmentDiffuse(
26275            self_: *mut whiteout_M3StandardMaterial,
26276            value: f32,
26277        );
26278        pub fn whiteout_m3_M3StandardMaterial_get_hdrEnvironmentSpecular(
26279            self_: *mut whiteout_M3StandardMaterial,
26280        ) -> f32;
26281        pub fn whiteout_m3_M3StandardMaterial_set_hdrEnvironmentSpecular(
26282            self_: *mut whiteout_M3StandardMaterial,
26283            value: f32,
26284        );
26285        pub fn whiteout_m3_M3StandardMaterial_get_materialClass(
26286            self_: *mut whiteout_M3StandardMaterial,
26287        ) -> i32;
26288        pub fn whiteout_m3_M3StandardMaterial_set_materialClass(
26289            self_: *mut whiteout_M3StandardMaterial,
26290            value: i32,
26291        );
26292        pub fn whiteout_m3_M3StandardMaterial_get_layerBlendMode(
26293            self_: *mut whiteout_M3StandardMaterial,
26294        ) -> i32;
26295        pub fn whiteout_m3_M3StandardMaterial_set_layerBlendMode(
26296            self_: *mut whiteout_M3StandardMaterial,
26297            value: i32,
26298        );
26299        pub fn whiteout_m3_M3StandardMaterial_get_emissiveBlendMode1(
26300            self_: *mut whiteout_M3StandardMaterial,
26301        ) -> i32;
26302        pub fn whiteout_m3_M3StandardMaterial_set_emissiveBlendMode1(
26303            self_: *mut whiteout_M3StandardMaterial,
26304            value: i32,
26305        );
26306        pub fn whiteout_m3_M3StandardMaterial_get_emissiveBlendMode2(
26307            self_: *mut whiteout_M3StandardMaterial,
26308        ) -> i32;
26309        pub fn whiteout_m3_M3StandardMaterial_set_emissiveBlendMode2(
26310            self_: *mut whiteout_M3StandardMaterial,
26311            value: i32,
26312        );
26313        pub fn whiteout_m3_M3StandardMaterial_get_specularMode(
26314            self_: *mut whiteout_M3StandardMaterial,
26315        ) -> i32;
26316        pub fn whiteout_m3_M3StandardMaterial_set_specularMode(
26317            self_: *mut whiteout_M3StandardMaterial,
26318            value: i32,
26319        );
26320        pub fn whiteout_m3_M3StandardMaterial_get_parallaxHeight(
26321            self_: *mut whiteout_M3StandardMaterial,
26322        ) -> *mut whiteout_M3AnimRefF32;
26323        pub fn whiteout_m3_M3StandardMaterial_set_parallaxHeight(
26324            self_: *mut whiteout_M3StandardMaterial,
26325            value: *const whiteout_M3AnimRefF32,
26326        );
26327        pub fn whiteout_m3_M3StandardMaterial_get_motionBlurAmount(
26328            self_: *mut whiteout_M3StandardMaterial,
26329        ) -> *mut whiteout_M3AnimRefF32;
26330        pub fn whiteout_m3_M3StandardMaterial_set_motionBlurAmount(
26331            self_: *mut whiteout_M3StandardMaterial,
26332            value: *const whiteout_M3AnimRefF32,
26333        );
26334        pub fn whiteout_m3_M3StandardMaterial_get_normalBlendFactors_count(
26335            self_: *mut whiteout_M3StandardMaterial,
26336        ) -> usize;
26337        pub fn whiteout_m3_M3StandardMaterial_resize_normalBlendFactors(
26338            self_: *mut whiteout_M3StandardMaterial,
26339            count: usize,
26340        );
26341        pub fn whiteout_m3_M3StandardMaterial_get_normalBlendFactors_at(
26342            self_: *mut whiteout_M3StandardMaterial,
26343            index: usize,
26344        ) -> *mut whiteout_M3AnimRefF32;
26345        // DisplacementMaterial
26346        pub fn whiteout_m3_M3DisplacementMaterial_new() -> *mut whiteout_M3DisplacementMaterial;
26347        pub fn whiteout_m3_M3DisplacementMaterial_delete(
26348            self_: *mut whiteout_M3DisplacementMaterial,
26349        );
26350        pub fn whiteout_m3_M3DisplacementMaterial_get_name(
26351            self_: *mut whiteout_M3DisplacementMaterial,
26352        ) -> RawCString;
26353        pub fn whiteout_m3_M3DisplacementMaterial_set_name(
26354            self_: *mut whiteout_M3DisplacementMaterial,
26355            value: *const core::ffi::c_char,
26356        );
26357        pub fn whiteout_m3_M3DisplacementMaterial_get_unknown(
26358            self_: *mut whiteout_M3DisplacementMaterial,
26359        ) -> u32;
26360        pub fn whiteout_m3_M3DisplacementMaterial_set_unknown(
26361            self_: *mut whiteout_M3DisplacementMaterial,
26362            value: u32,
26363        );
26364        pub fn whiteout_m3_M3DisplacementMaterial_get_strength(
26365            self_: *mut whiteout_M3DisplacementMaterial,
26366        ) -> *mut whiteout_M3AnimRefF32;
26367        pub fn whiteout_m3_M3DisplacementMaterial_set_strength(
26368            self_: *mut whiteout_M3DisplacementMaterial,
26369            value: *const whiteout_M3AnimRefF32,
26370        );
26371        pub fn whiteout_m3_M3DisplacementMaterial_get_priority(
26372            self_: *mut whiteout_M3DisplacementMaterial,
26373        ) -> u32;
26374        pub fn whiteout_m3_M3DisplacementMaterial_set_priority(
26375            self_: *mut whiteout_M3DisplacementMaterial,
26376            value: u32,
26377        );
26378        // CompositeSection
26379        pub fn whiteout_m3_M3CompositeSection_new() -> *mut whiteout_M3CompositeSection;
26380        pub fn whiteout_m3_M3CompositeSection_delete(self_: *mut whiteout_M3CompositeSection);
26381        pub fn whiteout_m3_M3CompositeSection_get_materialIndex(
26382            self_: *mut whiteout_M3CompositeSection,
26383        ) -> u32;
26384        pub fn whiteout_m3_M3CompositeSection_set_materialIndex(
26385            self_: *mut whiteout_M3CompositeSection,
26386            value: u32,
26387        );
26388        pub fn whiteout_m3_M3CompositeSection_get_mapMultiplier(
26389            self_: *mut whiteout_M3CompositeSection,
26390        ) -> *mut whiteout_M3AnimRefF32;
26391        pub fn whiteout_m3_M3CompositeSection_set_mapMultiplier(
26392            self_: *mut whiteout_M3CompositeSection,
26393            value: *const whiteout_M3AnimRefF32,
26394        );
26395        // CompositeMaterial
26396        pub fn whiteout_m3_M3CompositeMaterial_new() -> *mut whiteout_M3CompositeMaterial;
26397        pub fn whiteout_m3_M3CompositeMaterial_delete(self_: *mut whiteout_M3CompositeMaterial);
26398        pub fn whiteout_m3_M3CompositeMaterial_get_name(
26399            self_: *mut whiteout_M3CompositeMaterial,
26400        ) -> RawCString;
26401        pub fn whiteout_m3_M3CompositeMaterial_set_name(
26402            self_: *mut whiteout_M3CompositeMaterial,
26403            value: *const core::ffi::c_char,
26404        );
26405        pub fn whiteout_m3_M3CompositeMaterial_get_priority(
26406            self_: *mut whiteout_M3CompositeMaterial,
26407        ) -> u32;
26408        pub fn whiteout_m3_M3CompositeMaterial_set_priority(
26409            self_: *mut whiteout_M3CompositeMaterial,
26410            value: u32,
26411        );
26412        pub fn whiteout_m3_M3CompositeMaterial_get_sections_count(
26413            self_: *mut whiteout_M3CompositeMaterial,
26414        ) -> usize;
26415        pub fn whiteout_m3_M3CompositeMaterial_resize_sections(
26416            self_: *mut whiteout_M3CompositeMaterial,
26417            count: usize,
26418        );
26419        pub fn whiteout_m3_M3CompositeMaterial_get_sections_at(
26420            self_: *mut whiteout_M3CompositeMaterial,
26421            index: usize,
26422        ) -> *mut whiteout_M3CompositeSection;
26423        // TerrainMaterial
26424        pub fn whiteout_m3_M3TerrainMaterial_new() -> *mut whiteout_M3TerrainMaterial;
26425        pub fn whiteout_m3_M3TerrainMaterial_delete(self_: *mut whiteout_M3TerrainMaterial);
26426        pub fn whiteout_m3_M3TerrainMaterial_get_name(
26427            self_: *mut whiteout_M3TerrainMaterial,
26428        ) -> RawCString;
26429        pub fn whiteout_m3_M3TerrainMaterial_set_name(
26430            self_: *mut whiteout_M3TerrainMaterial,
26431            value: *const core::ffi::c_char,
26432        );
26433        pub fn whiteout_m3_M3TerrainMaterial_get_unknown(
26434            self_: *mut whiteout_M3TerrainMaterial,
26435        ) -> u32;
26436        pub fn whiteout_m3_M3TerrainMaterial_set_unknown(
26437            self_: *mut whiteout_M3TerrainMaterial,
26438            value: u32,
26439        );
26440        // VolumeMaterial
26441        pub fn whiteout_m3_M3VolumeMaterial_new() -> *mut whiteout_M3VolumeMaterial;
26442        pub fn whiteout_m3_M3VolumeMaterial_delete(self_: *mut whiteout_M3VolumeMaterial);
26443        pub fn whiteout_m3_M3VolumeMaterial_get_name(
26444            self_: *mut whiteout_M3VolumeMaterial,
26445        ) -> RawCString;
26446        pub fn whiteout_m3_M3VolumeMaterial_set_name(
26447            self_: *mut whiteout_M3VolumeMaterial,
26448            value: *const core::ffi::c_char,
26449        );
26450        pub fn whiteout_m3_M3VolumeMaterial_get_blendMode(
26451            self_: *mut whiteout_M3VolumeMaterial,
26452        ) -> u32;
26453        pub fn whiteout_m3_M3VolumeMaterial_set_blendMode(
26454            self_: *mut whiteout_M3VolumeMaterial,
26455            value: u32,
26456        );
26457        pub fn whiteout_m3_M3VolumeMaterial_get_falloffType(
26458            self_: *mut whiteout_M3VolumeMaterial,
26459        ) -> i32;
26460        pub fn whiteout_m3_M3VolumeMaterial_set_falloffType(
26461            self_: *mut whiteout_M3VolumeMaterial,
26462            value: i32,
26463        );
26464        pub fn whiteout_m3_M3VolumeMaterial_get_density(
26465            self_: *mut whiteout_M3VolumeMaterial,
26466        ) -> *mut whiteout_M3AnimRefF32;
26467        pub fn whiteout_m3_M3VolumeMaterial_set_density(
26468            self_: *mut whiteout_M3VolumeMaterial,
26469            value: *const whiteout_M3AnimRefF32,
26470        );
26471        pub fn whiteout_m3_M3VolumeMaterial_get_alphaThreshold(
26472            self_: *mut whiteout_M3VolumeMaterial,
26473        ) -> u32;
26474        pub fn whiteout_m3_M3VolumeMaterial_set_alphaThreshold(
26475            self_: *mut whiteout_M3VolumeMaterial,
26476            value: u32,
26477        );
26478        // HairMaterial
26479        pub fn whiteout_m3_M3HairMaterial_new() -> *mut whiteout_M3HairMaterial;
26480        pub fn whiteout_m3_M3HairMaterial_delete(self_: *mut whiteout_M3HairMaterial);
26481        pub fn whiteout_m3_M3HairMaterial_get_name(
26482            self_: *mut whiteout_M3HairMaterial,
26483        ) -> RawCString;
26484        pub fn whiteout_m3_M3HairMaterial_set_name(
26485            self_: *mut whiteout_M3HairMaterial,
26486            value: *const core::ffi::c_char,
26487        );
26488        pub fn whiteout_m3_M3HairMaterial_get_shiftPrimary(
26489            self_: *mut whiteout_M3HairMaterial,
26490        ) -> f32;
26491        pub fn whiteout_m3_M3HairMaterial_set_shiftPrimary(
26492            self_: *mut whiteout_M3HairMaterial,
26493            value: f32,
26494        );
26495        pub fn whiteout_m3_M3HairMaterial_get_shiftSecondary(
26496            self_: *mut whiteout_M3HairMaterial,
26497        ) -> f32;
26498        pub fn whiteout_m3_M3HairMaterial_set_shiftSecondary(
26499            self_: *mut whiteout_M3HairMaterial,
26500            value: f32,
26501        );
26502        pub fn whiteout_m3_M3HairMaterial_get_colorDiffuse(
26503            self_: *mut whiteout_M3HairMaterial,
26504        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
26505        pub fn whiteout_m3_M3HairMaterial_set_colorDiffuse(
26506            self_: *mut whiteout_M3HairMaterial,
26507            value: *const whiteout_M3AnimRefM3ColorBGRA,
26508        );
26509        pub fn whiteout_m3_M3HairMaterial_get_colorSpec(
26510            self_: *mut whiteout_M3HairMaterial,
26511        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
26512        pub fn whiteout_m3_M3HairMaterial_set_colorSpec(
26513            self_: *mut whiteout_M3HairMaterial,
26514            value: *const whiteout_M3AnimRefM3ColorBGRA,
26515        );
26516        pub fn whiteout_m3_M3HairMaterial_get_specExponent0(
26517            self_: *mut whiteout_M3HairMaterial,
26518        ) -> f32;
26519        pub fn whiteout_m3_M3HairMaterial_set_specExponent0(
26520            self_: *mut whiteout_M3HairMaterial,
26521            value: f32,
26522        );
26523        pub fn whiteout_m3_M3HairMaterial_get_specExponent1(
26524            self_: *mut whiteout_M3HairMaterial,
26525        ) -> f32;
26526        pub fn whiteout_m3_M3HairMaterial_set_specExponent1(
26527            self_: *mut whiteout_M3HairMaterial,
26528            value: f32,
26529        );
26530        // VolumeNoiseMaterial
26531        pub fn whiteout_m3_M3VolumeNoiseMaterial_new() -> *mut whiteout_M3VolumeNoiseMaterial;
26532        pub fn whiteout_m3_M3VolumeNoiseMaterial_delete(self_: *mut whiteout_M3VolumeNoiseMaterial);
26533        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_name(
26534            self_: *mut whiteout_M3VolumeNoiseMaterial,
26535        ) -> RawCString;
26536        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_name(
26537            self_: *mut whiteout_M3VolumeNoiseMaterial,
26538            value: *const core::ffi::c_char,
26539        );
26540        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_falloffType(
26541            self_: *mut whiteout_M3VolumeNoiseMaterial,
26542        ) -> i32;
26543        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_falloffType(
26544            self_: *mut whiteout_M3VolumeNoiseMaterial,
26545            value: i32,
26546        );
26547        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_drawTransparency(
26548            self_: *mut whiteout_M3VolumeNoiseMaterial,
26549        ) -> i32;
26550        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_drawTransparency(
26551            self_: *mut whiteout_M3VolumeNoiseMaterial,
26552            value: i32,
26553        );
26554        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_density(
26555            self_: *mut whiteout_M3VolumeNoiseMaterial,
26556        ) -> *mut whiteout_M3AnimRefF32;
26557        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_density(
26558            self_: *mut whiteout_M3VolumeNoiseMaterial,
26559            value: *const whiteout_M3AnimRefF32,
26560        );
26561        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_nearPlane(
26562            self_: *mut whiteout_M3VolumeNoiseMaterial,
26563        ) -> *mut whiteout_M3AnimRefF32;
26564        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_nearPlane(
26565            self_: *mut whiteout_M3VolumeNoiseMaterial,
26566            value: *const whiteout_M3AnimRefF32,
26567        );
26568        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_falloff(
26569            self_: *mut whiteout_M3VolumeNoiseMaterial,
26570        ) -> *mut whiteout_M3AnimRefF32;
26571        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_falloff(
26572            self_: *mut whiteout_M3VolumeNoiseMaterial,
26573            value: *const whiteout_M3AnimRefF32,
26574        );
26575        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_scrollRate(
26576            self_: *mut whiteout_M3VolumeNoiseMaterial,
26577        ) -> *mut whiteout_M3AnimRefVector3f;
26578        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_scrollRate(
26579            self_: *mut whiteout_M3VolumeNoiseMaterial,
26580            value: *const whiteout_M3AnimRefVector3f,
26581        );
26582        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_position(
26583            self_: *mut whiteout_M3VolumeNoiseMaterial,
26584        ) -> *mut whiteout_M3AnimRefVector3f;
26585        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_position(
26586            self_: *mut whiteout_M3VolumeNoiseMaterial,
26587            value: *const whiteout_M3AnimRefVector3f,
26588        );
26589        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_scale(
26590            self_: *mut whiteout_M3VolumeNoiseMaterial,
26591        ) -> *mut whiteout_M3AnimRefVector3f;
26592        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_scale(
26593            self_: *mut whiteout_M3VolumeNoiseMaterial,
26594            value: *const whiteout_M3AnimRefVector3f,
26595        );
26596        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_rotation(
26597            self_: *mut whiteout_M3VolumeNoiseMaterial,
26598        ) -> *mut whiteout_M3AnimRefVector3f;
26599        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_rotation(
26600            self_: *mut whiteout_M3VolumeNoiseMaterial,
26601            value: *const whiteout_M3AnimRefVector3f,
26602        );
26603        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_alphaThreshold(
26604            self_: *mut whiteout_M3VolumeNoiseMaterial,
26605        ) -> u32;
26606        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_alphaThreshold(
26607            self_: *mut whiteout_M3VolumeNoiseMaterial,
26608            value: u32,
26609        );
26610        pub fn whiteout_m3_M3VolumeNoiseMaterial_get_flags(
26611            self_: *mut whiteout_M3VolumeNoiseMaterial,
26612        ) -> i32;
26613        pub fn whiteout_m3_M3VolumeNoiseMaterial_set_flags(
26614            self_: *mut whiteout_M3VolumeNoiseMaterial,
26615            value: i32,
26616        );
26617        // CreepMaterial
26618        pub fn whiteout_m3_M3CreepMaterial_new() -> *mut whiteout_M3CreepMaterial;
26619        pub fn whiteout_m3_M3CreepMaterial_delete(self_: *mut whiteout_M3CreepMaterial);
26620        pub fn whiteout_m3_M3CreepMaterial_get_name(
26621            self_: *mut whiteout_M3CreepMaterial,
26622        ) -> RawCString;
26623        pub fn whiteout_m3_M3CreepMaterial_set_name(
26624            self_: *mut whiteout_M3CreepMaterial,
26625            value: *const core::ffi::c_char,
26626        );
26627        pub fn whiteout_m3_M3CreepMaterial_get_creepLow(
26628            self_: *mut whiteout_M3CreepMaterial,
26629        ) -> u32;
26630        pub fn whiteout_m3_M3CreepMaterial_set_creepLow(
26631            self_: *mut whiteout_M3CreepMaterial,
26632            value: u32,
26633        );
26634        // STBMaterial
26635        pub fn whiteout_m3_M3STBMaterial_new() -> *mut whiteout_M3STBMaterial;
26636        pub fn whiteout_m3_M3STBMaterial_delete(self_: *mut whiteout_M3STBMaterial);
26637        pub fn whiteout_m3_M3STBMaterial_get_name(self_: *mut whiteout_M3STBMaterial)
26638            -> RawCString;
26639        pub fn whiteout_m3_M3STBMaterial_set_name(
26640            self_: *mut whiteout_M3STBMaterial,
26641            value: *const core::ffi::c_char,
26642        );
26643        // ReflectionMaterial
26644        pub fn whiteout_m3_M3ReflectionMaterial_new() -> *mut whiteout_M3ReflectionMaterial;
26645        pub fn whiteout_m3_M3ReflectionMaterial_delete(self_: *mut whiteout_M3ReflectionMaterial);
26646        pub fn whiteout_m3_M3ReflectionMaterial_get_name(
26647            self_: *mut whiteout_M3ReflectionMaterial,
26648        ) -> RawCString;
26649        pub fn whiteout_m3_M3ReflectionMaterial_set_name(
26650            self_: *mut whiteout_M3ReflectionMaterial,
26651            value: *const core::ffi::c_char,
26652        );
26653        pub fn whiteout_m3_M3ReflectionMaterial_get_unknown(
26654            self_: *mut whiteout_M3ReflectionMaterial,
26655        ) -> u32;
26656        pub fn whiteout_m3_M3ReflectionMaterial_set_unknown(
26657            self_: *mut whiteout_M3ReflectionMaterial,
26658            value: u32,
26659        );
26660        pub fn whiteout_m3_M3ReflectionMaterial_get_reflectionStrength(
26661            self_: *mut whiteout_M3ReflectionMaterial,
26662        ) -> *mut whiteout_M3AnimRefF32;
26663        pub fn whiteout_m3_M3ReflectionMaterial_set_reflectionStrength(
26664            self_: *mut whiteout_M3ReflectionMaterial,
26665            value: *const whiteout_M3AnimRefF32,
26666        );
26667        pub fn whiteout_m3_M3ReflectionMaterial_get_displacementStrength(
26668            self_: *mut whiteout_M3ReflectionMaterial,
26669        ) -> *mut whiteout_M3AnimRefF32;
26670        pub fn whiteout_m3_M3ReflectionMaterial_set_displacementStrength(
26671            self_: *mut whiteout_M3ReflectionMaterial,
26672            value: *const whiteout_M3AnimRefF32,
26673        );
26674        pub fn whiteout_m3_M3ReflectionMaterial_get_reflectionOffset(
26675            self_: *mut whiteout_M3ReflectionMaterial,
26676        ) -> *mut whiteout_M3AnimRefF32;
26677        pub fn whiteout_m3_M3ReflectionMaterial_set_reflectionOffset(
26678            self_: *mut whiteout_M3ReflectionMaterial,
26679            value: *const whiteout_M3AnimRefF32,
26680        );
26681        pub fn whiteout_m3_M3ReflectionMaterial_get_blurAngle(
26682            self_: *mut whiteout_M3ReflectionMaterial,
26683        ) -> *mut whiteout_M3AnimRefF32;
26684        pub fn whiteout_m3_M3ReflectionMaterial_set_blurAngle(
26685            self_: *mut whiteout_M3ReflectionMaterial,
26686            value: *const whiteout_M3AnimRefF32,
26687        );
26688        pub fn whiteout_m3_M3ReflectionMaterial_get_blurDistanceMax(
26689            self_: *mut whiteout_M3ReflectionMaterial,
26690        ) -> *mut whiteout_M3AnimRefF32;
26691        pub fn whiteout_m3_M3ReflectionMaterial_set_blurDistanceMax(
26692            self_: *mut whiteout_M3ReflectionMaterial,
26693            value: *const whiteout_M3AnimRefF32,
26694        );
26695        pub fn whiteout_m3_M3ReflectionMaterial_get_flags(
26696            self_: *mut whiteout_M3ReflectionMaterial,
26697        ) -> i32;
26698        pub fn whiteout_m3_M3ReflectionMaterial_set_flags(
26699            self_: *mut whiteout_M3ReflectionMaterial,
26700            value: i32,
26701        );
26702        pub fn whiteout_m3_M3ReflectionMaterial_get_unknown2(
26703            self_: *mut whiteout_M3ReflectionMaterial,
26704        ) -> u32;
26705        pub fn whiteout_m3_M3ReflectionMaterial_set_unknown2(
26706            self_: *mut whiteout_M3ReflectionMaterial,
26707            value: u32,
26708        );
26709        // SubFlare
26710        pub fn whiteout_m3_M3SubFlare_new() -> *mut whiteout_M3SubFlare;
26711        pub fn whiteout_m3_M3SubFlare_delete(self_: *mut whiteout_M3SubFlare);
26712        pub fn whiteout_m3_M3SubFlare_get_index(self_: *mut whiteout_M3SubFlare) -> u32;
26713        pub fn whiteout_m3_M3SubFlare_set_index(self_: *mut whiteout_M3SubFlare, value: u32);
26714        pub fn whiteout_m3_M3SubFlare_get_position(self_: *mut whiteout_M3SubFlare) -> f32;
26715        pub fn whiteout_m3_M3SubFlare_set_position(self_: *mut whiteout_M3SubFlare, value: f32);
26716        pub fn whiteout_m3_M3SubFlare_get_sizeXY(
26717            self_: *mut whiteout_M3SubFlare,
26718        ) -> *mut core::ffi::c_void;
26719        pub fn whiteout_m3_M3SubFlare_set_sizeXY(
26720            self_: *mut whiteout_M3SubFlare,
26721            value: *const core::ffi::c_void,
26722        );
26723        pub fn whiteout_m3_M3SubFlare_get_scaleXY(
26724            self_: *mut whiteout_M3SubFlare,
26725        ) -> *mut core::ffi::c_void;
26726        pub fn whiteout_m3_M3SubFlare_set_scaleXY(
26727            self_: *mut whiteout_M3SubFlare,
26728            value: *const core::ffi::c_void,
26729        );
26730        pub fn whiteout_m3_M3SubFlare_get_fadeIn(
26731            self_: *mut whiteout_M3SubFlare,
26732        ) -> *mut core::ffi::c_void;
26733        pub fn whiteout_m3_M3SubFlare_set_fadeIn(
26734            self_: *mut whiteout_M3SubFlare,
26735            value: *const core::ffi::c_void,
26736        );
26737        pub fn whiteout_m3_M3SubFlare_get_fadeOut(
26738            self_: *mut whiteout_M3SubFlare,
26739        ) -> *mut core::ffi::c_void;
26740        pub fn whiteout_m3_M3SubFlare_set_fadeOut(
26741            self_: *mut whiteout_M3SubFlare,
26742            value: *const core::ffi::c_void,
26743        );
26744        pub fn whiteout_m3_M3SubFlare_get_colorAlpha(
26745            self_: *mut whiteout_M3SubFlare,
26746        ) -> *mut whiteout_M3ColorBGRA;
26747        pub fn whiteout_m3_M3SubFlare_set_colorAlpha(
26748            self_: *mut whiteout_M3SubFlare,
26749            value: *const whiteout_M3ColorBGRA,
26750        );
26751        pub fn whiteout_m3_M3SubFlare_get_faceCenter(self_: *mut whiteout_M3SubFlare) -> u32;
26752        pub fn whiteout_m3_M3SubFlare_set_faceCenter(self_: *mut whiteout_M3SubFlare, value: u32);
26753        pub fn whiteout_m3_M3SubFlare_get_offset(
26754            self_: *mut whiteout_M3SubFlare,
26755        ) -> *mut core::ffi::c_void;
26756        pub fn whiteout_m3_M3SubFlare_set_offset(
26757            self_: *mut whiteout_M3SubFlare,
26758            value: *const core::ffi::c_void,
26759        );
26760        // LensFlare
26761        pub fn whiteout_m3_M3LensFlare_new() -> *mut whiteout_M3LensFlare;
26762        pub fn whiteout_m3_M3LensFlare_delete(self_: *mut whiteout_M3LensFlare);
26763        pub fn whiteout_m3_M3LensFlare_get_name(self_: *mut whiteout_M3LensFlare) -> RawCString;
26764        pub fn whiteout_m3_M3LensFlare_set_name(
26765            self_: *mut whiteout_M3LensFlare,
26766            value: *const core::ffi::c_char,
26767        );
26768        pub fn whiteout_m3_M3LensFlare_get_subFlares_count(
26769            self_: *mut whiteout_M3LensFlare,
26770        ) -> usize;
26771        pub fn whiteout_m3_M3LensFlare_resize_subFlares(
26772            self_: *mut whiteout_M3LensFlare,
26773            count: usize,
26774        );
26775        pub fn whiteout_m3_M3LensFlare_get_subFlares_at(
26776            self_: *mut whiteout_M3LensFlare,
26777            index: usize,
26778        ) -> *mut whiteout_M3SubFlare;
26779        pub fn whiteout_m3_M3LensFlare_get_columns(self_: *mut whiteout_M3LensFlare) -> u32;
26780        pub fn whiteout_m3_M3LensFlare_set_columns(self_: *mut whiteout_M3LensFlare, value: u32);
26781        pub fn whiteout_m3_M3LensFlare_get_rows(self_: *mut whiteout_M3LensFlare) -> u32;
26782        pub fn whiteout_m3_M3LensFlare_set_rows(self_: *mut whiteout_M3LensFlare, value: u32);
26783        pub fn whiteout_m3_M3LensFlare_get_distanceFade(self_: *mut whiteout_M3LensFlare) -> f32;
26784        pub fn whiteout_m3_M3LensFlare_set_distanceFade(
26785            self_: *mut whiteout_M3LensFlare,
26786            value: f32,
26787        );
26788        pub fn whiteout_m3_M3LensFlare_get_libName(self_: *mut whiteout_M3LensFlare) -> RawCString;
26789        pub fn whiteout_m3_M3LensFlare_set_libName(
26790            self_: *mut whiteout_M3LensFlare,
26791            value: *const core::ffi::c_char,
26792        );
26793        pub fn whiteout_m3_M3LensFlare_get_intensity(
26794            self_: *mut whiteout_M3LensFlare,
26795        ) -> *mut whiteout_M3AnimRefF32;
26796        pub fn whiteout_m3_M3LensFlare_set_intensity(
26797            self_: *mut whiteout_M3LensFlare,
26798            value: *const whiteout_M3AnimRefF32,
26799        );
26800        pub fn whiteout_m3_M3LensFlare_get_color(
26801            self_: *mut whiteout_M3LensFlare,
26802        ) -> *mut whiteout_M3AnimRefM3ColorBGRA;
26803        pub fn whiteout_m3_M3LensFlare_set_color(
26804            self_: *mut whiteout_M3LensFlare,
26805            value: *const whiteout_M3AnimRefM3ColorBGRA,
26806        );
26807        pub fn whiteout_m3_M3LensFlare_get_hdr(
26808            self_: *mut whiteout_M3LensFlare,
26809        ) -> *mut whiteout_M3AnimRefF32;
26810        pub fn whiteout_m3_M3LensFlare_set_hdr(
26811            self_: *mut whiteout_M3LensFlare,
26812            value: *const whiteout_M3AnimRefF32,
26813        );
26814        pub fn whiteout_m3_M3LensFlare_get_size(
26815            self_: *mut whiteout_M3LensFlare,
26816        ) -> *mut whiteout_M3AnimRefF32;
26817        pub fn whiteout_m3_M3LensFlare_set_size(
26818            self_: *mut whiteout_M3LensFlare,
26819            value: *const whiteout_M3AnimRefF32,
26820        );
26821        // DataDrivenProperty
26822        pub fn whiteout_m3_M3DataDrivenProperty_new() -> *mut whiteout_M3DataDrivenProperty;
26823        pub fn whiteout_m3_M3DataDrivenProperty_delete(self_: *mut whiteout_M3DataDrivenProperty);
26824        pub fn whiteout_m3_M3DataDrivenProperty_get_nameHash(
26825            self_: *mut whiteout_M3DataDrivenProperty,
26826        ) -> u32;
26827        pub fn whiteout_m3_M3DataDrivenProperty_set_nameHash(
26828            self_: *mut whiteout_M3DataDrivenProperty,
26829            value: u32,
26830        );
26831        pub fn whiteout_m3_M3DataDrivenProperty_get_name(
26832            self_: *mut whiteout_M3DataDrivenProperty,
26833        ) -> RawCString;
26834        pub fn whiteout_m3_M3DataDrivenProperty_set_name(
26835            self_: *mut whiteout_M3DataDrivenProperty,
26836            value: *const core::ffi::c_char,
26837        );
26838        pub fn whiteout_m3_M3DataDrivenProperty_get_data_count(
26839            self_: *mut whiteout_M3DataDrivenProperty,
26840        ) -> usize;
26841        pub fn whiteout_m3_M3DataDrivenProperty_resize_data(
26842            self_: *mut whiteout_M3DataDrivenProperty,
26843            count: usize,
26844        );
26845        pub fn whiteout_m3_M3DataDrivenProperty_get_data_data(
26846            self_: *mut whiteout_M3DataDrivenProperty,
26847        ) -> *const u8;
26848        pub fn whiteout_m3_M3DataDrivenProperty_assign_data(
26849            self_: *mut whiteout_M3DataDrivenProperty,
26850            data: *const u8,
26851            count: usize,
26852        );
26853        // DataDrivenGroup
26854        pub fn whiteout_m3_M3DataDrivenGroup_new() -> *mut whiteout_M3DataDrivenGroup;
26855        pub fn whiteout_m3_M3DataDrivenGroup_delete(self_: *mut whiteout_M3DataDrivenGroup);
26856        pub fn whiteout_m3_M3DataDrivenGroup_get_nameHash(
26857            self_: *mut whiteout_M3DataDrivenGroup,
26858        ) -> u32;
26859        pub fn whiteout_m3_M3DataDrivenGroup_set_nameHash(
26860            self_: *mut whiteout_M3DataDrivenGroup,
26861            value: u32,
26862        );
26863        pub fn whiteout_m3_M3DataDrivenGroup_get_name(
26864            self_: *mut whiteout_M3DataDrivenGroup,
26865        ) -> RawCString;
26866        pub fn whiteout_m3_M3DataDrivenGroup_set_name(
26867            self_: *mut whiteout_M3DataDrivenGroup,
26868            value: *const core::ffi::c_char,
26869        );
26870        pub fn whiteout_m3_M3DataDrivenGroup_get_properties_count(
26871            self_: *mut whiteout_M3DataDrivenGroup,
26872        ) -> usize;
26873        pub fn whiteout_m3_M3DataDrivenGroup_resize_properties(
26874            self_: *mut whiteout_M3DataDrivenGroup,
26875            count: usize,
26876        );
26877        pub fn whiteout_m3_M3DataDrivenGroup_get_properties_at(
26878            self_: *mut whiteout_M3DataDrivenGroup,
26879            index: usize,
26880        ) -> *mut whiteout_M3DataDrivenProperty;
26881        // DataDrivenProperties
26882        pub fn whiteout_m3_M3DataDrivenProperties_new() -> *mut whiteout_M3DataDrivenProperties;
26883        pub fn whiteout_m3_M3DataDrivenProperties_delete(
26884            self_: *mut whiteout_M3DataDrivenProperties,
26885        );
26886        pub fn whiteout_m3_M3DataDrivenProperties_get_groups_count(
26887            self_: *mut whiteout_M3DataDrivenProperties,
26888        ) -> usize;
26889        pub fn whiteout_m3_M3DataDrivenProperties_resize_groups(
26890            self_: *mut whiteout_M3DataDrivenProperties,
26891            count: usize,
26892        );
26893        pub fn whiteout_m3_M3DataDrivenProperties_get_groups_at(
26894            self_: *mut whiteout_M3DataDrivenProperties,
26895            index: usize,
26896        ) -> *mut whiteout_M3DataDrivenGroup;
26897        // StandardMaterialConversion
26898        pub fn whiteout_m3_M3StandardMaterialConversion_new(
26899        ) -> *mut whiteout_M3StandardMaterialConversion;
26900        pub fn whiteout_m3_M3StandardMaterialConversion_delete(
26901            self_: *mut whiteout_M3StandardMaterialConversion,
26902        );
26903        pub fn whiteout_m3_M3StandardMaterialConversion_get_converted(
26904            self_: *mut whiteout_M3StandardMaterialConversion,
26905        ) -> i32;
26906        pub fn whiteout_m3_M3StandardMaterialConversion_set_converted(
26907            self_: *mut whiteout_M3StandardMaterialConversion,
26908            value: i32,
26909        );
26910        pub fn whiteout_m3_M3StandardMaterialConversion_get_blocker(
26911            self_: *mut whiteout_M3StandardMaterialConversion,
26912        ) -> RawCString;
26913        pub fn whiteout_m3_M3StandardMaterialConversion_set_blocker(
26914            self_: *mut whiteout_M3StandardMaterialConversion,
26915            value: *const core::ffi::c_char,
26916        );
26917        pub fn whiteout_m3_M3StandardMaterialConversion_get_material(
26918            self_: *mut whiteout_M3StandardMaterialConversion,
26919        ) -> *mut whiteout_M3StandardMaterial;
26920        pub fn whiteout_m3_M3StandardMaterialConversion_set_material(
26921            self_: *mut whiteout_M3StandardMaterialConversion,
26922            value: *const whiteout_M3StandardMaterial,
26923        );
26924        // DataDrivenMaterial
26925        pub fn whiteout_m3_M3DataDrivenMaterial_new() -> *mut whiteout_M3DataDrivenMaterial;
26926        pub fn whiteout_m3_M3DataDrivenMaterial_delete(self_: *mut whiteout_M3DataDrivenMaterial);
26927        pub fn whiteout_m3_M3DataDrivenMaterial_get_materialName(
26928            self_: *mut whiteout_M3DataDrivenMaterial,
26929        ) -> RawCString;
26930        pub fn whiteout_m3_M3DataDrivenMaterial_set_materialName(
26931            self_: *mut whiteout_M3DataDrivenMaterial,
26932            value: *const core::ffi::c_char,
26933        );
26934        pub fn whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_count(
26935            self_: *mut whiteout_M3DataDrivenMaterial,
26936        ) -> usize;
26937        pub fn whiteout_m3_M3DataDrivenMaterial_resize_fragmentHashes(
26938            self_: *mut whiteout_M3DataDrivenMaterial,
26939            count: usize,
26940        );
26941        pub fn whiteout_m3_M3DataDrivenMaterial_get_fragmentHashes_data(
26942            self_: *mut whiteout_M3DataDrivenMaterial,
26943        ) -> *const u32;
26944        pub fn whiteout_m3_M3DataDrivenMaterial_assign_fragmentHashes(
26945            self_: *mut whiteout_M3DataDrivenMaterial,
26946            data: *const u32,
26947            count: usize,
26948        );
26949        pub fn whiteout_m3_M3DataDrivenMaterial_get_extraHashes_count(
26950            self_: *mut whiteout_M3DataDrivenMaterial,
26951        ) -> usize;
26952        pub fn whiteout_m3_M3DataDrivenMaterial_resize_extraHashes(
26953            self_: *mut whiteout_M3DataDrivenMaterial,
26954            count: usize,
26955        );
26956        pub fn whiteout_m3_M3DataDrivenMaterial_get_extraHashes_data(
26957            self_: *mut whiteout_M3DataDrivenMaterial,
26958        ) -> *const u32;
26959        pub fn whiteout_m3_M3DataDrivenMaterial_assign_extraHashes(
26960            self_: *mut whiteout_M3DataDrivenMaterial,
26961            data: *const u32,
26962            count: usize,
26963        );
26964        pub fn whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_count(
26965            self_: *mut whiteout_M3DataDrivenMaterial,
26966        ) -> usize;
26967        pub fn whiteout_m3_M3DataDrivenMaterial_resize_propertyBlob(
26968            self_: *mut whiteout_M3DataDrivenMaterial,
26969            count: usize,
26970        );
26971        pub fn whiteout_m3_M3DataDrivenMaterial_get_propertyBlob_data(
26972            self_: *mut whiteout_M3DataDrivenMaterial,
26973        ) -> *const u8;
26974        pub fn whiteout_m3_M3DataDrivenMaterial_assign_propertyBlob(
26975            self_: *mut whiteout_M3DataDrivenMaterial,
26976            data: *const u8,
26977            count: usize,
26978        );
26979        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown108(
26980            self_: *mut whiteout_M3DataDrivenMaterial,
26981        ) -> f32;
26982        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown108(
26983            self_: *mut whiteout_M3DataDrivenMaterial,
26984            value: f32,
26985        );
26986        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown112(
26987            self_: *mut whiteout_M3DataDrivenMaterial,
26988        ) -> f32;
26989        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown112(
26990            self_: *mut whiteout_M3DataDrivenMaterial,
26991            value: f32,
26992        );
26993        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown116(
26994            self_: *mut whiteout_M3DataDrivenMaterial,
26995        ) -> f32;
26996        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown116(
26997            self_: *mut whiteout_M3DataDrivenMaterial,
26998            value: f32,
26999        );
27000        pub fn whiteout_m3_M3DataDrivenMaterial_get_effectNameHash(
27001            self_: *mut whiteout_M3DataDrivenMaterial,
27002        ) -> u32;
27003        pub fn whiteout_m3_M3DataDrivenMaterial_set_effectNameHash(
27004            self_: *mut whiteout_M3DataDrivenMaterial,
27005            value: u32,
27006        );
27007        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown124(
27008            self_: *mut whiteout_M3DataDrivenMaterial,
27009        ) -> u32;
27010        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown124(
27011            self_: *mut whiteout_M3DataDrivenMaterial,
27012            value: u32,
27013        );
27014        pub fn whiteout_m3_M3DataDrivenMaterial_get_padding128(
27015            self_: *mut whiteout_M3DataDrivenMaterial,
27016        ) -> u32;
27017        pub fn whiteout_m3_M3DataDrivenMaterial_set_padding128(
27018            self_: *mut whiteout_M3DataDrivenMaterial,
27019            value: u32,
27020        );
27021        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown132(
27022            self_: *mut whiteout_M3DataDrivenMaterial,
27023        ) -> i32;
27024        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown132(
27025            self_: *mut whiteout_M3DataDrivenMaterial,
27026            value: i32,
27027        );
27028        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown136(
27029            self_: *mut whiteout_M3DataDrivenMaterial,
27030        ) -> u32;
27031        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown136(
27032            self_: *mut whiteout_M3DataDrivenMaterial,
27033            value: u32,
27034        );
27035        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown140(
27036            self_: *mut whiteout_M3DataDrivenMaterial,
27037        ) -> u32;
27038        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown140(
27039            self_: *mut whiteout_M3DataDrivenMaterial,
27040            value: u32,
27041        );
27042        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown144(
27043            self_: *mut whiteout_M3DataDrivenMaterial,
27044        ) -> u32;
27045        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown144(
27046            self_: *mut whiteout_M3DataDrivenMaterial,
27047            value: u32,
27048        );
27049        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown148(
27050            self_: *mut whiteout_M3DataDrivenMaterial,
27051        ) -> u8;
27052        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown148(
27053            self_: *mut whiteout_M3DataDrivenMaterial,
27054            value: u8,
27055        );
27056        pub fn whiteout_m3_M3DataDrivenMaterial_get_alphaFresnelFlags(
27057            self_: *mut whiteout_M3DataDrivenMaterial,
27058        ) -> u8;
27059        pub fn whiteout_m3_M3DataDrivenMaterial_set_alphaFresnelFlags(
27060            self_: *mut whiteout_M3DataDrivenMaterial,
27061            value: u8,
27062        );
27063        pub fn whiteout_m3_M3DataDrivenMaterial_get_shaderType(
27064            self_: *mut whiteout_M3DataDrivenMaterial,
27065        ) -> i32;
27066        pub fn whiteout_m3_M3DataDrivenMaterial_set_shaderType(
27067            self_: *mut whiteout_M3DataDrivenMaterial,
27068            value: i32,
27069        );
27070        pub fn whiteout_m3_M3DataDrivenMaterial_get_unknown151(
27071            self_: *mut whiteout_M3DataDrivenMaterial,
27072        ) -> u8;
27073        pub fn whiteout_m3_M3DataDrivenMaterial_set_unknown151(
27074            self_: *mut whiteout_M3DataDrivenMaterial,
27075            value: u8,
27076        );
27077        pub fn whiteout_m3_M3DataDrivenMaterial_get_effectNameHash2(
27078            self_: *mut whiteout_M3DataDrivenMaterial,
27079        ) -> u32;
27080        pub fn whiteout_m3_M3DataDrivenMaterial_set_effectNameHash2(
27081            self_: *mut whiteout_M3DataDrivenMaterial,
27082            value: u32,
27083        );
27084        pub fn whiteout_m3_M3DataDrivenMaterial_get_effectNameHash3(
27085            self_: *mut whiteout_M3DataDrivenMaterial,
27086        ) -> u32;
27087        pub fn whiteout_m3_M3DataDrivenMaterial_set_effectNameHash3(
27088            self_: *mut whiteout_M3DataDrivenMaterial,
27089            value: u32,
27090        );
27091        pub fn whiteout_m3_M3DataDrivenMaterial_decodeProperties(
27092            self_: *mut whiteout_M3DataDrivenMaterial,
27093        ) -> *mut whiteout_M3DataDrivenProperties;
27094        pub fn whiteout_m3_M3DataDrivenMaterial_toStandardMaterial(
27095            self_: *mut whiteout_M3DataDrivenMaterial,
27096        ) -> *mut whiteout_M3StandardMaterialConversion;
27097        pub fn whiteout_m3_M3DataDrivenMaterial_approximateStandardMaterial(
27098            self_: *mut whiteout_M3DataDrivenMaterial,
27099        ) -> *mut whiteout_M3StandardMaterialConversion;
27100        pub fn whiteout_m3_M3DataDrivenMaterial_getVersion(
27101            self_: *mut whiteout_M3DataDrivenMaterial,
27102        ) -> i32;
27103        pub fn whiteout_m3_M3DataDrivenMaterial_setVersion(
27104            self_: *mut whiteout_M3DataDrivenMaterial,
27105            new_version: i32,
27106        ) -> i32;
27107        pub fn whiteout_m3_M3DataDrivenMaterial_forceVersion(
27108            self_: *mut whiteout_M3DataDrivenMaterial,
27109            new_version: i32,
27110        );
27111        // Bone
27112        pub fn whiteout_m3_M3Bone_new() -> *mut whiteout_M3Bone;
27113        pub fn whiteout_m3_M3Bone_delete(self_: *mut whiteout_M3Bone);
27114        pub fn whiteout_m3_M3Bone_get_unknown(self_: *mut whiteout_M3Bone) -> u32;
27115        pub fn whiteout_m3_M3Bone_set_unknown(self_: *mut whiteout_M3Bone, value: u32);
27116        pub fn whiteout_m3_M3Bone_get_name(self_: *mut whiteout_M3Bone) -> RawCString;
27117        pub fn whiteout_m3_M3Bone_set_name(
27118            self_: *mut whiteout_M3Bone,
27119            value: *const core::ffi::c_char,
27120        );
27121        pub fn whiteout_m3_M3Bone_get_flags(self_: *mut whiteout_M3Bone) -> i32;
27122        pub fn whiteout_m3_M3Bone_set_flags(self_: *mut whiteout_M3Bone, value: i32);
27123        pub fn whiteout_m3_M3Bone_get_parentIndex(self_: *mut whiteout_M3Bone) -> u16;
27124        pub fn whiteout_m3_M3Bone_set_parentIndex(self_: *mut whiteout_M3Bone, value: u16);
27125        pub fn whiteout_m3_M3Bone_get_padding(self_: *mut whiteout_M3Bone) -> u16;
27126        pub fn whiteout_m3_M3Bone_set_padding(self_: *mut whiteout_M3Bone, value: u16);
27127        pub fn whiteout_m3_M3Bone_get_position(
27128            self_: *mut whiteout_M3Bone,
27129        ) -> *mut whiteout_M3AnimRefVector3f;
27130        pub fn whiteout_m3_M3Bone_set_position(
27131            self_: *mut whiteout_M3Bone,
27132            value: *const whiteout_M3AnimRefVector3f,
27133        );
27134        pub fn whiteout_m3_M3Bone_get_rotation(
27135            self_: *mut whiteout_M3Bone,
27136        ) -> *mut whiteout_M3AnimRefQuaternion;
27137        pub fn whiteout_m3_M3Bone_set_rotation(
27138            self_: *mut whiteout_M3Bone,
27139            value: *const whiteout_M3AnimRefQuaternion,
27140        );
27141        pub fn whiteout_m3_M3Bone_get_scale(
27142            self_: *mut whiteout_M3Bone,
27143        ) -> *mut whiteout_M3AnimRefVector3f;
27144        pub fn whiteout_m3_M3Bone_set_scale(
27145            self_: *mut whiteout_M3Bone,
27146            value: *const whiteout_M3AnimRefVector3f,
27147        );
27148        pub fn whiteout_m3_M3Bone_get_visibility(
27149            self_: *mut whiteout_M3Bone,
27150        ) -> *mut whiteout_M3AnimRefU32;
27151        pub fn whiteout_m3_M3Bone_set_visibility(
27152            self_: *mut whiteout_M3Bone,
27153            value: *const whiteout_M3AnimRefU32,
27154        );
27155        // Region
27156        pub fn whiteout_m3_M3Region_new() -> *mut whiteout_M3Region;
27157        pub fn whiteout_m3_M3Region_delete(self_: *mut whiteout_M3Region);
27158        pub fn whiteout_m3_M3Region_get_index(self_: *mut whiteout_M3Region) -> u32;
27159        pub fn whiteout_m3_M3Region_set_index(self_: *mut whiteout_M3Region, value: u32);
27160        pub fn whiteout_m3_M3Region_get_unknown(self_: *mut whiteout_M3Region) -> u32;
27161        pub fn whiteout_m3_M3Region_set_unknown(self_: *mut whiteout_M3Region, value: u32);
27162        pub fn whiteout_m3_M3Region_get_firstVertex(self_: *mut whiteout_M3Region) -> u32;
27163        pub fn whiteout_m3_M3Region_set_firstVertex(self_: *mut whiteout_M3Region, value: u32);
27164        pub fn whiteout_m3_M3Region_get_vertexCount(self_: *mut whiteout_M3Region) -> u32;
27165        pub fn whiteout_m3_M3Region_set_vertexCount(self_: *mut whiteout_M3Region, value: u32);
27166        pub fn whiteout_m3_M3Region_get_firstIndex(self_: *mut whiteout_M3Region) -> u32;
27167        pub fn whiteout_m3_M3Region_set_firstIndex(self_: *mut whiteout_M3Region, value: u32);
27168        pub fn whiteout_m3_M3Region_get_indexCount(self_: *mut whiteout_M3Region) -> u32;
27169        pub fn whiteout_m3_M3Region_set_indexCount(self_: *mut whiteout_M3Region, value: u32);
27170        pub fn whiteout_m3_M3Region_get_unknown2(self_: *mut whiteout_M3Region) -> u16;
27171        pub fn whiteout_m3_M3Region_set_unknown2(self_: *mut whiteout_M3Region, value: u16);
27172        pub fn whiteout_m3_M3Region_get_firstBoneLookup(self_: *mut whiteout_M3Region) -> u16;
27173        pub fn whiteout_m3_M3Region_set_firstBoneLookup(self_: *mut whiteout_M3Region, value: u16);
27174        pub fn whiteout_m3_M3Region_get_boneLookupCount(self_: *mut whiteout_M3Region) -> u16;
27175        pub fn whiteout_m3_M3Region_set_boneLookupCount(self_: *mut whiteout_M3Region, value: u16);
27176        pub fn whiteout_m3_M3Region_get_padding(self_: *mut whiteout_M3Region) -> u16;
27177        pub fn whiteout_m3_M3Region_set_padding(self_: *mut whiteout_M3Region, value: u16);
27178        pub fn whiteout_m3_M3Region_get_boneWeightPairs(self_: *mut whiteout_M3Region) -> u8;
27179        pub fn whiteout_m3_M3Region_set_boneWeightPairs(self_: *mut whiteout_M3Region, value: u8);
27180        pub fn whiteout_m3_M3Region_get_boneIndexPairs(self_: *mut whiteout_M3Region) -> u8;
27181        pub fn whiteout_m3_M3Region_set_boneIndexPairs(self_: *mut whiteout_M3Region, value: u8);
27182        pub fn whiteout_m3_M3Region_get_rootBone(self_: *mut whiteout_M3Region) -> u16;
27183        pub fn whiteout_m3_M3Region_set_rootBone(self_: *mut whiteout_M3Region, value: u16);
27184        pub fn whiteout_m3_M3Region_get_flags(self_: *mut whiteout_M3Region) -> i32;
27185        pub fn whiteout_m3_M3Region_set_flags(self_: *mut whiteout_M3Region, value: i32);
27186        pub fn whiteout_m3_M3Region_get_uvScale(self_: *mut whiteout_M3Region) -> f32;
27187        pub fn whiteout_m3_M3Region_set_uvScale(self_: *mut whiteout_M3Region, value: f32);
27188        pub fn whiteout_m3_M3Region_get_uvOffset(self_: *mut whiteout_M3Region) -> f32;
27189        pub fn whiteout_m3_M3Region_set_uvOffset(self_: *mut whiteout_M3Region, value: f32);
27190        // Batch
27191        pub fn whiteout_m3_M3Batch_new() -> *mut whiteout_M3Batch;
27192        pub fn whiteout_m3_M3Batch_delete(self_: *mut whiteout_M3Batch);
27193        pub fn whiteout_m3_M3Batch_get_unknown(self_: *mut whiteout_M3Batch) -> u32;
27194        pub fn whiteout_m3_M3Batch_set_unknown(self_: *mut whiteout_M3Batch, value: u32);
27195        pub fn whiteout_m3_M3Batch_get_regionIndex(self_: *mut whiteout_M3Batch) -> u16;
27196        pub fn whiteout_m3_M3Batch_set_regionIndex(self_: *mut whiteout_M3Batch, value: u16);
27197        pub fn whiteout_m3_M3Batch_get_unknown2(self_: *mut whiteout_M3Batch) -> u32;
27198        pub fn whiteout_m3_M3Batch_set_unknown2(self_: *mut whiteout_M3Batch, value: u32);
27199        pub fn whiteout_m3_M3Batch_get_materialIndex(self_: *mut whiteout_M3Batch) -> u16;
27200        pub fn whiteout_m3_M3Batch_set_materialIndex(self_: *mut whiteout_M3Batch, value: u16);
27201        pub fn whiteout_m3_M3Batch_get_boneCount(self_: *mut whiteout_M3Batch) -> u16;
27202        pub fn whiteout_m3_M3Batch_set_boneCount(self_: *mut whiteout_M3Batch, value: u16);
27203        // MeshSection
27204        pub fn whiteout_m3_M3MeshSection_new() -> *mut whiteout_M3MeshSection;
27205        pub fn whiteout_m3_M3MeshSection_delete(self_: *mut whiteout_M3MeshSection);
27206        pub fn whiteout_m3_M3MeshSection_get_nodeIndex(self_: *mut whiteout_M3MeshSection) -> u32;
27207        pub fn whiteout_m3_M3MeshSection_set_nodeIndex(
27208            self_: *mut whiteout_M3MeshSection,
27209            value: u32,
27210        );
27211        pub fn whiteout_m3_M3MeshSection_get_bounds(
27212            self_: *mut whiteout_M3MeshSection,
27213        ) -> *mut whiteout_M3AnimRefM3Extent;
27214        pub fn whiteout_m3_M3MeshSection_set_bounds(
27215            self_: *mut whiteout_M3MeshSection,
27216            value: *const whiteout_M3AnimRefM3Extent,
27217        );
27218        // MeshDivision
27219        pub fn whiteout_m3_M3MeshDivision_new() -> *mut whiteout_M3MeshDivision;
27220        pub fn whiteout_m3_M3MeshDivision_delete(self_: *mut whiteout_M3MeshDivision);
27221        pub fn whiteout_m3_M3MeshDivision_get_faces_count(
27222            self_: *mut whiteout_M3MeshDivision,
27223        ) -> usize;
27224        pub fn whiteout_m3_M3MeshDivision_resize_faces(
27225            self_: *mut whiteout_M3MeshDivision,
27226            count: usize,
27227        );
27228        pub fn whiteout_m3_M3MeshDivision_get_faces_data(
27229            self_: *mut whiteout_M3MeshDivision,
27230        ) -> *const u16;
27231        pub fn whiteout_m3_M3MeshDivision_assign_faces(
27232            self_: *mut whiteout_M3MeshDivision,
27233            data: *const u16,
27234            count: usize,
27235        );
27236        pub fn whiteout_m3_M3MeshDivision_get_regions_count(
27237            self_: *mut whiteout_M3MeshDivision,
27238        ) -> usize;
27239        pub fn whiteout_m3_M3MeshDivision_resize_regions(
27240            self_: *mut whiteout_M3MeshDivision,
27241            count: usize,
27242        );
27243        pub fn whiteout_m3_M3MeshDivision_get_regions_at(
27244            self_: *mut whiteout_M3MeshDivision,
27245            index: usize,
27246        ) -> *mut whiteout_M3Region;
27247        pub fn whiteout_m3_M3MeshDivision_get_batches_count(
27248            self_: *mut whiteout_M3MeshDivision,
27249        ) -> usize;
27250        pub fn whiteout_m3_M3MeshDivision_resize_batches(
27251            self_: *mut whiteout_M3MeshDivision,
27252            count: usize,
27253        );
27254        pub fn whiteout_m3_M3MeshDivision_get_batches_at(
27255            self_: *mut whiteout_M3MeshDivision,
27256            index: usize,
27257        ) -> *mut whiteout_M3Batch;
27258        pub fn whiteout_m3_M3MeshDivision_get_msec_count(
27259            self_: *mut whiteout_M3MeshDivision,
27260        ) -> usize;
27261        pub fn whiteout_m3_M3MeshDivision_resize_msec(
27262            self_: *mut whiteout_M3MeshDivision,
27263            count: usize,
27264        );
27265        pub fn whiteout_m3_M3MeshDivision_get_msec_at(
27266            self_: *mut whiteout_M3MeshDivision,
27267            index: usize,
27268        ) -> *mut whiteout_M3MeshSection;
27269        pub fn whiteout_m3_M3MeshDivision_get_instances(self_: *mut whiteout_M3MeshDivision)
27270            -> u32;
27271        pub fn whiteout_m3_M3MeshDivision_set_instances(
27272            self_: *mut whiteout_M3MeshDivision,
27273            value: u32,
27274        );
27275        // InitialReference
27276        pub fn whiteout_m3_M3InitialReference_new() -> *mut whiteout_M3InitialReference;
27277        pub fn whiteout_m3_M3InitialReference_delete(self_: *mut whiteout_M3InitialReference);
27278        // AttachmentPoint
27279        pub fn whiteout_m3_M3AttachmentPoint_new() -> *mut whiteout_M3AttachmentPoint;
27280        pub fn whiteout_m3_M3AttachmentPoint_delete(self_: *mut whiteout_M3AttachmentPoint);
27281        pub fn whiteout_m3_M3AttachmentPoint_get_unknown(
27282            self_: *mut whiteout_M3AttachmentPoint,
27283        ) -> u32;
27284        pub fn whiteout_m3_M3AttachmentPoint_set_unknown(
27285            self_: *mut whiteout_M3AttachmentPoint,
27286            value: u32,
27287        );
27288        pub fn whiteout_m3_M3AttachmentPoint_get_name(
27289            self_: *mut whiteout_M3AttachmentPoint,
27290        ) -> RawCString;
27291        pub fn whiteout_m3_M3AttachmentPoint_set_name(
27292            self_: *mut whiteout_M3AttachmentPoint,
27293            value: *const core::ffi::c_char,
27294        );
27295        pub fn whiteout_m3_M3AttachmentPoint_get_boneIndex(
27296            self_: *mut whiteout_M3AttachmentPoint,
27297        ) -> u32;
27298        pub fn whiteout_m3_M3AttachmentPoint_set_boneIndex(
27299            self_: *mut whiteout_M3AttachmentPoint,
27300            value: u32,
27301        );
27302        // HitTestShape
27303        pub fn whiteout_m3_M3HitTestShape_new() -> *mut whiteout_M3HitTestShape;
27304        pub fn whiteout_m3_M3HitTestShape_delete(self_: *mut whiteout_M3HitTestShape);
27305        pub fn whiteout_m3_M3HitTestShape_get_shapeType(self_: *mut whiteout_M3HitTestShape)
27306            -> i32;
27307        pub fn whiteout_m3_M3HitTestShape_set_shapeType(
27308            self_: *mut whiteout_M3HitTestShape,
27309            value: i32,
27310        );
27311        pub fn whiteout_m3_M3HitTestShape_get_boneIndex(self_: *mut whiteout_M3HitTestShape)
27312            -> u16;
27313        pub fn whiteout_m3_M3HitTestShape_set_boneIndex(
27314            self_: *mut whiteout_M3HitTestShape,
27315            value: u16,
27316        );
27317        pub fn whiteout_m3_M3HitTestShape_get_padding(self_: *mut whiteout_M3HitTestShape) -> u16;
27318        pub fn whiteout_m3_M3HitTestShape_set_padding(
27319            self_: *mut whiteout_M3HitTestShape,
27320            value: u16,
27321        );
27322        pub fn whiteout_m3_M3HitTestShape_get_vertexPositions_count(
27323            self_: *mut whiteout_M3HitTestShape,
27324        ) -> usize;
27325        pub fn whiteout_m3_M3HitTestShape_resize_vertexPositions(
27326            self_: *mut whiteout_M3HitTestShape,
27327            count: usize,
27328        );
27329        pub fn whiteout_m3_M3HitTestShape_get_vertexPositions_data(
27330            self_: *mut whiteout_M3HitTestShape,
27331        ) -> *const f32;
27332        pub fn whiteout_m3_M3HitTestShape_assign_vertexPositions(
27333            self_: *mut whiteout_M3HitTestShape,
27334            data: *const f32,
27335            count: usize,
27336        );
27337        pub fn whiteout_m3_M3HitTestShape_get_faceIndices_count(
27338            self_: *mut whiteout_M3HitTestShape,
27339        ) -> usize;
27340        pub fn whiteout_m3_M3HitTestShape_resize_faceIndices(
27341            self_: *mut whiteout_M3HitTestShape,
27342            count: usize,
27343        );
27344        pub fn whiteout_m3_M3HitTestShape_get_faceIndices_data(
27345            self_: *mut whiteout_M3HitTestShape,
27346        ) -> *const u16;
27347        pub fn whiteout_m3_M3HitTestShape_assign_faceIndices(
27348            self_: *mut whiteout_M3HitTestShape,
27349            data: *const u16,
27350            count: usize,
27351        );
27352        pub fn whiteout_m3_M3HitTestShape_get_sizeX(self_: *mut whiteout_M3HitTestShape) -> f32;
27353        pub fn whiteout_m3_M3HitTestShape_set_sizeX(
27354            self_: *mut whiteout_M3HitTestShape,
27355            value: f32,
27356        );
27357        pub fn whiteout_m3_M3HitTestShape_get_sizeY(self_: *mut whiteout_M3HitTestShape) -> f32;
27358        pub fn whiteout_m3_M3HitTestShape_set_sizeY(
27359            self_: *mut whiteout_M3HitTestShape,
27360            value: f32,
27361        );
27362        pub fn whiteout_m3_M3HitTestShape_get_sizeZ(self_: *mut whiteout_M3HitTestShape) -> f32;
27363        pub fn whiteout_m3_M3HitTestShape_set_sizeZ(
27364            self_: *mut whiteout_M3HitTestShape,
27365            value: f32,
27366        );
27367        // AttachmentVolume
27368        pub fn whiteout_m3_M3AttachmentVolume_new() -> *mut whiteout_M3AttachmentVolume;
27369        pub fn whiteout_m3_M3AttachmentVolume_delete(self_: *mut whiteout_M3AttachmentVolume);
27370        pub fn whiteout_m3_M3AttachmentVolume_get_bone1(
27371            self_: *mut whiteout_M3AttachmentVolume,
27372        ) -> u32;
27373        pub fn whiteout_m3_M3AttachmentVolume_set_bone1(
27374            self_: *mut whiteout_M3AttachmentVolume,
27375            value: u32,
27376        );
27377        pub fn whiteout_m3_M3AttachmentVolume_get_bone2(
27378            self_: *mut whiteout_M3AttachmentVolume,
27379        ) -> u32;
27380        pub fn whiteout_m3_M3AttachmentVolume_set_bone2(
27381            self_: *mut whiteout_M3AttachmentVolume,
27382            value: u32,
27383        );
27384        pub fn whiteout_m3_M3AttachmentVolume_get_shapeType(
27385            self_: *mut whiteout_M3AttachmentVolume,
27386        ) -> i32;
27387        pub fn whiteout_m3_M3AttachmentVolume_set_shapeType(
27388            self_: *mut whiteout_M3AttachmentVolume,
27389            value: i32,
27390        );
27391        pub fn whiteout_m3_M3AttachmentVolume_get_boneIndex(
27392            self_: *mut whiteout_M3AttachmentVolume,
27393        ) -> u16;
27394        pub fn whiteout_m3_M3AttachmentVolume_set_boneIndex(
27395            self_: *mut whiteout_M3AttachmentVolume,
27396            value: u16,
27397        );
27398        pub fn whiteout_m3_M3AttachmentVolume_get_padding(
27399            self_: *mut whiteout_M3AttachmentVolume,
27400        ) -> u16;
27401        pub fn whiteout_m3_M3AttachmentVolume_set_padding(
27402            self_: *mut whiteout_M3AttachmentVolume,
27403            value: u16,
27404        );
27405        pub fn whiteout_m3_M3AttachmentVolume_get_vertexPositions_count(
27406            self_: *mut whiteout_M3AttachmentVolume,
27407        ) -> usize;
27408        pub fn whiteout_m3_M3AttachmentVolume_resize_vertexPositions(
27409            self_: *mut whiteout_M3AttachmentVolume,
27410            count: usize,
27411        );
27412        pub fn whiteout_m3_M3AttachmentVolume_get_vertexPositions_data(
27413            self_: *mut whiteout_M3AttachmentVolume,
27414        ) -> *const f32;
27415        pub fn whiteout_m3_M3AttachmentVolume_assign_vertexPositions(
27416            self_: *mut whiteout_M3AttachmentVolume,
27417            data: *const f32,
27418            count: usize,
27419        );
27420        pub fn whiteout_m3_M3AttachmentVolume_get_faceIndices_count(
27421            self_: *mut whiteout_M3AttachmentVolume,
27422        ) -> usize;
27423        pub fn whiteout_m3_M3AttachmentVolume_resize_faceIndices(
27424            self_: *mut whiteout_M3AttachmentVolume,
27425            count: usize,
27426        );
27427        pub fn whiteout_m3_M3AttachmentVolume_get_faceIndices_data(
27428            self_: *mut whiteout_M3AttachmentVolume,
27429        ) -> *const u16;
27430        pub fn whiteout_m3_M3AttachmentVolume_assign_faceIndices(
27431            self_: *mut whiteout_M3AttachmentVolume,
27432            data: *const u16,
27433            count: usize,
27434        );
27435        pub fn whiteout_m3_M3AttachmentVolume_get_sizeX(
27436            self_: *mut whiteout_M3AttachmentVolume,
27437        ) -> f32;
27438        pub fn whiteout_m3_M3AttachmentVolume_set_sizeX(
27439            self_: *mut whiteout_M3AttachmentVolume,
27440            value: f32,
27441        );
27442        pub fn whiteout_m3_M3AttachmentVolume_get_sizeY(
27443            self_: *mut whiteout_M3AttachmentVolume,
27444        ) -> f32;
27445        pub fn whiteout_m3_M3AttachmentVolume_set_sizeY(
27446            self_: *mut whiteout_M3AttachmentVolume,
27447            value: f32,
27448        );
27449        pub fn whiteout_m3_M3AttachmentVolume_get_sizeZ(
27450            self_: *mut whiteout_M3AttachmentVolume,
27451        ) -> f32;
27452        pub fn whiteout_m3_M3AttachmentVolume_set_sizeZ(
27453            self_: *mut whiteout_M3AttachmentVolume,
27454            value: f32,
27455        );
27456        // TriggerData
27457        pub fn whiteout_m3_M3TriggerData_new() -> *mut whiteout_M3TriggerData;
27458        pub fn whiteout_m3_M3TriggerData_delete(self_: *mut whiteout_M3TriggerData);
27459        pub fn whiteout_m3_M3TriggerData_get_dataIndices_count(
27460            self_: *mut whiteout_M3TriggerData,
27461        ) -> usize;
27462        pub fn whiteout_m3_M3TriggerData_resize_dataIndices(
27463            self_: *mut whiteout_M3TriggerData,
27464            count: usize,
27465        );
27466        pub fn whiteout_m3_M3TriggerData_get_dataIndices_data(
27467            self_: *mut whiteout_M3TriggerData,
27468        ) -> *const u32;
27469        pub fn whiteout_m3_M3TriggerData_assign_dataIndices(
27470            self_: *mut whiteout_M3TriggerData,
27471            data: *const u32,
27472            count: usize,
27473        );
27474        pub fn whiteout_m3_M3TriggerData_get_name(self_: *mut whiteout_M3TriggerData)
27475            -> RawCString;
27476        pub fn whiteout_m3_M3TriggerData_set_name(
27477            self_: *mut whiteout_M3TriggerData,
27478            value: *const core::ffi::c_char,
27479        );
27480        // TurretBehavior
27481        pub fn whiteout_m3_M3TurretBehavior_new() -> *mut whiteout_M3TurretBehavior;
27482        pub fn whiteout_m3_M3TurretBehavior_delete(self_: *mut whiteout_M3TurretBehavior);
27483        pub fn whiteout_m3_M3TurretBehavior_get_unknown1(
27484            self_: *mut whiteout_M3TurretBehavior,
27485        ) -> *mut core::ffi::c_void;
27486        pub fn whiteout_m3_M3TurretBehavior_set_unknown1(
27487            self_: *mut whiteout_M3TurretBehavior,
27488            value: *const core::ffi::c_void,
27489        );
27490        pub fn whiteout_m3_M3TurretBehavior_get_unknown2(
27491            self_: *mut whiteout_M3TurretBehavior,
27492        ) -> *mut core::ffi::c_void;
27493        pub fn whiteout_m3_M3TurretBehavior_set_unknown2(
27494            self_: *mut whiteout_M3TurretBehavior,
27495            value: *const core::ffi::c_void,
27496        );
27497        pub fn whiteout_m3_M3TurretBehavior_get_boneIndex(
27498            self_: *mut whiteout_M3TurretBehavior,
27499        ) -> u16;
27500        pub fn whiteout_m3_M3TurretBehavior_set_boneIndex(
27501            self_: *mut whiteout_M3TurretBehavior,
27502            value: u16,
27503        );
27504        pub fn whiteout_m3_M3TurretBehavior_get_useAsMainTurret(
27505            self_: *mut whiteout_M3TurretBehavior,
27506        ) -> u8;
27507        pub fn whiteout_m3_M3TurretBehavior_set_useAsMainTurret(
27508            self_: *mut whiteout_M3TurretBehavior,
27509            value: u8,
27510        );
27511        pub fn whiteout_m3_M3TurretBehavior_get_turretGroupId(
27512            self_: *mut whiteout_M3TurretBehavior,
27513        ) -> u8;
27514        pub fn whiteout_m3_M3TurretBehavior_set_turretGroupId(
27515            self_: *mut whiteout_M3TurretBehavior,
27516            value: u8,
27517        );
27518        pub fn whiteout_m3_M3TurretBehavior_get_yawLimited(
27519            self_: *mut whiteout_M3TurretBehavior,
27520        ) -> u32;
27521        pub fn whiteout_m3_M3TurretBehavior_set_yawLimited(
27522            self_: *mut whiteout_M3TurretBehavior,
27523            value: u32,
27524        );
27525        pub fn whiteout_m3_M3TurretBehavior_get_yawMin(
27526            self_: *mut whiteout_M3TurretBehavior,
27527        ) -> f32;
27528        pub fn whiteout_m3_M3TurretBehavior_set_yawMin(
27529            self_: *mut whiteout_M3TurretBehavior,
27530            value: f32,
27531        );
27532        pub fn whiteout_m3_M3TurretBehavior_get_yawMax(
27533            self_: *mut whiteout_M3TurretBehavior,
27534        ) -> f32;
27535        pub fn whiteout_m3_M3TurretBehavior_set_yawMax(
27536            self_: *mut whiteout_M3TurretBehavior,
27537            value: f32,
27538        );
27539        pub fn whiteout_m3_M3TurretBehavior_get_yawWeight(
27540            self_: *mut whiteout_M3TurretBehavior,
27541        ) -> f32;
27542        pub fn whiteout_m3_M3TurretBehavior_set_yawWeight(
27543            self_: *mut whiteout_M3TurretBehavior,
27544            value: f32,
27545        );
27546        pub fn whiteout_m3_M3TurretBehavior_get_pitchLimited(
27547            self_: *mut whiteout_M3TurretBehavior,
27548        ) -> u32;
27549        pub fn whiteout_m3_M3TurretBehavior_set_pitchLimited(
27550            self_: *mut whiteout_M3TurretBehavior,
27551            value: u32,
27552        );
27553        pub fn whiteout_m3_M3TurretBehavior_get_pitchMin(
27554            self_: *mut whiteout_M3TurretBehavior,
27555        ) -> f32;
27556        pub fn whiteout_m3_M3TurretBehavior_set_pitchMin(
27557            self_: *mut whiteout_M3TurretBehavior,
27558            value: f32,
27559        );
27560        pub fn whiteout_m3_M3TurretBehavior_get_pitchMax(
27561            self_: *mut whiteout_M3TurretBehavior,
27562        ) -> f32;
27563        pub fn whiteout_m3_M3TurretBehavior_set_pitchMax(
27564            self_: *mut whiteout_M3TurretBehavior,
27565            value: f32,
27566        );
27567        pub fn whiteout_m3_M3TurretBehavior_get_pitchWeight(
27568            self_: *mut whiteout_M3TurretBehavior,
27569        ) -> f32;
27570        pub fn whiteout_m3_M3TurretBehavior_set_pitchWeight(
27571            self_: *mut whiteout_M3TurretBehavior,
27572            value: f32,
27573        );
27574        pub fn whiteout_m3_M3TurretBehavior_get_unknown3(
27575            self_: *mut whiteout_M3TurretBehavior,
27576        ) -> f32;
27577        pub fn whiteout_m3_M3TurretBehavior_set_unknown3(
27578            self_: *mut whiteout_M3TurretBehavior,
27579            value: f32,
27580        );
27581        pub fn whiteout_m3_M3TurretBehavior_get_unknown4(
27582            self_: *mut whiteout_M3TurretBehavior,
27583        ) -> f32;
27584        pub fn whiteout_m3_M3TurretBehavior_set_unknown4(
27585            self_: *mut whiteout_M3TurretBehavior,
27586            value: f32,
27587        );
27588        pub fn whiteout_m3_M3TurretBehavior_get_mainBoneOffset(
27589            self_: *mut whiteout_M3TurretBehavior,
27590        ) -> *mut core::ffi::c_void;
27591        pub fn whiteout_m3_M3TurretBehavior_set_mainBoneOffset(
27592            self_: *mut whiteout_M3TurretBehavior,
27593            value: *const core::ffi::c_void,
27594        );
27595        // BillboardBehavior
27596        pub fn whiteout_m3_M3BillboardBehavior_new() -> *mut whiteout_M3BillboardBehavior;
27597        pub fn whiteout_m3_M3BillboardBehavior_delete(self_: *mut whiteout_M3BillboardBehavior);
27598        pub fn whiteout_m3_M3BillboardBehavior_get_dependents_count(
27599            self_: *mut whiteout_M3BillboardBehavior,
27600        ) -> usize;
27601        pub fn whiteout_m3_M3BillboardBehavior_resize_dependents(
27602            self_: *mut whiteout_M3BillboardBehavior,
27603            count: usize,
27604        );
27605        pub fn whiteout_m3_M3BillboardBehavior_get_dependents_data(
27606            self_: *mut whiteout_M3BillboardBehavior,
27607        ) -> *const u16;
27608        pub fn whiteout_m3_M3BillboardBehavior_assign_dependents(
27609            self_: *mut whiteout_M3BillboardBehavior,
27610            data: *const u16,
27611            count: usize,
27612        );
27613        pub fn whiteout_m3_M3BillboardBehavior_get_boneIndex(
27614            self_: *mut whiteout_M3BillboardBehavior,
27615        ) -> u16;
27616        pub fn whiteout_m3_M3BillboardBehavior_set_boneIndex(
27617            self_: *mut whiteout_M3BillboardBehavior,
27618            value: u16,
27619        );
27620        pub fn whiteout_m3_M3BillboardBehavior_get_billboardType(
27621            self_: *mut whiteout_M3BillboardBehavior,
27622        ) -> u8;
27623        pub fn whiteout_m3_M3BillboardBehavior_set_billboardType(
27624            self_: *mut whiteout_M3BillboardBehavior,
27625            value: u8,
27626        );
27627        pub fn whiteout_m3_M3BillboardBehavior_get_cameraLookAt(
27628            self_: *mut whiteout_M3BillboardBehavior,
27629        ) -> u8;
27630        pub fn whiteout_m3_M3BillboardBehavior_set_cameraLookAt(
27631            self_: *mut whiteout_M3BillboardBehavior,
27632            value: u8,
27633        );
27634        pub fn whiteout_m3_M3BillboardBehavior_get_up(
27635            self_: *mut whiteout_M3BillboardBehavior,
27636        ) -> *mut core::ffi::c_void;
27637        pub fn whiteout_m3_M3BillboardBehavior_set_up(
27638            self_: *mut whiteout_M3BillboardBehavior,
27639            value: *const core::ffi::c_void,
27640        );
27641        pub fn whiteout_m3_M3BillboardBehavior_get_forward(
27642            self_: *mut whiteout_M3BillboardBehavior,
27643        ) -> *mut core::ffi::c_void;
27644        pub fn whiteout_m3_M3BillboardBehavior_set_forward(
27645            self_: *mut whiteout_M3BillboardBehavior,
27646            value: *const core::ffi::c_void,
27647        );
27648        // IKJoint
27649        pub fn whiteout_m3_M3IKJoint_new() -> *mut whiteout_M3IKJoint;
27650        pub fn whiteout_m3_M3IKJoint_delete(self_: *mut whiteout_M3IKJoint);
27651        pub fn whiteout_m3_M3IKJoint_get_dependents_count(self_: *mut whiteout_M3IKJoint) -> usize;
27652        pub fn whiteout_m3_M3IKJoint_resize_dependents(
27653            self_: *mut whiteout_M3IKJoint,
27654            count: usize,
27655        );
27656        pub fn whiteout_m3_M3IKJoint_get_dependents_data(
27657            self_: *mut whiteout_M3IKJoint,
27658        ) -> *const u16;
27659        pub fn whiteout_m3_M3IKJoint_assign_dependents(
27660            self_: *mut whiteout_M3IKJoint,
27661            data: *const u16,
27662            count: usize,
27663        );
27664        pub fn whiteout_m3_M3IKJoint_get_boneIndex1(self_: *mut whiteout_M3IKJoint) -> u16;
27665        pub fn whiteout_m3_M3IKJoint_set_boneIndex1(self_: *mut whiteout_M3IKJoint, value: u16);
27666        pub fn whiteout_m3_M3IKJoint_get_boneIndex2(self_: *mut whiteout_M3IKJoint) -> u16;
27667        pub fn whiteout_m3_M3IKJoint_set_boneIndex2(self_: *mut whiteout_M3IKJoint, value: u16);
27668        pub fn whiteout_m3_M3IKJoint_get_raycastUp(self_: *mut whiteout_M3IKJoint) -> f32;
27669        pub fn whiteout_m3_M3IKJoint_set_raycastUp(self_: *mut whiteout_M3IKJoint, value: f32);
27670        pub fn whiteout_m3_M3IKJoint_get_raycastDown(self_: *mut whiteout_M3IKJoint) -> f32;
27671        pub fn whiteout_m3_M3IKJoint_set_raycastDown(self_: *mut whiteout_M3IKJoint, value: f32);
27672        pub fn whiteout_m3_M3IKJoint_get_maxSpeed(self_: *mut whiteout_M3IKJoint) -> f32;
27673        pub fn whiteout_m3_M3IKJoint_set_maxSpeed(self_: *mut whiteout_M3IKJoint, value: f32);
27674        pub fn whiteout_m3_M3IKJoint_get_goalThreshold(self_: *mut whiteout_M3IKJoint) -> f32;
27675        pub fn whiteout_m3_M3IKJoint_set_goalThreshold(self_: *mut whiteout_M3IKJoint, value: f32);
27676        // IKTwoJoint
27677        pub fn whiteout_m3_M3IKTwoJoint_new() -> *mut whiteout_M3IKTwoJoint;
27678        pub fn whiteout_m3_M3IKTwoJoint_delete(self_: *mut whiteout_M3IKTwoJoint);
27679        pub fn whiteout_m3_M3IKTwoJoint_get_dependents_count(
27680            self_: *mut whiteout_M3IKTwoJoint,
27681        ) -> usize;
27682        pub fn whiteout_m3_M3IKTwoJoint_resize_dependents(
27683            self_: *mut whiteout_M3IKTwoJoint,
27684            count: usize,
27685        );
27686        pub fn whiteout_m3_M3IKTwoJoint_get_dependents_data(
27687            self_: *mut whiteout_M3IKTwoJoint,
27688        ) -> *const u16;
27689        pub fn whiteout_m3_M3IKTwoJoint_assign_dependents(
27690            self_: *mut whiteout_M3IKTwoJoint,
27691            data: *const u16,
27692            count: usize,
27693        );
27694        pub fn whiteout_m3_M3IKTwoJoint_get_boneBase(self_: *mut whiteout_M3IKTwoJoint) -> u16;
27695        pub fn whiteout_m3_M3IKTwoJoint_set_boneBase(self_: *mut whiteout_M3IKTwoJoint, value: u16);
27696        pub fn whiteout_m3_M3IKTwoJoint_get_boneTarget(self_: *mut whiteout_M3IKTwoJoint) -> u16;
27697        pub fn whiteout_m3_M3IKTwoJoint_set_boneTarget(
27698            self_: *mut whiteout_M3IKTwoJoint,
27699            value: u16,
27700        );
27701        pub fn whiteout_m3_M3IKTwoJoint_get_boneEnd(self_: *mut whiteout_M3IKTwoJoint) -> u16;
27702        pub fn whiteout_m3_M3IKTwoJoint_set_boneEnd(self_: *mut whiteout_M3IKTwoJoint, value: u16);
27703        pub fn whiteout_m3_M3IKTwoJoint_get_padding(self_: *mut whiteout_M3IKTwoJoint) -> u16;
27704        pub fn whiteout_m3_M3IKTwoJoint_set_padding(self_: *mut whiteout_M3IKTwoJoint, value: u16);
27705        pub fn whiteout_m3_M3IKTwoJoint_get_hingeAxis(
27706            self_: *mut whiteout_M3IKTwoJoint,
27707        ) -> *mut core::ffi::c_void;
27708        pub fn whiteout_m3_M3IKTwoJoint_set_hingeAxis(
27709            self_: *mut whiteout_M3IKTwoJoint,
27710            value: *const core::ffi::c_void,
27711        );
27712        pub fn whiteout_m3_M3IKTwoJoint_get_maxAngleInner(self_: *mut whiteout_M3IKTwoJoint)
27713            -> f32;
27714        pub fn whiteout_m3_M3IKTwoJoint_set_maxAngleInner(
27715            self_: *mut whiteout_M3IKTwoJoint,
27716            value: f32,
27717        );
27718        pub fn whiteout_m3_M3IKTwoJoint_get_maxAngleOuter(self_: *mut whiteout_M3IKTwoJoint)
27719            -> f32;
27720        pub fn whiteout_m3_M3IKTwoJoint_set_maxAngleOuter(
27721            self_: *mut whiteout_M3IKTwoJoint,
27722            value: f32,
27723        );
27724        pub fn whiteout_m3_M3IKTwoJoint_get_searchUp(self_: *mut whiteout_M3IKTwoJoint) -> f32;
27725        pub fn whiteout_m3_M3IKTwoJoint_set_searchUp(self_: *mut whiteout_M3IKTwoJoint, value: f32);
27726        pub fn whiteout_m3_M3IKTwoJoint_get_searchDown(self_: *mut whiteout_M3IKTwoJoint) -> f32;
27727        pub fn whiteout_m3_M3IKTwoJoint_set_searchDown(
27728            self_: *mut whiteout_M3IKTwoJoint,
27729            value: f32,
27730        );
27731        // IKCCD
27732        pub fn whiteout_m3_M3IKCCD_new() -> *mut whiteout_M3IKCCD;
27733        pub fn whiteout_m3_M3IKCCD_delete(self_: *mut whiteout_M3IKCCD);
27734        pub fn whiteout_m3_M3IKCCD_get_dependents_count(self_: *mut whiteout_M3IKCCD) -> usize;
27735        pub fn whiteout_m3_M3IKCCD_resize_dependents(self_: *mut whiteout_M3IKCCD, count: usize);
27736        pub fn whiteout_m3_M3IKCCD_get_dependents_data(self_: *mut whiteout_M3IKCCD) -> *const u16;
27737        pub fn whiteout_m3_M3IKCCD_assign_dependents(
27738            self_: *mut whiteout_M3IKCCD,
27739            data: *const u16,
27740            count: usize,
27741        );
27742        pub fn whiteout_m3_M3IKCCD_get_boneBase(self_: *mut whiteout_M3IKCCD) -> u16;
27743        pub fn whiteout_m3_M3IKCCD_set_boneBase(self_: *mut whiteout_M3IKCCD, value: u16);
27744        pub fn whiteout_m3_M3IKCCD_get_boneTarget(self_: *mut whiteout_M3IKCCD) -> u16;
27745        pub fn whiteout_m3_M3IKCCD_set_boneTarget(self_: *mut whiteout_M3IKCCD, value: u16);
27746        pub fn whiteout_m3_M3IKCCD_get_searchUp(self_: *mut whiteout_M3IKCCD) -> f32;
27747        pub fn whiteout_m3_M3IKCCD_set_searchUp(self_: *mut whiteout_M3IKCCD, value: f32);
27748        pub fn whiteout_m3_M3IKCCD_get_searchDown(self_: *mut whiteout_M3IKCCD) -> f32;
27749        pub fn whiteout_m3_M3IKCCD_set_searchDown(self_: *mut whiteout_M3IKCCD, value: f32);
27750        // OneBoneSolver
27751        pub fn whiteout_m3_M3OneBoneSolver_new() -> *mut whiteout_M3OneBoneSolver;
27752        pub fn whiteout_m3_M3OneBoneSolver_delete(self_: *mut whiteout_M3OneBoneSolver);
27753        pub fn whiteout_m3_M3OneBoneSolver_get_dependents_count(
27754            self_: *mut whiteout_M3OneBoneSolver,
27755        ) -> usize;
27756        pub fn whiteout_m3_M3OneBoneSolver_resize_dependents(
27757            self_: *mut whiteout_M3OneBoneSolver,
27758            count: usize,
27759        );
27760        pub fn whiteout_m3_M3OneBoneSolver_get_dependents_data(
27761            self_: *mut whiteout_M3OneBoneSolver,
27762        ) -> *const u16;
27763        pub fn whiteout_m3_M3OneBoneSolver_assign_dependents(
27764            self_: *mut whiteout_M3OneBoneSolver,
27765            data: *const u16,
27766            count: usize,
27767        );
27768        pub fn whiteout_m3_M3OneBoneSolver_get_bone(self_: *mut whiteout_M3OneBoneSolver) -> u16;
27769        pub fn whiteout_m3_M3OneBoneSolver_set_bone(
27770            self_: *mut whiteout_M3OneBoneSolver,
27771            value: u16,
27772        );
27773        pub fn whiteout_m3_M3OneBoneSolver_get_boneFallback(
27774            self_: *mut whiteout_M3OneBoneSolver,
27775        ) -> u16;
27776        pub fn whiteout_m3_M3OneBoneSolver_set_boneFallback(
27777            self_: *mut whiteout_M3OneBoneSolver,
27778            value: u16,
27779        );
27780        pub fn whiteout_m3_M3OneBoneSolver_get_maxAngle(
27781            self_: *mut whiteout_M3OneBoneSolver,
27782        ) -> f32;
27783        pub fn whiteout_m3_M3OneBoneSolver_set_maxAngle(
27784            self_: *mut whiteout_M3OneBoneSolver,
27785            value: f32,
27786        );
27787        // ShadowBox
27788        pub fn whiteout_m3_M3ShadowBox_new() -> *mut whiteout_M3ShadowBox;
27789        pub fn whiteout_m3_M3ShadowBox_delete(self_: *mut whiteout_M3ShadowBox);
27790        // ViewVolume
27791        pub fn whiteout_m3_M3ViewVolume_new() -> *mut whiteout_M3ViewVolume;
27792        pub fn whiteout_m3_M3ViewVolume_delete(self_: *mut whiteout_M3ViewVolume);
27793        pub fn whiteout_m3_M3ViewVolume_get_nodeIndex(self_: *mut whiteout_M3ViewVolume) -> u32;
27794        pub fn whiteout_m3_M3ViewVolume_set_nodeIndex(
27795            self_: *mut whiteout_M3ViewVolume,
27796            value: u32,
27797        );
27798        pub fn whiteout_m3_M3ViewVolume_get_size(
27799            self_: *mut whiteout_M3ViewVolume,
27800        ) -> *mut whiteout_M3AnimRefVector3f;
27801        pub fn whiteout_m3_M3ViewVolume_set_size(
27802            self_: *mut whiteout_M3ViewVolume,
27803            value: *const whiteout_M3AnimRefVector3f,
27804        );
27805        // TrailingModel
27806        pub fn whiteout_m3_M3TrailingModel_new() -> *mut whiteout_M3TrailingModel;
27807        pub fn whiteout_m3_M3TrailingModel_delete(self_: *mut whiteout_M3TrailingModel);
27808        pub fn whiteout_m3_M3TrailingModel_get_vectors_count(
27809            self_: *mut whiteout_M3TrailingModel,
27810        ) -> usize;
27811        pub fn whiteout_m3_M3TrailingModel_resize_vectors(
27812            self_: *mut whiteout_M3TrailingModel,
27813            count: usize,
27814        );
27815        pub fn whiteout_m3_M3TrailingModel_get_vectors_data(
27816            self_: *mut whiteout_M3TrailingModel,
27817        ) -> *const f32;
27818        pub fn whiteout_m3_M3TrailingModel_assign_vectors(
27819            self_: *mut whiteout_M3TrailingModel,
27820            data: *const f32,
27821            count: usize,
27822        );
27823        pub fn whiteout_m3_M3TrailingModel_get_param0(self_: *mut whiteout_M3TrailingModel) -> f32;
27824        pub fn whiteout_m3_M3TrailingModel_set_param0(
27825            self_: *mut whiteout_M3TrailingModel,
27826            value: f32,
27827        );
27828        pub fn whiteout_m3_M3TrailingModel_get_param1(self_: *mut whiteout_M3TrailingModel) -> f32;
27829        pub fn whiteout_m3_M3TrailingModel_set_param1(
27830            self_: *mut whiteout_M3TrailingModel,
27831            value: f32,
27832        );
27833        pub fn whiteout_m3_M3TrailingModel_get_animFloat0(
27834            self_: *mut whiteout_M3TrailingModel,
27835        ) -> *mut whiteout_M3AnimRefF32;
27836        pub fn whiteout_m3_M3TrailingModel_set_animFloat0(
27837            self_: *mut whiteout_M3TrailingModel,
27838            value: *const whiteout_M3AnimRefF32,
27839        );
27840        pub fn whiteout_m3_M3TrailingModel_get_animFloat1(
27841            self_: *mut whiteout_M3TrailingModel,
27842        ) -> *mut whiteout_M3AnimRefF32;
27843        pub fn whiteout_m3_M3TrailingModel_set_animFloat1(
27844            self_: *mut whiteout_M3TrailingModel,
27845            value: *const whiteout_M3AnimRefF32,
27846        );
27847        pub fn whiteout_m3_M3TrailingModel_get_flag(self_: *mut whiteout_M3TrailingModel) -> u32;
27848        pub fn whiteout_m3_M3TrailingModel_set_flag(
27849            self_: *mut whiteout_M3TrailingModel,
27850            value: u32,
27851        );
27852        pub fn whiteout_m3_M3TrailingModel_get_reserved0(
27853            self_: *mut whiteout_M3TrailingModel,
27854        ) -> u32;
27855        pub fn whiteout_m3_M3TrailingModel_set_reserved0(
27856            self_: *mut whiteout_M3TrailingModel,
27857            value: u32,
27858        );
27859        pub fn whiteout_m3_M3TrailingModel_get_reserved1(
27860            self_: *mut whiteout_M3TrailingModel,
27861        ) -> u32;
27862        pub fn whiteout_m3_M3TrailingModel_set_reserved1(
27863            self_: *mut whiteout_M3TrailingModel,
27864            value: u32,
27865        );
27866        // Force
27867        pub fn whiteout_m3_M3Force_new() -> *mut whiteout_M3Force;
27868        pub fn whiteout_m3_M3Force_delete(self_: *mut whiteout_M3Force);
27869        pub fn whiteout_m3_M3Force_get_forceType(self_: *mut whiteout_M3Force) -> i32;
27870        pub fn whiteout_m3_M3Force_set_forceType(self_: *mut whiteout_M3Force, value: i32);
27871        pub fn whiteout_m3_M3Force_get_forceShape(self_: *mut whiteout_M3Force) -> i32;
27872        pub fn whiteout_m3_M3Force_set_forceShape(self_: *mut whiteout_M3Force, value: i32);
27873        pub fn whiteout_m3_M3Force_get_unknown(self_: *mut whiteout_M3Force) -> u32;
27874        pub fn whiteout_m3_M3Force_set_unknown(self_: *mut whiteout_M3Force, value: u32);
27875        pub fn whiteout_m3_M3Force_get_boneIndex(self_: *mut whiteout_M3Force) -> u32;
27876        pub fn whiteout_m3_M3Force_set_boneIndex(self_: *mut whiteout_M3Force, value: u32);
27877        pub fn whiteout_m3_M3Force_get_flags(self_: *mut whiteout_M3Force) -> i32;
27878        pub fn whiteout_m3_M3Force_set_flags(self_: *mut whiteout_M3Force, value: i32);
27879        pub fn whiteout_m3_M3Force_get_localChannels(self_: *mut whiteout_M3Force) -> u32;
27880        pub fn whiteout_m3_M3Force_set_localChannels(self_: *mut whiteout_M3Force, value: u32);
27881        pub fn whiteout_m3_M3Force_get_strength(
27882            self_: *mut whiteout_M3Force,
27883        ) -> *mut whiteout_M3AnimRefF32;
27884        pub fn whiteout_m3_M3Force_set_strength(
27885            self_: *mut whiteout_M3Force,
27886            value: *const whiteout_M3AnimRefF32,
27887        );
27888        pub fn whiteout_m3_M3Force_get_width(
27889            self_: *mut whiteout_M3Force,
27890        ) -> *mut whiteout_M3AnimRefF32;
27891        pub fn whiteout_m3_M3Force_set_width(
27892            self_: *mut whiteout_M3Force,
27893            value: *const whiteout_M3AnimRefF32,
27894        );
27895        pub fn whiteout_m3_M3Force_get_height(
27896            self_: *mut whiteout_M3Force,
27897        ) -> *mut whiteout_M3AnimRefF32;
27898        pub fn whiteout_m3_M3Force_set_height(
27899            self_: *mut whiteout_M3Force,
27900            value: *const whiteout_M3AnimRefF32,
27901        );
27902        pub fn whiteout_m3_M3Force_get_length(
27903            self_: *mut whiteout_M3Force,
27904        ) -> *mut whiteout_M3AnimRefF32;
27905        pub fn whiteout_m3_M3Force_set_length(
27906            self_: *mut whiteout_M3Force,
27907            value: *const whiteout_M3AnimRefF32,
27908        );
27909        // Warp
27910        pub fn whiteout_m3_M3Warp_new() -> *mut whiteout_M3Warp;
27911        pub fn whiteout_m3_M3Warp_delete(self_: *mut whiteout_M3Warp);
27912        pub fn whiteout_m3_M3Warp_get_warpType(self_: *mut whiteout_M3Warp) -> u32;
27913        pub fn whiteout_m3_M3Warp_set_warpType(self_: *mut whiteout_M3Warp, value: u32);
27914        pub fn whiteout_m3_M3Warp_get_boneIndex(self_: *mut whiteout_M3Warp) -> u32;
27915        pub fn whiteout_m3_M3Warp_set_boneIndex(self_: *mut whiteout_M3Warp, value: u32);
27916        pub fn whiteout_m3_M3Warp_get_unknown(self_: *mut whiteout_M3Warp) -> u32;
27917        pub fn whiteout_m3_M3Warp_set_unknown(self_: *mut whiteout_M3Warp, value: u32);
27918        pub fn whiteout_m3_M3Warp_get_radius(
27919            self_: *mut whiteout_M3Warp,
27920        ) -> *mut whiteout_M3AnimRefF32;
27921        pub fn whiteout_m3_M3Warp_set_radius(
27922            self_: *mut whiteout_M3Warp,
27923            value: *const whiteout_M3AnimRefF32,
27924        );
27925        pub fn whiteout_m3_M3Warp_get_height(
27926            self_: *mut whiteout_M3Warp,
27927        ) -> *mut whiteout_M3AnimRefF32;
27928        pub fn whiteout_m3_M3Warp_set_height(
27929            self_: *mut whiteout_M3Warp,
27930            value: *const whiteout_M3AnimRefF32,
27931        );
27932        pub fn whiteout_m3_M3Warp_get_strength(
27933            self_: *mut whiteout_M3Warp,
27934        ) -> *mut whiteout_M3AnimRefF32;
27935        pub fn whiteout_m3_M3Warp_set_strength(
27936            self_: *mut whiteout_M3Warp,
27937            value: *const whiteout_M3AnimRefF32,
27938        );
27939        pub fn whiteout_m3_M3Warp_get_angular(
27940            self_: *mut whiteout_M3Warp,
27941        ) -> *mut whiteout_M3AnimRefF32;
27942        pub fn whiteout_m3_M3Warp_set_angular(
27943            self_: *mut whiteout_M3Warp,
27944            value: *const whiteout_M3AnimRefF32,
27945        );
27946        pub fn whiteout_m3_M3Warp_get_axial(
27947            self_: *mut whiteout_M3Warp,
27948        ) -> *mut whiteout_M3AnimRefF32;
27949        pub fn whiteout_m3_M3Warp_set_axial(
27950            self_: *mut whiteout_M3Warp,
27951            value: *const whiteout_M3AnimRefF32,
27952        );
27953        pub fn whiteout_m3_M3Warp_get_radial(
27954            self_: *mut whiteout_M3Warp,
27955        ) -> *mut whiteout_M3AnimRefF32;
27956        pub fn whiteout_m3_M3Warp_set_radial(
27957            self_: *mut whiteout_M3Warp,
27958            value: *const whiteout_M3AnimRefF32,
27959        );
27960        // ConvexHullHalfEdge
27961        pub fn whiteout_m3_M3ConvexHullHalfEdge_new() -> *mut whiteout_M3ConvexHullHalfEdge;
27962        pub fn whiteout_m3_M3ConvexHullHalfEdge_delete(self_: *mut whiteout_M3ConvexHullHalfEdge);
27963        pub fn whiteout_m3_M3ConvexHullHalfEdge_get_type(
27964            self_: *mut whiteout_M3ConvexHullHalfEdge,
27965        ) -> u8;
27966        pub fn whiteout_m3_M3ConvexHullHalfEdge_set_type(
27967            self_: *mut whiteout_M3ConvexHullHalfEdge,
27968            value: u8,
27969        );
27970        pub fn whiteout_m3_M3ConvexHullHalfEdge_get_faceIndex(
27971            self_: *mut whiteout_M3ConvexHullHalfEdge,
27972        ) -> u8;
27973        pub fn whiteout_m3_M3ConvexHullHalfEdge_set_faceIndex(
27974            self_: *mut whiteout_M3ConvexHullHalfEdge,
27975            value: u8,
27976        );
27977        pub fn whiteout_m3_M3ConvexHullHalfEdge_get_vertexIndex(
27978            self_: *mut whiteout_M3ConvexHullHalfEdge,
27979        ) -> u8;
27980        pub fn whiteout_m3_M3ConvexHullHalfEdge_set_vertexIndex(
27981            self_: *mut whiteout_M3ConvexHullHalfEdge,
27982            value: u8,
27983        );
27984        pub fn whiteout_m3_M3ConvexHullHalfEdge_get_nextAroundVertex(
27985            self_: *mut whiteout_M3ConvexHullHalfEdge,
27986        ) -> u8;
27987        pub fn whiteout_m3_M3ConvexHullHalfEdge_set_nextAroundVertex(
27988            self_: *mut whiteout_M3ConvexHullHalfEdge,
27989            value: u8,
27990        );
27991        // PhysicsMeshBvhNode
27992        pub fn whiteout_m3_M3PhysicsMeshBvhNode_new() -> *mut whiteout_M3PhysicsMeshBvhNode;
27993        pub fn whiteout_m3_M3PhysicsMeshBvhNode_delete(self_: *mut whiteout_M3PhysicsMeshBvhNode);
27994        // PhysicsMeshTriangle
27995        pub fn whiteout_m3_M3PhysicsMeshTriangle_new() -> *mut whiteout_M3PhysicsMeshTriangle;
27996        pub fn whiteout_m3_M3PhysicsMeshTriangle_delete(self_: *mut whiteout_M3PhysicsMeshTriangle);
27997        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex0(
27998            self_: *mut whiteout_M3PhysicsMeshTriangle,
27999        ) -> u32;
28000        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex0(
28001            self_: *mut whiteout_M3PhysicsMeshTriangle,
28002            value: u32,
28003        );
28004        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex1(
28005            self_: *mut whiteout_M3PhysicsMeshTriangle,
28006        ) -> u32;
28007        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex1(
28008            self_: *mut whiteout_M3PhysicsMeshTriangle,
28009            value: u32,
28010        );
28011        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_vertexIndex2(
28012            self_: *mut whiteout_M3PhysicsMeshTriangle,
28013        ) -> u32;
28014        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_vertexIndex2(
28015            self_: *mut whiteout_M3PhysicsMeshTriangle,
28016            value: u32,
28017        );
28018        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex0(
28019            self_: *mut whiteout_M3PhysicsMeshTriangle,
28020        ) -> u32;
28021        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex0(
28022            self_: *mut whiteout_M3PhysicsMeshTriangle,
28023            value: u32,
28024        );
28025        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex1(
28026            self_: *mut whiteout_M3PhysicsMeshTriangle,
28027        ) -> u32;
28028        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex1(
28029            self_: *mut whiteout_M3PhysicsMeshTriangle,
28030            value: u32,
28031        );
28032        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_edgeIndex2(
28033            self_: *mut whiteout_M3PhysicsMeshTriangle,
28034        ) -> u32;
28035        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_edgeIndex2(
28036            self_: *mut whiteout_M3PhysicsMeshTriangle,
28037            value: u32,
28038        );
28039        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_reserved(
28040            self_: *mut whiteout_M3PhysicsMeshTriangle,
28041        ) -> u16;
28042        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_reserved(
28043            self_: *mut whiteout_M3PhysicsMeshTriangle,
28044            value: u16,
28045        );
28046        pub fn whiteout_m3_M3PhysicsMeshTriangle_get_flags(
28047            self_: *mut whiteout_M3PhysicsMeshTriangle,
28048        ) -> u16;
28049        pub fn whiteout_m3_M3PhysicsMeshTriangle_set_flags(
28050            self_: *mut whiteout_M3PhysicsMeshTriangle,
28051            value: u16,
28052        );
28053        // PhysicsMeshEdge
28054        pub fn whiteout_m3_M3PhysicsMeshEdge_new() -> *mut whiteout_M3PhysicsMeshEdge;
28055        pub fn whiteout_m3_M3PhysicsMeshEdge_delete(self_: *mut whiteout_M3PhysicsMeshEdge);
28056        pub fn whiteout_m3_M3PhysicsMeshEdge_get_edgeType(
28057            self_: *mut whiteout_M3PhysicsMeshEdge,
28058        ) -> u32;
28059        pub fn whiteout_m3_M3PhysicsMeshEdge_set_edgeType(
28060            self_: *mut whiteout_M3PhysicsMeshEdge,
28061            value: u32,
28062        );
28063        pub fn whiteout_m3_M3PhysicsMeshEdge_get_vertexA(
28064            self_: *mut whiteout_M3PhysicsMeshEdge,
28065        ) -> u32;
28066        pub fn whiteout_m3_M3PhysicsMeshEdge_set_vertexA(
28067            self_: *mut whiteout_M3PhysicsMeshEdge,
28068            value: u32,
28069        );
28070        pub fn whiteout_m3_M3PhysicsMeshEdge_get_vertexB(
28071            self_: *mut whiteout_M3PhysicsMeshEdge,
28072        ) -> u32;
28073        pub fn whiteout_m3_M3PhysicsMeshEdge_set_vertexB(
28074            self_: *mut whiteout_M3PhysicsMeshEdge,
28075            value: u32,
28076        );
28077        pub fn whiteout_m3_M3PhysicsMeshEdge_get_faceA(
28078            self_: *mut whiteout_M3PhysicsMeshEdge,
28079        ) -> u32;
28080        pub fn whiteout_m3_M3PhysicsMeshEdge_set_faceA(
28081            self_: *mut whiteout_M3PhysicsMeshEdge,
28082            value: u32,
28083        );
28084        pub fn whiteout_m3_M3PhysicsMeshEdge_get_faceB(
28085            self_: *mut whiteout_M3PhysicsMeshEdge,
28086        ) -> u32;
28087        pub fn whiteout_m3_M3PhysicsMeshEdge_set_faceB(
28088            self_: *mut whiteout_M3PhysicsMeshEdge,
28089            value: u32,
28090        );
28091        // PhysicsShape
28092        pub fn whiteout_m3_M3PhysicsShape_new() -> *mut whiteout_M3PhysicsShape;
28093        pub fn whiteout_m3_M3PhysicsShape_delete(self_: *mut whiteout_M3PhysicsShape);
28094        pub fn whiteout_m3_M3PhysicsShape_get_collisionMargin(
28095            self_: *mut whiteout_M3PhysicsShape,
28096        ) -> f32;
28097        pub fn whiteout_m3_M3PhysicsShape_set_collisionMargin(
28098            self_: *mut whiteout_M3PhysicsShape,
28099            value: f32,
28100        );
28101        pub fn whiteout_m3_M3PhysicsShape_get_shapeType(self_: *mut whiteout_M3PhysicsShape)
28102            -> i32;
28103        pub fn whiteout_m3_M3PhysicsShape_set_shapeType(
28104            self_: *mut whiteout_M3PhysicsShape,
28105            value: i32,
28106        );
28107        pub fn whiteout_m3_M3PhysicsShape_get_oldSizes(
28108            self_: *mut whiteout_M3PhysicsShape,
28109        ) -> *mut core::ffi::c_void;
28110        pub fn whiteout_m3_M3PhysicsShape_set_oldSizes(
28111            self_: *mut whiteout_M3PhysicsShape,
28112            value: *const core::ffi::c_void,
28113        );
28114        pub fn whiteout_m3_M3PhysicsShape_get_shapeDimensions(
28115            self_: *mut whiteout_M3PhysicsShape,
28116        ) -> *mut core::ffi::c_void;
28117        pub fn whiteout_m3_M3PhysicsShape_set_shapeDimensions(
28118            self_: *mut whiteout_M3PhysicsShape,
28119            value: *const core::ffi::c_void,
28120        );
28121        pub fn whiteout_m3_M3PhysicsShape_get_hullFaceNormals_count(
28122            self_: *mut whiteout_M3PhysicsShape,
28123        ) -> usize;
28124        pub fn whiteout_m3_M3PhysicsShape_resize_hullFaceNormals(
28125            self_: *mut whiteout_M3PhysicsShape,
28126            count: usize,
28127        );
28128        pub fn whiteout_m3_M3PhysicsShape_get_hullFaceNormals_data(
28129            self_: *mut whiteout_M3PhysicsShape,
28130        ) -> *const f32;
28131        pub fn whiteout_m3_M3PhysicsShape_assign_hullFaceNormals(
28132            self_: *mut whiteout_M3PhysicsShape,
28133            data: *const f32,
28134            count: usize,
28135        );
28136        pub fn whiteout_m3_M3PhysicsShape_get_hullVertexPositions_count(
28137            self_: *mut whiteout_M3PhysicsShape,
28138        ) -> usize;
28139        pub fn whiteout_m3_M3PhysicsShape_resize_hullVertexPositions(
28140            self_: *mut whiteout_M3PhysicsShape,
28141            count: usize,
28142        );
28143        pub fn whiteout_m3_M3PhysicsShape_get_hullVertexPositions_data(
28144            self_: *mut whiteout_M3PhysicsShape,
28145        ) -> *const f32;
28146        pub fn whiteout_m3_M3PhysicsShape_assign_hullVertexPositions(
28147            self_: *mut whiteout_M3PhysicsShape,
28148            data: *const f32,
28149            count: usize,
28150        );
28151        pub fn whiteout_m3_M3PhysicsShape_get_hullHalfEdges_count(
28152            self_: *mut whiteout_M3PhysicsShape,
28153        ) -> usize;
28154        pub fn whiteout_m3_M3PhysicsShape_resize_hullHalfEdges(
28155            self_: *mut whiteout_M3PhysicsShape,
28156            count: usize,
28157        );
28158        pub fn whiteout_m3_M3PhysicsShape_get_hullHalfEdges_at(
28159            self_: *mut whiteout_M3PhysicsShape,
28160            index: usize,
28161        ) -> *mut whiteout_M3ConvexHullHalfEdge;
28162        pub fn whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_count(
28163            self_: *mut whiteout_M3PhysicsShape,
28164        ) -> usize;
28165        pub fn whiteout_m3_M3PhysicsShape_resize_hullVertexFaceIndices(
28166            self_: *mut whiteout_M3PhysicsShape,
28167            count: usize,
28168        );
28169        pub fn whiteout_m3_M3PhysicsShape_get_hullVertexFaceIndices_data(
28170            self_: *mut whiteout_M3PhysicsShape,
28171        ) -> *const u8;
28172        pub fn whiteout_m3_M3PhysicsShape_assign_hullVertexFaceIndices(
28173            self_: *mut whiteout_M3PhysicsShape,
28174            data: *const u8,
28175            count: usize,
28176        );
28177        pub fn whiteout_m3_M3PhysicsShape_get_hullCenter(
28178            self_: *mut whiteout_M3PhysicsShape,
28179        ) -> *mut core::ffi::c_void;
28180        pub fn whiteout_m3_M3PhysicsShape_set_hullCenter(
28181            self_: *mut whiteout_M3PhysicsShape,
28182            value: *const core::ffi::c_void,
28183        );
28184        pub fn whiteout_m3_M3PhysicsShape_get_hullFaceNormalCount(
28185            self_: *mut whiteout_M3PhysicsShape,
28186        ) -> u32;
28187        pub fn whiteout_m3_M3PhysicsShape_set_hullFaceNormalCount(
28188            self_: *mut whiteout_M3PhysicsShape,
28189            value: u32,
28190        );
28191        pub fn whiteout_m3_M3PhysicsShape_get_hullVertexCount(
28192            self_: *mut whiteout_M3PhysicsShape,
28193        ) -> u32;
28194        pub fn whiteout_m3_M3PhysicsShape_set_hullVertexCount(
28195            self_: *mut whiteout_M3PhysicsShape,
28196            value: u32,
28197        );
28198        pub fn whiteout_m3_M3PhysicsShape_get_hullHalfEdgeCount(
28199            self_: *mut whiteout_M3PhysicsShape,
28200        ) -> u32;
28201        pub fn whiteout_m3_M3PhysicsShape_set_hullHalfEdgeCount(
28202            self_: *mut whiteout_M3PhysicsShape,
28203            value: u32,
28204        );
28205        pub fn whiteout_m3_M3PhysicsShape_get_hullUnknown0(
28206            self_: *mut whiteout_M3PhysicsShape,
28207        ) -> f32;
28208        pub fn whiteout_m3_M3PhysicsShape_set_hullUnknown0(
28209            self_: *mut whiteout_M3PhysicsShape,
28210            value: f32,
28211        );
28212        pub fn whiteout_m3_M3PhysicsShape_get_hullUnknown1(
28213            self_: *mut whiteout_M3PhysicsShape,
28214        ) -> f32;
28215        pub fn whiteout_m3_M3PhysicsShape_set_hullUnknown1(
28216            self_: *mut whiteout_M3PhysicsShape,
28217            value: f32,
28218        );
28219        pub fn whiteout_m3_M3PhysicsShape_get_meshBvhNodes_count(
28220            self_: *mut whiteout_M3PhysicsShape,
28221        ) -> usize;
28222        pub fn whiteout_m3_M3PhysicsShape_resize_meshBvhNodes(
28223            self_: *mut whiteout_M3PhysicsShape,
28224            count: usize,
28225        );
28226        pub fn whiteout_m3_M3PhysicsShape_get_meshBvhNodes_at(
28227            self_: *mut whiteout_M3PhysicsShape,
28228            index: usize,
28229        ) -> *mut whiteout_M3PhysicsMeshBvhNode;
28230        pub fn whiteout_m3_M3PhysicsShape_get_meshVertexPositions_count(
28231            self_: *mut whiteout_M3PhysicsShape,
28232        ) -> usize;
28233        pub fn whiteout_m3_M3PhysicsShape_resize_meshVertexPositions(
28234            self_: *mut whiteout_M3PhysicsShape,
28235            count: usize,
28236        );
28237        pub fn whiteout_m3_M3PhysicsShape_get_meshVertexPositions_data(
28238            self_: *mut whiteout_M3PhysicsShape,
28239        ) -> *const f32;
28240        pub fn whiteout_m3_M3PhysicsShape_assign_meshVertexPositions(
28241            self_: *mut whiteout_M3PhysicsShape,
28242            data: *const f32,
28243            count: usize,
28244        );
28245        pub fn whiteout_m3_M3PhysicsShape_get_meshBoundsCenter(
28246            self_: *mut whiteout_M3PhysicsShape,
28247        ) -> *mut core::ffi::c_void;
28248        pub fn whiteout_m3_M3PhysicsShape_set_meshBoundsCenter(
28249            self_: *mut whiteout_M3PhysicsShape,
28250            value: *const core::ffi::c_void,
28251        );
28252        pub fn whiteout_m3_M3PhysicsShape_get_meshBoundsExtent(
28253            self_: *mut whiteout_M3PhysicsShape,
28254        ) -> *mut core::ffi::c_void;
28255        pub fn whiteout_m3_M3PhysicsShape_set_meshBoundsExtent(
28256            self_: *mut whiteout_M3PhysicsShape,
28257            value: *const core::ffi::c_void,
28258        );
28259        pub fn whiteout_m3_M3PhysicsShape_get_meshTolerance(
28260            self_: *mut whiteout_M3PhysicsShape,
28261        ) -> *mut core::ffi::c_void;
28262        pub fn whiteout_m3_M3PhysicsShape_set_meshTolerance(
28263            self_: *mut whiteout_M3PhysicsShape,
28264            value: *const core::ffi::c_void,
28265        );
28266        pub fn whiteout_m3_M3PhysicsShape_get_meshNormalCount(
28267            self_: *mut whiteout_M3PhysicsShape,
28268        ) -> u32;
28269        pub fn whiteout_m3_M3PhysicsShape_set_meshNormalCount(
28270            self_: *mut whiteout_M3PhysicsShape,
28271            value: u32,
28272        );
28273        pub fn whiteout_m3_M3PhysicsShape_get_meshVertexCount(
28274            self_: *mut whiteout_M3PhysicsShape,
28275        ) -> u32;
28276        pub fn whiteout_m3_M3PhysicsShape_set_meshVertexCount(
28277            self_: *mut whiteout_M3PhysicsShape,
28278            value: u32,
28279        );
28280        pub fn whiteout_m3_M3PhysicsShape_get_meshFaceIndex16Count(
28281            self_: *mut whiteout_M3PhysicsShape,
28282        ) -> u32;
28283        pub fn whiteout_m3_M3PhysicsShape_set_meshFaceIndex16Count(
28284            self_: *mut whiteout_M3PhysicsShape,
28285            value: u32,
28286        );
28287        pub fn whiteout_m3_M3PhysicsShape_get_meshFaceIndex32Count(
28288            self_: *mut whiteout_M3PhysicsShape,
28289        ) -> u32;
28290        pub fn whiteout_m3_M3PhysicsShape_set_meshFaceIndex32Count(
28291            self_: *mut whiteout_M3PhysicsShape,
28292            value: u32,
28293        );
28294        pub fn whiteout_m3_M3PhysicsShape_get_meshUnknown1(
28295            self_: *mut whiteout_M3PhysicsShape,
28296        ) -> u32;
28297        pub fn whiteout_m3_M3PhysicsShape_set_meshUnknown1(
28298            self_: *mut whiteout_M3PhysicsShape,
28299            value: u32,
28300        );
28301        pub fn whiteout_m3_M3PhysicsShape_get_meshReserved(
28302            self_: *mut whiteout_M3PhysicsShape,
28303        ) -> u32;
28304        pub fn whiteout_m3_M3PhysicsShape_set_meshReserved(
28305            self_: *mut whiteout_M3PhysicsShape,
28306            value: u32,
28307        );
28308        pub fn whiteout_m3_M3PhysicsShape_get_meshTreeDepth(
28309            self_: *mut whiteout_M3PhysicsShape,
28310        ) -> u32;
28311        pub fn whiteout_m3_M3PhysicsShape_set_meshTreeDepth(
28312            self_: *mut whiteout_M3PhysicsShape,
28313            value: u32,
28314        );
28315        pub fn whiteout_m3_M3PhysicsShape_get_meshCollisionMargin(
28316            self_: *mut whiteout_M3PhysicsShape,
28317        ) -> f32;
28318        pub fn whiteout_m3_M3PhysicsShape_set_meshCollisionMargin(
28319            self_: *mut whiteout_M3PhysicsShape,
28320            value: f32,
28321        );
28322        // RigidBody
28323        pub fn whiteout_m3_M3RigidBody_new() -> *mut whiteout_M3RigidBody;
28324        pub fn whiteout_m3_M3RigidBody_delete(self_: *mut whiteout_M3RigidBody);
28325        pub fn whiteout_m3_M3RigidBody_get_simulationType(self_: *mut whiteout_M3RigidBody) -> u16;
28326        pub fn whiteout_m3_M3RigidBody_set_simulationType(
28327            self_: *mut whiteout_M3RigidBody,
28328            value: u16,
28329        );
28330        pub fn whiteout_m3_M3RigidBody_get_parentBoneIndex(self_: *mut whiteout_M3RigidBody)
28331            -> u16;
28332        pub fn whiteout_m3_M3RigidBody_set_parentBoneIndex(
28333            self_: *mut whiteout_M3RigidBody,
28334            value: u16,
28335        );
28336        pub fn whiteout_m3_M3RigidBody_get_physicsType(self_: *mut whiteout_M3RigidBody) -> u32;
28337        pub fn whiteout_m3_M3RigidBody_set_physicsType(
28338            self_: *mut whiteout_M3RigidBody,
28339            value: u32,
28340        );
28341        pub fn whiteout_m3_M3RigidBody_get_density(self_: *mut whiteout_M3RigidBody) -> f32;
28342        pub fn whiteout_m3_M3RigidBody_set_density(self_: *mut whiteout_M3RigidBody, value: f32);
28343        pub fn whiteout_m3_M3RigidBody_get_friction(self_: *mut whiteout_M3RigidBody) -> f32;
28344        pub fn whiteout_m3_M3RigidBody_set_friction(self_: *mut whiteout_M3RigidBody, value: f32);
28345        pub fn whiteout_m3_M3RigidBody_get_restitution(self_: *mut whiteout_M3RigidBody) -> f32;
28346        pub fn whiteout_m3_M3RigidBody_set_restitution(
28347            self_: *mut whiteout_M3RigidBody,
28348            value: f32,
28349        );
28350        pub fn whiteout_m3_M3RigidBody_get_linearDamping(self_: *mut whiteout_M3RigidBody) -> f32;
28351        pub fn whiteout_m3_M3RigidBody_set_linearDamping(
28352            self_: *mut whiteout_M3RigidBody,
28353            value: f32,
28354        );
28355        pub fn whiteout_m3_M3RigidBody_get_angularDamping(self_: *mut whiteout_M3RigidBody) -> f32;
28356        pub fn whiteout_m3_M3RigidBody_set_angularDamping(
28357            self_: *mut whiteout_M3RigidBody,
28358            value: f32,
28359        );
28360        pub fn whiteout_m3_M3RigidBody_get_gravityScale(self_: *mut whiteout_M3RigidBody) -> f32;
28361        pub fn whiteout_m3_M3RigidBody_set_gravityScale(
28362            self_: *mut whiteout_M3RigidBody,
28363            value: f32,
28364        );
28365        pub fn whiteout_m3_M3RigidBody_get_dynamicState(
28366            self_: *mut whiteout_M3RigidBody,
28367        ) -> *mut whiteout_M3AnimRefU32;
28368        pub fn whiteout_m3_M3RigidBody_set_dynamicState(
28369            self_: *mut whiteout_M3RigidBody,
28370            value: *const whiteout_M3AnimRefU32,
28371        );
28372        pub fn whiteout_m3_M3RigidBody_get_dynamicBlendOut(self_: *mut whiteout_M3RigidBody)
28373            -> f32;
28374        pub fn whiteout_m3_M3RigidBody_set_dynamicBlendOut(
28375            self_: *mut whiteout_M3RigidBody,
28376            value: f32,
28377        );
28378        pub fn whiteout_m3_M3RigidBody_get_rigidBodyShape_count(
28379            self_: *mut whiteout_M3RigidBody,
28380        ) -> usize;
28381        pub fn whiteout_m3_M3RigidBody_resize_rigidBodyShape(
28382            self_: *mut whiteout_M3RigidBody,
28383            count: usize,
28384        );
28385        pub fn whiteout_m3_M3RigidBody_get_rigidBodyShape_at(
28386            self_: *mut whiteout_M3RigidBody,
28387            index: usize,
28388        ) -> *mut whiteout_M3PhysicsShape;
28389        pub fn whiteout_m3_M3RigidBody_get_flags(self_: *mut whiteout_M3RigidBody) -> i32;
28390        pub fn whiteout_m3_M3RigidBody_set_flags(self_: *mut whiteout_M3RigidBody, value: i32);
28391        pub fn whiteout_m3_M3RigidBody_get_localForces(self_: *mut whiteout_M3RigidBody) -> u16;
28392        pub fn whiteout_m3_M3RigidBody_set_localForces(
28393            self_: *mut whiteout_M3RigidBody,
28394            value: u16,
28395        );
28396        pub fn whiteout_m3_M3RigidBody_get_worldForces(self_: *mut whiteout_M3RigidBody) -> u16;
28397        pub fn whiteout_m3_M3RigidBody_set_worldForces(
28398            self_: *mut whiteout_M3RigidBody,
28399            value: u16,
28400        );
28401        pub fn whiteout_m3_M3RigidBody_get_priority(self_: *mut whiteout_M3RigidBody) -> u32;
28402        pub fn whiteout_m3_M3RigidBody_set_priority(self_: *mut whiteout_M3RigidBody, value: u32);
28403        // PhysicsJoint
28404        pub fn whiteout_m3_M3PhysicsJoint_new() -> *mut whiteout_M3PhysicsJoint;
28405        pub fn whiteout_m3_M3PhysicsJoint_delete(self_: *mut whiteout_M3PhysicsJoint);
28406        pub fn whiteout_m3_M3PhysicsJoint_get_jointType(self_: *mut whiteout_M3PhysicsJoint)
28407            -> u32;
28408        pub fn whiteout_m3_M3PhysicsJoint_set_jointType(
28409            self_: *mut whiteout_M3PhysicsJoint,
28410            value: u32,
28411        );
28412        pub fn whiteout_m3_M3PhysicsJoint_get_boneIndex1(
28413            self_: *mut whiteout_M3PhysicsJoint,
28414        ) -> u32;
28415        pub fn whiteout_m3_M3PhysicsJoint_set_boneIndex1(
28416            self_: *mut whiteout_M3PhysicsJoint,
28417            value: u32,
28418        );
28419        pub fn whiteout_m3_M3PhysicsJoint_get_boneIndex2(
28420            self_: *mut whiteout_M3PhysicsJoint,
28421        ) -> u32;
28422        pub fn whiteout_m3_M3PhysicsJoint_set_boneIndex2(
28423            self_: *mut whiteout_M3PhysicsJoint,
28424            value: u32,
28425        );
28426        pub fn whiteout_m3_M3PhysicsJoint_get_enableLimits(
28427            self_: *mut whiteout_M3PhysicsJoint,
28428        ) -> u32;
28429        pub fn whiteout_m3_M3PhysicsJoint_set_enableLimits(
28430            self_: *mut whiteout_M3PhysicsJoint,
28431            value: u32,
28432        );
28433        pub fn whiteout_m3_M3PhysicsJoint_get_limitMin(self_: *mut whiteout_M3PhysicsJoint) -> f32;
28434        pub fn whiteout_m3_M3PhysicsJoint_set_limitMin(
28435            self_: *mut whiteout_M3PhysicsJoint,
28436            value: f32,
28437        );
28438        pub fn whiteout_m3_M3PhysicsJoint_get_limitMax(self_: *mut whiteout_M3PhysicsJoint) -> f32;
28439        pub fn whiteout_m3_M3PhysicsJoint_set_limitMax(
28440            self_: *mut whiteout_M3PhysicsJoint,
28441            value: f32,
28442        );
28443        pub fn whiteout_m3_M3PhysicsJoint_get_coneAngle(self_: *mut whiteout_M3PhysicsJoint)
28444            -> f32;
28445        pub fn whiteout_m3_M3PhysicsJoint_set_coneAngle(
28446            self_: *mut whiteout_M3PhysicsJoint,
28447            value: f32,
28448        );
28449        pub fn whiteout_m3_M3PhysicsJoint_get_enableFriction(
28450            self_: *mut whiteout_M3PhysicsJoint,
28451        ) -> u32;
28452        pub fn whiteout_m3_M3PhysicsJoint_set_enableFriction(
28453            self_: *mut whiteout_M3PhysicsJoint,
28454            value: u32,
28455        );
28456        pub fn whiteout_m3_M3PhysicsJoint_get_friction(self_: *mut whiteout_M3PhysicsJoint) -> f32;
28457        pub fn whiteout_m3_M3PhysicsJoint_set_friction(
28458            self_: *mut whiteout_M3PhysicsJoint,
28459            value: f32,
28460        );
28461        pub fn whiteout_m3_M3PhysicsJoint_get_dampingRatio(
28462            self_: *mut whiteout_M3PhysicsJoint,
28463        ) -> f32;
28464        pub fn whiteout_m3_M3PhysicsJoint_set_dampingRatio(
28465            self_: *mut whiteout_M3PhysicsJoint,
28466            value: f32,
28467        );
28468        pub fn whiteout_m3_M3PhysicsJoint_get_angularFrequency(
28469            self_: *mut whiteout_M3PhysicsJoint,
28470        ) -> f32;
28471        pub fn whiteout_m3_M3PhysicsJoint_set_angularFrequency(
28472            self_: *mut whiteout_M3PhysicsJoint,
28473            value: f32,
28474        );
28475        pub fn whiteout_m3_M3PhysicsJoint_get_breakThreshold(
28476            self_: *mut whiteout_M3PhysicsJoint,
28477        ) -> f32;
28478        pub fn whiteout_m3_M3PhysicsJoint_set_breakThreshold(
28479            self_: *mut whiteout_M3PhysicsJoint,
28480            value: f32,
28481        );
28482        pub fn whiteout_m3_M3PhysicsJoint_get_enableShape(
28483            self_: *mut whiteout_M3PhysicsJoint,
28484        ) -> u8;
28485        pub fn whiteout_m3_M3PhysicsJoint_set_enableShape(
28486            self_: *mut whiteout_M3PhysicsJoint,
28487            value: u8,
28488        );
28489        // PhysicsConstraint
28490        pub fn whiteout_m3_M3PhysicsConstraint_new() -> *mut whiteout_M3PhysicsConstraint;
28491        pub fn whiteout_m3_M3PhysicsConstraint_delete(self_: *mut whiteout_M3PhysicsConstraint);
28492        pub fn whiteout_m3_M3PhysicsConstraint_get_dependents_count(
28493            self_: *mut whiteout_M3PhysicsConstraint,
28494        ) -> usize;
28495        pub fn whiteout_m3_M3PhysicsConstraint_resize_dependents(
28496            self_: *mut whiteout_M3PhysicsConstraint,
28497            count: usize,
28498        );
28499        pub fn whiteout_m3_M3PhysicsConstraint_get_dependents_data(
28500            self_: *mut whiteout_M3PhysicsConstraint,
28501        ) -> *const u16;
28502        pub fn whiteout_m3_M3PhysicsConstraint_assign_dependents(
28503            self_: *mut whiteout_M3PhysicsConstraint,
28504            data: *const u16,
28505            count: usize,
28506        );
28507        pub fn whiteout_m3_M3PhysicsConstraint_get_rigidBody1(
28508            self_: *mut whiteout_M3PhysicsConstraint,
28509        ) -> u16;
28510        pub fn whiteout_m3_M3PhysicsConstraint_set_rigidBody1(
28511            self_: *mut whiteout_M3PhysicsConstraint,
28512            value: u16,
28513        );
28514        pub fn whiteout_m3_M3PhysicsConstraint_get_rigidBody2(
28515            self_: *mut whiteout_M3PhysicsConstraint,
28516        ) -> u16;
28517        pub fn whiteout_m3_M3PhysicsConstraint_set_rigidBody2(
28518            self_: *mut whiteout_M3PhysicsConstraint,
28519            value: u16,
28520        );
28521        pub fn whiteout_m3_M3PhysicsConstraint_get_breakForce(
28522            self_: *mut whiteout_M3PhysicsConstraint,
28523        ) -> f32;
28524        pub fn whiteout_m3_M3PhysicsConstraint_set_breakForce(
28525            self_: *mut whiteout_M3PhysicsConstraint,
28526            value: f32,
28527        );
28528        // ClothCollider
28529        pub fn whiteout_m3_M3ClothCollider_new() -> *mut whiteout_M3ClothCollider;
28530        pub fn whiteout_m3_M3ClothCollider_delete(self_: *mut whiteout_M3ClothCollider);
28531        pub fn whiteout_m3_M3ClothCollider_get_radius(self_: *mut whiteout_M3ClothCollider) -> f32;
28532        pub fn whiteout_m3_M3ClothCollider_set_radius(
28533            self_: *mut whiteout_M3ClothCollider,
28534            value: f32,
28535        );
28536        pub fn whiteout_m3_M3ClothCollider_get_height(self_: *mut whiteout_M3ClothCollider) -> f32;
28537        pub fn whiteout_m3_M3ClothCollider_set_height(
28538            self_: *mut whiteout_M3ClothCollider,
28539            value: f32,
28540        );
28541        pub fn whiteout_m3_M3ClothCollider_get_padding(self_: *mut whiteout_M3ClothCollider)
28542            -> u32;
28543        pub fn whiteout_m3_M3ClothCollider_set_padding(
28544            self_: *mut whiteout_M3ClothCollider,
28545            value: u32,
28546        );
28547        // ClothProxy
28548        pub fn whiteout_m3_M3ClothProxy_new() -> *mut whiteout_M3ClothProxy;
28549        pub fn whiteout_m3_M3ClothProxy_delete(self_: *mut whiteout_M3ClothProxy);
28550        pub fn whiteout_m3_M3ClothProxy_get_proxyIndex(self_: *mut whiteout_M3ClothProxy) -> u32;
28551        pub fn whiteout_m3_M3ClothProxy_set_proxyIndex(
28552            self_: *mut whiteout_M3ClothProxy,
28553            value: u32,
28554        );
28555        pub fn whiteout_m3_M3ClothProxy_get_clothIndex(self_: *mut whiteout_M3ClothProxy) -> u32;
28556        pub fn whiteout_m3_M3ClothProxy_set_clothIndex(
28557            self_: *mut whiteout_M3ClothProxy,
28558            value: u32,
28559        );
28560        pub fn whiteout_m3_M3ClothProxy_get_proxyVertices_count(
28561            self_: *mut whiteout_M3ClothProxy,
28562        ) -> usize;
28563        pub fn whiteout_m3_M3ClothProxy_resize_proxyVertices(
28564            self_: *mut whiteout_M3ClothProxy,
28565            count: usize,
28566        );
28567        pub fn whiteout_m3_M3ClothProxy_get_proxyVertices_data(
28568            self_: *mut whiteout_M3ClothProxy,
28569        ) -> *const u64;
28570        pub fn whiteout_m3_M3ClothProxy_assign_proxyVertices(
28571            self_: *mut whiteout_M3ClothProxy,
28572            data: *const u64,
28573            count: usize,
28574        );
28575        pub fn whiteout_m3_M3ClothProxy_get_proxyWeights_count(
28576            self_: *mut whiteout_M3ClothProxy,
28577        ) -> usize;
28578        pub fn whiteout_m3_M3ClothProxy_resize_proxyWeights(
28579            self_: *mut whiteout_M3ClothProxy,
28580            count: usize,
28581        );
28582        pub fn whiteout_m3_M3ClothProxy_get_proxyWeights_data(
28583            self_: *mut whiteout_M3ClothProxy,
28584        ) -> *const u32;
28585        pub fn whiteout_m3_M3ClothProxy_assign_proxyWeights(
28586            self_: *mut whiteout_M3ClothProxy,
28587            data: *const u32,
28588            count: usize,
28589        );
28590        // ClothPhysics
28591        pub fn whiteout_m3_M3ClothPhysics_new() -> *mut whiteout_M3ClothPhysics;
28592        pub fn whiteout_m3_M3ClothPhysics_delete(self_: *mut whiteout_M3ClothPhysics);
28593        pub fn whiteout_m3_M3ClothPhysics_get_clothMeshCount(
28594            self_: *mut whiteout_M3ClothPhysics,
28595        ) -> u32;
28596        pub fn whiteout_m3_M3ClothPhysics_set_clothMeshCount(
28597            self_: *mut whiteout_M3ClothPhysics,
28598            value: u32,
28599        );
28600        pub fn whiteout_m3_M3ClothPhysics_get_skinBoneCount(
28601            self_: *mut whiteout_M3ClothPhysics,
28602        ) -> u32;
28603        pub fn whiteout_m3_M3ClothPhysics_set_skinBoneCount(
28604            self_: *mut whiteout_M3ClothPhysics,
28605            value: u32,
28606        );
28607        pub fn whiteout_m3_M3ClothPhysics_get_skinBones_count(
28608            self_: *mut whiteout_M3ClothPhysics,
28609        ) -> usize;
28610        pub fn whiteout_m3_M3ClothPhysics_resize_skinBones(
28611            self_: *mut whiteout_M3ClothPhysics,
28612            count: usize,
28613        );
28614        pub fn whiteout_m3_M3ClothPhysics_get_skinBones_data(
28615            self_: *mut whiteout_M3ClothPhysics,
28616        ) -> *const u16;
28617        pub fn whiteout_m3_M3ClothPhysics_assign_skinBones(
28618            self_: *mut whiteout_M3ClothPhysics,
28619            data: *const u16,
28620            count: usize,
28621        );
28622        pub fn whiteout_m3_M3ClothPhysics_get_simEnabled_count(
28623            self_: *mut whiteout_M3ClothPhysics,
28624        ) -> usize;
28625        pub fn whiteout_m3_M3ClothPhysics_resize_simEnabled(
28626            self_: *mut whiteout_M3ClothPhysics,
28627            count: usize,
28628        );
28629        pub fn whiteout_m3_M3ClothPhysics_get_simEnabled_data(
28630            self_: *mut whiteout_M3ClothPhysics,
28631        ) -> *const u8;
28632        pub fn whiteout_m3_M3ClothPhysics_assign_simEnabled(
28633            self_: *mut whiteout_M3ClothPhysics,
28634            data: *const u8,
28635            count: usize,
28636        );
28637        pub fn whiteout_m3_M3ClothPhysics_get_vertexBones_count(
28638            self_: *mut whiteout_M3ClothPhysics,
28639        ) -> usize;
28640        pub fn whiteout_m3_M3ClothPhysics_resize_vertexBones(
28641            self_: *mut whiteout_M3ClothPhysics,
28642            count: usize,
28643        );
28644        pub fn whiteout_m3_M3ClothPhysics_get_vertexBones_data(
28645            self_: *mut whiteout_M3ClothPhysics,
28646        ) -> *const u32;
28647        pub fn whiteout_m3_M3ClothPhysics_assign_vertexBones(
28648            self_: *mut whiteout_M3ClothPhysics,
28649            data: *const u32,
28650            count: usize,
28651        );
28652        pub fn whiteout_m3_M3ClothPhysics_get_vertexWeights_count(
28653            self_: *mut whiteout_M3ClothPhysics,
28654        ) -> usize;
28655        pub fn whiteout_m3_M3ClothPhysics_resize_vertexWeights(
28656            self_: *mut whiteout_M3ClothPhysics,
28657            count: usize,
28658        );
28659        pub fn whiteout_m3_M3ClothPhysics_get_vertexWeights_data(
28660            self_: *mut whiteout_M3ClothPhysics,
28661        ) -> *const u32;
28662        pub fn whiteout_m3_M3ClothPhysics_assign_vertexWeights(
28663            self_: *mut whiteout_M3ClothPhysics,
28664            data: *const u32,
28665            count: usize,
28666        );
28667        pub fn whiteout_m3_M3ClothPhysics_get_colliders_count(
28668            self_: *mut whiteout_M3ClothPhysics,
28669        ) -> usize;
28670        pub fn whiteout_m3_M3ClothPhysics_resize_colliders(
28671            self_: *mut whiteout_M3ClothPhysics,
28672            count: usize,
28673        );
28674        pub fn whiteout_m3_M3ClothPhysics_get_colliders_at(
28675            self_: *mut whiteout_M3ClothPhysics,
28676            index: usize,
28677        ) -> *mut whiteout_M3ClothCollider;
28678        pub fn whiteout_m3_M3ClothPhysics_get_proxies_count(
28679            self_: *mut whiteout_M3ClothPhysics,
28680        ) -> usize;
28681        pub fn whiteout_m3_M3ClothPhysics_resize_proxies(
28682            self_: *mut whiteout_M3ClothPhysics,
28683            count: usize,
28684        );
28685        pub fn whiteout_m3_M3ClothPhysics_get_proxies_at(
28686            self_: *mut whiteout_M3ClothPhysics,
28687            index: usize,
28688        ) -> *mut whiteout_M3ClothProxy;
28689        pub fn whiteout_m3_M3ClothPhysics_get_density(self_: *mut whiteout_M3ClothPhysics) -> f32;
28690        pub fn whiteout_m3_M3ClothPhysics_set_density(
28691            self_: *mut whiteout_M3ClothPhysics,
28692            value: f32,
28693        );
28694        pub fn whiteout_m3_M3ClothPhysics_get_tracking(self_: *mut whiteout_M3ClothPhysics) -> f32;
28695        pub fn whiteout_m3_M3ClothPhysics_set_tracking(
28696            self_: *mut whiteout_M3ClothPhysics,
28697            value: f32,
28698        );
28699        pub fn whiteout_m3_M3ClothPhysics_get_stretchStiffness(
28700            self_: *mut whiteout_M3ClothPhysics,
28701        ) -> f32;
28702        pub fn whiteout_m3_M3ClothPhysics_set_stretchStiffness(
28703            self_: *mut whiteout_M3ClothPhysics,
28704            value: f32,
28705        );
28706        pub fn whiteout_m3_M3ClothPhysics_get_horizontalStiffness(
28707            self_: *mut whiteout_M3ClothPhysics,
28708        ) -> f32;
28709        pub fn whiteout_m3_M3ClothPhysics_set_horizontalStiffness(
28710            self_: *mut whiteout_M3ClothPhysics,
28711            value: f32,
28712        );
28713        pub fn whiteout_m3_M3ClothPhysics_get_bendingStiffness(
28714            self_: *mut whiteout_M3ClothPhysics,
28715        ) -> f32;
28716        pub fn whiteout_m3_M3ClothPhysics_set_bendingStiffness(
28717            self_: *mut whiteout_M3ClothPhysics,
28718            value: f32,
28719        );
28720        pub fn whiteout_m3_M3ClothPhysics_get_damping(self_: *mut whiteout_M3ClothPhysics) -> f32;
28721        pub fn whiteout_m3_M3ClothPhysics_set_damping(
28722            self_: *mut whiteout_M3ClothPhysics,
28723            value: f32,
28724        );
28725        pub fn whiteout_m3_M3ClothPhysics_get_friction(self_: *mut whiteout_M3ClothPhysics) -> f32;
28726        pub fn whiteout_m3_M3ClothPhysics_set_friction(
28727            self_: *mut whiteout_M3ClothPhysics,
28728            value: f32,
28729        );
28730        pub fn whiteout_m3_M3ClothPhysics_get_gravity(self_: *mut whiteout_M3ClothPhysics) -> f32;
28731        pub fn whiteout_m3_M3ClothPhysics_set_gravity(
28732            self_: *mut whiteout_M3ClothPhysics,
28733            value: f32,
28734        );
28735        pub fn whiteout_m3_M3ClothPhysics_get_explosionScale(
28736            self_: *mut whiteout_M3ClothPhysics,
28737        ) -> f32;
28738        pub fn whiteout_m3_M3ClothPhysics_set_explosionScale(
28739            self_: *mut whiteout_M3ClothPhysics,
28740            value: f32,
28741        );
28742        pub fn whiteout_m3_M3ClothPhysics_get_windScale(self_: *mut whiteout_M3ClothPhysics)
28743            -> f32;
28744        pub fn whiteout_m3_M3ClothPhysics_set_windScale(
28745            self_: *mut whiteout_M3ClothPhysics,
28746            value: f32,
28747        );
28748        pub fn whiteout_m3_M3ClothPhysics_get_shearStiffness(
28749            self_: *mut whiteout_M3ClothPhysics,
28750        ) -> f32;
28751        pub fn whiteout_m3_M3ClothPhysics_set_shearStiffness(
28752            self_: *mut whiteout_M3ClothPhysics,
28753            value: f32,
28754        );
28755        pub fn whiteout_m3_M3ClothPhysics_get_dragFactor(
28756            self_: *mut whiteout_M3ClothPhysics,
28757        ) -> f32;
28758        pub fn whiteout_m3_M3ClothPhysics_set_dragFactor(
28759            self_: *mut whiteout_M3ClothPhysics,
28760            value: f32,
28761        );
28762        pub fn whiteout_m3_M3ClothPhysics_get_liftFactor(
28763            self_: *mut whiteout_M3ClothPhysics,
28764        ) -> f32;
28765        pub fn whiteout_m3_M3ClothPhysics_set_liftFactor(
28766            self_: *mut whiteout_M3ClothPhysics,
28767            value: f32,
28768        );
28769        pub fn whiteout_m3_M3ClothPhysics_get_sphereStiffness(
28770            self_: *mut whiteout_M3ClothPhysics,
28771        ) -> f32;
28772        pub fn whiteout_m3_M3ClothPhysics_set_sphereStiffness(
28773            self_: *mut whiteout_M3ClothPhysics,
28774            value: f32,
28775        );
28776        pub fn whiteout_m3_M3ClothPhysics_get_flatten(self_: *mut whiteout_M3ClothPhysics) -> u32;
28777        pub fn whiteout_m3_M3ClothPhysics_set_flatten(
28778            self_: *mut whiteout_M3ClothPhysics,
28779            value: u32,
28780        );
28781        pub fn whiteout_m3_M3ClothPhysics_get_active(
28782            self_: *mut whiteout_M3ClothPhysics,
28783        ) -> *mut whiteout_M3AnimRefU32;
28784        pub fn whiteout_m3_M3ClothPhysics_set_active(
28785            self_: *mut whiteout_M3ClothPhysics,
28786            value: *const whiteout_M3AnimRefU32,
28787        );
28788        pub fn whiteout_m3_M3ClothPhysics_get_useSkinCollision(
28789            self_: *mut whiteout_M3ClothPhysics,
28790        ) -> u32;
28791        pub fn whiteout_m3_M3ClothPhysics_set_useSkinCollision(
28792            self_: *mut whiteout_M3ClothPhysics,
28793            value: u32,
28794        );
28795        pub fn whiteout_m3_M3ClothPhysics_get_skinOffset(
28796            self_: *mut whiteout_M3ClothPhysics,
28797        ) -> f32;
28798        pub fn whiteout_m3_M3ClothPhysics_set_skinOffset(
28799            self_: *mut whiteout_M3ClothPhysics,
28800            value: f32,
28801        );
28802        pub fn whiteout_m3_M3ClothPhysics_get_skinExponent(
28803            self_: *mut whiteout_M3ClothPhysics,
28804        ) -> f32;
28805        pub fn whiteout_m3_M3ClothPhysics_set_skinExponent(
28806            self_: *mut whiteout_M3ClothPhysics,
28807            value: f32,
28808        );
28809        pub fn whiteout_m3_M3ClothPhysics_get_skinStiffness(
28810            self_: *mut whiteout_M3ClothPhysics,
28811        ) -> f32;
28812        pub fn whiteout_m3_M3ClothPhysics_set_skinStiffness(
28813            self_: *mut whiteout_M3ClothPhysics,
28814            value: f32,
28815        );
28816        pub fn whiteout_m3_M3ClothPhysics_get_localChannels(
28817            self_: *mut whiteout_M3ClothPhysics,
28818        ) -> u32;
28819        pub fn whiteout_m3_M3ClothPhysics_set_localChannels(
28820            self_: *mut whiteout_M3ClothPhysics,
28821            value: u32,
28822        );
28823        pub fn whiteout_m3_M3ClothPhysics_get_localWind(
28824            self_: *mut whiteout_M3ClothPhysics,
28825        ) -> *mut core::ffi::c_void;
28826        pub fn whiteout_m3_M3ClothPhysics_set_localWind(
28827            self_: *mut whiteout_M3ClothPhysics,
28828            value: *const core::ffi::c_void,
28829        );
28830        // Light
28831        pub fn whiteout_m3_M3Light_new() -> *mut whiteout_M3Light;
28832        pub fn whiteout_m3_M3Light_delete(self_: *mut whiteout_M3Light);
28833        pub fn whiteout_m3_M3Light_get_lightType(self_: *mut whiteout_M3Light) -> i32;
28834        pub fn whiteout_m3_M3Light_set_lightType(self_: *mut whiteout_M3Light, value: i32);
28835        pub fn whiteout_m3_M3Light_get_boneIndex(self_: *mut whiteout_M3Light) -> u16;
28836        pub fn whiteout_m3_M3Light_set_boneIndex(self_: *mut whiteout_M3Light, value: u16);
28837        pub fn whiteout_m3_M3Light_get_flags(self_: *mut whiteout_M3Light) -> i32;
28838        pub fn whiteout_m3_M3Light_set_flags(self_: *mut whiteout_M3Light, value: i32);
28839        pub fn whiteout_m3_M3Light_get_lodCut(self_: *mut whiteout_M3Light) -> u32;
28840        pub fn whiteout_m3_M3Light_set_lodCut(self_: *mut whiteout_M3Light, value: u32);
28841        pub fn whiteout_m3_M3Light_get_shadowLodCut(self_: *mut whiteout_M3Light) -> u32;
28842        pub fn whiteout_m3_M3Light_set_shadowLodCut(self_: *mut whiteout_M3Light, value: u32);
28843        pub fn whiteout_m3_M3Light_get_diffuseColor(
28844            self_: *mut whiteout_M3Light,
28845        ) -> *mut whiteout_M3AnimRefVector3f;
28846        pub fn whiteout_m3_M3Light_set_diffuseColor(
28847            self_: *mut whiteout_M3Light,
28848            value: *const whiteout_M3AnimRefVector3f,
28849        );
28850        pub fn whiteout_m3_M3Light_get_intensityMultiplier(
28851            self_: *mut whiteout_M3Light,
28852        ) -> *mut whiteout_M3AnimRefF32;
28853        pub fn whiteout_m3_M3Light_set_intensityMultiplier(
28854            self_: *mut whiteout_M3Light,
28855            value: *const whiteout_M3AnimRefF32,
28856        );
28857        pub fn whiteout_m3_M3Light_get_specularColor(
28858            self_: *mut whiteout_M3Light,
28859        ) -> *mut whiteout_M3AnimRefVector3f;
28860        pub fn whiteout_m3_M3Light_set_specularColor(
28861            self_: *mut whiteout_M3Light,
28862            value: *const whiteout_M3AnimRefVector3f,
28863        );
28864        pub fn whiteout_m3_M3Light_get_specularMultiplier(
28865            self_: *mut whiteout_M3Light,
28866        ) -> *mut whiteout_M3AnimRefF32;
28867        pub fn whiteout_m3_M3Light_set_specularMultiplier(
28868            self_: *mut whiteout_M3Light,
28869            value: *const whiteout_M3AnimRefF32,
28870        );
28871        pub fn whiteout_m3_M3Light_get_decay(
28872            self_: *mut whiteout_M3Light,
28873        ) -> *mut whiteout_M3AnimRefF32;
28874        pub fn whiteout_m3_M3Light_set_decay(
28875            self_: *mut whiteout_M3Light,
28876            value: *const whiteout_M3AnimRefF32,
28877        );
28878        pub fn whiteout_m3_M3Light_get_attenuationEnd(self_: *mut whiteout_M3Light) -> f32;
28879        pub fn whiteout_m3_M3Light_set_attenuationEnd(self_: *mut whiteout_M3Light, value: f32);
28880        pub fn whiteout_m3_M3Light_get_attenuationStart(
28881            self_: *mut whiteout_M3Light,
28882        ) -> *mut whiteout_M3AnimRefF32;
28883        pub fn whiteout_m3_M3Light_set_attenuationStart(
28884            self_: *mut whiteout_M3Light,
28885            value: *const whiteout_M3AnimRefF32,
28886        );
28887        pub fn whiteout_m3_M3Light_get_hotSpot(
28888            self_: *mut whiteout_M3Light,
28889        ) -> *mut whiteout_M3AnimRefF32;
28890        pub fn whiteout_m3_M3Light_set_hotSpot(
28891            self_: *mut whiteout_M3Light,
28892            value: *const whiteout_M3AnimRefF32,
28893        );
28894        pub fn whiteout_m3_M3Light_get_falloff(
28895            self_: *mut whiteout_M3Light,
28896        ) -> *mut whiteout_M3AnimRefF32;
28897        pub fn whiteout_m3_M3Light_set_falloff(
28898            self_: *mut whiteout_M3Light,
28899            value: *const whiteout_M3AnimRefF32,
28900        );
28901        // Camera
28902        pub fn whiteout_m3_M3Camera_new() -> *mut whiteout_M3Camera;
28903        pub fn whiteout_m3_M3Camera_delete(self_: *mut whiteout_M3Camera);
28904        pub fn whiteout_m3_M3Camera_get_boneIndex(self_: *mut whiteout_M3Camera) -> u32;
28905        pub fn whiteout_m3_M3Camera_set_boneIndex(self_: *mut whiteout_M3Camera, value: u32);
28906        pub fn whiteout_m3_M3Camera_get_name(self_: *mut whiteout_M3Camera) -> RawCString;
28907        pub fn whiteout_m3_M3Camera_set_name(
28908            self_: *mut whiteout_M3Camera,
28909            value: *const core::ffi::c_char,
28910        );
28911        pub fn whiteout_m3_M3Camera_get_fieldOfView(
28912            self_: *mut whiteout_M3Camera,
28913        ) -> *mut whiteout_M3AnimRefF32;
28914        pub fn whiteout_m3_M3Camera_set_fieldOfView(
28915            self_: *mut whiteout_M3Camera,
28916            value: *const whiteout_M3AnimRefF32,
28917        );
28918        pub fn whiteout_m3_M3Camera_get_useVerticalFOV(self_: *mut whiteout_M3Camera) -> u32;
28919        pub fn whiteout_m3_M3Camera_set_useVerticalFOV(self_: *mut whiteout_M3Camera, value: u32);
28920        pub fn whiteout_m3_M3Camera_get_dofType(self_: *mut whiteout_M3Camera) -> u32;
28921        pub fn whiteout_m3_M3Camera_set_dofType(self_: *mut whiteout_M3Camera, value: u32);
28922        pub fn whiteout_m3_M3Camera_get_farClip(
28923            self_: *mut whiteout_M3Camera,
28924        ) -> *mut whiteout_M3AnimRefF32;
28925        pub fn whiteout_m3_M3Camera_set_farClip(
28926            self_: *mut whiteout_M3Camera,
28927            value: *const whiteout_M3AnimRefF32,
28928        );
28929        pub fn whiteout_m3_M3Camera_get_nearClip(
28930            self_: *mut whiteout_M3Camera,
28931        ) -> *mut whiteout_M3AnimRefF32;
28932        pub fn whiteout_m3_M3Camera_set_nearClip(
28933            self_: *mut whiteout_M3Camera,
28934            value: *const whiteout_M3AnimRefF32,
28935        );
28936        pub fn whiteout_m3_M3Camera_get_shadowClipDistance(
28937            self_: *mut whiteout_M3Camera,
28938        ) -> *mut whiteout_M3AnimRefF32;
28939        pub fn whiteout_m3_M3Camera_set_shadowClipDistance(
28940            self_: *mut whiteout_M3Camera,
28941            value: *const whiteout_M3AnimRefF32,
28942        );
28943        pub fn whiteout_m3_M3Camera_get_focusDistance(
28944            self_: *mut whiteout_M3Camera,
28945        ) -> *mut whiteout_M3AnimRefF32;
28946        pub fn whiteout_m3_M3Camera_set_focusDistance(
28947            self_: *mut whiteout_M3Camera,
28948            value: *const whiteout_M3AnimRefF32,
28949        );
28950        pub fn whiteout_m3_M3Camera_get_farFocusRange(
28951            self_: *mut whiteout_M3Camera,
28952        ) -> *mut whiteout_M3AnimRefF32;
28953        pub fn whiteout_m3_M3Camera_set_farFocusRange(
28954            self_: *mut whiteout_M3Camera,
28955            value: *const whiteout_M3AnimRefF32,
28956        );
28957        pub fn whiteout_m3_M3Camera_get_nearFocusRange(
28958            self_: *mut whiteout_M3Camera,
28959        ) -> *mut whiteout_M3AnimRefF32;
28960        pub fn whiteout_m3_M3Camera_set_nearFocusRange(
28961            self_: *mut whiteout_M3Camera,
28962            value: *const whiteout_M3AnimRefF32,
28963        );
28964        pub fn whiteout_m3_M3Camera_get_nearFalloffStart(
28965            self_: *mut whiteout_M3Camera,
28966        ) -> *mut whiteout_M3AnimRefF32;
28967        pub fn whiteout_m3_M3Camera_set_nearFalloffStart(
28968            self_: *mut whiteout_M3Camera,
28969            value: *const whiteout_M3AnimRefF32,
28970        );
28971        pub fn whiteout_m3_M3Camera_get_nearFalloffEnd(
28972            self_: *mut whiteout_M3Camera,
28973        ) -> *mut whiteout_M3AnimRefF32;
28974        pub fn whiteout_m3_M3Camera_set_nearFalloffEnd(
28975            self_: *mut whiteout_M3Camera,
28976            value: *const whiteout_M3AnimRefF32,
28977        );
28978        pub fn whiteout_m3_M3Camera_get_dofAmount(
28979            self_: *mut whiteout_M3Camera,
28980        ) -> *mut whiteout_M3AnimRefF32;
28981        pub fn whiteout_m3_M3Camera_set_dofAmount(
28982            self_: *mut whiteout_M3Camera,
28983            value: *const whiteout_M3AnimRefF32,
28984        );
28985        pub fn whiteout_m3_M3Camera_get_bokehFStop(
28986            self_: *mut whiteout_M3Camera,
28987        ) -> *mut whiteout_M3AnimRefF32;
28988        pub fn whiteout_m3_M3Camera_set_bokehFStop(
28989            self_: *mut whiteout_M3Camera,
28990            value: *const whiteout_M3AnimRefF32,
28991        );
28992        pub fn whiteout_m3_M3Camera_get_bokehMaxCoCDiameter(
28993            self_: *mut whiteout_M3Camera,
28994        ) -> *mut whiteout_M3AnimRefF32;
28995        pub fn whiteout_m3_M3Camera_set_bokehMaxCoCDiameter(
28996            self_: *mut whiteout_M3Camera,
28997            value: *const whiteout_M3AnimRefF32,
28998        );
28999        // Model
29000        pub fn whiteout_m3_M3Model_new() -> *mut whiteout_M3Model;
29001        pub fn whiteout_m3_M3Model_delete(self_: *mut whiteout_M3Model);
29002        pub fn whiteout_m3_M3Model_get_name(self_: *mut whiteout_M3Model) -> RawCString;
29003        pub fn whiteout_m3_M3Model_set_name(
29004            self_: *mut whiteout_M3Model,
29005            value: *const core::ffi::c_char,
29006        );
29007        pub fn whiteout_m3_M3Model_get_flags(self_: *mut whiteout_M3Model) -> i32;
29008        pub fn whiteout_m3_M3Model_set_flags(self_: *mut whiteout_M3Model, value: i32);
29009        pub fn whiteout_m3_M3Model_get_sequences_count(self_: *mut whiteout_M3Model) -> usize;
29010        pub fn whiteout_m3_M3Model_resize_sequences(self_: *mut whiteout_M3Model, count: usize);
29011        pub fn whiteout_m3_M3Model_get_sequences_at(
29012            self_: *mut whiteout_M3Model,
29013            index: usize,
29014        ) -> *mut whiteout_M3Sequence;
29015        pub fn whiteout_m3_M3Model_get_subTrackCollections_count(
29016            self_: *mut whiteout_M3Model,
29017        ) -> usize;
29018        pub fn whiteout_m3_M3Model_resize_subTrackCollections(
29019            self_: *mut whiteout_M3Model,
29020            count: usize,
29021        );
29022        pub fn whiteout_m3_M3Model_get_subTrackCollections_at(
29023            self_: *mut whiteout_M3Model,
29024            index: usize,
29025        ) -> *mut whiteout_M3SubTrackContainer;
29026        pub fn whiteout_m3_M3Model_get_animationGroups_count(self_: *mut whiteout_M3Model)
29027            -> usize;
29028        pub fn whiteout_m3_M3Model_resize_animationGroups(
29029            self_: *mut whiteout_M3Model,
29030            count: usize,
29031        );
29032        pub fn whiteout_m3_M3Model_get_animationGroups_at(
29033            self_: *mut whiteout_M3Model,
29034            index: usize,
29035        ) -> *mut whiteout_M3AnimationGroup;
29036        pub fn whiteout_m3_M3Model_get_boneAnimationSets_count(
29037            self_: *mut whiteout_M3Model,
29038        ) -> usize;
29039        pub fn whiteout_m3_M3Model_resize_boneAnimationSets(
29040            self_: *mut whiteout_M3Model,
29041            count: usize,
29042        );
29043        pub fn whiteout_m3_M3Model_get_boneAnimationSets_at(
29044            self_: *mut whiteout_M3Model,
29045            index: usize,
29046        ) -> *mut whiteout_M3BoneAnimationSet;
29047        pub fn whiteout_m3_M3Model_get_animationSplitCount(self_: *mut whiteout_M3Model) -> u32;
29048        pub fn whiteout_m3_M3Model_set_animationSplitCount(
29049            self_: *mut whiteout_M3Model,
29050            value: u32,
29051        );
29052        pub fn whiteout_m3_M3Model_get_animationStates_count(self_: *mut whiteout_M3Model)
29053            -> usize;
29054        pub fn whiteout_m3_M3Model_resize_animationStates(
29055            self_: *mut whiteout_M3Model,
29056            count: usize,
29057        );
29058        pub fn whiteout_m3_M3Model_get_animationStates_at(
29059            self_: *mut whiteout_M3Model,
29060            index: usize,
29061        ) -> *mut whiteout_M3AnimationState;
29062        pub fn whiteout_m3_M3Model_get_bones_count(self_: *mut whiteout_M3Model) -> usize;
29063        pub fn whiteout_m3_M3Model_resize_bones(self_: *mut whiteout_M3Model, count: usize);
29064        pub fn whiteout_m3_M3Model_get_bones_at(
29065            self_: *mut whiteout_M3Model,
29066            index: usize,
29067        ) -> *mut whiteout_M3Bone;
29068        pub fn whiteout_m3_M3Model_get_skinBoneCount(self_: *mut whiteout_M3Model) -> u32;
29069        pub fn whiteout_m3_M3Model_set_skinBoneCount(self_: *mut whiteout_M3Model, value: u32);
29070        pub fn whiteout_m3_M3Model_get_divisions_count(self_: *mut whiteout_M3Model) -> usize;
29071        pub fn whiteout_m3_M3Model_resize_divisions(self_: *mut whiteout_M3Model, count: usize);
29072        pub fn whiteout_m3_M3Model_get_divisions_at(
29073            self_: *mut whiteout_M3Model,
29074            index: usize,
29075        ) -> *mut whiteout_M3MeshDivision;
29076        pub fn whiteout_m3_M3Model_get_boneLookup_count(self_: *mut whiteout_M3Model) -> usize;
29077        pub fn whiteout_m3_M3Model_resize_boneLookup(self_: *mut whiteout_M3Model, count: usize);
29078        pub fn whiteout_m3_M3Model_get_boneLookup_data(self_: *mut whiteout_M3Model) -> *const u16;
29079        pub fn whiteout_m3_M3Model_assign_boneLookup(
29080            self_: *mut whiteout_M3Model,
29081            data: *const u16,
29082            count: usize,
29083        );
29084        pub fn whiteout_m3_M3Model_get_bounds(
29085            self_: *mut whiteout_M3Model,
29086        ) -> *mut whiteout_M3Extent;
29087        pub fn whiteout_m3_M3Model_set_bounds(
29088            self_: *mut whiteout_M3Model,
29089            value: *const whiteout_M3Extent,
29090        );
29091        pub fn whiteout_m3_M3Model_get_collisionBounds(
29092            self_: *mut whiteout_M3Model,
29093        ) -> *mut whiteout_M3Extent;
29094        pub fn whiteout_m3_M3Model_set_collisionBounds(
29095            self_: *mut whiteout_M3Model,
29096            value: *const whiteout_M3Extent,
29097        );
29098        pub fn whiteout_m3_M3Model_get_collisionFaces_count(self_: *mut whiteout_M3Model) -> usize;
29099        pub fn whiteout_m3_M3Model_resize_collisionFaces(
29100            self_: *mut whiteout_M3Model,
29101            count: usize,
29102        );
29103        pub fn whiteout_m3_M3Model_get_collisionFaces_data(
29104            self_: *mut whiteout_M3Model,
29105        ) -> *const u16;
29106        pub fn whiteout_m3_M3Model_assign_collisionFaces(
29107            self_: *mut whiteout_M3Model,
29108            data: *const u16,
29109            count: usize,
29110        );
29111        pub fn whiteout_m3_M3Model_get_collisionVerts_count(self_: *mut whiteout_M3Model) -> usize;
29112        pub fn whiteout_m3_M3Model_resize_collisionVerts(
29113            self_: *mut whiteout_M3Model,
29114            count: usize,
29115        );
29116        pub fn whiteout_m3_M3Model_get_collisionVerts_data(
29117            self_: *mut whiteout_M3Model,
29118        ) -> *const f32;
29119        pub fn whiteout_m3_M3Model_assign_collisionVerts(
29120            self_: *mut whiteout_M3Model,
29121            data: *const f32,
29122            count: usize,
29123        );
29124        pub fn whiteout_m3_M3Model_get_collisionNormals_count(
29125            self_: *mut whiteout_M3Model,
29126        ) -> usize;
29127        pub fn whiteout_m3_M3Model_resize_collisionNormals(
29128            self_: *mut whiteout_M3Model,
29129            count: usize,
29130        );
29131        pub fn whiteout_m3_M3Model_get_collisionNormals_data(
29132            self_: *mut whiteout_M3Model,
29133        ) -> *const f32;
29134        pub fn whiteout_m3_M3Model_assign_collisionNormals(
29135            self_: *mut whiteout_M3Model,
29136            data: *const f32,
29137            count: usize,
29138        );
29139        pub fn whiteout_m3_M3Model_get_attachmentPoints_count(
29140            self_: *mut whiteout_M3Model,
29141        ) -> usize;
29142        pub fn whiteout_m3_M3Model_resize_attachmentPoints(
29143            self_: *mut whiteout_M3Model,
29144            count: usize,
29145        );
29146        pub fn whiteout_m3_M3Model_get_attachmentPoints_at(
29147            self_: *mut whiteout_M3Model,
29148            index: usize,
29149        ) -> *mut whiteout_M3AttachmentPoint;
29150        pub fn whiteout_m3_M3Model_get_attachmentPointAddons_count(
29151            self_: *mut whiteout_M3Model,
29152        ) -> usize;
29153        pub fn whiteout_m3_M3Model_resize_attachmentPointAddons(
29154            self_: *mut whiteout_M3Model,
29155            count: usize,
29156        );
29157        pub fn whiteout_m3_M3Model_get_attachmentPointAddons_data(
29158            self_: *mut whiteout_M3Model,
29159        ) -> *const u16;
29160        pub fn whiteout_m3_M3Model_assign_attachmentPointAddons(
29161            self_: *mut whiteout_M3Model,
29162            data: *const u16,
29163            count: usize,
29164        );
29165        pub fn whiteout_m3_M3Model_get_lights_count(self_: *mut whiteout_M3Model) -> usize;
29166        pub fn whiteout_m3_M3Model_resize_lights(self_: *mut whiteout_M3Model, count: usize);
29167        pub fn whiteout_m3_M3Model_get_lights_at(
29168            self_: *mut whiteout_M3Model,
29169            index: usize,
29170        ) -> *mut whiteout_M3Light;
29171        pub fn whiteout_m3_M3Model_get_shadowBoxes_count(self_: *mut whiteout_M3Model) -> usize;
29172        pub fn whiteout_m3_M3Model_resize_shadowBoxes(self_: *mut whiteout_M3Model, count: usize);
29173        pub fn whiteout_m3_M3Model_get_shadowBoxes_at(
29174            self_: *mut whiteout_M3Model,
29175            index: usize,
29176        ) -> *mut whiteout_M3ShadowBox;
29177        pub fn whiteout_m3_M3Model_get_cameras_count(self_: *mut whiteout_M3Model) -> usize;
29178        pub fn whiteout_m3_M3Model_resize_cameras(self_: *mut whiteout_M3Model, count: usize);
29179        pub fn whiteout_m3_M3Model_get_cameras_at(
29180            self_: *mut whiteout_M3Model,
29181            index: usize,
29182        ) -> *mut whiteout_M3Camera;
29183        pub fn whiteout_m3_M3Model_get_camerasAddons_count(self_: *mut whiteout_M3Model) -> usize;
29184        pub fn whiteout_m3_M3Model_resize_camerasAddons(self_: *mut whiteout_M3Model, count: usize);
29185        pub fn whiteout_m3_M3Model_get_camerasAddons_data(
29186            self_: *mut whiteout_M3Model,
29187        ) -> *const u16;
29188        pub fn whiteout_m3_M3Model_assign_camerasAddons(
29189            self_: *mut whiteout_M3Model,
29190            data: *const u16,
29191            count: usize,
29192        );
29193        pub fn whiteout_m3_M3Model_get_materialMaps_count(self_: *mut whiteout_M3Model) -> usize;
29194        pub fn whiteout_m3_M3Model_resize_materialMaps(self_: *mut whiteout_M3Model, count: usize);
29195        pub fn whiteout_m3_M3Model_get_materialMaps_at(
29196            self_: *mut whiteout_M3Model,
29197            index: usize,
29198        ) -> *mut whiteout_M3MaterialMap;
29199        pub fn whiteout_m3_M3Model_get_standardMaterials_count(
29200            self_: *mut whiteout_M3Model,
29201        ) -> usize;
29202        pub fn whiteout_m3_M3Model_resize_standardMaterials(
29203            self_: *mut whiteout_M3Model,
29204            count: usize,
29205        );
29206        pub fn whiteout_m3_M3Model_get_standardMaterials_at(
29207            self_: *mut whiteout_M3Model,
29208            index: usize,
29209        ) -> *mut whiteout_M3StandardMaterial;
29210        pub fn whiteout_m3_M3Model_get_displacementMaterials_count(
29211            self_: *mut whiteout_M3Model,
29212        ) -> usize;
29213        pub fn whiteout_m3_M3Model_resize_displacementMaterials(
29214            self_: *mut whiteout_M3Model,
29215            count: usize,
29216        );
29217        pub fn whiteout_m3_M3Model_get_displacementMaterials_at(
29218            self_: *mut whiteout_M3Model,
29219            index: usize,
29220        ) -> *mut whiteout_M3DisplacementMaterial;
29221        pub fn whiteout_m3_M3Model_get_compositeMaterials_count(
29222            self_: *mut whiteout_M3Model,
29223        ) -> usize;
29224        pub fn whiteout_m3_M3Model_resize_compositeMaterials(
29225            self_: *mut whiteout_M3Model,
29226            count: usize,
29227        );
29228        pub fn whiteout_m3_M3Model_get_compositeMaterials_at(
29229            self_: *mut whiteout_M3Model,
29230            index: usize,
29231        ) -> *mut whiteout_M3CompositeMaterial;
29232        pub fn whiteout_m3_M3Model_get_terrainMaterials_count(
29233            self_: *mut whiteout_M3Model,
29234        ) -> usize;
29235        pub fn whiteout_m3_M3Model_resize_terrainMaterials(
29236            self_: *mut whiteout_M3Model,
29237            count: usize,
29238        );
29239        pub fn whiteout_m3_M3Model_get_terrainMaterials_at(
29240            self_: *mut whiteout_M3Model,
29241            index: usize,
29242        ) -> *mut whiteout_M3TerrainMaterial;
29243        pub fn whiteout_m3_M3Model_get_volumeMaterials_count(self_: *mut whiteout_M3Model)
29244            -> usize;
29245        pub fn whiteout_m3_M3Model_resize_volumeMaterials(
29246            self_: *mut whiteout_M3Model,
29247            count: usize,
29248        );
29249        pub fn whiteout_m3_M3Model_get_volumeMaterials_at(
29250            self_: *mut whiteout_M3Model,
29251            index: usize,
29252        ) -> *mut whiteout_M3VolumeMaterial;
29253        pub fn whiteout_m3_M3Model_get_hairMaterials_count(self_: *mut whiteout_M3Model) -> usize;
29254        pub fn whiteout_m3_M3Model_resize_hairMaterials(self_: *mut whiteout_M3Model, count: usize);
29255        pub fn whiteout_m3_M3Model_get_hairMaterials_at(
29256            self_: *mut whiteout_M3Model,
29257            index: usize,
29258        ) -> *mut whiteout_M3HairMaterial;
29259        pub fn whiteout_m3_M3Model_get_creepMaterials_count(self_: *mut whiteout_M3Model) -> usize;
29260        pub fn whiteout_m3_M3Model_resize_creepMaterials(
29261            self_: *mut whiteout_M3Model,
29262            count: usize,
29263        );
29264        pub fn whiteout_m3_M3Model_get_creepMaterials_at(
29265            self_: *mut whiteout_M3Model,
29266            index: usize,
29267        ) -> *mut whiteout_M3CreepMaterial;
29268        pub fn whiteout_m3_M3Model_get_volumeNoiseMaterials_count(
29269            self_: *mut whiteout_M3Model,
29270        ) -> usize;
29271        pub fn whiteout_m3_M3Model_resize_volumeNoiseMaterials(
29272            self_: *mut whiteout_M3Model,
29273            count: usize,
29274        );
29275        pub fn whiteout_m3_M3Model_get_volumeNoiseMaterials_at(
29276            self_: *mut whiteout_M3Model,
29277            index: usize,
29278        ) -> *mut whiteout_M3VolumeNoiseMaterial;
29279        pub fn whiteout_m3_M3Model_get_stbMaterials_count(self_: *mut whiteout_M3Model) -> usize;
29280        pub fn whiteout_m3_M3Model_resize_stbMaterials(self_: *mut whiteout_M3Model, count: usize);
29281        pub fn whiteout_m3_M3Model_get_stbMaterials_at(
29282            self_: *mut whiteout_M3Model,
29283            index: usize,
29284        ) -> *mut whiteout_M3STBMaterial;
29285        pub fn whiteout_m3_M3Model_get_reflectionMaterials_count(
29286            self_: *mut whiteout_M3Model,
29287        ) -> usize;
29288        pub fn whiteout_m3_M3Model_resize_reflectionMaterials(
29289            self_: *mut whiteout_M3Model,
29290            count: usize,
29291        );
29292        pub fn whiteout_m3_M3Model_get_reflectionMaterials_at(
29293            self_: *mut whiteout_M3Model,
29294            index: usize,
29295        ) -> *mut whiteout_M3ReflectionMaterial;
29296        pub fn whiteout_m3_M3Model_get_lensFlareMaterials_count(
29297            self_: *mut whiteout_M3Model,
29298        ) -> usize;
29299        pub fn whiteout_m3_M3Model_resize_lensFlareMaterials(
29300            self_: *mut whiteout_M3Model,
29301            count: usize,
29302        );
29303        pub fn whiteout_m3_M3Model_get_lensFlareMaterials_at(
29304            self_: *mut whiteout_M3Model,
29305            index: usize,
29306        ) -> *mut whiteout_M3LensFlare;
29307        pub fn whiteout_m3_M3Model_get_dataDrivenMaterials_count(
29308            self_: *mut whiteout_M3Model,
29309        ) -> usize;
29310        pub fn whiteout_m3_M3Model_resize_dataDrivenMaterials(
29311            self_: *mut whiteout_M3Model,
29312            count: usize,
29313        );
29314        pub fn whiteout_m3_M3Model_get_dataDrivenMaterials_at(
29315            self_: *mut whiteout_M3Model,
29316            index: usize,
29317        ) -> *mut whiteout_M3DataDrivenMaterial;
29318        pub fn whiteout_m3_M3Model_get_particleEmitters_count(
29319            self_: *mut whiteout_M3Model,
29320        ) -> usize;
29321        pub fn whiteout_m3_M3Model_resize_particleEmitters(
29322            self_: *mut whiteout_M3Model,
29323            count: usize,
29324        );
29325        pub fn whiteout_m3_M3Model_get_particleEmitters_at(
29326            self_: *mut whiteout_M3Model,
29327            index: usize,
29328        ) -> *mut whiteout_M3ParticleEmitter;
29329        pub fn whiteout_m3_M3Model_get_particleEmitterCopies_count(
29330            self_: *mut whiteout_M3Model,
29331        ) -> usize;
29332        pub fn whiteout_m3_M3Model_resize_particleEmitterCopies(
29333            self_: *mut whiteout_M3Model,
29334            count: usize,
29335        );
29336        pub fn whiteout_m3_M3Model_get_particleEmitterCopies_at(
29337            self_: *mut whiteout_M3Model,
29338            index: usize,
29339        ) -> *mut whiteout_M3ParticleEmitterCopy;
29340        pub fn whiteout_m3_M3Model_get_ribbonEmitters_count(self_: *mut whiteout_M3Model) -> usize;
29341        pub fn whiteout_m3_M3Model_resize_ribbonEmitters(
29342            self_: *mut whiteout_M3Model,
29343            count: usize,
29344        );
29345        pub fn whiteout_m3_M3Model_get_ribbonEmitters_at(
29346            self_: *mut whiteout_M3Model,
29347            index: usize,
29348        ) -> *mut whiteout_M3RibbonEmitter;
29349        pub fn whiteout_m3_M3Model_get_projections_count(self_: *mut whiteout_M3Model) -> usize;
29350        pub fn whiteout_m3_M3Model_resize_projections(self_: *mut whiteout_M3Model, count: usize);
29351        pub fn whiteout_m3_M3Model_get_projections_at(
29352            self_: *mut whiteout_M3Model,
29353            index: usize,
29354        ) -> *mut whiteout_M3Projector;
29355        pub fn whiteout_m3_M3Model_get_forces_count(self_: *mut whiteout_M3Model) -> usize;
29356        pub fn whiteout_m3_M3Model_resize_forces(self_: *mut whiteout_M3Model, count: usize);
29357        pub fn whiteout_m3_M3Model_get_forces_at(
29358            self_: *mut whiteout_M3Model,
29359            index: usize,
29360        ) -> *mut whiteout_M3Force;
29361        pub fn whiteout_m3_M3Model_get_warps_count(self_: *mut whiteout_M3Model) -> usize;
29362        pub fn whiteout_m3_M3Model_resize_warps(self_: *mut whiteout_M3Model, count: usize);
29363        pub fn whiteout_m3_M3Model_get_warps_at(
29364            self_: *mut whiteout_M3Model,
29365            index: usize,
29366        ) -> *mut whiteout_M3Warp;
29367        pub fn whiteout_m3_M3Model_get_viewVolumes_count(self_: *mut whiteout_M3Model) -> usize;
29368        pub fn whiteout_m3_M3Model_resize_viewVolumes(self_: *mut whiteout_M3Model, count: usize);
29369        pub fn whiteout_m3_M3Model_get_viewVolumes_at(
29370            self_: *mut whiteout_M3Model,
29371            index: usize,
29372        ) -> *mut whiteout_M3ViewVolume;
29373        pub fn whiteout_m3_M3Model_get_rigidBodies_count(self_: *mut whiteout_M3Model) -> usize;
29374        pub fn whiteout_m3_M3Model_resize_rigidBodies(self_: *mut whiteout_M3Model, count: usize);
29375        pub fn whiteout_m3_M3Model_get_rigidBodies_at(
29376            self_: *mut whiteout_M3Model,
29377            index: usize,
29378        ) -> *mut whiteout_M3RigidBody;
29379        pub fn whiteout_m3_M3Model_get_physicsConstraints_count(
29380            self_: *mut whiteout_M3Model,
29381        ) -> usize;
29382        pub fn whiteout_m3_M3Model_resize_physicsConstraints(
29383            self_: *mut whiteout_M3Model,
29384            count: usize,
29385        );
29386        pub fn whiteout_m3_M3Model_get_physicsConstraints_at(
29387            self_: *mut whiteout_M3Model,
29388            index: usize,
29389        ) -> *mut whiteout_M3PhysicsConstraint;
29390        pub fn whiteout_m3_M3Model_get_physicsJoints_count(self_: *mut whiteout_M3Model) -> usize;
29391        pub fn whiteout_m3_M3Model_resize_physicsJoints(self_: *mut whiteout_M3Model, count: usize);
29392        pub fn whiteout_m3_M3Model_get_physicsJoints_at(
29393            self_: *mut whiteout_M3Model,
29394            index: usize,
29395        ) -> *mut whiteout_M3PhysicsJoint;
29396        pub fn whiteout_m3_M3Model_get_clothPhysics_count(self_: *mut whiteout_M3Model) -> usize;
29397        pub fn whiteout_m3_M3Model_resize_clothPhysics(self_: *mut whiteout_M3Model, count: usize);
29398        pub fn whiteout_m3_M3Model_get_clothPhysics_at(
29399            self_: *mut whiteout_M3Model,
29400            index: usize,
29401        ) -> *mut whiteout_M3ClothPhysics;
29402        pub fn whiteout_m3_M3Model_get_ikTwoJoints_count(self_: *mut whiteout_M3Model) -> usize;
29403        pub fn whiteout_m3_M3Model_resize_ikTwoJoints(self_: *mut whiteout_M3Model, count: usize);
29404        pub fn whiteout_m3_M3Model_get_ikTwoJoints_at(
29405            self_: *mut whiteout_M3Model,
29406            index: usize,
29407        ) -> *mut whiteout_M3IKTwoJoint;
29408        pub fn whiteout_m3_M3Model_get_ikCCD_count(self_: *mut whiteout_M3Model) -> usize;
29409        pub fn whiteout_m3_M3Model_resize_ikCCD(self_: *mut whiteout_M3Model, count: usize);
29410        pub fn whiteout_m3_M3Model_get_ikCCD_at(
29411            self_: *mut whiteout_M3Model,
29412            index: usize,
29413        ) -> *mut whiteout_M3IKCCD;
29414        pub fn whiteout_m3_M3Model_get_ikJoints_count(self_: *mut whiteout_M3Model) -> usize;
29415        pub fn whiteout_m3_M3Model_resize_ikJoints(self_: *mut whiteout_M3Model, count: usize);
29416        pub fn whiteout_m3_M3Model_get_ikJoints_at(
29417            self_: *mut whiteout_M3Model,
29418            index: usize,
29419        ) -> *mut whiteout_M3IKJoint;
29420        pub fn whiteout_m3_M3Model_get_oneBoneSolvers_count(self_: *mut whiteout_M3Model) -> usize;
29421        pub fn whiteout_m3_M3Model_resize_oneBoneSolvers(
29422            self_: *mut whiteout_M3Model,
29423            count: usize,
29424        );
29425        pub fn whiteout_m3_M3Model_get_oneBoneSolvers_at(
29426            self_: *mut whiteout_M3Model,
29427            index: usize,
29428        ) -> *mut whiteout_M3OneBoneSolver;
29429        pub fn whiteout_m3_M3Model_get_turretBehaviors_count(self_: *mut whiteout_M3Model)
29430            -> usize;
29431        pub fn whiteout_m3_M3Model_resize_turretBehaviors(
29432            self_: *mut whiteout_M3Model,
29433            count: usize,
29434        );
29435        pub fn whiteout_m3_M3Model_get_turretBehaviors_at(
29436            self_: *mut whiteout_M3Model,
29437            index: usize,
29438        ) -> *mut whiteout_M3TurretBehavior;
29439        pub fn whiteout_m3_M3Model_get_triggerData_count(self_: *mut whiteout_M3Model) -> usize;
29440        pub fn whiteout_m3_M3Model_resize_triggerData(self_: *mut whiteout_M3Model, count: usize);
29441        pub fn whiteout_m3_M3Model_get_triggerData_at(
29442            self_: *mut whiteout_M3Model,
29443            index: usize,
29444        ) -> *mut whiteout_M3TriggerData;
29445        pub fn whiteout_m3_M3Model_get_initialReference_count(
29446            self_: *mut whiteout_M3Model,
29447        ) -> usize;
29448        pub fn whiteout_m3_M3Model_resize_initialReference(
29449            self_: *mut whiteout_M3Model,
29450            count: usize,
29451        );
29452        pub fn whiteout_m3_M3Model_get_initialReference_at(
29453            self_: *mut whiteout_M3Model,
29454            index: usize,
29455        ) -> *mut whiteout_M3InitialReference;
29456        pub fn whiteout_m3_M3Model_get_tightHitTestObject(
29457            self_: *mut whiteout_M3Model,
29458        ) -> *mut whiteout_M3HitTestShape;
29459        pub fn whiteout_m3_M3Model_set_tightHitTestObject(
29460            self_: *mut whiteout_M3Model,
29461            value: *const whiteout_M3HitTestShape,
29462        );
29463        pub fn whiteout_m3_M3Model_get_fuzzyHitTestObjects_count(
29464            self_: *mut whiteout_M3Model,
29465        ) -> usize;
29466        pub fn whiteout_m3_M3Model_resize_fuzzyHitTestObjects(
29467            self_: *mut whiteout_M3Model,
29468            count: usize,
29469        );
29470        pub fn whiteout_m3_M3Model_get_fuzzyHitTestObjects_at(
29471            self_: *mut whiteout_M3Model,
29472            index: usize,
29473        ) -> *mut whiteout_M3HitTestShape;
29474        pub fn whiteout_m3_M3Model_get_attachmentVolumes_count(
29475            self_: *mut whiteout_M3Model,
29476        ) -> usize;
29477        pub fn whiteout_m3_M3Model_resize_attachmentVolumes(
29478            self_: *mut whiteout_M3Model,
29479            count: usize,
29480        );
29481        pub fn whiteout_m3_M3Model_get_attachmentVolumes_at(
29482            self_: *mut whiteout_M3Model,
29483            index: usize,
29484        ) -> *mut whiteout_M3AttachmentVolume;
29485        pub fn whiteout_m3_M3Model_get_attachmentVolumesAddon0_count(
29486            self_: *mut whiteout_M3Model,
29487        ) -> usize;
29488        pub fn whiteout_m3_M3Model_resize_attachmentVolumesAddon0(
29489            self_: *mut whiteout_M3Model,
29490            count: usize,
29491        );
29492        pub fn whiteout_m3_M3Model_get_attachmentVolumesAddon0_data(
29493            self_: *mut whiteout_M3Model,
29494        ) -> *const u16;
29495        pub fn whiteout_m3_M3Model_assign_attachmentVolumesAddon0(
29496            self_: *mut whiteout_M3Model,
29497            data: *const u16,
29498            count: usize,
29499        );
29500        pub fn whiteout_m3_M3Model_get_attachmentVolumesAddon1_count(
29501            self_: *mut whiteout_M3Model,
29502        ) -> usize;
29503        pub fn whiteout_m3_M3Model_resize_attachmentVolumesAddon1(
29504            self_: *mut whiteout_M3Model,
29505            count: usize,
29506        );
29507        pub fn whiteout_m3_M3Model_get_attachmentVolumesAddon1_data(
29508            self_: *mut whiteout_M3Model,
29509        ) -> *const u16;
29510        pub fn whiteout_m3_M3Model_assign_attachmentVolumesAddon1(
29511            self_: *mut whiteout_M3Model,
29512            data: *const u16,
29513            count: usize,
29514        );
29515        pub fn whiteout_m3_M3Model_get_billboardBehaviors_count(
29516            self_: *mut whiteout_M3Model,
29517        ) -> usize;
29518        pub fn whiteout_m3_M3Model_resize_billboardBehaviors(
29519            self_: *mut whiteout_M3Model,
29520            count: usize,
29521        );
29522        pub fn whiteout_m3_M3Model_get_billboardBehaviors_at(
29523            self_: *mut whiteout_M3Model,
29524            index: usize,
29525        ) -> *mut whiteout_M3BillboardBehavior;
29526        pub fn whiteout_m3_M3Model_get_trailingModels_count(self_: *mut whiteout_M3Model) -> usize;
29527        pub fn whiteout_m3_M3Model_resize_trailingModels(
29528            self_: *mut whiteout_M3Model,
29529            count: usize,
29530        );
29531        pub fn whiteout_m3_M3Model_get_trailingModels_at(
29532            self_: *mut whiteout_M3Model,
29533            index: usize,
29534        ) -> *mut whiteout_M3TrailingModel;
29535        pub fn whiteout_m3_M3Model_get_m3aAnimHash(self_: *mut whiteout_M3Model) -> u32;
29536        pub fn whiteout_m3_M3Model_set_m3aAnimHash(self_: *mut whiteout_M3Model, value: u32);
29537        pub fn whiteout_m3_M3Model_get_m3aAnimHashes_count(self_: *mut whiteout_M3Model) -> usize;
29538        pub fn whiteout_m3_M3Model_resize_m3aAnimHashes(self_: *mut whiteout_M3Model, count: usize);
29539        pub fn whiteout_m3_M3Model_get_m3aAnimHashes_data(
29540            self_: *mut whiteout_M3Model,
29541        ) -> *const u32;
29542        pub fn whiteout_m3_M3Model_assign_m3aAnimHashes(
29543            self_: *mut whiteout_M3Model,
29544            data: *const u32,
29545            count: usize,
29546        );
29547        // Parser
29548        pub fn whiteout_m3_M3Parser_new() -> *mut whiteout_M3Parser;
29549        pub fn whiteout_m3_M3Parser_delete(self_: *mut whiteout_M3Parser);
29550        pub fn whiteout_m3_M3Parser_parse(
29551            self_: *mut whiteout_M3Parser,
29552            file_path: *const core::ffi::c_char,
29553        ) -> *mut whiteout_M3Model;
29554        pub fn whiteout_m3_M3Parser_parse_buffer(
29555            self_: *mut whiteout_M3Parser,
29556            buffer: *const u8,
29557            buffer_size: usize,
29558        ) -> *mut whiteout_M3Model;
29559        pub fn whiteout_m3_M3Parser_hasIssues(self_: *mut whiteout_M3Parser) -> i32;
29560        pub fn whiteout_m3_M3Parser_getIssues_count(self_: *mut whiteout_M3Parser) -> usize;
29561        pub fn whiteout_m3_M3Parser_getIssues_at(
29562            self_: *mut whiteout_M3Parser,
29563            index: usize,
29564        ) -> RawCString;
29565        // Writer
29566        pub fn whiteout_m3_M3Writer_new() -> *mut whiteout_M3Writer;
29567        pub fn whiteout_m3_M3Writer_delete(self_: *mut whiteout_M3Writer);
29568        pub fn whiteout_m3_M3Writer_write(
29569            self_: *mut whiteout_M3Writer,
29570            file_path: *const core::ffi::c_char,
29571            model: *mut whiteout_M3Model,
29572        );
29573        pub fn whiteout_m3_M3Writer_write_model(
29574            self_: *mut whiteout_M3Writer,
29575            model: *mut whiteout_M3Model,
29576        ) -> RawBytes;
29577        // AnimRefF32
29578        pub fn whiteout_m3_M3AnimRefF32_new() -> *mut whiteout_M3AnimRefF32;
29579        pub fn whiteout_m3_M3AnimRefF32_delete(self_: *mut whiteout_M3AnimRefF32);
29580        pub fn whiteout_m3_M3AnimRefF32_get_interpType(self_: *mut whiteout_M3AnimRefF32) -> u16;
29581        pub fn whiteout_m3_M3AnimRefF32_set_interpType(
29582            self_: *mut whiteout_M3AnimRefF32,
29583            value: u16,
29584        );
29585        pub fn whiteout_m3_M3AnimRefF32_get_flags(self_: *mut whiteout_M3AnimRefF32) -> u16;
29586        pub fn whiteout_m3_M3AnimRefF32_set_flags(self_: *mut whiteout_M3AnimRefF32, value: u16);
29587        pub fn whiteout_m3_M3AnimRefF32_get_animId(self_: *mut whiteout_M3AnimRefF32) -> u32;
29588        pub fn whiteout_m3_M3AnimRefF32_set_animId(self_: *mut whiteout_M3AnimRefF32, value: u32);
29589        pub fn whiteout_m3_M3AnimRefF32_get_initValue(self_: *mut whiteout_M3AnimRefF32) -> f32;
29590        pub fn whiteout_m3_M3AnimRefF32_set_initValue(
29591            self_: *mut whiteout_M3AnimRefF32,
29592            value: f32,
29593        );
29594        pub fn whiteout_m3_M3AnimRefF32_get_nullValue(self_: *mut whiteout_M3AnimRefF32) -> f32;
29595        pub fn whiteout_m3_M3AnimRefF32_set_nullValue(
29596            self_: *mut whiteout_M3AnimRefF32,
29597            value: f32,
29598        );
29599        pub fn whiteout_m3_M3AnimRefF32_get_unused(self_: *mut whiteout_M3AnimRefF32) -> i32;
29600        pub fn whiteout_m3_M3AnimRefF32_set_unused(self_: *mut whiteout_M3AnimRefF32, value: i32);
29601        // AnimRefVector3f
29602        pub fn whiteout_m3_M3AnimRefVector3f_new() -> *mut whiteout_M3AnimRefVector3f;
29603        pub fn whiteout_m3_M3AnimRefVector3f_delete(self_: *mut whiteout_M3AnimRefVector3f);
29604        pub fn whiteout_m3_M3AnimRefVector3f_get_interpType(
29605            self_: *mut whiteout_M3AnimRefVector3f,
29606        ) -> u16;
29607        pub fn whiteout_m3_M3AnimRefVector3f_set_interpType(
29608            self_: *mut whiteout_M3AnimRefVector3f,
29609            value: u16,
29610        );
29611        pub fn whiteout_m3_M3AnimRefVector3f_get_flags(
29612            self_: *mut whiteout_M3AnimRefVector3f,
29613        ) -> u16;
29614        pub fn whiteout_m3_M3AnimRefVector3f_set_flags(
29615            self_: *mut whiteout_M3AnimRefVector3f,
29616            value: u16,
29617        );
29618        pub fn whiteout_m3_M3AnimRefVector3f_get_animId(
29619            self_: *mut whiteout_M3AnimRefVector3f,
29620        ) -> u32;
29621        pub fn whiteout_m3_M3AnimRefVector3f_set_animId(
29622            self_: *mut whiteout_M3AnimRefVector3f,
29623            value: u32,
29624        );
29625        pub fn whiteout_m3_M3AnimRefVector3f_get_initValue(
29626            self_: *mut whiteout_M3AnimRefVector3f,
29627        ) -> *mut core::ffi::c_void;
29628        pub fn whiteout_m3_M3AnimRefVector3f_set_initValue(
29629            self_: *mut whiteout_M3AnimRefVector3f,
29630            value: *const core::ffi::c_void,
29631        );
29632        pub fn whiteout_m3_M3AnimRefVector3f_get_nullValue(
29633            self_: *mut whiteout_M3AnimRefVector3f,
29634        ) -> *mut core::ffi::c_void;
29635        pub fn whiteout_m3_M3AnimRefVector3f_set_nullValue(
29636            self_: *mut whiteout_M3AnimRefVector3f,
29637            value: *const core::ffi::c_void,
29638        );
29639        pub fn whiteout_m3_M3AnimRefVector3f_get_unused(
29640            self_: *mut whiteout_M3AnimRefVector3f,
29641        ) -> i32;
29642        pub fn whiteout_m3_M3AnimRefVector3f_set_unused(
29643            self_: *mut whiteout_M3AnimRefVector3f,
29644            value: i32,
29645        );
29646        // AnimRefM3ColorBGRA
29647        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_new() -> *mut whiteout_M3AnimRefM3ColorBGRA;
29648        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_delete(self_: *mut whiteout_M3AnimRefM3ColorBGRA);
29649        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_interpType(
29650            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29651        ) -> u16;
29652        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_interpType(
29653            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29654            value: u16,
29655        );
29656        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_flags(
29657            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29658        ) -> u16;
29659        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_flags(
29660            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29661            value: u16,
29662        );
29663        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_animId(
29664            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29665        ) -> u32;
29666        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_animId(
29667            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29668            value: u32,
29669        );
29670        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_initValue(
29671            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29672        ) -> *mut whiteout_M3ColorBGRA;
29673        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_initValue(
29674            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29675            value: *const whiteout_M3ColorBGRA,
29676        );
29677        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_nullValue(
29678            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29679        ) -> *mut whiteout_M3ColorBGRA;
29680        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_nullValue(
29681            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29682            value: *const whiteout_M3ColorBGRA,
29683        );
29684        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_get_unused(
29685            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29686        ) -> i32;
29687        pub fn whiteout_m3_M3AnimRefM3ColorBGRA_set_unused(
29688            self_: *mut whiteout_M3AnimRefM3ColorBGRA,
29689            value: i32,
29690        );
29691        // AnimRefU16
29692        pub fn whiteout_m3_M3AnimRefU16_new() -> *mut whiteout_M3AnimRefU16;
29693        pub fn whiteout_m3_M3AnimRefU16_delete(self_: *mut whiteout_M3AnimRefU16);
29694        pub fn whiteout_m3_M3AnimRefU16_get_interpType(self_: *mut whiteout_M3AnimRefU16) -> u16;
29695        pub fn whiteout_m3_M3AnimRefU16_set_interpType(
29696            self_: *mut whiteout_M3AnimRefU16,
29697            value: u16,
29698        );
29699        pub fn whiteout_m3_M3AnimRefU16_get_flags(self_: *mut whiteout_M3AnimRefU16) -> u16;
29700        pub fn whiteout_m3_M3AnimRefU16_set_flags(self_: *mut whiteout_M3AnimRefU16, value: u16);
29701        pub fn whiteout_m3_M3AnimRefU16_get_animId(self_: *mut whiteout_M3AnimRefU16) -> u32;
29702        pub fn whiteout_m3_M3AnimRefU16_set_animId(self_: *mut whiteout_M3AnimRefU16, value: u32);
29703        pub fn whiteout_m3_M3AnimRefU16_get_initValue(self_: *mut whiteout_M3AnimRefU16) -> u16;
29704        pub fn whiteout_m3_M3AnimRefU16_set_initValue(
29705            self_: *mut whiteout_M3AnimRefU16,
29706            value: u16,
29707        );
29708        pub fn whiteout_m3_M3AnimRefU16_get_nullValue(self_: *mut whiteout_M3AnimRefU16) -> u16;
29709        pub fn whiteout_m3_M3AnimRefU16_set_nullValue(
29710            self_: *mut whiteout_M3AnimRefU16,
29711            value: u16,
29712        );
29713        pub fn whiteout_m3_M3AnimRefU16_get_unused(self_: *mut whiteout_M3AnimRefU16) -> i32;
29714        pub fn whiteout_m3_M3AnimRefU16_set_unused(self_: *mut whiteout_M3AnimRefU16, value: i32);
29715        // AnimRefVector2f
29716        pub fn whiteout_m3_M3AnimRefVector2f_new() -> *mut whiteout_M3AnimRefVector2f;
29717        pub fn whiteout_m3_M3AnimRefVector2f_delete(self_: *mut whiteout_M3AnimRefVector2f);
29718        pub fn whiteout_m3_M3AnimRefVector2f_get_interpType(
29719            self_: *mut whiteout_M3AnimRefVector2f,
29720        ) -> u16;
29721        pub fn whiteout_m3_M3AnimRefVector2f_set_interpType(
29722            self_: *mut whiteout_M3AnimRefVector2f,
29723            value: u16,
29724        );
29725        pub fn whiteout_m3_M3AnimRefVector2f_get_flags(
29726            self_: *mut whiteout_M3AnimRefVector2f,
29727        ) -> u16;
29728        pub fn whiteout_m3_M3AnimRefVector2f_set_flags(
29729            self_: *mut whiteout_M3AnimRefVector2f,
29730            value: u16,
29731        );
29732        pub fn whiteout_m3_M3AnimRefVector2f_get_animId(
29733            self_: *mut whiteout_M3AnimRefVector2f,
29734        ) -> u32;
29735        pub fn whiteout_m3_M3AnimRefVector2f_set_animId(
29736            self_: *mut whiteout_M3AnimRefVector2f,
29737            value: u32,
29738        );
29739        pub fn whiteout_m3_M3AnimRefVector2f_get_initValue(
29740            self_: *mut whiteout_M3AnimRefVector2f,
29741        ) -> *mut core::ffi::c_void;
29742        pub fn whiteout_m3_M3AnimRefVector2f_set_initValue(
29743            self_: *mut whiteout_M3AnimRefVector2f,
29744            value: *const core::ffi::c_void,
29745        );
29746        pub fn whiteout_m3_M3AnimRefVector2f_get_nullValue(
29747            self_: *mut whiteout_M3AnimRefVector2f,
29748        ) -> *mut core::ffi::c_void;
29749        pub fn whiteout_m3_M3AnimRefVector2f_set_nullValue(
29750            self_: *mut whiteout_M3AnimRefVector2f,
29751            value: *const core::ffi::c_void,
29752        );
29753        pub fn whiteout_m3_M3AnimRefVector2f_get_unused(
29754            self_: *mut whiteout_M3AnimRefVector2f,
29755        ) -> i32;
29756        pub fn whiteout_m3_M3AnimRefVector2f_set_unused(
29757            self_: *mut whiteout_M3AnimRefVector2f,
29758            value: i32,
29759        );
29760        // AnimRefU32
29761        pub fn whiteout_m3_M3AnimRefU32_new() -> *mut whiteout_M3AnimRefU32;
29762        pub fn whiteout_m3_M3AnimRefU32_delete(self_: *mut whiteout_M3AnimRefU32);
29763        pub fn whiteout_m3_M3AnimRefU32_get_interpType(self_: *mut whiteout_M3AnimRefU32) -> u16;
29764        pub fn whiteout_m3_M3AnimRefU32_set_interpType(
29765            self_: *mut whiteout_M3AnimRefU32,
29766            value: u16,
29767        );
29768        pub fn whiteout_m3_M3AnimRefU32_get_flags(self_: *mut whiteout_M3AnimRefU32) -> u16;
29769        pub fn whiteout_m3_M3AnimRefU32_set_flags(self_: *mut whiteout_M3AnimRefU32, value: u16);
29770        pub fn whiteout_m3_M3AnimRefU32_get_animId(self_: *mut whiteout_M3AnimRefU32) -> u32;
29771        pub fn whiteout_m3_M3AnimRefU32_set_animId(self_: *mut whiteout_M3AnimRefU32, value: u32);
29772        pub fn whiteout_m3_M3AnimRefU32_get_initValue(self_: *mut whiteout_M3AnimRefU32) -> u32;
29773        pub fn whiteout_m3_M3AnimRefU32_set_initValue(
29774            self_: *mut whiteout_M3AnimRefU32,
29775            value: u32,
29776        );
29777        pub fn whiteout_m3_M3AnimRefU32_get_nullValue(self_: *mut whiteout_M3AnimRefU32) -> u32;
29778        pub fn whiteout_m3_M3AnimRefU32_set_nullValue(
29779            self_: *mut whiteout_M3AnimRefU32,
29780            value: u32,
29781        );
29782        pub fn whiteout_m3_M3AnimRefU32_get_unused(self_: *mut whiteout_M3AnimRefU32) -> i32;
29783        pub fn whiteout_m3_M3AnimRefU32_set_unused(self_: *mut whiteout_M3AnimRefU32, value: i32);
29784        // AnimRefQuaternion
29785        pub fn whiteout_m3_M3AnimRefQuaternion_new() -> *mut whiteout_M3AnimRefQuaternion;
29786        pub fn whiteout_m3_M3AnimRefQuaternion_delete(self_: *mut whiteout_M3AnimRefQuaternion);
29787        pub fn whiteout_m3_M3AnimRefQuaternion_get_interpType(
29788            self_: *mut whiteout_M3AnimRefQuaternion,
29789        ) -> u16;
29790        pub fn whiteout_m3_M3AnimRefQuaternion_set_interpType(
29791            self_: *mut whiteout_M3AnimRefQuaternion,
29792            value: u16,
29793        );
29794        pub fn whiteout_m3_M3AnimRefQuaternion_get_flags(
29795            self_: *mut whiteout_M3AnimRefQuaternion,
29796        ) -> u16;
29797        pub fn whiteout_m3_M3AnimRefQuaternion_set_flags(
29798            self_: *mut whiteout_M3AnimRefQuaternion,
29799            value: u16,
29800        );
29801        pub fn whiteout_m3_M3AnimRefQuaternion_get_animId(
29802            self_: *mut whiteout_M3AnimRefQuaternion,
29803        ) -> u32;
29804        pub fn whiteout_m3_M3AnimRefQuaternion_set_animId(
29805            self_: *mut whiteout_M3AnimRefQuaternion,
29806            value: u32,
29807        );
29808        pub fn whiteout_m3_M3AnimRefQuaternion_get_initValue(
29809            self_: *mut whiteout_M3AnimRefQuaternion,
29810        ) -> *mut core::ffi::c_void;
29811        pub fn whiteout_m3_M3AnimRefQuaternion_set_initValue(
29812            self_: *mut whiteout_M3AnimRefQuaternion,
29813            value: *const core::ffi::c_void,
29814        );
29815        pub fn whiteout_m3_M3AnimRefQuaternion_get_nullValue(
29816            self_: *mut whiteout_M3AnimRefQuaternion,
29817        ) -> *mut core::ffi::c_void;
29818        pub fn whiteout_m3_M3AnimRefQuaternion_set_nullValue(
29819            self_: *mut whiteout_M3AnimRefQuaternion,
29820            value: *const core::ffi::c_void,
29821        );
29822        pub fn whiteout_m3_M3AnimRefQuaternion_get_unused(
29823            self_: *mut whiteout_M3AnimRefQuaternion,
29824        ) -> i32;
29825        pub fn whiteout_m3_M3AnimRefQuaternion_set_unused(
29826            self_: *mut whiteout_M3AnimRefQuaternion,
29827            value: i32,
29828        );
29829        // AnimRefM3Extent
29830        pub fn whiteout_m3_M3AnimRefM3Extent_new() -> *mut whiteout_M3AnimRefM3Extent;
29831        pub fn whiteout_m3_M3AnimRefM3Extent_delete(self_: *mut whiteout_M3AnimRefM3Extent);
29832        pub fn whiteout_m3_M3AnimRefM3Extent_get_interpType(
29833            self_: *mut whiteout_M3AnimRefM3Extent,
29834        ) -> u16;
29835        pub fn whiteout_m3_M3AnimRefM3Extent_set_interpType(
29836            self_: *mut whiteout_M3AnimRefM3Extent,
29837            value: u16,
29838        );
29839        pub fn whiteout_m3_M3AnimRefM3Extent_get_flags(
29840            self_: *mut whiteout_M3AnimRefM3Extent,
29841        ) -> u16;
29842        pub fn whiteout_m3_M3AnimRefM3Extent_set_flags(
29843            self_: *mut whiteout_M3AnimRefM3Extent,
29844            value: u16,
29845        );
29846        pub fn whiteout_m3_M3AnimRefM3Extent_get_animId(
29847            self_: *mut whiteout_M3AnimRefM3Extent,
29848        ) -> u32;
29849        pub fn whiteout_m3_M3AnimRefM3Extent_set_animId(
29850            self_: *mut whiteout_M3AnimRefM3Extent,
29851            value: u32,
29852        );
29853        pub fn whiteout_m3_M3AnimRefM3Extent_get_initValue(
29854            self_: *mut whiteout_M3AnimRefM3Extent,
29855        ) -> *mut whiteout_M3Extent;
29856        pub fn whiteout_m3_M3AnimRefM3Extent_set_initValue(
29857            self_: *mut whiteout_M3AnimRefM3Extent,
29858            value: *const whiteout_M3Extent,
29859        );
29860        pub fn whiteout_m3_M3AnimRefM3Extent_get_nullValue(
29861            self_: *mut whiteout_M3AnimRefM3Extent,
29862        ) -> *mut whiteout_M3Extent;
29863        pub fn whiteout_m3_M3AnimRefM3Extent_set_nullValue(
29864            self_: *mut whiteout_M3AnimRefM3Extent,
29865            value: *const whiteout_M3Extent,
29866        );
29867        pub fn whiteout_m3_M3AnimRefM3Extent_get_unused(
29868            self_: *mut whiteout_M3AnimRefM3Extent,
29869        ) -> i32;
29870        pub fn whiteout_m3_M3AnimRefM3Extent_set_unused(
29871            self_: *mut whiteout_M3AnimRefM3Extent,
29872            value: i32,
29873        );
29874    }
29875}