Skip to main content

whiteout/
m2.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 m2 --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#[repr(i32)]
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
15pub enum InterpolationType {
16    None = 0,
17    Linear = 1,
18    Bezier = 2,
19    Hermite = 3,
20}
21
22impl TryFrom<i32> for InterpolationType {
23    type Error = crate::Error;
24    fn try_from(v: i32) -> Result<Self, crate::Error> {
25        match v {
26            0 => Ok(InterpolationType::None),
27            1 => Ok(InterpolationType::Linear),
28            2 => Ok(InterpolationType::Bezier),
29            3 => Ok(InterpolationType::Hermite),
30            other => Err(crate::Error::UnknownEnum {
31                name: "InterpolationType",
32                value: other,
33            }),
34        }
35    }
36}
37
38/// Bit flags. Combine with `|`, test with [`GlobalFlag::contains`].
39#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
40pub struct GlobalFlag(pub i32);
41
42impl GlobalFlag {
43    pub const NONE: Self = Self(0);
44    pub const TILT_X: Self = Self(1);
45    pub const TILT_Y: Self = Self(2);
46    pub const ADD_BACK_REFERENCES: Self = Self(4);
47    pub const USE_TEXTURE_COMBINER_COMBOS: Self = Self(8);
48    pub const IS_CAMERA: Self = Self(16);
49    pub const LOAD_PHYSICS_DATA: Self = Self(32);
50    pub const UNK_0X_80: Self = Self(128);
51    pub const UNK_0X_100: Self = Self(256);
52    pub const NEW_PARTICLE_RECORD: Self = Self(512);
53    pub const UNK_0X_400: Self = Self(1024);
54    pub const TEXTURE_TRANSFORMS_USES_BONE_SEQUENCES: Self = Self(2048);
55    pub const UNK_0X_1000: Self = Self(4096);
56    pub const CHUNKED_ANIM_FILES: Self = Self(8192);
57    pub const UPGRADED_FORMAT: Self = Self(2097152);
58
59    #[inline]
60    pub const fn contains(self, other: Self) -> bool {
61        (self.0 & other.0) == other.0
62    }
63
64    #[inline]
65    pub const fn is_empty(self) -> bool {
66        self.0 == 0
67    }
68}
69
70impl core::ops::BitOr for GlobalFlag {
71    type Output = Self;
72    #[inline]
73    fn bitor(self, rhs: Self) -> Self {
74        Self(self.0 | rhs.0)
75    }
76}
77
78impl core::ops::BitAnd for GlobalFlag {
79    type Output = Self;
80    #[inline]
81    fn bitand(self, rhs: Self) -> Self {
82        Self(self.0 & rhs.0)
83    }
84}
85
86impl core::ops::Not for GlobalFlag {
87    type Output = Self;
88    #[inline]
89    fn not(self) -> Self {
90        Self(!self.0)
91    }
92}
93
94impl core::fmt::Debug for GlobalFlag {
95    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96        write!(f, "GlobalFlag({:#x})", self.0)
97    }
98}
99
100/// Bit flags. Combine with `|`, test with [`SequenceFlag::contains`].
101#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
102pub struct SequenceFlag(pub i32);
103
104impl SequenceFlag {
105    pub const NONE: Self = Self(0);
106    pub const TILT_IN: Self = Self(1);
107    pub const TILT_OUT: Self = Self(2);
108    pub const TILT_FIXED: Self = Self(4);
109    pub const LOOPING: Self = Self(32);
110    pub const IS_ALIAS: Self = Self(64);
111    pub const ANIMATED_SETUP: Self = Self(128);
112    pub const STORED_ANIMATED: Self = Self(256);
113    pub const ENABLE_COMPOSITE: Self = Self(512);
114
115    #[inline]
116    pub const fn contains(self, other: Self) -> bool {
117        (self.0 & other.0) == other.0
118    }
119
120    #[inline]
121    pub const fn is_empty(self) -> bool {
122        self.0 == 0
123    }
124}
125
126impl core::ops::BitOr for SequenceFlag {
127    type Output = Self;
128    #[inline]
129    fn bitor(self, rhs: Self) -> Self {
130        Self(self.0 | rhs.0)
131    }
132}
133
134impl core::ops::BitAnd for SequenceFlag {
135    type Output = Self;
136    #[inline]
137    fn bitand(self, rhs: Self) -> Self {
138        Self(self.0 & rhs.0)
139    }
140}
141
142impl core::ops::Not for SequenceFlag {
143    type Output = Self;
144    #[inline]
145    fn not(self) -> Self {
146        Self(!self.0)
147    }
148}
149
150impl core::fmt::Debug for SequenceFlag {
151    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152        write!(f, "SequenceFlag({:#x})", self.0)
153    }
154}
155
156/// Bit flags. Combine with `|`, test with [`BoneFlag::contains`].
157#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
158pub struct BoneFlag(pub i32);
159
160impl BoneFlag {
161    pub const NONE: Self = Self(0);
162    pub const IGNORE_PARENT_TRANSLATE: Self = Self(1);
163    pub const IGNORE_PARENT_SCALE: Self = Self(2);
164    pub const IGNORE_PARENT_ROTATION: Self = Self(4);
165    pub const SPHERICAL_BILLBOARD: Self = Self(8);
166    pub const CYLINDRICAL_BILLBOARD_X: Self = Self(16);
167    pub const CYLINDRICAL_BILLBOARD_Y: Self = Self(32);
168    pub const CYLINDRICAL_BILLBOARD_Z: Self = Self(64);
169    pub const TRANSFORMED: Self = Self(512);
170    pub const KINEMATIC: Self = Self(1024);
171    pub const HELMET_ANIM_SCALED: Self = Self(4096);
172
173    #[inline]
174    pub const fn contains(self, other: Self) -> bool {
175        (self.0 & other.0) == other.0
176    }
177
178    #[inline]
179    pub const fn is_empty(self) -> bool {
180        self.0 == 0
181    }
182}
183
184impl core::ops::BitOr for BoneFlag {
185    type Output = Self;
186    #[inline]
187    fn bitor(self, rhs: Self) -> Self {
188        Self(self.0 | rhs.0)
189    }
190}
191
192impl core::ops::BitAnd for BoneFlag {
193    type Output = Self;
194    #[inline]
195    fn bitand(self, rhs: Self) -> Self {
196        Self(self.0 & rhs.0)
197    }
198}
199
200impl core::ops::Not for BoneFlag {
201    type Output = Self;
202    #[inline]
203    fn not(self) -> Self {
204        Self(!self.0)
205    }
206}
207
208impl core::fmt::Debug for BoneFlag {
209    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
210        write!(f, "BoneFlag({:#x})", self.0)
211    }
212}
213
214/// Bit flags. Combine with `|`, test with [`MaterialFlag::contains`].
215#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
216pub struct MaterialFlag(pub i32);
217
218impl MaterialFlag {
219    pub const NONE: Self = Self(0);
220    pub const UNLIT: Self = Self(1);
221    pub const UNFOGGED: Self = Self(2);
222    pub const TWO_SIDED: Self = Self(4);
223    pub const DEPTH_TEST: Self = Self(8);
224    pub const DEPTH_WRITE: Self = Self(16);
225    pub const NO_ALPHA_COMPOSITE: Self = Self(2048);
226
227    #[inline]
228    pub const fn contains(self, other: Self) -> bool {
229        (self.0 & other.0) == other.0
230    }
231
232    #[inline]
233    pub const fn is_empty(self) -> bool {
234        self.0 == 0
235    }
236}
237
238impl core::ops::BitOr for MaterialFlag {
239    type Output = Self;
240    #[inline]
241    fn bitor(self, rhs: Self) -> Self {
242        Self(self.0 | rhs.0)
243    }
244}
245
246impl core::ops::BitAnd for MaterialFlag {
247    type Output = Self;
248    #[inline]
249    fn bitand(self, rhs: Self) -> Self {
250        Self(self.0 & rhs.0)
251    }
252}
253
254impl core::ops::Not for MaterialFlag {
255    type Output = Self;
256    #[inline]
257    fn not(self) -> Self {
258        Self(!self.0)
259    }
260}
261
262impl core::fmt::Debug for MaterialFlag {
263    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
264        write!(f, "MaterialFlag({:#x})", self.0)
265    }
266}
267
268#[repr(i32)]
269#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
270pub enum ParticleEmitterType {
271    Plane = 1,
272    Sphere = 2,
273    Spline = 3,
274    Bone = 4,
275}
276
277impl TryFrom<i32> for ParticleEmitterType {
278    type Error = crate::Error;
279    fn try_from(v: i32) -> Result<Self, crate::Error> {
280        match v {
281            1 => Ok(ParticleEmitterType::Plane),
282            2 => Ok(ParticleEmitterType::Sphere),
283            3 => Ok(ParticleEmitterType::Spline),
284            4 => Ok(ParticleEmitterType::Bone),
285            other => Err(crate::Error::UnknownEnum {
286                name: "ParticleEmitterType",
287                value: other,
288            }),
289        }
290    }
291}
292
293#[repr(i32)]
294#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
295pub enum ParticleBlending {
296    Opaque = 0,
297    AlphaBlend = 1,
298    Additive = 2,
299    AlphaTest = 3,
300    AdditiveAlphaTest = 4,
301}
302
303impl TryFrom<i32> for ParticleBlending {
304    type Error = crate::Error;
305    fn try_from(v: i32) -> Result<Self, crate::Error> {
306        match v {
307            0 => Ok(ParticleBlending::Opaque),
308            1 => Ok(ParticleBlending::AlphaBlend),
309            2 => Ok(ParticleBlending::Additive),
310            3 => Ok(ParticleBlending::AlphaTest),
311            4 => Ok(ParticleBlending::AdditiveAlphaTest),
312            other => Err(crate::Error::UnknownEnum {
313                name: "ParticleBlending",
314                value: other,
315            }),
316        }
317    }
318}
319
320/// Bit flags. Combine with `|`, test with [`ParticleFlag::contains`].
321#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
322pub struct ParticleFlag(pub i32);
323
324impl ParticleFlag {
325    pub const NONE: Self = Self(0);
326    pub const UNLIT: Self = Self(1);
327    pub const SORT_PARTICLES: Self = Self(2);
328    pub const VELOCITY_ORIENT: Self = Self(4);
329    pub const UNFOGGED: Self = Self(8);
330    pub const WORLD_SPACE: Self = Self(16);
331    pub const INHERIT_BONE_SCALE: Self = Self(32);
332    pub const INHERIT_VELOCITY: Self = Self(64);
333    pub const IMPLOSION_FILTER: Self = Self(128);
334    pub const HEMISPHERE_UP_DIRECTION: Self = Self(256);
335    pub const NEGATE_SPIN_RANDOM: Self = Self(512);
336    pub const CLAMP_TAIL_TO_AGE: Self = Self(1024);
337    pub const INHERIT_POSITION: Self = Self(2048);
338    pub const XY_QUAD: Self = Self(4096);
339    pub const PROJECT_PARTICLE: Self = Self(8192);
340    pub const FOLLOW_POSITION: Self = Self(16384);
341    pub const SQUIRT: Self = Self(32768);
342    pub const CHOOSE_RANDOM_TEXTURE: Self = Self(65536);
343    pub const HEAD_STYLE: Self = Self(131072);
344    pub const TAIL_STYLE: Self = Self(262144);
345    pub const UNSCALED_SIZE_VARIATION: Self = Self(524288);
346    pub const REFRACTION: Self = Self(1048576);
347    pub const RAND_FLIPBOOK_START: Self = Self(2097152);
348    pub const UNK_0X_400000: Self = Self(4194304);
349    pub const COMPRESSED_GRAVITY: Self = Self(8388608);
350    pub const BONE_GENERATOR_BONE: Self = Self(16777216);
351    pub const NO_GLOBAL_VIEW_SCALE: Self = Self(33554432);
352    pub const LOD_IGNORE_DISTANCE: Self = Self(67108864);
353    pub const OFFSET_HEAD_BY_SPIN: Self = Self(134217728);
354    pub const MULTI_TEXTURE: Self = Self(268435456);
355    pub const MULTITEX_USE_MODX_4: Self = Self(536870912);
356    pub const MULTITEX_USE_3_COLORS: Self = Self(1073741824);
357    pub const DYNAMIC_WIND: Self = Self(-2147483648);
358
359    #[inline]
360    pub const fn contains(self, other: Self) -> bool {
361        (self.0 & other.0) == other.0
362    }
363
364    #[inline]
365    pub const fn is_empty(self) -> bool {
366        self.0 == 0
367    }
368}
369
370impl core::ops::BitOr for ParticleFlag {
371    type Output = Self;
372    #[inline]
373    fn bitor(self, rhs: Self) -> Self {
374        Self(self.0 | rhs.0)
375    }
376}
377
378impl core::ops::BitAnd for ParticleFlag {
379    type Output = Self;
380    #[inline]
381    fn bitand(self, rhs: Self) -> Self {
382        Self(self.0 & rhs.0)
383    }
384}
385
386impl core::ops::Not for ParticleFlag {
387    type Output = Self;
388    #[inline]
389    fn not(self) -> Self {
390        Self(!self.0)
391    }
392}
393
394impl core::fmt::Debug for ParticleFlag {
395    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
396        write!(f, "ParticleFlag({:#x})", self.0)
397    }
398}
399
400/// How the client drives a body — the value stored in BODY is inverted relative to Domino's own `dmBodyType`.
401#[repr(i32)]
402#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
403pub enum PhysicsBodyType {
404    /// Animation-driven collider. Becomes `dmBodyType` 1; the client keeps it glued to its bone and the simulation only reads it.
405    Kinematic = 0,
406    /// Simulated. Becomes `dmBodyType` 0 and gets its bone transform written back every frame. These are the cloth/tassel segments.
407    Dynamic = 1,
408}
409
410impl TryFrom<i32> for PhysicsBodyType {
411    type Error = crate::Error;
412    fn try_from(v: i32) -> Result<Self, crate::Error> {
413        match v {
414            0 => Ok(PhysicsBodyType::Kinematic),
415            1 => Ok(PhysicsBodyType::Dynamic),
416            other => Err(crate::Error::UnknownEnum {
417                name: "PhysicsBodyType",
418                value: other,
419            }),
420        }
421    }
422}
423
424/// Which shape chunk a PhysicsShape indexes into.
425#[repr(i32)]
426#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
427pub enum PhysicsShapeType {
428    /// BOXS
429    Box = 0,
430    /// CAPS
431    Capsule = 1,
432    /// SPHS
433    Sphere = 2,
434    /// PLYT, version 3+
435    Polytope = 3,
436}
437
438impl TryFrom<i32> for PhysicsShapeType {
439    type Error = crate::Error;
440    fn try_from(v: i32) -> Result<Self, crate::Error> {
441        match v {
442            0 => Ok(PhysicsShapeType::Box),
443            1 => Ok(PhysicsShapeType::Capsule),
444            2 => Ok(PhysicsShapeType::Sphere),
445            3 => Ok(PhysicsShapeType::Polytope),
446            other => Err(crate::Error::UnknownEnum {
447                name: "PhysicsShapeType",
448                value: other,
449            }),
450        }
451    }
452}
453
454/// Which joint chunk a PhysicsJoint indexes into.
455#[repr(i32)]
456#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
457pub enum PhysicsJointType {
458    /// SPHJ
459    Spherical = 0,
460    /// SHOJ / SHJ2
461    Shoulder = 1,
462    /// WELJ / WLJ2 / WLJ3
463    Weld = 2,
464    /// REVJ / REV2, version 2+
465    Revolute = 3,
466    /// PRSJ / PRS2, version 2+
467    Prismatic = 4,
468    /// DSTJ, version 2+
469    Distance = 5,
470}
471
472impl TryFrom<i32> for PhysicsJointType {
473    type Error = crate::Error;
474    fn try_from(v: i32) -> Result<Self, crate::Error> {
475        match v {
476            0 => Ok(PhysicsJointType::Spherical),
477            1 => Ok(PhysicsJointType::Shoulder),
478            2 => Ok(PhysicsJointType::Weld),
479            3 => Ok(PhysicsJointType::Revolute),
480            4 => Ok(PhysicsJointType::Prismatic),
481            5 => Ok(PhysicsJointType::Distance),
482            other => Err(crate::Error::UnknownEnum {
483                name: "PhysicsJointType",
484                value: other,
485            }),
486        }
487    }
488}
489
490pub struct CompatQuaternion {
491    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2CompatQuaternion>,
492}
493
494impl Drop for CompatQuaternion {
495    fn drop(&mut self) {
496        // SAFETY: `raw` came from a native constructor and Drop runs once.
497        unsafe { ffi::whiteout_m2_M2CompatQuaternion_delete(self.raw.as_ptr()) }
498    }
499}
500
501impl CompatQuaternion {
502    /// # Safety
503    /// `raw` must be a live handle this value takes ownership of.
504    #[allow(dead_code)] // used by whichever methods return this type
505    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2CompatQuaternion) -> Option<Self> {
506        core::ptr::NonNull::new(raw).map(|raw| CompatQuaternion { raw })
507    }
508}
509
510// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
511// is deliberately NOT implemented — the C++ types make no documented
512// guarantee about concurrent use, and claiming one we haven't verified
513// would be unsound. See `@bind thread_safe` in the plan.
514unsafe impl Send for CompatQuaternion {}
515
516impl core::fmt::Debug for CompatQuaternion {
517    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
518        f.debug_struct("CompatQuaternion").finish_non_exhaustive()
519    }
520}
521
522impl CompatQuaternion {
523    /// # Panics
524    /// Panics if the native allocation fails.
525    pub fn new() -> Self {
526        // SAFETY: the native constructor returns a live handle; a null here
527        // means the library is unusable.
528        unsafe {
529            let raw = ffi::whiteout_m2_M2CompatQuaternion_new();
530            Self::from_raw(raw).expect("native CompatQuaternion allocation failed")
531        }
532    }
533}
534
535impl Default for CompatQuaternion {
536    fn default() -> Self {
537        Self::new()
538    }
539}
540
541pub struct ColorBGRA {
542    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ColorBGRA>,
543}
544
545impl Drop for ColorBGRA {
546    fn drop(&mut self) {
547        // SAFETY: `raw` came from a native constructor and Drop runs once.
548        unsafe { ffi::whiteout_m2_M2ColorBGRA_delete(self.raw.as_ptr()) }
549    }
550}
551
552impl ColorBGRA {
553    /// # Safety
554    /// `raw` must be a live handle this value takes ownership of.
555    #[allow(dead_code)] // used by whichever methods return this type
556    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ColorBGRA) -> Option<Self> {
557        core::ptr::NonNull::new(raw).map(|raw| ColorBGRA { raw })
558    }
559}
560
561// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
562// is deliberately NOT implemented — the C++ types make no documented
563// guarantee about concurrent use, and claiming one we haven't verified
564// would be unsound. See `@bind thread_safe` in the plan.
565unsafe impl Send for ColorBGRA {}
566
567impl core::fmt::Debug for ColorBGRA {
568    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
569        f.debug_struct("ColorBGRA").finish_non_exhaustive()
570    }
571}
572
573impl ColorBGRA {
574    /// # Panics
575    /// Panics if the native allocation fails.
576    pub fn new() -> Self {
577        // SAFETY: the native constructor returns a live handle; a null here
578        // means the library is unusable.
579        unsafe {
580            let raw = ffi::whiteout_m2_M2ColorBGRA_new();
581            Self::from_raw(raw).expect("native ColorBGRA allocation failed")
582        }
583    }
584}
585
586impl Default for ColorBGRA {
587    fn default() -> Self {
588        Self::new()
589    }
590}
591
592pub struct Extent {
593    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Extent>,
594}
595
596impl Drop for Extent {
597    fn drop(&mut self) {
598        // SAFETY: `raw` came from a native constructor and Drop runs once.
599        unsafe { ffi::whiteout_m2_M2Extent_delete(self.raw.as_ptr()) }
600    }
601}
602
603impl Extent {
604    /// # Safety
605    /// `raw` must be a live handle this value takes ownership of.
606    #[allow(dead_code)] // used by whichever methods return this type
607    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Extent) -> Option<Self> {
608        core::ptr::NonNull::new(raw).map(|raw| Extent { raw })
609    }
610}
611
612// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
613// is deliberately NOT implemented — the C++ types make no documented
614// guarantee about concurrent use, and claiming one we haven't verified
615// would be unsound. See `@bind thread_safe` in the plan.
616unsafe impl Send for Extent {}
617
618impl core::fmt::Debug for Extent {
619    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
620        f.debug_struct("Extent").finish_non_exhaustive()
621    }
622}
623
624impl Extent {
625    /// # Panics
626    /// Panics if the native allocation fails.
627    pub fn new() -> Self {
628        // SAFETY: the native constructor returns a live handle; a null here
629        // means the library is unusable.
630        unsafe {
631            let raw = ffi::whiteout_m2_M2Extent_new();
632            Self::from_raw(raw).expect("native Extent allocation failed")
633        }
634    }
635
636    pub fn minimum(&self) -> crate::math::Vector3f {
637        // SAFETY: the getter returns an interior pointer to a
638        // layout-identical POD; we copy it out immediately.
639        unsafe {
640            *(ffi::whiteout_m2_M2Extent_get_minimum(self.raw.as_ptr())
641                as *const crate::math::Vector3f)
642        }
643    }
644
645    pub fn set_minimum(&mut self, value: crate::math::Vector3f) {
646        // SAFETY: as above, in the other direction.
647        unsafe {
648            ffi::whiteout_m2_M2Extent_set_minimum(
649                self.raw.as_ptr(),
650                &value as *const crate::math::Vector3f as *const _,
651            )
652        }
653    }
654
655    pub fn maximum(&self) -> crate::math::Vector3f {
656        // SAFETY: the getter returns an interior pointer to a
657        // layout-identical POD; we copy it out immediately.
658        unsafe {
659            *(ffi::whiteout_m2_M2Extent_get_maximum(self.raw.as_ptr())
660                as *const crate::math::Vector3f)
661        }
662    }
663
664    pub fn set_maximum(&mut self, value: crate::math::Vector3f) {
665        // SAFETY: as above, in the other direction.
666        unsafe {
667            ffi::whiteout_m2_M2Extent_set_maximum(
668                self.raw.as_ptr(),
669                &value as *const crate::math::Vector3f as *const _,
670            )
671        }
672    }
673
674    pub fn sphere_radius(&self) -> f32 {
675        // SAFETY: plain scalar read through a live handle.
676        unsafe { ffi::whiteout_m2_M2Extent_get_sphereRadius(self.raw.as_ptr()) }
677    }
678
679    pub fn set_sphere_radius(&mut self, value: f32) {
680        // SAFETY: plain scalar write through a live handle.
681        unsafe { ffi::whiteout_m2_M2Extent_set_sphereRadius(self.raw.as_ptr(), value) }
682    }
683}
684
685impl Default for Extent {
686    fn default() -> Self {
687        Self::new()
688    }
689}
690
691/// One sequence's slice of a key array, as the file writes it: a count and an offset into whichever file holds that sequence's keys.
692///
693/// Kept only by a lazily parsed model (Parser::setLazyAnimations), which leaves the sub-arrays of externally-stored sequences empty until loadSequence() reads their `.anim` sibling. Nothing else needs it: an eager parse consumes the reference on the spot.
694pub struct KeySpanRef {
695    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2KeySpanRef>,
696}
697
698impl Drop for KeySpanRef {
699    fn drop(&mut self) {
700        // SAFETY: `raw` came from a native constructor and Drop runs once.
701        unsafe { ffi::whiteout_m2_M2KeySpanRef_delete(self.raw.as_ptr()) }
702    }
703}
704
705impl KeySpanRef {
706    /// # Safety
707    /// `raw` must be a live handle this value takes ownership of.
708    #[allow(dead_code)] // used by whichever methods return this type
709    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2KeySpanRef) -> Option<Self> {
710        core::ptr::NonNull::new(raw).map(|raw| KeySpanRef { raw })
711    }
712}
713
714// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
715// is deliberately NOT implemented — the C++ types make no documented
716// guarantee about concurrent use, and claiming one we haven't verified
717// would be unsound. See `@bind thread_safe` in the plan.
718unsafe impl Send for KeySpanRef {}
719
720impl core::fmt::Debug for KeySpanRef {
721    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
722        f.debug_struct("KeySpanRef").finish_non_exhaustive()
723    }
724}
725
726impl KeySpanRef {
727    /// # Panics
728    /// Panics if the native allocation fails.
729    pub fn new() -> Self {
730        // SAFETY: the native constructor returns a live handle; a null here
731        // means the library is unusable.
732        unsafe {
733            let raw = ffi::whiteout_m2_M2KeySpanRef_new();
734            Self::from_raw(raw).expect("native KeySpanRef allocation failed")
735        }
736    }
737
738    pub fn count(&self) -> u32 {
739        // SAFETY: plain scalar read through a live handle.
740        unsafe { ffi::whiteout_m2_M2KeySpanRef_get_count(self.raw.as_ptr()) }
741    }
742
743    pub fn set_count(&mut self, value: u32) {
744        // SAFETY: plain scalar write through a live handle.
745        unsafe { ffi::whiteout_m2_M2KeySpanRef_set_count(self.raw.as_ptr(), value) }
746    }
747
748    pub fn offset(&self) -> u32 {
749        // SAFETY: plain scalar read through a live handle.
750        unsafe { ffi::whiteout_m2_M2KeySpanRef_get_offset(self.raw.as_ptr()) }
751    }
752
753    pub fn set_offset(&mut self, value: u32) {
754        // SAFETY: plain scalar write through a live handle.
755        unsafe { ffi::whiteout_m2_M2KeySpanRef_set_offset(self.raw.as_ptr(), value) }
756    }
757}
758
759impl Default for KeySpanRef {
760    fn default() -> Self {
761        Self::new()
762    }
763}
764
765pub struct AnimationTrackBase {
766    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackBase>,
767}
768
769impl Drop for AnimationTrackBase {
770    fn drop(&mut self) {
771        // SAFETY: `raw` came from a native constructor and Drop runs once.
772        unsafe { ffi::whiteout_m2_M2AnimationTrackBase_delete(self.raw.as_ptr()) }
773    }
774}
775
776impl AnimationTrackBase {
777    /// # Safety
778    /// `raw` must be a live handle this value takes ownership of.
779    #[allow(dead_code)] // used by whichever methods return this type
780    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2AnimationTrackBase) -> Option<Self> {
781        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackBase { raw })
782    }
783}
784
785// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
786// is deliberately NOT implemented — the C++ types make no documented
787// guarantee about concurrent use, and claiming one we haven't verified
788// would be unsound. See `@bind thread_safe` in the plan.
789unsafe impl Send for AnimationTrackBase {}
790
791impl core::fmt::Debug for AnimationTrackBase {
792    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
793        f.debug_struct("AnimationTrackBase").finish_non_exhaustive()
794    }
795}
796
797impl AnimationTrackBase {
798    /// # Panics
799    /// Panics if the native allocation fails.
800    pub fn new() -> Self {
801        // SAFETY: the native constructor returns a live handle; a null here
802        // means the library is unusable.
803        unsafe {
804            let raw = ffi::whiteout_m2_M2AnimationTrackBase_new();
805            Self::from_raw(raw).expect("native AnimationTrackBase allocation failed")
806        }
807    }
808
809    pub fn interpolation_type(&self) -> InterpolationType {
810        // SAFETY: scalar read; the discriminant is validated below.
811        unsafe { ffi::whiteout_m2_M2AnimationTrackBase_get_interpolationType(self.raw.as_ptr()) }
812            .try_into()
813            .expect("unknown enum discriminant from the native library")
814    }
815
816    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
817        // SAFETY: scalar write through a live handle.
818        unsafe {
819            ffi::whiteout_m2_M2AnimationTrackBase_set_interpolationType(
820                self.raw.as_ptr(),
821                value as i32,
822            )
823        }
824    }
825
826    pub fn global_sequence_id(&self) -> u16 {
827        // SAFETY: plain scalar read through a live handle.
828        unsafe { ffi::whiteout_m2_M2AnimationTrackBase_get_globalSequenceId(self.raw.as_ptr()) }
829    }
830
831    pub fn set_global_sequence_id(&mut self, value: u16) {
832        // SAFETY: plain scalar write through a live handle.
833        unsafe {
834            ffi::whiteout_m2_M2AnimationTrackBase_set_globalSequenceId(self.raw.as_ptr(), value)
835        }
836    }
837
838    /// Number of inner sequences.
839    pub fn timestamps_len(&self) -> usize {
840        // SAFETY: scalar read through a live handle.
841        unsafe { ffi::whiteout_m2_M2AnimationTrackBase_get_timestamps_count(self.raw.as_ptr()) }
842    }
843
844    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
845    ///
846    /// Each inner vector is contiguous on its own, but the outer one
847    /// is a vector of vectors — so this borrows per sequence rather
848    /// than handing back one flat slice.
849    pub fn timestamps(&self, outer: usize) -> &[u32] {
850        if outer >= self.timestamps_len() {
851            return &[];
852        }
853        // SAFETY: index checked; the pointer borrows `self`.
854        unsafe {
855            let n = ffi::whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_count(
856                self.raw.as_ptr(),
857                outer,
858            );
859            let p = ffi::whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_data(
860                self.raw.as_ptr(),
861                outer,
862            );
863            if p.is_null() || n == 0 {
864                &[]
865            } else {
866                core::slice::from_raw_parts(p, n)
867            }
868        }
869    }
870
871    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
872        if outer >= self.timestamps_len() {
873            return &mut [];
874        }
875        // SAFETY: as above; `&mut self` rules out aliasing.
876        unsafe {
877            let n = ffi::whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_count(
878                self.raw.as_ptr(),
879                outer,
880            );
881            let p = ffi::whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_data(
882                self.raw.as_ptr(),
883                outer,
884            ) as *mut u32;
885            if p.is_null() || n == 0 {
886                &mut []
887            } else {
888                core::slice::from_raw_parts_mut(p, n)
889            }
890        }
891    }
892
893    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
894        // SAFETY: the native side copies `values` before returning.
895        unsafe {
896            ffi::whiteout_m2_M2AnimationTrackBase_assign_timestamps_inner(
897                self.raw.as_ptr(),
898                outer,
899                values.as_ptr() as *const _,
900                values.len(),
901            )
902        }
903    }
904
905    /// Resize the outer sequence. Do this before taking any borrow.
906    pub fn resize_timestamps(&mut self, count: usize) {
907        // SAFETY: exclusive access, so no borrow is outstanding.
908        unsafe { ffi::whiteout_m2_M2AnimationTrackBase_resize_timestamps(self.raw.as_ptr(), count) }
909    }
910
911    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
912        // SAFETY: as above.
913        unsafe {
914            ffi::whiteout_m2_M2AnimationTrackBase_resize_timestamps_inner(
915                self.raw.as_ptr(),
916                outer,
917                count,
918            )
919        }
920    }
921}
922
923impl Default for AnimationTrackBase {
924    fn default() -> Self {
925        Self::new()
926    }
927}
928
929pub struct ParticleEmitterExtension {
930    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ParticleEmitterExtension>,
931}
932
933impl Drop for ParticleEmitterExtension {
934    fn drop(&mut self) {
935        // SAFETY: `raw` came from a native constructor and Drop runs once.
936        unsafe { ffi::whiteout_m2_M2ParticleEmitterExtension_delete(self.raw.as_ptr()) }
937    }
938}
939
940impl ParticleEmitterExtension {
941    /// # Safety
942    /// `raw` must be a live handle this value takes ownership of.
943    #[allow(dead_code)] // used by whichever methods return this type
944    pub(crate) unsafe fn from_raw(
945        raw: *mut ffi::whiteout_M2ParticleEmitterExtension,
946    ) -> Option<Self> {
947        core::ptr::NonNull::new(raw).map(|raw| ParticleEmitterExtension { raw })
948    }
949}
950
951// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
952// is deliberately NOT implemented — the C++ types make no documented
953// guarantee about concurrent use, and claiming one we haven't verified
954// would be unsound. See `@bind thread_safe` in the plan.
955unsafe impl Send for ParticleEmitterExtension {}
956
957impl core::fmt::Debug for ParticleEmitterExtension {
958    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
959        f.debug_struct("ParticleEmitterExtension")
960            .finish_non_exhaustive()
961    }
962}
963
964impl ParticleEmitterExtension {
965    /// # Panics
966    /// Panics if the native allocation fails.
967    pub fn new() -> Self {
968        // SAFETY: the native constructor returns a live handle; a null here
969        // means the library is unusable.
970        unsafe {
971            let raw = ffi::whiteout_m2_M2ParticleEmitterExtension_new();
972            Self::from_raw(raw).expect("native ParticleEmitterExtension allocation failed")
973        }
974    }
975
976    pub fn z_source(&self) -> f32 {
977        // SAFETY: plain scalar read through a live handle.
978        unsafe { ffi::whiteout_m2_M2ParticleEmitterExtension_get_zSource(self.raw.as_ptr()) }
979    }
980
981    pub fn set_z_source(&mut self, value: f32) {
982        // SAFETY: plain scalar write through a live handle.
983        unsafe { ffi::whiteout_m2_M2ParticleEmitterExtension_set_zSource(self.raw.as_ptr(), value) }
984    }
985
986    pub fn color_mult(&self) -> f32 {
987        // SAFETY: plain scalar read through a live handle.
988        unsafe { ffi::whiteout_m2_M2ParticleEmitterExtension_get_colorMult(self.raw.as_ptr()) }
989    }
990
991    pub fn set_color_mult(&mut self, value: f32) {
992        // SAFETY: plain scalar write through a live handle.
993        unsafe {
994            ffi::whiteout_m2_M2ParticleEmitterExtension_set_colorMult(self.raw.as_ptr(), value)
995        }
996    }
997
998    pub fn alpha_mult(&self) -> f32 {
999        // SAFETY: plain scalar read through a live handle.
1000        unsafe { ffi::whiteout_m2_M2ParticleEmitterExtension_get_alphaMult(self.raw.as_ptr()) }
1001    }
1002
1003    pub fn set_alpha_mult(&mut self, value: f32) {
1004        // SAFETY: plain scalar write through a live handle.
1005        unsafe {
1006            ffi::whiteout_m2_M2ParticleEmitterExtension_set_alphaMult(self.raw.as_ptr(), value)
1007        }
1008    }
1009}
1010
1011impl Default for ParticleEmitterExtension {
1012    fn default() -> Self {
1013        Self::new()
1014    }
1015}
1016
1017pub struct LodProfile {
1018    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2LodProfile>,
1019}
1020
1021impl Drop for LodProfile {
1022    fn drop(&mut self) {
1023        // SAFETY: `raw` came from a native constructor and Drop runs once.
1024        unsafe { ffi::whiteout_m2_M2LodProfile_delete(self.raw.as_ptr()) }
1025    }
1026}
1027
1028impl LodProfile {
1029    /// # Safety
1030    /// `raw` must be a live handle this value takes ownership of.
1031    #[allow(dead_code)] // used by whichever methods return this type
1032    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2LodProfile) -> Option<Self> {
1033        core::ptr::NonNull::new(raw).map(|raw| LodProfile { raw })
1034    }
1035}
1036
1037// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1038// is deliberately NOT implemented — the C++ types make no documented
1039// guarantee about concurrent use, and claiming one we haven't verified
1040// would be unsound. See `@bind thread_safe` in the plan.
1041unsafe impl Send for LodProfile {}
1042
1043impl core::fmt::Debug for LodProfile {
1044    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1045        f.debug_struct("LodProfile").finish_non_exhaustive()
1046    }
1047}
1048
1049impl LodProfile {
1050    /// # Panics
1051    /// Panics if the native allocation fails.
1052    pub fn new() -> Self {
1053        // SAFETY: the native constructor returns a live handle; a null here
1054        // means the library is unusable.
1055        unsafe {
1056            let raw = ffi::whiteout_m2_M2LodProfile_new();
1057            Self::from_raw(raw).expect("native LodProfile allocation failed")
1058        }
1059    }
1060
1061    pub fn flags(&self) -> u16 {
1062        // SAFETY: plain scalar read through a live handle.
1063        unsafe { ffi::whiteout_m2_M2LodProfile_get_flags(self.raw.as_ptr()) }
1064    }
1065
1066    pub fn set_flags(&mut self, value: u16) {
1067        // SAFETY: plain scalar write through a live handle.
1068        unsafe { ffi::whiteout_m2_M2LodProfile_set_flags(self.raw.as_ptr(), value) }
1069    }
1070
1071    pub fn num_lod_levels(&self) -> u16 {
1072        // SAFETY: plain scalar read through a live handle.
1073        unsafe { ffi::whiteout_m2_M2LodProfile_get_numLodLevels(self.raw.as_ptr()) }
1074    }
1075
1076    pub fn set_num_lod_levels(&mut self, value: u16) {
1077        // SAFETY: plain scalar write through a live handle.
1078        unsafe { ffi::whiteout_m2_M2LodProfile_set_numLodLevels(self.raw.as_ptr(), value) }
1079    }
1080
1081    pub fn lod_distance(&self) -> f32 {
1082        // SAFETY: plain scalar read through a live handle.
1083        unsafe { ffi::whiteout_m2_M2LodProfile_get_lodDistance(self.raw.as_ptr()) }
1084    }
1085
1086    pub fn set_lod_distance(&mut self, value: f32) {
1087        // SAFETY: plain scalar write through a live handle.
1088        unsafe { ffi::whiteout_m2_M2LodProfile_set_lodDistance(self.raw.as_ptr(), value) }
1089    }
1090
1091    /// Per-LOD particle bone mask index. Only four are stored, but the client drives up to eight LOD levels: it copies [0..3] into its first four slots and then replicates entry [3] into slots 4..7.
1092    /// Number of elements — a fixed-size C++ array.
1093    pub const fn particle_bone_lod_len() -> usize {
1094        4
1095    }
1096
1097    /// # Panics
1098    /// If `index >= 4`, matching Rust slice indexing.
1099    pub fn particle_bone_lod(&self, index: usize) -> u8 {
1100        assert!(
1101            index < 4,
1102            "particle_bone_lod index {index} out of range (len 4)"
1103        );
1104        // SAFETY: index checked above; plain scalar read.
1105        unsafe { ffi::whiteout_m2_M2LodProfile_get_particleBoneLod_at(self.raw.as_ptr(), index) }
1106    }
1107
1108    /// # Panics
1109    /// If `index >= 4`.
1110    pub fn set_particle_bone_lod(&mut self, index: usize, value: u8) {
1111        assert!(
1112            index < 4,
1113            "particle_bone_lod index {index} out of range (len 4)"
1114        );
1115        // SAFETY: index checked above.
1116        unsafe {
1117            ffi::whiteout_m2_M2LodProfile_set_particleBoneLod_at(self.raw.as_ptr(), index, value)
1118        }
1119    }
1120
1121    /// Fixed-point LOD scale, applied as `lodScaleRaw / 2048.0` and only when `flags & 0x08` is set (otherwise the client uses 1.0). This is the pair of bytes previously read as `reserved0` + `lodFlags`; reading it as a u16 explains why the high byte looked like a mirror of flags bit 3, since 0x0800 / 2048 == 1.0.
1122    pub fn lod_scale_raw(&self) -> u16 {
1123        // SAFETY: plain scalar read through a live handle.
1124        unsafe { ffi::whiteout_m2_M2LodProfile_get_lodScaleRaw(self.raw.as_ptr()) }
1125    }
1126
1127    pub fn set_lod_scale_raw(&mut self, value: u16) {
1128        // SAFETY: plain scalar write through a live handle.
1129        unsafe { ffi::whiteout_m2_M2LodProfile_set_lodScaleRaw(self.raw.as_ptr(), value) }
1130    }
1131
1132    pub fn lod_batch_count(&self) -> u8 {
1133        // SAFETY: plain scalar read through a live handle.
1134        unsafe { ffi::whiteout_m2_M2LodProfile_get_lodBatchCount(self.raw.as_ptr()) }
1135    }
1136
1137    pub fn set_lod_batch_count(&mut self, value: u8) {
1138        // SAFETY: plain scalar write through a live handle.
1139        unsafe { ffi::whiteout_m2_M2LodProfile_set_lodBatchCount(self.raw.as_ptr(), value) }
1140    }
1141
1142    pub fn reserved_1(&self) -> u8 {
1143        // SAFETY: plain scalar read through a live handle.
1144        unsafe { ffi::whiteout_m2_M2LodProfile_get_reserved1(self.raw.as_ptr()) }
1145    }
1146
1147    pub fn set_reserved_1(&mut self, value: u8) {
1148        // SAFETY: plain scalar write through a live handle.
1149        unsafe { ffi::whiteout_m2_M2LodProfile_set_reserved1(self.raw.as_ptr(), value) }
1150    }
1151}
1152
1153impl Default for LodProfile {
1154    fn default() -> Self {
1155        Self::new()
1156    }
1157}
1158
1159pub struct WaterfallData {
1160    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2WaterfallData>,
1161}
1162
1163impl Drop for WaterfallData {
1164    fn drop(&mut self) {
1165        // SAFETY: `raw` came from a native constructor and Drop runs once.
1166        unsafe { ffi::whiteout_m2_M2WaterfallData_delete(self.raw.as_ptr()) }
1167    }
1168}
1169
1170impl WaterfallData {
1171    /// # Safety
1172    /// `raw` must be a live handle this value takes ownership of.
1173    #[allow(dead_code)] // used by whichever methods return this type
1174    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2WaterfallData) -> Option<Self> {
1175        core::ptr::NonNull::new(raw).map(|raw| WaterfallData { raw })
1176    }
1177}
1178
1179// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1180// is deliberately NOT implemented — the C++ types make no documented
1181// guarantee about concurrent use, and claiming one we haven't verified
1182// would be unsound. See `@bind thread_safe` in the plan.
1183unsafe impl Send for WaterfallData {}
1184
1185impl core::fmt::Debug for WaterfallData {
1186    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1187        f.debug_struct("WaterfallData").finish_non_exhaustive()
1188    }
1189}
1190
1191impl WaterfallData {
1192    /// # Panics
1193    /// Panics if the native allocation fails.
1194    pub fn new() -> Self {
1195        // SAFETY: the native constructor returns a live handle; a null here
1196        // means the library is unusable.
1197        unsafe {
1198            let raw = ffi::whiteout_m2_M2WaterfallData_new();
1199            Self::from_raw(raw).expect("native WaterfallData allocation failed")
1200        }
1201    }
1202
1203    pub fn bump_scale(&self) -> f32 {
1204        // SAFETY: plain scalar read through a live handle.
1205        unsafe { ffi::whiteout_m2_M2WaterfallData_get_bumpScale(self.raw.as_ptr()) }
1206    }
1207
1208    pub fn set_bump_scale(&mut self, value: f32) {
1209        // SAFETY: plain scalar write through a live handle.
1210        unsafe { ffi::whiteout_m2_M2WaterfallData_set_bumpScale(self.raw.as_ptr(), value) }
1211    }
1212
1213    pub fn value_0x(&self) -> f32 {
1214        // SAFETY: plain scalar read through a live handle.
1215        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value0_x(self.raw.as_ptr()) }
1216    }
1217
1218    pub fn set_value_0x(&mut self, value: f32) {
1219        // SAFETY: plain scalar write through a live handle.
1220        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value0_x(self.raw.as_ptr(), value) }
1221    }
1222
1223    pub fn value_0y(&self) -> f32 {
1224        // SAFETY: plain scalar read through a live handle.
1225        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value0_y(self.raw.as_ptr()) }
1226    }
1227
1228    pub fn set_value_0y(&mut self, value: f32) {
1229        // SAFETY: plain scalar write through a live handle.
1230        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value0_y(self.raw.as_ptr(), value) }
1231    }
1232
1233    pub fn value_0z(&self) -> f32 {
1234        // SAFETY: plain scalar read through a live handle.
1235        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value0_z(self.raw.as_ptr()) }
1236    }
1237
1238    pub fn set_value_0z(&mut self, value: f32) {
1239        // SAFETY: plain scalar write through a live handle.
1240        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value0_z(self.raw.as_ptr(), value) }
1241    }
1242
1243    pub fn value_1w(&self) -> f32 {
1244        // SAFETY: plain scalar read through a live handle.
1245        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value1_w(self.raw.as_ptr()) }
1246    }
1247
1248    pub fn set_value_1w(&mut self, value: f32) {
1249        // SAFETY: plain scalar write through a live handle.
1250        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value1_w(self.raw.as_ptr(), value) }
1251    }
1252
1253    pub fn value_0w(&self) -> f32 {
1254        // SAFETY: plain scalar read through a live handle.
1255        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value0_w(self.raw.as_ptr()) }
1256    }
1257
1258    pub fn set_value_0w(&mut self, value: f32) {
1259        // SAFETY: plain scalar write through a live handle.
1260        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value0_w(self.raw.as_ptr(), value) }
1261    }
1262
1263    pub fn value_1x(&self) -> f32 {
1264        // SAFETY: plain scalar read through a live handle.
1265        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value1_x(self.raw.as_ptr()) }
1266    }
1267
1268    pub fn set_value_1x(&mut self, value: f32) {
1269        // SAFETY: plain scalar write through a live handle.
1270        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value1_x(self.raw.as_ptr(), value) }
1271    }
1272
1273    pub fn value_1y(&self) -> f32 {
1274        // SAFETY: plain scalar read through a live handle.
1275        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value1_y(self.raw.as_ptr()) }
1276    }
1277
1278    pub fn set_value_1y(&mut self, value: f32) {
1279        // SAFETY: plain scalar write through a live handle.
1280        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value1_y(self.raw.as_ptr(), value) }
1281    }
1282
1283    pub fn value_2w(&self) -> f32 {
1284        // SAFETY: plain scalar read through a live handle.
1285        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value2_w(self.raw.as_ptr()) }
1286    }
1287
1288    pub fn set_value_2w(&mut self, value: f32) {
1289        // SAFETY: plain scalar write through a live handle.
1290        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value2_w(self.raw.as_ptr(), value) }
1291    }
1292
1293    pub fn value_3y(&self) -> f32 {
1294        // SAFETY: plain scalar read through a live handle.
1295        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value3_y(self.raw.as_ptr()) }
1296    }
1297
1298    pub fn set_value_3y(&mut self, value: f32) {
1299        // SAFETY: plain scalar write through a live handle.
1300        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value3_y(self.raw.as_ptr(), value) }
1301    }
1302
1303    pub fn value_3x(&self) -> f32 {
1304        // SAFETY: plain scalar read through a live handle.
1305        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value3_x(self.raw.as_ptr()) }
1306    }
1307
1308    pub fn set_value_3x(&mut self, value: f32) {
1309        // SAFETY: plain scalar write through a live handle.
1310        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value3_x(self.raw.as_ptr(), value) }
1311    }
1312
1313    pub fn base_color(&self) -> crate::math::Vector4f {
1314        // SAFETY: the getter returns an interior pointer to a
1315        // layout-identical POD; we copy it out immediately.
1316        unsafe {
1317            *(ffi::whiteout_m2_M2WaterfallData_get_baseColor(self.raw.as_ptr())
1318                as *const crate::math::Vector4f)
1319        }
1320    }
1321
1322    pub fn set_base_color(&mut self, value: crate::math::Vector4f) {
1323        // SAFETY: as above, in the other direction.
1324        unsafe {
1325            ffi::whiteout_m2_M2WaterfallData_set_baseColor(
1326                self.raw.as_ptr(),
1327                &value as *const crate::math::Vector4f as *const _,
1328            )
1329        }
1330    }
1331
1332    pub fn flags(&self) -> u16 {
1333        // SAFETY: plain scalar read through a live handle.
1334        unsafe { ffi::whiteout_m2_M2WaterfallData_get_flags(self.raw.as_ptr()) }
1335    }
1336
1337    pub fn set_flags(&mut self, value: u16) {
1338        // SAFETY: plain scalar write through a live handle.
1339        unsafe { ffi::whiteout_m2_M2WaterfallData_set_flags(self.raw.as_ptr(), value) }
1340    }
1341
1342    pub fn unknown_0(&self) -> u16 {
1343        // SAFETY: plain scalar read through a live handle.
1344        unsafe { ffi::whiteout_m2_M2WaterfallData_get_unknown0(self.raw.as_ptr()) }
1345    }
1346
1347    pub fn set_unknown_0(&mut self, value: u16) {
1348        // SAFETY: plain scalar write through a live handle.
1349        unsafe { ffi::whiteout_m2_M2WaterfallData_set_unknown0(self.raw.as_ptr(), value) }
1350    }
1351
1352    pub fn value_3w(&self) -> f32 {
1353        // SAFETY: plain scalar read through a live handle.
1354        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value3_w(self.raw.as_ptr()) }
1355    }
1356
1357    pub fn set_value_3w(&mut self, value: f32) {
1358        // SAFETY: plain scalar write through a live handle.
1359        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value3_w(self.raw.as_ptr(), value) }
1360    }
1361
1362    pub fn value_3z(&self) -> f32 {
1363        // SAFETY: plain scalar read through a live handle.
1364        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value3_z(self.raw.as_ptr()) }
1365    }
1366
1367    pub fn set_value_3z(&mut self, value: f32) {
1368        // SAFETY: plain scalar write through a live handle.
1369        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value3_z(self.raw.as_ptr(), value) }
1370    }
1371
1372    pub fn value_4y(&self) -> f32 {
1373        // SAFETY: plain scalar read through a live handle.
1374        unsafe { ffi::whiteout_m2_M2WaterfallData_get_value4_y(self.raw.as_ptr()) }
1375    }
1376
1377    pub fn set_value_4y(&mut self, value: f32) {
1378        // SAFETY: plain scalar write through a live handle.
1379        unsafe { ffi::whiteout_m2_M2WaterfallData_set_value4_y(self.raw.as_ptr(), value) }
1380    }
1381
1382    pub fn unknown_1(&self) -> f32 {
1383        // SAFETY: plain scalar read through a live handle.
1384        unsafe { ffi::whiteout_m2_M2WaterfallData_get_unknown1(self.raw.as_ptr()) }
1385    }
1386
1387    pub fn set_unknown_1(&mut self, value: f32) {
1388        // SAFETY: plain scalar write through a live handle.
1389        unsafe { ffi::whiteout_m2_M2WaterfallData_set_unknown1(self.raw.as_ptr(), value) }
1390    }
1391
1392    pub fn unknown_2(&self) -> f32 {
1393        // SAFETY: plain scalar read through a live handle.
1394        unsafe { ffi::whiteout_m2_M2WaterfallData_get_unknown2(self.raw.as_ptr()) }
1395    }
1396
1397    pub fn set_unknown_2(&mut self, value: f32) {
1398        // SAFETY: plain scalar write through a live handle.
1399        unsafe { ffi::whiteout_m2_M2WaterfallData_set_unknown2(self.raw.as_ptr(), value) }
1400    }
1401
1402    pub fn unknown_3(&self) -> f32 {
1403        // SAFETY: plain scalar read through a live handle.
1404        unsafe { ffi::whiteout_m2_M2WaterfallData_get_unknown3(self.raw.as_ptr()) }
1405    }
1406
1407    pub fn set_unknown_3(&mut self, value: f32) {
1408        // SAFETY: plain scalar write through a live handle.
1409        unsafe { ffi::whiteout_m2_M2WaterfallData_set_unknown3(self.raw.as_ptr(), value) }
1410    }
1411
1412    pub fn unknown_4(&self) -> f32 {
1413        // SAFETY: plain scalar read through a live handle.
1414        unsafe { ffi::whiteout_m2_M2WaterfallData_get_unknown4(self.raw.as_ptr()) }
1415    }
1416
1417    pub fn set_unknown_4(&mut self, value: f32) {
1418        // SAFETY: plain scalar write through a live handle.
1419        unsafe { ffi::whiteout_m2_M2WaterfallData_set_unknown4(self.raw.as_ptr(), value) }
1420    }
1421}
1422
1423impl Default for WaterfallData {
1424    fn default() -> Self {
1425        Self::new()
1426    }
1427}
1428
1429pub struct ParticleGeosetData {
1430    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ParticleGeosetData>,
1431}
1432
1433impl Drop for ParticleGeosetData {
1434    fn drop(&mut self) {
1435        // SAFETY: `raw` came from a native constructor and Drop runs once.
1436        unsafe { ffi::whiteout_m2_M2ParticleGeosetData_delete(self.raw.as_ptr()) }
1437    }
1438}
1439
1440impl ParticleGeosetData {
1441    /// # Safety
1442    /// `raw` must be a live handle this value takes ownership of.
1443    #[allow(dead_code)] // used by whichever methods return this type
1444    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ParticleGeosetData) -> Option<Self> {
1445        core::ptr::NonNull::new(raw).map(|raw| ParticleGeosetData { raw })
1446    }
1447}
1448
1449// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1450// is deliberately NOT implemented — the C++ types make no documented
1451// guarantee about concurrent use, and claiming one we haven't verified
1452// would be unsound. See `@bind thread_safe` in the plan.
1453unsafe impl Send for ParticleGeosetData {}
1454
1455impl core::fmt::Debug for ParticleGeosetData {
1456    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1457        f.debug_struct("ParticleGeosetData").finish_non_exhaustive()
1458    }
1459}
1460
1461impl ParticleGeosetData {
1462    /// # Panics
1463    /// Panics if the native allocation fails.
1464    pub fn new() -> Self {
1465        // SAFETY: the native constructor returns a live handle; a null here
1466        // means the library is unusable.
1467        unsafe {
1468            let raw = ffi::whiteout_m2_M2ParticleGeosetData_new();
1469            Self::from_raw(raw).expect("native ParticleGeosetData allocation failed")
1470        }
1471    }
1472
1473    pub fn geoset(&self) -> u16 {
1474        // SAFETY: plain scalar read through a live handle.
1475        unsafe { ffi::whiteout_m2_M2ParticleGeosetData_get_geoset(self.raw.as_ptr()) }
1476    }
1477
1478    pub fn set_geoset(&mut self, value: u16) {
1479        // SAFETY: plain scalar write through a live handle.
1480        unsafe { ffi::whiteout_m2_M2ParticleGeosetData_set_geoset(self.raw.as_ptr(), value) }
1481    }
1482}
1483
1484impl Default for ParticleGeosetData {
1485    fn default() -> Self {
1486        Self::new()
1487    }
1488}
1489
1490pub struct EdgeFadeData {
1491    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2EdgeFadeData>,
1492}
1493
1494impl Drop for EdgeFadeData {
1495    fn drop(&mut self) {
1496        // SAFETY: `raw` came from a native constructor and Drop runs once.
1497        unsafe { ffi::whiteout_m2_M2EdgeFadeData_delete(self.raw.as_ptr()) }
1498    }
1499}
1500
1501impl EdgeFadeData {
1502    /// # Safety
1503    /// `raw` must be a live handle this value takes ownership of.
1504    #[allow(dead_code)] // used by whichever methods return this type
1505    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2EdgeFadeData) -> Option<Self> {
1506        core::ptr::NonNull::new(raw).map(|raw| EdgeFadeData { raw })
1507    }
1508}
1509
1510// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1511// is deliberately NOT implemented — the C++ types make no documented
1512// guarantee about concurrent use, and claiming one we haven't verified
1513// would be unsound. See `@bind thread_safe` in the plan.
1514unsafe impl Send for EdgeFadeData {}
1515
1516impl core::fmt::Debug for EdgeFadeData {
1517    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1518        f.debug_struct("EdgeFadeData").finish_non_exhaustive()
1519    }
1520}
1521
1522impl EdgeFadeData {
1523    /// # Panics
1524    /// Panics if the native allocation fails.
1525    pub fn new() -> Self {
1526        // SAFETY: the native constructor returns a live handle; a null here
1527        // means the library is unusable.
1528        unsafe {
1529            let raw = ffi::whiteout_m2_M2EdgeFadeData_new();
1530            Self::from_raw(raw).expect("native EdgeFadeData allocation failed")
1531        }
1532    }
1533
1534    /// Number of elements — a fixed-size C++ array.
1535    pub const fn value_0_len() -> usize {
1536        2
1537    }
1538
1539    /// # Panics
1540    /// If `index >= 2`, matching Rust slice indexing.
1541    pub fn value_0(&self, index: usize) -> f32 {
1542        assert!(index < 2, "value_0 index {index} out of range (len 2)");
1543        // SAFETY: index checked above; plain scalar read.
1544        unsafe { ffi::whiteout_m2_M2EdgeFadeData_get_value0_at(self.raw.as_ptr(), index) }
1545    }
1546
1547    /// # Panics
1548    /// If `index >= 2`.
1549    pub fn set_value_0(&mut self, index: usize, value: f32) {
1550        assert!(index < 2, "value_0 index {index} out of range (len 2)");
1551        // SAFETY: index checked above.
1552        unsafe { ffi::whiteout_m2_M2EdgeFadeData_set_value0_at(self.raw.as_ptr(), index, value) }
1553    }
1554
1555    pub fn value_8(&self) -> f32 {
1556        // SAFETY: plain scalar read through a live handle.
1557        unsafe { ffi::whiteout_m2_M2EdgeFadeData_get_value8(self.raw.as_ptr()) }
1558    }
1559
1560    pub fn set_value_8(&mut self, value: f32) {
1561        // SAFETY: plain scalar write through a live handle.
1562        unsafe { ffi::whiteout_m2_M2EdgeFadeData_set_value8(self.raw.as_ptr(), value) }
1563    }
1564
1565    /// Number of elements — a fixed-size C++ array.
1566    pub const fn value_c_len() -> usize {
1567        12
1568    }
1569
1570    /// # Panics
1571    /// If `index >= 12`, matching Rust slice indexing.
1572    pub fn value_c(&self, index: usize) -> u8 {
1573        assert!(index < 12, "value_c index {index} out of range (len 12)");
1574        // SAFETY: index checked above; plain scalar read.
1575        unsafe { ffi::whiteout_m2_M2EdgeFadeData_get_valueC_at(self.raw.as_ptr(), index) }
1576    }
1577
1578    /// # Panics
1579    /// If `index >= 12`.
1580    pub fn set_value_c(&mut self, index: usize, value: u8) {
1581        assert!(index < 12, "value_c index {index} out of range (len 12)");
1582        // SAFETY: index checked above.
1583        unsafe { ffi::whiteout_m2_M2EdgeFadeData_set_valueC_at(self.raw.as_ptr(), index, value) }
1584    }
1585}
1586
1587impl Default for EdgeFadeData {
1588    fn default() -> Self {
1589        Self::new()
1590    }
1591}
1592
1593pub struct DistanceFadeData {
1594    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2DistanceFadeData>,
1595}
1596
1597impl Drop for DistanceFadeData {
1598    fn drop(&mut self) {
1599        // SAFETY: `raw` came from a native constructor and Drop runs once.
1600        unsafe { ffi::whiteout_m2_M2DistanceFadeData_delete(self.raw.as_ptr()) }
1601    }
1602}
1603
1604impl DistanceFadeData {
1605    /// # Safety
1606    /// `raw` must be a live handle this value takes ownership of.
1607    #[allow(dead_code)] // used by whichever methods return this type
1608    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2DistanceFadeData) -> Option<Self> {
1609        core::ptr::NonNull::new(raw).map(|raw| DistanceFadeData { raw })
1610    }
1611}
1612
1613// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1614// is deliberately NOT implemented — the C++ types make no documented
1615// guarantee about concurrent use, and claiming one we haven't verified
1616// would be unsound. See `@bind thread_safe` in the plan.
1617unsafe impl Send for DistanceFadeData {}
1618
1619impl core::fmt::Debug for DistanceFadeData {
1620    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1621        f.debug_struct("DistanceFadeData").finish_non_exhaustive()
1622    }
1623}
1624
1625impl DistanceFadeData {
1626    /// # Panics
1627    /// Panics if the native allocation fails.
1628    pub fn new() -> Self {
1629        // SAFETY: the native constructor returns a live handle; a null here
1630        // means the library is unusable.
1631        unsafe {
1632            let raw = ffi::whiteout_m2_M2DistanceFadeData_new();
1633            Self::from_raw(raw).expect("native DistanceFadeData allocation failed")
1634        }
1635    }
1636
1637    pub fn squared_far_dist(&self) -> f32 {
1638        // SAFETY: plain scalar read through a live handle.
1639        unsafe { ffi::whiteout_m2_M2DistanceFadeData_get_squaredFarDist(self.raw.as_ptr()) }
1640    }
1641
1642    pub fn set_squared_far_dist(&mut self, value: f32) {
1643        // SAFETY: plain scalar write through a live handle.
1644        unsafe { ffi::whiteout_m2_M2DistanceFadeData_set_squaredFarDist(self.raw.as_ptr(), value) }
1645    }
1646
1647    pub fn squared_near_dist(&self) -> f32 {
1648        // SAFETY: plain scalar read through a live handle.
1649        unsafe { ffi::whiteout_m2_M2DistanceFadeData_get_squaredNearDist(self.raw.as_ptr()) }
1650    }
1651
1652    pub fn set_squared_near_dist(&mut self, value: f32) {
1653        // SAFETY: plain scalar write through a live handle.
1654        unsafe { ffi::whiteout_m2_M2DistanceFadeData_set_squaredNearDist(self.raw.as_ptr(), value) }
1655    }
1656
1657    /// Number of elements — a fixed-size C++ array.
1658    pub const fn reserved_len() -> usize {
1659        2
1660    }
1661
1662    /// # Panics
1663    /// If `index >= 2`, matching Rust slice indexing.
1664    pub fn reserved(&self, index: usize) -> u32 {
1665        assert!(index < 2, "reserved index {index} out of range (len 2)");
1666        // SAFETY: index checked above; plain scalar read.
1667        unsafe { ffi::whiteout_m2_M2DistanceFadeData_get_reserved_at(self.raw.as_ptr(), index) }
1668    }
1669
1670    /// # Panics
1671    /// If `index >= 2`.
1672    pub fn set_reserved(&mut self, index: usize, value: u32) {
1673        assert!(index < 2, "reserved index {index} out of range (len 2)");
1674        // SAFETY: index checked above.
1675        unsafe {
1676            ffi::whiteout_m2_M2DistanceFadeData_set_reserved_at(self.raw.as_ptr(), index, value)
1677        }
1678    }
1679}
1680
1681impl Default for DistanceFadeData {
1682    fn default() -> Self {
1683        Self::new()
1684    }
1685}
1686
1687pub struct DetailedLightData {
1688    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2DetailedLightData>,
1689}
1690
1691impl Drop for DetailedLightData {
1692    fn drop(&mut self) {
1693        // SAFETY: `raw` came from a native constructor and Drop runs once.
1694        unsafe { ffi::whiteout_m2_M2DetailedLightData_delete(self.raw.as_ptr()) }
1695    }
1696}
1697
1698impl DetailedLightData {
1699    /// # Safety
1700    /// `raw` must be a live handle this value takes ownership of.
1701    #[allow(dead_code)] // used by whichever methods return this type
1702    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2DetailedLightData) -> Option<Self> {
1703        core::ptr::NonNull::new(raw).map(|raw| DetailedLightData { raw })
1704    }
1705}
1706
1707// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1708// is deliberately NOT implemented — the C++ types make no documented
1709// guarantee about concurrent use, and claiming one we haven't verified
1710// would be unsound. See `@bind thread_safe` in the plan.
1711unsafe impl Send for DetailedLightData {}
1712
1713impl core::fmt::Debug for DetailedLightData {
1714    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1715        f.debug_struct("DetailedLightData").finish_non_exhaustive()
1716    }
1717}
1718
1719impl DetailedLightData {
1720    /// # Panics
1721    /// Panics if the native allocation fails.
1722    pub fn new() -> Self {
1723        // SAFETY: the native constructor returns a live handle; a null here
1724        // means the library is unusable.
1725        unsafe {
1726            let raw = ffi::whiteout_m2_M2DetailedLightData_new();
1727            Self::from_raw(raw).expect("native DetailedLightData allocation failed")
1728        }
1729    }
1730
1731    pub fn flags(&self) -> u16 {
1732        // SAFETY: plain scalar read through a live handle.
1733        unsafe { ffi::whiteout_m2_M2DetailedLightData_get_flags(self.raw.as_ptr()) }
1734    }
1735
1736    pub fn set_flags(&mut self, value: u16) {
1737        // SAFETY: plain scalar write through a live handle.
1738        unsafe { ffi::whiteout_m2_M2DetailedLightData_set_flags(self.raw.as_ptr(), value) }
1739    }
1740
1741    pub fn unknown_0(&self) -> u16 {
1742        // SAFETY: plain scalar read through a live handle.
1743        unsafe { ffi::whiteout_m2_M2DetailedLightData_get_unknown0(self.raw.as_ptr()) }
1744    }
1745
1746    pub fn set_unknown_0(&mut self, value: u16) {
1747        // SAFETY: plain scalar write through a live handle.
1748        unsafe { ffi::whiteout_m2_M2DetailedLightData_set_unknown0(self.raw.as_ptr(), value) }
1749    }
1750
1751    pub fn unknown_1(&self) -> u32 {
1752        // SAFETY: plain scalar read through a live handle.
1753        unsafe { ffi::whiteout_m2_M2DetailedLightData_get_unknown1(self.raw.as_ptr()) }
1754    }
1755
1756    pub fn set_unknown_1(&mut self, value: u32) {
1757        // SAFETY: plain scalar write through a live handle.
1758        unsafe { ffi::whiteout_m2_M2DetailedLightData_set_unknown1(self.raw.as_ptr(), value) }
1759    }
1760}
1761
1762impl Default for DetailedLightData {
1763    fn default() -> Self {
1764        Self::new()
1765    }
1766}
1767
1768pub struct DebugOcclusionData {
1769    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2DebugOcclusionData>,
1770}
1771
1772impl Drop for DebugOcclusionData {
1773    fn drop(&mut self) {
1774        // SAFETY: `raw` came from a native constructor and Drop runs once.
1775        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_delete(self.raw.as_ptr()) }
1776    }
1777}
1778
1779impl DebugOcclusionData {
1780    /// # Safety
1781    /// `raw` must be a live handle this value takes ownership of.
1782    #[allow(dead_code)] // used by whichever methods return this type
1783    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2DebugOcclusionData) -> Option<Self> {
1784        core::ptr::NonNull::new(raw).map(|raw| DebugOcclusionData { raw })
1785    }
1786}
1787
1788// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1789// is deliberately NOT implemented — the C++ types make no documented
1790// guarantee about concurrent use, and claiming one we haven't verified
1791// would be unsound. See `@bind thread_safe` in the plan.
1792unsafe impl Send for DebugOcclusionData {}
1793
1794impl core::fmt::Debug for DebugOcclusionData {
1795    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1796        f.debug_struct("DebugOcclusionData").finish_non_exhaustive()
1797    }
1798}
1799
1800impl DebugOcclusionData {
1801    /// # Panics
1802    /// Panics if the native allocation fails.
1803    pub fn new() -> Self {
1804        // SAFETY: the native constructor returns a live handle; a null here
1805        // means the library is unusable.
1806        unsafe {
1807            let raw = ffi::whiteout_m2_M2DebugOcclusionData_new();
1808            Self::from_raw(raw).expect("native DebugOcclusionData allocation failed")
1809        }
1810    }
1811
1812    pub fn unknown_1_1(&self) -> f32 {
1813        // SAFETY: plain scalar read through a live handle.
1814        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_get_unknown1_1(self.raw.as_ptr()) }
1815    }
1816
1817    pub fn set_unknown_1_1(&mut self, value: f32) {
1818        // SAFETY: plain scalar write through a live handle.
1819        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_set_unknown1_1(self.raw.as_ptr(), value) }
1820    }
1821
1822    pub fn unknown_1_2(&self) -> f32 {
1823        // SAFETY: plain scalar read through a live handle.
1824        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_get_unknown1_2(self.raw.as_ptr()) }
1825    }
1826
1827    pub fn set_unknown_1_2(&mut self, value: f32) {
1828        // SAFETY: plain scalar write through a live handle.
1829        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_set_unknown1_2(self.raw.as_ptr(), value) }
1830    }
1831
1832    pub fn unknown_1_3(&self) -> u32 {
1833        // SAFETY: plain scalar read through a live handle.
1834        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_get_unknown1_3(self.raw.as_ptr()) }
1835    }
1836
1837    pub fn set_unknown_1_3(&mut self, value: u32) {
1838        // SAFETY: plain scalar write through a live handle.
1839        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_set_unknown1_3(self.raw.as_ptr(), value) }
1840    }
1841
1842    pub fn unknown_1_4(&self) -> u32 {
1843        // SAFETY: plain scalar read through a live handle.
1844        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_get_unknown1_4(self.raw.as_ptr()) }
1845    }
1846
1847    pub fn set_unknown_1_4(&mut self, value: u32) {
1848        // SAFETY: plain scalar write through a live handle.
1849        unsafe { ffi::whiteout_m2_M2DebugOcclusionData_set_unknown1_4(self.raw.as_ptr(), value) }
1850    }
1851}
1852
1853impl Default for DebugOcclusionData {
1854    fn default() -> Self {
1855        Self::new()
1856    }
1857}
1858
1859pub struct TexturedLightData {
1860    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2TexturedLightData>,
1861}
1862
1863impl Drop for TexturedLightData {
1864    fn drop(&mut self) {
1865        // SAFETY: `raw` came from a native constructor and Drop runs once.
1866        unsafe { ffi::whiteout_m2_M2TexturedLightData_delete(self.raw.as_ptr()) }
1867    }
1868}
1869
1870impl TexturedLightData {
1871    /// # Safety
1872    /// `raw` must be a live handle this value takes ownership of.
1873    #[allow(dead_code)] // used by whichever methods return this type
1874    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2TexturedLightData) -> Option<Self> {
1875        core::ptr::NonNull::new(raw).map(|raw| TexturedLightData { raw })
1876    }
1877}
1878
1879// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1880// is deliberately NOT implemented — the C++ types make no documented
1881// guarantee about concurrent use, and claiming one we haven't verified
1882// would be unsound. See `@bind thread_safe` in the plan.
1883unsafe impl Send for TexturedLightData {}
1884
1885impl core::fmt::Debug for TexturedLightData {
1886    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1887        f.debug_struct("TexturedLightData").finish_non_exhaustive()
1888    }
1889}
1890
1891impl TexturedLightData {
1892    /// # Panics
1893    /// Panics if the native allocation fails.
1894    pub fn new() -> Self {
1895        // SAFETY: the native constructor returns a live handle; a null here
1896        // means the library is unusable.
1897        unsafe {
1898            let raw = ffi::whiteout_m2_M2TexturedLightData_new();
1899            Self::from_raw(raw).expect("native TexturedLightData allocation failed")
1900        }
1901    }
1902
1903    pub fn unknown_0(&self) -> f32 {
1904        // SAFETY: plain scalar read through a live handle.
1905        unsafe { ffi::whiteout_m2_M2TexturedLightData_get_unknown0(self.raw.as_ptr()) }
1906    }
1907
1908    pub fn set_unknown_0(&mut self, value: f32) {
1909        // SAFETY: plain scalar write through a live handle.
1910        unsafe { ffi::whiteout_m2_M2TexturedLightData_set_unknown0(self.raw.as_ptr(), value) }
1911    }
1912
1913    pub fn unknown_1(&self) -> f32 {
1914        // SAFETY: plain scalar read through a live handle.
1915        unsafe { ffi::whiteout_m2_M2TexturedLightData_get_unknown1(self.raw.as_ptr()) }
1916    }
1917
1918    pub fn set_unknown_1(&mut self, value: f32) {
1919        // SAFETY: plain scalar write through a live handle.
1920        unsafe { ffi::whiteout_m2_M2TexturedLightData_set_unknown1(self.raw.as_ptr(), value) }
1921    }
1922
1923    pub fn texture_lookup(&self) -> i32 {
1924        // SAFETY: plain scalar read through a live handle.
1925        unsafe { ffi::whiteout_m2_M2TexturedLightData_get_textureLookup(self.raw.as_ptr()) }
1926    }
1927
1928    pub fn set_texture_lookup(&mut self, value: i32) {
1929        // SAFETY: plain scalar write through a live handle.
1930        unsafe { ffi::whiteout_m2_M2TexturedLightData_set_textureLookup(self.raw.as_ptr(), value) }
1931    }
1932
1933    pub fn unknown_2(&self) -> i32 {
1934        // SAFETY: plain scalar read through a live handle.
1935        unsafe { ffi::whiteout_m2_M2TexturedLightData_get_unknown2(self.raw.as_ptr()) }
1936    }
1937
1938    pub fn set_unknown_2(&mut self, value: i32) {
1939        // SAFETY: plain scalar write through a live handle.
1940        unsafe { ffi::whiteout_m2_M2TexturedLightData_set_unknown2(self.raw.as_ptr(), value) }
1941    }
1942}
1943
1944impl Default for TexturedLightData {
1945    fn default() -> Self {
1946        Self::new()
1947    }
1948}
1949
1950/// One DPIV (pivot displacement) record, 32 bytes.
1951///
1952/// The client keeps the payload pointer and a record count of `chunkSize / 32`, so a chunk holds N of these — the corpus has both 1- and 2-record chunks.
1953pub struct PivotDisplacementData {
1954    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PivotDisplacementData>,
1955}
1956
1957impl Drop for PivotDisplacementData {
1958    fn drop(&mut self) {
1959        // SAFETY: `raw` came from a native constructor and Drop runs once.
1960        unsafe { ffi::whiteout_m2_M2PivotDisplacementData_delete(self.raw.as_ptr()) }
1961    }
1962}
1963
1964impl PivotDisplacementData {
1965    /// # Safety
1966    /// `raw` must be a live handle this value takes ownership of.
1967    #[allow(dead_code)] // used by whichever methods return this type
1968    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PivotDisplacementData) -> Option<Self> {
1969        core::ptr::NonNull::new(raw).map(|raw| PivotDisplacementData { raw })
1970    }
1971}
1972
1973// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
1974// is deliberately NOT implemented — the C++ types make no documented
1975// guarantee about concurrent use, and claiming one we haven't verified
1976// would be unsound. See `@bind thread_safe` in the plan.
1977unsafe impl Send for PivotDisplacementData {}
1978
1979impl core::fmt::Debug for PivotDisplacementData {
1980    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1981        f.debug_struct("PivotDisplacementData")
1982            .finish_non_exhaustive()
1983    }
1984}
1985
1986impl PivotDisplacementData {
1987    /// # Panics
1988    /// Panics if the native allocation fails.
1989    pub fn new() -> Self {
1990        // SAFETY: the native constructor returns a live handle; a null here
1991        // means the library is unusable.
1992        unsafe {
1993            let raw = ffi::whiteout_m2_M2PivotDisplacementData_new();
1994            Self::from_raw(raw).expect("native PivotDisplacementData allocation failed")
1995        }
1996    }
1997
1998    /// small displacement; Z varies most
1999    pub fn offset(&self) -> crate::math::Vector3f {
2000        // SAFETY: the getter returns an interior pointer to a
2001        // layout-identical POD; we copy it out immediately.
2002        unsafe {
2003            *(ffi::whiteout_m2_M2PivotDisplacementData_get_offset(self.raw.as_ptr())
2004                as *const crate::math::Vector3f)
2005        }
2006    }
2007
2008    pub fn set_offset(&mut self, value: crate::math::Vector3f) {
2009        // SAFETY: as above, in the other direction.
2010        unsafe {
2011            ffi::whiteout_m2_M2PivotDisplacementData_set_offset(
2012                self.raw.as_ptr(),
2013                &value as *const crate::math::Vector3f as *const _,
2014            )
2015        }
2016    }
2017
2018    /// 0 or 1
2019    pub fn flags(&self) -> u32 {
2020        // SAFETY: plain scalar read through a live handle.
2021        unsafe { ffi::whiteout_m2_M2PivotDisplacementData_get_flags(self.raw.as_ptr()) }
2022    }
2023
2024    pub fn set_flags(&mut self, value: u32) {
2025        // SAFETY: plain scalar write through a live handle.
2026        unsafe { ffi::whiteout_m2_M2PivotDisplacementData_set_flags(self.raw.as_ptr(), value) }
2027    }
2028
2029    /// always 0
2030    /// Number of elements — a fixed-size C++ array.
2031    pub const fn reserved_len() -> usize {
2032        4
2033    }
2034
2035    /// # Panics
2036    /// If `index >= 4`, matching Rust slice indexing.
2037    pub fn reserved(&self, index: usize) -> u32 {
2038        assert!(index < 4, "reserved index {index} out of range (len 4)");
2039        // SAFETY: index checked above; plain scalar read.
2040        unsafe {
2041            ffi::whiteout_m2_M2PivotDisplacementData_get_reserved_at(self.raw.as_ptr(), index)
2042        }
2043    }
2044
2045    /// # Panics
2046    /// If `index >= 4`.
2047    pub fn set_reserved(&mut self, index: usize, value: u32) {
2048        assert!(index < 4, "reserved index {index} out of range (len 4)");
2049        // SAFETY: index checked above.
2050        unsafe {
2051            ffi::whiteout_m2_M2PivotDisplacementData_set_reserved_at(
2052                self.raw.as_ptr(),
2053                index,
2054                value,
2055            )
2056        }
2057    }
2058}
2059
2060impl Default for PivotDisplacementData {
2061    fn default() -> Self {
2062        Self::new()
2063    }
2064}
2065
2066pub struct PhysicsCollision {
2067    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsCollision>,
2068}
2069
2070impl Drop for PhysicsCollision {
2071    fn drop(&mut self) {
2072        // SAFETY: `raw` came from a native constructor and Drop runs once.
2073        unsafe { ffi::whiteout_m2_M2PhysicsCollision_delete(self.raw.as_ptr()) }
2074    }
2075}
2076
2077impl PhysicsCollision {
2078    /// # Safety
2079    /// `raw` must be a live handle this value takes ownership of.
2080    #[allow(dead_code)] // used by whichever methods return this type
2081    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsCollision) -> Option<Self> {
2082        core::ptr::NonNull::new(raw).map(|raw| PhysicsCollision { raw })
2083    }
2084}
2085
2086// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2087// is deliberately NOT implemented — the C++ types make no documented
2088// guarantee about concurrent use, and claiming one we haven't verified
2089// would be unsound. See `@bind thread_safe` in the plan.
2090unsafe impl Send for PhysicsCollision {}
2091
2092impl core::fmt::Debug for PhysicsCollision {
2093    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2094        f.debug_struct("PhysicsCollision").finish_non_exhaustive()
2095    }
2096}
2097
2098impl PhysicsCollision {
2099    /// # Panics
2100    /// Panics if the native allocation fails.
2101    pub fn new() -> Self {
2102        // SAFETY: the native constructor returns a live handle; a null here
2103        // means the library is unusable.
2104        unsafe {
2105            let raw = ffi::whiteout_m2_M2PhysicsCollision_new();
2106            Self::from_raw(raw).expect("native PhysicsCollision allocation failed")
2107        }
2108    }
2109
2110    /// Zero-copy view of the underlying `std::vector`.
2111    pub fn vertex_positions(&self) -> &[crate::math::Vector3f] {
2112        // SAFETY: `_data`/`_count` describe one contiguous C++
2113        // allocation, borrowed for as long as `self` is.
2114        unsafe {
2115            let n =
2116                ffi::whiteout_m2_M2PhysicsCollision_get_vertexPositions_count(self.raw.as_ptr());
2117            let p = ffi::whiteout_m2_M2PhysicsCollision_get_vertexPositions_data(self.raw.as_ptr())
2118                as *const crate::math::Vector3f;
2119            if p.is_null() || n == 0 {
2120                &[]
2121            } else {
2122                core::slice::from_raw_parts(p, n)
2123            }
2124        }
2125    }
2126
2127    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2128    pub fn vertex_positions_mut(&mut self) -> &mut [crate::math::Vector3f] {
2129        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2130        unsafe {
2131            let n =
2132                ffi::whiteout_m2_M2PhysicsCollision_get_vertexPositions_count(self.raw.as_ptr());
2133            let p = ffi::whiteout_m2_M2PhysicsCollision_get_vertexPositions_data(self.raw.as_ptr())
2134                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
2135            if p.is_null() || n == 0 {
2136                &mut []
2137            } else {
2138                core::slice::from_raw_parts_mut(p, n)
2139            }
2140        }
2141    }
2142
2143    pub fn set_vertex_positions(&mut self, values: &[crate::math::Vector3f]) {
2144        // SAFETY: the native side copies `values` before returning.
2145        unsafe {
2146            ffi::whiteout_m2_M2PhysicsCollision_assign_vertexPositions(
2147                self.raw.as_ptr(),
2148                values.as_ptr() as *const _,
2149                values.len(),
2150            )
2151        }
2152    }
2153
2154    pub fn resize_vertex_positions(&mut self, count: usize) {
2155        // SAFETY: reallocation is safe here precisely because
2156        // `&mut self` means no slice borrow is outstanding.
2157        unsafe {
2158            ffi::whiteout_m2_M2PhysicsCollision_resize_vertexPositions(self.raw.as_ptr(), count)
2159        }
2160    }
2161
2162    /// Zero-copy view of the underlying `std::vector`.
2163    pub fn face_normals(&self) -> &[crate::math::Vector3f] {
2164        // SAFETY: `_data`/`_count` describe one contiguous C++
2165        // allocation, borrowed for as long as `self` is.
2166        unsafe {
2167            let n = ffi::whiteout_m2_M2PhysicsCollision_get_faceNormals_count(self.raw.as_ptr());
2168            let p = ffi::whiteout_m2_M2PhysicsCollision_get_faceNormals_data(self.raw.as_ptr())
2169                as *const crate::math::Vector3f;
2170            if p.is_null() || n == 0 {
2171                &[]
2172            } else {
2173                core::slice::from_raw_parts(p, n)
2174            }
2175        }
2176    }
2177
2178    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2179    pub fn face_normals_mut(&mut self) -> &mut [crate::math::Vector3f] {
2180        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2181        unsafe {
2182            let n = ffi::whiteout_m2_M2PhysicsCollision_get_faceNormals_count(self.raw.as_ptr());
2183            let p = ffi::whiteout_m2_M2PhysicsCollision_get_faceNormals_data(self.raw.as_ptr())
2184                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
2185            if p.is_null() || n == 0 {
2186                &mut []
2187            } else {
2188                core::slice::from_raw_parts_mut(p, n)
2189            }
2190        }
2191    }
2192
2193    pub fn set_face_normals(&mut self, values: &[crate::math::Vector3f]) {
2194        // SAFETY: the native side copies `values` before returning.
2195        unsafe {
2196            ffi::whiteout_m2_M2PhysicsCollision_assign_faceNormals(
2197                self.raw.as_ptr(),
2198                values.as_ptr() as *const _,
2199                values.len(),
2200            )
2201        }
2202    }
2203
2204    pub fn resize_face_normals(&mut self, count: usize) {
2205        // SAFETY: reallocation is safe here precisely because
2206        // `&mut self` means no slice borrow is outstanding.
2207        unsafe { ffi::whiteout_m2_M2PhysicsCollision_resize_faceNormals(self.raw.as_ptr(), count) }
2208    }
2209
2210    /// Zero-copy view of the underlying `std::vector`.
2211    pub fn indices(&self) -> &[i16] {
2212        // SAFETY: `_data`/`_count` describe one contiguous C++
2213        // allocation, borrowed for as long as `self` is.
2214        unsafe {
2215            let n = ffi::whiteout_m2_M2PhysicsCollision_get_indices_count(self.raw.as_ptr());
2216            let p = ffi::whiteout_m2_M2PhysicsCollision_get_indices_data(self.raw.as_ptr());
2217            if p.is_null() || n == 0 {
2218                &[]
2219            } else {
2220                core::slice::from_raw_parts(p, n)
2221            }
2222        }
2223    }
2224
2225    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2226    pub fn indices_mut(&mut self) -> &mut [i16] {
2227        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2228        unsafe {
2229            let n = ffi::whiteout_m2_M2PhysicsCollision_get_indices_count(self.raw.as_ptr());
2230            let p =
2231                ffi::whiteout_m2_M2PhysicsCollision_get_indices_data(self.raw.as_ptr()) as *mut i16;
2232            if p.is_null() || n == 0 {
2233                &mut []
2234            } else {
2235                core::slice::from_raw_parts_mut(p, n)
2236            }
2237        }
2238    }
2239
2240    pub fn set_indices(&mut self, values: &[i16]) {
2241        // SAFETY: the native side copies `values` before returning.
2242        unsafe {
2243            ffi::whiteout_m2_M2PhysicsCollision_assign_indices(
2244                self.raw.as_ptr(),
2245                values.as_ptr() as *const _,
2246                values.len(),
2247            )
2248        }
2249    }
2250
2251    pub fn resize_indices(&mut self, count: usize) {
2252        // SAFETY: reallocation is safe here precisely because
2253        // `&mut self` means no slice borrow is outstanding.
2254        unsafe { ffi::whiteout_m2_M2PhysicsCollision_resize_indices(self.raw.as_ptr(), count) }
2255    }
2256
2257    /// Zero-copy view of the underlying `std::vector`.
2258    pub fn flags(&self) -> &[i16] {
2259        // SAFETY: `_data`/`_count` describe one contiguous C++
2260        // allocation, borrowed for as long as `self` is.
2261        unsafe {
2262            let n = ffi::whiteout_m2_M2PhysicsCollision_get_flags_count(self.raw.as_ptr());
2263            let p = ffi::whiteout_m2_M2PhysicsCollision_get_flags_data(self.raw.as_ptr());
2264            if p.is_null() || n == 0 {
2265                &[]
2266            } else {
2267                core::slice::from_raw_parts(p, n)
2268            }
2269        }
2270    }
2271
2272    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2273    pub fn flags_mut(&mut self) -> &mut [i16] {
2274        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2275        unsafe {
2276            let n = ffi::whiteout_m2_M2PhysicsCollision_get_flags_count(self.raw.as_ptr());
2277            let p =
2278                ffi::whiteout_m2_M2PhysicsCollision_get_flags_data(self.raw.as_ptr()) as *mut i16;
2279            if p.is_null() || n == 0 {
2280                &mut []
2281            } else {
2282                core::slice::from_raw_parts_mut(p, n)
2283            }
2284        }
2285    }
2286
2287    pub fn set_flags(&mut self, values: &[i16]) {
2288        // SAFETY: the native side copies `values` before returning.
2289        unsafe {
2290            ffi::whiteout_m2_M2PhysicsCollision_assign_flags(
2291                self.raw.as_ptr(),
2292                values.as_ptr() as *const _,
2293                values.len(),
2294            )
2295        }
2296    }
2297
2298    pub fn resize_flags(&mut self, count: usize) {
2299        // SAFETY: reallocation is safe here precisely because
2300        // `&mut self` means no slice borrow is outstanding.
2301        unsafe { ffi::whiteout_m2_M2PhysicsCollision_resize_flags(self.raw.as_ptr(), count) }
2302    }
2303}
2304
2305impl Default for PhysicsCollision {
2306    fn default() -> Self {
2307        Self::new()
2308    }
2309}
2310
2311pub struct SkinSection {
2312    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2SkinSection>,
2313}
2314
2315impl Drop for SkinSection {
2316    fn drop(&mut self) {
2317        // SAFETY: `raw` came from a native constructor and Drop runs once.
2318        unsafe { ffi::whiteout_m2_M2SkinSection_delete(self.raw.as_ptr()) }
2319    }
2320}
2321
2322impl SkinSection {
2323    /// # Safety
2324    /// `raw` must be a live handle this value takes ownership of.
2325    #[allow(dead_code)] // used by whichever methods return this type
2326    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2SkinSection) -> Option<Self> {
2327        core::ptr::NonNull::new(raw).map(|raw| SkinSection { raw })
2328    }
2329}
2330
2331// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2332// is deliberately NOT implemented — the C++ types make no documented
2333// guarantee about concurrent use, and claiming one we haven't verified
2334// would be unsound. See `@bind thread_safe` in the plan.
2335unsafe impl Send for SkinSection {}
2336
2337impl core::fmt::Debug for SkinSection {
2338    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2339        f.debug_struct("SkinSection").finish_non_exhaustive()
2340    }
2341}
2342
2343impl SkinSection {
2344    /// # Panics
2345    /// Panics if the native allocation fails.
2346    pub fn new() -> Self {
2347        // SAFETY: the native constructor returns a live handle; a null here
2348        // means the library is unusable.
2349        unsafe {
2350            let raw = ffi::whiteout_m2_M2SkinSection_new();
2351            Self::from_raw(raw).expect("native SkinSection allocation failed")
2352        }
2353    }
2354
2355    pub fn skin_section_id(&self) -> u16 {
2356        // SAFETY: plain scalar read through a live handle.
2357        unsafe { ffi::whiteout_m2_M2SkinSection_get_skinSectionId(self.raw.as_ptr()) }
2358    }
2359
2360    pub fn set_skin_section_id(&mut self, value: u16) {
2361        // SAFETY: plain scalar write through a live handle.
2362        unsafe { ffi::whiteout_m2_M2SkinSection_set_skinSectionId(self.raw.as_ptr(), value) }
2363    }
2364
2365    pub fn level(&self) -> u16 {
2366        // SAFETY: plain scalar read through a live handle.
2367        unsafe { ffi::whiteout_m2_M2SkinSection_get_level(self.raw.as_ptr()) }
2368    }
2369
2370    pub fn set_level(&mut self, value: u16) {
2371        // SAFETY: plain scalar write through a live handle.
2372        unsafe { ffi::whiteout_m2_M2SkinSection_set_level(self.raw.as_ptr(), value) }
2373    }
2374
2375    pub fn vertex_start(&self) -> u16 {
2376        // SAFETY: plain scalar read through a live handle.
2377        unsafe { ffi::whiteout_m2_M2SkinSection_get_vertexStart(self.raw.as_ptr()) }
2378    }
2379
2380    pub fn set_vertex_start(&mut self, value: u16) {
2381        // SAFETY: plain scalar write through a live handle.
2382        unsafe { ffi::whiteout_m2_M2SkinSection_set_vertexStart(self.raw.as_ptr(), value) }
2383    }
2384
2385    pub fn vertex_count(&self) -> u16 {
2386        // SAFETY: plain scalar read through a live handle.
2387        unsafe { ffi::whiteout_m2_M2SkinSection_get_vertexCount(self.raw.as_ptr()) }
2388    }
2389
2390    pub fn set_vertex_count(&mut self, value: u16) {
2391        // SAFETY: plain scalar write through a live handle.
2392        unsafe { ffi::whiteout_m2_M2SkinSection_set_vertexCount(self.raw.as_ptr(), value) }
2393    }
2394
2395    pub fn index_start(&self) -> u16 {
2396        // SAFETY: plain scalar read through a live handle.
2397        unsafe { ffi::whiteout_m2_M2SkinSection_get_indexStart(self.raw.as_ptr()) }
2398    }
2399
2400    pub fn set_index_start(&mut self, value: u16) {
2401        // SAFETY: plain scalar write through a live handle.
2402        unsafe { ffi::whiteout_m2_M2SkinSection_set_indexStart(self.raw.as_ptr(), value) }
2403    }
2404
2405    pub fn index_count(&self) -> u16 {
2406        // SAFETY: plain scalar read through a live handle.
2407        unsafe { ffi::whiteout_m2_M2SkinSection_get_indexCount(self.raw.as_ptr()) }
2408    }
2409
2410    pub fn set_index_count(&mut self, value: u16) {
2411        // SAFETY: plain scalar write through a live handle.
2412        unsafe { ffi::whiteout_m2_M2SkinSection_set_indexCount(self.raw.as_ptr(), value) }
2413    }
2414
2415    pub fn bone_count(&self) -> u16 {
2416        // SAFETY: plain scalar read through a live handle.
2417        unsafe { ffi::whiteout_m2_M2SkinSection_get_boneCount(self.raw.as_ptr()) }
2418    }
2419
2420    pub fn set_bone_count(&mut self, value: u16) {
2421        // SAFETY: plain scalar write through a live handle.
2422        unsafe { ffi::whiteout_m2_M2SkinSection_set_boneCount(self.raw.as_ptr(), value) }
2423    }
2424
2425    pub fn bone_combo_index(&self) -> u16 {
2426        // SAFETY: plain scalar read through a live handle.
2427        unsafe { ffi::whiteout_m2_M2SkinSection_get_boneComboIndex(self.raw.as_ptr()) }
2428    }
2429
2430    pub fn set_bone_combo_index(&mut self, value: u16) {
2431        // SAFETY: plain scalar write through a live handle.
2432        unsafe { ffi::whiteout_m2_M2SkinSection_set_boneComboIndex(self.raw.as_ptr(), value) }
2433    }
2434
2435    pub fn bone_influences(&self) -> u16 {
2436        // SAFETY: plain scalar read through a live handle.
2437        unsafe { ffi::whiteout_m2_M2SkinSection_get_boneInfluences(self.raw.as_ptr()) }
2438    }
2439
2440    pub fn set_bone_influences(&mut self, value: u16) {
2441        // SAFETY: plain scalar write through a live handle.
2442        unsafe { ffi::whiteout_m2_M2SkinSection_set_boneInfluences(self.raw.as_ptr(), value) }
2443    }
2444
2445    pub fn center_bone_index(&self) -> u16 {
2446        // SAFETY: plain scalar read through a live handle.
2447        unsafe { ffi::whiteout_m2_M2SkinSection_get_centerBoneIndex(self.raw.as_ptr()) }
2448    }
2449
2450    pub fn set_center_bone_index(&mut self, value: u16) {
2451        // SAFETY: plain scalar write through a live handle.
2452        unsafe { ffi::whiteout_m2_M2SkinSection_set_centerBoneIndex(self.raw.as_ptr(), value) }
2453    }
2454
2455    pub fn center_position(&self) -> crate::math::Vector3f {
2456        // SAFETY: the getter returns an interior pointer to a
2457        // layout-identical POD; we copy it out immediately.
2458        unsafe {
2459            *(ffi::whiteout_m2_M2SkinSection_get_centerPosition(self.raw.as_ptr())
2460                as *const crate::math::Vector3f)
2461        }
2462    }
2463
2464    pub fn set_center_position(&mut self, value: crate::math::Vector3f) {
2465        // SAFETY: as above, in the other direction.
2466        unsafe {
2467            ffi::whiteout_m2_M2SkinSection_set_centerPosition(
2468                self.raw.as_ptr(),
2469                &value as *const crate::math::Vector3f as *const _,
2470            )
2471        }
2472    }
2473
2474    pub fn sort_center_position(&self) -> crate::math::Vector3f {
2475        // SAFETY: the getter returns an interior pointer to a
2476        // layout-identical POD; we copy it out immediately.
2477        unsafe {
2478            *(ffi::whiteout_m2_M2SkinSection_get_sortCenterPosition(self.raw.as_ptr())
2479                as *const crate::math::Vector3f)
2480        }
2481    }
2482
2483    pub fn set_sort_center_position(&mut self, value: crate::math::Vector3f) {
2484        // SAFETY: as above, in the other direction.
2485        unsafe {
2486            ffi::whiteout_m2_M2SkinSection_set_sortCenterPosition(
2487                self.raw.as_ptr(),
2488                &value as *const crate::math::Vector3f as *const _,
2489            )
2490        }
2491    }
2492
2493    pub fn sort_radius(&self) -> f32 {
2494        // SAFETY: plain scalar read through a live handle.
2495        unsafe { ffi::whiteout_m2_M2SkinSection_get_sortRadius(self.raw.as_ptr()) }
2496    }
2497
2498    pub fn set_sort_radius(&mut self, value: f32) {
2499        // SAFETY: plain scalar write through a live handle.
2500        unsafe { ffi::whiteout_m2_M2SkinSection_set_sortRadius(self.raw.as_ptr(), value) }
2501    }
2502}
2503
2504impl Default for SkinSection {
2505    fn default() -> Self {
2506        Self::new()
2507    }
2508}
2509
2510pub struct Batch {
2511    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Batch>,
2512}
2513
2514impl Drop for Batch {
2515    fn drop(&mut self) {
2516        // SAFETY: `raw` came from a native constructor and Drop runs once.
2517        unsafe { ffi::whiteout_m2_M2Batch_delete(self.raw.as_ptr()) }
2518    }
2519}
2520
2521impl Batch {
2522    /// # Safety
2523    /// `raw` must be a live handle this value takes ownership of.
2524    #[allow(dead_code)] // used by whichever methods return this type
2525    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Batch) -> Option<Self> {
2526        core::ptr::NonNull::new(raw).map(|raw| Batch { raw })
2527    }
2528}
2529
2530// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2531// is deliberately NOT implemented — the C++ types make no documented
2532// guarantee about concurrent use, and claiming one we haven't verified
2533// would be unsound. See `@bind thread_safe` in the plan.
2534unsafe impl Send for Batch {}
2535
2536impl core::fmt::Debug for Batch {
2537    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2538        f.debug_struct("Batch").finish_non_exhaustive()
2539    }
2540}
2541
2542impl Batch {
2543    /// # Panics
2544    /// Panics if the native allocation fails.
2545    pub fn new() -> Self {
2546        // SAFETY: the native constructor returns a live handle; a null here
2547        // means the library is unusable.
2548        unsafe {
2549            let raw = ffi::whiteout_m2_M2Batch_new();
2550            Self::from_raw(raw).expect("native Batch allocation failed")
2551        }
2552    }
2553
2554    pub fn flags(&self) -> u8 {
2555        // SAFETY: plain scalar read through a live handle.
2556        unsafe { ffi::whiteout_m2_M2Batch_get_flags(self.raw.as_ptr()) }
2557    }
2558
2559    pub fn set_flags(&mut self, value: u8) {
2560        // SAFETY: plain scalar write through a live handle.
2561        unsafe { ffi::whiteout_m2_M2Batch_set_flags(self.raw.as_ptr(), value) }
2562    }
2563
2564    pub fn priority_plane(&self) -> i8 {
2565        // SAFETY: plain scalar read through a live handle.
2566        unsafe { ffi::whiteout_m2_M2Batch_get_priorityPlane(self.raw.as_ptr()) }
2567    }
2568
2569    pub fn set_priority_plane(&mut self, value: i8) {
2570        // SAFETY: plain scalar write through a live handle.
2571        unsafe { ffi::whiteout_m2_M2Batch_set_priorityPlane(self.raw.as_ptr(), value) }
2572    }
2573
2574    pub fn shader_id(&self) -> u16 {
2575        // SAFETY: plain scalar read through a live handle.
2576        unsafe { ffi::whiteout_m2_M2Batch_get_shaderId(self.raw.as_ptr()) }
2577    }
2578
2579    pub fn set_shader_id(&mut self, value: u16) {
2580        // SAFETY: plain scalar write through a live handle.
2581        unsafe { ffi::whiteout_m2_M2Batch_set_shaderId(self.raw.as_ptr(), value) }
2582    }
2583
2584    pub fn skin_section_index(&self) -> u16 {
2585        // SAFETY: plain scalar read through a live handle.
2586        unsafe { ffi::whiteout_m2_M2Batch_get_skinSectionIndex(self.raw.as_ptr()) }
2587    }
2588
2589    pub fn set_skin_section_index(&mut self, value: u16) {
2590        // SAFETY: plain scalar write through a live handle.
2591        unsafe { ffi::whiteout_m2_M2Batch_set_skinSectionIndex(self.raw.as_ptr(), value) }
2592    }
2593
2594    pub fn geoset_index(&self) -> u16 {
2595        // SAFETY: plain scalar read through a live handle.
2596        unsafe { ffi::whiteout_m2_M2Batch_get_geosetIndex(self.raw.as_ptr()) }
2597    }
2598
2599    pub fn set_geoset_index(&mut self, value: u16) {
2600        // SAFETY: plain scalar write through a live handle.
2601        unsafe { ffi::whiteout_m2_M2Batch_set_geosetIndex(self.raw.as_ptr(), value) }
2602    }
2603
2604    pub fn color_index(&self) -> i16 {
2605        // SAFETY: plain scalar read through a live handle.
2606        unsafe { ffi::whiteout_m2_M2Batch_get_colorIndex(self.raw.as_ptr()) }
2607    }
2608
2609    pub fn set_color_index(&mut self, value: i16) {
2610        // SAFETY: plain scalar write through a live handle.
2611        unsafe { ffi::whiteout_m2_M2Batch_set_colorIndex(self.raw.as_ptr(), value) }
2612    }
2613
2614    pub fn material_index(&self) -> u16 {
2615        // SAFETY: plain scalar read through a live handle.
2616        unsafe { ffi::whiteout_m2_M2Batch_get_materialIndex(self.raw.as_ptr()) }
2617    }
2618
2619    pub fn set_material_index(&mut self, value: u16) {
2620        // SAFETY: plain scalar write through a live handle.
2621        unsafe { ffi::whiteout_m2_M2Batch_set_materialIndex(self.raw.as_ptr(), value) }
2622    }
2623
2624    pub fn material_layer(&self) -> u16 {
2625        // SAFETY: plain scalar read through a live handle.
2626        unsafe { ffi::whiteout_m2_M2Batch_get_materialLayer(self.raw.as_ptr()) }
2627    }
2628
2629    pub fn set_material_layer(&mut self, value: u16) {
2630        // SAFETY: plain scalar write through a live handle.
2631        unsafe { ffi::whiteout_m2_M2Batch_set_materialLayer(self.raw.as_ptr(), value) }
2632    }
2633
2634    pub fn texture_count(&self) -> u16 {
2635        // SAFETY: plain scalar read through a live handle.
2636        unsafe { ffi::whiteout_m2_M2Batch_get_textureCount(self.raw.as_ptr()) }
2637    }
2638
2639    pub fn set_texture_count(&mut self, value: u16) {
2640        // SAFETY: plain scalar write through a live handle.
2641        unsafe { ffi::whiteout_m2_M2Batch_set_textureCount(self.raw.as_ptr(), value) }
2642    }
2643
2644    pub fn texture_combo_index(&self) -> u16 {
2645        // SAFETY: plain scalar read through a live handle.
2646        unsafe { ffi::whiteout_m2_M2Batch_get_textureComboIndex(self.raw.as_ptr()) }
2647    }
2648
2649    pub fn set_texture_combo_index(&mut self, value: u16) {
2650        // SAFETY: plain scalar write through a live handle.
2651        unsafe { ffi::whiteout_m2_M2Batch_set_textureComboIndex(self.raw.as_ptr(), value) }
2652    }
2653
2654    pub fn texture_coord_combo_index(&self) -> u16 {
2655        // SAFETY: plain scalar read through a live handle.
2656        unsafe { ffi::whiteout_m2_M2Batch_get_textureCoordComboIndex(self.raw.as_ptr()) }
2657    }
2658
2659    pub fn set_texture_coord_combo_index(&mut self, value: u16) {
2660        // SAFETY: plain scalar write through a live handle.
2661        unsafe { ffi::whiteout_m2_M2Batch_set_textureCoordComboIndex(self.raw.as_ptr(), value) }
2662    }
2663
2664    pub fn texture_weight_combo_index(&self) -> u16 {
2665        // SAFETY: plain scalar read through a live handle.
2666        unsafe { ffi::whiteout_m2_M2Batch_get_textureWeightComboIndex(self.raw.as_ptr()) }
2667    }
2668
2669    pub fn set_texture_weight_combo_index(&mut self, value: u16) {
2670        // SAFETY: plain scalar write through a live handle.
2671        unsafe { ffi::whiteout_m2_M2Batch_set_textureWeightComboIndex(self.raw.as_ptr(), value) }
2672    }
2673
2674    pub fn texture_transform_combo_index(&self) -> u16 {
2675        // SAFETY: plain scalar read through a live handle.
2676        unsafe { ffi::whiteout_m2_M2Batch_get_textureTransformComboIndex(self.raw.as_ptr()) }
2677    }
2678
2679    pub fn set_texture_transform_combo_index(&mut self, value: u16) {
2680        // SAFETY: plain scalar write through a live handle.
2681        unsafe { ffi::whiteout_m2_M2Batch_set_textureTransformComboIndex(self.raw.as_ptr(), value) }
2682    }
2683}
2684
2685impl Default for Batch {
2686    fn default() -> Self {
2687        Self::new()
2688    }
2689}
2690
2691pub struct ShadowBatch {
2692    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ShadowBatch>,
2693}
2694
2695impl Drop for ShadowBatch {
2696    fn drop(&mut self) {
2697        // SAFETY: `raw` came from a native constructor and Drop runs once.
2698        unsafe { ffi::whiteout_m2_M2ShadowBatch_delete(self.raw.as_ptr()) }
2699    }
2700}
2701
2702impl ShadowBatch {
2703    /// # Safety
2704    /// `raw` must be a live handle this value takes ownership of.
2705    #[allow(dead_code)] // used by whichever methods return this type
2706    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ShadowBatch) -> Option<Self> {
2707        core::ptr::NonNull::new(raw).map(|raw| ShadowBatch { raw })
2708    }
2709}
2710
2711// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2712// is deliberately NOT implemented — the C++ types make no documented
2713// guarantee about concurrent use, and claiming one we haven't verified
2714// would be unsound. See `@bind thread_safe` in the plan.
2715unsafe impl Send for ShadowBatch {}
2716
2717impl core::fmt::Debug for ShadowBatch {
2718    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2719        f.debug_struct("ShadowBatch").finish_non_exhaustive()
2720    }
2721}
2722
2723impl ShadowBatch {
2724    /// # Panics
2725    /// Panics if the native allocation fails.
2726    pub fn new() -> Self {
2727        // SAFETY: the native constructor returns a live handle; a null here
2728        // means the library is unusable.
2729        unsafe {
2730            let raw = ffi::whiteout_m2_M2ShadowBatch_new();
2731            Self::from_raw(raw).expect("native ShadowBatch allocation failed")
2732        }
2733    }
2734
2735    pub fn flags(&self) -> u8 {
2736        // SAFETY: plain scalar read through a live handle.
2737        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_flags(self.raw.as_ptr()) }
2738    }
2739
2740    pub fn set_flags(&mut self, value: u8) {
2741        // SAFETY: plain scalar write through a live handle.
2742        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_flags(self.raw.as_ptr(), value) }
2743    }
2744
2745    pub fn flags_2(&self) -> u8 {
2746        // SAFETY: plain scalar read through a live handle.
2747        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_flags2(self.raw.as_ptr()) }
2748    }
2749
2750    pub fn set_flags_2(&mut self, value: u8) {
2751        // SAFETY: plain scalar write through a live handle.
2752        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_flags2(self.raw.as_ptr(), value) }
2753    }
2754
2755    pub fn unknown_0(&self) -> u16 {
2756        // SAFETY: plain scalar read through a live handle.
2757        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_unknown0(self.raw.as_ptr()) }
2758    }
2759
2760    pub fn set_unknown_0(&mut self, value: u16) {
2761        // SAFETY: plain scalar write through a live handle.
2762        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_unknown0(self.raw.as_ptr(), value) }
2763    }
2764
2765    pub fn submesh_id(&self) -> u16 {
2766        // SAFETY: plain scalar read through a live handle.
2767        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_submeshId(self.raw.as_ptr()) }
2768    }
2769
2770    pub fn set_submesh_id(&mut self, value: u16) {
2771        // SAFETY: plain scalar write through a live handle.
2772        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_submeshId(self.raw.as_ptr(), value) }
2773    }
2774
2775    pub fn texture_id(&self) -> u16 {
2776        // SAFETY: plain scalar read through a live handle.
2777        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_textureId(self.raw.as_ptr()) }
2778    }
2779
2780    pub fn set_texture_id(&mut self, value: u16) {
2781        // SAFETY: plain scalar write through a live handle.
2782        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_textureId(self.raw.as_ptr(), value) }
2783    }
2784
2785    pub fn color_id(&self) -> u16 {
2786        // SAFETY: plain scalar read through a live handle.
2787        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_colorId(self.raw.as_ptr()) }
2788    }
2789
2790    pub fn set_color_id(&mut self, value: u16) {
2791        // SAFETY: plain scalar write through a live handle.
2792        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_colorId(self.raw.as_ptr(), value) }
2793    }
2794
2795    pub fn transparency_id(&self) -> u16 {
2796        // SAFETY: plain scalar read through a live handle.
2797        unsafe { ffi::whiteout_m2_M2ShadowBatch_get_transparencyId(self.raw.as_ptr()) }
2798    }
2799
2800    pub fn set_transparency_id(&mut self, value: u16) {
2801        // SAFETY: plain scalar write through a live handle.
2802        unsafe { ffi::whiteout_m2_M2ShadowBatch_set_transparencyId(self.raw.as_ptr(), value) }
2803    }
2804}
2805
2806impl Default for ShadowBatch {
2807    fn default() -> Self {
2808        Self::new()
2809    }
2810}
2811
2812pub struct SkinProfile {
2813    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2SkinProfile>,
2814}
2815
2816impl Drop for SkinProfile {
2817    fn drop(&mut self) {
2818        // SAFETY: `raw` came from a native constructor and Drop runs once.
2819        unsafe { ffi::whiteout_m2_M2SkinProfile_delete(self.raw.as_ptr()) }
2820    }
2821}
2822
2823impl SkinProfile {
2824    /// # Safety
2825    /// `raw` must be a live handle this value takes ownership of.
2826    #[allow(dead_code)] // used by whichever methods return this type
2827    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2SkinProfile) -> Option<Self> {
2828        core::ptr::NonNull::new(raw).map(|raw| SkinProfile { raw })
2829    }
2830}
2831
2832// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
2833// is deliberately NOT implemented — the C++ types make no documented
2834// guarantee about concurrent use, and claiming one we haven't verified
2835// would be unsound. See `@bind thread_safe` in the plan.
2836unsafe impl Send for SkinProfile {}
2837
2838impl core::fmt::Debug for SkinProfile {
2839    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2840        f.debug_struct("SkinProfile").finish_non_exhaustive()
2841    }
2842}
2843
2844impl SkinProfile {
2845    /// # Panics
2846    /// Panics if the native allocation fails.
2847    pub fn new() -> Self {
2848        // SAFETY: the native constructor returns a live handle; a null here
2849        // means the library is unusable.
2850        unsafe {
2851            let raw = ffi::whiteout_m2_M2SkinProfile_new();
2852            Self::from_raw(raw).expect("native SkinProfile allocation failed")
2853        }
2854    }
2855
2856    /// Zero-copy view of the underlying `std::vector`.
2857    pub fn vertices(&self) -> &[u16] {
2858        // SAFETY: `_data`/`_count` describe one contiguous C++
2859        // allocation, borrowed for as long as `self` is.
2860        unsafe {
2861            let n = ffi::whiteout_m2_M2SkinProfile_get_vertices_count(self.raw.as_ptr());
2862            let p = ffi::whiteout_m2_M2SkinProfile_get_vertices_data(self.raw.as_ptr());
2863            if p.is_null() || n == 0 {
2864                &[]
2865            } else {
2866                core::slice::from_raw_parts(p, n)
2867            }
2868        }
2869    }
2870
2871    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2872    pub fn vertices_mut(&mut self) -> &mut [u16] {
2873        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2874        unsafe {
2875            let n = ffi::whiteout_m2_M2SkinProfile_get_vertices_count(self.raw.as_ptr());
2876            let p = ffi::whiteout_m2_M2SkinProfile_get_vertices_data(self.raw.as_ptr()) as *mut u16;
2877            if p.is_null() || n == 0 {
2878                &mut []
2879            } else {
2880                core::slice::from_raw_parts_mut(p, n)
2881            }
2882        }
2883    }
2884
2885    pub fn set_vertices(&mut self, values: &[u16]) {
2886        // SAFETY: the native side copies `values` before returning.
2887        unsafe {
2888            ffi::whiteout_m2_M2SkinProfile_assign_vertices(
2889                self.raw.as_ptr(),
2890                values.as_ptr() as *const _,
2891                values.len(),
2892            )
2893        }
2894    }
2895
2896    pub fn resize_vertices(&mut self, count: usize) {
2897        // SAFETY: reallocation is safe here precisely because
2898        // `&mut self` means no slice borrow is outstanding.
2899        unsafe { ffi::whiteout_m2_M2SkinProfile_resize_vertices(self.raw.as_ptr(), count) }
2900    }
2901
2902    /// Zero-copy view of the underlying `std::vector`.
2903    pub fn indices(&self) -> &[u16] {
2904        // SAFETY: `_data`/`_count` describe one contiguous C++
2905        // allocation, borrowed for as long as `self` is.
2906        unsafe {
2907            let n = ffi::whiteout_m2_M2SkinProfile_get_indices_count(self.raw.as_ptr());
2908            let p = ffi::whiteout_m2_M2SkinProfile_get_indices_data(self.raw.as_ptr());
2909            if p.is_null() || n == 0 {
2910                &[]
2911            } else {
2912                core::slice::from_raw_parts(p, n)
2913            }
2914        }
2915    }
2916
2917    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
2918    pub fn indices_mut(&mut self) -> &mut [u16] {
2919        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
2920        unsafe {
2921            let n = ffi::whiteout_m2_M2SkinProfile_get_indices_count(self.raw.as_ptr());
2922            let p = ffi::whiteout_m2_M2SkinProfile_get_indices_data(self.raw.as_ptr()) as *mut u16;
2923            if p.is_null() || n == 0 {
2924                &mut []
2925            } else {
2926                core::slice::from_raw_parts_mut(p, n)
2927            }
2928        }
2929    }
2930
2931    pub fn set_indices(&mut self, values: &[u16]) {
2932        // SAFETY: the native side copies `values` before returning.
2933        unsafe {
2934            ffi::whiteout_m2_M2SkinProfile_assign_indices(
2935                self.raw.as_ptr(),
2936                values.as_ptr() as *const _,
2937                values.len(),
2938            )
2939        }
2940    }
2941
2942    pub fn resize_indices(&mut self, count: usize) {
2943        // SAFETY: reallocation is safe here precisely because
2944        // `&mut self` means no slice borrow is outstanding.
2945        unsafe { ffi::whiteout_m2_M2SkinProfile_resize_indices(self.raw.as_ptr(), count) }
2946    }
2947
2948    pub fn submeshes_len(&self) -> usize {
2949        // SAFETY: scalar read through a live handle.
2950        unsafe { ffi::whiteout_m2_M2SkinProfile_get_submeshes_count(self.raw.as_ptr()) }
2951    }
2952
2953    /// Borrows element `index` in place. `None` when out of range.
2954    pub fn submeshes(&self, index: usize) -> Option<crate::support::Ref<'_, SkinSection>> {
2955        if index >= self.submeshes_len() {
2956            return None;
2957        }
2958        // SAFETY: index checked above; the pointer is interior to `self`.
2959        unsafe {
2960            Some(crate::support::Ref::new(SkinSection {
2961                raw: core::ptr::NonNull::new_unchecked(
2962                    ffi::whiteout_m2_M2SkinProfile_get_submeshes_at(self.raw.as_ptr(), index),
2963                ),
2964            }))
2965        }
2966    }
2967
2968    pub fn submeshes_mut(
2969        &mut self,
2970        index: usize,
2971    ) -> Option<crate::support::RefMut<'_, SkinSection>> {
2972        if index >= self.submeshes_len() {
2973            return None;
2974        }
2975        // SAFETY: as above; `&mut self` guarantees exclusivity.
2976        unsafe {
2977            Some(crate::support::RefMut::new(SkinSection {
2978                raw: core::ptr::NonNull::new_unchecked(
2979                    ffi::whiteout_m2_M2SkinProfile_get_submeshes_at(self.raw.as_ptr(), index),
2980                ),
2981            }))
2982        }
2983    }
2984
2985    /// Iterate the elements, borrowing each in turn.
2986    pub fn submeshes_iter(
2987        &self,
2988    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SkinSection>> {
2989        (0..self.submeshes_len()).map(move |i| self.submeshes(i).expect("index below len"))
2990    }
2991
2992    pub fn resize_submeshes(&mut self, count: usize) {
2993        // SAFETY: exclusive access, so no borrow is outstanding.
2994        unsafe { ffi::whiteout_m2_M2SkinProfile_resize_submeshes(self.raw.as_ptr(), count) }
2995    }
2996
2997    pub fn batches_len(&self) -> usize {
2998        // SAFETY: scalar read through a live handle.
2999        unsafe { ffi::whiteout_m2_M2SkinProfile_get_batches_count(self.raw.as_ptr()) }
3000    }
3001
3002    /// Borrows element `index` in place. `None` when out of range.
3003    pub fn batches(&self, index: usize) -> Option<crate::support::Ref<'_, Batch>> {
3004        if index >= self.batches_len() {
3005            return None;
3006        }
3007        // SAFETY: index checked above; the pointer is interior to `self`.
3008        unsafe {
3009            Some(crate::support::Ref::new(Batch {
3010                raw: core::ptr::NonNull::new_unchecked(
3011                    ffi::whiteout_m2_M2SkinProfile_get_batches_at(self.raw.as_ptr(), index),
3012                ),
3013            }))
3014        }
3015    }
3016
3017    pub fn batches_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Batch>> {
3018        if index >= self.batches_len() {
3019            return None;
3020        }
3021        // SAFETY: as above; `&mut self` guarantees exclusivity.
3022        unsafe {
3023            Some(crate::support::RefMut::new(Batch {
3024                raw: core::ptr::NonNull::new_unchecked(
3025                    ffi::whiteout_m2_M2SkinProfile_get_batches_at(self.raw.as_ptr(), index),
3026                ),
3027            }))
3028        }
3029    }
3030
3031    /// Iterate the elements, borrowing each in turn.
3032    pub fn batches_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Batch>> {
3033        (0..self.batches_len()).map(move |i| self.batches(i).expect("index below len"))
3034    }
3035
3036    pub fn resize_batches(&mut self, count: usize) {
3037        // SAFETY: exclusive access, so no borrow is outstanding.
3038        unsafe { ffi::whiteout_m2_M2SkinProfile_resize_batches(self.raw.as_ptr(), count) }
3039    }
3040
3041    pub fn lod_vertex_base(&self) -> u32 {
3042        // SAFETY: plain scalar read through a live handle.
3043        unsafe { ffi::whiteout_m2_M2SkinProfile_get_lodVertexBase(self.raw.as_ptr()) }
3044    }
3045
3046    pub fn set_lod_vertex_base(&mut self, value: u32) {
3047        // SAFETY: plain scalar write through a live handle.
3048        unsafe { ffi::whiteout_m2_M2SkinProfile_set_lodVertexBase(self.raw.as_ptr(), value) }
3049    }
3050
3051    pub fn shadow_batches_len(&self) -> usize {
3052        // SAFETY: scalar read through a live handle.
3053        unsafe { ffi::whiteout_m2_M2SkinProfile_get_shadowBatches_count(self.raw.as_ptr()) }
3054    }
3055
3056    /// Borrows element `index` in place. `None` when out of range.
3057    pub fn shadow_batches(&self, index: usize) -> Option<crate::support::Ref<'_, ShadowBatch>> {
3058        if index >= self.shadow_batches_len() {
3059            return None;
3060        }
3061        // SAFETY: index checked above; the pointer is interior to `self`.
3062        unsafe {
3063            Some(crate::support::Ref::new(ShadowBatch {
3064                raw: core::ptr::NonNull::new_unchecked(
3065                    ffi::whiteout_m2_M2SkinProfile_get_shadowBatches_at(self.raw.as_ptr(), index),
3066                ),
3067            }))
3068        }
3069    }
3070
3071    pub fn shadow_batches_mut(
3072        &mut self,
3073        index: usize,
3074    ) -> Option<crate::support::RefMut<'_, ShadowBatch>> {
3075        if index >= self.shadow_batches_len() {
3076            return None;
3077        }
3078        // SAFETY: as above; `&mut self` guarantees exclusivity.
3079        unsafe {
3080            Some(crate::support::RefMut::new(ShadowBatch {
3081                raw: core::ptr::NonNull::new_unchecked(
3082                    ffi::whiteout_m2_M2SkinProfile_get_shadowBatches_at(self.raw.as_ptr(), index),
3083                ),
3084            }))
3085        }
3086    }
3087
3088    /// Iterate the elements, borrowing each in turn.
3089    pub fn shadow_batches_iter(
3090        &self,
3091    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ShadowBatch>> {
3092        (0..self.shadow_batches_len())
3093            .map(move |i| self.shadow_batches(i).expect("index below len"))
3094    }
3095
3096    pub fn resize_shadow_batches(&mut self, count: usize) {
3097        // SAFETY: exclusive access, so no borrow is outstanding.
3098        unsafe { ffi::whiteout_m2_M2SkinProfile_resize_shadowBatches(self.raw.as_ptr(), count) }
3099    }
3100}
3101
3102impl Default for SkinProfile {
3103    fn default() -> Self {
3104        Self::new()
3105    }
3106}
3107
3108pub struct GlobalFlags {
3109    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2GlobalFlags>,
3110}
3111
3112impl Drop for GlobalFlags {
3113    fn drop(&mut self) {
3114        // SAFETY: `raw` came from a native constructor and Drop runs once.
3115        unsafe { ffi::whiteout_m2_M2GlobalFlags_delete(self.raw.as_ptr()) }
3116    }
3117}
3118
3119impl GlobalFlags {
3120    /// # Safety
3121    /// `raw` must be a live handle this value takes ownership of.
3122    #[allow(dead_code)] // used by whichever methods return this type
3123    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2GlobalFlags) -> Option<Self> {
3124        core::ptr::NonNull::new(raw).map(|raw| GlobalFlags { raw })
3125    }
3126}
3127
3128// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3129// is deliberately NOT implemented — the C++ types make no documented
3130// guarantee about concurrent use, and claiming one we haven't verified
3131// would be unsound. See `@bind thread_safe` in the plan.
3132unsafe impl Send for GlobalFlags {}
3133
3134impl core::fmt::Debug for GlobalFlags {
3135    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3136        f.debug_struct("GlobalFlags").finish_non_exhaustive()
3137    }
3138}
3139
3140impl GlobalFlags {
3141    /// # Panics
3142    /// Panics if the native allocation fails.
3143    pub fn new() -> Self {
3144        // SAFETY: the native constructor returns a live handle; a null here
3145        // means the library is unusable.
3146        unsafe {
3147            let raw = ffi::whiteout_m2_M2GlobalFlags_new();
3148            Self::from_raw(raw).expect("native GlobalFlags allocation failed")
3149        }
3150    }
3151
3152    pub fn value(&self) -> GlobalFlag {
3153        // SAFETY: scalar read; a flag set accepts any bits.
3154        GlobalFlag(unsafe { ffi::whiteout_m2_M2GlobalFlags_get_value(self.raw.as_ptr()) })
3155    }
3156
3157    pub fn set_value(&mut self, value: GlobalFlag) {
3158        // SAFETY: scalar write through a live handle.
3159        unsafe { ffi::whiteout_m2_M2GlobalFlags_set_value(self.raw.as_ptr(), value.0) }
3160    }
3161}
3162
3163impl Default for GlobalFlags {
3164    fn default() -> Self {
3165        Self::new()
3166    }
3167}
3168
3169pub struct GlobalSequence {
3170    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2GlobalSequence>,
3171}
3172
3173impl Drop for GlobalSequence {
3174    fn drop(&mut self) {
3175        // SAFETY: `raw` came from a native constructor and Drop runs once.
3176        unsafe { ffi::whiteout_m2_M2GlobalSequence_delete(self.raw.as_ptr()) }
3177    }
3178}
3179
3180impl GlobalSequence {
3181    /// # Safety
3182    /// `raw` must be a live handle this value takes ownership of.
3183    #[allow(dead_code)] // used by whichever methods return this type
3184    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2GlobalSequence) -> Option<Self> {
3185        core::ptr::NonNull::new(raw).map(|raw| GlobalSequence { raw })
3186    }
3187}
3188
3189// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3190// is deliberately NOT implemented — the C++ types make no documented
3191// guarantee about concurrent use, and claiming one we haven't verified
3192// would be unsound. See `@bind thread_safe` in the plan.
3193unsafe impl Send for GlobalSequence {}
3194
3195impl core::fmt::Debug for GlobalSequence {
3196    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3197        f.debug_struct("GlobalSequence").finish_non_exhaustive()
3198    }
3199}
3200
3201impl GlobalSequence {
3202    /// # Panics
3203    /// Panics if the native allocation fails.
3204    pub fn new() -> Self {
3205        // SAFETY: the native constructor returns a live handle; a null here
3206        // means the library is unusable.
3207        unsafe {
3208            let raw = ffi::whiteout_m2_M2GlobalSequence_new();
3209            Self::from_raw(raw).expect("native GlobalSequence allocation failed")
3210        }
3211    }
3212
3213    pub fn timestamp(&self) -> u32 {
3214        // SAFETY: plain scalar read through a live handle.
3215        unsafe { ffi::whiteout_m2_M2GlobalSequence_get_timestamp(self.raw.as_ptr()) }
3216    }
3217
3218    pub fn set_timestamp(&mut self, value: u32) {
3219        // SAFETY: plain scalar write through a live handle.
3220        unsafe { ffi::whiteout_m2_M2GlobalSequence_set_timestamp(self.raw.as_ptr(), value) }
3221    }
3222}
3223
3224impl Default for GlobalSequence {
3225    fn default() -> Self {
3226        Self::new()
3227    }
3228}
3229
3230pub struct Sequence {
3231    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Sequence>,
3232}
3233
3234impl Drop for Sequence {
3235    fn drop(&mut self) {
3236        // SAFETY: `raw` came from a native constructor and Drop runs once.
3237        unsafe { ffi::whiteout_m2_M2Sequence_delete(self.raw.as_ptr()) }
3238    }
3239}
3240
3241impl Sequence {
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_M2Sequence) -> Option<Self> {
3246        core::ptr::NonNull::new(raw).map(|raw| Sequence { 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 Sequence {}
3255
3256impl core::fmt::Debug for Sequence {
3257    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3258        f.debug_struct("Sequence").finish_non_exhaustive()
3259    }
3260}
3261
3262impl Sequence {
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_m2_M2Sequence_new();
3270            Self::from_raw(raw).expect("native Sequence allocation failed")
3271        }
3272    }
3273
3274    pub fn id(&self) -> u16 {
3275        // SAFETY: plain scalar read through a live handle.
3276        unsafe { ffi::whiteout_m2_M2Sequence_get_id(self.raw.as_ptr()) }
3277    }
3278
3279    pub fn set_id(&mut self, value: u16) {
3280        // SAFETY: plain scalar write through a live handle.
3281        unsafe { ffi::whiteout_m2_M2Sequence_set_id(self.raw.as_ptr(), value) }
3282    }
3283
3284    pub fn variation_index(&self) -> u16 {
3285        // SAFETY: plain scalar read through a live handle.
3286        unsafe { ffi::whiteout_m2_M2Sequence_get_variationIndex(self.raw.as_ptr()) }
3287    }
3288
3289    pub fn set_variation_index(&mut self, value: u16) {
3290        // SAFETY: plain scalar write through a live handle.
3291        unsafe { ffi::whiteout_m2_M2Sequence_set_variationIndex(self.raw.as_ptr(), value) }
3292    }
3293
3294    pub fn duration(&self) -> u32 {
3295        // SAFETY: plain scalar read through a live handle.
3296        unsafe { ffi::whiteout_m2_M2Sequence_get_duration(self.raw.as_ptr()) }
3297    }
3298
3299    pub fn set_duration(&mut self, value: u32) {
3300        // SAFETY: plain scalar write through a live handle.
3301        unsafe { ffi::whiteout_m2_M2Sequence_set_duration(self.raw.as_ptr(), value) }
3302    }
3303
3304    pub fn movespeed(&self) -> f32 {
3305        // SAFETY: plain scalar read through a live handle.
3306        unsafe { ffi::whiteout_m2_M2Sequence_get_movespeed(self.raw.as_ptr()) }
3307    }
3308
3309    pub fn set_movespeed(&mut self, value: f32) {
3310        // SAFETY: plain scalar write through a live handle.
3311        unsafe { ffi::whiteout_m2_M2Sequence_set_movespeed(self.raw.as_ptr(), value) }
3312    }
3313
3314    pub fn flags(&self) -> SequenceFlag {
3315        // SAFETY: scalar read; a flag set accepts any bits.
3316        SequenceFlag(unsafe { ffi::whiteout_m2_M2Sequence_get_flags(self.raw.as_ptr()) })
3317    }
3318
3319    pub fn set_flags(&mut self, value: SequenceFlag) {
3320        // SAFETY: scalar write through a live handle.
3321        unsafe { ffi::whiteout_m2_M2Sequence_set_flags(self.raw.as_ptr(), value.0) }
3322    }
3323
3324    pub fn frequency(&self) -> i16 {
3325        // SAFETY: plain scalar read through a live handle.
3326        unsafe { ffi::whiteout_m2_M2Sequence_get_frequency(self.raw.as_ptr()) }
3327    }
3328
3329    pub fn set_frequency(&mut self, value: i16) {
3330        // SAFETY: plain scalar write through a live handle.
3331        unsafe { ffi::whiteout_m2_M2Sequence_set_frequency(self.raw.as_ptr(), value) }
3332    }
3333
3334    pub fn padding(&self) -> u16 {
3335        // SAFETY: plain scalar read through a live handle.
3336        unsafe { ffi::whiteout_m2_M2Sequence_get_padding(self.raw.as_ptr()) }
3337    }
3338
3339    pub fn set_padding(&mut self, value: u16) {
3340        // SAFETY: plain scalar write through a live handle.
3341        unsafe { ffi::whiteout_m2_M2Sequence_set_padding(self.raw.as_ptr(), value) }
3342    }
3343
3344    pub fn replay_min(&self) -> u32 {
3345        // SAFETY: plain scalar read through a live handle.
3346        unsafe { ffi::whiteout_m2_M2Sequence_get_replayMin(self.raw.as_ptr()) }
3347    }
3348
3349    pub fn set_replay_min(&mut self, value: u32) {
3350        // SAFETY: plain scalar write through a live handle.
3351        unsafe { ffi::whiteout_m2_M2Sequence_set_replayMin(self.raw.as_ptr(), value) }
3352    }
3353
3354    pub fn replay_max(&self) -> u32 {
3355        // SAFETY: plain scalar read through a live handle.
3356        unsafe { ffi::whiteout_m2_M2Sequence_get_replayMax(self.raw.as_ptr()) }
3357    }
3358
3359    pub fn set_replay_max(&mut self, value: u32) {
3360        // SAFETY: plain scalar write through a live handle.
3361        unsafe { ffi::whiteout_m2_M2Sequence_set_replayMax(self.raw.as_ptr(), value) }
3362    }
3363
3364    pub fn blend_time_in(&self) -> u16 {
3365        // SAFETY: plain scalar read through a live handle.
3366        unsafe { ffi::whiteout_m2_M2Sequence_get_blendTimeIn(self.raw.as_ptr()) }
3367    }
3368
3369    pub fn set_blend_time_in(&mut self, value: u16) {
3370        // SAFETY: plain scalar write through a live handle.
3371        unsafe { ffi::whiteout_m2_M2Sequence_set_blendTimeIn(self.raw.as_ptr(), value) }
3372    }
3373
3374    pub fn blend_time_out(&self) -> u16 {
3375        // SAFETY: plain scalar read through a live handle.
3376        unsafe { ffi::whiteout_m2_M2Sequence_get_blendTimeOut(self.raw.as_ptr()) }
3377    }
3378
3379    pub fn set_blend_time_out(&mut self, value: u16) {
3380        // SAFETY: plain scalar write through a live handle.
3381        unsafe { ffi::whiteout_m2_M2Sequence_set_blendTimeOut(self.raw.as_ptr(), value) }
3382    }
3383
3384    /// Borrows the field in place — no copy, no allocation.
3385    pub fn bounding(&self) -> crate::support::Ref<'_, Extent> {
3386        // SAFETY: an interior pointer into `self`, valid for this
3387        // borrow and never freed by the `Ref`.
3388        unsafe {
3389            crate::support::Ref::new(Extent {
3390                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Sequence_get_bounding(
3391                    self.raw.as_ptr(),
3392                )),
3393            })
3394        }
3395    }
3396
3397    pub fn bounding_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
3398        // SAFETY: as above; `&mut self` guarantees exclusivity.
3399        unsafe {
3400            crate::support::RefMut::new(Extent {
3401                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Sequence_get_bounding(
3402                    self.raw.as_ptr(),
3403                )),
3404            })
3405        }
3406    }
3407
3408    pub fn variation_next(&self) -> i16 {
3409        // SAFETY: plain scalar read through a live handle.
3410        unsafe { ffi::whiteout_m2_M2Sequence_get_variationNext(self.raw.as_ptr()) }
3411    }
3412
3413    pub fn set_variation_next(&mut self, value: i16) {
3414        // SAFETY: plain scalar write through a live handle.
3415        unsafe { ffi::whiteout_m2_M2Sequence_set_variationNext(self.raw.as_ptr(), value) }
3416    }
3417
3418    pub fn alias_next(&self) -> u16 {
3419        // SAFETY: plain scalar read through a live handle.
3420        unsafe { ffi::whiteout_m2_M2Sequence_get_aliasNext(self.raw.as_ptr()) }
3421    }
3422
3423    pub fn set_alias_next(&mut self, value: u16) {
3424        // SAFETY: plain scalar write through a live handle.
3425        unsafe { ffi::whiteout_m2_M2Sequence_set_aliasNext(self.raw.as_ptr(), value) }
3426    }
3427}
3428
3429impl Default for Sequence {
3430    fn default() -> Self {
3431        Self::new()
3432    }
3433}
3434
3435pub struct Vertex {
3436    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Vertex>,
3437}
3438
3439impl Drop for Vertex {
3440    fn drop(&mut self) {
3441        // SAFETY: `raw` came from a native constructor and Drop runs once.
3442        unsafe { ffi::whiteout_m2_M2Vertex_delete(self.raw.as_ptr()) }
3443    }
3444}
3445
3446impl Vertex {
3447    /// # Safety
3448    /// `raw` must be a live handle this value takes ownership of.
3449    #[allow(dead_code)] // used by whichever methods return this type
3450    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Vertex) -> Option<Self> {
3451        core::ptr::NonNull::new(raw).map(|raw| Vertex { raw })
3452    }
3453}
3454
3455// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3456// is deliberately NOT implemented — the C++ types make no documented
3457// guarantee about concurrent use, and claiming one we haven't verified
3458// would be unsound. See `@bind thread_safe` in the plan.
3459unsafe impl Send for Vertex {}
3460
3461impl core::fmt::Debug for Vertex {
3462    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3463        f.debug_struct("Vertex").finish_non_exhaustive()
3464    }
3465}
3466
3467impl Vertex {
3468    /// # Panics
3469    /// Panics if the native allocation fails.
3470    pub fn new() -> Self {
3471        // SAFETY: the native constructor returns a live handle; a null here
3472        // means the library is unusable.
3473        unsafe {
3474            let raw = ffi::whiteout_m2_M2Vertex_new();
3475            Self::from_raw(raw).expect("native Vertex allocation failed")
3476        }
3477    }
3478
3479    pub fn position(&self) -> crate::math::Vector3f {
3480        // SAFETY: the getter returns an interior pointer to a
3481        // layout-identical POD; we copy it out immediately.
3482        unsafe {
3483            *(ffi::whiteout_m2_M2Vertex_get_position(self.raw.as_ptr())
3484                as *const crate::math::Vector3f)
3485        }
3486    }
3487
3488    pub fn set_position(&mut self, value: crate::math::Vector3f) {
3489        // SAFETY: as above, in the other direction.
3490        unsafe {
3491            ffi::whiteout_m2_M2Vertex_set_position(
3492                self.raw.as_ptr(),
3493                &value as *const crate::math::Vector3f as *const _,
3494            )
3495        }
3496    }
3497
3498    /// Number of elements — a fixed-size C++ array.
3499    pub const fn bone_weights_len() -> usize {
3500        4
3501    }
3502
3503    /// # Panics
3504    /// If `index >= 4`, matching Rust slice indexing.
3505    pub fn bone_weights(&self, index: usize) -> u8 {
3506        assert!(index < 4, "bone_weights index {index} out of range (len 4)");
3507        // SAFETY: index checked above; plain scalar read.
3508        unsafe { ffi::whiteout_m2_M2Vertex_get_boneWeights_at(self.raw.as_ptr(), index) }
3509    }
3510
3511    /// # Panics
3512    /// If `index >= 4`.
3513    pub fn set_bone_weights(&mut self, index: usize, value: u8) {
3514        assert!(index < 4, "bone_weights index {index} out of range (len 4)");
3515        // SAFETY: index checked above.
3516        unsafe { ffi::whiteout_m2_M2Vertex_set_boneWeights_at(self.raw.as_ptr(), index, value) }
3517    }
3518
3519    /// Number of elements — a fixed-size C++ array.
3520    pub const fn bone_indices_len() -> usize {
3521        4
3522    }
3523
3524    /// # Panics
3525    /// If `index >= 4`, matching Rust slice indexing.
3526    pub fn bone_indices(&self, index: usize) -> u8 {
3527        assert!(index < 4, "bone_indices index {index} out of range (len 4)");
3528        // SAFETY: index checked above; plain scalar read.
3529        unsafe { ffi::whiteout_m2_M2Vertex_get_boneIndices_at(self.raw.as_ptr(), index) }
3530    }
3531
3532    /// # Panics
3533    /// If `index >= 4`.
3534    pub fn set_bone_indices(&mut self, index: usize, value: u8) {
3535        assert!(index < 4, "bone_indices index {index} out of range (len 4)");
3536        // SAFETY: index checked above.
3537        unsafe { ffi::whiteout_m2_M2Vertex_set_boneIndices_at(self.raw.as_ptr(), index, value) }
3538    }
3539
3540    pub fn normal(&self) -> crate::math::Vector3f {
3541        // SAFETY: the getter returns an interior pointer to a
3542        // layout-identical POD; we copy it out immediately.
3543        unsafe {
3544            *(ffi::whiteout_m2_M2Vertex_get_normal(self.raw.as_ptr())
3545                as *const crate::math::Vector3f)
3546        }
3547    }
3548
3549    pub fn set_normal(&mut self, value: crate::math::Vector3f) {
3550        // SAFETY: as above, in the other direction.
3551        unsafe {
3552            ffi::whiteout_m2_M2Vertex_set_normal(
3553                self.raw.as_ptr(),
3554                &value as *const crate::math::Vector3f as *const _,
3555            )
3556        }
3557    }
3558
3559    /// Number of elements — a fixed-size C++ array.
3560    pub const fn tex_coords_len() -> usize {
3561        2
3562    }
3563
3564    /// # Panics
3565    /// If `index >= 2`, matching Rust slice indexing. The
3566    /// native accessor does no bounds checking of its own, so
3567    /// this check is what keeps the method safe to call.
3568    pub fn tex_coords(&self, index: usize) -> crate::math::Vector2f {
3569        assert!(index < 2, "tex_coords index {index} out of range (len 2)");
3570        // SAFETY: index checked above; the getter returns an
3571        // interior pointer to a layout-identical POD, copied
3572        // out immediately.
3573        unsafe {
3574            *(ffi::whiteout_m2_M2Vertex_get_texCoords_at(self.raw.as_ptr(), index)
3575                as *const crate::math::Vector2f)
3576        }
3577    }
3578}
3579
3580impl Default for Vertex {
3581    fn default() -> Self {
3582        Self::new()
3583    }
3584}
3585
3586pub struct Bone {
3587    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Bone>,
3588}
3589
3590impl Drop for Bone {
3591    fn drop(&mut self) {
3592        // SAFETY: `raw` came from a native constructor and Drop runs once.
3593        unsafe { ffi::whiteout_m2_M2Bone_delete(self.raw.as_ptr()) }
3594    }
3595}
3596
3597impl Bone {
3598    /// # Safety
3599    /// `raw` must be a live handle this value takes ownership of.
3600    #[allow(dead_code)] // used by whichever methods return this type
3601    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Bone) -> Option<Self> {
3602        core::ptr::NonNull::new(raw).map(|raw| Bone { raw })
3603    }
3604}
3605
3606// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3607// is deliberately NOT implemented — the C++ types make no documented
3608// guarantee about concurrent use, and claiming one we haven't verified
3609// would be unsound. See `@bind thread_safe` in the plan.
3610unsafe impl Send for Bone {}
3611
3612impl core::fmt::Debug for Bone {
3613    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3614        f.debug_struct("Bone").finish_non_exhaustive()
3615    }
3616}
3617
3618impl Bone {
3619    /// # Panics
3620    /// Panics if the native allocation fails.
3621    pub fn new() -> Self {
3622        // SAFETY: the native constructor returns a live handle; a null here
3623        // means the library is unusable.
3624        unsafe {
3625            let raw = ffi::whiteout_m2_M2Bone_new();
3626            Self::from_raw(raw).expect("native Bone allocation failed")
3627        }
3628    }
3629
3630    pub fn key_bone_id(&self) -> i32 {
3631        // SAFETY: plain scalar read through a live handle.
3632        unsafe { ffi::whiteout_m2_M2Bone_get_keyBoneId(self.raw.as_ptr()) }
3633    }
3634
3635    pub fn set_key_bone_id(&mut self, value: i32) {
3636        // SAFETY: plain scalar write through a live handle.
3637        unsafe { ffi::whiteout_m2_M2Bone_set_keyBoneId(self.raw.as_ptr(), value) }
3638    }
3639
3640    pub fn flags(&self) -> u32 {
3641        // SAFETY: plain scalar read through a live handle.
3642        unsafe { ffi::whiteout_m2_M2Bone_get_flags(self.raw.as_ptr()) }
3643    }
3644
3645    pub fn set_flags(&mut self, value: u32) {
3646        // SAFETY: plain scalar write through a live handle.
3647        unsafe { ffi::whiteout_m2_M2Bone_set_flags(self.raw.as_ptr(), value) }
3648    }
3649
3650    pub fn parent_bone_id(&self) -> i16 {
3651        // SAFETY: plain scalar read through a live handle.
3652        unsafe { ffi::whiteout_m2_M2Bone_get_parentBoneId(self.raw.as_ptr()) }
3653    }
3654
3655    pub fn set_parent_bone_id(&mut self, value: i16) {
3656        // SAFETY: plain scalar write through a live handle.
3657        unsafe { ffi::whiteout_m2_M2Bone_set_parentBoneId(self.raw.as_ptr(), value) }
3658    }
3659
3660    pub fn submesh_id(&self) -> u16 {
3661        // SAFETY: plain scalar read through a live handle.
3662        unsafe { ffi::whiteout_m2_M2Bone_get_submeshId(self.raw.as_ptr()) }
3663    }
3664
3665    pub fn set_submesh_id(&mut self, value: u16) {
3666        // SAFETY: plain scalar write through a live handle.
3667        unsafe { ffi::whiteout_m2_M2Bone_set_submeshId(self.raw.as_ptr(), value) }
3668    }
3669
3670    pub fn bone_name_crc(&self) -> u32 {
3671        // SAFETY: plain scalar read through a live handle.
3672        unsafe { ffi::whiteout_m2_M2Bone_get_boneNameCRC(self.raw.as_ptr()) }
3673    }
3674
3675    pub fn set_bone_name_crc(&mut self, value: u32) {
3676        // SAFETY: plain scalar write through a live handle.
3677        unsafe { ffi::whiteout_m2_M2Bone_set_boneNameCRC(self.raw.as_ptr(), value) }
3678    }
3679
3680    /// Borrows the field in place — no copy, no allocation.
3681    pub fn translation(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
3682        // SAFETY: an interior pointer into `self`, valid for this
3683        // borrow and never freed by the `Ref`.
3684        unsafe {
3685            crate::support::Ref::new(AnimationTrackVector3f {
3686                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_translation(
3687                    self.raw.as_ptr(),
3688                )),
3689            })
3690        }
3691    }
3692
3693    pub fn translation_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
3694        // SAFETY: as above; `&mut self` guarantees exclusivity.
3695        unsafe {
3696            crate::support::RefMut::new(AnimationTrackVector3f {
3697                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_translation(
3698                    self.raw.as_ptr(),
3699                )),
3700            })
3701        }
3702    }
3703
3704    /// Borrows the field in place — no copy, no allocation.
3705    pub fn rotation(&self) -> crate::support::Ref<'_, AnimationTrackM2CompatQuaternion> {
3706        // SAFETY: an interior pointer into `self`, valid for this
3707        // borrow and never freed by the `Ref`.
3708        unsafe {
3709            crate::support::Ref::new(AnimationTrackM2CompatQuaternion {
3710                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_rotation(
3711                    self.raw.as_ptr(),
3712                )),
3713            })
3714        }
3715    }
3716
3717    pub fn rotation_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackM2CompatQuaternion> {
3718        // SAFETY: as above; `&mut self` guarantees exclusivity.
3719        unsafe {
3720            crate::support::RefMut::new(AnimationTrackM2CompatQuaternion {
3721                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_rotation(
3722                    self.raw.as_ptr(),
3723                )),
3724            })
3725        }
3726    }
3727
3728    /// Borrows the field in place — no copy, no allocation.
3729    pub fn scale(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
3730        // SAFETY: an interior pointer into `self`, valid for this
3731        // borrow and never freed by the `Ref`.
3732        unsafe {
3733            crate::support::Ref::new(AnimationTrackVector3f {
3734                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_scale(
3735                    self.raw.as_ptr(),
3736                )),
3737            })
3738        }
3739    }
3740
3741    pub fn scale_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
3742        // SAFETY: as above; `&mut self` guarantees exclusivity.
3743        unsafe {
3744            crate::support::RefMut::new(AnimationTrackVector3f {
3745                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Bone_get_scale(
3746                    self.raw.as_ptr(),
3747                )),
3748            })
3749        }
3750    }
3751
3752    pub fn pivot(&self) -> crate::math::Vector3f {
3753        // SAFETY: the getter returns an interior pointer to a
3754        // layout-identical POD; we copy it out immediately.
3755        unsafe {
3756            *(ffi::whiteout_m2_M2Bone_get_pivot(self.raw.as_ptr()) as *const crate::math::Vector3f)
3757        }
3758    }
3759
3760    pub fn set_pivot(&mut self, value: crate::math::Vector3f) {
3761        // SAFETY: as above, in the other direction.
3762        unsafe {
3763            ffi::whiteout_m2_M2Bone_set_pivot(
3764                self.raw.as_ptr(),
3765                &value as *const crate::math::Vector3f as *const _,
3766            )
3767        }
3768    }
3769}
3770
3771impl Default for Bone {
3772    fn default() -> Self {
3773        Self::new()
3774    }
3775}
3776
3777pub struct Texture {
3778    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Texture>,
3779}
3780
3781impl Drop for Texture {
3782    fn drop(&mut self) {
3783        // SAFETY: `raw` came from a native constructor and Drop runs once.
3784        unsafe { ffi::whiteout_m2_M2Texture_delete(self.raw.as_ptr()) }
3785    }
3786}
3787
3788impl Texture {
3789    /// # Safety
3790    /// `raw` must be a live handle this value takes ownership of.
3791    #[allow(dead_code)] // used by whichever methods return this type
3792    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Texture) -> Option<Self> {
3793        core::ptr::NonNull::new(raw).map(|raw| Texture { raw })
3794    }
3795}
3796
3797// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3798// is deliberately NOT implemented — the C++ types make no documented
3799// guarantee about concurrent use, and claiming one we haven't verified
3800// would be unsound. See `@bind thread_safe` in the plan.
3801unsafe impl Send for Texture {}
3802
3803impl core::fmt::Debug for Texture {
3804    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3805        f.debug_struct("Texture").finish_non_exhaustive()
3806    }
3807}
3808
3809impl Texture {
3810    /// # Panics
3811    /// Panics if the native allocation fails.
3812    pub fn new() -> Self {
3813        // SAFETY: the native constructor returns a live handle; a null here
3814        // means the library is unusable.
3815        unsafe {
3816            let raw = ffi::whiteout_m2_M2Texture_new();
3817            Self::from_raw(raw).expect("native Texture allocation failed")
3818        }
3819    }
3820
3821    pub fn type_(&self) -> u32 {
3822        // SAFETY: plain scalar read through a live handle.
3823        unsafe { ffi::whiteout_m2_M2Texture_get_type(self.raw.as_ptr()) }
3824    }
3825
3826    pub fn set_type_(&mut self, value: u32) {
3827        // SAFETY: plain scalar write through a live handle.
3828        unsafe { ffi::whiteout_m2_M2Texture_set_type(self.raw.as_ptr(), value) }
3829    }
3830
3831    pub fn flags(&self) -> u32 {
3832        // SAFETY: plain scalar read through a live handle.
3833        unsafe { ffi::whiteout_m2_M2Texture_get_flags(self.raw.as_ptr()) }
3834    }
3835
3836    pub fn set_flags(&mut self, value: u32) {
3837        // SAFETY: plain scalar write through a live handle.
3838        unsafe { ffi::whiteout_m2_M2Texture_set_flags(self.raw.as_ptr(), value) }
3839    }
3840
3841    pub fn filename(&self) -> String {
3842        // SAFETY: the native side hands over an owned CString.
3843        unsafe {
3844            crate::support::take_string(ffi::whiteout_m2_M2Texture_get_filename(self.raw.as_ptr()))
3845        }
3846    }
3847
3848    pub fn set_filename(&mut self, value: &str) {
3849        let value = std::ffi::CString::new(value).unwrap_or_default();
3850        // SAFETY: the pointer outlives the call.
3851        unsafe { ffi::whiteout_m2_M2Texture_set_filename(self.raw.as_ptr(), value.as_ptr()) }
3852    }
3853}
3854
3855impl Default for Texture {
3856    fn default() -> Self {
3857        Self::new()
3858    }
3859}
3860
3861pub struct Material {
3862    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Material>,
3863}
3864
3865impl Drop for Material {
3866    fn drop(&mut self) {
3867        // SAFETY: `raw` came from a native constructor and Drop runs once.
3868        unsafe { ffi::whiteout_m2_M2Material_delete(self.raw.as_ptr()) }
3869    }
3870}
3871
3872impl Material {
3873    /// # Safety
3874    /// `raw` must be a live handle this value takes ownership of.
3875    #[allow(dead_code)] // used by whichever methods return this type
3876    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Material) -> Option<Self> {
3877        core::ptr::NonNull::new(raw).map(|raw| Material { raw })
3878    }
3879}
3880
3881// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3882// is deliberately NOT implemented — the C++ types make no documented
3883// guarantee about concurrent use, and claiming one we haven't verified
3884// would be unsound. See `@bind thread_safe` in the plan.
3885unsafe impl Send for Material {}
3886
3887impl core::fmt::Debug for Material {
3888    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3889        f.debug_struct("Material").finish_non_exhaustive()
3890    }
3891}
3892
3893impl Material {
3894    /// # Panics
3895    /// Panics if the native allocation fails.
3896    pub fn new() -> Self {
3897        // SAFETY: the native constructor returns a live handle; a null here
3898        // means the library is unusable.
3899        unsafe {
3900            let raw = ffi::whiteout_m2_M2Material_new();
3901            Self::from_raw(raw).expect("native Material allocation failed")
3902        }
3903    }
3904
3905    pub fn flags(&self) -> u16 {
3906        // SAFETY: plain scalar read through a live handle.
3907        unsafe { ffi::whiteout_m2_M2Material_get_flags(self.raw.as_ptr()) }
3908    }
3909
3910    pub fn set_flags(&mut self, value: u16) {
3911        // SAFETY: plain scalar write through a live handle.
3912        unsafe { ffi::whiteout_m2_M2Material_set_flags(self.raw.as_ptr(), value) }
3913    }
3914
3915    pub fn blending_mode(&self) -> u16 {
3916        // SAFETY: plain scalar read through a live handle.
3917        unsafe { ffi::whiteout_m2_M2Material_get_blendingMode(self.raw.as_ptr()) }
3918    }
3919
3920    pub fn set_blending_mode(&mut self, value: u16) {
3921        // SAFETY: plain scalar write through a live handle.
3922        unsafe { ffi::whiteout_m2_M2Material_set_blendingMode(self.raw.as_ptr(), value) }
3923    }
3924}
3925
3926impl Default for Material {
3927    fn default() -> Self {
3928        Self::new()
3929    }
3930}
3931
3932pub struct TextureWeight {
3933    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2TextureWeight>,
3934}
3935
3936impl Drop for TextureWeight {
3937    fn drop(&mut self) {
3938        // SAFETY: `raw` came from a native constructor and Drop runs once.
3939        unsafe { ffi::whiteout_m2_M2TextureWeight_delete(self.raw.as_ptr()) }
3940    }
3941}
3942
3943impl TextureWeight {
3944    /// # Safety
3945    /// `raw` must be a live handle this value takes ownership of.
3946    #[allow(dead_code)] // used by whichever methods return this type
3947    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2TextureWeight) -> Option<Self> {
3948        core::ptr::NonNull::new(raw).map(|raw| TextureWeight { raw })
3949    }
3950}
3951
3952// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
3953// is deliberately NOT implemented — the C++ types make no documented
3954// guarantee about concurrent use, and claiming one we haven't verified
3955// would be unsound. See `@bind thread_safe` in the plan.
3956unsafe impl Send for TextureWeight {}
3957
3958impl core::fmt::Debug for TextureWeight {
3959    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3960        f.debug_struct("TextureWeight").finish_non_exhaustive()
3961    }
3962}
3963
3964impl TextureWeight {
3965    /// # Panics
3966    /// Panics if the native allocation fails.
3967    pub fn new() -> Self {
3968        // SAFETY: the native constructor returns a live handle; a null here
3969        // means the library is unusable.
3970        unsafe {
3971            let raw = ffi::whiteout_m2_M2TextureWeight_new();
3972            Self::from_raw(raw).expect("native TextureWeight allocation failed")
3973        }
3974    }
3975
3976    /// Borrows the field in place — no copy, no allocation.
3977    pub fn weight(&self) -> crate::support::Ref<'_, AnimationTrackI16> {
3978        // SAFETY: an interior pointer into `self`, valid for this
3979        // borrow and never freed by the `Ref`.
3980        unsafe {
3981            crate::support::Ref::new(AnimationTrackI16 {
3982                raw: core::ptr::NonNull::new_unchecked(
3983                    ffi::whiteout_m2_M2TextureWeight_get_weight(self.raw.as_ptr()),
3984                ),
3985            })
3986        }
3987    }
3988
3989    pub fn weight_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackI16> {
3990        // SAFETY: as above; `&mut self` guarantees exclusivity.
3991        unsafe {
3992            crate::support::RefMut::new(AnimationTrackI16 {
3993                raw: core::ptr::NonNull::new_unchecked(
3994                    ffi::whiteout_m2_M2TextureWeight_get_weight(self.raw.as_ptr()),
3995                ),
3996            })
3997        }
3998    }
3999}
4000
4001impl Default for TextureWeight {
4002    fn default() -> Self {
4003        Self::new()
4004    }
4005}
4006
4007pub struct TextureTransform {
4008    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2TextureTransform>,
4009}
4010
4011impl Drop for TextureTransform {
4012    fn drop(&mut self) {
4013        // SAFETY: `raw` came from a native constructor and Drop runs once.
4014        unsafe { ffi::whiteout_m2_M2TextureTransform_delete(self.raw.as_ptr()) }
4015    }
4016}
4017
4018impl TextureTransform {
4019    /// # Safety
4020    /// `raw` must be a live handle this value takes ownership of.
4021    #[allow(dead_code)] // used by whichever methods return this type
4022    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2TextureTransform) -> Option<Self> {
4023        core::ptr::NonNull::new(raw).map(|raw| TextureTransform { raw })
4024    }
4025}
4026
4027// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4028// is deliberately NOT implemented — the C++ types make no documented
4029// guarantee about concurrent use, and claiming one we haven't verified
4030// would be unsound. See `@bind thread_safe` in the plan.
4031unsafe impl Send for TextureTransform {}
4032
4033impl core::fmt::Debug for TextureTransform {
4034    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4035        f.debug_struct("TextureTransform").finish_non_exhaustive()
4036    }
4037}
4038
4039impl TextureTransform {
4040    /// # Panics
4041    /// Panics if the native allocation fails.
4042    pub fn new() -> Self {
4043        // SAFETY: the native constructor returns a live handle; a null here
4044        // means the library is unusable.
4045        unsafe {
4046            let raw = ffi::whiteout_m2_M2TextureTransform_new();
4047            Self::from_raw(raw).expect("native TextureTransform allocation failed")
4048        }
4049    }
4050
4051    /// Borrows the field in place — no copy, no allocation.
4052    pub fn translation(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
4053        // SAFETY: an interior pointer into `self`, valid for this
4054        // borrow and never freed by the `Ref`.
4055        unsafe {
4056            crate::support::Ref::new(AnimationTrackVector3f {
4057                raw: core::ptr::NonNull::new_unchecked(
4058                    ffi::whiteout_m2_M2TextureTransform_get_translation(self.raw.as_ptr()),
4059                ),
4060            })
4061        }
4062    }
4063
4064    pub fn translation_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
4065        // SAFETY: as above; `&mut self` guarantees exclusivity.
4066        unsafe {
4067            crate::support::RefMut::new(AnimationTrackVector3f {
4068                raw: core::ptr::NonNull::new_unchecked(
4069                    ffi::whiteout_m2_M2TextureTransform_get_translation(self.raw.as_ptr()),
4070                ),
4071            })
4072        }
4073    }
4074
4075    /// Borrows the field in place — no copy, no allocation.
4076    pub fn rotation(&self) -> crate::support::Ref<'_, AnimationTrackQuaternion> {
4077        // SAFETY: an interior pointer into `self`, valid for this
4078        // borrow and never freed by the `Ref`.
4079        unsafe {
4080            crate::support::Ref::new(AnimationTrackQuaternion {
4081                raw: core::ptr::NonNull::new_unchecked(
4082                    ffi::whiteout_m2_M2TextureTransform_get_rotation(self.raw.as_ptr()),
4083                ),
4084            })
4085        }
4086    }
4087
4088    pub fn rotation_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackQuaternion> {
4089        // SAFETY: as above; `&mut self` guarantees exclusivity.
4090        unsafe {
4091            crate::support::RefMut::new(AnimationTrackQuaternion {
4092                raw: core::ptr::NonNull::new_unchecked(
4093                    ffi::whiteout_m2_M2TextureTransform_get_rotation(self.raw.as_ptr()),
4094                ),
4095            })
4096        }
4097    }
4098
4099    /// Borrows the field in place — no copy, no allocation.
4100    pub fn scaling(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
4101        // SAFETY: an interior pointer into `self`, valid for this
4102        // borrow and never freed by the `Ref`.
4103        unsafe {
4104            crate::support::Ref::new(AnimationTrackVector3f {
4105                raw: core::ptr::NonNull::new_unchecked(
4106                    ffi::whiteout_m2_M2TextureTransform_get_scaling(self.raw.as_ptr()),
4107                ),
4108            })
4109        }
4110    }
4111
4112    pub fn scaling_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
4113        // SAFETY: as above; `&mut self` guarantees exclusivity.
4114        unsafe {
4115            crate::support::RefMut::new(AnimationTrackVector3f {
4116                raw: core::ptr::NonNull::new_unchecked(
4117                    ffi::whiteout_m2_M2TextureTransform_get_scaling(self.raw.as_ptr()),
4118                ),
4119            })
4120        }
4121    }
4122}
4123
4124impl Default for TextureTransform {
4125    fn default() -> Self {
4126        Self::new()
4127    }
4128}
4129
4130pub struct ColorAnimation {
4131    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ColorAnimation>,
4132}
4133
4134impl Drop for ColorAnimation {
4135    fn drop(&mut self) {
4136        // SAFETY: `raw` came from a native constructor and Drop runs once.
4137        unsafe { ffi::whiteout_m2_M2ColorAnimation_delete(self.raw.as_ptr()) }
4138    }
4139}
4140
4141impl ColorAnimation {
4142    /// # Safety
4143    /// `raw` must be a live handle this value takes ownership of.
4144    #[allow(dead_code)] // used by whichever methods return this type
4145    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ColorAnimation) -> Option<Self> {
4146        core::ptr::NonNull::new(raw).map(|raw| ColorAnimation { raw })
4147    }
4148}
4149
4150// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4151// is deliberately NOT implemented — the C++ types make no documented
4152// guarantee about concurrent use, and claiming one we haven't verified
4153// would be unsound. See `@bind thread_safe` in the plan.
4154unsafe impl Send for ColorAnimation {}
4155
4156impl core::fmt::Debug for ColorAnimation {
4157    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4158        f.debug_struct("ColorAnimation").finish_non_exhaustive()
4159    }
4160}
4161
4162impl ColorAnimation {
4163    /// # Panics
4164    /// Panics if the native allocation fails.
4165    pub fn new() -> Self {
4166        // SAFETY: the native constructor returns a live handle; a null here
4167        // means the library is unusable.
4168        unsafe {
4169            let raw = ffi::whiteout_m2_M2ColorAnimation_new();
4170            Self::from_raw(raw).expect("native ColorAnimation allocation failed")
4171        }
4172    }
4173
4174    /// Borrows the field in place — no copy, no allocation.
4175    pub fn color(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
4176        // SAFETY: an interior pointer into `self`, valid for this
4177        // borrow and never freed by the `Ref`.
4178        unsafe {
4179            crate::support::Ref::new(AnimationTrackVector3f {
4180                raw: core::ptr::NonNull::new_unchecked(
4181                    ffi::whiteout_m2_M2ColorAnimation_get_color(self.raw.as_ptr()),
4182                ),
4183            })
4184        }
4185    }
4186
4187    pub fn color_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
4188        // SAFETY: as above; `&mut self` guarantees exclusivity.
4189        unsafe {
4190            crate::support::RefMut::new(AnimationTrackVector3f {
4191                raw: core::ptr::NonNull::new_unchecked(
4192                    ffi::whiteout_m2_M2ColorAnimation_get_color(self.raw.as_ptr()),
4193                ),
4194            })
4195        }
4196    }
4197
4198    /// Borrows the field in place — no copy, no allocation.
4199    pub fn alpha(&self) -> crate::support::Ref<'_, AnimationTrackI16> {
4200        // SAFETY: an interior pointer into `self`, valid for this
4201        // borrow and never freed by the `Ref`.
4202        unsafe {
4203            crate::support::Ref::new(AnimationTrackI16 {
4204                raw: core::ptr::NonNull::new_unchecked(
4205                    ffi::whiteout_m2_M2ColorAnimation_get_alpha(self.raw.as_ptr()),
4206                ),
4207            })
4208        }
4209    }
4210
4211    pub fn alpha_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackI16> {
4212        // SAFETY: as above; `&mut self` guarantees exclusivity.
4213        unsafe {
4214            crate::support::RefMut::new(AnimationTrackI16 {
4215                raw: core::ptr::NonNull::new_unchecked(
4216                    ffi::whiteout_m2_M2ColorAnimation_get_alpha(self.raw.as_ptr()),
4217                ),
4218            })
4219        }
4220    }
4221}
4222
4223impl Default for ColorAnimation {
4224    fn default() -> Self {
4225        Self::new()
4226    }
4227}
4228
4229pub struct Light {
4230    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Light>,
4231}
4232
4233impl Drop for Light {
4234    fn drop(&mut self) {
4235        // SAFETY: `raw` came from a native constructor and Drop runs once.
4236        unsafe { ffi::whiteout_m2_M2Light_delete(self.raw.as_ptr()) }
4237    }
4238}
4239
4240impl Light {
4241    /// # Safety
4242    /// `raw` must be a live handle this value takes ownership of.
4243    #[allow(dead_code)] // used by whichever methods return this type
4244    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Light) -> Option<Self> {
4245        core::ptr::NonNull::new(raw).map(|raw| Light { raw })
4246    }
4247}
4248
4249// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4250// is deliberately NOT implemented — the C++ types make no documented
4251// guarantee about concurrent use, and claiming one we haven't verified
4252// would be unsound. See `@bind thread_safe` in the plan.
4253unsafe impl Send for Light {}
4254
4255impl core::fmt::Debug for Light {
4256    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4257        f.debug_struct("Light").finish_non_exhaustive()
4258    }
4259}
4260
4261impl Light {
4262    /// # Panics
4263    /// Panics if the native allocation fails.
4264    pub fn new() -> Self {
4265        // SAFETY: the native constructor returns a live handle; a null here
4266        // means the library is unusable.
4267        unsafe {
4268            let raw = ffi::whiteout_m2_M2Light_new();
4269            Self::from_raw(raw).expect("native Light allocation failed")
4270        }
4271    }
4272
4273    pub fn type_(&self) -> u16 {
4274        // SAFETY: plain scalar read through a live handle.
4275        unsafe { ffi::whiteout_m2_M2Light_get_type(self.raw.as_ptr()) }
4276    }
4277
4278    pub fn set_type_(&mut self, value: u16) {
4279        // SAFETY: plain scalar write through a live handle.
4280        unsafe { ffi::whiteout_m2_M2Light_set_type(self.raw.as_ptr(), value) }
4281    }
4282
4283    pub fn bone_id(&self) -> i16 {
4284        // SAFETY: plain scalar read through a live handle.
4285        unsafe { ffi::whiteout_m2_M2Light_get_boneId(self.raw.as_ptr()) }
4286    }
4287
4288    pub fn set_bone_id(&mut self, value: i16) {
4289        // SAFETY: plain scalar write through a live handle.
4290        unsafe { ffi::whiteout_m2_M2Light_set_boneId(self.raw.as_ptr(), value) }
4291    }
4292
4293    pub fn position(&self) -> crate::math::Vector3f {
4294        // SAFETY: the getter returns an interior pointer to a
4295        // layout-identical POD; we copy it out immediately.
4296        unsafe {
4297            *(ffi::whiteout_m2_M2Light_get_position(self.raw.as_ptr())
4298                as *const crate::math::Vector3f)
4299        }
4300    }
4301
4302    pub fn set_position(&mut self, value: crate::math::Vector3f) {
4303        // SAFETY: as above, in the other direction.
4304        unsafe {
4305            ffi::whiteout_m2_M2Light_set_position(
4306                self.raw.as_ptr(),
4307                &value as *const crate::math::Vector3f as *const _,
4308            )
4309        }
4310    }
4311
4312    /// Borrows the field in place — no copy, no allocation.
4313    pub fn ambient_color(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
4314        // SAFETY: an interior pointer into `self`, valid for this
4315        // borrow and never freed by the `Ref`.
4316        unsafe {
4317            crate::support::Ref::new(AnimationTrackVector3f {
4318                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_ambientColor(
4319                    self.raw.as_ptr(),
4320                )),
4321            })
4322        }
4323    }
4324
4325    pub fn ambient_color_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
4326        // SAFETY: as above; `&mut self` guarantees exclusivity.
4327        unsafe {
4328            crate::support::RefMut::new(AnimationTrackVector3f {
4329                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_ambientColor(
4330                    self.raw.as_ptr(),
4331                )),
4332            })
4333        }
4334    }
4335
4336    /// Borrows the field in place — no copy, no allocation.
4337    pub fn ambient_intensity(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
4338        // SAFETY: an interior pointer into `self`, valid for this
4339        // borrow and never freed by the `Ref`.
4340        unsafe {
4341            crate::support::Ref::new(AnimationTrackF32 {
4342                raw: core::ptr::NonNull::new_unchecked(
4343                    ffi::whiteout_m2_M2Light_get_ambientIntensity(self.raw.as_ptr()),
4344                ),
4345            })
4346        }
4347    }
4348
4349    pub fn ambient_intensity_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4350        // SAFETY: as above; `&mut self` guarantees exclusivity.
4351        unsafe {
4352            crate::support::RefMut::new(AnimationTrackF32 {
4353                raw: core::ptr::NonNull::new_unchecked(
4354                    ffi::whiteout_m2_M2Light_get_ambientIntensity(self.raw.as_ptr()),
4355                ),
4356            })
4357        }
4358    }
4359
4360    /// Borrows the field in place — no copy, no allocation.
4361    pub fn diffuse_color(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
4362        // SAFETY: an interior pointer into `self`, valid for this
4363        // borrow and never freed by the `Ref`.
4364        unsafe {
4365            crate::support::Ref::new(AnimationTrackVector3f {
4366                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_diffuseColor(
4367                    self.raw.as_ptr(),
4368                )),
4369            })
4370        }
4371    }
4372
4373    pub fn diffuse_color_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
4374        // SAFETY: as above; `&mut self` guarantees exclusivity.
4375        unsafe {
4376            crate::support::RefMut::new(AnimationTrackVector3f {
4377                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_diffuseColor(
4378                    self.raw.as_ptr(),
4379                )),
4380            })
4381        }
4382    }
4383
4384    /// Borrows the field in place — no copy, no allocation.
4385    pub fn diffuse_intensity(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
4386        // SAFETY: an interior pointer into `self`, valid for this
4387        // borrow and never freed by the `Ref`.
4388        unsafe {
4389            crate::support::Ref::new(AnimationTrackF32 {
4390                raw: core::ptr::NonNull::new_unchecked(
4391                    ffi::whiteout_m2_M2Light_get_diffuseIntensity(self.raw.as_ptr()),
4392                ),
4393            })
4394        }
4395    }
4396
4397    pub fn diffuse_intensity_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4398        // SAFETY: as above; `&mut self` guarantees exclusivity.
4399        unsafe {
4400            crate::support::RefMut::new(AnimationTrackF32 {
4401                raw: core::ptr::NonNull::new_unchecked(
4402                    ffi::whiteout_m2_M2Light_get_diffuseIntensity(self.raw.as_ptr()),
4403                ),
4404            })
4405        }
4406    }
4407
4408    /// Borrows the field in place — no copy, no allocation.
4409    pub fn attenuation_start(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
4410        // SAFETY: an interior pointer into `self`, valid for this
4411        // borrow and never freed by the `Ref`.
4412        unsafe {
4413            crate::support::Ref::new(AnimationTrackF32 {
4414                raw: core::ptr::NonNull::new_unchecked(
4415                    ffi::whiteout_m2_M2Light_get_attenuationStart(self.raw.as_ptr()),
4416                ),
4417            })
4418        }
4419    }
4420
4421    pub fn attenuation_start_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4422        // SAFETY: as above; `&mut self` guarantees exclusivity.
4423        unsafe {
4424            crate::support::RefMut::new(AnimationTrackF32 {
4425                raw: core::ptr::NonNull::new_unchecked(
4426                    ffi::whiteout_m2_M2Light_get_attenuationStart(self.raw.as_ptr()),
4427                ),
4428            })
4429        }
4430    }
4431
4432    /// Borrows the field in place — no copy, no allocation.
4433    pub fn attenuation_end(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
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(AnimationTrackF32 {
4438                raw: core::ptr::NonNull::new_unchecked(
4439                    ffi::whiteout_m2_M2Light_get_attenuationEnd(self.raw.as_ptr()),
4440                ),
4441            })
4442        }
4443    }
4444
4445    pub fn attenuation_end_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4446        // SAFETY: as above; `&mut self` guarantees exclusivity.
4447        unsafe {
4448            crate::support::RefMut::new(AnimationTrackF32 {
4449                raw: core::ptr::NonNull::new_unchecked(
4450                    ffi::whiteout_m2_M2Light_get_attenuationEnd(self.raw.as_ptr()),
4451                ),
4452            })
4453        }
4454    }
4455
4456    /// Borrows the field in place — no copy, no allocation.
4457    pub fn visibility(&self) -> crate::support::Ref<'_, AnimationTrackU8> {
4458        // SAFETY: an interior pointer into `self`, valid for this
4459        // borrow and never freed by the `Ref`.
4460        unsafe {
4461            crate::support::Ref::new(AnimationTrackU8 {
4462                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_visibility(
4463                    self.raw.as_ptr(),
4464                )),
4465            })
4466        }
4467    }
4468
4469    pub fn visibility_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackU8> {
4470        // SAFETY: as above; `&mut self` guarantees exclusivity.
4471        unsafe {
4472            crate::support::RefMut::new(AnimationTrackU8 {
4473                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Light_get_visibility(
4474                    self.raw.as_ptr(),
4475                )),
4476            })
4477        }
4478    }
4479}
4480
4481impl Default for Light {
4482    fn default() -> Self {
4483        Self::new()
4484    }
4485}
4486
4487pub struct CameraSpline {
4488    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2CameraSpline>,
4489}
4490
4491impl Drop for CameraSpline {
4492    fn drop(&mut self) {
4493        // SAFETY: `raw` came from a native constructor and Drop runs once.
4494        unsafe { ffi::whiteout_m2_M2CameraSpline_delete(self.raw.as_ptr()) }
4495    }
4496}
4497
4498impl CameraSpline {
4499    /// # Safety
4500    /// `raw` must be a live handle this value takes ownership of.
4501    #[allow(dead_code)] // used by whichever methods return this type
4502    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2CameraSpline) -> Option<Self> {
4503        core::ptr::NonNull::new(raw).map(|raw| CameraSpline { raw })
4504    }
4505}
4506
4507// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4508// is deliberately NOT implemented — the C++ types make no documented
4509// guarantee about concurrent use, and claiming one we haven't verified
4510// would be unsound. See `@bind thread_safe` in the plan.
4511unsafe impl Send for CameraSpline {}
4512
4513impl core::fmt::Debug for CameraSpline {
4514    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4515        f.debug_struct("CameraSpline").finish_non_exhaustive()
4516    }
4517}
4518
4519impl CameraSpline {
4520    /// # Panics
4521    /// Panics if the native allocation fails.
4522    pub fn new() -> Self {
4523        // SAFETY: the native constructor returns a live handle; a null here
4524        // means the library is unusable.
4525        unsafe {
4526            let raw = ffi::whiteout_m2_M2CameraSpline_new();
4527            Self::from_raw(raw).expect("native CameraSpline allocation failed")
4528        }
4529    }
4530
4531    pub fn value(&self) -> crate::math::Vector3f {
4532        // SAFETY: the getter returns an interior pointer to a
4533        // layout-identical POD; we copy it out immediately.
4534        unsafe {
4535            *(ffi::whiteout_m2_M2CameraSpline_get_value(self.raw.as_ptr())
4536                as *const crate::math::Vector3f)
4537        }
4538    }
4539
4540    pub fn set_value(&mut self, value: crate::math::Vector3f) {
4541        // SAFETY: as above, in the other direction.
4542        unsafe {
4543            ffi::whiteout_m2_M2CameraSpline_set_value(
4544                self.raw.as_ptr(),
4545                &value as *const crate::math::Vector3f as *const _,
4546            )
4547        }
4548    }
4549
4550    pub fn in_tangent(&self) -> crate::math::Vector3f {
4551        // SAFETY: the getter returns an interior pointer to a
4552        // layout-identical POD; we copy it out immediately.
4553        unsafe {
4554            *(ffi::whiteout_m2_M2CameraSpline_get_inTangent(self.raw.as_ptr())
4555                as *const crate::math::Vector3f)
4556        }
4557    }
4558
4559    pub fn set_in_tangent(&mut self, value: crate::math::Vector3f) {
4560        // SAFETY: as above, in the other direction.
4561        unsafe {
4562            ffi::whiteout_m2_M2CameraSpline_set_inTangent(
4563                self.raw.as_ptr(),
4564                &value as *const crate::math::Vector3f as *const _,
4565            )
4566        }
4567    }
4568
4569    pub fn out_tangent(&self) -> crate::math::Vector3f {
4570        // SAFETY: the getter returns an interior pointer to a
4571        // layout-identical POD; we copy it out immediately.
4572        unsafe {
4573            *(ffi::whiteout_m2_M2CameraSpline_get_outTangent(self.raw.as_ptr())
4574                as *const crate::math::Vector3f)
4575        }
4576    }
4577
4578    pub fn set_out_tangent(&mut self, value: crate::math::Vector3f) {
4579        // SAFETY: as above, in the other direction.
4580        unsafe {
4581            ffi::whiteout_m2_M2CameraSpline_set_outTangent(
4582                self.raw.as_ptr(),
4583                &value as *const crate::math::Vector3f as *const _,
4584            )
4585        }
4586    }
4587}
4588
4589impl Default for CameraSpline {
4590    fn default() -> Self {
4591        Self::new()
4592    }
4593}
4594
4595pub struct Camera {
4596    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Camera>,
4597}
4598
4599impl Drop for Camera {
4600    fn drop(&mut self) {
4601        // SAFETY: `raw` came from a native constructor and Drop runs once.
4602        unsafe { ffi::whiteout_m2_M2Camera_delete(self.raw.as_ptr()) }
4603    }
4604}
4605
4606impl Camera {
4607    /// # Safety
4608    /// `raw` must be a live handle this value takes ownership of.
4609    #[allow(dead_code)] // used by whichever methods return this type
4610    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Camera) -> Option<Self> {
4611        core::ptr::NonNull::new(raw).map(|raw| Camera { raw })
4612    }
4613}
4614
4615// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4616// is deliberately NOT implemented — the C++ types make no documented
4617// guarantee about concurrent use, and claiming one we haven't verified
4618// would be unsound. See `@bind thread_safe` in the plan.
4619unsafe impl Send for Camera {}
4620
4621impl core::fmt::Debug for Camera {
4622    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4623        f.debug_struct("Camera").finish_non_exhaustive()
4624    }
4625}
4626
4627impl Camera {
4628    /// # Panics
4629    /// Panics if the native allocation fails.
4630    pub fn new() -> Self {
4631        // SAFETY: the native constructor returns a live handle; a null here
4632        // means the library is unusable.
4633        unsafe {
4634            let raw = ffi::whiteout_m2_M2Camera_new();
4635            Self::from_raw(raw).expect("native Camera allocation failed")
4636        }
4637    }
4638
4639    pub fn type_(&self) -> u32 {
4640        // SAFETY: plain scalar read through a live handle.
4641        unsafe { ffi::whiteout_m2_M2Camera_get_type(self.raw.as_ptr()) }
4642    }
4643
4644    pub fn set_type_(&mut self, value: u32) {
4645        // SAFETY: plain scalar write through a live handle.
4646        unsafe { ffi::whiteout_m2_M2Camera_set_type(self.raw.as_ptr(), value) }
4647    }
4648
4649    pub fn field_of_view(&self) -> f32 {
4650        // SAFETY: plain scalar read through a live handle.
4651        unsafe { ffi::whiteout_m2_M2Camera_get_fieldOfView(self.raw.as_ptr()) }
4652    }
4653
4654    pub fn set_field_of_view(&mut self, value: f32) {
4655        // SAFETY: plain scalar write through a live handle.
4656        unsafe { ffi::whiteout_m2_M2Camera_set_fieldOfView(self.raw.as_ptr(), value) }
4657    }
4658
4659    pub fn far_clip(&self) -> f32 {
4660        // SAFETY: plain scalar read through a live handle.
4661        unsafe { ffi::whiteout_m2_M2Camera_get_farClip(self.raw.as_ptr()) }
4662    }
4663
4664    pub fn set_far_clip(&mut self, value: f32) {
4665        // SAFETY: plain scalar write through a live handle.
4666        unsafe { ffi::whiteout_m2_M2Camera_set_farClip(self.raw.as_ptr(), value) }
4667    }
4668
4669    pub fn near_clip(&self) -> f32 {
4670        // SAFETY: plain scalar read through a live handle.
4671        unsafe { ffi::whiteout_m2_M2Camera_get_nearClip(self.raw.as_ptr()) }
4672    }
4673
4674    pub fn set_near_clip(&mut self, value: f32) {
4675        // SAFETY: plain scalar write through a live handle.
4676        unsafe { ffi::whiteout_m2_M2Camera_set_nearClip(self.raw.as_ptr(), value) }
4677    }
4678
4679    /// Borrows the field in place — no copy, no allocation.
4680    pub fn positions(&self) -> crate::support::Ref<'_, AnimationTrackM2CameraSpline> {
4681        // SAFETY: an interior pointer into `self`, valid for this
4682        // borrow and never freed by the `Ref`.
4683        unsafe {
4684            crate::support::Ref::new(AnimationTrackM2CameraSpline {
4685                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Camera_get_positions(
4686                    self.raw.as_ptr(),
4687                )),
4688            })
4689        }
4690    }
4691
4692    pub fn positions_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackM2CameraSpline> {
4693        // SAFETY: as above; `&mut self` guarantees exclusivity.
4694        unsafe {
4695            crate::support::RefMut::new(AnimationTrackM2CameraSpline {
4696                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Camera_get_positions(
4697                    self.raw.as_ptr(),
4698                )),
4699            })
4700        }
4701    }
4702
4703    pub fn position_base(&self) -> crate::math::Vector3f {
4704        // SAFETY: the getter returns an interior pointer to a
4705        // layout-identical POD; we copy it out immediately.
4706        unsafe {
4707            *(ffi::whiteout_m2_M2Camera_get_positionBase(self.raw.as_ptr())
4708                as *const crate::math::Vector3f)
4709        }
4710    }
4711
4712    pub fn set_position_base(&mut self, value: crate::math::Vector3f) {
4713        // SAFETY: as above, in the other direction.
4714        unsafe {
4715            ffi::whiteout_m2_M2Camera_set_positionBase(
4716                self.raw.as_ptr(),
4717                &value as *const crate::math::Vector3f as *const _,
4718            )
4719        }
4720    }
4721
4722    /// Borrows the field in place — no copy, no allocation.
4723    pub fn target_positions(&self) -> crate::support::Ref<'_, AnimationTrackM2CameraSpline> {
4724        // SAFETY: an interior pointer into `self`, valid for this
4725        // borrow and never freed by the `Ref`.
4726        unsafe {
4727            crate::support::Ref::new(AnimationTrackM2CameraSpline {
4728                raw: core::ptr::NonNull::new_unchecked(
4729                    ffi::whiteout_m2_M2Camera_get_targetPositions(self.raw.as_ptr()),
4730                ),
4731            })
4732        }
4733    }
4734
4735    pub fn target_positions_mut(
4736        &mut self,
4737    ) -> crate::support::RefMut<'_, AnimationTrackM2CameraSpline> {
4738        // SAFETY: as above; `&mut self` guarantees exclusivity.
4739        unsafe {
4740            crate::support::RefMut::new(AnimationTrackM2CameraSpline {
4741                raw: core::ptr::NonNull::new_unchecked(
4742                    ffi::whiteout_m2_M2Camera_get_targetPositions(self.raw.as_ptr()),
4743                ),
4744            })
4745        }
4746    }
4747
4748    pub fn target_position_base(&self) -> crate::math::Vector3f {
4749        // SAFETY: the getter returns an interior pointer to a
4750        // layout-identical POD; we copy it out immediately.
4751        unsafe {
4752            *(ffi::whiteout_m2_M2Camera_get_targetPositionBase(self.raw.as_ptr())
4753                as *const crate::math::Vector3f)
4754        }
4755    }
4756
4757    pub fn set_target_position_base(&mut self, value: crate::math::Vector3f) {
4758        // SAFETY: as above, in the other direction.
4759        unsafe {
4760            ffi::whiteout_m2_M2Camera_set_targetPositionBase(
4761                self.raw.as_ptr(),
4762                &value as *const crate::math::Vector3f as *const _,
4763            )
4764        }
4765    }
4766
4767    /// Borrows the field in place — no copy, no allocation.
4768    pub fn roll(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
4769        // SAFETY: an interior pointer into `self`, valid for this
4770        // borrow and never freed by the `Ref`.
4771        unsafe {
4772            crate::support::Ref::new(AnimationTrackF32 {
4773                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Camera_get_roll(
4774                    self.raw.as_ptr(),
4775                )),
4776            })
4777        }
4778    }
4779
4780    pub fn roll_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4781        // SAFETY: as above; `&mut self` guarantees exclusivity.
4782        unsafe {
4783            crate::support::RefMut::new(AnimationTrackF32 {
4784                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Camera_get_roll(
4785                    self.raw.as_ptr(),
4786                )),
4787            })
4788        }
4789    }
4790
4791    /// Borrows the field in place — no copy, no allocation.
4792    pub fn field_of_view_track(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
4793        // SAFETY: an interior pointer into `self`, valid for this
4794        // borrow and never freed by the `Ref`.
4795        unsafe {
4796            crate::support::Ref::new(AnimationTrackF32 {
4797                raw: core::ptr::NonNull::new_unchecked(
4798                    ffi::whiteout_m2_M2Camera_get_fieldOfViewTrack(self.raw.as_ptr()),
4799                ),
4800            })
4801        }
4802    }
4803
4804    pub fn field_of_view_track_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
4805        // SAFETY: as above; `&mut self` guarantees exclusivity.
4806        unsafe {
4807            crate::support::RefMut::new(AnimationTrackF32 {
4808                raw: core::ptr::NonNull::new_unchecked(
4809                    ffi::whiteout_m2_M2Camera_get_fieldOfViewTrack(self.raw.as_ptr()),
4810                ),
4811            })
4812        }
4813    }
4814}
4815
4816impl Default for Camera {
4817    fn default() -> Self {
4818        Self::new()
4819    }
4820}
4821
4822pub struct Attachment {
4823    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Attachment>,
4824}
4825
4826impl Drop for Attachment {
4827    fn drop(&mut self) {
4828        // SAFETY: `raw` came from a native constructor and Drop runs once.
4829        unsafe { ffi::whiteout_m2_M2Attachment_delete(self.raw.as_ptr()) }
4830    }
4831}
4832
4833impl Attachment {
4834    /// # Safety
4835    /// `raw` must be a live handle this value takes ownership of.
4836    #[allow(dead_code)] // used by whichever methods return this type
4837    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Attachment) -> Option<Self> {
4838        core::ptr::NonNull::new(raw).map(|raw| Attachment { raw })
4839    }
4840}
4841
4842// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4843// is deliberately NOT implemented — the C++ types make no documented
4844// guarantee about concurrent use, and claiming one we haven't verified
4845// would be unsound. See `@bind thread_safe` in the plan.
4846unsafe impl Send for Attachment {}
4847
4848impl core::fmt::Debug for Attachment {
4849    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4850        f.debug_struct("Attachment").finish_non_exhaustive()
4851    }
4852}
4853
4854impl Attachment {
4855    /// # Panics
4856    /// Panics if the native allocation fails.
4857    pub fn new() -> Self {
4858        // SAFETY: the native constructor returns a live handle; a null here
4859        // means the library is unusable.
4860        unsafe {
4861            let raw = ffi::whiteout_m2_M2Attachment_new();
4862            Self::from_raw(raw).expect("native Attachment allocation failed")
4863        }
4864    }
4865
4866    pub fn id(&self) -> u32 {
4867        // SAFETY: plain scalar read through a live handle.
4868        unsafe { ffi::whiteout_m2_M2Attachment_get_id(self.raw.as_ptr()) }
4869    }
4870
4871    pub fn set_id(&mut self, value: u32) {
4872        // SAFETY: plain scalar write through a live handle.
4873        unsafe { ffi::whiteout_m2_M2Attachment_set_id(self.raw.as_ptr(), value) }
4874    }
4875
4876    pub fn bone_id(&self) -> u16 {
4877        // SAFETY: plain scalar read through a live handle.
4878        unsafe { ffi::whiteout_m2_M2Attachment_get_boneId(self.raw.as_ptr()) }
4879    }
4880
4881    pub fn set_bone_id(&mut self, value: u16) {
4882        // SAFETY: plain scalar write through a live handle.
4883        unsafe { ffi::whiteout_m2_M2Attachment_set_boneId(self.raw.as_ptr(), value) }
4884    }
4885
4886    pub fn unknown(&self) -> u16 {
4887        // SAFETY: plain scalar read through a live handle.
4888        unsafe { ffi::whiteout_m2_M2Attachment_get_unknown(self.raw.as_ptr()) }
4889    }
4890
4891    pub fn set_unknown(&mut self, value: u16) {
4892        // SAFETY: plain scalar write through a live handle.
4893        unsafe { ffi::whiteout_m2_M2Attachment_set_unknown(self.raw.as_ptr(), value) }
4894    }
4895
4896    pub fn position(&self) -> crate::math::Vector3f {
4897        // SAFETY: the getter returns an interior pointer to a
4898        // layout-identical POD; we copy it out immediately.
4899        unsafe {
4900            *(ffi::whiteout_m2_M2Attachment_get_position(self.raw.as_ptr())
4901                as *const crate::math::Vector3f)
4902        }
4903    }
4904
4905    pub fn set_position(&mut self, value: crate::math::Vector3f) {
4906        // SAFETY: as above, in the other direction.
4907        unsafe {
4908            ffi::whiteout_m2_M2Attachment_set_position(
4909                self.raw.as_ptr(),
4910                &value as *const crate::math::Vector3f as *const _,
4911            )
4912        }
4913    }
4914
4915    /// Borrows the field in place — no copy, no allocation.
4916    pub fn animate(&self) -> crate::support::Ref<'_, AnimationTrackU8> {
4917        // SAFETY: an interior pointer into `self`, valid for this
4918        // borrow and never freed by the `Ref`.
4919        unsafe {
4920            crate::support::Ref::new(AnimationTrackU8 {
4921                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Attachment_get_animate(
4922                    self.raw.as_ptr(),
4923                )),
4924            })
4925        }
4926    }
4927
4928    pub fn animate_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackU8> {
4929        // SAFETY: as above; `&mut self` guarantees exclusivity.
4930        unsafe {
4931            crate::support::RefMut::new(AnimationTrackU8 {
4932                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Attachment_get_animate(
4933                    self.raw.as_ptr(),
4934                )),
4935            })
4936        }
4937    }
4938}
4939
4940impl Default for Attachment {
4941    fn default() -> Self {
4942        Self::new()
4943    }
4944}
4945
4946pub struct RibbonEmitter {
4947    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2RibbonEmitter>,
4948}
4949
4950impl Drop for RibbonEmitter {
4951    fn drop(&mut self) {
4952        // SAFETY: `raw` came from a native constructor and Drop runs once.
4953        unsafe { ffi::whiteout_m2_M2RibbonEmitter_delete(self.raw.as_ptr()) }
4954    }
4955}
4956
4957impl RibbonEmitter {
4958    /// # Safety
4959    /// `raw` must be a live handle this value takes ownership of.
4960    #[allow(dead_code)] // used by whichever methods return this type
4961    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2RibbonEmitter) -> Option<Self> {
4962        core::ptr::NonNull::new(raw).map(|raw| RibbonEmitter { raw })
4963    }
4964}
4965
4966// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
4967// is deliberately NOT implemented — the C++ types make no documented
4968// guarantee about concurrent use, and claiming one we haven't verified
4969// would be unsound. See `@bind thread_safe` in the plan.
4970unsafe impl Send for RibbonEmitter {}
4971
4972impl core::fmt::Debug for RibbonEmitter {
4973    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4974        f.debug_struct("RibbonEmitter").finish_non_exhaustive()
4975    }
4976}
4977
4978impl RibbonEmitter {
4979    /// # Panics
4980    /// Panics if the native allocation fails.
4981    pub fn new() -> Self {
4982        // SAFETY: the native constructor returns a live handle; a null here
4983        // means the library is unusable.
4984        unsafe {
4985            let raw = ffi::whiteout_m2_M2RibbonEmitter_new();
4986            Self::from_raw(raw).expect("native RibbonEmitter allocation failed")
4987        }
4988    }
4989
4990    pub fn ribbon_id(&self) -> u32 {
4991        // SAFETY: plain scalar read through a live handle.
4992        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_ribbonId(self.raw.as_ptr()) }
4993    }
4994
4995    pub fn set_ribbon_id(&mut self, value: u32) {
4996        // SAFETY: plain scalar write through a live handle.
4997        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_ribbonId(self.raw.as_ptr(), value) }
4998    }
4999
5000    pub fn bone_id(&self) -> u32 {
5001        // SAFETY: plain scalar read through a live handle.
5002        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_boneId(self.raw.as_ptr()) }
5003    }
5004
5005    pub fn set_bone_id(&mut self, value: u32) {
5006        // SAFETY: plain scalar write through a live handle.
5007        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_boneId(self.raw.as_ptr(), value) }
5008    }
5009
5010    pub fn position(&self) -> crate::math::Vector3f {
5011        // SAFETY: the getter returns an interior pointer to a
5012        // layout-identical POD; we copy it out immediately.
5013        unsafe {
5014            *(ffi::whiteout_m2_M2RibbonEmitter_get_position(self.raw.as_ptr())
5015                as *const crate::math::Vector3f)
5016        }
5017    }
5018
5019    pub fn set_position(&mut self, value: crate::math::Vector3f) {
5020        // SAFETY: as above, in the other direction.
5021        unsafe {
5022            ffi::whiteout_m2_M2RibbonEmitter_set_position(
5023                self.raw.as_ptr(),
5024                &value as *const crate::math::Vector3f as *const _,
5025            )
5026        }
5027    }
5028
5029    /// Zero-copy view of the underlying `std::vector`.
5030    pub fn texture_indices(&self) -> &[u16] {
5031        // SAFETY: `_data`/`_count` describe one contiguous C++
5032        // allocation, borrowed for as long as `self` is.
5033        unsafe {
5034            let n = ffi::whiteout_m2_M2RibbonEmitter_get_textureIndices_count(self.raw.as_ptr());
5035            let p = ffi::whiteout_m2_M2RibbonEmitter_get_textureIndices_data(self.raw.as_ptr());
5036            if p.is_null() || n == 0 {
5037                &[]
5038            } else {
5039                core::slice::from_raw_parts(p, n)
5040            }
5041        }
5042    }
5043
5044    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
5045    pub fn texture_indices_mut(&mut self) -> &mut [u16] {
5046        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
5047        unsafe {
5048            let n = ffi::whiteout_m2_M2RibbonEmitter_get_textureIndices_count(self.raw.as_ptr());
5049            let p = ffi::whiteout_m2_M2RibbonEmitter_get_textureIndices_data(self.raw.as_ptr())
5050                as *mut u16;
5051            if p.is_null() || n == 0 {
5052                &mut []
5053            } else {
5054                core::slice::from_raw_parts_mut(p, n)
5055            }
5056        }
5057    }
5058
5059    pub fn set_texture_indices(&mut self, values: &[u16]) {
5060        // SAFETY: the native side copies `values` before returning.
5061        unsafe {
5062            ffi::whiteout_m2_M2RibbonEmitter_assign_textureIndices(
5063                self.raw.as_ptr(),
5064                values.as_ptr() as *const _,
5065                values.len(),
5066            )
5067        }
5068    }
5069
5070    pub fn resize_texture_indices(&mut self, count: usize) {
5071        // SAFETY: reallocation is safe here precisely because
5072        // `&mut self` means no slice borrow is outstanding.
5073        unsafe { ffi::whiteout_m2_M2RibbonEmitter_resize_textureIndices(self.raw.as_ptr(), count) }
5074    }
5075
5076    /// Zero-copy view of the underlying `std::vector`.
5077    pub fn material_indices(&self) -> &[u16] {
5078        // SAFETY: `_data`/`_count` describe one contiguous C++
5079        // allocation, borrowed for as long as `self` is.
5080        unsafe {
5081            let n = ffi::whiteout_m2_M2RibbonEmitter_get_materialIndices_count(self.raw.as_ptr());
5082            let p = ffi::whiteout_m2_M2RibbonEmitter_get_materialIndices_data(self.raw.as_ptr());
5083            if p.is_null() || n == 0 {
5084                &[]
5085            } else {
5086                core::slice::from_raw_parts(p, n)
5087            }
5088        }
5089    }
5090
5091    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
5092    pub fn material_indices_mut(&mut self) -> &mut [u16] {
5093        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
5094        unsafe {
5095            let n = ffi::whiteout_m2_M2RibbonEmitter_get_materialIndices_count(self.raw.as_ptr());
5096            let p = ffi::whiteout_m2_M2RibbonEmitter_get_materialIndices_data(self.raw.as_ptr())
5097                as *mut u16;
5098            if p.is_null() || n == 0 {
5099                &mut []
5100            } else {
5101                core::slice::from_raw_parts_mut(p, n)
5102            }
5103        }
5104    }
5105
5106    pub fn set_material_indices(&mut self, values: &[u16]) {
5107        // SAFETY: the native side copies `values` before returning.
5108        unsafe {
5109            ffi::whiteout_m2_M2RibbonEmitter_assign_materialIndices(
5110                self.raw.as_ptr(),
5111                values.as_ptr() as *const _,
5112                values.len(),
5113            )
5114        }
5115    }
5116
5117    pub fn resize_material_indices(&mut self, count: usize) {
5118        // SAFETY: reallocation is safe here precisely because
5119        // `&mut self` means no slice borrow is outstanding.
5120        unsafe { ffi::whiteout_m2_M2RibbonEmitter_resize_materialIndices(self.raw.as_ptr(), count) }
5121    }
5122
5123    /// Borrows the field in place — no copy, no allocation.
5124    pub fn color_track(&self) -> crate::support::Ref<'_, AnimationTrackVector3f> {
5125        // SAFETY: an interior pointer into `self`, valid for this
5126        // borrow and never freed by the `Ref`.
5127        unsafe {
5128            crate::support::Ref::new(AnimationTrackVector3f {
5129                raw: core::ptr::NonNull::new_unchecked(
5130                    ffi::whiteout_m2_M2RibbonEmitter_get_colorTrack(self.raw.as_ptr()),
5131                ),
5132            })
5133        }
5134    }
5135
5136    pub fn color_track_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackVector3f> {
5137        // SAFETY: as above; `&mut self` guarantees exclusivity.
5138        unsafe {
5139            crate::support::RefMut::new(AnimationTrackVector3f {
5140                raw: core::ptr::NonNull::new_unchecked(
5141                    ffi::whiteout_m2_M2RibbonEmitter_get_colorTrack(self.raw.as_ptr()),
5142                ),
5143            })
5144        }
5145    }
5146
5147    /// Borrows the field in place — no copy, no allocation.
5148    pub fn alpha_track(&self) -> crate::support::Ref<'_, AnimationTrackI16> {
5149        // SAFETY: an interior pointer into `self`, valid for this
5150        // borrow and never freed by the `Ref`.
5151        unsafe {
5152            crate::support::Ref::new(AnimationTrackI16 {
5153                raw: core::ptr::NonNull::new_unchecked(
5154                    ffi::whiteout_m2_M2RibbonEmitter_get_alphaTrack(self.raw.as_ptr()),
5155                ),
5156            })
5157        }
5158    }
5159
5160    pub fn alpha_track_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackI16> {
5161        // SAFETY: as above; `&mut self` guarantees exclusivity.
5162        unsafe {
5163            crate::support::RefMut::new(AnimationTrackI16 {
5164                raw: core::ptr::NonNull::new_unchecked(
5165                    ffi::whiteout_m2_M2RibbonEmitter_get_alphaTrack(self.raw.as_ptr()),
5166                ),
5167            })
5168        }
5169    }
5170
5171    /// Borrows the field in place — no copy, no allocation.
5172    pub fn height_above(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5173        // SAFETY: an interior pointer into `self`, valid for this
5174        // borrow and never freed by the `Ref`.
5175        unsafe {
5176            crate::support::Ref::new(AnimationTrackF32 {
5177                raw: core::ptr::NonNull::new_unchecked(
5178                    ffi::whiteout_m2_M2RibbonEmitter_get_heightAbove(self.raw.as_ptr()),
5179                ),
5180            })
5181        }
5182    }
5183
5184    pub fn height_above_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5185        // SAFETY: as above; `&mut self` guarantees exclusivity.
5186        unsafe {
5187            crate::support::RefMut::new(AnimationTrackF32 {
5188                raw: core::ptr::NonNull::new_unchecked(
5189                    ffi::whiteout_m2_M2RibbonEmitter_get_heightAbove(self.raw.as_ptr()),
5190                ),
5191            })
5192        }
5193    }
5194
5195    /// Borrows the field in place — no copy, no allocation.
5196    pub fn height_below(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5197        // SAFETY: an interior pointer into `self`, valid for this
5198        // borrow and never freed by the `Ref`.
5199        unsafe {
5200            crate::support::Ref::new(AnimationTrackF32 {
5201                raw: core::ptr::NonNull::new_unchecked(
5202                    ffi::whiteout_m2_M2RibbonEmitter_get_heightBelow(self.raw.as_ptr()),
5203                ),
5204            })
5205        }
5206    }
5207
5208    pub fn height_below_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5209        // SAFETY: as above; `&mut self` guarantees exclusivity.
5210        unsafe {
5211            crate::support::RefMut::new(AnimationTrackF32 {
5212                raw: core::ptr::NonNull::new_unchecked(
5213                    ffi::whiteout_m2_M2RibbonEmitter_get_heightBelow(self.raw.as_ptr()),
5214                ),
5215            })
5216        }
5217    }
5218
5219    pub fn edges_per_second(&self) -> f32 {
5220        // SAFETY: plain scalar read through a live handle.
5221        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_edgesPerSecond(self.raw.as_ptr()) }
5222    }
5223
5224    pub fn set_edges_per_second(&mut self, value: f32) {
5225        // SAFETY: plain scalar write through a live handle.
5226        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_edgesPerSecond(self.raw.as_ptr(), value) }
5227    }
5228
5229    pub fn edge_lifetime(&self) -> f32 {
5230        // SAFETY: plain scalar read through a live handle.
5231        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_edgeLifetime(self.raw.as_ptr()) }
5232    }
5233
5234    pub fn set_edge_lifetime(&mut self, value: f32) {
5235        // SAFETY: plain scalar write through a live handle.
5236        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_edgeLifetime(self.raw.as_ptr(), value) }
5237    }
5238
5239    pub fn gravity(&self) -> f32 {
5240        // SAFETY: plain scalar read through a live handle.
5241        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_gravity(self.raw.as_ptr()) }
5242    }
5243
5244    pub fn set_gravity(&mut self, value: f32) {
5245        // SAFETY: plain scalar write through a live handle.
5246        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_gravity(self.raw.as_ptr(), value) }
5247    }
5248
5249    pub fn texture_rows(&self) -> u16 {
5250        // SAFETY: plain scalar read through a live handle.
5251        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_textureRows(self.raw.as_ptr()) }
5252    }
5253
5254    pub fn set_texture_rows(&mut self, value: u16) {
5255        // SAFETY: plain scalar write through a live handle.
5256        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_textureRows(self.raw.as_ptr(), value) }
5257    }
5258
5259    pub fn texture_cols(&self) -> u16 {
5260        // SAFETY: plain scalar read through a live handle.
5261        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_textureCols(self.raw.as_ptr()) }
5262    }
5263
5264    pub fn set_texture_cols(&mut self, value: u16) {
5265        // SAFETY: plain scalar write through a live handle.
5266        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_textureCols(self.raw.as_ptr(), value) }
5267    }
5268
5269    /// Borrows the field in place — no copy, no allocation.
5270    pub fn tex_slot(&self) -> crate::support::Ref<'_, AnimationTrackU16> {
5271        // SAFETY: an interior pointer into `self`, valid for this
5272        // borrow and never freed by the `Ref`.
5273        unsafe {
5274            crate::support::Ref::new(AnimationTrackU16 {
5275                raw: core::ptr::NonNull::new_unchecked(
5276                    ffi::whiteout_m2_M2RibbonEmitter_get_texSlot(self.raw.as_ptr()),
5277                ),
5278            })
5279        }
5280    }
5281
5282    pub fn tex_slot_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackU16> {
5283        // SAFETY: as above; `&mut self` guarantees exclusivity.
5284        unsafe {
5285            crate::support::RefMut::new(AnimationTrackU16 {
5286                raw: core::ptr::NonNull::new_unchecked(
5287                    ffi::whiteout_m2_M2RibbonEmitter_get_texSlot(self.raw.as_ptr()),
5288                ),
5289            })
5290        }
5291    }
5292
5293    /// Borrows the field in place — no copy, no allocation.
5294    pub fn visibility(&self) -> crate::support::Ref<'_, AnimationTrackU8> {
5295        // SAFETY: an interior pointer into `self`, valid for this
5296        // borrow and never freed by the `Ref`.
5297        unsafe {
5298            crate::support::Ref::new(AnimationTrackU8 {
5299                raw: core::ptr::NonNull::new_unchecked(
5300                    ffi::whiteout_m2_M2RibbonEmitter_get_visibility(self.raw.as_ptr()),
5301                ),
5302            })
5303        }
5304    }
5305
5306    pub fn visibility_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackU8> {
5307        // SAFETY: as above; `&mut self` guarantees exclusivity.
5308        unsafe {
5309            crate::support::RefMut::new(AnimationTrackU8 {
5310                raw: core::ptr::NonNull::new_unchecked(
5311                    ffi::whiteout_m2_M2RibbonEmitter_get_visibility(self.raw.as_ptr()),
5312                ),
5313            })
5314        }
5315    }
5316
5317    pub fn priority_plane(&self) -> i16 {
5318        // SAFETY: plain scalar read through a live handle.
5319        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_priorityPlane(self.raw.as_ptr()) }
5320    }
5321
5322    pub fn set_priority_plane(&mut self, value: i16) {
5323        // SAFETY: plain scalar write through a live handle.
5324        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_priorityPlane(self.raw.as_ptr(), value) }
5325    }
5326
5327    pub fn ribbon_color_index(&self) -> i8 {
5328        // SAFETY: plain scalar read through a live handle.
5329        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_ribbonColorIndex(self.raw.as_ptr()) }
5330    }
5331
5332    pub fn set_ribbon_color_index(&mut self, value: i8) {
5333        // SAFETY: plain scalar write through a live handle.
5334        unsafe { ffi::whiteout_m2_M2RibbonEmitter_set_ribbonColorIndex(self.raw.as_ptr(), value) }
5335    }
5336
5337    pub fn texture_transform_index(&self) -> i8 {
5338        // SAFETY: plain scalar read through a live handle.
5339        unsafe { ffi::whiteout_m2_M2RibbonEmitter_get_textureTransformIndex(self.raw.as_ptr()) }
5340    }
5341
5342    pub fn set_texture_transform_index(&mut self, value: i8) {
5343        // SAFETY: plain scalar write through a live handle.
5344        unsafe {
5345            ffi::whiteout_m2_M2RibbonEmitter_set_textureTransformIndex(self.raw.as_ptr(), value)
5346        }
5347    }
5348}
5349
5350impl Default for RibbonEmitter {
5351    fn default() -> Self {
5352        Self::new()
5353    }
5354}
5355
5356pub struct Box {
5357    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Box>,
5358}
5359
5360impl Drop for Box {
5361    fn drop(&mut self) {
5362        // SAFETY: `raw` came from a native constructor and Drop runs once.
5363        unsafe { ffi::whiteout_m2_M2Box_delete(self.raw.as_ptr()) }
5364    }
5365}
5366
5367impl Box {
5368    /// # Safety
5369    /// `raw` must be a live handle this value takes ownership of.
5370    #[allow(dead_code)] // used by whichever methods return this type
5371    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Box) -> Option<Self> {
5372        core::ptr::NonNull::new(raw).map(|raw| Box { raw })
5373    }
5374}
5375
5376// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
5377// is deliberately NOT implemented — the C++ types make no documented
5378// guarantee about concurrent use, and claiming one we haven't verified
5379// would be unsound. See `@bind thread_safe` in the plan.
5380unsafe impl Send for Box {}
5381
5382impl core::fmt::Debug for Box {
5383    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5384        f.debug_struct("Box").finish_non_exhaustive()
5385    }
5386}
5387
5388impl Box {
5389    /// # Panics
5390    /// Panics if the native allocation fails.
5391    pub fn new() -> Self {
5392        // SAFETY: the native constructor returns a live handle; a null here
5393        // means the library is unusable.
5394        unsafe {
5395            let raw = ffi::whiteout_m2_M2Box_new();
5396            Self::from_raw(raw).expect("native Box allocation failed")
5397        }
5398    }
5399
5400    pub fn minimum(&self) -> crate::math::Vector3f {
5401        // SAFETY: the getter returns an interior pointer to a
5402        // layout-identical POD; we copy it out immediately.
5403        unsafe {
5404            *(ffi::whiteout_m2_M2Box_get_minimum(self.raw.as_ptr()) as *const crate::math::Vector3f)
5405        }
5406    }
5407
5408    pub fn set_minimum(&mut self, value: crate::math::Vector3f) {
5409        // SAFETY: as above, in the other direction.
5410        unsafe {
5411            ffi::whiteout_m2_M2Box_set_minimum(
5412                self.raw.as_ptr(),
5413                &value as *const crate::math::Vector3f as *const _,
5414            )
5415        }
5416    }
5417
5418    pub fn maximum(&self) -> crate::math::Vector3f {
5419        // SAFETY: the getter returns an interior pointer to a
5420        // layout-identical POD; we copy it out immediately.
5421        unsafe {
5422            *(ffi::whiteout_m2_M2Box_get_maximum(self.raw.as_ptr()) as *const crate::math::Vector3f)
5423        }
5424    }
5425
5426    pub fn set_maximum(&mut self, value: crate::math::Vector3f) {
5427        // SAFETY: as above, in the other direction.
5428        unsafe {
5429            ffi::whiteout_m2_M2Box_set_maximum(
5430                self.raw.as_ptr(),
5431                &value as *const crate::math::Vector3f as *const _,
5432            )
5433        }
5434    }
5435}
5436
5437impl Default for Box {
5438    fn default() -> Self {
5439        Self::new()
5440    }
5441}
5442
5443pub struct ParticleEmitter {
5444    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ParticleEmitter>,
5445}
5446
5447impl Drop for ParticleEmitter {
5448    fn drop(&mut self) {
5449        // SAFETY: `raw` came from a native constructor and Drop runs once.
5450        unsafe { ffi::whiteout_m2_M2ParticleEmitter_delete(self.raw.as_ptr()) }
5451    }
5452}
5453
5454impl ParticleEmitter {
5455    /// # Safety
5456    /// `raw` must be a live handle this value takes ownership of.
5457    #[allow(dead_code)] // used by whichever methods return this type
5458    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ParticleEmitter) -> Option<Self> {
5459        core::ptr::NonNull::new(raw).map(|raw| ParticleEmitter { raw })
5460    }
5461}
5462
5463// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
5464// is deliberately NOT implemented — the C++ types make no documented
5465// guarantee about concurrent use, and claiming one we haven't verified
5466// would be unsound. See `@bind thread_safe` in the plan.
5467unsafe impl Send for ParticleEmitter {}
5468
5469impl core::fmt::Debug for ParticleEmitter {
5470    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5471        f.debug_struct("ParticleEmitter").finish_non_exhaustive()
5472    }
5473}
5474
5475impl ParticleEmitter {
5476    /// # Panics
5477    /// Panics if the native allocation fails.
5478    pub fn new() -> Self {
5479        // SAFETY: the native constructor returns a live handle; a null here
5480        // means the library is unusable.
5481        unsafe {
5482            let raw = ffi::whiteout_m2_M2ParticleEmitter_new();
5483            Self::from_raw(raw).expect("native ParticleEmitter allocation failed")
5484        }
5485    }
5486
5487    pub fn particle_id(&self) -> u32 {
5488        // SAFETY: plain scalar read through a live handle.
5489        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_particleId(self.raw.as_ptr()) }
5490    }
5491
5492    pub fn set_particle_id(&mut self, value: u32) {
5493        // SAFETY: plain scalar write through a live handle.
5494        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_particleId(self.raw.as_ptr(), value) }
5495    }
5496
5497    pub fn flags(&self) -> ParticleFlag {
5498        // SAFETY: scalar read; a flag set accepts any bits.
5499        ParticleFlag(unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_flags(self.raw.as_ptr()) })
5500    }
5501
5502    pub fn set_flags(&mut self, value: ParticleFlag) {
5503        // SAFETY: scalar write through a live handle.
5504        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_flags(self.raw.as_ptr(), value.0) }
5505    }
5506
5507    pub fn position(&self) -> crate::math::Vector3f {
5508        // SAFETY: the getter returns an interior pointer to a
5509        // layout-identical POD; we copy it out immediately.
5510        unsafe {
5511            *(ffi::whiteout_m2_M2ParticleEmitter_get_position(self.raw.as_ptr())
5512                as *const crate::math::Vector3f)
5513        }
5514    }
5515
5516    pub fn set_position(&mut self, value: crate::math::Vector3f) {
5517        // SAFETY: as above, in the other direction.
5518        unsafe {
5519            ffi::whiteout_m2_M2ParticleEmitter_set_position(
5520                self.raw.as_ptr(),
5521                &value as *const crate::math::Vector3f as *const _,
5522            )
5523        }
5524    }
5525
5526    pub fn bone_id(&self) -> u16 {
5527        // SAFETY: plain scalar read through a live handle.
5528        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_boneId(self.raw.as_ptr()) }
5529    }
5530
5531    pub fn set_bone_id(&mut self, value: u16) {
5532        // SAFETY: plain scalar write through a live handle.
5533        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_boneId(self.raw.as_ptr(), value) }
5534    }
5535
5536    pub fn particle_model_filename(&self) -> String {
5537        // SAFETY: the native side hands over an owned CString.
5538        unsafe {
5539            crate::support::take_string(
5540                ffi::whiteout_m2_M2ParticleEmitter_get_particleModelFilename(self.raw.as_ptr()),
5541            )
5542        }
5543    }
5544
5545    pub fn set_particle_model_filename(&mut self, value: &str) {
5546        let value = std::ffi::CString::new(value).unwrap_or_default();
5547        // SAFETY: the pointer outlives the call.
5548        unsafe {
5549            ffi::whiteout_m2_M2ParticleEmitter_set_particleModelFilename(
5550                self.raw.as_ptr(),
5551                value.as_ptr(),
5552            )
5553        }
5554    }
5555
5556    pub fn child_emitters_model_filename(&self) -> String {
5557        // SAFETY: the native side hands over an owned CString.
5558        unsafe {
5559            crate::support::take_string(
5560                ffi::whiteout_m2_M2ParticleEmitter_get_childEmittersModelFilename(
5561                    self.raw.as_ptr(),
5562                ),
5563            )
5564        }
5565    }
5566
5567    pub fn set_child_emitters_model_filename(&mut self, value: &str) {
5568        let value = std::ffi::CString::new(value).unwrap_or_default();
5569        // SAFETY: the pointer outlives the call.
5570        unsafe {
5571            ffi::whiteout_m2_M2ParticleEmitter_set_childEmittersModelFilename(
5572                self.raw.as_ptr(),
5573                value.as_ptr(),
5574            )
5575        }
5576    }
5577
5578    pub fn blending_type(&self) -> ParticleBlending {
5579        // SAFETY: scalar read; the discriminant is validated below.
5580        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_blendingType(self.raw.as_ptr()) }
5581            .try_into()
5582            .expect("unknown enum discriminant from the native library")
5583    }
5584
5585    pub fn set_blending_type(&mut self, value: ParticleBlending) {
5586        // SAFETY: scalar write through a live handle.
5587        unsafe {
5588            ffi::whiteout_m2_M2ParticleEmitter_set_blendingType(self.raw.as_ptr(), value as i32)
5589        }
5590    }
5591
5592    pub fn emitter_type(&self) -> ParticleEmitterType {
5593        // SAFETY: scalar read; the discriminant is validated below.
5594        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_emitterType(self.raw.as_ptr()) }
5595            .try_into()
5596            .expect("unknown enum discriminant from the native library")
5597    }
5598
5599    pub fn set_emitter_type(&mut self, value: ParticleEmitterType) {
5600        // SAFETY: scalar write through a live handle.
5601        unsafe {
5602            ffi::whiteout_m2_M2ParticleEmitter_set_emitterType(self.raw.as_ptr(), value as i32)
5603        }
5604    }
5605
5606    pub fn particle_color_index(&self) -> u16 {
5607        // SAFETY: plain scalar read through a live handle.
5608        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_particleColorIndex(self.raw.as_ptr()) }
5609    }
5610
5611    pub fn set_particle_color_index(&mut self, value: u16) {
5612        // SAFETY: plain scalar write through a live handle.
5613        unsafe {
5614            ffi::whiteout_m2_M2ParticleEmitter_set_particleColorIndex(self.raw.as_ptr(), value)
5615        }
5616    }
5617
5618    pub fn particle_type(&self) -> u8 {
5619        // SAFETY: plain scalar read through a live handle.
5620        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_particleType(self.raw.as_ptr()) }
5621    }
5622
5623    pub fn set_particle_type(&mut self, value: u8) {
5624        // SAFETY: plain scalar write through a live handle.
5625        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_particleType(self.raw.as_ptr(), value) }
5626    }
5627
5628    pub fn head_or_tail(&self) -> u8 {
5629        // SAFETY: plain scalar read through a live handle.
5630        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_headOrTail(self.raw.as_ptr()) }
5631    }
5632
5633    pub fn set_head_or_tail(&mut self, value: u8) {
5634        // SAFETY: plain scalar write through a live handle.
5635        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_headOrTail(self.raw.as_ptr(), value) }
5636    }
5637
5638    pub fn texture_tilerotation(&self) -> i16 {
5639        // SAFETY: plain scalar read through a live handle.
5640        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_textureTilerotation(self.raw.as_ptr()) }
5641    }
5642
5643    pub fn set_texture_tilerotation(&mut self, value: i16) {
5644        // SAFETY: plain scalar write through a live handle.
5645        unsafe {
5646            ffi::whiteout_m2_M2ParticleEmitter_set_textureTilerotation(self.raw.as_ptr(), value)
5647        }
5648    }
5649
5650    pub fn rows(&self) -> u16 {
5651        // SAFETY: plain scalar read through a live handle.
5652        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_rows(self.raw.as_ptr()) }
5653    }
5654
5655    pub fn set_rows(&mut self, value: u16) {
5656        // SAFETY: plain scalar write through a live handle.
5657        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_rows(self.raw.as_ptr(), value) }
5658    }
5659
5660    pub fn columns(&self) -> u16 {
5661        // SAFETY: plain scalar read through a live handle.
5662        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_columns(self.raw.as_ptr()) }
5663    }
5664
5665    pub fn set_columns(&mut self, value: u16) {
5666        // SAFETY: plain scalar write through a live handle.
5667        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_columns(self.raw.as_ptr(), value) }
5668    }
5669
5670    /// Borrows the field in place — no copy, no allocation.
5671    pub fn emission_speed(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5672        // SAFETY: an interior pointer into `self`, valid for this
5673        // borrow and never freed by the `Ref`.
5674        unsafe {
5675            crate::support::Ref::new(AnimationTrackF32 {
5676                raw: core::ptr::NonNull::new_unchecked(
5677                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionSpeed(self.raw.as_ptr()),
5678                ),
5679            })
5680        }
5681    }
5682
5683    pub fn emission_speed_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5684        // SAFETY: as above; `&mut self` guarantees exclusivity.
5685        unsafe {
5686            crate::support::RefMut::new(AnimationTrackF32 {
5687                raw: core::ptr::NonNull::new_unchecked(
5688                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionSpeed(self.raw.as_ptr()),
5689                ),
5690            })
5691        }
5692    }
5693
5694    /// Borrows the field in place — no copy, no allocation.
5695    pub fn speed_variation(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5696        // SAFETY: an interior pointer into `self`, valid for this
5697        // borrow and never freed by the `Ref`.
5698        unsafe {
5699            crate::support::Ref::new(AnimationTrackF32 {
5700                raw: core::ptr::NonNull::new_unchecked(
5701                    ffi::whiteout_m2_M2ParticleEmitter_get_speedVariation(self.raw.as_ptr()),
5702                ),
5703            })
5704        }
5705    }
5706
5707    pub fn speed_variation_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5708        // SAFETY: as above; `&mut self` guarantees exclusivity.
5709        unsafe {
5710            crate::support::RefMut::new(AnimationTrackF32 {
5711                raw: core::ptr::NonNull::new_unchecked(
5712                    ffi::whiteout_m2_M2ParticleEmitter_get_speedVariation(self.raw.as_ptr()),
5713                ),
5714            })
5715        }
5716    }
5717
5718    /// Borrows the field in place — no copy, no allocation.
5719    pub fn vertical_range(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5720        // SAFETY: an interior pointer into `self`, valid for this
5721        // borrow and never freed by the `Ref`.
5722        unsafe {
5723            crate::support::Ref::new(AnimationTrackF32 {
5724                raw: core::ptr::NonNull::new_unchecked(
5725                    ffi::whiteout_m2_M2ParticleEmitter_get_verticalRange(self.raw.as_ptr()),
5726                ),
5727            })
5728        }
5729    }
5730
5731    pub fn vertical_range_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5732        // SAFETY: as above; `&mut self` guarantees exclusivity.
5733        unsafe {
5734            crate::support::RefMut::new(AnimationTrackF32 {
5735                raw: core::ptr::NonNull::new_unchecked(
5736                    ffi::whiteout_m2_M2ParticleEmitter_get_verticalRange(self.raw.as_ptr()),
5737                ),
5738            })
5739        }
5740    }
5741
5742    /// Borrows the field in place — no copy, no allocation.
5743    pub fn horizontal_range(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5744        // SAFETY: an interior pointer into `self`, valid for this
5745        // borrow and never freed by the `Ref`.
5746        unsafe {
5747            crate::support::Ref::new(AnimationTrackF32 {
5748                raw: core::ptr::NonNull::new_unchecked(
5749                    ffi::whiteout_m2_M2ParticleEmitter_get_horizontalRange(self.raw.as_ptr()),
5750                ),
5751            })
5752        }
5753    }
5754
5755    pub fn horizontal_range_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5756        // SAFETY: as above; `&mut self` guarantees exclusivity.
5757        unsafe {
5758            crate::support::RefMut::new(AnimationTrackF32 {
5759                raw: core::ptr::NonNull::new_unchecked(
5760                    ffi::whiteout_m2_M2ParticleEmitter_get_horizontalRange(self.raw.as_ptr()),
5761                ),
5762            })
5763        }
5764    }
5765
5766    /// Borrows the field in place — no copy, no allocation.
5767    pub fn gravity(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5768        // SAFETY: an interior pointer into `self`, valid for this
5769        // borrow and never freed by the `Ref`.
5770        unsafe {
5771            crate::support::Ref::new(AnimationTrackF32 {
5772                raw: core::ptr::NonNull::new_unchecked(
5773                    ffi::whiteout_m2_M2ParticleEmitter_get_gravity(self.raw.as_ptr()),
5774                ),
5775            })
5776        }
5777    }
5778
5779    pub fn gravity_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5780        // SAFETY: as above; `&mut self` guarantees exclusivity.
5781        unsafe {
5782            crate::support::RefMut::new(AnimationTrackF32 {
5783                raw: core::ptr::NonNull::new_unchecked(
5784                    ffi::whiteout_m2_M2ParticleEmitter_get_gravity(self.raw.as_ptr()),
5785                ),
5786            })
5787        }
5788    }
5789
5790    /// Borrows the field in place — no copy, no allocation.
5791    pub fn lifespan(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5792        // SAFETY: an interior pointer into `self`, valid for this
5793        // borrow and never freed by the `Ref`.
5794        unsafe {
5795            crate::support::Ref::new(AnimationTrackF32 {
5796                raw: core::ptr::NonNull::new_unchecked(
5797                    ffi::whiteout_m2_M2ParticleEmitter_get_lifespan(self.raw.as_ptr()),
5798                ),
5799            })
5800        }
5801    }
5802
5803    pub fn lifespan_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5804        // SAFETY: as above; `&mut self` guarantees exclusivity.
5805        unsafe {
5806            crate::support::RefMut::new(AnimationTrackF32 {
5807                raw: core::ptr::NonNull::new_unchecked(
5808                    ffi::whiteout_m2_M2ParticleEmitter_get_lifespan(self.raw.as_ptr()),
5809                ),
5810            })
5811        }
5812    }
5813
5814    pub fn lifespan_variation(&self) -> f32 {
5815        // SAFETY: plain scalar read through a live handle.
5816        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_lifespanVariation(self.raw.as_ptr()) }
5817    }
5818
5819    pub fn set_lifespan_variation(&mut self, value: f32) {
5820        // SAFETY: plain scalar write through a live handle.
5821        unsafe {
5822            ffi::whiteout_m2_M2ParticleEmitter_set_lifespanVariation(self.raw.as_ptr(), value)
5823        }
5824    }
5825
5826    /// Borrows the field in place — no copy, no allocation.
5827    pub fn emission_rate(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5828        // SAFETY: an interior pointer into `self`, valid for this
5829        // borrow and never freed by the `Ref`.
5830        unsafe {
5831            crate::support::Ref::new(AnimationTrackF32 {
5832                raw: core::ptr::NonNull::new_unchecked(
5833                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionRate(self.raw.as_ptr()),
5834                ),
5835            })
5836        }
5837    }
5838
5839    pub fn emission_rate_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5840        // SAFETY: as above; `&mut self` guarantees exclusivity.
5841        unsafe {
5842            crate::support::RefMut::new(AnimationTrackF32 {
5843                raw: core::ptr::NonNull::new_unchecked(
5844                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionRate(self.raw.as_ptr()),
5845                ),
5846            })
5847        }
5848    }
5849
5850    pub fn emission_rate_variation(&self) -> f32 {
5851        // SAFETY: plain scalar read through a live handle.
5852        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_emissionRateVariation(self.raw.as_ptr()) }
5853    }
5854
5855    pub fn set_emission_rate_variation(&mut self, value: f32) {
5856        // SAFETY: plain scalar write through a live handle.
5857        unsafe {
5858            ffi::whiteout_m2_M2ParticleEmitter_set_emissionRateVariation(self.raw.as_ptr(), value)
5859        }
5860    }
5861
5862    /// Borrows the field in place — no copy, no allocation.
5863    pub fn emission_area_width(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5864        // SAFETY: an interior pointer into `self`, valid for this
5865        // borrow and never freed by the `Ref`.
5866        unsafe {
5867            crate::support::Ref::new(AnimationTrackF32 {
5868                raw: core::ptr::NonNull::new_unchecked(
5869                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionAreaWidth(self.raw.as_ptr()),
5870                ),
5871            })
5872        }
5873    }
5874
5875    pub fn emission_area_width_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5876        // SAFETY: as above; `&mut self` guarantees exclusivity.
5877        unsafe {
5878            crate::support::RefMut::new(AnimationTrackF32 {
5879                raw: core::ptr::NonNull::new_unchecked(
5880                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionAreaWidth(self.raw.as_ptr()),
5881                ),
5882            })
5883        }
5884    }
5885
5886    /// Borrows the field in place — no copy, no allocation.
5887    pub fn emission_area_length(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5888        // SAFETY: an interior pointer into `self`, valid for this
5889        // borrow and never freed by the `Ref`.
5890        unsafe {
5891            crate::support::Ref::new(AnimationTrackF32 {
5892                raw: core::ptr::NonNull::new_unchecked(
5893                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionAreaLength(self.raw.as_ptr()),
5894                ),
5895            })
5896        }
5897    }
5898
5899    pub fn emission_area_length_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5900        // SAFETY: as above; `&mut self` guarantees exclusivity.
5901        unsafe {
5902            crate::support::RefMut::new(AnimationTrackF32 {
5903                raw: core::ptr::NonNull::new_unchecked(
5904                    ffi::whiteout_m2_M2ParticleEmitter_get_emissionAreaLength(self.raw.as_ptr()),
5905                ),
5906            })
5907        }
5908    }
5909
5910    /// Borrows the field in place — no copy, no allocation.
5911    pub fn z_source(&self) -> crate::support::Ref<'_, AnimationTrackF32> {
5912        // SAFETY: an interior pointer into `self`, valid for this
5913        // borrow and never freed by the `Ref`.
5914        unsafe {
5915            crate::support::Ref::new(AnimationTrackF32 {
5916                raw: core::ptr::NonNull::new_unchecked(
5917                    ffi::whiteout_m2_M2ParticleEmitter_get_zSource(self.raw.as_ptr()),
5918                ),
5919            })
5920        }
5921    }
5922
5923    pub fn z_source_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackF32> {
5924        // SAFETY: as above; `&mut self` guarantees exclusivity.
5925        unsafe {
5926            crate::support::RefMut::new(AnimationTrackF32 {
5927                raw: core::ptr::NonNull::new_unchecked(
5928                    ffi::whiteout_m2_M2ParticleEmitter_get_zSource(self.raw.as_ptr()),
5929                ),
5930            })
5931        }
5932    }
5933
5934    /// Borrows the field in place — no copy, no allocation.
5935    pub fn color_track(&self) -> crate::support::Ref<'_, ParticleAnimationTrackVector3f> {
5936        // SAFETY: an interior pointer into `self`, valid for this
5937        // borrow and never freed by the `Ref`.
5938        unsafe {
5939            crate::support::Ref::new(ParticleAnimationTrackVector3f {
5940                raw: core::ptr::NonNull::new_unchecked(
5941                    ffi::whiteout_m2_M2ParticleEmitter_get_colorTrack(self.raw.as_ptr()),
5942                ),
5943            })
5944        }
5945    }
5946
5947    pub fn color_track_mut(
5948        &mut self,
5949    ) -> crate::support::RefMut<'_, ParticleAnimationTrackVector3f> {
5950        // SAFETY: as above; `&mut self` guarantees exclusivity.
5951        unsafe {
5952            crate::support::RefMut::new(ParticleAnimationTrackVector3f {
5953                raw: core::ptr::NonNull::new_unchecked(
5954                    ffi::whiteout_m2_M2ParticleEmitter_get_colorTrack(self.raw.as_ptr()),
5955                ),
5956            })
5957        }
5958    }
5959
5960    /// Borrows the field in place — no copy, no allocation.
5961    pub fn scale_track(&self) -> crate::support::Ref<'_, ParticleAnimationTrackVector2f> {
5962        // SAFETY: an interior pointer into `self`, valid for this
5963        // borrow and never freed by the `Ref`.
5964        unsafe {
5965            crate::support::Ref::new(ParticleAnimationTrackVector2f {
5966                raw: core::ptr::NonNull::new_unchecked(
5967                    ffi::whiteout_m2_M2ParticleEmitter_get_scaleTrack(self.raw.as_ptr()),
5968                ),
5969            })
5970        }
5971    }
5972
5973    pub fn scale_track_mut(
5974        &mut self,
5975    ) -> crate::support::RefMut<'_, ParticleAnimationTrackVector2f> {
5976        // SAFETY: as above; `&mut self` guarantees exclusivity.
5977        unsafe {
5978            crate::support::RefMut::new(ParticleAnimationTrackVector2f {
5979                raw: core::ptr::NonNull::new_unchecked(
5980                    ffi::whiteout_m2_M2ParticleEmitter_get_scaleTrack(self.raw.as_ptr()),
5981                ),
5982            })
5983        }
5984    }
5985
5986    pub fn scale_vary(&self) -> crate::math::Vector2f {
5987        // SAFETY: the getter returns an interior pointer to a
5988        // layout-identical POD; we copy it out immediately.
5989        unsafe {
5990            *(ffi::whiteout_m2_M2ParticleEmitter_get_scaleVary(self.raw.as_ptr())
5991                as *const crate::math::Vector2f)
5992        }
5993    }
5994
5995    pub fn set_scale_vary(&mut self, value: crate::math::Vector2f) {
5996        // SAFETY: as above, in the other direction.
5997        unsafe {
5998            ffi::whiteout_m2_M2ParticleEmitter_set_scaleVary(
5999                self.raw.as_ptr(),
6000                &value as *const crate::math::Vector2f as *const _,
6001            )
6002        }
6003    }
6004
6005    pub fn tail_length(&self) -> f32 {
6006        // SAFETY: plain scalar read through a live handle.
6007        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_tailLength(self.raw.as_ptr()) }
6008    }
6009
6010    pub fn set_tail_length(&mut self, value: f32) {
6011        // SAFETY: plain scalar write through a live handle.
6012        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_tailLength(self.raw.as_ptr(), value) }
6013    }
6014
6015    pub fn twinkle_speed(&self) -> f32 {
6016        // SAFETY: plain scalar read through a live handle.
6017        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_twinkleSpeed(self.raw.as_ptr()) }
6018    }
6019
6020    pub fn set_twinkle_speed(&mut self, value: f32) {
6021        // SAFETY: plain scalar write through a live handle.
6022        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_twinkleSpeed(self.raw.as_ptr(), value) }
6023    }
6024
6025    pub fn twinkle_percent(&self) -> f32 {
6026        // SAFETY: plain scalar read through a live handle.
6027        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_twinklePercent(self.raw.as_ptr()) }
6028    }
6029
6030    pub fn set_twinkle_percent(&mut self, value: f32) {
6031        // SAFETY: plain scalar write through a live handle.
6032        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_twinklePercent(self.raw.as_ptr(), value) }
6033    }
6034
6035    pub fn twinkle_scale(&self) -> crate::math::Vector2f {
6036        // SAFETY: the getter returns an interior pointer to a
6037        // layout-identical POD; we copy it out immediately.
6038        unsafe {
6039            *(ffi::whiteout_m2_M2ParticleEmitter_get_twinkleScale(self.raw.as_ptr())
6040                as *const crate::math::Vector2f)
6041        }
6042    }
6043
6044    pub fn set_twinkle_scale(&mut self, value: crate::math::Vector2f) {
6045        // SAFETY: as above, in the other direction.
6046        unsafe {
6047            ffi::whiteout_m2_M2ParticleEmitter_set_twinkleScale(
6048                self.raw.as_ptr(),
6049                &value as *const crate::math::Vector2f as *const _,
6050            )
6051        }
6052    }
6053
6054    pub fn inherit_velocity_scale(&self) -> f32 {
6055        // SAFETY: plain scalar read through a live handle.
6056        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_inheritVelocityScale(self.raw.as_ptr()) }
6057    }
6058
6059    pub fn set_inherit_velocity_scale(&mut self, value: f32) {
6060        // SAFETY: plain scalar write through a live handle.
6061        unsafe {
6062            ffi::whiteout_m2_M2ParticleEmitter_set_inheritVelocityScale(self.raw.as_ptr(), value)
6063        }
6064    }
6065
6066    pub fn drag(&self) -> f32 {
6067        // SAFETY: plain scalar read through a live handle.
6068        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_drag(self.raw.as_ptr()) }
6069    }
6070
6071    pub fn set_drag(&mut self, value: f32) {
6072        // SAFETY: plain scalar write through a live handle.
6073        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_drag(self.raw.as_ptr(), value) }
6074    }
6075
6076    pub fn base_spin(&self) -> f32 {
6077        // SAFETY: plain scalar read through a live handle.
6078        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_baseSpin(self.raw.as_ptr()) }
6079    }
6080
6081    pub fn set_base_spin(&mut self, value: f32) {
6082        // SAFETY: plain scalar write through a live handle.
6083        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_baseSpin(self.raw.as_ptr(), value) }
6084    }
6085
6086    pub fn base_spin_variation(&self) -> f32 {
6087        // SAFETY: plain scalar read through a live handle.
6088        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_baseSpinVariation(self.raw.as_ptr()) }
6089    }
6090
6091    pub fn set_base_spin_variation(&mut self, value: f32) {
6092        // SAFETY: plain scalar write through a live handle.
6093        unsafe {
6094            ffi::whiteout_m2_M2ParticleEmitter_set_baseSpinVariation(self.raw.as_ptr(), value)
6095        }
6096    }
6097
6098    pub fn spin_speed(&self) -> f32 {
6099        // SAFETY: plain scalar read through a live handle.
6100        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_spinSpeed(self.raw.as_ptr()) }
6101    }
6102
6103    pub fn set_spin_speed(&mut self, value: f32) {
6104        // SAFETY: plain scalar write through a live handle.
6105        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_spinSpeed(self.raw.as_ptr(), value) }
6106    }
6107
6108    pub fn spin_speed_variation(&self) -> f32 {
6109        // SAFETY: plain scalar read through a live handle.
6110        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_spinSpeedVariation(self.raw.as_ptr()) }
6111    }
6112
6113    pub fn set_spin_speed_variation(&mut self, value: f32) {
6114        // SAFETY: plain scalar write through a live handle.
6115        unsafe {
6116            ffi::whiteout_m2_M2ParticleEmitter_set_spinSpeedVariation(self.raw.as_ptr(), value)
6117        }
6118    }
6119
6120    /// Borrows the field in place — no copy, no allocation.
6121    pub fn tumble(&self) -> crate::support::Ref<'_, Box> {
6122        // SAFETY: an interior pointer into `self`, valid for this
6123        // borrow and never freed by the `Ref`.
6124        unsafe {
6125            crate::support::Ref::new(Box {
6126                raw: core::ptr::NonNull::new_unchecked(
6127                    ffi::whiteout_m2_M2ParticleEmitter_get_tumble(self.raw.as_ptr()),
6128                ),
6129            })
6130        }
6131    }
6132
6133    pub fn tumble_mut(&mut self) -> crate::support::RefMut<'_, Box> {
6134        // SAFETY: as above; `&mut self` guarantees exclusivity.
6135        unsafe {
6136            crate::support::RefMut::new(Box {
6137                raw: core::ptr::NonNull::new_unchecked(
6138                    ffi::whiteout_m2_M2ParticleEmitter_get_tumble(self.raw.as_ptr()),
6139                ),
6140            })
6141        }
6142    }
6143
6144    pub fn wind_vector(&self) -> crate::math::Vector3f {
6145        // SAFETY: the getter returns an interior pointer to a
6146        // layout-identical POD; we copy it out immediately.
6147        unsafe {
6148            *(ffi::whiteout_m2_M2ParticleEmitter_get_windVector(self.raw.as_ptr())
6149                as *const crate::math::Vector3f)
6150        }
6151    }
6152
6153    pub fn set_wind_vector(&mut self, value: crate::math::Vector3f) {
6154        // SAFETY: as above, in the other direction.
6155        unsafe {
6156            ffi::whiteout_m2_M2ParticleEmitter_set_windVector(
6157                self.raw.as_ptr(),
6158                &value as *const crate::math::Vector3f as *const _,
6159            )
6160        }
6161    }
6162
6163    pub fn wind_time(&self) -> f32 {
6164        // SAFETY: plain scalar read through a live handle.
6165        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_windTime(self.raw.as_ptr()) }
6166    }
6167
6168    pub fn set_wind_time(&mut self, value: f32) {
6169        // SAFETY: plain scalar write through a live handle.
6170        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_windTime(self.raw.as_ptr(), value) }
6171    }
6172
6173    pub fn follow_speed_1(&self) -> f32 {
6174        // SAFETY: plain scalar read through a live handle.
6175        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_followSpeed1(self.raw.as_ptr()) }
6176    }
6177
6178    pub fn set_follow_speed_1(&mut self, value: f32) {
6179        // SAFETY: plain scalar write through a live handle.
6180        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_followSpeed1(self.raw.as_ptr(), value) }
6181    }
6182
6183    pub fn follow_scale_1(&self) -> f32 {
6184        // SAFETY: plain scalar read through a live handle.
6185        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_followScale1(self.raw.as_ptr()) }
6186    }
6187
6188    pub fn set_follow_scale_1(&mut self, value: f32) {
6189        // SAFETY: plain scalar write through a live handle.
6190        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_followScale1(self.raw.as_ptr(), value) }
6191    }
6192
6193    pub fn follow_speed_2(&self) -> f32 {
6194        // SAFETY: plain scalar read through a live handle.
6195        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_followSpeed2(self.raw.as_ptr()) }
6196    }
6197
6198    pub fn set_follow_speed_2(&mut self, value: f32) {
6199        // SAFETY: plain scalar write through a live handle.
6200        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_followSpeed2(self.raw.as_ptr(), value) }
6201    }
6202
6203    pub fn follow_scale_2(&self) -> f32 {
6204        // SAFETY: plain scalar read through a live handle.
6205        unsafe { ffi::whiteout_m2_M2ParticleEmitter_get_followScale2(self.raw.as_ptr()) }
6206    }
6207
6208    pub fn set_follow_scale_2(&mut self, value: f32) {
6209        // SAFETY: plain scalar write through a live handle.
6210        unsafe { ffi::whiteout_m2_M2ParticleEmitter_set_followScale2(self.raw.as_ptr(), value) }
6211    }
6212
6213    /// Zero-copy view of the underlying `std::vector`.
6214    pub fn spline_points(&self) -> &[crate::math::Vector3f] {
6215        // SAFETY: `_data`/`_count` describe one contiguous C++
6216        // allocation, borrowed for as long as `self` is.
6217        unsafe {
6218            let n = ffi::whiteout_m2_M2ParticleEmitter_get_splinePoints_count(self.raw.as_ptr());
6219            let p = ffi::whiteout_m2_M2ParticleEmitter_get_splinePoints_data(self.raw.as_ptr())
6220                as *const crate::math::Vector3f;
6221            if p.is_null() || n == 0 {
6222                &[]
6223            } else {
6224                core::slice::from_raw_parts(p, n)
6225            }
6226        }
6227    }
6228
6229    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
6230    pub fn spline_points_mut(&mut self) -> &mut [crate::math::Vector3f] {
6231        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
6232        unsafe {
6233            let n = ffi::whiteout_m2_M2ParticleEmitter_get_splinePoints_count(self.raw.as_ptr());
6234            let p = ffi::whiteout_m2_M2ParticleEmitter_get_splinePoints_data(self.raw.as_ptr())
6235                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
6236            if p.is_null() || n == 0 {
6237                &mut []
6238            } else {
6239                core::slice::from_raw_parts_mut(p, n)
6240            }
6241        }
6242    }
6243
6244    pub fn set_spline_points(&mut self, values: &[crate::math::Vector3f]) {
6245        // SAFETY: the native side copies `values` before returning.
6246        unsafe {
6247            ffi::whiteout_m2_M2ParticleEmitter_assign_splinePoints(
6248                self.raw.as_ptr(),
6249                values.as_ptr() as *const _,
6250                values.len(),
6251            )
6252        }
6253    }
6254
6255    pub fn resize_spline_points(&mut self, count: usize) {
6256        // SAFETY: reallocation is safe here precisely because
6257        // `&mut self` means no slice borrow is outstanding.
6258        unsafe { ffi::whiteout_m2_M2ParticleEmitter_resize_splinePoints(self.raw.as_ptr(), count) }
6259    }
6260
6261    /// Borrows the field in place — no copy, no allocation.
6262    pub fn enabled_in(&self) -> crate::support::Ref<'_, AnimationTrackU8> {
6263        // SAFETY: an interior pointer into `self`, valid for this
6264        // borrow and never freed by the `Ref`.
6265        unsafe {
6266            crate::support::Ref::new(AnimationTrackU8 {
6267                raw: core::ptr::NonNull::new_unchecked(
6268                    ffi::whiteout_m2_M2ParticleEmitter_get_enabledIn(self.raw.as_ptr()),
6269                ),
6270            })
6271        }
6272    }
6273
6274    pub fn enabled_in_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackU8> {
6275        // SAFETY: as above; `&mut self` guarantees exclusivity.
6276        unsafe {
6277            crate::support::RefMut::new(AnimationTrackU8 {
6278                raw: core::ptr::NonNull::new_unchecked(
6279                    ffi::whiteout_m2_M2ParticleEmitter_get_enabledIn(self.raw.as_ptr()),
6280                ),
6281            })
6282        }
6283    }
6284}
6285
6286impl Default for ParticleEmitter {
6287    fn default() -> Self {
6288        Self::new()
6289    }
6290}
6291
6292pub struct Event {
6293    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Event>,
6294}
6295
6296impl Drop for Event {
6297    fn drop(&mut self) {
6298        // SAFETY: `raw` came from a native constructor and Drop runs once.
6299        unsafe { ffi::whiteout_m2_M2Event_delete(self.raw.as_ptr()) }
6300    }
6301}
6302
6303impl Event {
6304    /// # Safety
6305    /// `raw` must be a live handle this value takes ownership of.
6306    #[allow(dead_code)] // used by whichever methods return this type
6307    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Event) -> Option<Self> {
6308        core::ptr::NonNull::new(raw).map(|raw| Event { raw })
6309    }
6310}
6311
6312// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6313// is deliberately NOT implemented — the C++ types make no documented
6314// guarantee about concurrent use, and claiming one we haven't verified
6315// would be unsound. See `@bind thread_safe` in the plan.
6316unsafe impl Send for Event {}
6317
6318impl core::fmt::Debug for Event {
6319    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6320        f.debug_struct("Event").finish_non_exhaustive()
6321    }
6322}
6323
6324impl Event {
6325    /// # Panics
6326    /// Panics if the native allocation fails.
6327    pub fn new() -> Self {
6328        // SAFETY: the native constructor returns a live handle; a null here
6329        // means the library is unusable.
6330        unsafe {
6331            let raw = ffi::whiteout_m2_M2Event_new();
6332            Self::from_raw(raw).expect("native Event allocation failed")
6333        }
6334    }
6335
6336    pub fn identifier(&self) -> u32 {
6337        // SAFETY: plain scalar read through a live handle.
6338        unsafe { ffi::whiteout_m2_M2Event_get_identifier(self.raw.as_ptr()) }
6339    }
6340
6341    pub fn set_identifier(&mut self, value: u32) {
6342        // SAFETY: plain scalar write through a live handle.
6343        unsafe { ffi::whiteout_m2_M2Event_set_identifier(self.raw.as_ptr(), value) }
6344    }
6345
6346    pub fn data(&self) -> u32 {
6347        // SAFETY: plain scalar read through a live handle.
6348        unsafe { ffi::whiteout_m2_M2Event_get_data(self.raw.as_ptr()) }
6349    }
6350
6351    pub fn set_data(&mut self, value: u32) {
6352        // SAFETY: plain scalar write through a live handle.
6353        unsafe { ffi::whiteout_m2_M2Event_set_data(self.raw.as_ptr(), value) }
6354    }
6355
6356    pub fn bone_id(&self) -> u32 {
6357        // SAFETY: plain scalar read through a live handle.
6358        unsafe { ffi::whiteout_m2_M2Event_get_boneId(self.raw.as_ptr()) }
6359    }
6360
6361    pub fn set_bone_id(&mut self, value: u32) {
6362        // SAFETY: plain scalar write through a live handle.
6363        unsafe { ffi::whiteout_m2_M2Event_set_boneId(self.raw.as_ptr(), value) }
6364    }
6365
6366    pub fn position(&self) -> crate::math::Vector3f {
6367        // SAFETY: the getter returns an interior pointer to a
6368        // layout-identical POD; we copy it out immediately.
6369        unsafe {
6370            *(ffi::whiteout_m2_M2Event_get_position(self.raw.as_ptr())
6371                as *const crate::math::Vector3f)
6372        }
6373    }
6374
6375    pub fn set_position(&mut self, value: crate::math::Vector3f) {
6376        // SAFETY: as above, in the other direction.
6377        unsafe {
6378            ffi::whiteout_m2_M2Event_set_position(
6379                self.raw.as_ptr(),
6380                &value as *const crate::math::Vector3f as *const _,
6381            )
6382        }
6383    }
6384
6385    /// Borrows the field in place — no copy, no allocation.
6386    pub fn enabled(&self) -> crate::support::Ref<'_, AnimationTrackBase> {
6387        // SAFETY: an interior pointer into `self`, valid for this
6388        // borrow and never freed by the `Ref`.
6389        unsafe {
6390            crate::support::Ref::new(AnimationTrackBase {
6391                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Event_get_enabled(
6392                    self.raw.as_ptr(),
6393                )),
6394            })
6395        }
6396    }
6397
6398    pub fn enabled_mut(&mut self) -> crate::support::RefMut<'_, AnimationTrackBase> {
6399        // SAFETY: as above; `&mut self` guarantees exclusivity.
6400        unsafe {
6401            crate::support::RefMut::new(AnimationTrackBase {
6402                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Event_get_enabled(
6403                    self.raw.as_ptr(),
6404                )),
6405            })
6406        }
6407    }
6408}
6409
6410impl Default for Event {
6411    fn default() -> Self {
6412        Self::new()
6413    }
6414}
6415
6416/// The affine frame the Domino chunks store: three basis columns and an origin, twelve floats in all.
6417///
6418/// The client reassembles it as `dmMtx{axisX, axisY, axisZ}` -> `dmQuatFromMtx` plus `origin` as the translation, giving a `dmTransform`.
6419pub struct PhysicsFrame {
6420    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsFrame>,
6421}
6422
6423impl Drop for PhysicsFrame {
6424    fn drop(&mut self) {
6425        // SAFETY: `raw` came from a native constructor and Drop runs once.
6426        unsafe { ffi::whiteout_m2_M2PhysicsFrame_delete(self.raw.as_ptr()) }
6427    }
6428}
6429
6430impl PhysicsFrame {
6431    /// # Safety
6432    /// `raw` must be a live handle this value takes ownership of.
6433    #[allow(dead_code)] // used by whichever methods return this type
6434    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsFrame) -> Option<Self> {
6435        core::ptr::NonNull::new(raw).map(|raw| PhysicsFrame { raw })
6436    }
6437}
6438
6439// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6440// is deliberately NOT implemented — the C++ types make no documented
6441// guarantee about concurrent use, and claiming one we haven't verified
6442// would be unsound. See `@bind thread_safe` in the plan.
6443unsafe impl Send for PhysicsFrame {}
6444
6445impl core::fmt::Debug for PhysicsFrame {
6446    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6447        f.debug_struct("PhysicsFrame").finish_non_exhaustive()
6448    }
6449}
6450
6451impl PhysicsFrame {
6452    /// # Panics
6453    /// Panics if the native allocation fails.
6454    pub fn new() -> Self {
6455        // SAFETY: the native constructor returns a live handle; a null here
6456        // means the library is unusable.
6457        unsafe {
6458            let raw = ffi::whiteout_m2_M2PhysicsFrame_new();
6459            Self::from_raw(raw).expect("native PhysicsFrame allocation failed")
6460        }
6461    }
6462
6463    pub fn axis_x(&self) -> crate::math::Vector3f {
6464        // SAFETY: the getter returns an interior pointer to a
6465        // layout-identical POD; we copy it out immediately.
6466        unsafe {
6467            *(ffi::whiteout_m2_M2PhysicsFrame_get_axisX(self.raw.as_ptr())
6468                as *const crate::math::Vector3f)
6469        }
6470    }
6471
6472    pub fn set_axis_x(&mut self, value: crate::math::Vector3f) {
6473        // SAFETY: as above, in the other direction.
6474        unsafe {
6475            ffi::whiteout_m2_M2PhysicsFrame_set_axisX(
6476                self.raw.as_ptr(),
6477                &value as *const crate::math::Vector3f as *const _,
6478            )
6479        }
6480    }
6481
6482    pub fn axis_y(&self) -> crate::math::Vector3f {
6483        // SAFETY: the getter returns an interior pointer to a
6484        // layout-identical POD; we copy it out immediately.
6485        unsafe {
6486            *(ffi::whiteout_m2_M2PhysicsFrame_get_axisY(self.raw.as_ptr())
6487                as *const crate::math::Vector3f)
6488        }
6489    }
6490
6491    pub fn set_axis_y(&mut self, value: crate::math::Vector3f) {
6492        // SAFETY: as above, in the other direction.
6493        unsafe {
6494            ffi::whiteout_m2_M2PhysicsFrame_set_axisY(
6495                self.raw.as_ptr(),
6496                &value as *const crate::math::Vector3f as *const _,
6497            )
6498        }
6499    }
6500
6501    pub fn axis_z(&self) -> crate::math::Vector3f {
6502        // SAFETY: the getter returns an interior pointer to a
6503        // layout-identical POD; we copy it out immediately.
6504        unsafe {
6505            *(ffi::whiteout_m2_M2PhysicsFrame_get_axisZ(self.raw.as_ptr())
6506                as *const crate::math::Vector3f)
6507        }
6508    }
6509
6510    pub fn set_axis_z(&mut self, value: crate::math::Vector3f) {
6511        // SAFETY: as above, in the other direction.
6512        unsafe {
6513            ffi::whiteout_m2_M2PhysicsFrame_set_axisZ(
6514                self.raw.as_ptr(),
6515                &value as *const crate::math::Vector3f as *const _,
6516            )
6517        }
6518    }
6519
6520    pub fn origin(&self) -> crate::math::Vector3f {
6521        // SAFETY: the getter returns an interior pointer to a
6522        // layout-identical POD; we copy it out immediately.
6523        unsafe {
6524            *(ffi::whiteout_m2_M2PhysicsFrame_get_origin(self.raw.as_ptr())
6525                as *const crate::math::Vector3f)
6526        }
6527    }
6528
6529    pub fn set_origin(&mut self, value: crate::math::Vector3f) {
6530        // SAFETY: as above, in the other direction.
6531        unsafe {
6532            ffi::whiteout_m2_M2PhysicsFrame_set_origin(
6533                self.raw.as_ptr(),
6534                &value as *const crate::math::Vector3f as *const _,
6535            )
6536        }
6537    }
6538}
6539
6540impl Default for PhysicsFrame {
6541    fn default() -> Self {
6542        Self::new()
6543    }
6544}
6545
6546/// One rigid body, bound to a single model bone — BODY/BDY2/BDY3/BDY4.
6547///
6548/// The four on-disk layouts are the same fields accreting over time, so they share one struct; PhysicsData::version decides which of them is written back, and fields the older layouts lack keep their defaults.
6549pub struct PhysicsBody {
6550    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsBody>,
6551}
6552
6553impl Drop for PhysicsBody {
6554    fn drop(&mut self) {
6555        // SAFETY: `raw` came from a native constructor and Drop runs once.
6556        unsafe { ffi::whiteout_m2_M2PhysicsBody_delete(self.raw.as_ptr()) }
6557    }
6558}
6559
6560impl PhysicsBody {
6561    /// # Safety
6562    /// `raw` must be a live handle this value takes ownership of.
6563    #[allow(dead_code)] // used by whichever methods return this type
6564    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsBody) -> Option<Self> {
6565        core::ptr::NonNull::new(raw).map(|raw| PhysicsBody { raw })
6566    }
6567}
6568
6569// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6570// is deliberately NOT implemented — the C++ types make no documented
6571// guarantee about concurrent use, and claiming one we haven't verified
6572// would be unsound. See `@bind thread_safe` in the plan.
6573unsafe impl Send for PhysicsBody {}
6574
6575impl core::fmt::Debug for PhysicsBody {
6576    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6577        f.debug_struct("PhysicsBody").finish_non_exhaustive()
6578    }
6579}
6580
6581impl PhysicsBody {
6582    /// # Panics
6583    /// Panics if the native allocation fails.
6584    pub fn new() -> Self {
6585        // SAFETY: the native constructor returns a live handle; a null here
6586        // means the library is unusable.
6587        unsafe {
6588            let raw = ffi::whiteout_m2_M2PhysicsBody_new();
6589            Self::from_raw(raw).expect("native PhysicsBody allocation failed")
6590        }
6591    }
6592
6593    pub fn type_(&self) -> PhysicsBodyType {
6594        // SAFETY: scalar read; the discriminant is validated below.
6595        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_type(self.raw.as_ptr()) }
6596            .try_into()
6597            .expect("unknown enum discriminant from the native library")
6598    }
6599
6600    pub fn set_type_(&mut self, value: PhysicsBodyType) {
6601        // SAFETY: scalar write through a live handle.
6602        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_type(self.raw.as_ptr(), value as i32) }
6603    }
6604
6605    pub fn bone_index(&self) -> u16 {
6606        // SAFETY: plain scalar read through a live handle.
6607        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_boneIndex(self.raw.as_ptr()) }
6608    }
6609
6610    pub fn set_bone_index(&mut self, value: u16) {
6611        // SAFETY: plain scalar write through a live handle.
6612        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_boneIndex(self.raw.as_ptr(), value) }
6613    }
6614
6615    /// Offset from the bone's animated position, not an absolute position: the client spawns the body at `bonePosition + position`.
6616    pub fn position(&self) -> crate::math::Vector3f {
6617        // SAFETY: the getter returns an interior pointer to a
6618        // layout-identical POD; we copy it out immediately.
6619        unsafe {
6620            *(ffi::whiteout_m2_M2PhysicsBody_get_position(self.raw.as_ptr())
6621                as *const crate::math::Vector3f)
6622        }
6623    }
6624
6625    pub fn set_position(&mut self, value: crate::math::Vector3f) {
6626        // SAFETY: as above, in the other direction.
6627        unsafe {
6628            ffi::whiteout_m2_M2PhysicsBody_set_position(
6629                self.raw.as_ptr(),
6630                &value as *const crate::math::Vector3f as *const _,
6631            )
6632        }
6633    }
6634
6635    /// First entry in PhysicsData::shapes belonging to this body. 32 bits wide in BODY/BDY2, 16 from BDY3 on — writing a larger index back into one of those truncates it.
6636    pub fn shape_index(&self) -> i32 {
6637        // SAFETY: plain scalar read through a live handle.
6638        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_shapeIndex(self.raw.as_ptr()) }
6639    }
6640
6641    pub fn set_shape_index(&mut self, value: i32) {
6642        // SAFETY: plain scalar write through a live handle.
6643        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_shapeIndex(self.raw.as_ptr(), value) }
6644    }
6645
6646    pub fn shape_count(&self) -> i32 {
6647        // SAFETY: plain scalar read through a live handle.
6648        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_shapeCount(self.raw.as_ptr()) }
6649    }
6650
6651    pub fn set_shape_count(&mut self, value: i32) {
6652        // SAFETY: plain scalar write through a live handle.
6653        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_shapeCount(self.raw.as_ptr(), value) }
6654    }
6655
6656    /// BDY3+. 1.0 on all but 45 of 1213 kinematic bodies but tuned freely on dynamic ones, negatives included — the shape of `dmBodyDef::m_gravityScale`.
6657    pub fn gravity_scale(&self) -> f32 {
6658        // SAFETY: plain scalar read through a live handle.
6659        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_gravityScale(self.raw.as_ptr()) }
6660    }
6661
6662    pub fn set_gravity_scale(&mut self, value: f32) {
6663        // SAFETY: plain scalar write through a live handle.
6664        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_gravityScale(self.raw.as_ptr(), value) }
6665    }
6666
6667    /// BDY2+. 1.0 in 3457 of 3526 bodies, otherwise 1.1-10 — `dmBodyDef::m_inertiaScale`.
6668    pub fn inertia_scale(&self) -> f32 {
6669        // SAFETY: plain scalar read through a live handle.
6670        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_inertiaScale(self.raw.as_ptr()) }
6671    }
6672
6673    pub fn set_inertia_scale(&mut self, value: f32) {
6674        // SAFETY: plain scalar write through a live handle.
6675        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_inertiaScale(self.raw.as_ptr(), value) }
6676    }
6677
6678    /// BDY3+. Zero on 1196 of 1213 kinematic bodies and 0-10 on dynamic ones — `dmBodyDef::m_linearDamping`.
6679    pub fn linear_damping(&self) -> f32 {
6680        // SAFETY: plain scalar read through a live handle.
6681        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_linearDamping(self.raw.as_ptr()) }
6682    }
6683
6684    pub fn set_linear_damping(&mut self, value: f32) {
6685        // SAFETY: plain scalar write through a live handle.
6686        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_linearDamping(self.raw.as_ptr(), value) }
6687    }
6688
6689    /// BDY3+. Same kinematic/dynamic split as @ref linearDamping — `dmBodyDef::m_angularDamping`.
6690    pub fn angular_damping(&self) -> f32 {
6691        // SAFETY: plain scalar read through a live handle.
6692        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_angularDamping(self.raw.as_ptr()) }
6693    }
6694
6695    pub fn set_angular_damping(&mut self, value: f32) {
6696        // SAFETY: plain scalar write through a live handle.
6697        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_angularDamping(self.raw.as_ptr(), value) }
6698    }
6699
6700    /// BDY3+. Unidentified. Unlike the four above it is set on kinematic and dynamic bodies alike, so it is not a rigid-body integration parameter; values cluster on 0.5, 0.01, 0.9 and 0.1.
6701    pub fn unknown_28(&self) -> f32 {
6702        // SAFETY: plain scalar read through a live handle.
6703        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_unknown28(self.raw.as_ptr()) }
6704    }
6705
6706    pub fn set_unknown_28(&mut self, value: f32) {
6707        // SAFETY: plain scalar write through a live handle.
6708        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_unknown28(self.raw.as_ptr(), value) }
6709    }
6710
6711    /// BDY4+. Unidentified; 0 in half the corpus, otherwise small values or 0x8000 alone, which reads like a bit field.
6712    pub fn unknown_2c(&self) -> u16 {
6713        // SAFETY: plain scalar read through a live handle.
6714        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_unknown2c(self.raw.as_ptr()) }
6715    }
6716
6717    pub fn set_unknown_2c(&mut self, value: u16) {
6718        // SAFETY: plain scalar write through a live handle.
6719        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_unknown2c(self.raw.as_ptr(), value) }
6720    }
6721
6722    /// BDY4+. Zero in every corpus body.
6723    pub fn padding_2e(&self) -> u16 {
6724        // SAFETY: plain scalar read through a live handle.
6725        unsafe { ffi::whiteout_m2_M2PhysicsBody_get_padding2e(self.raw.as_ptr()) }
6726    }
6727
6728    pub fn set_padding_2e(&mut self, value: u16) {
6729        // SAFETY: plain scalar write through a live handle.
6730        unsafe { ffi::whiteout_m2_M2PhysicsBody_set_padding2e(self.raw.as_ptr(), value) }
6731    }
6732}
6733
6734impl Default for PhysicsBody {
6735    fn default() -> Self {
6736        Self::new()
6737    }
6738}
6739
6740/// One collision shape reference — SHAP/SHP2. Points at an entry of the box/capsule/sphere/polytope array named by @ref shapeType.
6741pub struct PhysicsShape {
6742    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsShape>,
6743}
6744
6745impl Drop for PhysicsShape {
6746    fn drop(&mut self) {
6747        // SAFETY: `raw` came from a native constructor and Drop runs once.
6748        unsafe { ffi::whiteout_m2_M2PhysicsShape_delete(self.raw.as_ptr()) }
6749    }
6750}
6751
6752impl PhysicsShape {
6753    /// # Safety
6754    /// `raw` must be a live handle this value takes ownership of.
6755    #[allow(dead_code)] // used by whichever methods return this type
6756    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsShape) -> Option<Self> {
6757        core::ptr::NonNull::new(raw).map(|raw| PhysicsShape { raw })
6758    }
6759}
6760
6761// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6762// is deliberately NOT implemented — the C++ types make no documented
6763// guarantee about concurrent use, and claiming one we haven't verified
6764// would be unsound. See `@bind thread_safe` in the plan.
6765unsafe impl Send for PhysicsShape {}
6766
6767impl core::fmt::Debug for PhysicsShape {
6768    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6769        f.debug_struct("PhysicsShape").finish_non_exhaustive()
6770    }
6771}
6772
6773impl PhysicsShape {
6774    /// # Panics
6775    /// Panics if the native allocation fails.
6776    pub fn new() -> Self {
6777        // SAFETY: the native constructor returns a live handle; a null here
6778        // means the library is unusable.
6779        unsafe {
6780            let raw = ffi::whiteout_m2_M2PhysicsShape_new();
6781            Self::from_raw(raw).expect("native PhysicsShape allocation failed")
6782        }
6783    }
6784
6785    pub fn shape_type(&self) -> PhysicsShapeType {
6786        // SAFETY: scalar read; the discriminant is validated below.
6787        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_shapeType(self.raw.as_ptr()) }
6788            .try_into()
6789            .expect("unknown enum discriminant from the native library")
6790    }
6791
6792    pub fn set_shape_type(&mut self, value: PhysicsShapeType) {
6793        // SAFETY: scalar write through a live handle.
6794        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_shapeType(self.raw.as_ptr(), value as i32) }
6795    }
6796
6797    pub fn shape_index(&self) -> i16 {
6798        // SAFETY: plain scalar read through a live handle.
6799        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_shapeIndex(self.raw.as_ptr()) }
6800    }
6801
6802    pub fn set_shape_index(&mut self, value: i16) {
6803        // SAFETY: plain scalar write through a live handle.
6804        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_shapeIndex(self.raw.as_ptr(), value) }
6805    }
6806
6807    /// Zero in every corpus shape.
6808    pub fn padding_04(&self) -> u32 {
6809        // SAFETY: plain scalar read through a live handle.
6810        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_padding04(self.raw.as_ptr()) }
6811    }
6812
6813    pub fn set_padding_04(&mut self, value: u32) {
6814        // SAFETY: plain scalar write through a live handle.
6815        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_padding04(self.raw.as_ptr(), value) }
6816    }
6817
6818    pub fn friction(&self) -> f32 {
6819        // SAFETY: plain scalar read through a live handle.
6820        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_friction(self.raw.as_ptr()) }
6821    }
6822
6823    pub fn set_friction(&mut self, value: f32) {
6824        // SAFETY: plain scalar write through a live handle.
6825        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_friction(self.raw.as_ptr(), value) }
6826    }
6827
6828    pub fn restitution(&self) -> f32 {
6829        // SAFETY: plain scalar read through a live handle.
6830        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_restitution(self.raw.as_ptr()) }
6831    }
6832
6833    pub fn set_restitution(&mut self, value: f32) {
6834        // SAFETY: plain scalar write through a live handle.
6835        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_restitution(self.raw.as_ptr(), value) }
6836    }
6837
6838    pub fn density(&self) -> f32 {
6839        // SAFETY: plain scalar read through a live handle.
6840        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_density(self.raw.as_ptr()) }
6841    }
6842
6843    pub fn set_density(&mut self, value: f32) {
6844        // SAFETY: plain scalar write through a live handle.
6845        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_density(self.raw.as_ptr(), value) }
6846    }
6847
6848    /// SHP2+. Unidentified, but a float: only 0, 0.01, 0.8 and 1.0 occur. The one `dmFixtureDef` float the rest of this struct does not account for is `m_rollingResistance`.
6849    pub fn unknown_14(&self) -> f32 {
6850        // SAFETY: plain scalar read through a live handle.
6851        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_unknown14(self.raw.as_ptr()) }
6852    }
6853
6854    pub fn set_unknown_14(&mut self, value: f32) {
6855        // SAFETY: plain scalar write through a live handle.
6856        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_unknown14(self.raw.as_ptr(), value) }
6857    }
6858
6859    /// SHP2+. 1.0 in 3229 of 3230 shapes, matching the `m_scaleOrRadius` the client hands every fixture.
6860    pub fn scale(&self) -> f32 {
6861        // SAFETY: plain scalar read through a live handle.
6862        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_scale(self.raw.as_ptr()) }
6863    }
6864
6865    pub fn set_scale(&mut self, value: f32) {
6866        // SAFETY: plain scalar write through a live handle.
6867        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_scale(self.raw.as_ptr(), value) }
6868    }
6869
6870    /// SHP2+. Zero in every corpus shape.
6871    pub fn unknown_1c(&self) -> u16 {
6872        // SAFETY: plain scalar read through a live handle.
6873        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_unknown1c(self.raw.as_ptr()) }
6874    }
6875
6876    pub fn set_unknown_1c(&mut self, value: u16) {
6877        // SAFETY: plain scalar write through a live handle.
6878        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_unknown1c(self.raw.as_ptr(), value) }
6879    }
6880
6881    /// SHP2+. Uninitialised on disk; kept so writes match.
6882    pub fn padding_1e(&self) -> u16 {
6883        // SAFETY: plain scalar read through a live handle.
6884        unsafe { ffi::whiteout_m2_M2PhysicsShape_get_padding1e(self.raw.as_ptr()) }
6885    }
6886
6887    pub fn set_padding_1e(&mut self, value: u16) {
6888        // SAFETY: plain scalar write through a live handle.
6889        unsafe { ffi::whiteout_m2_M2PhysicsShape_set_padding1e(self.raw.as_ptr(), value) }
6890    }
6891}
6892
6893impl Default for PhysicsShape {
6894    fn default() -> Self {
6895        Self::new()
6896    }
6897}
6898
6899/// BOXS — an oriented box. The client turns it straight into a polytope via `CPhysicsBoxShapeDef::SetPolytopeData(frame, halfExtents)`.
6900pub struct BoxShape {
6901    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2BoxShape>,
6902}
6903
6904impl Drop for BoxShape {
6905    fn drop(&mut self) {
6906        // SAFETY: `raw` came from a native constructor and Drop runs once.
6907        unsafe { ffi::whiteout_m2_M2BoxShape_delete(self.raw.as_ptr()) }
6908    }
6909}
6910
6911impl BoxShape {
6912    /// # Safety
6913    /// `raw` must be a live handle this value takes ownership of.
6914    #[allow(dead_code)] // used by whichever methods return this type
6915    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2BoxShape) -> Option<Self> {
6916        core::ptr::NonNull::new(raw).map(|raw| BoxShape { raw })
6917    }
6918}
6919
6920// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
6921// is deliberately NOT implemented — the C++ types make no documented
6922// guarantee about concurrent use, and claiming one we haven't verified
6923// would be unsound. See `@bind thread_safe` in the plan.
6924unsafe impl Send for BoxShape {}
6925
6926impl core::fmt::Debug for BoxShape {
6927    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6928        f.debug_struct("BoxShape").finish_non_exhaustive()
6929    }
6930}
6931
6932impl BoxShape {
6933    /// # Panics
6934    /// Panics if the native allocation fails.
6935    pub fn new() -> Self {
6936        // SAFETY: the native constructor returns a live handle; a null here
6937        // means the library is unusable.
6938        unsafe {
6939            let raw = ffi::whiteout_m2_M2BoxShape_new();
6940            Self::from_raw(raw).expect("native BoxShape allocation failed")
6941        }
6942    }
6943
6944    /// Borrows the field in place — no copy, no allocation.
6945    pub fn frame(&self) -> crate::support::Ref<'_, PhysicsFrame> {
6946        // SAFETY: an interior pointer into `self`, valid for this
6947        // borrow and never freed by the `Ref`.
6948        unsafe {
6949            crate::support::Ref::new(PhysicsFrame {
6950                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2BoxShape_get_frame(
6951                    self.raw.as_ptr(),
6952                )),
6953            })
6954        }
6955    }
6956
6957    pub fn frame_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
6958        // SAFETY: as above; `&mut self` guarantees exclusivity.
6959        unsafe {
6960            crate::support::RefMut::new(PhysicsFrame {
6961                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2BoxShape_get_frame(
6962                    self.raw.as_ptr(),
6963                )),
6964            })
6965        }
6966    }
6967
6968    pub fn half_extents(&self) -> crate::math::Vector3f {
6969        // SAFETY: the getter returns an interior pointer to a
6970        // layout-identical POD; we copy it out immediately.
6971        unsafe {
6972            *(ffi::whiteout_m2_M2BoxShape_get_halfExtents(self.raw.as_ptr())
6973                as *const crate::math::Vector3f)
6974        }
6975    }
6976
6977    pub fn set_half_extents(&mut self, value: crate::math::Vector3f) {
6978        // SAFETY: as above, in the other direction.
6979        unsafe {
6980            ffi::whiteout_m2_M2BoxShape_set_halfExtents(
6981                self.raw.as_ptr(),
6982                &value as *const crate::math::Vector3f as *const _,
6983            )
6984        }
6985    }
6986}
6987
6988impl Default for BoxShape {
6989    fn default() -> Self {
6990        Self::new()
6991    }
6992}
6993
6994/// CAPS — a capsule between two local points.
6995pub struct CapsuleShape {
6996    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2CapsuleShape>,
6997}
6998
6999impl Drop for CapsuleShape {
7000    fn drop(&mut self) {
7001        // SAFETY: `raw` came from a native constructor and Drop runs once.
7002        unsafe { ffi::whiteout_m2_M2CapsuleShape_delete(self.raw.as_ptr()) }
7003    }
7004}
7005
7006impl CapsuleShape {
7007    /// # Safety
7008    /// `raw` must be a live handle this value takes ownership of.
7009    #[allow(dead_code)] // used by whichever methods return this type
7010    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2CapsuleShape) -> Option<Self> {
7011        core::ptr::NonNull::new(raw).map(|raw| CapsuleShape { raw })
7012    }
7013}
7014
7015// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7016// is deliberately NOT implemented — the C++ types make no documented
7017// guarantee about concurrent use, and claiming one we haven't verified
7018// would be unsound. See `@bind thread_safe` in the plan.
7019unsafe impl Send for CapsuleShape {}
7020
7021impl core::fmt::Debug for CapsuleShape {
7022    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7023        f.debug_struct("CapsuleShape").finish_non_exhaustive()
7024    }
7025}
7026
7027impl CapsuleShape {
7028    /// # Panics
7029    /// Panics if the native allocation fails.
7030    pub fn new() -> Self {
7031        // SAFETY: the native constructor returns a live handle; a null here
7032        // means the library is unusable.
7033        unsafe {
7034            let raw = ffi::whiteout_m2_M2CapsuleShape_new();
7035            Self::from_raw(raw).expect("native CapsuleShape allocation failed")
7036        }
7037    }
7038
7039    pub fn local_position_1(&self) -> crate::math::Vector3f {
7040        // SAFETY: the getter returns an interior pointer to a
7041        // layout-identical POD; we copy it out immediately.
7042        unsafe {
7043            *(ffi::whiteout_m2_M2CapsuleShape_get_localPosition1(self.raw.as_ptr())
7044                as *const crate::math::Vector3f)
7045        }
7046    }
7047
7048    pub fn set_local_position_1(&mut self, value: crate::math::Vector3f) {
7049        // SAFETY: as above, in the other direction.
7050        unsafe {
7051            ffi::whiteout_m2_M2CapsuleShape_set_localPosition1(
7052                self.raw.as_ptr(),
7053                &value as *const crate::math::Vector3f as *const _,
7054            )
7055        }
7056    }
7057
7058    pub fn local_position_2(&self) -> crate::math::Vector3f {
7059        // SAFETY: the getter returns an interior pointer to a
7060        // layout-identical POD; we copy it out immediately.
7061        unsafe {
7062            *(ffi::whiteout_m2_M2CapsuleShape_get_localPosition2(self.raw.as_ptr())
7063                as *const crate::math::Vector3f)
7064        }
7065    }
7066
7067    pub fn set_local_position_2(&mut self, value: crate::math::Vector3f) {
7068        // SAFETY: as above, in the other direction.
7069        unsafe {
7070            ffi::whiteout_m2_M2CapsuleShape_set_localPosition2(
7071                self.raw.as_ptr(),
7072                &value as *const crate::math::Vector3f as *const _,
7073            )
7074        }
7075    }
7076
7077    pub fn radius(&self) -> f32 {
7078        // SAFETY: plain scalar read through a live handle.
7079        unsafe { ffi::whiteout_m2_M2CapsuleShape_get_radius(self.raw.as_ptr()) }
7080    }
7081
7082    pub fn set_radius(&mut self, value: f32) {
7083        // SAFETY: plain scalar write through a live handle.
7084        unsafe { ffi::whiteout_m2_M2CapsuleShape_set_radius(self.raw.as_ptr(), value) }
7085    }
7086}
7087
7088impl Default for CapsuleShape {
7089    fn default() -> Self {
7090        Self::new()
7091    }
7092}
7093
7094/// SPHS — a sphere at a local point.
7095pub struct SphereShape {
7096    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2SphereShape>,
7097}
7098
7099impl Drop for SphereShape {
7100    fn drop(&mut self) {
7101        // SAFETY: `raw` came from a native constructor and Drop runs once.
7102        unsafe { ffi::whiteout_m2_M2SphereShape_delete(self.raw.as_ptr()) }
7103    }
7104}
7105
7106impl SphereShape {
7107    /// # Safety
7108    /// `raw` must be a live handle this value takes ownership of.
7109    #[allow(dead_code)] // used by whichever methods return this type
7110    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2SphereShape) -> Option<Self> {
7111        core::ptr::NonNull::new(raw).map(|raw| SphereShape { raw })
7112    }
7113}
7114
7115// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7116// is deliberately NOT implemented — the C++ types make no documented
7117// guarantee about concurrent use, and claiming one we haven't verified
7118// would be unsound. See `@bind thread_safe` in the plan.
7119unsafe impl Send for SphereShape {}
7120
7121impl core::fmt::Debug for SphereShape {
7122    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7123        f.debug_struct("SphereShape").finish_non_exhaustive()
7124    }
7125}
7126
7127impl SphereShape {
7128    /// # Panics
7129    /// Panics if the native allocation fails.
7130    pub fn new() -> Self {
7131        // SAFETY: the native constructor returns a live handle; a null here
7132        // means the library is unusable.
7133        unsafe {
7134            let raw = ffi::whiteout_m2_M2SphereShape_new();
7135            Self::from_raw(raw).expect("native SphereShape allocation failed")
7136        }
7137    }
7138
7139    pub fn local_position(&self) -> crate::math::Vector3f {
7140        // SAFETY: the getter returns an interior pointer to a
7141        // layout-identical POD; we copy it out immediately.
7142        unsafe {
7143            *(ffi::whiteout_m2_M2SphereShape_get_localPosition(self.raw.as_ptr())
7144                as *const crate::math::Vector3f)
7145        }
7146    }
7147
7148    pub fn set_local_position(&mut self, value: crate::math::Vector3f) {
7149        // SAFETY: as above, in the other direction.
7150        unsafe {
7151            ffi::whiteout_m2_M2SphereShape_set_localPosition(
7152                self.raw.as_ptr(),
7153                &value as *const crate::math::Vector3f as *const _,
7154            )
7155        }
7156    }
7157
7158    pub fn radius(&self) -> f32 {
7159        // SAFETY: plain scalar read through a live handle.
7160        unsafe { ffi::whiteout_m2_M2SphereShape_get_radius(self.raw.as_ptr()) }
7161    }
7162
7163    pub fn set_radius(&mut self, value: f32) {
7164        // SAFETY: plain scalar write through a live handle.
7165        unsafe { ffi::whiteout_m2_M2SphereShape_set_radius(self.raw.as_ptr(), value) }
7166    }
7167}
7168
7169impl Default for SphereShape {
7170    fn default() -> Self {
7171        Self::new()
7172    }
7173}
7174
7175/// One half-edge of a polytope — Domino's `dmSubEdge`, four bytes.
7176///
7177/// Half-edges are stored in twin pairs at adjacent indices, and the ones bounding a face form a cycle through @ref nextEdge.
7178pub struct PolytopeHalfEdge {
7179    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PolytopeHalfEdge>,
7180}
7181
7182impl Drop for PolytopeHalfEdge {
7183    fn drop(&mut self) {
7184        // SAFETY: `raw` came from a native constructor and Drop runs once.
7185        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_delete(self.raw.as_ptr()) }
7186    }
7187}
7188
7189impl PolytopeHalfEdge {
7190    /// # Safety
7191    /// `raw` must be a live handle this value takes ownership of.
7192    #[allow(dead_code)] // used by whichever methods return this type
7193    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PolytopeHalfEdge) -> Option<Self> {
7194        core::ptr::NonNull::new(raw).map(|raw| PolytopeHalfEdge { raw })
7195    }
7196}
7197
7198// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7199// is deliberately NOT implemented — the C++ types make no documented
7200// guarantee about concurrent use, and claiming one we haven't verified
7201// would be unsound. See `@bind thread_safe` in the plan.
7202unsafe impl Send for PolytopeHalfEdge {}
7203
7204impl core::fmt::Debug for PolytopeHalfEdge {
7205    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7206        f.debug_struct("PolytopeHalfEdge").finish_non_exhaustive()
7207    }
7208}
7209
7210impl PolytopeHalfEdge {
7211    /// # Panics
7212    /// Panics if the native allocation fails.
7213    pub fn new() -> Self {
7214        // SAFETY: the native constructor returns a live handle; a null here
7215        // means the library is unusable.
7216        unsafe {
7217            let raw = ffi::whiteout_m2_M2PolytopeHalfEdge_new();
7218            Self::from_raw(raw).expect("native PolytopeHalfEdge allocation failed")
7219        }
7220    }
7221
7222    /// Signed step to the paired half-edge: the twin of edge `i` is `i + twinOffset`. Only +1 and -1 occur, in equal numbers.
7223    pub fn twin_offset(&self) -> i8 {
7224        // SAFETY: plain scalar read through a live handle.
7225        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_get_twinOffset(self.raw.as_ptr()) }
7226    }
7227
7228    pub fn set_twin_offset(&mut self, value: i8) {
7229        // SAFETY: plain scalar write through a live handle.
7230        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_set_twinOffset(self.raw.as_ptr(), value) }
7231    }
7232
7233    /// Where this half-edge starts, indexing PolytopeShape::vertices.
7234    pub fn origin_vertex(&self) -> u8 {
7235        // SAFETY: plain scalar read through a live handle.
7236        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_get_originVertex(self.raw.as_ptr()) }
7237    }
7238
7239    pub fn set_origin_vertex(&mut self, value: u8) {
7240        // SAFETY: plain scalar write through a live handle.
7241        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_set_originVertex(self.raw.as_ptr(), value) }
7242    }
7243
7244    /// The face this half-edge bounds, indexing PolytopeShape::facePlanes.
7245    pub fn face_index(&self) -> u8 {
7246        // SAFETY: plain scalar read through a live handle.
7247        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_get_faceIndex(self.raw.as_ptr()) }
7248    }
7249
7250    pub fn set_face_index(&mut self, value: u8) {
7251        // SAFETY: plain scalar write through a live handle.
7252        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_set_faceIndex(self.raw.as_ptr(), value) }
7253    }
7254
7255    /// Next half-edge around @ref faceIndex.
7256    pub fn next_edge(&self) -> u8 {
7257        // SAFETY: plain scalar read through a live handle.
7258        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_get_nextEdge(self.raw.as_ptr()) }
7259    }
7260
7261    pub fn set_next_edge(&mut self, value: u8) {
7262        // SAFETY: plain scalar write through a live handle.
7263        unsafe { ffi::whiteout_m2_M2PolytopeHalfEdge_set_nextEdge(self.raw.as_ptr(), value) }
7264    }
7265}
7266
7267impl Default for PolytopeHalfEdge {
7268    fn default() -> Self {
7269        Self::new()
7270    }
7271}
7272
7273/// PLYT — a convex hull, version 3+. Domino's `dmPolytope`.
7274///
7275/// The chunk stores fixed-size headers and variable-size payloads in two blocks; both halves are folded into this one struct, and the header's counts are recomputed from the vectors on write. The header's four pointer fields are filled in by the client at load time and are zero in every file, so they are not kept.
7276pub struct PolytopeShape {
7277    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PolytopeShape>,
7278}
7279
7280impl Drop for PolytopeShape {
7281    fn drop(&mut self) {
7282        // SAFETY: `raw` came from a native constructor and Drop runs once.
7283        unsafe { ffi::whiteout_m2_M2PolytopeShape_delete(self.raw.as_ptr()) }
7284    }
7285}
7286
7287impl PolytopeShape {
7288    /// # Safety
7289    /// `raw` must be a live handle this value takes ownership of.
7290    #[allow(dead_code)] // used by whichever methods return this type
7291    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PolytopeShape) -> Option<Self> {
7292        core::ptr::NonNull::new(raw).map(|raw| PolytopeShape { raw })
7293    }
7294}
7295
7296// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7297// is deliberately NOT implemented — the C++ types make no documented
7298// guarantee about concurrent use, and claiming one we haven't verified
7299// would be unsound. See `@bind thread_safe` in the plan.
7300unsafe impl Send for PolytopeShape {}
7301
7302impl core::fmt::Debug for PolytopeShape {
7303    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7304        f.debug_struct("PolytopeShape").finish_non_exhaustive()
7305    }
7306}
7307
7308impl PolytopeShape {
7309    /// # Panics
7310    /// Panics if the native allocation fails.
7311    pub fn new() -> Self {
7312        // SAFETY: the native constructor returns a live handle; a null here
7313        // means the library is unusable.
7314        unsafe {
7315            let raw = ffi::whiteout_m2_M2PolytopeShape_new();
7316            Self::from_raw(raw).expect("native PolytopeShape allocation failed")
7317        }
7318    }
7319
7320    /// Hull corners.
7321    /// Zero-copy view of the underlying `std::vector`.
7322    pub fn vertices(&self) -> &[crate::math::Vector3f] {
7323        // SAFETY: `_data`/`_count` describe one contiguous C++
7324        // allocation, borrowed for as long as `self` is.
7325        unsafe {
7326            let n = ffi::whiteout_m2_M2PolytopeShape_get_vertices_count(self.raw.as_ptr());
7327            let p = ffi::whiteout_m2_M2PolytopeShape_get_vertices_data(self.raw.as_ptr())
7328                as *const crate::math::Vector3f;
7329            if p.is_null() || n == 0 {
7330                &[]
7331            } else {
7332                core::slice::from_raw_parts(p, n)
7333            }
7334        }
7335    }
7336
7337    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
7338    pub fn vertices_mut(&mut self) -> &mut [crate::math::Vector3f] {
7339        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
7340        unsafe {
7341            let n = ffi::whiteout_m2_M2PolytopeShape_get_vertices_count(self.raw.as_ptr());
7342            let p = ffi::whiteout_m2_M2PolytopeShape_get_vertices_data(self.raw.as_ptr())
7343                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
7344            if p.is_null() || n == 0 {
7345                &mut []
7346            } else {
7347                core::slice::from_raw_parts_mut(p, n)
7348            }
7349        }
7350    }
7351
7352    pub fn set_vertices(&mut self, values: &[crate::math::Vector3f]) {
7353        // SAFETY: the native side copies `values` before returning.
7354        unsafe {
7355            ffi::whiteout_m2_M2PolytopeShape_assign_vertices(
7356                self.raw.as_ptr(),
7357                values.as_ptr() as *const _,
7358                values.len(),
7359            )
7360        }
7361    }
7362
7363    pub fn resize_vertices(&mut self, count: usize) {
7364        // SAFETY: reallocation is safe here precisely because
7365        // `&mut self` means no slice borrow is outstanding.
7366        unsafe { ffi::whiteout_m2_M2PolytopeShape_resize_vertices(self.raw.as_ptr(), count) }
7367    }
7368
7369    /// Outward plane of each face, `xyz` normal and `w` offset.
7370    /// Zero-copy view of the underlying `std::vector`.
7371    pub fn face_planes(&self) -> &[crate::math::Vector4f] {
7372        // SAFETY: `_data`/`_count` describe one contiguous C++
7373        // allocation, borrowed for as long as `self` is.
7374        unsafe {
7375            let n = ffi::whiteout_m2_M2PolytopeShape_get_facePlanes_count(self.raw.as_ptr());
7376            let p = ffi::whiteout_m2_M2PolytopeShape_get_facePlanes_data(self.raw.as_ptr())
7377                as *const crate::math::Vector4f;
7378            if p.is_null() || n == 0 {
7379                &[]
7380            } else {
7381                core::slice::from_raw_parts(p, n)
7382            }
7383        }
7384    }
7385
7386    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
7387    pub fn face_planes_mut(&mut self) -> &mut [crate::math::Vector4f] {
7388        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
7389        unsafe {
7390            let n = ffi::whiteout_m2_M2PolytopeShape_get_facePlanes_count(self.raw.as_ptr());
7391            let p = ffi::whiteout_m2_M2PolytopeShape_get_facePlanes_data(self.raw.as_ptr())
7392                as *const crate::math::Vector4f as *mut crate::math::Vector4f;
7393            if p.is_null() || n == 0 {
7394                &mut []
7395            } else {
7396                core::slice::from_raw_parts_mut(p, n)
7397            }
7398        }
7399    }
7400
7401    pub fn set_face_planes(&mut self, values: &[crate::math::Vector4f]) {
7402        // SAFETY: the native side copies `values` before returning.
7403        unsafe {
7404            ffi::whiteout_m2_M2PolytopeShape_assign_facePlanes(
7405                self.raw.as_ptr(),
7406                values.as_ptr() as *const _,
7407                values.len(),
7408            )
7409        }
7410    }
7411
7412    pub fn resize_face_planes(&mut self, count: usize) {
7413        // SAFETY: reallocation is safe here precisely because
7414        // `&mut self` means no slice borrow is outstanding.
7415        unsafe { ffi::whiteout_m2_M2PolytopeShape_resize_facePlanes(self.raw.as_ptr(), count) }
7416    }
7417
7418    /// One entry per face: any half-edge bounding it, as the entry point for walking the face through PolytopeHalfEdge::nextEdge.
7419    /// Zero-copy view of the underlying `std::vector`.
7420    pub fn face_first_edges(&self) -> &[u8] {
7421        // SAFETY: `_data`/`_count` describe one contiguous C++
7422        // allocation, borrowed for as long as `self` is.
7423        unsafe {
7424            let n = ffi::whiteout_m2_M2PolytopeShape_get_faceFirstEdges_count(self.raw.as_ptr());
7425            let p = ffi::whiteout_m2_M2PolytopeShape_get_faceFirstEdges_data(self.raw.as_ptr());
7426            if p.is_null() || n == 0 {
7427                &[]
7428            } else {
7429                core::slice::from_raw_parts(p, n)
7430            }
7431        }
7432    }
7433
7434    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
7435    pub fn face_first_edges_mut(&mut self) -> &mut [u8] {
7436        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
7437        unsafe {
7438            let n = ffi::whiteout_m2_M2PolytopeShape_get_faceFirstEdges_count(self.raw.as_ptr());
7439            let p = ffi::whiteout_m2_M2PolytopeShape_get_faceFirstEdges_data(self.raw.as_ptr())
7440                as *mut u8;
7441            if p.is_null() || n == 0 {
7442                &mut []
7443            } else {
7444                core::slice::from_raw_parts_mut(p, n)
7445            }
7446        }
7447    }
7448
7449    pub fn set_face_first_edges(&mut self, values: &[u8]) {
7450        // SAFETY: the native side copies `values` before returning.
7451        unsafe {
7452            ffi::whiteout_m2_M2PolytopeShape_assign_faceFirstEdges(
7453                self.raw.as_ptr(),
7454                values.as_ptr() as *const _,
7455                values.len(),
7456            )
7457        }
7458    }
7459
7460    pub fn resize_face_first_edges(&mut self, count: usize) {
7461        // SAFETY: reallocation is safe here precisely because
7462        // `&mut self` means no slice borrow is outstanding.
7463        unsafe { ffi::whiteout_m2_M2PolytopeShape_resize_faceFirstEdges(self.raw.as_ptr(), count) }
7464    }
7465
7466    pub fn edges_len(&self) -> usize {
7467        // SAFETY: scalar read through a live handle.
7468        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_edges_count(self.raw.as_ptr()) }
7469    }
7470
7471    /// Borrows element `index` in place. `None` when out of range.
7472    pub fn edges(&self, index: usize) -> Option<crate::support::Ref<'_, PolytopeHalfEdge>> {
7473        if index >= self.edges_len() {
7474            return None;
7475        }
7476        // SAFETY: index checked above; the pointer is interior to `self`.
7477        unsafe {
7478            Some(crate::support::Ref::new(PolytopeHalfEdge {
7479                raw: core::ptr::NonNull::new_unchecked(
7480                    ffi::whiteout_m2_M2PolytopeShape_get_edges_at(self.raw.as_ptr(), index),
7481                ),
7482            }))
7483        }
7484    }
7485
7486    pub fn edges_mut(
7487        &mut self,
7488        index: usize,
7489    ) -> Option<crate::support::RefMut<'_, PolytopeHalfEdge>> {
7490        if index >= self.edges_len() {
7491            return None;
7492        }
7493        // SAFETY: as above; `&mut self` guarantees exclusivity.
7494        unsafe {
7495            Some(crate::support::RefMut::new(PolytopeHalfEdge {
7496                raw: core::ptr::NonNull::new_unchecked(
7497                    ffi::whiteout_m2_M2PolytopeShape_get_edges_at(self.raw.as_ptr(), index),
7498                ),
7499            }))
7500        }
7501    }
7502
7503    /// Iterate the elements, borrowing each in turn.
7504    pub fn edges_iter(
7505        &self,
7506    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PolytopeHalfEdge>> {
7507        (0..self.edges_len()).map(move |i| self.edges(i).expect("index below len"))
7508    }
7509
7510    pub fn resize_edges(&mut self, count: usize) {
7511        // SAFETY: exclusive access, so no borrow is outstanding.
7512        unsafe { ffi::whiteout_m2_M2PolytopeShape_resize_edges(self.raw.as_ptr(), count) }
7513    }
7514
7515    /// Volume-weighted, not the vertex average.
7516    pub fn centroid(&self) -> crate::math::Vector3f {
7517        // SAFETY: the getter returns an interior pointer to a
7518        // layout-identical POD; we copy it out immediately.
7519        unsafe {
7520            *(ffi::whiteout_m2_M2PolytopeShape_get_centroid(self.raw.as_ptr())
7521                as *const crate::math::Vector3f)
7522        }
7523    }
7524
7525    pub fn set_centroid(&mut self, value: crate::math::Vector3f) {
7526        // SAFETY: as above, in the other direction.
7527        unsafe {
7528            ffi::whiteout_m2_M2PolytopeShape_set_centroid(
7529                self.raw.as_ptr(),
7530                &value as *const crate::math::Vector3f as *const _,
7531            )
7532        }
7533    }
7534
7535    /// Hull volume.
7536    pub fn volume(&self) -> f32 {
7537        // SAFETY: plain scalar read through a live handle.
7538        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_volume(self.raw.as_ptr()) }
7539    }
7540
7541    pub fn set_volume(&mut self, value: f32) {
7542        // SAFETY: plain scalar write through a live handle.
7543        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_volume(self.raw.as_ptr(), value) }
7544    }
7545
7546    /// Hull surface area.
7547    pub fn surface_area(&self) -> f32 {
7548        // SAFETY: plain scalar read through a live handle.
7549        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_surfaceArea(self.raw.as_ptr()) }
7550    }
7551
7552    pub fn set_surface_area(&mut self, value: f32) {
7553        // SAFETY: plain scalar write through a live handle.
7554        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_surfaceArea(self.raw.as_ptr(), value) }
7555    }
7556
7557    /// The four-byte gaps each count leaves in front of its 64-bit pointer, and the one that trails the header. Uninitialised in the files — some carry fragments of unrelated strings — so they are kept verbatim for writing.
7558    pub fn padding_04(&self) -> u32 {
7559        // SAFETY: plain scalar read through a live handle.
7560        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_padding04(self.raw.as_ptr()) }
7561    }
7562
7563    pub fn set_padding_04(&mut self, value: u32) {
7564        // SAFETY: plain scalar write through a live handle.
7565        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_padding04(self.raw.as_ptr(), value) }
7566    }
7567
7568    pub fn padding_14(&self) -> u32 {
7569        // SAFETY: plain scalar read through a live handle.
7570        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_padding14(self.raw.as_ptr()) }
7571    }
7572
7573    pub fn set_padding_14(&mut self, value: u32) {
7574        // SAFETY: plain scalar write through a live handle.
7575        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_padding14(self.raw.as_ptr(), value) }
7576    }
7577
7578    pub fn padding_2c(&self) -> u32 {
7579        // SAFETY: plain scalar read through a live handle.
7580        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_padding2c(self.raw.as_ptr()) }
7581    }
7582
7583    pub fn set_padding_2c(&mut self, value: u32) {
7584        // SAFETY: plain scalar write through a live handle.
7585        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_padding2c(self.raw.as_ptr(), value) }
7586    }
7587
7588    pub fn padding_4c(&self) -> u32 {
7589        // SAFETY: plain scalar read through a live handle.
7590        unsafe { ffi::whiteout_m2_M2PolytopeShape_get_padding4c(self.raw.as_ptr()) }
7591    }
7592
7593    pub fn set_padding_4c(&mut self, value: u32) {
7594        // SAFETY: plain scalar write through a live handle.
7595        unsafe { ffi::whiteout_m2_M2PolytopeShape_set_padding4c(self.raw.as_ptr(), value) }
7596    }
7597}
7598
7599impl Default for PolytopeShape {
7600    fn default() -> Self {
7601        Self::new()
7602    }
7603}
7604
7605/// JOIN — connects two bodies with the joint named by @ref jointType.
7606pub struct PhysicsJoint {
7607    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsJoint>,
7608}
7609
7610impl Drop for PhysicsJoint {
7611    fn drop(&mut self) {
7612        // SAFETY: `raw` came from a native constructor and Drop runs once.
7613        unsafe { ffi::whiteout_m2_M2PhysicsJoint_delete(self.raw.as_ptr()) }
7614    }
7615}
7616
7617impl PhysicsJoint {
7618    /// # Safety
7619    /// `raw` must be a live handle this value takes ownership of.
7620    #[allow(dead_code)] // used by whichever methods return this type
7621    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsJoint) -> Option<Self> {
7622        core::ptr::NonNull::new(raw).map(|raw| PhysicsJoint { raw })
7623    }
7624}
7625
7626// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7627// is deliberately NOT implemented — the C++ types make no documented
7628// guarantee about concurrent use, and claiming one we haven't verified
7629// would be unsound. See `@bind thread_safe` in the plan.
7630unsafe impl Send for PhysicsJoint {}
7631
7632impl core::fmt::Debug for PhysicsJoint {
7633    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7634        f.debug_struct("PhysicsJoint").finish_non_exhaustive()
7635    }
7636}
7637
7638impl PhysicsJoint {
7639    /// # Panics
7640    /// Panics if the native allocation fails.
7641    pub fn new() -> Self {
7642        // SAFETY: the native constructor returns a live handle; a null here
7643        // means the library is unusable.
7644        unsafe {
7645            let raw = ffi::whiteout_m2_M2PhysicsJoint_new();
7646            Self::from_raw(raw).expect("native PhysicsJoint allocation failed")
7647        }
7648    }
7649
7650    pub fn body_a_index(&self) -> u32 {
7651        // SAFETY: plain scalar read through a live handle.
7652        unsafe { ffi::whiteout_m2_M2PhysicsJoint_get_bodyAIndex(self.raw.as_ptr()) }
7653    }
7654
7655    pub fn set_body_a_index(&mut self, value: u32) {
7656        // SAFETY: plain scalar write through a live handle.
7657        unsafe { ffi::whiteout_m2_M2PhysicsJoint_set_bodyAIndex(self.raw.as_ptr(), value) }
7658    }
7659
7660    pub fn body_b_index(&self) -> u32 {
7661        // SAFETY: plain scalar read through a live handle.
7662        unsafe { ffi::whiteout_m2_M2PhysicsJoint_get_bodyBIndex(self.raw.as_ptr()) }
7663    }
7664
7665    pub fn set_body_b_index(&mut self, value: u32) {
7666        // SAFETY: plain scalar write through a live handle.
7667        unsafe { ffi::whiteout_m2_M2PhysicsJoint_set_bodyBIndex(self.raw.as_ptr(), value) }
7668    }
7669
7670    /// Zero in every corpus joint.
7671    pub fn padding_08(&self) -> u32 {
7672        // SAFETY: plain scalar read through a live handle.
7673        unsafe { ffi::whiteout_m2_M2PhysicsJoint_get_padding08(self.raw.as_ptr()) }
7674    }
7675
7676    pub fn set_padding_08(&mut self, value: u32) {
7677        // SAFETY: plain scalar write through a live handle.
7678        unsafe { ffi::whiteout_m2_M2PhysicsJoint_set_padding08(self.raw.as_ptr(), value) }
7679    }
7680
7681    pub fn joint_type(&self) -> PhysicsJointType {
7682        // SAFETY: scalar read; the discriminant is validated below.
7683        unsafe { ffi::whiteout_m2_M2PhysicsJoint_get_jointType(self.raw.as_ptr()) }
7684            .try_into()
7685            .expect("unknown enum discriminant from the native library")
7686    }
7687
7688    pub fn set_joint_type(&mut self, value: PhysicsJointType) {
7689        // SAFETY: scalar write through a live handle.
7690        unsafe { ffi::whiteout_m2_M2PhysicsJoint_set_jointType(self.raw.as_ptr(), value as i32) }
7691    }
7692
7693    /// Entry index within the joint array @ref jointType selects.
7694    pub fn joint_id(&self) -> i16 {
7695        // SAFETY: plain scalar read through a live handle.
7696        unsafe { ffi::whiteout_m2_M2PhysicsJoint_get_jointId(self.raw.as_ptr()) }
7697    }
7698
7699    pub fn set_joint_id(&mut self, value: i16) {
7700        // SAFETY: plain scalar write through a live handle.
7701        unsafe { ffi::whiteout_m2_M2PhysicsJoint_set_jointId(self.raw.as_ptr(), value) }
7702    }
7703}
7704
7705impl Default for PhysicsJoint {
7706    fn default() -> Self {
7707        Self::new()
7708    }
7709}
7710
7711/// WELJ/WLJ2/WLJ3 — a soft rigid connection. Zero frequency means the axis is solved as a hard constraint.
7712pub struct WeldJoint {
7713    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2WeldJoint>,
7714}
7715
7716impl Drop for WeldJoint {
7717    fn drop(&mut self) {
7718        // SAFETY: `raw` came from a native constructor and Drop runs once.
7719        unsafe { ffi::whiteout_m2_M2WeldJoint_delete(self.raw.as_ptr()) }
7720    }
7721}
7722
7723impl WeldJoint {
7724    /// # Safety
7725    /// `raw` must be a live handle this value takes ownership of.
7726    #[allow(dead_code)] // used by whichever methods return this type
7727    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2WeldJoint) -> Option<Self> {
7728        core::ptr::NonNull::new(raw).map(|raw| WeldJoint { raw })
7729    }
7730}
7731
7732// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7733// is deliberately NOT implemented — the C++ types make no documented
7734// guarantee about concurrent use, and claiming one we haven't verified
7735// would be unsound. See `@bind thread_safe` in the plan.
7736unsafe impl Send for WeldJoint {}
7737
7738impl core::fmt::Debug for WeldJoint {
7739    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7740        f.debug_struct("WeldJoint").finish_non_exhaustive()
7741    }
7742}
7743
7744impl WeldJoint {
7745    /// # Panics
7746    /// Panics if the native allocation fails.
7747    pub fn new() -> Self {
7748        // SAFETY: the native constructor returns a live handle; a null here
7749        // means the library is unusable.
7750        unsafe {
7751            let raw = ffi::whiteout_m2_M2WeldJoint_new();
7752            Self::from_raw(raw).expect("native WeldJoint allocation failed")
7753        }
7754    }
7755
7756    /// Borrows the field in place — no copy, no allocation.
7757    pub fn frame_a(&self) -> crate::support::Ref<'_, PhysicsFrame> {
7758        // SAFETY: an interior pointer into `self`, valid for this
7759        // borrow and never freed by the `Ref`.
7760        unsafe {
7761            crate::support::Ref::new(PhysicsFrame {
7762                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2WeldJoint_get_frameA(
7763                    self.raw.as_ptr(),
7764                )),
7765            })
7766        }
7767    }
7768
7769    pub fn frame_a_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
7770        // SAFETY: as above; `&mut self` guarantees exclusivity.
7771        unsafe {
7772            crate::support::RefMut::new(PhysicsFrame {
7773                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2WeldJoint_get_frameA(
7774                    self.raw.as_ptr(),
7775                )),
7776            })
7777        }
7778    }
7779
7780    /// Borrows the field in place — no copy, no allocation.
7781    pub fn frame_b(&self) -> crate::support::Ref<'_, PhysicsFrame> {
7782        // SAFETY: an interior pointer into `self`, valid for this
7783        // borrow and never freed by the `Ref`.
7784        unsafe {
7785            crate::support::Ref::new(PhysicsFrame {
7786                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2WeldJoint_get_frameB(
7787                    self.raw.as_ptr(),
7788                )),
7789            })
7790        }
7791    }
7792
7793    pub fn frame_b_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
7794        // SAFETY: as above; `&mut self` guarantees exclusivity.
7795        unsafe {
7796            crate::support::RefMut::new(PhysicsFrame {
7797                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2WeldJoint_get_frameB(
7798                    self.raw.as_ptr(),
7799                )),
7800            })
7801        }
7802    }
7803
7804    pub fn angular_frequency_hz(&self) -> f32 {
7805        // SAFETY: plain scalar read through a live handle.
7806        unsafe { ffi::whiteout_m2_M2WeldJoint_get_angularFrequencyHz(self.raw.as_ptr()) }
7807    }
7808
7809    pub fn set_angular_frequency_hz(&mut self, value: f32) {
7810        // SAFETY: plain scalar write through a live handle.
7811        unsafe { ffi::whiteout_m2_M2WeldJoint_set_angularFrequencyHz(self.raw.as_ptr(), value) }
7812    }
7813
7814    pub fn angular_damping_ratio(&self) -> f32 {
7815        // SAFETY: plain scalar read through a live handle.
7816        unsafe { ffi::whiteout_m2_M2WeldJoint_get_angularDampingRatio(self.raw.as_ptr()) }
7817    }
7818
7819    pub fn set_angular_damping_ratio(&mut self, value: f32) {
7820        // SAFETY: plain scalar write through a live handle.
7821        unsafe { ffi::whiteout_m2_M2WeldJoint_set_angularDampingRatio(self.raw.as_ptr(), value) }
7822    }
7823
7824    /// WLJ2+
7825    pub fn linear_frequency_hz(&self) -> f32 {
7826        // SAFETY: plain scalar read through a live handle.
7827        unsafe { ffi::whiteout_m2_M2WeldJoint_get_linearFrequencyHz(self.raw.as_ptr()) }
7828    }
7829
7830    pub fn set_linear_frequency_hz(&mut self, value: f32) {
7831        // SAFETY: plain scalar write through a live handle.
7832        unsafe { ffi::whiteout_m2_M2WeldJoint_set_linearFrequencyHz(self.raw.as_ptr(), value) }
7833    }
7834
7835    /// WLJ2+
7836    pub fn linear_damping_ratio(&self) -> f32 {
7837        // SAFETY: plain scalar read through a live handle.
7838        unsafe { ffi::whiteout_m2_M2WeldJoint_get_linearDampingRatio(self.raw.as_ptr()) }
7839    }
7840
7841    pub fn set_linear_damping_ratio(&mut self, value: f32) {
7842        // SAFETY: plain scalar write through a live handle.
7843        unsafe { ffi::whiteout_m2_M2WeldJoint_set_linearDampingRatio(self.raw.as_ptr(), value) }
7844    }
7845
7846    /// WLJ3+. Zero in 265 of 274 weld joints.
7847    pub fn unknown_70(&self) -> f32 {
7848        // SAFETY: plain scalar read through a live handle.
7849        unsafe { ffi::whiteout_m2_M2WeldJoint_get_unknown70(self.raw.as_ptr()) }
7850    }
7851
7852    pub fn set_unknown_70(&mut self, value: f32) {
7853        // SAFETY: plain scalar write through a live handle.
7854        unsafe { ffi::whiteout_m2_M2WeldJoint_set_unknown70(self.raw.as_ptr(), value) }
7855    }
7856}
7857
7858impl Default for WeldJoint {
7859    fn default() -> Self {
7860        Self::new()
7861    }
7862}
7863
7864/// SPHJ — a ball joint between two anchor points.
7865pub struct SphericalJoint {
7866    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2SphericalJoint>,
7867}
7868
7869impl Drop for SphericalJoint {
7870    fn drop(&mut self) {
7871        // SAFETY: `raw` came from a native constructor and Drop runs once.
7872        unsafe { ffi::whiteout_m2_M2SphericalJoint_delete(self.raw.as_ptr()) }
7873    }
7874}
7875
7876impl SphericalJoint {
7877    /// # Safety
7878    /// `raw` must be a live handle this value takes ownership of.
7879    #[allow(dead_code)] // used by whichever methods return this type
7880    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2SphericalJoint) -> Option<Self> {
7881        core::ptr::NonNull::new(raw).map(|raw| SphericalJoint { raw })
7882    }
7883}
7884
7885// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7886// is deliberately NOT implemented — the C++ types make no documented
7887// guarantee about concurrent use, and claiming one we haven't verified
7888// would be unsound. See `@bind thread_safe` in the plan.
7889unsafe impl Send for SphericalJoint {}
7890
7891impl core::fmt::Debug for SphericalJoint {
7892    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7893        f.debug_struct("SphericalJoint").finish_non_exhaustive()
7894    }
7895}
7896
7897impl SphericalJoint {
7898    /// # Panics
7899    /// Panics if the native allocation fails.
7900    pub fn new() -> Self {
7901        // SAFETY: the native constructor returns a live handle; a null here
7902        // means the library is unusable.
7903        unsafe {
7904            let raw = ffi::whiteout_m2_M2SphericalJoint_new();
7905            Self::from_raw(raw).expect("native SphericalJoint allocation failed")
7906        }
7907    }
7908
7909    pub fn anchor_a(&self) -> crate::math::Vector3f {
7910        // SAFETY: the getter returns an interior pointer to a
7911        // layout-identical POD; we copy it out immediately.
7912        unsafe {
7913            *(ffi::whiteout_m2_M2SphericalJoint_get_anchorA(self.raw.as_ptr())
7914                as *const crate::math::Vector3f)
7915        }
7916    }
7917
7918    pub fn set_anchor_a(&mut self, value: crate::math::Vector3f) {
7919        // SAFETY: as above, in the other direction.
7920        unsafe {
7921            ffi::whiteout_m2_M2SphericalJoint_set_anchorA(
7922                self.raw.as_ptr(),
7923                &value as *const crate::math::Vector3f as *const _,
7924            )
7925        }
7926    }
7927
7928    pub fn anchor_b(&self) -> crate::math::Vector3f {
7929        // SAFETY: the getter returns an interior pointer to a
7930        // layout-identical POD; we copy it out immediately.
7931        unsafe {
7932            *(ffi::whiteout_m2_M2SphericalJoint_get_anchorB(self.raw.as_ptr())
7933                as *const crate::math::Vector3f)
7934        }
7935    }
7936
7937    pub fn set_anchor_b(&mut self, value: crate::math::Vector3f) {
7938        // SAFETY: as above, in the other direction.
7939        unsafe {
7940            ffi::whiteout_m2_M2SphericalJoint_set_anchorB(
7941                self.raw.as_ptr(),
7942                &value as *const crate::math::Vector3f as *const _,
7943            )
7944        }
7945    }
7946
7947    pub fn friction_torque(&self) -> f32 {
7948        // SAFETY: plain scalar read through a live handle.
7949        unsafe { ffi::whiteout_m2_M2SphericalJoint_get_frictionTorque(self.raw.as_ptr()) }
7950    }
7951
7952    pub fn set_friction_torque(&mut self, value: f32) {
7953        // SAFETY: plain scalar write through a live handle.
7954        unsafe { ffi::whiteout_m2_M2SphericalJoint_set_frictionTorque(self.raw.as_ptr(), value) }
7955    }
7956}
7957
7958impl Default for SphericalJoint {
7959    fn default() -> Self {
7960        Self::new()
7961    }
7962}
7963
7964/// SHOJ/SHJ2 — a twist-and-cone joint, the one that chains cloth.
7965pub struct ShoulderJoint {
7966    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ShoulderJoint>,
7967}
7968
7969impl Drop for ShoulderJoint {
7970    fn drop(&mut self) {
7971        // SAFETY: `raw` came from a native constructor and Drop runs once.
7972        unsafe { ffi::whiteout_m2_M2ShoulderJoint_delete(self.raw.as_ptr()) }
7973    }
7974}
7975
7976impl ShoulderJoint {
7977    /// # Safety
7978    /// `raw` must be a live handle this value takes ownership of.
7979    #[allow(dead_code)] // used by whichever methods return this type
7980    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2ShoulderJoint) -> Option<Self> {
7981        core::ptr::NonNull::new(raw).map(|raw| ShoulderJoint { raw })
7982    }
7983}
7984
7985// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
7986// is deliberately NOT implemented — the C++ types make no documented
7987// guarantee about concurrent use, and claiming one we haven't verified
7988// would be unsound. See `@bind thread_safe` in the plan.
7989unsafe impl Send for ShoulderJoint {}
7990
7991impl core::fmt::Debug for ShoulderJoint {
7992    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7993        f.debug_struct("ShoulderJoint").finish_non_exhaustive()
7994    }
7995}
7996
7997impl ShoulderJoint {
7998    /// # Panics
7999    /// Panics if the native allocation fails.
8000    pub fn new() -> Self {
8001        // SAFETY: the native constructor returns a live handle; a null here
8002        // means the library is unusable.
8003        unsafe {
8004            let raw = ffi::whiteout_m2_M2ShoulderJoint_new();
8005            Self::from_raw(raw).expect("native ShoulderJoint allocation failed")
8006        }
8007    }
8008
8009    /// Borrows the field in place — no copy, no allocation.
8010    pub fn frame_a(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8011        // SAFETY: an interior pointer into `self`, valid for this
8012        // borrow and never freed by the `Ref`.
8013        unsafe {
8014            crate::support::Ref::new(PhysicsFrame {
8015                raw: core::ptr::NonNull::new_unchecked(
8016                    ffi::whiteout_m2_M2ShoulderJoint_get_frameA(self.raw.as_ptr()),
8017                ),
8018            })
8019        }
8020    }
8021
8022    pub fn frame_a_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8023        // SAFETY: as above; `&mut self` guarantees exclusivity.
8024        unsafe {
8025            crate::support::RefMut::new(PhysicsFrame {
8026                raw: core::ptr::NonNull::new_unchecked(
8027                    ffi::whiteout_m2_M2ShoulderJoint_get_frameA(self.raw.as_ptr()),
8028                ),
8029            })
8030        }
8031    }
8032
8033    /// Borrows the field in place — no copy, no allocation.
8034    pub fn frame_b(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8035        // SAFETY: an interior pointer into `self`, valid for this
8036        // borrow and never freed by the `Ref`.
8037        unsafe {
8038            crate::support::Ref::new(PhysicsFrame {
8039                raw: core::ptr::NonNull::new_unchecked(
8040                    ffi::whiteout_m2_M2ShoulderJoint_get_frameB(self.raw.as_ptr()),
8041                ),
8042            })
8043        }
8044    }
8045
8046    pub fn frame_b_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8047        // SAFETY: as above; `&mut self` guarantees exclusivity.
8048        unsafe {
8049            crate::support::RefMut::new(PhysicsFrame {
8050                raw: core::ptr::NonNull::new_unchecked(
8051                    ffi::whiteout_m2_M2ShoulderJoint_get_frameB(self.raw.as_ptr()),
8052                ),
8053            })
8054        }
8055    }
8056
8057    pub fn lower_twist_angle(&self) -> f32 {
8058        // SAFETY: plain scalar read through a live handle.
8059        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_lowerTwistAngle(self.raw.as_ptr()) }
8060    }
8061
8062    pub fn set_lower_twist_angle(&mut self, value: f32) {
8063        // SAFETY: plain scalar write through a live handle.
8064        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_lowerTwistAngle(self.raw.as_ptr(), value) }
8065    }
8066
8067    pub fn upper_twist_angle(&self) -> f32 {
8068        // SAFETY: plain scalar read through a live handle.
8069        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_upperTwistAngle(self.raw.as_ptr()) }
8070    }
8071
8072    pub fn set_upper_twist_angle(&mut self, value: f32) {
8073        // SAFETY: plain scalar write through a live handle.
8074        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_upperTwistAngle(self.raw.as_ptr(), value) }
8075    }
8076
8077    /// Degrees: the corpus holds 20, 35, 45 and 60, while `dmShoulderJoint` clamps its own cone to [10°, 170°] expressed in radians — so the loader converts on the way in.
8078    pub fn cone_angle(&self) -> f32 {
8079        // SAFETY: plain scalar read through a live handle.
8080        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_coneAngle(self.raw.as_ptr()) }
8081    }
8082
8083    pub fn set_cone_angle(&mut self, value: f32) {
8084        // SAFETY: plain scalar write through a live handle.
8085        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_coneAngle(self.raw.as_ptr(), value) }
8086    }
8087
8088    /// version 2+
8089    pub fn max_motor_torque(&self) -> f32 {
8090        // SAFETY: plain scalar read through a live handle.
8091        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_maxMotorTorque(self.raw.as_ptr()) }
8092    }
8093
8094    pub fn set_max_motor_torque(&mut self, value: f32) {
8095        // SAFETY: plain scalar write through a live handle.
8096        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_maxMotorTorque(self.raw.as_ptr(), value) }
8097    }
8098
8099    /// version 2+
8100    pub fn motor_mode(&self) -> u32 {
8101        // SAFETY: plain scalar read through a live handle.
8102        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_motorMode(self.raw.as_ptr()) }
8103    }
8104
8105    pub fn set_motor_mode(&mut self, value: u32) {
8106        // SAFETY: plain scalar write through a live handle.
8107        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_motorMode(self.raw.as_ptr(), value) }
8108    }
8109
8110    /// SHJ2
8111    pub fn motor_frequency_hz(&self) -> f32 {
8112        // SAFETY: plain scalar read through a live handle.
8113        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_motorFrequencyHz(self.raw.as_ptr()) }
8114    }
8115
8116    pub fn set_motor_frequency_hz(&mut self, value: f32) {
8117        // SAFETY: plain scalar write through a live handle.
8118        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_motorFrequencyHz(self.raw.as_ptr(), value) }
8119    }
8120
8121    /// SHJ2
8122    pub fn motor_damping_ratio(&self) -> f32 {
8123        // SAFETY: plain scalar read through a live handle.
8124        unsafe { ffi::whiteout_m2_M2ShoulderJoint_get_motorDampingRatio(self.raw.as_ptr()) }
8125    }
8126
8127    pub fn set_motor_damping_ratio(&mut self, value: f32) {
8128        // SAFETY: plain scalar write through a live handle.
8129        unsafe { ffi::whiteout_m2_M2ShoulderJoint_set_motorDampingRatio(self.raw.as_ptr(), value) }
8130    }
8131}
8132
8133impl Default for ShoulderJoint {
8134    fn default() -> Self {
8135        Self::new()
8136    }
8137}
8138
8139/// PRSJ/PRS2 — a sliding joint, version 2+.
8140pub struct PrismaticJoint {
8141    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PrismaticJoint>,
8142}
8143
8144impl Drop for PrismaticJoint {
8145    fn drop(&mut self) {
8146        // SAFETY: `raw` came from a native constructor and Drop runs once.
8147        unsafe { ffi::whiteout_m2_M2PrismaticJoint_delete(self.raw.as_ptr()) }
8148    }
8149}
8150
8151impl PrismaticJoint {
8152    /// # Safety
8153    /// `raw` must be a live handle this value takes ownership of.
8154    #[allow(dead_code)] // used by whichever methods return this type
8155    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PrismaticJoint) -> Option<Self> {
8156        core::ptr::NonNull::new(raw).map(|raw| PrismaticJoint { raw })
8157    }
8158}
8159
8160// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8161// is deliberately NOT implemented — the C++ types make no documented
8162// guarantee about concurrent use, and claiming one we haven't verified
8163// would be unsound. See `@bind thread_safe` in the plan.
8164unsafe impl Send for PrismaticJoint {}
8165
8166impl core::fmt::Debug for PrismaticJoint {
8167    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8168        f.debug_struct("PrismaticJoint").finish_non_exhaustive()
8169    }
8170}
8171
8172impl PrismaticJoint {
8173    /// # Panics
8174    /// Panics if the native allocation fails.
8175    pub fn new() -> Self {
8176        // SAFETY: the native constructor returns a live handle; a null here
8177        // means the library is unusable.
8178        unsafe {
8179            let raw = ffi::whiteout_m2_M2PrismaticJoint_new();
8180            Self::from_raw(raw).expect("native PrismaticJoint allocation failed")
8181        }
8182    }
8183
8184    /// Borrows the field in place — no copy, no allocation.
8185    pub fn frame_a(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8186        // SAFETY: an interior pointer into `self`, valid for this
8187        // borrow and never freed by the `Ref`.
8188        unsafe {
8189            crate::support::Ref::new(PhysicsFrame {
8190                raw: core::ptr::NonNull::new_unchecked(
8191                    ffi::whiteout_m2_M2PrismaticJoint_get_frameA(self.raw.as_ptr()),
8192                ),
8193            })
8194        }
8195    }
8196
8197    pub fn frame_a_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8198        // SAFETY: as above; `&mut self` guarantees exclusivity.
8199        unsafe {
8200            crate::support::RefMut::new(PhysicsFrame {
8201                raw: core::ptr::NonNull::new_unchecked(
8202                    ffi::whiteout_m2_M2PrismaticJoint_get_frameA(self.raw.as_ptr()),
8203                ),
8204            })
8205        }
8206    }
8207
8208    /// Borrows the field in place — no copy, no allocation.
8209    pub fn frame_b(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8210        // SAFETY: an interior pointer into `self`, valid for this
8211        // borrow and never freed by the `Ref`.
8212        unsafe {
8213            crate::support::Ref::new(PhysicsFrame {
8214                raw: core::ptr::NonNull::new_unchecked(
8215                    ffi::whiteout_m2_M2PrismaticJoint_get_frameB(self.raw.as_ptr()),
8216                ),
8217            })
8218        }
8219    }
8220
8221    pub fn frame_b_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8222        // SAFETY: as above; `&mut self` guarantees exclusivity.
8223        unsafe {
8224            crate::support::RefMut::new(PhysicsFrame {
8225                raw: core::ptr::NonNull::new_unchecked(
8226                    ffi::whiteout_m2_M2PrismaticJoint_get_frameB(self.raw.as_ptr()),
8227                ),
8228            })
8229        }
8230    }
8231
8232    pub fn lower_limit(&self) -> f32 {
8233        // SAFETY: plain scalar read through a live handle.
8234        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_lowerLimit(self.raw.as_ptr()) }
8235    }
8236
8237    pub fn set_lower_limit(&mut self, value: f32) {
8238        // SAFETY: plain scalar write through a live handle.
8239        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_lowerLimit(self.raw.as_ptr(), value) }
8240    }
8241
8242    pub fn upper_limit(&self) -> f32 {
8243        // SAFETY: plain scalar read through a live handle.
8244        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_upperLimit(self.raw.as_ptr()) }
8245    }
8246
8247    pub fn set_upper_limit(&mut self, value: f32) {
8248        // SAFETY: plain scalar write through a live handle.
8249        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_upperLimit(self.raw.as_ptr(), value) }
8250    }
8251
8252    /// Unidentified; zero in all twelve corpus prismatic joints. Domino's prismatic def carries an enable-limit flag next to the limit pair.
8253    pub fn unknown_68(&self) -> f32 {
8254        // SAFETY: plain scalar read through a live handle.
8255        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_unknown68(self.raw.as_ptr()) }
8256    }
8257
8258    pub fn set_unknown_68(&mut self, value: f32) {
8259        // SAFETY: plain scalar write through a live handle.
8260        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_unknown68(self.raw.as_ptr(), value) }
8261    }
8262
8263    pub fn max_motor_force(&self) -> f32 {
8264        // SAFETY: plain scalar read through a live handle.
8265        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_maxMotorForce(self.raw.as_ptr()) }
8266    }
8267
8268    pub fn set_max_motor_force(&mut self, value: f32) {
8269        // SAFETY: plain scalar write through a live handle.
8270        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_maxMotorForce(self.raw.as_ptr(), value) }
8271    }
8272
8273    /// Unidentified; zero in all twelve.
8274    pub fn unknown_70(&self) -> f32 {
8275        // SAFETY: plain scalar read through a live handle.
8276        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_unknown70(self.raw.as_ptr()) }
8277    }
8278
8279    pub fn set_unknown_70(&mut self, value: f32) {
8280        // SAFETY: plain scalar write through a live handle.
8281        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_unknown70(self.raw.as_ptr(), value) }
8282    }
8283
8284    pub fn motor_mode(&self) -> u32 {
8285        // SAFETY: plain scalar read through a live handle.
8286        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_motorMode(self.raw.as_ptr()) }
8287    }
8288
8289    pub fn set_motor_mode(&mut self, value: u32) {
8290        // SAFETY: plain scalar write through a live handle.
8291        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_motorMode(self.raw.as_ptr(), value) }
8292    }
8293
8294    /// PRS2
8295    pub fn motor_frequency_hz(&self) -> f32 {
8296        // SAFETY: plain scalar read through a live handle.
8297        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_motorFrequencyHz(self.raw.as_ptr()) }
8298    }
8299
8300    pub fn set_motor_frequency_hz(&mut self, value: f32) {
8301        // SAFETY: plain scalar write through a live handle.
8302        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_motorFrequencyHz(self.raw.as_ptr(), value) }
8303    }
8304
8305    /// PRS2
8306    pub fn motor_damping_ratio(&self) -> f32 {
8307        // SAFETY: plain scalar read through a live handle.
8308        unsafe { ffi::whiteout_m2_M2PrismaticJoint_get_motorDampingRatio(self.raw.as_ptr()) }
8309    }
8310
8311    pub fn set_motor_damping_ratio(&mut self, value: f32) {
8312        // SAFETY: plain scalar write through a live handle.
8313        unsafe { ffi::whiteout_m2_M2PrismaticJoint_set_motorDampingRatio(self.raw.as_ptr(), value) }
8314    }
8315}
8316
8317impl Default for PrismaticJoint {
8318    fn default() -> Self {
8319        Self::new()
8320    }
8321}
8322
8323/// REVJ/REV2 — a hinge, version 2+.
8324pub struct RevoluteJoint {
8325    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2RevoluteJoint>,
8326}
8327
8328impl Drop for RevoluteJoint {
8329    fn drop(&mut self) {
8330        // SAFETY: `raw` came from a native constructor and Drop runs once.
8331        unsafe { ffi::whiteout_m2_M2RevoluteJoint_delete(self.raw.as_ptr()) }
8332    }
8333}
8334
8335impl RevoluteJoint {
8336    /// # Safety
8337    /// `raw` must be a live handle this value takes ownership of.
8338    #[allow(dead_code)] // used by whichever methods return this type
8339    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2RevoluteJoint) -> Option<Self> {
8340        core::ptr::NonNull::new(raw).map(|raw| RevoluteJoint { raw })
8341    }
8342}
8343
8344// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8345// is deliberately NOT implemented — the C++ types make no documented
8346// guarantee about concurrent use, and claiming one we haven't verified
8347// would be unsound. See `@bind thread_safe` in the plan.
8348unsafe impl Send for RevoluteJoint {}
8349
8350impl core::fmt::Debug for RevoluteJoint {
8351    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8352        f.debug_struct("RevoluteJoint").finish_non_exhaustive()
8353    }
8354}
8355
8356impl RevoluteJoint {
8357    /// # Panics
8358    /// Panics if the native allocation fails.
8359    pub fn new() -> Self {
8360        // SAFETY: the native constructor returns a live handle; a null here
8361        // means the library is unusable.
8362        unsafe {
8363            let raw = ffi::whiteout_m2_M2RevoluteJoint_new();
8364            Self::from_raw(raw).expect("native RevoluteJoint allocation failed")
8365        }
8366    }
8367
8368    /// Borrows the field in place — no copy, no allocation.
8369    pub fn frame_a(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8370        // SAFETY: an interior pointer into `self`, valid for this
8371        // borrow and never freed by the `Ref`.
8372        unsafe {
8373            crate::support::Ref::new(PhysicsFrame {
8374                raw: core::ptr::NonNull::new_unchecked(
8375                    ffi::whiteout_m2_M2RevoluteJoint_get_frameA(self.raw.as_ptr()),
8376                ),
8377            })
8378        }
8379    }
8380
8381    pub fn frame_a_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8382        // SAFETY: as above; `&mut self` guarantees exclusivity.
8383        unsafe {
8384            crate::support::RefMut::new(PhysicsFrame {
8385                raw: core::ptr::NonNull::new_unchecked(
8386                    ffi::whiteout_m2_M2RevoluteJoint_get_frameA(self.raw.as_ptr()),
8387                ),
8388            })
8389        }
8390    }
8391
8392    /// Borrows the field in place — no copy, no allocation.
8393    pub fn frame_b(&self) -> crate::support::Ref<'_, PhysicsFrame> {
8394        // SAFETY: an interior pointer into `self`, valid for this
8395        // borrow and never freed by the `Ref`.
8396        unsafe {
8397            crate::support::Ref::new(PhysicsFrame {
8398                raw: core::ptr::NonNull::new_unchecked(
8399                    ffi::whiteout_m2_M2RevoluteJoint_get_frameB(self.raw.as_ptr()),
8400                ),
8401            })
8402        }
8403    }
8404
8405    pub fn frame_b_mut(&mut self) -> crate::support::RefMut<'_, PhysicsFrame> {
8406        // SAFETY: as above; `&mut self` guarantees exclusivity.
8407        unsafe {
8408            crate::support::RefMut::new(PhysicsFrame {
8409                raw: core::ptr::NonNull::new_unchecked(
8410                    ffi::whiteout_m2_M2RevoluteJoint_get_frameB(self.raw.as_ptr()),
8411                ),
8412            })
8413        }
8414    }
8415
8416    pub fn lower_angle(&self) -> f32 {
8417        // SAFETY: plain scalar read through a live handle.
8418        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_lowerAngle(self.raw.as_ptr()) }
8419    }
8420
8421    pub fn set_lower_angle(&mut self, value: f32) {
8422        // SAFETY: plain scalar write through a live handle.
8423        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_lowerAngle(self.raw.as_ptr(), value) }
8424    }
8425
8426    pub fn upper_angle(&self) -> f32 {
8427        // SAFETY: plain scalar read through a live handle.
8428        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_upperAngle(self.raw.as_ptr()) }
8429    }
8430
8431    pub fn set_upper_angle(&mut self, value: f32) {
8432        // SAFETY: plain scalar write through a live handle.
8433        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_upperAngle(self.raw.as_ptr(), value) }
8434    }
8435
8436    pub fn max_motor_torque(&self) -> f32 {
8437        // SAFETY: plain scalar read through a live handle.
8438        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_maxMotorTorque(self.raw.as_ptr()) }
8439    }
8440
8441    pub fn set_max_motor_torque(&mut self, value: f32) {
8442        // SAFETY: plain scalar write through a live handle.
8443        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_maxMotorTorque(self.raw.as_ptr(), value) }
8444    }
8445
8446    /// 1: position mode (frequency > 0), 2: velocity mode.
8447    pub fn motor_mode(&self) -> u32 {
8448        // SAFETY: plain scalar read through a live handle.
8449        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_motorMode(self.raw.as_ptr()) }
8450    }
8451
8452    pub fn set_motor_mode(&mut self, value: u32) {
8453        // SAFETY: plain scalar write through a live handle.
8454        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_motorMode(self.raw.as_ptr(), value) }
8455    }
8456
8457    /// REV2
8458    pub fn motor_frequency_hz(&self) -> f32 {
8459        // SAFETY: plain scalar read through a live handle.
8460        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_motorFrequencyHz(self.raw.as_ptr()) }
8461    }
8462
8463    pub fn set_motor_frequency_hz(&mut self, value: f32) {
8464        // SAFETY: plain scalar write through a live handle.
8465        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_motorFrequencyHz(self.raw.as_ptr(), value) }
8466    }
8467
8468    /// REV2
8469    pub fn motor_damping_ratio(&self) -> f32 {
8470        // SAFETY: plain scalar read through a live handle.
8471        unsafe { ffi::whiteout_m2_M2RevoluteJoint_get_motorDampingRatio(self.raw.as_ptr()) }
8472    }
8473
8474    pub fn set_motor_damping_ratio(&mut self, value: f32) {
8475        // SAFETY: plain scalar write through a live handle.
8476        unsafe { ffi::whiteout_m2_M2RevoluteJoint_set_motorDampingRatio(self.raw.as_ptr(), value) }
8477    }
8478}
8479
8480impl Default for RevoluteJoint {
8481    fn default() -> Self {
8482        Self::new()
8483    }
8484}
8485
8486/// DSTJ — holds two anchors a fixed distance apart, version 2+.
8487pub struct DistanceJoint {
8488    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2DistanceJoint>,
8489}
8490
8491impl Drop for DistanceJoint {
8492    fn drop(&mut self) {
8493        // SAFETY: `raw` came from a native constructor and Drop runs once.
8494        unsafe { ffi::whiteout_m2_M2DistanceJoint_delete(self.raw.as_ptr()) }
8495    }
8496}
8497
8498impl DistanceJoint {
8499    /// # Safety
8500    /// `raw` must be a live handle this value takes ownership of.
8501    #[allow(dead_code)] // used by whichever methods return this type
8502    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2DistanceJoint) -> Option<Self> {
8503        core::ptr::NonNull::new(raw).map(|raw| DistanceJoint { raw })
8504    }
8505}
8506
8507// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8508// is deliberately NOT implemented — the C++ types make no documented
8509// guarantee about concurrent use, and claiming one we haven't verified
8510// would be unsound. See `@bind thread_safe` in the plan.
8511unsafe impl Send for DistanceJoint {}
8512
8513impl core::fmt::Debug for DistanceJoint {
8514    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8515        f.debug_struct("DistanceJoint").finish_non_exhaustive()
8516    }
8517}
8518
8519impl DistanceJoint {
8520    /// # Panics
8521    /// Panics if the native allocation fails.
8522    pub fn new() -> Self {
8523        // SAFETY: the native constructor returns a live handle; a null here
8524        // means the library is unusable.
8525        unsafe {
8526            let raw = ffi::whiteout_m2_M2DistanceJoint_new();
8527            Self::from_raw(raw).expect("native DistanceJoint allocation failed")
8528        }
8529    }
8530
8531    pub fn local_anchor_a(&self) -> crate::math::Vector3f {
8532        // SAFETY: the getter returns an interior pointer to a
8533        // layout-identical POD; we copy it out immediately.
8534        unsafe {
8535            *(ffi::whiteout_m2_M2DistanceJoint_get_localAnchorA(self.raw.as_ptr())
8536                as *const crate::math::Vector3f)
8537        }
8538    }
8539
8540    pub fn set_local_anchor_a(&mut self, value: crate::math::Vector3f) {
8541        // SAFETY: as above, in the other direction.
8542        unsafe {
8543            ffi::whiteout_m2_M2DistanceJoint_set_localAnchorA(
8544                self.raw.as_ptr(),
8545                &value as *const crate::math::Vector3f as *const _,
8546            )
8547        }
8548    }
8549
8550    pub fn local_anchor_b(&self) -> crate::math::Vector3f {
8551        // SAFETY: the getter returns an interior pointer to a
8552        // layout-identical POD; we copy it out immediately.
8553        unsafe {
8554            *(ffi::whiteout_m2_M2DistanceJoint_get_localAnchorB(self.raw.as_ptr())
8555                as *const crate::math::Vector3f)
8556        }
8557    }
8558
8559    pub fn set_local_anchor_b(&mut self, value: crate::math::Vector3f) {
8560        // SAFETY: as above, in the other direction.
8561        unsafe {
8562            ffi::whiteout_m2_M2DistanceJoint_set_localAnchorB(
8563                self.raw.as_ptr(),
8564                &value as *const crate::math::Vector3f as *const _,
8565            )
8566        }
8567    }
8568
8569    pub fn distance(&self) -> f32 {
8570        // SAFETY: plain scalar read through a live handle.
8571        unsafe { ffi::whiteout_m2_M2DistanceJoint_get_distance(self.raw.as_ptr()) }
8572    }
8573
8574    pub fn set_distance(&mut self, value: f32) {
8575        // SAFETY: plain scalar write through a live handle.
8576        unsafe { ffi::whiteout_m2_M2DistanceJoint_set_distance(self.raw.as_ptr(), value) }
8577    }
8578}
8579
8580impl Default for DistanceJoint {
8581    fn default() -> Self {
8582        Self::new()
8583    }
8584}
8585
8586/// PHYV — six floats that overwrite the head of a tuning block the client otherwise fills with constants. Version 1+.
8587pub struct PhysicsTuning {
8588    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsTuning>,
8589}
8590
8591impl Drop for PhysicsTuning {
8592    fn drop(&mut self) {
8593        // SAFETY: `raw` came from a native constructor and Drop runs once.
8594        unsafe { ffi::whiteout_m2_M2PhysicsTuning_delete(self.raw.as_ptr()) }
8595    }
8596}
8597
8598impl PhysicsTuning {
8599    /// # Safety
8600    /// `raw` must be a live handle this value takes ownership of.
8601    #[allow(dead_code)] // used by whichever methods return this type
8602    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsTuning) -> Option<Self> {
8603        core::ptr::NonNull::new(raw).map(|raw| PhysicsTuning { raw })
8604    }
8605}
8606
8607// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8608// is deliberately NOT implemented — the C++ types make no documented
8609// guarantee about concurrent use, and claiming one we haven't verified
8610// would be unsound. See `@bind thread_safe` in the plan.
8611unsafe impl Send for PhysicsTuning {}
8612
8613impl core::fmt::Debug for PhysicsTuning {
8614    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8615        f.debug_struct("PhysicsTuning").finish_non_exhaustive()
8616    }
8617}
8618
8619impl PhysicsTuning {
8620    /// # Panics
8621    /// Panics if the native allocation fails.
8622    pub fn new() -> Self {
8623        // SAFETY: the native constructor returns a live handle; a null here
8624        // means the library is unusable.
8625        unsafe {
8626            let raw = ffi::whiteout_m2_M2PhysicsTuning_new();
8627            Self::from_raw(raw).expect("native PhysicsTuning allocation failed")
8628        }
8629    }
8630
8631    /// Number of elements — a fixed-size C++ array.
8632    pub const fn values_len() -> usize {
8633        6
8634    }
8635
8636    /// # Panics
8637    /// If `index >= 6`, matching Rust slice indexing.
8638    pub fn values(&self, index: usize) -> f32 {
8639        assert!(index < 6, "values index {index} out of range (len 6)");
8640        // SAFETY: index checked above; plain scalar read.
8641        unsafe { ffi::whiteout_m2_M2PhysicsTuning_get_values_at(self.raw.as_ptr(), index) }
8642    }
8643
8644    /// # Panics
8645    /// If `index >= 6`.
8646    pub fn set_values(&mut self, index: usize, value: f32) {
8647        assert!(index < 6, "values index {index} out of range (len 6)");
8648        // SAFETY: index checked above.
8649        unsafe { ffi::whiteout_m2_M2PhysicsTuning_set_values_at(self.raw.as_ptr(), index, value) }
8650    }
8651}
8652
8653impl Default for PhysicsTuning {
8654    fn default() -> Self {
8655        Self::new()
8656    }
8657}
8658
8659/// A `.phys` chunk this library does not know, kept verbatim so a parse/write cycle does not drop it.
8660pub struct PhysicsUnknownChunk {
8661    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsUnknownChunk>,
8662}
8663
8664impl Drop for PhysicsUnknownChunk {
8665    fn drop(&mut self) {
8666        // SAFETY: `raw` came from a native constructor and Drop runs once.
8667        unsafe { ffi::whiteout_m2_M2PhysicsUnknownChunk_delete(self.raw.as_ptr()) }
8668    }
8669}
8670
8671impl PhysicsUnknownChunk {
8672    /// # Safety
8673    /// `raw` must be a live handle this value takes ownership of.
8674    #[allow(dead_code)] // used by whichever methods return this type
8675    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsUnknownChunk) -> Option<Self> {
8676        core::ptr::NonNull::new(raw).map(|raw| PhysicsUnknownChunk { raw })
8677    }
8678}
8679
8680// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8681// is deliberately NOT implemented — the C++ types make no documented
8682// guarantee about concurrent use, and claiming one we haven't verified
8683// would be unsound. See `@bind thread_safe` in the plan.
8684unsafe impl Send for PhysicsUnknownChunk {}
8685
8686impl core::fmt::Debug for PhysicsUnknownChunk {
8687    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8688        f.debug_struct("PhysicsUnknownChunk")
8689            .finish_non_exhaustive()
8690    }
8691}
8692
8693impl PhysicsUnknownChunk {
8694    /// # Panics
8695    /// Panics if the native allocation fails.
8696    pub fn new() -> Self {
8697        // SAFETY: the native constructor returns a live handle; a null here
8698        // means the library is unusable.
8699        unsafe {
8700            let raw = ffi::whiteout_m2_M2PhysicsUnknownChunk_new();
8701            Self::from_raw(raw).expect("native PhysicsUnknownChunk allocation failed")
8702        }
8703    }
8704
8705    /// FourCC as written on disk — `.phys` stores chunk ids reversed, so a PHYS chunk reads as "SYHP".
8706    /// Number of elements — a fixed-size C++ array.
8707    pub const fn tag_len() -> usize {
8708        4
8709    }
8710
8711    /// # Panics
8712    /// If `index >= 4`, matching Rust slice indexing.
8713    pub fn tag(&self, index: usize) -> i8 {
8714        assert!(index < 4, "tag index {index} out of range (len 4)");
8715        // SAFETY: index checked above; plain scalar read.
8716        unsafe { ffi::whiteout_m2_M2PhysicsUnknownChunk_get_tag_at(self.raw.as_ptr(), index) }
8717    }
8718
8719    /// # Panics
8720    /// If `index >= 4`.
8721    pub fn set_tag(&mut self, index: usize, value: i8) {
8722        assert!(index < 4, "tag index {index} out of range (len 4)");
8723        // SAFETY: index checked above.
8724        unsafe {
8725            ffi::whiteout_m2_M2PhysicsUnknownChunk_set_tag_at(self.raw.as_ptr(), index, value)
8726        }
8727    }
8728
8729    /// Zero-copy view of the underlying `std::vector`.
8730    pub fn data(&self) -> &[u8] {
8731        // SAFETY: `_data`/`_count` describe one contiguous C++
8732        // allocation, borrowed for as long as `self` is.
8733        unsafe {
8734            let n = ffi::whiteout_m2_M2PhysicsUnknownChunk_get_data_count(self.raw.as_ptr());
8735            let p = ffi::whiteout_m2_M2PhysicsUnknownChunk_get_data_data(self.raw.as_ptr());
8736            if p.is_null() || n == 0 {
8737                &[]
8738            } else {
8739                core::slice::from_raw_parts(p, n)
8740            }
8741        }
8742    }
8743
8744    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
8745    pub fn data_mut(&mut self) -> &mut [u8] {
8746        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
8747        unsafe {
8748            let n = ffi::whiteout_m2_M2PhysicsUnknownChunk_get_data_count(self.raw.as_ptr());
8749            let p =
8750                ffi::whiteout_m2_M2PhysicsUnknownChunk_get_data_data(self.raw.as_ptr()) as *mut u8;
8751            if p.is_null() || n == 0 {
8752                &mut []
8753            } else {
8754                core::slice::from_raw_parts_mut(p, n)
8755            }
8756        }
8757    }
8758
8759    pub fn set_data(&mut self, values: &[u8]) {
8760        // SAFETY: the native side copies `values` before returning.
8761        unsafe {
8762            ffi::whiteout_m2_M2PhysicsUnknownChunk_assign_data(
8763                self.raw.as_ptr(),
8764                values.as_ptr() as *const _,
8765                values.len(),
8766            )
8767        }
8768    }
8769
8770    pub fn resize_data(&mut self, count: usize) {
8771        // SAFETY: reallocation is safe here precisely because
8772        // `&mut self` means no slice borrow is outstanding.
8773        unsafe { ffi::whiteout_m2_M2PhysicsUnknownChunk_resize_data(self.raw.as_ptr(), count) }
8774    }
8775}
8776
8777impl Default for PhysicsUnknownChunk {
8778    fn default() -> Self {
8779        Self::new()
8780    }
8781}
8782
8783/// A whole `.phys` file — Blizzard's Domino rigid-body setup for a model, either a `.phys` sibling or an M2's inline PFDC chunk.
8784///
8785/// Bodies attach to bones and are linked by joints; each body owns a run of @ref shapes, and each shape indexes the array its type names.
8786pub struct PhysicsData {
8787    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2PhysicsData>,
8788}
8789
8790impl Drop for PhysicsData {
8791    fn drop(&mut self) {
8792        // SAFETY: `raw` came from a native constructor and Drop runs once.
8793        unsafe { ffi::whiteout_m2_M2PhysicsData_delete(self.raw.as_ptr()) }
8794    }
8795}
8796
8797impl PhysicsData {
8798    /// # Safety
8799    /// `raw` must be a live handle this value takes ownership of.
8800    #[allow(dead_code)] // used by whichever methods return this type
8801    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2PhysicsData) -> Option<Self> {
8802        core::ptr::NonNull::new(raw).map(|raw| PhysicsData { raw })
8803    }
8804}
8805
8806// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
8807// is deliberately NOT implemented — the C++ types make no documented
8808// guarantee about concurrent use, and claiming one we haven't verified
8809// would be unsound. See `@bind thread_safe` in the plan.
8810unsafe impl Send for PhysicsData {}
8811
8812impl core::fmt::Debug for PhysicsData {
8813    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8814        f.debug_struct("PhysicsData").finish_non_exhaustive()
8815    }
8816}
8817
8818impl PhysicsData {
8819    /// # Panics
8820    /// Panics if the native allocation fails.
8821    pub fn new() -> Self {
8822        // SAFETY: the native constructor returns a live handle; a null here
8823        // means the library is unusable.
8824        unsafe {
8825            let raw = ffi::whiteout_m2_M2PhysicsData_new();
8826            Self::from_raw(raw).expect("native PhysicsData allocation failed")
8827        }
8828    }
8829
8830    /// 0 (MoP) through 6. Decides which layout each chunk is written in — see the per-field version notes on the structs above.
8831    pub fn version(&self) -> u16 {
8832        // SAFETY: plain scalar read through a live handle.
8833        unsafe { ffi::whiteout_m2_M2PhysicsData_get_version(self.raw.as_ptr()) }
8834    }
8835
8836    pub fn set_version(&mut self, value: u16) {
8837        // SAFETY: plain scalar write through a live handle.
8838        unsafe { ffi::whiteout_m2_M2PhysicsData_set_version(self.raw.as_ptr(), value) }
8839    }
8840
8841    pub fn bodies_len(&self) -> usize {
8842        // SAFETY: scalar read through a live handle.
8843        unsafe { ffi::whiteout_m2_M2PhysicsData_get_bodies_count(self.raw.as_ptr()) }
8844    }
8845
8846    /// Borrows element `index` in place. `None` when out of range.
8847    pub fn bodies(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsBody>> {
8848        if index >= self.bodies_len() {
8849            return None;
8850        }
8851        // SAFETY: index checked above; the pointer is interior to `self`.
8852        unsafe {
8853            Some(crate::support::Ref::new(PhysicsBody {
8854                raw: core::ptr::NonNull::new_unchecked(
8855                    ffi::whiteout_m2_M2PhysicsData_get_bodies_at(self.raw.as_ptr(), index),
8856                ),
8857            }))
8858        }
8859    }
8860
8861    pub fn bodies_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, PhysicsBody>> {
8862        if index >= self.bodies_len() {
8863            return None;
8864        }
8865        // SAFETY: as above; `&mut self` guarantees exclusivity.
8866        unsafe {
8867            Some(crate::support::RefMut::new(PhysicsBody {
8868                raw: core::ptr::NonNull::new_unchecked(
8869                    ffi::whiteout_m2_M2PhysicsData_get_bodies_at(self.raw.as_ptr(), index),
8870                ),
8871            }))
8872        }
8873    }
8874
8875    /// Iterate the elements, borrowing each in turn.
8876    pub fn bodies_iter(
8877        &self,
8878    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsBody>> {
8879        (0..self.bodies_len()).map(move |i| self.bodies(i).expect("index below len"))
8880    }
8881
8882    pub fn resize_bodies(&mut self, count: usize) {
8883        // SAFETY: exclusive access, so no borrow is outstanding.
8884        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_bodies(self.raw.as_ptr(), count) }
8885    }
8886
8887    pub fn shapes_len(&self) -> usize {
8888        // SAFETY: scalar read through a live handle.
8889        unsafe { ffi::whiteout_m2_M2PhysicsData_get_shapes_count(self.raw.as_ptr()) }
8890    }
8891
8892    /// Borrows element `index` in place. `None` when out of range.
8893    pub fn shapes(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsShape>> {
8894        if index >= self.shapes_len() {
8895            return None;
8896        }
8897        // SAFETY: index checked above; the pointer is interior to `self`.
8898        unsafe {
8899            Some(crate::support::Ref::new(PhysicsShape {
8900                raw: core::ptr::NonNull::new_unchecked(
8901                    ffi::whiteout_m2_M2PhysicsData_get_shapes_at(self.raw.as_ptr(), index),
8902                ),
8903            }))
8904        }
8905    }
8906
8907    pub fn shapes_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, PhysicsShape>> {
8908        if index >= self.shapes_len() {
8909            return None;
8910        }
8911        // SAFETY: as above; `&mut self` guarantees exclusivity.
8912        unsafe {
8913            Some(crate::support::RefMut::new(PhysicsShape {
8914                raw: core::ptr::NonNull::new_unchecked(
8915                    ffi::whiteout_m2_M2PhysicsData_get_shapes_at(self.raw.as_ptr(), index),
8916                ),
8917            }))
8918        }
8919    }
8920
8921    /// Iterate the elements, borrowing each in turn.
8922    pub fn shapes_iter(
8923        &self,
8924    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsShape>> {
8925        (0..self.shapes_len()).map(move |i| self.shapes(i).expect("index below len"))
8926    }
8927
8928    pub fn resize_shapes(&mut self, count: usize) {
8929        // SAFETY: exclusive access, so no borrow is outstanding.
8930        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_shapes(self.raw.as_ptr(), count) }
8931    }
8932
8933    pub fn box_shapes_len(&self) -> usize {
8934        // SAFETY: scalar read through a live handle.
8935        unsafe { ffi::whiteout_m2_M2PhysicsData_get_boxShapes_count(self.raw.as_ptr()) }
8936    }
8937
8938    /// Borrows element `index` in place. `None` when out of range.
8939    pub fn box_shapes(&self, index: usize) -> Option<crate::support::Ref<'_, BoxShape>> {
8940        if index >= self.box_shapes_len() {
8941            return None;
8942        }
8943        // SAFETY: index checked above; the pointer is interior to `self`.
8944        unsafe {
8945            Some(crate::support::Ref::new(BoxShape {
8946                raw: core::ptr::NonNull::new_unchecked(
8947                    ffi::whiteout_m2_M2PhysicsData_get_boxShapes_at(self.raw.as_ptr(), index),
8948                ),
8949            }))
8950        }
8951    }
8952
8953    pub fn box_shapes_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, BoxShape>> {
8954        if index >= self.box_shapes_len() {
8955            return None;
8956        }
8957        // SAFETY: as above; `&mut self` guarantees exclusivity.
8958        unsafe {
8959            Some(crate::support::RefMut::new(BoxShape {
8960                raw: core::ptr::NonNull::new_unchecked(
8961                    ffi::whiteout_m2_M2PhysicsData_get_boxShapes_at(self.raw.as_ptr(), index),
8962                ),
8963            }))
8964        }
8965    }
8966
8967    /// Iterate the elements, borrowing each in turn.
8968    pub fn box_shapes_iter(
8969        &self,
8970    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, BoxShape>> {
8971        (0..self.box_shapes_len()).map(move |i| self.box_shapes(i).expect("index below len"))
8972    }
8973
8974    pub fn resize_box_shapes(&mut self, count: usize) {
8975        // SAFETY: exclusive access, so no borrow is outstanding.
8976        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_boxShapes(self.raw.as_ptr(), count) }
8977    }
8978
8979    pub fn capsule_shapes_len(&self) -> usize {
8980        // SAFETY: scalar read through a live handle.
8981        unsafe { ffi::whiteout_m2_M2PhysicsData_get_capsuleShapes_count(self.raw.as_ptr()) }
8982    }
8983
8984    /// Borrows element `index` in place. `None` when out of range.
8985    pub fn capsule_shapes(&self, index: usize) -> Option<crate::support::Ref<'_, CapsuleShape>> {
8986        if index >= self.capsule_shapes_len() {
8987            return None;
8988        }
8989        // SAFETY: index checked above; the pointer is interior to `self`.
8990        unsafe {
8991            Some(crate::support::Ref::new(CapsuleShape {
8992                raw: core::ptr::NonNull::new_unchecked(
8993                    ffi::whiteout_m2_M2PhysicsData_get_capsuleShapes_at(self.raw.as_ptr(), index),
8994                ),
8995            }))
8996        }
8997    }
8998
8999    pub fn capsule_shapes_mut(
9000        &mut self,
9001        index: usize,
9002    ) -> Option<crate::support::RefMut<'_, CapsuleShape>> {
9003        if index >= self.capsule_shapes_len() {
9004            return None;
9005        }
9006        // SAFETY: as above; `&mut self` guarantees exclusivity.
9007        unsafe {
9008            Some(crate::support::RefMut::new(CapsuleShape {
9009                raw: core::ptr::NonNull::new_unchecked(
9010                    ffi::whiteout_m2_M2PhysicsData_get_capsuleShapes_at(self.raw.as_ptr(), index),
9011                ),
9012            }))
9013        }
9014    }
9015
9016    /// Iterate the elements, borrowing each in turn.
9017    pub fn capsule_shapes_iter(
9018        &self,
9019    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, CapsuleShape>> {
9020        (0..self.capsule_shapes_len())
9021            .map(move |i| self.capsule_shapes(i).expect("index below len"))
9022    }
9023
9024    pub fn resize_capsule_shapes(&mut self, count: usize) {
9025        // SAFETY: exclusive access, so no borrow is outstanding.
9026        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_capsuleShapes(self.raw.as_ptr(), count) }
9027    }
9028
9029    pub fn sphere_shapes_len(&self) -> usize {
9030        // SAFETY: scalar read through a live handle.
9031        unsafe { ffi::whiteout_m2_M2PhysicsData_get_sphereShapes_count(self.raw.as_ptr()) }
9032    }
9033
9034    /// Borrows element `index` in place. `None` when out of range.
9035    pub fn sphere_shapes(&self, index: usize) -> Option<crate::support::Ref<'_, SphereShape>> {
9036        if index >= self.sphere_shapes_len() {
9037            return None;
9038        }
9039        // SAFETY: index checked above; the pointer is interior to `self`.
9040        unsafe {
9041            Some(crate::support::Ref::new(SphereShape {
9042                raw: core::ptr::NonNull::new_unchecked(
9043                    ffi::whiteout_m2_M2PhysicsData_get_sphereShapes_at(self.raw.as_ptr(), index),
9044                ),
9045            }))
9046        }
9047    }
9048
9049    pub fn sphere_shapes_mut(
9050        &mut self,
9051        index: usize,
9052    ) -> Option<crate::support::RefMut<'_, SphereShape>> {
9053        if index >= self.sphere_shapes_len() {
9054            return None;
9055        }
9056        // SAFETY: as above; `&mut self` guarantees exclusivity.
9057        unsafe {
9058            Some(crate::support::RefMut::new(SphereShape {
9059                raw: core::ptr::NonNull::new_unchecked(
9060                    ffi::whiteout_m2_M2PhysicsData_get_sphereShapes_at(self.raw.as_ptr(), index),
9061                ),
9062            }))
9063        }
9064    }
9065
9066    /// Iterate the elements, borrowing each in turn.
9067    pub fn sphere_shapes_iter(
9068        &self,
9069    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SphereShape>> {
9070        (0..self.sphere_shapes_len()).map(move |i| self.sphere_shapes(i).expect("index below len"))
9071    }
9072
9073    pub fn resize_sphere_shapes(&mut self, count: usize) {
9074        // SAFETY: exclusive access, so no borrow is outstanding.
9075        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_sphereShapes(self.raw.as_ptr(), count) }
9076    }
9077
9078    pub fn polytope_shapes_len(&self) -> usize {
9079        // SAFETY: scalar read through a live handle.
9080        unsafe { ffi::whiteout_m2_M2PhysicsData_get_polytopeShapes_count(self.raw.as_ptr()) }
9081    }
9082
9083    /// Borrows element `index` in place. `None` when out of range.
9084    pub fn polytope_shapes(&self, index: usize) -> Option<crate::support::Ref<'_, PolytopeShape>> {
9085        if index >= self.polytope_shapes_len() {
9086            return None;
9087        }
9088        // SAFETY: index checked above; the pointer is interior to `self`.
9089        unsafe {
9090            Some(crate::support::Ref::new(PolytopeShape {
9091                raw: core::ptr::NonNull::new_unchecked(
9092                    ffi::whiteout_m2_M2PhysicsData_get_polytopeShapes_at(self.raw.as_ptr(), index),
9093                ),
9094            }))
9095        }
9096    }
9097
9098    pub fn polytope_shapes_mut(
9099        &mut self,
9100        index: usize,
9101    ) -> Option<crate::support::RefMut<'_, PolytopeShape>> {
9102        if index >= self.polytope_shapes_len() {
9103            return None;
9104        }
9105        // SAFETY: as above; `&mut self` guarantees exclusivity.
9106        unsafe {
9107            Some(crate::support::RefMut::new(PolytopeShape {
9108                raw: core::ptr::NonNull::new_unchecked(
9109                    ffi::whiteout_m2_M2PhysicsData_get_polytopeShapes_at(self.raw.as_ptr(), index),
9110                ),
9111            }))
9112        }
9113    }
9114
9115    /// Iterate the elements, borrowing each in turn.
9116    pub fn polytope_shapes_iter(
9117        &self,
9118    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PolytopeShape>> {
9119        (0..self.polytope_shapes_len())
9120            .map(move |i| self.polytope_shapes(i).expect("index below len"))
9121    }
9122
9123    pub fn resize_polytope_shapes(&mut self, count: usize) {
9124        // SAFETY: exclusive access, so no borrow is outstanding.
9125        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_polytopeShapes(self.raw.as_ptr(), count) }
9126    }
9127
9128    pub fn joints_len(&self) -> usize {
9129        // SAFETY: scalar read through a live handle.
9130        unsafe { ffi::whiteout_m2_M2PhysicsData_get_joints_count(self.raw.as_ptr()) }
9131    }
9132
9133    /// Borrows element `index` in place. `None` when out of range.
9134    pub fn joints(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsJoint>> {
9135        if index >= self.joints_len() {
9136            return None;
9137        }
9138        // SAFETY: index checked above; the pointer is interior to `self`.
9139        unsafe {
9140            Some(crate::support::Ref::new(PhysicsJoint {
9141                raw: core::ptr::NonNull::new_unchecked(
9142                    ffi::whiteout_m2_M2PhysicsData_get_joints_at(self.raw.as_ptr(), index),
9143                ),
9144            }))
9145        }
9146    }
9147
9148    pub fn joints_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, PhysicsJoint>> {
9149        if index >= self.joints_len() {
9150            return None;
9151        }
9152        // SAFETY: as above; `&mut self` guarantees exclusivity.
9153        unsafe {
9154            Some(crate::support::RefMut::new(PhysicsJoint {
9155                raw: core::ptr::NonNull::new_unchecked(
9156                    ffi::whiteout_m2_M2PhysicsData_get_joints_at(self.raw.as_ptr(), index),
9157                ),
9158            }))
9159        }
9160    }
9161
9162    /// Iterate the elements, borrowing each in turn.
9163    pub fn joints_iter(
9164        &self,
9165    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsJoint>> {
9166        (0..self.joints_len()).map(move |i| self.joints(i).expect("index below len"))
9167    }
9168
9169    pub fn resize_joints(&mut self, count: usize) {
9170        // SAFETY: exclusive access, so no borrow is outstanding.
9171        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_joints(self.raw.as_ptr(), count) }
9172    }
9173
9174    pub fn weld_joints_len(&self) -> usize {
9175        // SAFETY: scalar read through a live handle.
9176        unsafe { ffi::whiteout_m2_M2PhysicsData_get_weldJoints_count(self.raw.as_ptr()) }
9177    }
9178
9179    /// Borrows element `index` in place. `None` when out of range.
9180    pub fn weld_joints(&self, index: usize) -> Option<crate::support::Ref<'_, WeldJoint>> {
9181        if index >= self.weld_joints_len() {
9182            return None;
9183        }
9184        // SAFETY: index checked above; the pointer is interior to `self`.
9185        unsafe {
9186            Some(crate::support::Ref::new(WeldJoint {
9187                raw: core::ptr::NonNull::new_unchecked(
9188                    ffi::whiteout_m2_M2PhysicsData_get_weldJoints_at(self.raw.as_ptr(), index),
9189                ),
9190            }))
9191        }
9192    }
9193
9194    pub fn weld_joints_mut(
9195        &mut self,
9196        index: usize,
9197    ) -> Option<crate::support::RefMut<'_, WeldJoint>> {
9198        if index >= self.weld_joints_len() {
9199            return None;
9200        }
9201        // SAFETY: as above; `&mut self` guarantees exclusivity.
9202        unsafe {
9203            Some(crate::support::RefMut::new(WeldJoint {
9204                raw: core::ptr::NonNull::new_unchecked(
9205                    ffi::whiteout_m2_M2PhysicsData_get_weldJoints_at(self.raw.as_ptr(), index),
9206                ),
9207            }))
9208        }
9209    }
9210
9211    /// Iterate the elements, borrowing each in turn.
9212    pub fn weld_joints_iter(
9213        &self,
9214    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, WeldJoint>> {
9215        (0..self.weld_joints_len()).map(move |i| self.weld_joints(i).expect("index below len"))
9216    }
9217
9218    pub fn resize_weld_joints(&mut self, count: usize) {
9219        // SAFETY: exclusive access, so no borrow is outstanding.
9220        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_weldJoints(self.raw.as_ptr(), count) }
9221    }
9222
9223    pub fn spherical_joints_len(&self) -> usize {
9224        // SAFETY: scalar read through a live handle.
9225        unsafe { ffi::whiteout_m2_M2PhysicsData_get_sphericalJoints_count(self.raw.as_ptr()) }
9226    }
9227
9228    /// Borrows element `index` in place. `None` when out of range.
9229    pub fn spherical_joints(
9230        &self,
9231        index: usize,
9232    ) -> Option<crate::support::Ref<'_, SphericalJoint>> {
9233        if index >= self.spherical_joints_len() {
9234            return None;
9235        }
9236        // SAFETY: index checked above; the pointer is interior to `self`.
9237        unsafe {
9238            Some(crate::support::Ref::new(SphericalJoint {
9239                raw: core::ptr::NonNull::new_unchecked(
9240                    ffi::whiteout_m2_M2PhysicsData_get_sphericalJoints_at(self.raw.as_ptr(), index),
9241                ),
9242            }))
9243        }
9244    }
9245
9246    pub fn spherical_joints_mut(
9247        &mut self,
9248        index: usize,
9249    ) -> Option<crate::support::RefMut<'_, SphericalJoint>> {
9250        if index >= self.spherical_joints_len() {
9251            return None;
9252        }
9253        // SAFETY: as above; `&mut self` guarantees exclusivity.
9254        unsafe {
9255            Some(crate::support::RefMut::new(SphericalJoint {
9256                raw: core::ptr::NonNull::new_unchecked(
9257                    ffi::whiteout_m2_M2PhysicsData_get_sphericalJoints_at(self.raw.as_ptr(), index),
9258                ),
9259            }))
9260        }
9261    }
9262
9263    /// Iterate the elements, borrowing each in turn.
9264    pub fn spherical_joints_iter(
9265        &self,
9266    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SphericalJoint>> {
9267        (0..self.spherical_joints_len())
9268            .map(move |i| self.spherical_joints(i).expect("index below len"))
9269    }
9270
9271    pub fn resize_spherical_joints(&mut self, count: usize) {
9272        // SAFETY: exclusive access, so no borrow is outstanding.
9273        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_sphericalJoints(self.raw.as_ptr(), count) }
9274    }
9275
9276    pub fn shoulder_joints_len(&self) -> usize {
9277        // SAFETY: scalar read through a live handle.
9278        unsafe { ffi::whiteout_m2_M2PhysicsData_get_shoulderJoints_count(self.raw.as_ptr()) }
9279    }
9280
9281    /// Borrows element `index` in place. `None` when out of range.
9282    pub fn shoulder_joints(&self, index: usize) -> Option<crate::support::Ref<'_, ShoulderJoint>> {
9283        if index >= self.shoulder_joints_len() {
9284            return None;
9285        }
9286        // SAFETY: index checked above; the pointer is interior to `self`.
9287        unsafe {
9288            Some(crate::support::Ref::new(ShoulderJoint {
9289                raw: core::ptr::NonNull::new_unchecked(
9290                    ffi::whiteout_m2_M2PhysicsData_get_shoulderJoints_at(self.raw.as_ptr(), index),
9291                ),
9292            }))
9293        }
9294    }
9295
9296    pub fn shoulder_joints_mut(
9297        &mut self,
9298        index: usize,
9299    ) -> Option<crate::support::RefMut<'_, ShoulderJoint>> {
9300        if index >= self.shoulder_joints_len() {
9301            return None;
9302        }
9303        // SAFETY: as above; `&mut self` guarantees exclusivity.
9304        unsafe {
9305            Some(crate::support::RefMut::new(ShoulderJoint {
9306                raw: core::ptr::NonNull::new_unchecked(
9307                    ffi::whiteout_m2_M2PhysicsData_get_shoulderJoints_at(self.raw.as_ptr(), index),
9308                ),
9309            }))
9310        }
9311    }
9312
9313    /// Iterate the elements, borrowing each in turn.
9314    pub fn shoulder_joints_iter(
9315        &self,
9316    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ShoulderJoint>> {
9317        (0..self.shoulder_joints_len())
9318            .map(move |i| self.shoulder_joints(i).expect("index below len"))
9319    }
9320
9321    pub fn resize_shoulder_joints(&mut self, count: usize) {
9322        // SAFETY: exclusive access, so no borrow is outstanding.
9323        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_shoulderJoints(self.raw.as_ptr(), count) }
9324    }
9325
9326    pub fn prismatic_joints_len(&self) -> usize {
9327        // SAFETY: scalar read through a live handle.
9328        unsafe { ffi::whiteout_m2_M2PhysicsData_get_prismaticJoints_count(self.raw.as_ptr()) }
9329    }
9330
9331    /// Borrows element `index` in place. `None` when out of range.
9332    pub fn prismatic_joints(
9333        &self,
9334        index: usize,
9335    ) -> Option<crate::support::Ref<'_, PrismaticJoint>> {
9336        if index >= self.prismatic_joints_len() {
9337            return None;
9338        }
9339        // SAFETY: index checked above; the pointer is interior to `self`.
9340        unsafe {
9341            Some(crate::support::Ref::new(PrismaticJoint {
9342                raw: core::ptr::NonNull::new_unchecked(
9343                    ffi::whiteout_m2_M2PhysicsData_get_prismaticJoints_at(self.raw.as_ptr(), index),
9344                ),
9345            }))
9346        }
9347    }
9348
9349    pub fn prismatic_joints_mut(
9350        &mut self,
9351        index: usize,
9352    ) -> Option<crate::support::RefMut<'_, PrismaticJoint>> {
9353        if index >= self.prismatic_joints_len() {
9354            return None;
9355        }
9356        // SAFETY: as above; `&mut self` guarantees exclusivity.
9357        unsafe {
9358            Some(crate::support::RefMut::new(PrismaticJoint {
9359                raw: core::ptr::NonNull::new_unchecked(
9360                    ffi::whiteout_m2_M2PhysicsData_get_prismaticJoints_at(self.raw.as_ptr(), index),
9361                ),
9362            }))
9363        }
9364    }
9365
9366    /// Iterate the elements, borrowing each in turn.
9367    pub fn prismatic_joints_iter(
9368        &self,
9369    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PrismaticJoint>> {
9370        (0..self.prismatic_joints_len())
9371            .map(move |i| self.prismatic_joints(i).expect("index below len"))
9372    }
9373
9374    pub fn resize_prismatic_joints(&mut self, count: usize) {
9375        // SAFETY: exclusive access, so no borrow is outstanding.
9376        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_prismaticJoints(self.raw.as_ptr(), count) }
9377    }
9378
9379    pub fn revolute_joints_len(&self) -> usize {
9380        // SAFETY: scalar read through a live handle.
9381        unsafe { ffi::whiteout_m2_M2PhysicsData_get_revoluteJoints_count(self.raw.as_ptr()) }
9382    }
9383
9384    /// Borrows element `index` in place. `None` when out of range.
9385    pub fn revolute_joints(&self, index: usize) -> Option<crate::support::Ref<'_, RevoluteJoint>> {
9386        if index >= self.revolute_joints_len() {
9387            return None;
9388        }
9389        // SAFETY: index checked above; the pointer is interior to `self`.
9390        unsafe {
9391            Some(crate::support::Ref::new(RevoluteJoint {
9392                raw: core::ptr::NonNull::new_unchecked(
9393                    ffi::whiteout_m2_M2PhysicsData_get_revoluteJoints_at(self.raw.as_ptr(), index),
9394                ),
9395            }))
9396        }
9397    }
9398
9399    pub fn revolute_joints_mut(
9400        &mut self,
9401        index: usize,
9402    ) -> Option<crate::support::RefMut<'_, RevoluteJoint>> {
9403        if index >= self.revolute_joints_len() {
9404            return None;
9405        }
9406        // SAFETY: as above; `&mut self` guarantees exclusivity.
9407        unsafe {
9408            Some(crate::support::RefMut::new(RevoluteJoint {
9409                raw: core::ptr::NonNull::new_unchecked(
9410                    ffi::whiteout_m2_M2PhysicsData_get_revoluteJoints_at(self.raw.as_ptr(), index),
9411                ),
9412            }))
9413        }
9414    }
9415
9416    /// Iterate the elements, borrowing each in turn.
9417    pub fn revolute_joints_iter(
9418        &self,
9419    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, RevoluteJoint>> {
9420        (0..self.revolute_joints_len())
9421            .map(move |i| self.revolute_joints(i).expect("index below len"))
9422    }
9423
9424    pub fn resize_revolute_joints(&mut self, count: usize) {
9425        // SAFETY: exclusive access, so no borrow is outstanding.
9426        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_revoluteJoints(self.raw.as_ptr(), count) }
9427    }
9428
9429    pub fn distance_joints_len(&self) -> usize {
9430        // SAFETY: scalar read through a live handle.
9431        unsafe { ffi::whiteout_m2_M2PhysicsData_get_distanceJoints_count(self.raw.as_ptr()) }
9432    }
9433
9434    /// Borrows element `index` in place. `None` when out of range.
9435    pub fn distance_joints(&self, index: usize) -> Option<crate::support::Ref<'_, DistanceJoint>> {
9436        if index >= self.distance_joints_len() {
9437            return None;
9438        }
9439        // SAFETY: index checked above; the pointer is interior to `self`.
9440        unsafe {
9441            Some(crate::support::Ref::new(DistanceJoint {
9442                raw: core::ptr::NonNull::new_unchecked(
9443                    ffi::whiteout_m2_M2PhysicsData_get_distanceJoints_at(self.raw.as_ptr(), index),
9444                ),
9445            }))
9446        }
9447    }
9448
9449    pub fn distance_joints_mut(
9450        &mut self,
9451        index: usize,
9452    ) -> Option<crate::support::RefMut<'_, DistanceJoint>> {
9453        if index >= self.distance_joints_len() {
9454            return None;
9455        }
9456        // SAFETY: as above; `&mut self` guarantees exclusivity.
9457        unsafe {
9458            Some(crate::support::RefMut::new(DistanceJoint {
9459                raw: core::ptr::NonNull::new_unchecked(
9460                    ffi::whiteout_m2_M2PhysicsData_get_distanceJoints_at(self.raw.as_ptr(), index),
9461                ),
9462            }))
9463        }
9464    }
9465
9466    /// Iterate the elements, borrowing each in turn.
9467    pub fn distance_joints_iter(
9468        &self,
9469    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DistanceJoint>> {
9470        (0..self.distance_joints_len())
9471            .map(move |i| self.distance_joints(i).expect("index below len"))
9472    }
9473
9474    pub fn resize_distance_joints(&mut self, count: usize) {
9475        // SAFETY: exclusive access, so no borrow is outstanding.
9476        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_distanceJoints(self.raw.as_ptr(), count) }
9477    }
9478
9479    /// PHYV. A file that has one carries nothing else.
9480    pub fn tuning_len(&self) -> usize {
9481        // SAFETY: scalar read through a live handle.
9482        unsafe { ffi::whiteout_m2_M2PhysicsData_get_tuning_count(self.raw.as_ptr()) }
9483    }
9484
9485    /// Borrows element `index` in place. `None` when out of range.
9486    pub fn tuning(&self, index: usize) -> Option<crate::support::Ref<'_, PhysicsTuning>> {
9487        if index >= self.tuning_len() {
9488            return None;
9489        }
9490        // SAFETY: index checked above; the pointer is interior to `self`.
9491        unsafe {
9492            Some(crate::support::Ref::new(PhysicsTuning {
9493                raw: core::ptr::NonNull::new_unchecked(
9494                    ffi::whiteout_m2_M2PhysicsData_get_tuning_at(self.raw.as_ptr(), index),
9495                ),
9496            }))
9497        }
9498    }
9499
9500    pub fn tuning_mut(
9501        &mut self,
9502        index: usize,
9503    ) -> Option<crate::support::RefMut<'_, PhysicsTuning>> {
9504        if index >= self.tuning_len() {
9505            return None;
9506        }
9507        // SAFETY: as above; `&mut self` guarantees exclusivity.
9508        unsafe {
9509            Some(crate::support::RefMut::new(PhysicsTuning {
9510                raw: core::ptr::NonNull::new_unchecked(
9511                    ffi::whiteout_m2_M2PhysicsData_get_tuning_at(self.raw.as_ptr(), index),
9512                ),
9513            }))
9514        }
9515    }
9516
9517    /// Iterate the elements, borrowing each in turn.
9518    pub fn tuning_iter(
9519        &self,
9520    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PhysicsTuning>> {
9521        (0..self.tuning_len()).map(move |i| self.tuning(i).expect("index below len"))
9522    }
9523
9524    pub fn resize_tuning(&mut self, count: usize) {
9525        // SAFETY: exclusive access, so no borrow is outstanding.
9526        unsafe { ffi::whiteout_m2_M2PhysicsData_resize_tuning(self.raw.as_ptr(), count) }
9527    }
9528}
9529
9530impl Default for PhysicsData {
9531    fn default() -> Self {
9532        Self::new()
9533    }
9534}
9535
9536/// One bone's replacement transform, from a `.bone` file.
9537pub struct BoneOverride {
9538    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2BoneOverride>,
9539}
9540
9541impl Drop for BoneOverride {
9542    fn drop(&mut self) {
9543        // SAFETY: `raw` came from a native constructor and Drop runs once.
9544        unsafe { ffi::whiteout_m2_M2BoneOverride_delete(self.raw.as_ptr()) }
9545    }
9546}
9547
9548impl BoneOverride {
9549    /// # Safety
9550    /// `raw` must be a live handle this value takes ownership of.
9551    #[allow(dead_code)] // used by whichever methods return this type
9552    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2BoneOverride) -> Option<Self> {
9553        core::ptr::NonNull::new(raw).map(|raw| BoneOverride { raw })
9554    }
9555}
9556
9557// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9558// is deliberately NOT implemented — the C++ types make no documented
9559// guarantee about concurrent use, and claiming one we haven't verified
9560// would be unsound. See `@bind thread_safe` in the plan.
9561unsafe impl Send for BoneOverride {}
9562
9563impl core::fmt::Debug for BoneOverride {
9564    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9565        f.debug_struct("BoneOverride").finish_non_exhaustive()
9566    }
9567}
9568
9569impl BoneOverride {
9570    /// # Panics
9571    /// Panics if the native allocation fails.
9572    pub fn new() -> Self {
9573        // SAFETY: the native constructor returns a live handle; a null here
9574        // means the library is unusable.
9575        unsafe {
9576            let raw = ffi::whiteout_m2_M2BoneOverride_new();
9577            Self::from_raw(raw).expect("native BoneOverride allocation failed")
9578        }
9579    }
9580
9581    /// Indexes Model::bones. Every id in the WoW corpus is below its model's bone count, and the ids within a file are strictly ascending.
9582    pub fn bone_index(&self) -> u16 {
9583        // SAFETY: plain scalar read through a live handle.
9584        unsafe { ffi::whiteout_m2_M2BoneOverride_get_boneIndex(self.raw.as_ptr()) }
9585    }
9586
9587    pub fn set_bone_index(&mut self, value: u16) {
9588        // SAFETY: plain scalar write through a live handle.
9589        unsafe { ffi::whiteout_m2_M2BoneOverride_set_boneIndex(self.raw.as_ptr(), value) }
9590    }
9591}
9592
9593impl Default for BoneOverride {
9594    fn default() -> Self {
9595        Self::new()
9596    }
9597}
9598
9599/// A whole `.bone` file: the skeleton edits one customization choice needs.
9600///
9601/// On disk this is two parallel chunks — `BIDA` holds the bone ids and `BOMT` the matrices — but their lengths match in every corpus file, so they are paired here and split again on write.
9602pub struct BoneOverrideSet {
9603    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2BoneOverrideSet>,
9604}
9605
9606impl Drop for BoneOverrideSet {
9607    fn drop(&mut self) {
9608        // SAFETY: `raw` came from a native constructor and Drop runs once.
9609        unsafe { ffi::whiteout_m2_M2BoneOverrideSet_delete(self.raw.as_ptr()) }
9610    }
9611}
9612
9613impl BoneOverrideSet {
9614    /// # Safety
9615    /// `raw` must be a live handle this value takes ownership of.
9616    #[allow(dead_code)] // used by whichever methods return this type
9617    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2BoneOverrideSet) -> Option<Self> {
9618        core::ptr::NonNull::new(raw).map(|raw| BoneOverrideSet { raw })
9619    }
9620}
9621
9622// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9623// is deliberately NOT implemented — the C++ types make no documented
9624// guarantee about concurrent use, and claiming one we haven't verified
9625// would be unsound. See `@bind thread_safe` in the plan.
9626unsafe impl Send for BoneOverrideSet {}
9627
9628impl core::fmt::Debug for BoneOverrideSet {
9629    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9630        f.debug_struct("BoneOverrideSet").finish_non_exhaustive()
9631    }
9632}
9633
9634impl BoneOverrideSet {
9635    /// # Panics
9636    /// Panics if the native allocation fails.
9637    pub fn new() -> Self {
9638        // SAFETY: the native constructor returns a live handle; a null here
9639        // means the library is unusable.
9640        unsafe {
9641            let raw = ffi::whiteout_m2_M2BoneOverrideSet_new();
9642            Self::from_raw(raw).expect("native BoneOverrideSet allocation failed")
9643        }
9644    }
9645
9646    /// 1 in every known file.
9647    pub fn version(&self) -> u32 {
9648        // SAFETY: plain scalar read through a live handle.
9649        unsafe { ffi::whiteout_m2_M2BoneOverrideSet_get_version(self.raw.as_ptr()) }
9650    }
9651
9652    pub fn set_version(&mut self, value: u32) {
9653        // SAFETY: plain scalar write through a live handle.
9654        unsafe { ffi::whiteout_m2_M2BoneOverrideSet_set_version(self.raw.as_ptr(), value) }
9655    }
9656
9657    /// Ascending by @ref BoneOverride::boneIndex, which is the order the files store and what lets the client binary-search a bone.
9658    pub fn overrides_len(&self) -> usize {
9659        // SAFETY: scalar read through a live handle.
9660        unsafe { ffi::whiteout_m2_M2BoneOverrideSet_get_overrides_count(self.raw.as_ptr()) }
9661    }
9662
9663    /// Borrows element `index` in place. `None` when out of range.
9664    pub fn overrides(&self, index: usize) -> Option<crate::support::Ref<'_, BoneOverride>> {
9665        if index >= self.overrides_len() {
9666            return None;
9667        }
9668        // SAFETY: index checked above; the pointer is interior to `self`.
9669        unsafe {
9670            Some(crate::support::Ref::new(BoneOverride {
9671                raw: core::ptr::NonNull::new_unchecked(
9672                    ffi::whiteout_m2_M2BoneOverrideSet_get_overrides_at(self.raw.as_ptr(), index),
9673                ),
9674            }))
9675        }
9676    }
9677
9678    pub fn overrides_mut(
9679        &mut self,
9680        index: usize,
9681    ) -> Option<crate::support::RefMut<'_, BoneOverride>> {
9682        if index >= self.overrides_len() {
9683            return None;
9684        }
9685        // SAFETY: as above; `&mut self` guarantees exclusivity.
9686        unsafe {
9687            Some(crate::support::RefMut::new(BoneOverride {
9688                raw: core::ptr::NonNull::new_unchecked(
9689                    ffi::whiteout_m2_M2BoneOverrideSet_get_overrides_at(self.raw.as_ptr(), index),
9690                ),
9691            }))
9692        }
9693    }
9694
9695    /// Iterate the elements, borrowing each in turn.
9696    pub fn overrides_iter(
9697        &self,
9698    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, BoneOverride>> {
9699        (0..self.overrides_len()).map(move |i| self.overrides(i).expect("index below len"))
9700    }
9701
9702    pub fn resize_overrides(&mut self, count: usize) {
9703        // SAFETY: exclusive access, so no borrow is outstanding.
9704        unsafe { ffi::whiteout_m2_M2BoneOverrideSet_resize_overrides(self.raw.as_ptr(), count) }
9705    }
9706}
9707
9708impl Default for BoneOverrideSet {
9709    fn default() -> Self {
9710        Self::new()
9711    }
9712}
9713
9714pub struct Model {
9715    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Model>,
9716}
9717
9718impl Drop for Model {
9719    fn drop(&mut self) {
9720        // SAFETY: `raw` came from a native constructor and Drop runs once.
9721        unsafe { ffi::whiteout_m2_M2Model_delete(self.raw.as_ptr()) }
9722    }
9723}
9724
9725impl Model {
9726    /// # Safety
9727    /// `raw` must be a live handle this value takes ownership of.
9728    #[allow(dead_code)] // used by whichever methods return this type
9729    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Model) -> Option<Self> {
9730        core::ptr::NonNull::new(raw).map(|raw| Model { raw })
9731    }
9732}
9733
9734// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
9735// is deliberately NOT implemented — the C++ types make no documented
9736// guarantee about concurrent use, and claiming one we haven't verified
9737// would be unsound. See `@bind thread_safe` in the plan.
9738unsafe impl Send for Model {}
9739
9740impl core::fmt::Debug for Model {
9741    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9742        f.debug_struct("Model").finish_non_exhaustive()
9743    }
9744}
9745
9746impl Model {
9747    /// # Panics
9748    /// Panics if the native allocation fails.
9749    pub fn new() -> Self {
9750        // SAFETY: the native constructor returns a live handle; a null here
9751        // means the library is unusable.
9752        unsafe {
9753            let raw = ffi::whiteout_m2_M2Model_new();
9754            Self::from_raw(raw).expect("native Model allocation failed")
9755        }
9756    }
9757
9758    pub fn model_name(&self) -> String {
9759        // SAFETY: the native side hands over an owned CString.
9760        unsafe {
9761            crate::support::take_string(ffi::whiteout_m2_M2Model_get_modelName(self.raw.as_ptr()))
9762        }
9763    }
9764
9765    pub fn set_model_name(&mut self, value: &str) {
9766        let value = std::ffi::CString::new(value).unwrap_or_default();
9767        // SAFETY: the pointer outlives the call.
9768        unsafe { ffi::whiteout_m2_M2Model_set_modelName(self.raw.as_ptr(), value.as_ptr()) }
9769    }
9770
9771    /// Borrows the field in place — no copy, no allocation.
9772    pub fn global_flags(&self) -> crate::support::Ref<'_, GlobalFlags> {
9773        // SAFETY: an interior pointer into `self`, valid for this
9774        // borrow and never freed by the `Ref`.
9775        unsafe {
9776            crate::support::Ref::new(GlobalFlags {
9777                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_globalFlags(
9778                    self.raw.as_ptr(),
9779                )),
9780            })
9781        }
9782    }
9783
9784    pub fn global_flags_mut(&mut self) -> crate::support::RefMut<'_, GlobalFlags> {
9785        // SAFETY: as above; `&mut self` guarantees exclusivity.
9786        unsafe {
9787            crate::support::RefMut::new(GlobalFlags {
9788                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_globalFlags(
9789                    self.raw.as_ptr(),
9790                )),
9791            })
9792        }
9793    }
9794
9795    pub fn global_loops_len(&self) -> usize {
9796        // SAFETY: scalar read through a live handle.
9797        unsafe { ffi::whiteout_m2_M2Model_get_globalLoops_count(self.raw.as_ptr()) }
9798    }
9799
9800    /// Borrows element `index` in place. `None` when out of range.
9801    pub fn global_loops(&self, index: usize) -> Option<crate::support::Ref<'_, GlobalSequence>> {
9802        if index >= self.global_loops_len() {
9803            return None;
9804        }
9805        // SAFETY: index checked above; the pointer is interior to `self`.
9806        unsafe {
9807            Some(crate::support::Ref::new(GlobalSequence {
9808                raw: core::ptr::NonNull::new_unchecked(
9809                    ffi::whiteout_m2_M2Model_get_globalLoops_at(self.raw.as_ptr(), index),
9810                ),
9811            }))
9812        }
9813    }
9814
9815    pub fn global_loops_mut(
9816        &mut self,
9817        index: usize,
9818    ) -> Option<crate::support::RefMut<'_, GlobalSequence>> {
9819        if index >= self.global_loops_len() {
9820            return None;
9821        }
9822        // SAFETY: as above; `&mut self` guarantees exclusivity.
9823        unsafe {
9824            Some(crate::support::RefMut::new(GlobalSequence {
9825                raw: core::ptr::NonNull::new_unchecked(
9826                    ffi::whiteout_m2_M2Model_get_globalLoops_at(self.raw.as_ptr(), index),
9827                ),
9828            }))
9829        }
9830    }
9831
9832    /// Iterate the elements, borrowing each in turn.
9833    pub fn global_loops_iter(
9834        &self,
9835    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, GlobalSequence>> {
9836        (0..self.global_loops_len()).map(move |i| self.global_loops(i).expect("index below len"))
9837    }
9838
9839    pub fn resize_global_loops(&mut self, count: usize) {
9840        // SAFETY: exclusive access, so no borrow is outstanding.
9841        unsafe { ffi::whiteout_m2_M2Model_resize_globalLoops(self.raw.as_ptr(), count) }
9842    }
9843
9844    pub fn sequences_len(&self) -> usize {
9845        // SAFETY: scalar read through a live handle.
9846        unsafe { ffi::whiteout_m2_M2Model_get_sequences_count(self.raw.as_ptr()) }
9847    }
9848
9849    /// Borrows element `index` in place. `None` when out of range.
9850    pub fn sequences(&self, index: usize) -> Option<crate::support::Ref<'_, Sequence>> {
9851        if index >= self.sequences_len() {
9852            return None;
9853        }
9854        // SAFETY: index checked above; the pointer is interior to `self`.
9855        unsafe {
9856            Some(crate::support::Ref::new(Sequence {
9857                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_sequences_at(
9858                    self.raw.as_ptr(),
9859                    index,
9860                )),
9861            }))
9862        }
9863    }
9864
9865    pub fn sequences_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Sequence>> {
9866        if index >= self.sequences_len() {
9867            return None;
9868        }
9869        // SAFETY: as above; `&mut self` guarantees exclusivity.
9870        unsafe {
9871            Some(crate::support::RefMut::new(Sequence {
9872                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_sequences_at(
9873                    self.raw.as_ptr(),
9874                    index,
9875                )),
9876            }))
9877        }
9878    }
9879
9880    /// Iterate the elements, borrowing each in turn.
9881    pub fn sequences_iter(
9882        &self,
9883    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Sequence>> {
9884        (0..self.sequences_len()).map(move |i| self.sequences(i).expect("index below len"))
9885    }
9886
9887    pub fn resize_sequences(&mut self, count: usize) {
9888        // SAFETY: exclusive access, so no borrow is outstanding.
9889        unsafe { ffi::whiteout_m2_M2Model_resize_sequences(self.raw.as_ptr(), count) }
9890    }
9891
9892    /// Zero-copy view of the underlying `std::vector`.
9893    pub fn sequence_idx_hash_by_id(&self) -> &[u16] {
9894        // SAFETY: `_data`/`_count` describe one contiguous C++
9895        // allocation, borrowed for as long as `self` is.
9896        unsafe {
9897            let n = ffi::whiteout_m2_M2Model_get_sequenceIdxHashById_count(self.raw.as_ptr());
9898            let p = ffi::whiteout_m2_M2Model_get_sequenceIdxHashById_data(self.raw.as_ptr());
9899            if p.is_null() || n == 0 {
9900                &[]
9901            } else {
9902                core::slice::from_raw_parts(p, n)
9903            }
9904        }
9905    }
9906
9907    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
9908    pub fn sequence_idx_hash_by_id_mut(&mut self) -> &mut [u16] {
9909        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
9910        unsafe {
9911            let n = ffi::whiteout_m2_M2Model_get_sequenceIdxHashById_count(self.raw.as_ptr());
9912            let p = ffi::whiteout_m2_M2Model_get_sequenceIdxHashById_data(self.raw.as_ptr())
9913                as *mut u16;
9914            if p.is_null() || n == 0 {
9915                &mut []
9916            } else {
9917                core::slice::from_raw_parts_mut(p, n)
9918            }
9919        }
9920    }
9921
9922    pub fn set_sequence_idx_hash_by_id(&mut self, values: &[u16]) {
9923        // SAFETY: the native side copies `values` before returning.
9924        unsafe {
9925            ffi::whiteout_m2_M2Model_assign_sequenceIdxHashById(
9926                self.raw.as_ptr(),
9927                values.as_ptr() as *const _,
9928                values.len(),
9929            )
9930        }
9931    }
9932
9933    pub fn resize_sequence_idx_hash_by_id(&mut self, count: usize) {
9934        // SAFETY: reallocation is safe here precisely because
9935        // `&mut self` means no slice borrow is outstanding.
9936        unsafe { ffi::whiteout_m2_M2Model_resize_sequenceIdxHashById(self.raw.as_ptr(), count) }
9937    }
9938
9939    pub fn bones_len(&self) -> usize {
9940        // SAFETY: scalar read through a live handle.
9941        unsafe { ffi::whiteout_m2_M2Model_get_bones_count(self.raw.as_ptr()) }
9942    }
9943
9944    /// Borrows element `index` in place. `None` when out of range.
9945    pub fn bones(&self, index: usize) -> Option<crate::support::Ref<'_, Bone>> {
9946        if index >= self.bones_len() {
9947            return None;
9948        }
9949        // SAFETY: index checked above; the pointer is interior to `self`.
9950        unsafe {
9951            Some(crate::support::Ref::new(Bone {
9952                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_bones_at(
9953                    self.raw.as_ptr(),
9954                    index,
9955                )),
9956            }))
9957        }
9958    }
9959
9960    pub fn bones_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Bone>> {
9961        if index >= self.bones_len() {
9962            return None;
9963        }
9964        // SAFETY: as above; `&mut self` guarantees exclusivity.
9965        unsafe {
9966            Some(crate::support::RefMut::new(Bone {
9967                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_bones_at(
9968                    self.raw.as_ptr(),
9969                    index,
9970                )),
9971            }))
9972        }
9973    }
9974
9975    /// Iterate the elements, borrowing each in turn.
9976    pub fn bones_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Bone>> {
9977        (0..self.bones_len()).map(move |i| self.bones(i).expect("index below len"))
9978    }
9979
9980    pub fn resize_bones(&mut self, count: usize) {
9981        // SAFETY: exclusive access, so no borrow is outstanding.
9982        unsafe { ffi::whiteout_m2_M2Model_resize_bones(self.raw.as_ptr(), count) }
9983    }
9984
9985    /// Zero-copy view of the underlying `std::vector`.
9986    pub fn key_bone_ids(&self) -> &[u16] {
9987        // SAFETY: `_data`/`_count` describe one contiguous C++
9988        // allocation, borrowed for as long as `self` is.
9989        unsafe {
9990            let n = ffi::whiteout_m2_M2Model_get_keyBoneIds_count(self.raw.as_ptr());
9991            let p = ffi::whiteout_m2_M2Model_get_keyBoneIds_data(self.raw.as_ptr());
9992            if p.is_null() || n == 0 {
9993                &[]
9994            } else {
9995                core::slice::from_raw_parts(p, n)
9996            }
9997        }
9998    }
9999
10000    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10001    pub fn key_bone_ids_mut(&mut self) -> &mut [u16] {
10002        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10003        unsafe {
10004            let n = ffi::whiteout_m2_M2Model_get_keyBoneIds_count(self.raw.as_ptr());
10005            let p = ffi::whiteout_m2_M2Model_get_keyBoneIds_data(self.raw.as_ptr()) as *mut u16;
10006            if p.is_null() || n == 0 {
10007                &mut []
10008            } else {
10009                core::slice::from_raw_parts_mut(p, n)
10010            }
10011        }
10012    }
10013
10014    pub fn set_key_bone_ids(&mut self, values: &[u16]) {
10015        // SAFETY: the native side copies `values` before returning.
10016        unsafe {
10017            ffi::whiteout_m2_M2Model_assign_keyBoneIds(
10018                self.raw.as_ptr(),
10019                values.as_ptr() as *const _,
10020                values.len(),
10021            )
10022        }
10023    }
10024
10025    pub fn resize_key_bone_ids(&mut self, count: usize) {
10026        // SAFETY: reallocation is safe here precisely because
10027        // `&mut self` means no slice borrow is outstanding.
10028        unsafe { ffi::whiteout_m2_M2Model_resize_keyBoneIds(self.raw.as_ptr(), count) }
10029    }
10030
10031    pub fn vertices_len(&self) -> usize {
10032        // SAFETY: scalar read through a live handle.
10033        unsafe { ffi::whiteout_m2_M2Model_get_vertices_count(self.raw.as_ptr()) }
10034    }
10035
10036    /// Borrows element `index` in place. `None` when out of range.
10037    pub fn vertices(&self, index: usize) -> Option<crate::support::Ref<'_, Vertex>> {
10038        if index >= self.vertices_len() {
10039            return None;
10040        }
10041        // SAFETY: index checked above; the pointer is interior to `self`.
10042        unsafe {
10043            Some(crate::support::Ref::new(Vertex {
10044                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_vertices_at(
10045                    self.raw.as_ptr(),
10046                    index,
10047                )),
10048            }))
10049        }
10050    }
10051
10052    pub fn vertices_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Vertex>> {
10053        if index >= self.vertices_len() {
10054            return None;
10055        }
10056        // SAFETY: as above; `&mut self` guarantees exclusivity.
10057        unsafe {
10058            Some(crate::support::RefMut::new(Vertex {
10059                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_vertices_at(
10060                    self.raw.as_ptr(),
10061                    index,
10062                )),
10063            }))
10064        }
10065    }
10066
10067    /// Iterate the elements, borrowing each in turn.
10068    pub fn vertices_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Vertex>> {
10069        (0..self.vertices_len()).map(move |i| self.vertices(i).expect("index below len"))
10070    }
10071
10072    pub fn resize_vertices(&mut self, count: usize) {
10073        // SAFETY: exclusive access, so no borrow is outstanding.
10074        unsafe { ffi::whiteout_m2_M2Model_resize_vertices(self.raw.as_ptr(), count) }
10075    }
10076
10077    pub fn skin_profiles_len(&self) -> usize {
10078        // SAFETY: scalar read through a live handle.
10079        unsafe { ffi::whiteout_m2_M2Model_get_skinProfiles_count(self.raw.as_ptr()) }
10080    }
10081
10082    /// Borrows element `index` in place. `None` when out of range.
10083    pub fn skin_profiles(&self, index: usize) -> Option<crate::support::Ref<'_, SkinProfile>> {
10084        if index >= self.skin_profiles_len() {
10085            return None;
10086        }
10087        // SAFETY: index checked above; the pointer is interior to `self`.
10088        unsafe {
10089            Some(crate::support::Ref::new(SkinProfile {
10090                raw: core::ptr::NonNull::new_unchecked(
10091                    ffi::whiteout_m2_M2Model_get_skinProfiles_at(self.raw.as_ptr(), index),
10092                ),
10093            }))
10094        }
10095    }
10096
10097    pub fn skin_profiles_mut(
10098        &mut self,
10099        index: usize,
10100    ) -> Option<crate::support::RefMut<'_, SkinProfile>> {
10101        if index >= self.skin_profiles_len() {
10102            return None;
10103        }
10104        // SAFETY: as above; `&mut self` guarantees exclusivity.
10105        unsafe {
10106            Some(crate::support::RefMut::new(SkinProfile {
10107                raw: core::ptr::NonNull::new_unchecked(
10108                    ffi::whiteout_m2_M2Model_get_skinProfiles_at(self.raw.as_ptr(), index),
10109                ),
10110            }))
10111        }
10112    }
10113
10114    /// Iterate the elements, borrowing each in turn.
10115    pub fn skin_profiles_iter(
10116        &self,
10117    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SkinProfile>> {
10118        (0..self.skin_profiles_len()).map(move |i| self.skin_profiles(i).expect("index below len"))
10119    }
10120
10121    pub fn resize_skin_profiles(&mut self, count: usize) {
10122        // SAFETY: exclusive access, so no borrow is outstanding.
10123        unsafe { ffi::whiteout_m2_M2Model_resize_skinProfiles(self.raw.as_ptr(), count) }
10124    }
10125
10126    pub fn lod_profiles_len(&self) -> usize {
10127        // SAFETY: scalar read through a live handle.
10128        unsafe { ffi::whiteout_m2_M2Model_get_lodProfiles_count(self.raw.as_ptr()) }
10129    }
10130
10131    /// Borrows element `index` in place. `None` when out of range.
10132    pub fn lod_profiles(&self, index: usize) -> Option<crate::support::Ref<'_, SkinProfile>> {
10133        if index >= self.lod_profiles_len() {
10134            return None;
10135        }
10136        // SAFETY: index checked above; the pointer is interior to `self`.
10137        unsafe {
10138            Some(crate::support::Ref::new(SkinProfile {
10139                raw: core::ptr::NonNull::new_unchecked(
10140                    ffi::whiteout_m2_M2Model_get_lodProfiles_at(self.raw.as_ptr(), index),
10141                ),
10142            }))
10143        }
10144    }
10145
10146    pub fn lod_profiles_mut(
10147        &mut self,
10148        index: usize,
10149    ) -> Option<crate::support::RefMut<'_, SkinProfile>> {
10150        if index >= self.lod_profiles_len() {
10151            return None;
10152        }
10153        // SAFETY: as above; `&mut self` guarantees exclusivity.
10154        unsafe {
10155            Some(crate::support::RefMut::new(SkinProfile {
10156                raw: core::ptr::NonNull::new_unchecked(
10157                    ffi::whiteout_m2_M2Model_get_lodProfiles_at(self.raw.as_ptr(), index),
10158                ),
10159            }))
10160        }
10161    }
10162
10163    /// Iterate the elements, borrowing each in turn.
10164    pub fn lod_profiles_iter(
10165        &self,
10166    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, SkinProfile>> {
10167        (0..self.lod_profiles_len()).map(move |i| self.lod_profiles(i).expect("index below len"))
10168    }
10169
10170    pub fn resize_lod_profiles(&mut self, count: usize) {
10171        // SAFETY: exclusive access, so no borrow is outstanding.
10172        unsafe { ffi::whiteout_m2_M2Model_resize_lodProfiles(self.raw.as_ptr(), count) }
10173    }
10174
10175    pub fn num_skin_profiles(&self) -> u32 {
10176        // SAFETY: plain scalar read through a live handle.
10177        unsafe { ffi::whiteout_m2_M2Model_get_numSkinProfiles(self.raw.as_ptr()) }
10178    }
10179
10180    pub fn set_num_skin_profiles(&mut self, value: u32) {
10181        // SAFETY: plain scalar write through a live handle.
10182        unsafe { ffi::whiteout_m2_M2Model_set_numSkinProfiles(self.raw.as_ptr(), value) }
10183    }
10184
10185    pub fn colors_len(&self) -> usize {
10186        // SAFETY: scalar read through a live handle.
10187        unsafe { ffi::whiteout_m2_M2Model_get_colors_count(self.raw.as_ptr()) }
10188    }
10189
10190    /// Borrows element `index` in place. `None` when out of range.
10191    pub fn colors(&self, index: usize) -> Option<crate::support::Ref<'_, ColorAnimation>> {
10192        if index >= self.colors_len() {
10193            return None;
10194        }
10195        // SAFETY: index checked above; the pointer is interior to `self`.
10196        unsafe {
10197            Some(crate::support::Ref::new(ColorAnimation {
10198                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_colors_at(
10199                    self.raw.as_ptr(),
10200                    index,
10201                )),
10202            }))
10203        }
10204    }
10205
10206    pub fn colors_mut(
10207        &mut self,
10208        index: usize,
10209    ) -> Option<crate::support::RefMut<'_, ColorAnimation>> {
10210        if index >= self.colors_len() {
10211            return None;
10212        }
10213        // SAFETY: as above; `&mut self` guarantees exclusivity.
10214        unsafe {
10215            Some(crate::support::RefMut::new(ColorAnimation {
10216                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_colors_at(
10217                    self.raw.as_ptr(),
10218                    index,
10219                )),
10220            }))
10221        }
10222    }
10223
10224    /// Iterate the elements, borrowing each in turn.
10225    pub fn colors_iter(
10226        &self,
10227    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ColorAnimation>> {
10228        (0..self.colors_len()).map(move |i| self.colors(i).expect("index below len"))
10229    }
10230
10231    pub fn resize_colors(&mut self, count: usize) {
10232        // SAFETY: exclusive access, so no borrow is outstanding.
10233        unsafe { ffi::whiteout_m2_M2Model_resize_colors(self.raw.as_ptr(), count) }
10234    }
10235
10236    pub fn textures_len(&self) -> usize {
10237        // SAFETY: scalar read through a live handle.
10238        unsafe { ffi::whiteout_m2_M2Model_get_textures_count(self.raw.as_ptr()) }
10239    }
10240
10241    /// Borrows element `index` in place. `None` when out of range.
10242    pub fn textures(&self, index: usize) -> Option<crate::support::Ref<'_, Texture>> {
10243        if index >= self.textures_len() {
10244            return None;
10245        }
10246        // SAFETY: index checked above; the pointer is interior to `self`.
10247        unsafe {
10248            Some(crate::support::Ref::new(Texture {
10249                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_textures_at(
10250                    self.raw.as_ptr(),
10251                    index,
10252                )),
10253            }))
10254        }
10255    }
10256
10257    pub fn textures_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Texture>> {
10258        if index >= self.textures_len() {
10259            return None;
10260        }
10261        // SAFETY: as above; `&mut self` guarantees exclusivity.
10262        unsafe {
10263            Some(crate::support::RefMut::new(Texture {
10264                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_textures_at(
10265                    self.raw.as_ptr(),
10266                    index,
10267                )),
10268            }))
10269        }
10270    }
10271
10272    /// Iterate the elements, borrowing each in turn.
10273    pub fn textures_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Texture>> {
10274        (0..self.textures_len()).map(move |i| self.textures(i).expect("index below len"))
10275    }
10276
10277    pub fn resize_textures(&mut self, count: usize) {
10278        // SAFETY: exclusive access, so no borrow is outstanding.
10279        unsafe { ffi::whiteout_m2_M2Model_resize_textures(self.raw.as_ptr(), count) }
10280    }
10281
10282    pub fn texture_weights_len(&self) -> usize {
10283        // SAFETY: scalar read through a live handle.
10284        unsafe { ffi::whiteout_m2_M2Model_get_textureWeights_count(self.raw.as_ptr()) }
10285    }
10286
10287    /// Borrows element `index` in place. `None` when out of range.
10288    pub fn texture_weights(&self, index: usize) -> Option<crate::support::Ref<'_, TextureWeight>> {
10289        if index >= self.texture_weights_len() {
10290            return None;
10291        }
10292        // SAFETY: index checked above; the pointer is interior to `self`.
10293        unsafe {
10294            Some(crate::support::Ref::new(TextureWeight {
10295                raw: core::ptr::NonNull::new_unchecked(
10296                    ffi::whiteout_m2_M2Model_get_textureWeights_at(self.raw.as_ptr(), index),
10297                ),
10298            }))
10299        }
10300    }
10301
10302    pub fn texture_weights_mut(
10303        &mut self,
10304        index: usize,
10305    ) -> Option<crate::support::RefMut<'_, TextureWeight>> {
10306        if index >= self.texture_weights_len() {
10307            return None;
10308        }
10309        // SAFETY: as above; `&mut self` guarantees exclusivity.
10310        unsafe {
10311            Some(crate::support::RefMut::new(TextureWeight {
10312                raw: core::ptr::NonNull::new_unchecked(
10313                    ffi::whiteout_m2_M2Model_get_textureWeights_at(self.raw.as_ptr(), index),
10314                ),
10315            }))
10316        }
10317    }
10318
10319    /// Iterate the elements, borrowing each in turn.
10320    pub fn texture_weights_iter(
10321        &self,
10322    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TextureWeight>> {
10323        (0..self.texture_weights_len())
10324            .map(move |i| self.texture_weights(i).expect("index below len"))
10325    }
10326
10327    pub fn resize_texture_weights(&mut self, count: usize) {
10328        // SAFETY: exclusive access, so no borrow is outstanding.
10329        unsafe { ffi::whiteout_m2_M2Model_resize_textureWeights(self.raw.as_ptr(), count) }
10330    }
10331
10332    pub fn texture_transforms_len(&self) -> usize {
10333        // SAFETY: scalar read through a live handle.
10334        unsafe { ffi::whiteout_m2_M2Model_get_textureTransforms_count(self.raw.as_ptr()) }
10335    }
10336
10337    /// Borrows element `index` in place. `None` when out of range.
10338    pub fn texture_transforms(
10339        &self,
10340        index: usize,
10341    ) -> Option<crate::support::Ref<'_, TextureTransform>> {
10342        if index >= self.texture_transforms_len() {
10343            return None;
10344        }
10345        // SAFETY: index checked above; the pointer is interior to `self`.
10346        unsafe {
10347            Some(crate::support::Ref::new(TextureTransform {
10348                raw: core::ptr::NonNull::new_unchecked(
10349                    ffi::whiteout_m2_M2Model_get_textureTransforms_at(self.raw.as_ptr(), index),
10350                ),
10351            }))
10352        }
10353    }
10354
10355    pub fn texture_transforms_mut(
10356        &mut self,
10357        index: usize,
10358    ) -> Option<crate::support::RefMut<'_, TextureTransform>> {
10359        if index >= self.texture_transforms_len() {
10360            return None;
10361        }
10362        // SAFETY: as above; `&mut self` guarantees exclusivity.
10363        unsafe {
10364            Some(crate::support::RefMut::new(TextureTransform {
10365                raw: core::ptr::NonNull::new_unchecked(
10366                    ffi::whiteout_m2_M2Model_get_textureTransforms_at(self.raw.as_ptr(), index),
10367                ),
10368            }))
10369        }
10370    }
10371
10372    /// Iterate the elements, borrowing each in turn.
10373    pub fn texture_transforms_iter(
10374        &self,
10375    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TextureTransform>> {
10376        (0..self.texture_transforms_len())
10377            .map(move |i| self.texture_transforms(i).expect("index below len"))
10378    }
10379
10380    pub fn resize_texture_transforms(&mut self, count: usize) {
10381        // SAFETY: exclusive access, so no borrow is outstanding.
10382        unsafe { ffi::whiteout_m2_M2Model_resize_textureTransforms(self.raw.as_ptr(), count) }
10383    }
10384
10385    /// Zero-copy view of the underlying `std::vector`.
10386    pub fn texture_indices_by_id(&self) -> &[u16] {
10387        // SAFETY: `_data`/`_count` describe one contiguous C++
10388        // allocation, borrowed for as long as `self` is.
10389        unsafe {
10390            let n = ffi::whiteout_m2_M2Model_get_textureIndicesById_count(self.raw.as_ptr());
10391            let p = ffi::whiteout_m2_M2Model_get_textureIndicesById_data(self.raw.as_ptr());
10392            if p.is_null() || n == 0 {
10393                &[]
10394            } else {
10395                core::slice::from_raw_parts(p, n)
10396            }
10397        }
10398    }
10399
10400    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10401    pub fn texture_indices_by_id_mut(&mut self) -> &mut [u16] {
10402        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10403        unsafe {
10404            let n = ffi::whiteout_m2_M2Model_get_textureIndicesById_count(self.raw.as_ptr());
10405            let p =
10406                ffi::whiteout_m2_M2Model_get_textureIndicesById_data(self.raw.as_ptr()) as *mut u16;
10407            if p.is_null() || n == 0 {
10408                &mut []
10409            } else {
10410                core::slice::from_raw_parts_mut(p, n)
10411            }
10412        }
10413    }
10414
10415    pub fn set_texture_indices_by_id(&mut self, values: &[u16]) {
10416        // SAFETY: the native side copies `values` before returning.
10417        unsafe {
10418            ffi::whiteout_m2_M2Model_assign_textureIndicesById(
10419                self.raw.as_ptr(),
10420                values.as_ptr() as *const _,
10421                values.len(),
10422            )
10423        }
10424    }
10425
10426    pub fn resize_texture_indices_by_id(&mut self, count: usize) {
10427        // SAFETY: reallocation is safe here precisely because
10428        // `&mut self` means no slice borrow is outstanding.
10429        unsafe { ffi::whiteout_m2_M2Model_resize_textureIndicesById(self.raw.as_ptr(), count) }
10430    }
10431
10432    pub fn materials_len(&self) -> usize {
10433        // SAFETY: scalar read through a live handle.
10434        unsafe { ffi::whiteout_m2_M2Model_get_materials_count(self.raw.as_ptr()) }
10435    }
10436
10437    /// Borrows element `index` in place. `None` when out of range.
10438    pub fn materials(&self, index: usize) -> Option<crate::support::Ref<'_, Material>> {
10439        if index >= self.materials_len() {
10440            return None;
10441        }
10442        // SAFETY: index checked above; the pointer is interior to `self`.
10443        unsafe {
10444            Some(crate::support::Ref::new(Material {
10445                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_materials_at(
10446                    self.raw.as_ptr(),
10447                    index,
10448                )),
10449            }))
10450        }
10451    }
10452
10453    pub fn materials_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Material>> {
10454        if index >= self.materials_len() {
10455            return None;
10456        }
10457        // SAFETY: as above; `&mut self` guarantees exclusivity.
10458        unsafe {
10459            Some(crate::support::RefMut::new(Material {
10460                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_materials_at(
10461                    self.raw.as_ptr(),
10462                    index,
10463                )),
10464            }))
10465        }
10466    }
10467
10468    /// Iterate the elements, borrowing each in turn.
10469    pub fn materials_iter(
10470        &self,
10471    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Material>> {
10472        (0..self.materials_len()).map(move |i| self.materials(i).expect("index below len"))
10473    }
10474
10475    pub fn resize_materials(&mut self, count: usize) {
10476        // SAFETY: exclusive access, so no borrow is outstanding.
10477        unsafe { ffi::whiteout_m2_M2Model_resize_materials(self.raw.as_ptr(), count) }
10478    }
10479
10480    /// Zero-copy view of the underlying `std::vector`.
10481    pub fn bone_combos(&self) -> &[u16] {
10482        // SAFETY: `_data`/`_count` describe one contiguous C++
10483        // allocation, borrowed for as long as `self` is.
10484        unsafe {
10485            let n = ffi::whiteout_m2_M2Model_get_boneCombos_count(self.raw.as_ptr());
10486            let p = ffi::whiteout_m2_M2Model_get_boneCombos_data(self.raw.as_ptr());
10487            if p.is_null() || n == 0 {
10488                &[]
10489            } else {
10490                core::slice::from_raw_parts(p, n)
10491            }
10492        }
10493    }
10494
10495    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10496    pub fn bone_combos_mut(&mut self) -> &mut [u16] {
10497        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10498        unsafe {
10499            let n = ffi::whiteout_m2_M2Model_get_boneCombos_count(self.raw.as_ptr());
10500            let p = ffi::whiteout_m2_M2Model_get_boneCombos_data(self.raw.as_ptr()) as *mut u16;
10501            if p.is_null() || n == 0 {
10502                &mut []
10503            } else {
10504                core::slice::from_raw_parts_mut(p, n)
10505            }
10506        }
10507    }
10508
10509    pub fn set_bone_combos(&mut self, values: &[u16]) {
10510        // SAFETY: the native side copies `values` before returning.
10511        unsafe {
10512            ffi::whiteout_m2_M2Model_assign_boneCombos(
10513                self.raw.as_ptr(),
10514                values.as_ptr() as *const _,
10515                values.len(),
10516            )
10517        }
10518    }
10519
10520    pub fn resize_bone_combos(&mut self, count: usize) {
10521        // SAFETY: reallocation is safe here precisely because
10522        // `&mut self` means no slice borrow is outstanding.
10523        unsafe { ffi::whiteout_m2_M2Model_resize_boneCombos(self.raw.as_ptr(), count) }
10524    }
10525
10526    /// Zero-copy view of the underlying `std::vector`.
10527    pub fn texture_combos(&self) -> &[u16] {
10528        // SAFETY: `_data`/`_count` describe one contiguous C++
10529        // allocation, borrowed for as long as `self` is.
10530        unsafe {
10531            let n = ffi::whiteout_m2_M2Model_get_textureCombos_count(self.raw.as_ptr());
10532            let p = ffi::whiteout_m2_M2Model_get_textureCombos_data(self.raw.as_ptr());
10533            if p.is_null() || n == 0 {
10534                &[]
10535            } else {
10536                core::slice::from_raw_parts(p, n)
10537            }
10538        }
10539    }
10540
10541    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10542    pub fn texture_combos_mut(&mut self) -> &mut [u16] {
10543        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10544        unsafe {
10545            let n = ffi::whiteout_m2_M2Model_get_textureCombos_count(self.raw.as_ptr());
10546            let p = ffi::whiteout_m2_M2Model_get_textureCombos_data(self.raw.as_ptr()) as *mut u16;
10547            if p.is_null() || n == 0 {
10548                &mut []
10549            } else {
10550                core::slice::from_raw_parts_mut(p, n)
10551            }
10552        }
10553    }
10554
10555    pub fn set_texture_combos(&mut self, values: &[u16]) {
10556        // SAFETY: the native side copies `values` before returning.
10557        unsafe {
10558            ffi::whiteout_m2_M2Model_assign_textureCombos(
10559                self.raw.as_ptr(),
10560                values.as_ptr() as *const _,
10561                values.len(),
10562            )
10563        }
10564    }
10565
10566    pub fn resize_texture_combos(&mut self, count: usize) {
10567        // SAFETY: reallocation is safe here precisely because
10568        // `&mut self` means no slice borrow is outstanding.
10569        unsafe { ffi::whiteout_m2_M2Model_resize_textureCombos(self.raw.as_ptr(), count) }
10570    }
10571
10572    /// Zero-copy view of the underlying `std::vector`.
10573    pub fn texture_coord_combos(&self) -> &[u16] {
10574        // SAFETY: `_data`/`_count` describe one contiguous C++
10575        // allocation, borrowed for as long as `self` is.
10576        unsafe {
10577            let n = ffi::whiteout_m2_M2Model_get_textureCoordCombos_count(self.raw.as_ptr());
10578            let p = ffi::whiteout_m2_M2Model_get_textureCoordCombos_data(self.raw.as_ptr());
10579            if p.is_null() || n == 0 {
10580                &[]
10581            } else {
10582                core::slice::from_raw_parts(p, n)
10583            }
10584        }
10585    }
10586
10587    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10588    pub fn texture_coord_combos_mut(&mut self) -> &mut [u16] {
10589        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10590        unsafe {
10591            let n = ffi::whiteout_m2_M2Model_get_textureCoordCombos_count(self.raw.as_ptr());
10592            let p =
10593                ffi::whiteout_m2_M2Model_get_textureCoordCombos_data(self.raw.as_ptr()) as *mut u16;
10594            if p.is_null() || n == 0 {
10595                &mut []
10596            } else {
10597                core::slice::from_raw_parts_mut(p, n)
10598            }
10599        }
10600    }
10601
10602    pub fn set_texture_coord_combos(&mut self, values: &[u16]) {
10603        // SAFETY: the native side copies `values` before returning.
10604        unsafe {
10605            ffi::whiteout_m2_M2Model_assign_textureCoordCombos(
10606                self.raw.as_ptr(),
10607                values.as_ptr() as *const _,
10608                values.len(),
10609            )
10610        }
10611    }
10612
10613    pub fn resize_texture_coord_combos(&mut self, count: usize) {
10614        // SAFETY: reallocation is safe here precisely because
10615        // `&mut self` means no slice borrow is outstanding.
10616        unsafe { ffi::whiteout_m2_M2Model_resize_textureCoordCombos(self.raw.as_ptr(), count) }
10617    }
10618
10619    /// Zero-copy view of the underlying `std::vector`.
10620    pub fn texture_weight_combos(&self) -> &[u16] {
10621        // SAFETY: `_data`/`_count` describe one contiguous C++
10622        // allocation, borrowed for as long as `self` is.
10623        unsafe {
10624            let n = ffi::whiteout_m2_M2Model_get_textureWeightCombos_count(self.raw.as_ptr());
10625            let p = ffi::whiteout_m2_M2Model_get_textureWeightCombos_data(self.raw.as_ptr());
10626            if p.is_null() || n == 0 {
10627                &[]
10628            } else {
10629                core::slice::from_raw_parts(p, n)
10630            }
10631        }
10632    }
10633
10634    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10635    pub fn texture_weight_combos_mut(&mut self) -> &mut [u16] {
10636        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10637        unsafe {
10638            let n = ffi::whiteout_m2_M2Model_get_textureWeightCombos_count(self.raw.as_ptr());
10639            let p = ffi::whiteout_m2_M2Model_get_textureWeightCombos_data(self.raw.as_ptr())
10640                as *mut u16;
10641            if p.is_null() || n == 0 {
10642                &mut []
10643            } else {
10644                core::slice::from_raw_parts_mut(p, n)
10645            }
10646        }
10647    }
10648
10649    pub fn set_texture_weight_combos(&mut self, values: &[u16]) {
10650        // SAFETY: the native side copies `values` before returning.
10651        unsafe {
10652            ffi::whiteout_m2_M2Model_assign_textureWeightCombos(
10653                self.raw.as_ptr(),
10654                values.as_ptr() as *const _,
10655                values.len(),
10656            )
10657        }
10658    }
10659
10660    pub fn resize_texture_weight_combos(&mut self, count: usize) {
10661        // SAFETY: reallocation is safe here precisely because
10662        // `&mut self` means no slice borrow is outstanding.
10663        unsafe { ffi::whiteout_m2_M2Model_resize_textureWeightCombos(self.raw.as_ptr(), count) }
10664    }
10665
10666    /// Zero-copy view of the underlying `std::vector`.
10667    pub fn texture_transform_combos(&self) -> &[u16] {
10668        // SAFETY: `_data`/`_count` describe one contiguous C++
10669        // allocation, borrowed for as long as `self` is.
10670        unsafe {
10671            let n = ffi::whiteout_m2_M2Model_get_textureTransformCombos_count(self.raw.as_ptr());
10672            let p = ffi::whiteout_m2_M2Model_get_textureTransformCombos_data(self.raw.as_ptr());
10673            if p.is_null() || n == 0 {
10674                &[]
10675            } else {
10676                core::slice::from_raw_parts(p, n)
10677            }
10678        }
10679    }
10680
10681    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10682    pub fn texture_transform_combos_mut(&mut self) -> &mut [u16] {
10683        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10684        unsafe {
10685            let n = ffi::whiteout_m2_M2Model_get_textureTransformCombos_count(self.raw.as_ptr());
10686            let p = ffi::whiteout_m2_M2Model_get_textureTransformCombos_data(self.raw.as_ptr())
10687                as *mut u16;
10688            if p.is_null() || n == 0 {
10689                &mut []
10690            } else {
10691                core::slice::from_raw_parts_mut(p, n)
10692            }
10693        }
10694    }
10695
10696    pub fn set_texture_transform_combos(&mut self, values: &[u16]) {
10697        // SAFETY: the native side copies `values` before returning.
10698        unsafe {
10699            ffi::whiteout_m2_M2Model_assign_textureTransformCombos(
10700                self.raw.as_ptr(),
10701                values.as_ptr() as *const _,
10702                values.len(),
10703            )
10704        }
10705    }
10706
10707    pub fn resize_texture_transform_combos(&mut self, count: usize) {
10708        // SAFETY: reallocation is safe here precisely because
10709        // `&mut self` means no slice borrow is outstanding.
10710        unsafe { ffi::whiteout_m2_M2Model_resize_textureTransformCombos(self.raw.as_ptr(), count) }
10711    }
10712
10713    /// Borrows the field in place — no copy, no allocation.
10714    pub fn bounding(&self) -> crate::support::Ref<'_, Extent> {
10715        // SAFETY: an interior pointer into `self`, valid for this
10716        // borrow and never freed by the `Ref`.
10717        unsafe {
10718            crate::support::Ref::new(Extent {
10719                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_bounding(
10720                    self.raw.as_ptr(),
10721                )),
10722            })
10723        }
10724    }
10725
10726    pub fn bounding_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
10727        // SAFETY: as above; `&mut self` guarantees exclusivity.
10728        unsafe {
10729            crate::support::RefMut::new(Extent {
10730                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_bounding(
10731                    self.raw.as_ptr(),
10732                )),
10733            })
10734        }
10735    }
10736
10737    /// Borrows the field in place — no copy, no allocation.
10738    pub fn collision(&self) -> crate::support::Ref<'_, Extent> {
10739        // SAFETY: an interior pointer into `self`, valid for this
10740        // borrow and never freed by the `Ref`.
10741        unsafe {
10742            crate::support::Ref::new(Extent {
10743                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_collision(
10744                    self.raw.as_ptr(),
10745                )),
10746            })
10747        }
10748    }
10749
10750    pub fn collision_mut(&mut self) -> crate::support::RefMut<'_, Extent> {
10751        // SAFETY: as above; `&mut self` guarantees exclusivity.
10752        unsafe {
10753            crate::support::RefMut::new(Extent {
10754                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_collision(
10755                    self.raw.as_ptr(),
10756                )),
10757            })
10758        }
10759    }
10760
10761    /// Zero-copy view of the underlying `std::vector`.
10762    pub fn collision_triangle_indices(&self) -> &[u16] {
10763        // SAFETY: `_data`/`_count` describe one contiguous C++
10764        // allocation, borrowed for as long as `self` is.
10765        unsafe {
10766            let n = ffi::whiteout_m2_M2Model_get_collisionTriangleIndices_count(self.raw.as_ptr());
10767            let p = ffi::whiteout_m2_M2Model_get_collisionTriangleIndices_data(self.raw.as_ptr());
10768            if p.is_null() || n == 0 {
10769                &[]
10770            } else {
10771                core::slice::from_raw_parts(p, n)
10772            }
10773        }
10774    }
10775
10776    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10777    pub fn collision_triangle_indices_mut(&mut self) -> &mut [u16] {
10778        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10779        unsafe {
10780            let n = ffi::whiteout_m2_M2Model_get_collisionTriangleIndices_count(self.raw.as_ptr());
10781            let p = ffi::whiteout_m2_M2Model_get_collisionTriangleIndices_data(self.raw.as_ptr())
10782                as *mut u16;
10783            if p.is_null() || n == 0 {
10784                &mut []
10785            } else {
10786                core::slice::from_raw_parts_mut(p, n)
10787            }
10788        }
10789    }
10790
10791    pub fn set_collision_triangle_indices(&mut self, values: &[u16]) {
10792        // SAFETY: the native side copies `values` before returning.
10793        unsafe {
10794            ffi::whiteout_m2_M2Model_assign_collisionTriangleIndices(
10795                self.raw.as_ptr(),
10796                values.as_ptr() as *const _,
10797                values.len(),
10798            )
10799        }
10800    }
10801
10802    pub fn resize_collision_triangle_indices(&mut self, count: usize) {
10803        // SAFETY: reallocation is safe here precisely because
10804        // `&mut self` means no slice borrow is outstanding.
10805        unsafe {
10806            ffi::whiteout_m2_M2Model_resize_collisionTriangleIndices(self.raw.as_ptr(), count)
10807        }
10808    }
10809
10810    /// Zero-copy view of the underlying `std::vector`.
10811    pub fn collision_vertices(&self) -> &[crate::math::Vector3f] {
10812        // SAFETY: `_data`/`_count` describe one contiguous C++
10813        // allocation, borrowed for as long as `self` is.
10814        unsafe {
10815            let n = ffi::whiteout_m2_M2Model_get_collisionVertices_count(self.raw.as_ptr());
10816            let p = ffi::whiteout_m2_M2Model_get_collisionVertices_data(self.raw.as_ptr())
10817                as *const crate::math::Vector3f;
10818            if p.is_null() || n == 0 {
10819                &[]
10820            } else {
10821                core::slice::from_raw_parts(p, n)
10822            }
10823        }
10824    }
10825
10826    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10827    pub fn collision_vertices_mut(&mut self) -> &mut [crate::math::Vector3f] {
10828        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10829        unsafe {
10830            let n = ffi::whiteout_m2_M2Model_get_collisionVertices_count(self.raw.as_ptr());
10831            let p = ffi::whiteout_m2_M2Model_get_collisionVertices_data(self.raw.as_ptr())
10832                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
10833            if p.is_null() || n == 0 {
10834                &mut []
10835            } else {
10836                core::slice::from_raw_parts_mut(p, n)
10837            }
10838        }
10839    }
10840
10841    pub fn set_collision_vertices(&mut self, values: &[crate::math::Vector3f]) {
10842        // SAFETY: the native side copies `values` before returning.
10843        unsafe {
10844            ffi::whiteout_m2_M2Model_assign_collisionVertices(
10845                self.raw.as_ptr(),
10846                values.as_ptr() as *const _,
10847                values.len(),
10848            )
10849        }
10850    }
10851
10852    pub fn resize_collision_vertices(&mut self, count: usize) {
10853        // SAFETY: reallocation is safe here precisely because
10854        // `&mut self` means no slice borrow is outstanding.
10855        unsafe { ffi::whiteout_m2_M2Model_resize_collisionVertices(self.raw.as_ptr(), count) }
10856    }
10857
10858    /// Zero-copy view of the underlying `std::vector`.
10859    pub fn collision_face_normals(&self) -> &[crate::math::Vector3f] {
10860        // SAFETY: `_data`/`_count` describe one contiguous C++
10861        // allocation, borrowed for as long as `self` is.
10862        unsafe {
10863            let n = ffi::whiteout_m2_M2Model_get_collisionFaceNormals_count(self.raw.as_ptr());
10864            let p = ffi::whiteout_m2_M2Model_get_collisionFaceNormals_data(self.raw.as_ptr())
10865                as *const crate::math::Vector3f;
10866            if p.is_null() || n == 0 {
10867                &[]
10868            } else {
10869                core::slice::from_raw_parts(p, n)
10870            }
10871        }
10872    }
10873
10874    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10875    pub fn collision_face_normals_mut(&mut self) -> &mut [crate::math::Vector3f] {
10876        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10877        unsafe {
10878            let n = ffi::whiteout_m2_M2Model_get_collisionFaceNormals_count(self.raw.as_ptr());
10879            let p = ffi::whiteout_m2_M2Model_get_collisionFaceNormals_data(self.raw.as_ptr())
10880                as *const crate::math::Vector3f as *mut crate::math::Vector3f;
10881            if p.is_null() || n == 0 {
10882                &mut []
10883            } else {
10884                core::slice::from_raw_parts_mut(p, n)
10885            }
10886        }
10887    }
10888
10889    pub fn set_collision_face_normals(&mut self, values: &[crate::math::Vector3f]) {
10890        // SAFETY: the native side copies `values` before returning.
10891        unsafe {
10892            ffi::whiteout_m2_M2Model_assign_collisionFaceNormals(
10893                self.raw.as_ptr(),
10894                values.as_ptr() as *const _,
10895                values.len(),
10896            )
10897        }
10898    }
10899
10900    pub fn resize_collision_face_normals(&mut self, count: usize) {
10901        // SAFETY: reallocation is safe here precisely because
10902        // `&mut self` means no slice borrow is outstanding.
10903        unsafe { ffi::whiteout_m2_M2Model_resize_collisionFaceNormals(self.raw.as_ptr(), count) }
10904    }
10905
10906    pub fn attachments_len(&self) -> usize {
10907        // SAFETY: scalar read through a live handle.
10908        unsafe { ffi::whiteout_m2_M2Model_get_attachments_count(self.raw.as_ptr()) }
10909    }
10910
10911    /// Borrows element `index` in place. `None` when out of range.
10912    pub fn attachments(&self, index: usize) -> Option<crate::support::Ref<'_, Attachment>> {
10913        if index >= self.attachments_len() {
10914            return None;
10915        }
10916        // SAFETY: index checked above; the pointer is interior to `self`.
10917        unsafe {
10918            Some(crate::support::Ref::new(Attachment {
10919                raw: core::ptr::NonNull::new_unchecked(
10920                    ffi::whiteout_m2_M2Model_get_attachments_at(self.raw.as_ptr(), index),
10921                ),
10922            }))
10923        }
10924    }
10925
10926    pub fn attachments_mut(
10927        &mut self,
10928        index: usize,
10929    ) -> Option<crate::support::RefMut<'_, Attachment>> {
10930        if index >= self.attachments_len() {
10931            return None;
10932        }
10933        // SAFETY: as above; `&mut self` guarantees exclusivity.
10934        unsafe {
10935            Some(crate::support::RefMut::new(Attachment {
10936                raw: core::ptr::NonNull::new_unchecked(
10937                    ffi::whiteout_m2_M2Model_get_attachments_at(self.raw.as_ptr(), index),
10938                ),
10939            }))
10940        }
10941    }
10942
10943    /// Iterate the elements, borrowing each in turn.
10944    pub fn attachments_iter(
10945        &self,
10946    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Attachment>> {
10947        (0..self.attachments_len()).map(move |i| self.attachments(i).expect("index below len"))
10948    }
10949
10950    pub fn resize_attachments(&mut self, count: usize) {
10951        // SAFETY: exclusive access, so no borrow is outstanding.
10952        unsafe { ffi::whiteout_m2_M2Model_resize_attachments(self.raw.as_ptr(), count) }
10953    }
10954
10955    /// Zero-copy view of the underlying `std::vector`.
10956    pub fn attachment_indices_by_id(&self) -> &[u16] {
10957        // SAFETY: `_data`/`_count` describe one contiguous C++
10958        // allocation, borrowed for as long as `self` is.
10959        unsafe {
10960            let n = ffi::whiteout_m2_M2Model_get_attachmentIndicesById_count(self.raw.as_ptr());
10961            let p = ffi::whiteout_m2_M2Model_get_attachmentIndicesById_data(self.raw.as_ptr());
10962            if p.is_null() || n == 0 {
10963                &[]
10964            } else {
10965                core::slice::from_raw_parts(p, n)
10966            }
10967        }
10968    }
10969
10970    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
10971    pub fn attachment_indices_by_id_mut(&mut self) -> &mut [u16] {
10972        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
10973        unsafe {
10974            let n = ffi::whiteout_m2_M2Model_get_attachmentIndicesById_count(self.raw.as_ptr());
10975            let p = ffi::whiteout_m2_M2Model_get_attachmentIndicesById_data(self.raw.as_ptr())
10976                as *mut u16;
10977            if p.is_null() || n == 0 {
10978                &mut []
10979            } else {
10980                core::slice::from_raw_parts_mut(p, n)
10981            }
10982        }
10983    }
10984
10985    pub fn set_attachment_indices_by_id(&mut self, values: &[u16]) {
10986        // SAFETY: the native side copies `values` before returning.
10987        unsafe {
10988            ffi::whiteout_m2_M2Model_assign_attachmentIndicesById(
10989                self.raw.as_ptr(),
10990                values.as_ptr() as *const _,
10991                values.len(),
10992            )
10993        }
10994    }
10995
10996    pub fn resize_attachment_indices_by_id(&mut self, count: usize) {
10997        // SAFETY: reallocation is safe here precisely because
10998        // `&mut self` means no slice borrow is outstanding.
10999        unsafe { ffi::whiteout_m2_M2Model_resize_attachmentIndicesById(self.raw.as_ptr(), count) }
11000    }
11001
11002    pub fn events_len(&self) -> usize {
11003        // SAFETY: scalar read through a live handle.
11004        unsafe { ffi::whiteout_m2_M2Model_get_events_count(self.raw.as_ptr()) }
11005    }
11006
11007    /// Borrows element `index` in place. `None` when out of range.
11008    pub fn events(&self, index: usize) -> Option<crate::support::Ref<'_, Event>> {
11009        if index >= self.events_len() {
11010            return None;
11011        }
11012        // SAFETY: index checked above; the pointer is interior to `self`.
11013        unsafe {
11014            Some(crate::support::Ref::new(Event {
11015                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_events_at(
11016                    self.raw.as_ptr(),
11017                    index,
11018                )),
11019            }))
11020        }
11021    }
11022
11023    pub fn events_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Event>> {
11024        if index >= self.events_len() {
11025            return None;
11026        }
11027        // SAFETY: as above; `&mut self` guarantees exclusivity.
11028        unsafe {
11029            Some(crate::support::RefMut::new(Event {
11030                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_events_at(
11031                    self.raw.as_ptr(),
11032                    index,
11033                )),
11034            }))
11035        }
11036    }
11037
11038    /// Iterate the elements, borrowing each in turn.
11039    pub fn events_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Event>> {
11040        (0..self.events_len()).map(move |i| self.events(i).expect("index below len"))
11041    }
11042
11043    pub fn resize_events(&mut self, count: usize) {
11044        // SAFETY: exclusive access, so no borrow is outstanding.
11045        unsafe { ffi::whiteout_m2_M2Model_resize_events(self.raw.as_ptr(), count) }
11046    }
11047
11048    pub fn lights_len(&self) -> usize {
11049        // SAFETY: scalar read through a live handle.
11050        unsafe { ffi::whiteout_m2_M2Model_get_lights_count(self.raw.as_ptr()) }
11051    }
11052
11053    /// Borrows element `index` in place. `None` when out of range.
11054    pub fn lights(&self, index: usize) -> Option<crate::support::Ref<'_, Light>> {
11055        if index >= self.lights_len() {
11056            return None;
11057        }
11058        // SAFETY: index checked above; the pointer is interior to `self`.
11059        unsafe {
11060            Some(crate::support::Ref::new(Light {
11061                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_lights_at(
11062                    self.raw.as_ptr(),
11063                    index,
11064                )),
11065            }))
11066        }
11067    }
11068
11069    pub fn lights_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Light>> {
11070        if index >= self.lights_len() {
11071            return None;
11072        }
11073        // SAFETY: as above; `&mut self` guarantees exclusivity.
11074        unsafe {
11075            Some(crate::support::RefMut::new(Light {
11076                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_lights_at(
11077                    self.raw.as_ptr(),
11078                    index,
11079                )),
11080            }))
11081        }
11082    }
11083
11084    /// Iterate the elements, borrowing each in turn.
11085    pub fn lights_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Light>> {
11086        (0..self.lights_len()).map(move |i| self.lights(i).expect("index below len"))
11087    }
11088
11089    pub fn resize_lights(&mut self, count: usize) {
11090        // SAFETY: exclusive access, so no borrow is outstanding.
11091        unsafe { ffi::whiteout_m2_M2Model_resize_lights(self.raw.as_ptr(), count) }
11092    }
11093
11094    pub fn cameras_len(&self) -> usize {
11095        // SAFETY: scalar read through a live handle.
11096        unsafe { ffi::whiteout_m2_M2Model_get_cameras_count(self.raw.as_ptr()) }
11097    }
11098
11099    /// Borrows element `index` in place. `None` when out of range.
11100    pub fn cameras(&self, index: usize) -> Option<crate::support::Ref<'_, Camera>> {
11101        if index >= self.cameras_len() {
11102            return None;
11103        }
11104        // SAFETY: index checked above; the pointer is interior to `self`.
11105        unsafe {
11106            Some(crate::support::Ref::new(Camera {
11107                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_cameras_at(
11108                    self.raw.as_ptr(),
11109                    index,
11110                )),
11111            }))
11112        }
11113    }
11114
11115    pub fn cameras_mut(&mut self, index: usize) -> Option<crate::support::RefMut<'_, Camera>> {
11116        if index >= self.cameras_len() {
11117            return None;
11118        }
11119        // SAFETY: as above; `&mut self` guarantees exclusivity.
11120        unsafe {
11121            Some(crate::support::RefMut::new(Camera {
11122                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_cameras_at(
11123                    self.raw.as_ptr(),
11124                    index,
11125                )),
11126            }))
11127        }
11128    }
11129
11130    /// Iterate the elements, borrowing each in turn.
11131    pub fn cameras_iter(&self) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Camera>> {
11132        (0..self.cameras_len()).map(move |i| self.cameras(i).expect("index below len"))
11133    }
11134
11135    pub fn resize_cameras(&mut self, count: usize) {
11136        // SAFETY: exclusive access, so no borrow is outstanding.
11137        unsafe { ffi::whiteout_m2_M2Model_resize_cameras(self.raw.as_ptr(), count) }
11138    }
11139
11140    /// Zero-copy view of the underlying `std::vector`.
11141    pub fn camera_indices_by_id(&self) -> &[u16] {
11142        // SAFETY: `_data`/`_count` describe one contiguous C++
11143        // allocation, borrowed for as long as `self` is.
11144        unsafe {
11145            let n = ffi::whiteout_m2_M2Model_get_cameraIndicesById_count(self.raw.as_ptr());
11146            let p = ffi::whiteout_m2_M2Model_get_cameraIndicesById_data(self.raw.as_ptr());
11147            if p.is_null() || n == 0 {
11148                &[]
11149            } else {
11150                core::slice::from_raw_parts(p, n)
11151            }
11152        }
11153    }
11154
11155    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11156    pub fn camera_indices_by_id_mut(&mut self) -> &mut [u16] {
11157        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11158        unsafe {
11159            let n = ffi::whiteout_m2_M2Model_get_cameraIndicesById_count(self.raw.as_ptr());
11160            let p =
11161                ffi::whiteout_m2_M2Model_get_cameraIndicesById_data(self.raw.as_ptr()) as *mut u16;
11162            if p.is_null() || n == 0 {
11163                &mut []
11164            } else {
11165                core::slice::from_raw_parts_mut(p, n)
11166            }
11167        }
11168    }
11169
11170    pub fn set_camera_indices_by_id(&mut self, values: &[u16]) {
11171        // SAFETY: the native side copies `values` before returning.
11172        unsafe {
11173            ffi::whiteout_m2_M2Model_assign_cameraIndicesById(
11174                self.raw.as_ptr(),
11175                values.as_ptr() as *const _,
11176                values.len(),
11177            )
11178        }
11179    }
11180
11181    pub fn resize_camera_indices_by_id(&mut self, count: usize) {
11182        // SAFETY: reallocation is safe here precisely because
11183        // `&mut self` means no slice borrow is outstanding.
11184        unsafe { ffi::whiteout_m2_M2Model_resize_cameraIndicesById(self.raw.as_ptr(), count) }
11185    }
11186
11187    pub fn ribbon_emitters_len(&self) -> usize {
11188        // SAFETY: scalar read through a live handle.
11189        unsafe { ffi::whiteout_m2_M2Model_get_ribbonEmitters_count(self.raw.as_ptr()) }
11190    }
11191
11192    /// Borrows element `index` in place. `None` when out of range.
11193    pub fn ribbon_emitters(&self, index: usize) -> Option<crate::support::Ref<'_, RibbonEmitter>> {
11194        if index >= self.ribbon_emitters_len() {
11195            return None;
11196        }
11197        // SAFETY: index checked above; the pointer is interior to `self`.
11198        unsafe {
11199            Some(crate::support::Ref::new(RibbonEmitter {
11200                raw: core::ptr::NonNull::new_unchecked(
11201                    ffi::whiteout_m2_M2Model_get_ribbonEmitters_at(self.raw.as_ptr(), index),
11202                ),
11203            }))
11204        }
11205    }
11206
11207    pub fn ribbon_emitters_mut(
11208        &mut self,
11209        index: usize,
11210    ) -> Option<crate::support::RefMut<'_, RibbonEmitter>> {
11211        if index >= self.ribbon_emitters_len() {
11212            return None;
11213        }
11214        // SAFETY: as above; `&mut self` guarantees exclusivity.
11215        unsafe {
11216            Some(crate::support::RefMut::new(RibbonEmitter {
11217                raw: core::ptr::NonNull::new_unchecked(
11218                    ffi::whiteout_m2_M2Model_get_ribbonEmitters_at(self.raw.as_ptr(), index),
11219                ),
11220            }))
11221        }
11222    }
11223
11224    /// Iterate the elements, borrowing each in turn.
11225    pub fn ribbon_emitters_iter(
11226        &self,
11227    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, RibbonEmitter>> {
11228        (0..self.ribbon_emitters_len())
11229            .map(move |i| self.ribbon_emitters(i).expect("index below len"))
11230    }
11231
11232    pub fn resize_ribbon_emitters(&mut self, count: usize) {
11233        // SAFETY: exclusive access, so no borrow is outstanding.
11234        unsafe { ffi::whiteout_m2_M2Model_resize_ribbonEmitters(self.raw.as_ptr(), count) }
11235    }
11236
11237    pub fn particle_emitters_len(&self) -> usize {
11238        // SAFETY: scalar read through a live handle.
11239        unsafe { ffi::whiteout_m2_M2Model_get_particleEmitters_count(self.raw.as_ptr()) }
11240    }
11241
11242    /// Borrows element `index` in place. `None` when out of range.
11243    pub fn particle_emitters(
11244        &self,
11245        index: usize,
11246    ) -> Option<crate::support::Ref<'_, ParticleEmitter>> {
11247        if index >= self.particle_emitters_len() {
11248            return None;
11249        }
11250        // SAFETY: index checked above; the pointer is interior to `self`.
11251        unsafe {
11252            Some(crate::support::Ref::new(ParticleEmitter {
11253                raw: core::ptr::NonNull::new_unchecked(
11254                    ffi::whiteout_m2_M2Model_get_particleEmitters_at(self.raw.as_ptr(), index),
11255                ),
11256            }))
11257        }
11258    }
11259
11260    pub fn particle_emitters_mut(
11261        &mut self,
11262        index: usize,
11263    ) -> Option<crate::support::RefMut<'_, ParticleEmitter>> {
11264        if index >= self.particle_emitters_len() {
11265            return None;
11266        }
11267        // SAFETY: as above; `&mut self` guarantees exclusivity.
11268        unsafe {
11269            Some(crate::support::RefMut::new(ParticleEmitter {
11270                raw: core::ptr::NonNull::new_unchecked(
11271                    ffi::whiteout_m2_M2Model_get_particleEmitters_at(self.raw.as_ptr(), index),
11272                ),
11273            }))
11274        }
11275    }
11276
11277    /// Iterate the elements, borrowing each in turn.
11278    pub fn particle_emitters_iter(
11279        &self,
11280    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ParticleEmitter>> {
11281        (0..self.particle_emitters_len())
11282            .map(move |i| self.particle_emitters(i).expect("index below len"))
11283    }
11284
11285    pub fn resize_particle_emitters(&mut self, count: usize) {
11286        // SAFETY: exclusive access, so no borrow is outstanding.
11287        unsafe { ffi::whiteout_m2_M2Model_resize_particleEmitters(self.raw.as_ptr(), count) }
11288    }
11289
11290    /// Zero-copy view of the underlying `std::vector`.
11291    pub fn texture_combiner_combos(&self) -> &[u16] {
11292        // SAFETY: `_data`/`_count` describe one contiguous C++
11293        // allocation, borrowed for as long as `self` is.
11294        unsafe {
11295            let n = ffi::whiteout_m2_M2Model_get_textureCombinerCombos_count(self.raw.as_ptr());
11296            let p = ffi::whiteout_m2_M2Model_get_textureCombinerCombos_data(self.raw.as_ptr());
11297            if p.is_null() || n == 0 {
11298                &[]
11299            } else {
11300                core::slice::from_raw_parts(p, n)
11301            }
11302        }
11303    }
11304
11305    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11306    pub fn texture_combiner_combos_mut(&mut self) -> &mut [u16] {
11307        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11308        unsafe {
11309            let n = ffi::whiteout_m2_M2Model_get_textureCombinerCombos_count(self.raw.as_ptr());
11310            let p = ffi::whiteout_m2_M2Model_get_textureCombinerCombos_data(self.raw.as_ptr())
11311                as *mut u16;
11312            if p.is_null() || n == 0 {
11313                &mut []
11314            } else {
11315                core::slice::from_raw_parts_mut(p, n)
11316            }
11317        }
11318    }
11319
11320    pub fn set_texture_combiner_combos(&mut self, values: &[u16]) {
11321        // SAFETY: the native side copies `values` before returning.
11322        unsafe {
11323            ffi::whiteout_m2_M2Model_assign_textureCombinerCombos(
11324                self.raw.as_ptr(),
11325                values.as_ptr() as *const _,
11326                values.len(),
11327            )
11328        }
11329    }
11330
11331    pub fn resize_texture_combiner_combos(&mut self, count: usize) {
11332        // SAFETY: reallocation is safe here precisely because
11333        // `&mut self` means no slice borrow is outstanding.
11334        unsafe { ffi::whiteout_m2_M2Model_resize_textureCombinerCombos(self.raw.as_ptr(), count) }
11335    }
11336
11337    /// One 4-byte record per animation id; vanilla/BC clients use it to pick fallback animations. Preserved verbatim so old files round-trip.
11338    /// Zero-copy view of the underlying `std::vector`.
11339    pub fn playable_animation_lookup(&self) -> &[u32] {
11340        // SAFETY: `_data`/`_count` describe one contiguous C++
11341        // allocation, borrowed for as long as `self` is.
11342        unsafe {
11343            let n = ffi::whiteout_m2_M2Model_get_playableAnimationLookup_count(self.raw.as_ptr());
11344            let p = ffi::whiteout_m2_M2Model_get_playableAnimationLookup_data(self.raw.as_ptr());
11345            if p.is_null() || n == 0 {
11346                &[]
11347            } else {
11348                core::slice::from_raw_parts(p, n)
11349            }
11350        }
11351    }
11352
11353    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11354    pub fn playable_animation_lookup_mut(&mut self) -> &mut [u32] {
11355        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11356        unsafe {
11357            let n = ffi::whiteout_m2_M2Model_get_playableAnimationLookup_count(self.raw.as_ptr());
11358            let p = ffi::whiteout_m2_M2Model_get_playableAnimationLookup_data(self.raw.as_ptr())
11359                as *mut u32;
11360            if p.is_null() || n == 0 {
11361                &mut []
11362            } else {
11363                core::slice::from_raw_parts_mut(p, n)
11364            }
11365        }
11366    }
11367
11368    pub fn set_playable_animation_lookup(&mut self, values: &[u32]) {
11369        // SAFETY: the native side copies `values` before returning.
11370        unsafe {
11371            ffi::whiteout_m2_M2Model_assign_playableAnimationLookup(
11372                self.raw.as_ptr(),
11373                values.as_ptr() as *const _,
11374                values.len(),
11375            )
11376        }
11377    }
11378
11379    pub fn resize_playable_animation_lookup(&mut self, count: usize) {
11380        // SAFETY: reallocation is safe here precisely because
11381        // `&mut self` means no slice borrow is outstanding.
11382        unsafe { ffi::whiteout_m2_M2Model_resize_playableAnimationLookup(self.raw.as_ptr(), count) }
11383    }
11384
11385    /// "Texture flipbooks" — unused even by old clients, preserved verbatim.
11386    /// Zero-copy view of the underlying `std::vector`.
11387    pub fn texture_flipbooks(&self) -> &[u16] {
11388        // SAFETY: `_data`/`_count` describe one contiguous C++
11389        // allocation, borrowed for as long as `self` is.
11390        unsafe {
11391            let n = ffi::whiteout_m2_M2Model_get_textureFlipbooks_count(self.raw.as_ptr());
11392            let p = ffi::whiteout_m2_M2Model_get_textureFlipbooks_data(self.raw.as_ptr());
11393            if p.is_null() || n == 0 {
11394                &[]
11395            } else {
11396                core::slice::from_raw_parts(p, n)
11397            }
11398        }
11399    }
11400
11401    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11402    pub fn texture_flipbooks_mut(&mut self) -> &mut [u16] {
11403        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11404        unsafe {
11405            let n = ffi::whiteout_m2_M2Model_get_textureFlipbooks_count(self.raw.as_ptr());
11406            let p =
11407                ffi::whiteout_m2_M2Model_get_textureFlipbooks_data(self.raw.as_ptr()) as *mut u16;
11408            if p.is_null() || n == 0 {
11409                &mut []
11410            } else {
11411                core::slice::from_raw_parts_mut(p, n)
11412            }
11413        }
11414    }
11415
11416    pub fn set_texture_flipbooks(&mut self, values: &[u16]) {
11417        // SAFETY: the native side copies `values` before returning.
11418        unsafe {
11419            ffi::whiteout_m2_M2Model_assign_textureFlipbooks(
11420                self.raw.as_ptr(),
11421                values.as_ptr() as *const _,
11422                values.len(),
11423            )
11424        }
11425    }
11426
11427    pub fn resize_texture_flipbooks(&mut self, count: usize) {
11428        // SAFETY: reallocation is safe here precisely because
11429        // `&mut self` means no slice borrow is outstanding.
11430        unsafe { ffi::whiteout_m2_M2Model_resize_textureFlipbooks(self.raw.as_ptr(), count) }
11431    }
11432
11433    /// TXID
11434    /// Zero-copy view of the underlying `std::vector`.
11435    pub fn texture_ids(&self) -> &[u32] {
11436        // SAFETY: `_data`/`_count` describe one contiguous C++
11437        // allocation, borrowed for as long as `self` is.
11438        unsafe {
11439            let n = ffi::whiteout_m2_M2Model_get_texture_ids_count(self.raw.as_ptr());
11440            let p = ffi::whiteout_m2_M2Model_get_texture_ids_data(self.raw.as_ptr());
11441            if p.is_null() || n == 0 {
11442                &[]
11443            } else {
11444                core::slice::from_raw_parts(p, n)
11445            }
11446        }
11447    }
11448
11449    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11450    pub fn texture_ids_mut(&mut self) -> &mut [u32] {
11451        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11452        unsafe {
11453            let n = ffi::whiteout_m2_M2Model_get_texture_ids_count(self.raw.as_ptr());
11454            let p = ffi::whiteout_m2_M2Model_get_texture_ids_data(self.raw.as_ptr()) as *mut u32;
11455            if p.is_null() || n == 0 {
11456                &mut []
11457            } else {
11458                core::slice::from_raw_parts_mut(p, n)
11459            }
11460        }
11461    }
11462
11463    pub fn set_texture_ids(&mut self, values: &[u32]) {
11464        // SAFETY: the native side copies `values` before returning.
11465        unsafe {
11466            ffi::whiteout_m2_M2Model_assign_texture_ids(
11467                self.raw.as_ptr(),
11468                values.as_ptr() as *const _,
11469                values.len(),
11470            )
11471        }
11472    }
11473
11474    pub fn resize_texture_ids(&mut self, count: usize) {
11475        // SAFETY: reallocation is safe here precisely because
11476        // `&mut self` means no slice borrow is outstanding.
11477        unsafe { ffi::whiteout_m2_M2Model_resize_texture_ids(self.raw.as_ptr(), count) }
11478    }
11479
11480    /// PABC
11481    /// Zero-copy view of the underlying `std::vector`.
11482    pub fn parent_sequence_replacements(&self) -> &[u16] {
11483        // SAFETY: `_data`/`_count` describe one contiguous C++
11484        // allocation, borrowed for as long as `self` is.
11485        unsafe {
11486            let n =
11487                ffi::whiteout_m2_M2Model_get_parentSequenceReplacements_count(self.raw.as_ptr());
11488            let p = ffi::whiteout_m2_M2Model_get_parentSequenceReplacements_data(self.raw.as_ptr());
11489            if p.is_null() || n == 0 {
11490                &[]
11491            } else {
11492                core::slice::from_raw_parts(p, n)
11493            }
11494        }
11495    }
11496
11497    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11498    pub fn parent_sequence_replacements_mut(&mut self) -> &mut [u16] {
11499        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11500        unsafe {
11501            let n =
11502                ffi::whiteout_m2_M2Model_get_parentSequenceReplacements_count(self.raw.as_ptr());
11503            let p = ffi::whiteout_m2_M2Model_get_parentSequenceReplacements_data(self.raw.as_ptr())
11504                as *mut u16;
11505            if p.is_null() || n == 0 {
11506                &mut []
11507            } else {
11508                core::slice::from_raw_parts_mut(p, n)
11509            }
11510        }
11511    }
11512
11513    pub fn set_parent_sequence_replacements(&mut self, values: &[u16]) {
11514        // SAFETY: the native side copies `values` before returning.
11515        unsafe {
11516            ffi::whiteout_m2_M2Model_assign_parentSequenceReplacements(
11517                self.raw.as_ptr(),
11518                values.as_ptr() as *const _,
11519                values.len(),
11520            )
11521        }
11522    }
11523
11524    pub fn resize_parent_sequence_replacements(&mut self, count: usize) {
11525        // SAFETY: reallocation is safe here precisely because
11526        // `&mut self` means no slice borrow is outstanding.
11527        unsafe {
11528            ffi::whiteout_m2_M2Model_resize_parentSequenceReplacements(self.raw.as_ptr(), count)
11529        }
11530    }
11531
11532    /// PADC
11533    pub fn parent_texture_weights_len(&self) -> usize {
11534        // SAFETY: scalar read through a live handle.
11535        unsafe { ffi::whiteout_m2_M2Model_get_parentTextureWeights_count(self.raw.as_ptr()) }
11536    }
11537
11538    /// Borrows element `index` in place. `None` when out of range.
11539    pub fn parent_texture_weights(
11540        &self,
11541        index: usize,
11542    ) -> Option<crate::support::Ref<'_, TextureWeight>> {
11543        if index >= self.parent_texture_weights_len() {
11544            return None;
11545        }
11546        // SAFETY: index checked above; the pointer is interior to `self`.
11547        unsafe {
11548            Some(crate::support::Ref::new(TextureWeight {
11549                raw: core::ptr::NonNull::new_unchecked(
11550                    ffi::whiteout_m2_M2Model_get_parentTextureWeights_at(self.raw.as_ptr(), index),
11551                ),
11552            }))
11553        }
11554    }
11555
11556    pub fn parent_texture_weights_mut(
11557        &mut self,
11558        index: usize,
11559    ) -> Option<crate::support::RefMut<'_, TextureWeight>> {
11560        if index >= self.parent_texture_weights_len() {
11561            return None;
11562        }
11563        // SAFETY: as above; `&mut self` guarantees exclusivity.
11564        unsafe {
11565            Some(crate::support::RefMut::new(TextureWeight {
11566                raw: core::ptr::NonNull::new_unchecked(
11567                    ffi::whiteout_m2_M2Model_get_parentTextureWeights_at(self.raw.as_ptr(), index),
11568                ),
11569            }))
11570        }
11571    }
11572
11573    /// Iterate the elements, borrowing each in turn.
11574    pub fn parent_texture_weights_iter(
11575        &self,
11576    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TextureWeight>> {
11577        (0..self.parent_texture_weights_len())
11578            .map(move |i| self.parent_texture_weights(i).expect("index below len"))
11579    }
11580
11581    pub fn resize_parent_texture_weights(&mut self, count: usize) {
11582        // SAFETY: exclusive access, so no borrow is outstanding.
11583        unsafe { ffi::whiteout_m2_M2Model_resize_parentTextureWeights(self.raw.as_ptr(), count) }
11584    }
11585
11586    /// PSBC
11587    pub fn parent_sequence_bounds_len(&self) -> usize {
11588        // SAFETY: scalar read through a live handle.
11589        unsafe { ffi::whiteout_m2_M2Model_get_parentSequenceBounds_count(self.raw.as_ptr()) }
11590    }
11591
11592    /// Borrows element `index` in place. `None` when out of range.
11593    pub fn parent_sequence_bounds(&self, index: usize) -> Option<crate::support::Ref<'_, Extent>> {
11594        if index >= self.parent_sequence_bounds_len() {
11595            return None;
11596        }
11597        // SAFETY: index checked above; the pointer is interior to `self`.
11598        unsafe {
11599            Some(crate::support::Ref::new(Extent {
11600                raw: core::ptr::NonNull::new_unchecked(
11601                    ffi::whiteout_m2_M2Model_get_parentSequenceBounds_at(self.raw.as_ptr(), index),
11602                ),
11603            }))
11604        }
11605    }
11606
11607    pub fn parent_sequence_bounds_mut(
11608        &mut self,
11609        index: usize,
11610    ) -> Option<crate::support::RefMut<'_, Extent>> {
11611        if index >= self.parent_sequence_bounds_len() {
11612            return None;
11613        }
11614        // SAFETY: as above; `&mut self` guarantees exclusivity.
11615        unsafe {
11616            Some(crate::support::RefMut::new(Extent {
11617                raw: core::ptr::NonNull::new_unchecked(
11618                    ffi::whiteout_m2_M2Model_get_parentSequenceBounds_at(self.raw.as_ptr(), index),
11619                ),
11620            }))
11621        }
11622    }
11623
11624    /// Iterate the elements, borrowing each in turn.
11625    pub fn parent_sequence_bounds_iter(
11626        &self,
11627    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, Extent>> {
11628        (0..self.parent_sequence_bounds_len())
11629            .map(move |i| self.parent_sequence_bounds(i).expect("index below len"))
11630    }
11631
11632    pub fn resize_parent_sequence_bounds(&mut self, count: usize) {
11633        // SAFETY: exclusive access, so no borrow is outstanding.
11634        unsafe { ffi::whiteout_m2_M2Model_resize_parentSequenceBounds(self.raw.as_ptr(), count) }
11635    }
11636
11637    /// PEDC
11638    pub fn parent_event_data_len(&self) -> usize {
11639        // SAFETY: scalar read through a live handle.
11640        unsafe { ffi::whiteout_m2_M2Model_get_parentEventData_count(self.raw.as_ptr()) }
11641    }
11642
11643    /// Borrows element `index` in place. `None` when out of range.
11644    pub fn parent_event_data(
11645        &self,
11646        index: usize,
11647    ) -> Option<crate::support::Ref<'_, AnimationTrackBase>> {
11648        if index >= self.parent_event_data_len() {
11649            return None;
11650        }
11651        // SAFETY: index checked above; the pointer is interior to `self`.
11652        unsafe {
11653            Some(crate::support::Ref::new(AnimationTrackBase {
11654                raw: core::ptr::NonNull::new_unchecked(
11655                    ffi::whiteout_m2_M2Model_get_parentEventData_at(self.raw.as_ptr(), index),
11656                ),
11657            }))
11658        }
11659    }
11660
11661    pub fn parent_event_data_mut(
11662        &mut self,
11663        index: usize,
11664    ) -> Option<crate::support::RefMut<'_, AnimationTrackBase>> {
11665        if index >= self.parent_event_data_len() {
11666            return None;
11667        }
11668        // SAFETY: as above; `&mut self` guarantees exclusivity.
11669        unsafe {
11670            Some(crate::support::RefMut::new(AnimationTrackBase {
11671                raw: core::ptr::NonNull::new_unchecked(
11672                    ffi::whiteout_m2_M2Model_get_parentEventData_at(self.raw.as_ptr(), index),
11673                ),
11674            }))
11675        }
11676    }
11677
11678    /// Iterate the elements, borrowing each in turn.
11679    pub fn parent_event_data_iter(
11680        &self,
11681    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, AnimationTrackBase>> {
11682        (0..self.parent_event_data_len())
11683            .map(move |i| self.parent_event_data(i).expect("index below len"))
11684    }
11685
11686    pub fn resize_parent_event_data(&mut self, count: usize) {
11687        // SAFETY: exclusive access, so no borrow is outstanding.
11688        unsafe { ffi::whiteout_m2_M2Model_resize_parentEventData(self.raw.as_ptr(), count) }
11689    }
11690
11691    /// RPID
11692    /// Zero-copy view of the underlying `std::vector`.
11693    pub fn recursive_particle_model_ids(&self) -> &[u32] {
11694        // SAFETY: `_data`/`_count` describe one contiguous C++
11695        // allocation, borrowed for as long as `self` is.
11696        unsafe {
11697            let n = ffi::whiteout_m2_M2Model_get_recursiveParticleModelIds_count(self.raw.as_ptr());
11698            let p = ffi::whiteout_m2_M2Model_get_recursiveParticleModelIds_data(self.raw.as_ptr());
11699            if p.is_null() || n == 0 {
11700                &[]
11701            } else {
11702                core::slice::from_raw_parts(p, n)
11703            }
11704        }
11705    }
11706
11707    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11708    pub fn recursive_particle_model_ids_mut(&mut self) -> &mut [u32] {
11709        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11710        unsafe {
11711            let n = ffi::whiteout_m2_M2Model_get_recursiveParticleModelIds_count(self.raw.as_ptr());
11712            let p = ffi::whiteout_m2_M2Model_get_recursiveParticleModelIds_data(self.raw.as_ptr())
11713                as *mut u32;
11714            if p.is_null() || n == 0 {
11715                &mut []
11716            } else {
11717                core::slice::from_raw_parts_mut(p, n)
11718            }
11719        }
11720    }
11721
11722    pub fn set_recursive_particle_model_ids(&mut self, values: &[u32]) {
11723        // SAFETY: the native side copies `values` before returning.
11724        unsafe {
11725            ffi::whiteout_m2_M2Model_assign_recursiveParticleModelIds(
11726                self.raw.as_ptr(),
11727                values.as_ptr() as *const _,
11728                values.len(),
11729            )
11730        }
11731    }
11732
11733    pub fn resize_recursive_particle_model_ids(&mut self, count: usize) {
11734        // SAFETY: reallocation is safe here precisely because
11735        // `&mut self` means no slice borrow is outstanding.
11736        unsafe {
11737            ffi::whiteout_m2_M2Model_resize_recursiveParticleModelIds(self.raw.as_ptr(), count)
11738        }
11739    }
11740
11741    /// GPID
11742    /// Zero-copy view of the underlying `std::vector`.
11743    pub fn geometry_particle_model_ids(&self) -> &[u32] {
11744        // SAFETY: `_data`/`_count` describe one contiguous C++
11745        // allocation, borrowed for as long as `self` is.
11746        unsafe {
11747            let n = ffi::whiteout_m2_M2Model_get_geometryParticleModelIds_count(self.raw.as_ptr());
11748            let p = ffi::whiteout_m2_M2Model_get_geometryParticleModelIds_data(self.raw.as_ptr());
11749            if p.is_null() || n == 0 {
11750                &[]
11751            } else {
11752                core::slice::from_raw_parts(p, n)
11753            }
11754        }
11755    }
11756
11757    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11758    pub fn geometry_particle_model_ids_mut(&mut self) -> &mut [u32] {
11759        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11760        unsafe {
11761            let n = ffi::whiteout_m2_M2Model_get_geometryParticleModelIds_count(self.raw.as_ptr());
11762            let p = ffi::whiteout_m2_M2Model_get_geometryParticleModelIds_data(self.raw.as_ptr())
11763                as *mut u32;
11764            if p.is_null() || n == 0 {
11765                &mut []
11766            } else {
11767                core::slice::from_raw_parts_mut(p, n)
11768            }
11769        }
11770    }
11771
11772    pub fn set_geometry_particle_model_ids(&mut self, values: &[u32]) {
11773        // SAFETY: the native side copies `values` before returning.
11774        unsafe {
11775            ffi::whiteout_m2_M2Model_assign_geometryParticleModelIds(
11776                self.raw.as_ptr(),
11777                values.as_ptr() as *const _,
11778                values.len(),
11779            )
11780        }
11781    }
11782
11783    pub fn resize_geometry_particle_model_ids(&mut self, count: usize) {
11784        // SAFETY: reallocation is safe here precisely because
11785        // `&mut self` means no slice borrow is outstanding.
11786        unsafe {
11787            ffi::whiteout_m2_M2Model_resize_geometryParticleModelIds(self.raw.as_ptr(), count)
11788        }
11789    }
11790
11791    /// PGD1
11792    pub fn particle_geosets_len(&self) -> usize {
11793        // SAFETY: scalar read through a live handle.
11794        unsafe { ffi::whiteout_m2_M2Model_get_particleGeosets_count(self.raw.as_ptr()) }
11795    }
11796
11797    /// Borrows element `index` in place. `None` when out of range.
11798    pub fn particle_geosets(
11799        &self,
11800        index: usize,
11801    ) -> Option<crate::support::Ref<'_, ParticleGeosetData>> {
11802        if index >= self.particle_geosets_len() {
11803            return None;
11804        }
11805        // SAFETY: index checked above; the pointer is interior to `self`.
11806        unsafe {
11807            Some(crate::support::Ref::new(ParticleGeosetData {
11808                raw: core::ptr::NonNull::new_unchecked(
11809                    ffi::whiteout_m2_M2Model_get_particleGeosets_at(self.raw.as_ptr(), index),
11810                ),
11811            }))
11812        }
11813    }
11814
11815    pub fn particle_geosets_mut(
11816        &mut self,
11817        index: usize,
11818    ) -> Option<crate::support::RefMut<'_, ParticleGeosetData>> {
11819        if index >= self.particle_geosets_len() {
11820            return None;
11821        }
11822        // SAFETY: as above; `&mut self` guarantees exclusivity.
11823        unsafe {
11824            Some(crate::support::RefMut::new(ParticleGeosetData {
11825                raw: core::ptr::NonNull::new_unchecked(
11826                    ffi::whiteout_m2_M2Model_get_particleGeosets_at(self.raw.as_ptr(), index),
11827                ),
11828            }))
11829        }
11830    }
11831
11832    /// Iterate the elements, borrowing each in turn.
11833    pub fn particle_geosets_iter(
11834        &self,
11835    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, ParticleGeosetData>> {
11836        (0..self.particle_geosets_len())
11837            .map(move |i| self.particle_geosets(i).expect("index below len"))
11838    }
11839
11840    pub fn resize_particle_geosets(&mut self, count: usize) {
11841        // SAFETY: exclusive access, so no borrow is outstanding.
11842        unsafe { ffi::whiteout_m2_M2Model_resize_particleGeosets(self.raw.as_ptr(), count) }
11843    }
11844
11845    /// One entry per customization choice, in BFID order — see bone_file.h.
11846    pub fn bone_overrides_len(&self) -> usize {
11847        // SAFETY: scalar read through a live handle.
11848        unsafe { ffi::whiteout_m2_M2Model_get_boneOverrides_count(self.raw.as_ptr()) }
11849    }
11850
11851    /// Borrows element `index` in place. `None` when out of range.
11852    pub fn bone_overrides(&self, index: usize) -> Option<crate::support::Ref<'_, BoneOverrideSet>> {
11853        if index >= self.bone_overrides_len() {
11854            return None;
11855        }
11856        // SAFETY: index checked above; the pointer is interior to `self`.
11857        unsafe {
11858            Some(crate::support::Ref::new(BoneOverrideSet {
11859                raw: core::ptr::NonNull::new_unchecked(
11860                    ffi::whiteout_m2_M2Model_get_boneOverrides_at(self.raw.as_ptr(), index),
11861                ),
11862            }))
11863        }
11864    }
11865
11866    pub fn bone_overrides_mut(
11867        &mut self,
11868        index: usize,
11869    ) -> Option<crate::support::RefMut<'_, BoneOverrideSet>> {
11870        if index >= self.bone_overrides_len() {
11871            return None;
11872        }
11873        // SAFETY: as above; `&mut self` guarantees exclusivity.
11874        unsafe {
11875            Some(crate::support::RefMut::new(BoneOverrideSet {
11876                raw: core::ptr::NonNull::new_unchecked(
11877                    ffi::whiteout_m2_M2Model_get_boneOverrides_at(self.raw.as_ptr(), index),
11878                ),
11879            }))
11880        }
11881    }
11882
11883    /// Iterate the elements, borrowing each in turn.
11884    pub fn bone_overrides_iter(
11885        &self,
11886    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, BoneOverrideSet>> {
11887        (0..self.bone_overrides_len())
11888            .map(move |i| self.bone_overrides(i).expect("index below len"))
11889    }
11890
11891    pub fn resize_bone_overrides(&mut self, count: usize) {
11892        // SAFETY: exclusive access, so no borrow is outstanding.
11893        unsafe { ffi::whiteout_m2_M2Model_resize_boneOverrides(self.raw.as_ptr(), count) }
11894    }
11895
11896    /// BFID, kept so a model that named its `.bone` files by id keeps doing so. Parallel to @ref boneOverrides when both are present.
11897    /// Zero-copy view of the underlying `std::vector`.
11898    pub fn bone_file_ids(&self) -> &[u32] {
11899        // SAFETY: `_data`/`_count` describe one contiguous C++
11900        // allocation, borrowed for as long as `self` is.
11901        unsafe {
11902            let n = ffi::whiteout_m2_M2Model_get_boneFileIds_count(self.raw.as_ptr());
11903            let p = ffi::whiteout_m2_M2Model_get_boneFileIds_data(self.raw.as_ptr());
11904            if p.is_null() || n == 0 {
11905                &[]
11906            } else {
11907                core::slice::from_raw_parts(p, n)
11908            }
11909        }
11910    }
11911
11912    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
11913    pub fn bone_file_ids_mut(&mut self) -> &mut [u32] {
11914        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
11915        unsafe {
11916            let n = ffi::whiteout_m2_M2Model_get_boneFileIds_count(self.raw.as_ptr());
11917            let p = ffi::whiteout_m2_M2Model_get_boneFileIds_data(self.raw.as_ptr()) as *mut u32;
11918            if p.is_null() || n == 0 {
11919                &mut []
11920            } else {
11921                core::slice::from_raw_parts_mut(p, n)
11922            }
11923        }
11924    }
11925
11926    pub fn set_bone_file_ids(&mut self, values: &[u32]) {
11927        // SAFETY: the native side copies `values` before returning.
11928        unsafe {
11929            ffi::whiteout_m2_M2Model_assign_boneFileIds(
11930                self.raw.as_ptr(),
11931                values.as_ptr() as *const _,
11932                values.len(),
11933            )
11934        }
11935    }
11936
11937    pub fn resize_bone_file_ids(&mut self, count: usize) {
11938        // SAFETY: reallocation is safe here precisely because
11939        // `&mut self` means no slice borrow is outstanding.
11940        unsafe { ffi::whiteout_m2_M2Model_resize_boneFileIds(self.raw.as_ptr(), count) }
11941    }
11942
11943    /// EDGF
11944    pub fn edge_fade_entries_len(&self) -> usize {
11945        // SAFETY: scalar read through a live handle.
11946        unsafe { ffi::whiteout_m2_M2Model_get_edgeFadeEntries_count(self.raw.as_ptr()) }
11947    }
11948
11949    /// Borrows element `index` in place. `None` when out of range.
11950    pub fn edge_fade_entries(&self, index: usize) -> Option<crate::support::Ref<'_, EdgeFadeData>> {
11951        if index >= self.edge_fade_entries_len() {
11952            return None;
11953        }
11954        // SAFETY: index checked above; the pointer is interior to `self`.
11955        unsafe {
11956            Some(crate::support::Ref::new(EdgeFadeData {
11957                raw: core::ptr::NonNull::new_unchecked(
11958                    ffi::whiteout_m2_M2Model_get_edgeFadeEntries_at(self.raw.as_ptr(), index),
11959                ),
11960            }))
11961        }
11962    }
11963
11964    pub fn edge_fade_entries_mut(
11965        &mut self,
11966        index: usize,
11967    ) -> Option<crate::support::RefMut<'_, EdgeFadeData>> {
11968        if index >= self.edge_fade_entries_len() {
11969            return None;
11970        }
11971        // SAFETY: as above; `&mut self` guarantees exclusivity.
11972        unsafe {
11973            Some(crate::support::RefMut::new(EdgeFadeData {
11974                raw: core::ptr::NonNull::new_unchecked(
11975                    ffi::whiteout_m2_M2Model_get_edgeFadeEntries_at(self.raw.as_ptr(), index),
11976                ),
11977            }))
11978        }
11979    }
11980
11981    /// Iterate the elements, borrowing each in turn.
11982    pub fn edge_fade_entries_iter(
11983        &self,
11984    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, EdgeFadeData>> {
11985        (0..self.edge_fade_entries_len())
11986            .map(move |i| self.edge_fade_entries(i).expect("index below len"))
11987    }
11988
11989    pub fn resize_edge_fade_entries(&mut self, count: usize) {
11990        // SAFETY: exclusive access, so no borrow is outstanding.
11991        unsafe { ffi::whiteout_m2_M2Model_resize_edgeFadeEntries(self.raw.as_ptr(), count) }
11992    }
11993
11994    /// NERF
11995    pub fn nerf_entries_len(&self) -> usize {
11996        // SAFETY: scalar read through a live handle.
11997        unsafe { ffi::whiteout_m2_M2Model_get_nerfEntries_count(self.raw.as_ptr()) }
11998    }
11999
12000    /// Borrows element `index` in place. `None` when out of range.
12001    pub fn nerf_entries(&self, index: usize) -> Option<crate::support::Ref<'_, DistanceFadeData>> {
12002        if index >= self.nerf_entries_len() {
12003            return None;
12004        }
12005        // SAFETY: index checked above; the pointer is interior to `self`.
12006        unsafe {
12007            Some(crate::support::Ref::new(DistanceFadeData {
12008                raw: core::ptr::NonNull::new_unchecked(
12009                    ffi::whiteout_m2_M2Model_get_nerfEntries_at(self.raw.as_ptr(), index),
12010                ),
12011            }))
12012        }
12013    }
12014
12015    pub fn nerf_entries_mut(
12016        &mut self,
12017        index: usize,
12018    ) -> Option<crate::support::RefMut<'_, DistanceFadeData>> {
12019        if index >= self.nerf_entries_len() {
12020            return None;
12021        }
12022        // SAFETY: as above; `&mut self` guarantees exclusivity.
12023        unsafe {
12024            Some(crate::support::RefMut::new(DistanceFadeData {
12025                raw: core::ptr::NonNull::new_unchecked(
12026                    ffi::whiteout_m2_M2Model_get_nerfEntries_at(self.raw.as_ptr(), index),
12027                ),
12028            }))
12029        }
12030    }
12031
12032    /// Iterate the elements, borrowing each in turn.
12033    pub fn nerf_entries_iter(
12034        &self,
12035    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DistanceFadeData>> {
12036        (0..self.nerf_entries_len()).map(move |i| self.nerf_entries(i).expect("index below len"))
12037    }
12038
12039    pub fn resize_nerf_entries(&mut self, count: usize) {
12040        // SAFETY: exclusive access, so no borrow is outstanding.
12041        unsafe { ffi::whiteout_m2_M2Model_resize_nerfEntries(self.raw.as_ptr(), count) }
12042    }
12043
12044    /// DETL
12045    pub fn detailed_light_entries_len(&self) -> usize {
12046        // SAFETY: scalar read through a live handle.
12047        unsafe { ffi::whiteout_m2_M2Model_get_detailedLightEntries_count(self.raw.as_ptr()) }
12048    }
12049
12050    /// Borrows element `index` in place. `None` when out of range.
12051    pub fn detailed_light_entries(
12052        &self,
12053        index: usize,
12054    ) -> Option<crate::support::Ref<'_, DetailedLightData>> {
12055        if index >= self.detailed_light_entries_len() {
12056            return None;
12057        }
12058        // SAFETY: index checked above; the pointer is interior to `self`.
12059        unsafe {
12060            Some(crate::support::Ref::new(DetailedLightData {
12061                raw: core::ptr::NonNull::new_unchecked(
12062                    ffi::whiteout_m2_M2Model_get_detailedLightEntries_at(self.raw.as_ptr(), index),
12063                ),
12064            }))
12065        }
12066    }
12067
12068    pub fn detailed_light_entries_mut(
12069        &mut self,
12070        index: usize,
12071    ) -> Option<crate::support::RefMut<'_, DetailedLightData>> {
12072        if index >= self.detailed_light_entries_len() {
12073            return None;
12074        }
12075        // SAFETY: as above; `&mut self` guarantees exclusivity.
12076        unsafe {
12077            Some(crate::support::RefMut::new(DetailedLightData {
12078                raw: core::ptr::NonNull::new_unchecked(
12079                    ffi::whiteout_m2_M2Model_get_detailedLightEntries_at(self.raw.as_ptr(), index),
12080                ),
12081            }))
12082        }
12083    }
12084
12085    /// Iterate the elements, borrowing each in turn.
12086    pub fn detailed_light_entries_iter(
12087        &self,
12088    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DetailedLightData>> {
12089        (0..self.detailed_light_entries_len())
12090            .map(move |i| self.detailed_light_entries(i).expect("index below len"))
12091    }
12092
12093    pub fn resize_detailed_light_entries(&mut self, count: usize) {
12094        // SAFETY: exclusive access, so no borrow is outstanding.
12095        unsafe { ffi::whiteout_m2_M2Model_resize_detailedLightEntries(self.raw.as_ptr(), count) }
12096    }
12097
12098    /// DBOC
12099    pub fn debug_occlusion_entries_len(&self) -> usize {
12100        // SAFETY: scalar read through a live handle.
12101        unsafe { ffi::whiteout_m2_M2Model_get_debugOcclusionEntries_count(self.raw.as_ptr()) }
12102    }
12103
12104    /// Borrows element `index` in place. `None` when out of range.
12105    pub fn debug_occlusion_entries(
12106        &self,
12107        index: usize,
12108    ) -> Option<crate::support::Ref<'_, DebugOcclusionData>> {
12109        if index >= self.debug_occlusion_entries_len() {
12110            return None;
12111        }
12112        // SAFETY: index checked above; the pointer is interior to `self`.
12113        unsafe {
12114            Some(crate::support::Ref::new(DebugOcclusionData {
12115                raw: core::ptr::NonNull::new_unchecked(
12116                    ffi::whiteout_m2_M2Model_get_debugOcclusionEntries_at(self.raw.as_ptr(), index),
12117                ),
12118            }))
12119        }
12120    }
12121
12122    pub fn debug_occlusion_entries_mut(
12123        &mut self,
12124        index: usize,
12125    ) -> Option<crate::support::RefMut<'_, DebugOcclusionData>> {
12126        if index >= self.debug_occlusion_entries_len() {
12127            return None;
12128        }
12129        // SAFETY: as above; `&mut self` guarantees exclusivity.
12130        unsafe {
12131            Some(crate::support::RefMut::new(DebugOcclusionData {
12132                raw: core::ptr::NonNull::new_unchecked(
12133                    ffi::whiteout_m2_M2Model_get_debugOcclusionEntries_at(self.raw.as_ptr(), index),
12134                ),
12135            }))
12136        }
12137    }
12138
12139    /// Iterate the elements, borrowing each in turn.
12140    pub fn debug_occlusion_entries_iter(
12141        &self,
12142    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, DebugOcclusionData>> {
12143        (0..self.debug_occlusion_entries_len())
12144            .map(move |i| self.debug_occlusion_entries(i).expect("index below len"))
12145    }
12146
12147    pub fn resize_debug_occlusion_entries(&mut self, count: usize) {
12148        // SAFETY: exclusive access, so no borrow is outstanding.
12149        unsafe { ffi::whiteout_m2_M2Model_resize_debugOcclusionEntries(self.raw.as_ptr(), count) }
12150    }
12151
12152    /// AFRA
12153    /// Zero-copy view of the underlying `std::vector`.
12154    pub fn anim_frame_data(&self) -> &[u8] {
12155        // SAFETY: `_data`/`_count` describe one contiguous C++
12156        // allocation, borrowed for as long as `self` is.
12157        unsafe {
12158            let n = ffi::whiteout_m2_M2Model_get_animFrameData_count(self.raw.as_ptr());
12159            let p = ffi::whiteout_m2_M2Model_get_animFrameData_data(self.raw.as_ptr());
12160            if p.is_null() || n == 0 {
12161                &[]
12162            } else {
12163                core::slice::from_raw_parts(p, n)
12164            }
12165        }
12166    }
12167
12168    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
12169    pub fn anim_frame_data_mut(&mut self) -> &mut [u8] {
12170        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
12171        unsafe {
12172            let n = ffi::whiteout_m2_M2Model_get_animFrameData_count(self.raw.as_ptr());
12173            let p = ffi::whiteout_m2_M2Model_get_animFrameData_data(self.raw.as_ptr()) as *mut u8;
12174            if p.is_null() || n == 0 {
12175                &mut []
12176            } else {
12177                core::slice::from_raw_parts_mut(p, n)
12178            }
12179        }
12180    }
12181
12182    pub fn set_anim_frame_data(&mut self, values: &[u8]) {
12183        // SAFETY: the native side copies `values` before returning.
12184        unsafe {
12185            ffi::whiteout_m2_M2Model_assign_animFrameData(
12186                self.raw.as_ptr(),
12187                values.as_ptr() as *const _,
12188                values.len(),
12189            )
12190        }
12191    }
12192
12193    pub fn resize_anim_frame_data(&mut self, count: usize) {
12194        // SAFETY: reallocation is safe here precisely because
12195        // `&mut self` means no slice borrow is outstanding.
12196        unsafe { ffi::whiteout_m2_M2Model_resize_animFrameData(self.raw.as_ptr(), count) }
12197    }
12198
12199    /// DPIV (32 B per record)
12200    pub fn dpiv_data_len(&self) -> usize {
12201        // SAFETY: scalar read through a live handle.
12202        unsafe { ffi::whiteout_m2_M2Model_get_dpivData_count(self.raw.as_ptr()) }
12203    }
12204
12205    /// Borrows element `index` in place. `None` when out of range.
12206    pub fn dpiv_data(
12207        &self,
12208        index: usize,
12209    ) -> Option<crate::support::Ref<'_, PivotDisplacementData>> {
12210        if index >= self.dpiv_data_len() {
12211            return None;
12212        }
12213        // SAFETY: index checked above; the pointer is interior to `self`.
12214        unsafe {
12215            Some(crate::support::Ref::new(PivotDisplacementData {
12216                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_dpivData_at(
12217                    self.raw.as_ptr(),
12218                    index,
12219                )),
12220            }))
12221        }
12222    }
12223
12224    pub fn dpiv_data_mut(
12225        &mut self,
12226        index: usize,
12227    ) -> Option<crate::support::RefMut<'_, PivotDisplacementData>> {
12228        if index >= self.dpiv_data_len() {
12229            return None;
12230        }
12231        // SAFETY: as above; `&mut self` guarantees exclusivity.
12232        unsafe {
12233            Some(crate::support::RefMut::new(PivotDisplacementData {
12234                raw: core::ptr::NonNull::new_unchecked(ffi::whiteout_m2_M2Model_get_dpivData_at(
12235                    self.raw.as_ptr(),
12236                    index,
12237                )),
12238            }))
12239        }
12240    }
12241
12242    /// Iterate the elements, borrowing each in turn.
12243    pub fn dpiv_data_iter(
12244        &self,
12245    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, PivotDisplacementData>> {
12246        (0..self.dpiv_data_len()).map(move |i| self.dpiv_data(i).expect("index below len"))
12247    }
12248
12249    pub fn resize_dpiv_data(&mut self, count: usize) {
12250        // SAFETY: exclusive access, so no borrow is outstanding.
12251        unsafe { ffi::whiteout_m2_M2Model_resize_dpivData(self.raw.as_ptr(), count) }
12252    }
12253
12254    /// TEXL
12255    pub fn textured_light_entries_len(&self) -> usize {
12256        // SAFETY: scalar read through a live handle.
12257        unsafe { ffi::whiteout_m2_M2Model_get_texturedLightEntries_count(self.raw.as_ptr()) }
12258    }
12259
12260    /// Borrows element `index` in place. `None` when out of range.
12261    pub fn textured_light_entries(
12262        &self,
12263        index: usize,
12264    ) -> Option<crate::support::Ref<'_, TexturedLightData>> {
12265        if index >= self.textured_light_entries_len() {
12266            return None;
12267        }
12268        // SAFETY: index checked above; the pointer is interior to `self`.
12269        unsafe {
12270            Some(crate::support::Ref::new(TexturedLightData {
12271                raw: core::ptr::NonNull::new_unchecked(
12272                    ffi::whiteout_m2_M2Model_get_texturedLightEntries_at(self.raw.as_ptr(), index),
12273                ),
12274            }))
12275        }
12276    }
12277
12278    pub fn textured_light_entries_mut(
12279        &mut self,
12280        index: usize,
12281    ) -> Option<crate::support::RefMut<'_, TexturedLightData>> {
12282        if index >= self.textured_light_entries_len() {
12283            return None;
12284        }
12285        // SAFETY: as above; `&mut self` guarantees exclusivity.
12286        unsafe {
12287            Some(crate::support::RefMut::new(TexturedLightData {
12288                raw: core::ptr::NonNull::new_unchecked(
12289                    ffi::whiteout_m2_M2Model_get_texturedLightEntries_at(self.raw.as_ptr(), index),
12290                ),
12291            }))
12292        }
12293    }
12294
12295    /// Iterate the elements, borrowing each in turn.
12296    pub fn textured_light_entries_iter(
12297        &self,
12298    ) -> impl ExactSizeIterator<Item = crate::support::Ref<'_, TexturedLightData>> {
12299        (0..self.textured_light_entries_len())
12300            .map(move |i| self.textured_light_entries(i).expect("index below len"))
12301    }
12302
12303    pub fn resize_textured_light_entries(&mut self, count: usize) {
12304        // SAFETY: exclusive access, so no borrow is outstanding.
12305        unsafe { ffi::whiteout_m2_M2Model_resize_texturedLightEntries(self.raw.as_ptr(), count) }
12306    }
12307}
12308
12309impl Default for Model {
12310    fn default() -> Self {
12311        Self::new()
12312    }
12313}
12314
12315pub struct Parser {
12316    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Parser>,
12317}
12318
12319impl Drop for Parser {
12320    fn drop(&mut self) {
12321        // SAFETY: `raw` came from a native constructor and Drop runs once.
12322        unsafe { ffi::whiteout_m2_M2Parser_delete(self.raw.as_ptr()) }
12323    }
12324}
12325
12326impl Parser {
12327    /// # Safety
12328    /// `raw` must be a live handle this value takes ownership of.
12329    #[allow(dead_code)] // used by whichever methods return this type
12330    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Parser) -> Option<Self> {
12331        core::ptr::NonNull::new(raw).map(|raw| Parser { raw })
12332    }
12333}
12334
12335// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12336// is deliberately NOT implemented — the C++ types make no documented
12337// guarantee about concurrent use, and claiming one we haven't verified
12338// would be unsound. See `@bind thread_safe` in the plan.
12339unsafe impl Send for Parser {}
12340
12341impl core::fmt::Debug for Parser {
12342    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12343        f.debug_struct("Parser").finish_non_exhaustive()
12344    }
12345}
12346
12347impl Parser {
12348    /// # Panics
12349    /// Panics if the native allocation fails.
12350    pub fn new() -> Self {
12351        // SAFETY: the native constructor returns a live handle; a null here
12352        // means the library is unusable.
12353        unsafe {
12354            let raw = ffi::whiteout_m2_M2Parser_new();
12355            Self::from_raw(raw).expect("native Parser allocation failed")
12356        }
12357    }
12358
12359    pub fn parse_file(
12360        &mut self,
12361        fs: Option<&crate::interfaces::HostFileSystem>,
12362        file_path: &str,
12363    ) -> Option<Model> {
12364        let file_path_cstr = std::ffi::CString::new(file_path).unwrap_or_default();
12365        // SAFETY: handle is live for the duration of the call.
12366        unsafe {
12367            Model::from_raw(ffi::whiteout_m2_M2Parser_parse(
12368                self.raw.as_ptr(),
12369                fs.map_or(core::ptr::null_mut(), |v| v.as_ptr()),
12370                file_path_cstr.as_ptr(),
12371            ))
12372        }
12373    }
12374
12375    pub fn parse_casc_fs_buffer(&mut self, casc_fs: &[u8], buffer: &[u8]) -> Option<Model> {
12376        // SAFETY: handle is live for the duration of the call.
12377        unsafe {
12378            Model::from_raw(ffi::whiteout_m2_M2Parser_parse_cascFs_buffer(
12379                self.raw.as_ptr(),
12380                casc_fs.as_ptr(),
12381                casc_fs.len(),
12382                buffer.as_ptr(),
12383                buffer.len(),
12384            ))
12385        }
12386    }
12387
12388    /// Leave the keys of sequences stored in `.anim` siblings unread until m2::loadSequence() asks for them. Off by default.
12389    ///
12390    /// This is what the client does — nothing reads a `.anim` until something plays that sequence — and on a character model with a hundred of them it is the difference between a load that reads one file and one that reads a hundred. See sequence_loader.h.
12391    ///
12392    /// The @p fs passed to parse() has to outlive the returned Model, because the deferred reads go back through it.
12393    pub fn set_lazy_animations(&mut self, enable: bool) {
12394        // SAFETY: handle is live for the duration of the call.
12395        unsafe {
12396            ffi::whiteout_m2_M2Parser_setLazyAnimations(
12397                self.raw.as_ptr(),
12398                if enable { 1 } else { 0 },
12399            );
12400        }
12401    }
12402
12403    pub fn has_issues(&self) -> bool {
12404        // SAFETY: handle is live for the duration of the call.
12405        unsafe { ffi::whiteout_m2_M2Parser_hasIssues(self.raw.as_ptr()) != 0 }
12406    }
12407
12408    pub fn issues(&self) -> Vec<String> {
12409        // SAFETY: index stays below the reported count.
12410        unsafe {
12411            let n = ffi::whiteout_m2_M2Parser_getIssues_count(self.raw.as_ptr());
12412            (0..n)
12413                .map(|i| {
12414                    crate::support::take_string(ffi::whiteout_m2_M2Parser_getIssues_at(
12415                        self.raw.as_ptr(),
12416                        i,
12417                    ))
12418                })
12419                .collect()
12420        }
12421    }
12422}
12423
12424impl Default for Parser {
12425    fn default() -> Self {
12426        Self::new()
12427    }
12428}
12429
12430pub struct WriteOptions {
12431    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2WriteOptions>,
12432}
12433
12434impl Drop for WriteOptions {
12435    fn drop(&mut self) {
12436        // SAFETY: `raw` came from a native constructor and Drop runs once.
12437        unsafe { ffi::whiteout_m2_M2WriteOptions_delete(self.raw.as_ptr()) }
12438    }
12439}
12440
12441impl WriteOptions {
12442    /// # Safety
12443    /// `raw` must be a live handle this value takes ownership of.
12444    #[allow(dead_code)] // used by whichever methods return this type
12445    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2WriteOptions) -> Option<Self> {
12446        core::ptr::NonNull::new(raw).map(|raw| WriteOptions { raw })
12447    }
12448}
12449
12450// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12451// is deliberately NOT implemented — the C++ types make no documented
12452// guarantee about concurrent use, and claiming one we haven't verified
12453// would be unsound. See `@bind thread_safe` in the plan.
12454unsafe impl Send for WriteOptions {}
12455
12456impl core::fmt::Debug for WriteOptions {
12457    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12458        f.debug_struct("WriteOptions").finish_non_exhaustive()
12459    }
12460}
12461
12462impl WriteOptions {
12463    /// # Panics
12464    /// Panics if the native allocation fails.
12465    pub fn new() -> Self {
12466        // SAFETY: the native constructor returns a live handle; a null here
12467        // means the library is unusable.
12468        unsafe {
12469            let raw = ffi::whiteout_m2_M2WriteOptions_new();
12470            Self::from_raw(raw).expect("native WriteOptions allocation failed")
12471        }
12472    }
12473
12474    pub fn m_2_version(&self) -> u32 {
12475        // SAFETY: plain scalar read through a live handle.
12476        unsafe { ffi::whiteout_m2_M2WriteOptions_get_m2Version(self.raw.as_ptr()) }
12477    }
12478
12479    pub fn set_m_2_version(&mut self, value: u32) {
12480        // SAFETY: plain scalar write through a live handle.
12481        unsafe { ffi::whiteout_m2_M2WriteOptions_set_m2Version(self.raw.as_ptr(), value) }
12482    }
12483
12484    pub fn emit_skeleton(&self) -> bool {
12485        // SAFETY: plain scalar read through a live handle.
12486        unsafe { ffi::whiteout_m2_M2WriteOptions_get_emitSkeleton(self.raw.as_ptr()) != 0 }
12487    }
12488
12489    pub fn set_emit_skeleton(&mut self, value: bool) {
12490        // SAFETY: plain scalar write through a live handle.
12491        unsafe {
12492            ffi::whiteout_m2_M2WriteOptions_set_emitSkeleton(
12493                self.raw.as_ptr(),
12494                if value { 1 } else { 0 },
12495            )
12496        }
12497    }
12498
12499    pub fn base_stem(&self) -> String {
12500        // SAFETY: the native side hands over an owned CString.
12501        unsafe {
12502            crate::support::take_string(ffi::whiteout_m2_M2WriteOptions_get_baseStem(
12503                self.raw.as_ptr(),
12504            ))
12505        }
12506    }
12507
12508    pub fn set_base_stem(&mut self, value: &str) {
12509        let value = std::ffi::CString::new(value).unwrap_or_default();
12510        // SAFETY: the pointer outlives the call.
12511        unsafe { ffi::whiteout_m2_M2WriteOptions_set_baseStem(self.raw.as_ptr(), value.as_ptr()) }
12512    }
12513}
12514
12515impl Default for WriteOptions {
12516    fn default() -> Self {
12517        Self::new()
12518    }
12519}
12520
12521pub struct SerializeResult {
12522    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2SerializeResult>,
12523}
12524
12525impl Drop for SerializeResult {
12526    fn drop(&mut self) {
12527        // SAFETY: `raw` came from a native constructor and Drop runs once.
12528        unsafe { ffi::whiteout_m2_M2SerializeResult_delete(self.raw.as_ptr()) }
12529    }
12530}
12531
12532impl SerializeResult {
12533    /// # Safety
12534    /// `raw` must be a live handle this value takes ownership of.
12535    #[allow(dead_code)] // used by whichever methods return this type
12536    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2SerializeResult) -> Option<Self> {
12537        core::ptr::NonNull::new(raw).map(|raw| SerializeResult { raw })
12538    }
12539}
12540
12541// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12542// is deliberately NOT implemented — the C++ types make no documented
12543// guarantee about concurrent use, and claiming one we haven't verified
12544// would be unsound. See `@bind thread_safe` in the plan.
12545unsafe impl Send for SerializeResult {}
12546
12547impl core::fmt::Debug for SerializeResult {
12548    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12549        f.debug_struct("SerializeResult").finish_non_exhaustive()
12550    }
12551}
12552
12553impl SerializeResult {
12554    /// # Panics
12555    /// Panics if the native allocation fails.
12556    pub fn new() -> Self {
12557        // SAFETY: the native constructor returns a live handle; a null here
12558        // means the library is unusable.
12559        unsafe {
12560            let raw = ffi::whiteout_m2_M2SerializeResult_new();
12561            Self::from_raw(raw).expect("native SerializeResult allocation failed")
12562        }
12563    }
12564
12565    /// Zero-copy view of the underlying `std::vector`.
12566    pub fn m_2_data(&self) -> &[u8] {
12567        // SAFETY: `_data`/`_count` describe one contiguous C++
12568        // allocation, borrowed for as long as `self` is.
12569        unsafe {
12570            let n = ffi::whiteout_m2_M2SerializeResult_get_m2Data_count(self.raw.as_ptr());
12571            let p = ffi::whiteout_m2_M2SerializeResult_get_m2Data_data(self.raw.as_ptr());
12572            if p.is_null() || n == 0 {
12573                &[]
12574            } else {
12575                core::slice::from_raw_parts(p, n)
12576            }
12577        }
12578    }
12579
12580    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
12581    pub fn m_2_data_mut(&mut self) -> &mut [u8] {
12582        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
12583        unsafe {
12584            let n = ffi::whiteout_m2_M2SerializeResult_get_m2Data_count(self.raw.as_ptr());
12585            let p =
12586                ffi::whiteout_m2_M2SerializeResult_get_m2Data_data(self.raw.as_ptr()) as *mut u8;
12587            if p.is_null() || n == 0 {
12588                &mut []
12589            } else {
12590                core::slice::from_raw_parts_mut(p, n)
12591            }
12592        }
12593    }
12594
12595    pub fn set_m_2_data(&mut self, values: &[u8]) {
12596        // SAFETY: the native side copies `values` before returning.
12597        unsafe {
12598            ffi::whiteout_m2_M2SerializeResult_assign_m2Data(
12599                self.raw.as_ptr(),
12600                values.as_ptr() as *const _,
12601                values.len(),
12602            )
12603        }
12604    }
12605
12606    pub fn resize_m_2_data(&mut self, count: usize) {
12607        // SAFETY: reallocation is safe here precisely because
12608        // `&mut self` means no slice borrow is outstanding.
12609        unsafe { ffi::whiteout_m2_M2SerializeResult_resize_m2Data(self.raw.as_ptr(), count) }
12610    }
12611}
12612
12613impl Default for SerializeResult {
12614    fn default() -> Self {
12615        Self::new()
12616    }
12617}
12618
12619pub struct Writer {
12620    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2Writer>,
12621}
12622
12623impl Drop for Writer {
12624    fn drop(&mut self) {
12625        // SAFETY: `raw` came from a native constructor and Drop runs once.
12626        unsafe { ffi::whiteout_m2_M2Writer_delete(self.raw.as_ptr()) }
12627    }
12628}
12629
12630impl Writer {
12631    /// # Safety
12632    /// `raw` must be a live handle this value takes ownership of.
12633    #[allow(dead_code)] // used by whichever methods return this type
12634    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2Writer) -> Option<Self> {
12635        core::ptr::NonNull::new(raw).map(|raw| Writer { raw })
12636    }
12637}
12638
12639// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12640// is deliberately NOT implemented — the C++ types make no documented
12641// guarantee about concurrent use, and claiming one we haven't verified
12642// would be unsound. See `@bind thread_safe` in the plan.
12643unsafe impl Send for Writer {}
12644
12645impl core::fmt::Debug for Writer {
12646    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12647        f.debug_struct("Writer").finish_non_exhaustive()
12648    }
12649}
12650
12651impl Writer {
12652    /// # Panics
12653    /// Panics if the native allocation fails.
12654    pub fn new() -> Self {
12655        // SAFETY: the native constructor returns a live handle; a null here
12656        // means the library is unusable.
12657        unsafe {
12658            let raw = ffi::whiteout_m2_M2Writer_new();
12659            Self::from_raw(raw).expect("native Writer allocation failed")
12660        }
12661    }
12662
12663    pub fn write_file(
12664        &mut self,
12665        fs: Option<&crate::interfaces::HostFileSystem>,
12666        file_path: &str,
12667        model: &Model,
12668    ) {
12669        let file_path_cstr = std::ffi::CString::new(file_path).unwrap_or_default();
12670        // SAFETY: handle is live for the duration of the call.
12671        unsafe {
12672            ffi::whiteout_m2_M2Writer_write(
12673                self.raw.as_ptr(),
12674                fs.map_or(core::ptr::null_mut(), |v| v.as_ptr()),
12675                file_path_cstr.as_ptr(),
12676                model.raw.as_ptr(),
12677            );
12678        }
12679    }
12680
12681    pub fn write_casc_fs_model(
12682        &mut self,
12683        casc_fs: Option<&crate::interfaces::HostCascFileSystem>,
12684        model: &Model,
12685    ) {
12686        // SAFETY: handle is live for the duration of the call.
12687        unsafe {
12688            ffi::whiteout_m2_M2Writer_write_cascFs_model(
12689                self.raw.as_ptr(),
12690                casc_fs.map_or(core::ptr::null_mut(), |v| v.as_ptr()),
12691                model.raw.as_ptr(),
12692            );
12693        }
12694    }
12695
12696    pub fn write(&mut self, model: &Model) -> Option<SerializeResult> {
12697        // SAFETY: handle is live for the duration of the call.
12698        unsafe {
12699            SerializeResult::from_raw(ffi::whiteout_m2_M2Writer_write_model(
12700                self.raw.as_ptr(),
12701                model.raw.as_ptr(),
12702            ))
12703        }
12704    }
12705
12706    pub fn has_issues(&self) -> bool {
12707        // SAFETY: handle is live for the duration of the call.
12708        unsafe { ffi::whiteout_m2_M2Writer_hasIssues(self.raw.as_ptr()) != 0 }
12709    }
12710
12711    pub fn issues(&self) -> Vec<String> {
12712        // SAFETY: index stays below the reported count.
12713        unsafe {
12714            let n = ffi::whiteout_m2_M2Writer_getIssues_count(self.raw.as_ptr());
12715            (0..n)
12716                .map(|i| {
12717                    crate::support::take_string(ffi::whiteout_m2_M2Writer_getIssues_at(
12718                        self.raw.as_ptr(),
12719                        i,
12720                    ))
12721                })
12722                .collect()
12723        }
12724    }
12725}
12726
12727impl Default for Writer {
12728    fn default() -> Self {
12729        Self::new()
12730    }
12731}
12732
12733/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
12734pub struct AnimationTrackVector3f {
12735    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackVector3f>,
12736}
12737
12738impl Drop for AnimationTrackVector3f {
12739    fn drop(&mut self) {
12740        // SAFETY: `raw` came from a native constructor and Drop runs once.
12741        unsafe { ffi::whiteout_m2_M2AnimationTrackVector3f_delete(self.raw.as_ptr()) }
12742    }
12743}
12744
12745impl AnimationTrackVector3f {
12746    /// # Safety
12747    /// `raw` must be a live handle this value takes ownership of.
12748    #[allow(dead_code)] // used by whichever methods return this type
12749    pub(crate) unsafe fn from_raw(
12750        raw: *mut ffi::whiteout_M2AnimationTrackVector3f,
12751    ) -> Option<Self> {
12752        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackVector3f { raw })
12753    }
12754}
12755
12756// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
12757// is deliberately NOT implemented — the C++ types make no documented
12758// guarantee about concurrent use, and claiming one we haven't verified
12759// would be unsound. See `@bind thread_safe` in the plan.
12760unsafe impl Send for AnimationTrackVector3f {}
12761
12762impl core::fmt::Debug for AnimationTrackVector3f {
12763    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12764        f.debug_struct("AnimationTrackVector3f")
12765            .finish_non_exhaustive()
12766    }
12767}
12768
12769impl AnimationTrackVector3f {
12770    /// # Panics
12771    /// Panics if the native allocation fails.
12772    pub fn new() -> Self {
12773        // SAFETY: the native constructor returns a live handle; a null here
12774        // means the library is unusable.
12775        unsafe {
12776            let raw = ffi::whiteout_m2_M2AnimationTrackVector3f_new();
12777            Self::from_raw(raw).expect("native AnimationTrackVector3f allocation failed")
12778        }
12779    }
12780
12781    pub fn interpolation_type(&self) -> InterpolationType {
12782        // SAFETY: scalar read; the discriminant is validated below.
12783        unsafe {
12784            ffi::whiteout_m2_M2AnimationTrackVector3f_get_interpolationType(self.raw.as_ptr())
12785        }
12786        .try_into()
12787        .expect("unknown enum discriminant from the native library")
12788    }
12789
12790    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
12791        // SAFETY: scalar write through a live handle.
12792        unsafe {
12793            ffi::whiteout_m2_M2AnimationTrackVector3f_set_interpolationType(
12794                self.raw.as_ptr(),
12795                value as i32,
12796            )
12797        }
12798    }
12799
12800    pub fn global_sequence_id(&self) -> u16 {
12801        // SAFETY: plain scalar read through a live handle.
12802        unsafe { ffi::whiteout_m2_M2AnimationTrackVector3f_get_globalSequenceId(self.raw.as_ptr()) }
12803    }
12804
12805    pub fn set_global_sequence_id(&mut self, value: u16) {
12806        // SAFETY: plain scalar write through a live handle.
12807        unsafe {
12808            ffi::whiteout_m2_M2AnimationTrackVector3f_set_globalSequenceId(self.raw.as_ptr(), value)
12809        }
12810    }
12811
12812    /// Number of inner sequences.
12813    pub fn timestamps_len(&self) -> usize {
12814        // SAFETY: scalar read through a live handle.
12815        unsafe { ffi::whiteout_m2_M2AnimationTrackVector3f_get_timestamps_count(self.raw.as_ptr()) }
12816    }
12817
12818    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
12819    ///
12820    /// Each inner vector is contiguous on its own, but the outer one
12821    /// is a vector of vectors — so this borrows per sequence rather
12822    /// than handing back one flat slice.
12823    pub fn timestamps(&self, outer: usize) -> &[u32] {
12824        if outer >= self.timestamps_len() {
12825            return &[];
12826        }
12827        // SAFETY: index checked; the pointer borrows `self`.
12828        unsafe {
12829            let n = ffi::whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_count(
12830                self.raw.as_ptr(),
12831                outer,
12832            );
12833            let p = ffi::whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_data(
12834                self.raw.as_ptr(),
12835                outer,
12836            );
12837            if p.is_null() || n == 0 {
12838                &[]
12839            } else {
12840                core::slice::from_raw_parts(p, n)
12841            }
12842        }
12843    }
12844
12845    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
12846        if outer >= self.timestamps_len() {
12847            return &mut [];
12848        }
12849        // SAFETY: as above; `&mut self` rules out aliasing.
12850        unsafe {
12851            let n = ffi::whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_count(
12852                self.raw.as_ptr(),
12853                outer,
12854            );
12855            let p = ffi::whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_data(
12856                self.raw.as_ptr(),
12857                outer,
12858            ) as *mut u32;
12859            if p.is_null() || n == 0 {
12860                &mut []
12861            } else {
12862                core::slice::from_raw_parts_mut(p, n)
12863            }
12864        }
12865    }
12866
12867    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
12868        // SAFETY: the native side copies `values` before returning.
12869        unsafe {
12870            ffi::whiteout_m2_M2AnimationTrackVector3f_assign_timestamps_inner(
12871                self.raw.as_ptr(),
12872                outer,
12873                values.as_ptr() as *const _,
12874                values.len(),
12875            )
12876        }
12877    }
12878
12879    /// Resize the outer sequence. Do this before taking any borrow.
12880    pub fn resize_timestamps(&mut self, count: usize) {
12881        // SAFETY: exclusive access, so no borrow is outstanding.
12882        unsafe {
12883            ffi::whiteout_m2_M2AnimationTrackVector3f_resize_timestamps(self.raw.as_ptr(), count)
12884        }
12885    }
12886
12887    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
12888        // SAFETY: as above.
12889        unsafe {
12890            ffi::whiteout_m2_M2AnimationTrackVector3f_resize_timestamps_inner(
12891                self.raw.as_ptr(),
12892                outer,
12893                count,
12894            )
12895        }
12896    }
12897
12898    /// Number of inner sequences.
12899    pub fn values_len(&self) -> usize {
12900        // SAFETY: scalar read through a live handle.
12901        unsafe { ffi::whiteout_m2_M2AnimationTrackVector3f_get_values_count(self.raw.as_ptr()) }
12902    }
12903
12904    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
12905    ///
12906    /// Each inner vector is contiguous on its own, but the outer one
12907    /// is a vector of vectors — so this borrows per sequence rather
12908    /// than handing back one flat slice.
12909    pub fn values(&self, outer: usize) -> &[crate::math::Vector3f] {
12910        if outer >= self.values_len() {
12911            return &[];
12912        }
12913        // SAFETY: index checked; the pointer borrows `self`.
12914        unsafe {
12915            let n = ffi::whiteout_m2_M2AnimationTrackVector3f_get_values_inner_count(
12916                self.raw.as_ptr(),
12917                outer,
12918            );
12919            let p = ffi::whiteout_m2_M2AnimationTrackVector3f_get_values_inner_data(
12920                self.raw.as_ptr(),
12921                outer,
12922            ) as *const crate::math::Vector3f;
12923            if p.is_null() || n == 0 {
12924                &[]
12925            } else {
12926                core::slice::from_raw_parts(p, n)
12927            }
12928        }
12929    }
12930
12931    pub fn values_mut(&mut self, outer: usize) -> &mut [crate::math::Vector3f] {
12932        if outer >= self.values_len() {
12933            return &mut [];
12934        }
12935        // SAFETY: as above; `&mut self` rules out aliasing.
12936        unsafe {
12937            let n = ffi::whiteout_m2_M2AnimationTrackVector3f_get_values_inner_count(
12938                self.raw.as_ptr(),
12939                outer,
12940            );
12941            let p = ffi::whiteout_m2_M2AnimationTrackVector3f_get_values_inner_data(
12942                self.raw.as_ptr(),
12943                outer,
12944            ) as *const crate::math::Vector3f as *mut crate::math::Vector3f;
12945            if p.is_null() || n == 0 {
12946                &mut []
12947            } else {
12948                core::slice::from_raw_parts_mut(p, n)
12949            }
12950        }
12951    }
12952
12953    pub fn set_values(&mut self, outer: usize, values: &[crate::math::Vector3f]) {
12954        // SAFETY: the native side copies `values` before returning.
12955        unsafe {
12956            ffi::whiteout_m2_M2AnimationTrackVector3f_assign_values_inner(
12957                self.raw.as_ptr(),
12958                outer,
12959                values.as_ptr() as *const _,
12960                values.len(),
12961            )
12962        }
12963    }
12964
12965    /// Resize the outer sequence. Do this before taking any borrow.
12966    pub fn resize_values(&mut self, count: usize) {
12967        // SAFETY: exclusive access, so no borrow is outstanding.
12968        unsafe { ffi::whiteout_m2_M2AnimationTrackVector3f_resize_values(self.raw.as_ptr(), count) }
12969    }
12970
12971    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
12972        // SAFETY: as above.
12973        unsafe {
12974            ffi::whiteout_m2_M2AnimationTrackVector3f_resize_values_inner(
12975                self.raw.as_ptr(),
12976                outer,
12977                count,
12978            )
12979        }
12980    }
12981}
12982
12983impl Default for AnimationTrackVector3f {
12984    fn default() -> Self {
12985        Self::new()
12986    }
12987}
12988
12989/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
12990pub struct AnimationTrackM2CompatQuaternion {
12991    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackM2CompatQuaternion>,
12992}
12993
12994impl Drop for AnimationTrackM2CompatQuaternion {
12995    fn drop(&mut self) {
12996        // SAFETY: `raw` came from a native constructor and Drop runs once.
12997        unsafe { ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_delete(self.raw.as_ptr()) }
12998    }
12999}
13000
13001impl AnimationTrackM2CompatQuaternion {
13002    /// # Safety
13003    /// `raw` must be a live handle this value takes ownership of.
13004    #[allow(dead_code)] // used by whichever methods return this type
13005    pub(crate) unsafe fn from_raw(
13006        raw: *mut ffi::whiteout_M2AnimationTrackM2CompatQuaternion,
13007    ) -> Option<Self> {
13008        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackM2CompatQuaternion { raw })
13009    }
13010}
13011
13012// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13013// is deliberately NOT implemented — the C++ types make no documented
13014// guarantee about concurrent use, and claiming one we haven't verified
13015// would be unsound. See `@bind thread_safe` in the plan.
13016unsafe impl Send for AnimationTrackM2CompatQuaternion {}
13017
13018impl core::fmt::Debug for AnimationTrackM2CompatQuaternion {
13019    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13020        f.debug_struct("AnimationTrackM2CompatQuaternion")
13021            .finish_non_exhaustive()
13022    }
13023}
13024
13025impl AnimationTrackM2CompatQuaternion {
13026    /// # Panics
13027    /// Panics if the native allocation fails.
13028    pub fn new() -> Self {
13029        // SAFETY: the native constructor returns a live handle; a null here
13030        // means the library is unusable.
13031        unsafe {
13032            let raw = ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_new();
13033            Self::from_raw(raw).expect("native AnimationTrackM2CompatQuaternion allocation failed")
13034        }
13035    }
13036
13037    pub fn interpolation_type(&self) -> InterpolationType {
13038        // SAFETY: scalar read; the discriminant is validated below.
13039        unsafe {
13040            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_interpolationType(
13041                self.raw.as_ptr(),
13042            )
13043        }
13044        .try_into()
13045        .expect("unknown enum discriminant from the native library")
13046    }
13047
13048    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
13049        // SAFETY: scalar write through a live handle.
13050        unsafe {
13051            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_set_interpolationType(
13052                self.raw.as_ptr(),
13053                value as i32,
13054            )
13055        }
13056    }
13057
13058    pub fn global_sequence_id(&self) -> u16 {
13059        // SAFETY: plain scalar read through a live handle.
13060        unsafe {
13061            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_globalSequenceId(
13062                self.raw.as_ptr(),
13063            )
13064        }
13065    }
13066
13067    pub fn set_global_sequence_id(&mut self, value: u16) {
13068        // SAFETY: plain scalar write through a live handle.
13069        unsafe {
13070            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_set_globalSequenceId(
13071                self.raw.as_ptr(),
13072                value,
13073            )
13074        }
13075    }
13076
13077    /// Number of inner sequences.
13078    pub fn timestamps_len(&self) -> usize {
13079        // SAFETY: scalar read through a live handle.
13080        unsafe {
13081            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_count(
13082                self.raw.as_ptr(),
13083            )
13084        }
13085    }
13086
13087    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13088    ///
13089    /// Each inner vector is contiguous on its own, but the outer one
13090    /// is a vector of vectors — so this borrows per sequence rather
13091    /// than handing back one flat slice.
13092    pub fn timestamps(&self, outer: usize) -> &[u32] {
13093        if outer >= self.timestamps_len() {
13094            return &[];
13095        }
13096        // SAFETY: index checked; the pointer borrows `self`.
13097        unsafe {
13098            let n = ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_count(
13099                self.raw.as_ptr(),
13100                outer,
13101            );
13102            let p = ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_data(
13103                self.raw.as_ptr(),
13104                outer,
13105            );
13106            if p.is_null() || n == 0 {
13107                &[]
13108            } else {
13109                core::slice::from_raw_parts(p, n)
13110            }
13111        }
13112    }
13113
13114    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
13115        if outer >= self.timestamps_len() {
13116            return &mut [];
13117        }
13118        // SAFETY: as above; `&mut self` rules out aliasing.
13119        unsafe {
13120            let n = ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_count(
13121                self.raw.as_ptr(),
13122                outer,
13123            );
13124            let p = ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_data(
13125                self.raw.as_ptr(),
13126                outer,
13127            ) as *mut u32;
13128            if p.is_null() || n == 0 {
13129                &mut []
13130            } else {
13131                core::slice::from_raw_parts_mut(p, n)
13132            }
13133        }
13134    }
13135
13136    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
13137        // SAFETY: the native side copies `values` before returning.
13138        unsafe {
13139            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_assign_timestamps_inner(
13140                self.raw.as_ptr(),
13141                outer,
13142                values.as_ptr() as *const _,
13143                values.len(),
13144            )
13145        }
13146    }
13147
13148    /// Resize the outer sequence. Do this before taking any borrow.
13149    pub fn resize_timestamps(&mut self, count: usize) {
13150        // SAFETY: exclusive access, so no borrow is outstanding.
13151        unsafe {
13152            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_timestamps(
13153                self.raw.as_ptr(),
13154                count,
13155            )
13156        }
13157    }
13158
13159    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
13160        // SAFETY: as above.
13161        unsafe {
13162            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_timestamps_inner(
13163                self.raw.as_ptr(),
13164                outer,
13165                count,
13166            )
13167        }
13168    }
13169
13170    /// Number of inner sequences.
13171    pub fn values_len(&self) -> usize {
13172        // SAFETY: scalar read through a live handle.
13173        unsafe {
13174            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_count(self.raw.as_ptr())
13175        }
13176    }
13177
13178    /// Length of inner sequence `outer`.
13179    pub fn values_inner_len(&self, outer: usize) -> usize {
13180        if outer >= self.values_len() {
13181            return 0;
13182        }
13183        // SAFETY: index checked above.
13184        unsafe {
13185            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_inner_count(
13186                self.raw.as_ptr(),
13187                outer,
13188            )
13189        }
13190    }
13191
13192    /// Borrow element `inner` of sequence `outer` in place.
13193    pub fn values(
13194        &self,
13195        outer: usize,
13196        inner: usize,
13197    ) -> Option<crate::support::Ref<'_, CompatQuaternion>> {
13198        if inner >= self.values_inner_len(outer) {
13199            return None;
13200        }
13201        // SAFETY: both indices checked; the pointer is
13202        // interior to `self`.
13203        unsafe {
13204            Some(crate::support::Ref::new(CompatQuaternion {
13205                raw: core::ptr::NonNull::new_unchecked(
13206                    ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_at(
13207                        self.raw.as_ptr(),
13208                        outer,
13209                        inner,
13210                    ),
13211                ),
13212            }))
13213        }
13214    }
13215
13216    pub fn values_mut(
13217        &mut self,
13218        outer: usize,
13219        inner: usize,
13220    ) -> Option<crate::support::RefMut<'_, CompatQuaternion>> {
13221        if inner >= self.values_inner_len(outer) {
13222            return None;
13223        }
13224        // SAFETY: as above; `&mut self` guarantees exclusivity.
13225        unsafe {
13226            Some(crate::support::RefMut::new(CompatQuaternion {
13227                raw: core::ptr::NonNull::new_unchecked(
13228                    ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_at(
13229                        self.raw.as_ptr(),
13230                        outer,
13231                        inner,
13232                    ),
13233                ),
13234            }))
13235        }
13236    }
13237
13238    /// Resize the outer sequence. Do this before taking a borrow.
13239    pub fn resize_values(&mut self, count: usize) {
13240        // SAFETY: exclusive access, so no borrow is outstanding.
13241        unsafe {
13242            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_values(
13243                self.raw.as_ptr(),
13244                count,
13245            )
13246        }
13247    }
13248
13249    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
13250        // SAFETY: as above.
13251        unsafe {
13252            ffi::whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_values_inner(
13253                self.raw.as_ptr(),
13254                outer,
13255                count,
13256            )
13257        }
13258    }
13259}
13260
13261impl Default for AnimationTrackM2CompatQuaternion {
13262    fn default() -> Self {
13263        Self::new()
13264    }
13265}
13266
13267/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
13268pub struct AnimationTrackI16 {
13269    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackI16>,
13270}
13271
13272impl Drop for AnimationTrackI16 {
13273    fn drop(&mut self) {
13274        // SAFETY: `raw` came from a native constructor and Drop runs once.
13275        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_delete(self.raw.as_ptr()) }
13276    }
13277}
13278
13279impl AnimationTrackI16 {
13280    /// # Safety
13281    /// `raw` must be a live handle this value takes ownership of.
13282    #[allow(dead_code)] // used by whichever methods return this type
13283    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2AnimationTrackI16) -> Option<Self> {
13284        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackI16 { raw })
13285    }
13286}
13287
13288// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13289// is deliberately NOT implemented — the C++ types make no documented
13290// guarantee about concurrent use, and claiming one we haven't verified
13291// would be unsound. See `@bind thread_safe` in the plan.
13292unsafe impl Send for AnimationTrackI16 {}
13293
13294impl core::fmt::Debug for AnimationTrackI16 {
13295    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13296        f.debug_struct("AnimationTrackI16").finish_non_exhaustive()
13297    }
13298}
13299
13300impl AnimationTrackI16 {
13301    /// # Panics
13302    /// Panics if the native allocation fails.
13303    pub fn new() -> Self {
13304        // SAFETY: the native constructor returns a live handle; a null here
13305        // means the library is unusable.
13306        unsafe {
13307            let raw = ffi::whiteout_m2_M2AnimationTrackI16_new();
13308            Self::from_raw(raw).expect("native AnimationTrackI16 allocation failed")
13309        }
13310    }
13311
13312    pub fn interpolation_type(&self) -> InterpolationType {
13313        // SAFETY: scalar read; the discriminant is validated below.
13314        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_get_interpolationType(self.raw.as_ptr()) }
13315            .try_into()
13316            .expect("unknown enum discriminant from the native library")
13317    }
13318
13319    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
13320        // SAFETY: scalar write through a live handle.
13321        unsafe {
13322            ffi::whiteout_m2_M2AnimationTrackI16_set_interpolationType(
13323                self.raw.as_ptr(),
13324                value as i32,
13325            )
13326        }
13327    }
13328
13329    pub fn global_sequence_id(&self) -> u16 {
13330        // SAFETY: plain scalar read through a live handle.
13331        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_get_globalSequenceId(self.raw.as_ptr()) }
13332    }
13333
13334    pub fn set_global_sequence_id(&mut self, value: u16) {
13335        // SAFETY: plain scalar write through a live handle.
13336        unsafe {
13337            ffi::whiteout_m2_M2AnimationTrackI16_set_globalSequenceId(self.raw.as_ptr(), value)
13338        }
13339    }
13340
13341    /// Number of inner sequences.
13342    pub fn timestamps_len(&self) -> usize {
13343        // SAFETY: scalar read through a live handle.
13344        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_get_timestamps_count(self.raw.as_ptr()) }
13345    }
13346
13347    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13348    ///
13349    /// Each inner vector is contiguous on its own, but the outer one
13350    /// is a vector of vectors — so this borrows per sequence rather
13351    /// than handing back one flat slice.
13352    pub fn timestamps(&self, outer: usize) -> &[u32] {
13353        if outer >= self.timestamps_len() {
13354            return &[];
13355        }
13356        // SAFETY: index checked; the pointer borrows `self`.
13357        unsafe {
13358            let n = ffi::whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_count(
13359                self.raw.as_ptr(),
13360                outer,
13361            );
13362            let p = ffi::whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_data(
13363                self.raw.as_ptr(),
13364                outer,
13365            );
13366            if p.is_null() || n == 0 {
13367                &[]
13368            } else {
13369                core::slice::from_raw_parts(p, n)
13370            }
13371        }
13372    }
13373
13374    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
13375        if outer >= self.timestamps_len() {
13376            return &mut [];
13377        }
13378        // SAFETY: as above; `&mut self` rules out aliasing.
13379        unsafe {
13380            let n = ffi::whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_count(
13381                self.raw.as_ptr(),
13382                outer,
13383            );
13384            let p = ffi::whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_data(
13385                self.raw.as_ptr(),
13386                outer,
13387            ) as *mut u32;
13388            if p.is_null() || n == 0 {
13389                &mut []
13390            } else {
13391                core::slice::from_raw_parts_mut(p, n)
13392            }
13393        }
13394    }
13395
13396    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
13397        // SAFETY: the native side copies `values` before returning.
13398        unsafe {
13399            ffi::whiteout_m2_M2AnimationTrackI16_assign_timestamps_inner(
13400                self.raw.as_ptr(),
13401                outer,
13402                values.as_ptr() as *const _,
13403                values.len(),
13404            )
13405        }
13406    }
13407
13408    /// Resize the outer sequence. Do this before taking any borrow.
13409    pub fn resize_timestamps(&mut self, count: usize) {
13410        // SAFETY: exclusive access, so no borrow is outstanding.
13411        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_resize_timestamps(self.raw.as_ptr(), count) }
13412    }
13413
13414    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
13415        // SAFETY: as above.
13416        unsafe {
13417            ffi::whiteout_m2_M2AnimationTrackI16_resize_timestamps_inner(
13418                self.raw.as_ptr(),
13419                outer,
13420                count,
13421            )
13422        }
13423    }
13424
13425    /// Number of inner sequences.
13426    pub fn values_len(&self) -> usize {
13427        // SAFETY: scalar read through a live handle.
13428        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_get_values_count(self.raw.as_ptr()) }
13429    }
13430
13431    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13432    ///
13433    /// Each inner vector is contiguous on its own, but the outer one
13434    /// is a vector of vectors — so this borrows per sequence rather
13435    /// than handing back one flat slice.
13436    pub fn values(&self, outer: usize) -> &[i16] {
13437        if outer >= self.values_len() {
13438            return &[];
13439        }
13440        // SAFETY: index checked; the pointer borrows `self`.
13441        unsafe {
13442            let n = ffi::whiteout_m2_M2AnimationTrackI16_get_values_inner_count(
13443                self.raw.as_ptr(),
13444                outer,
13445            );
13446            let p = ffi::whiteout_m2_M2AnimationTrackI16_get_values_inner_data(
13447                self.raw.as_ptr(),
13448                outer,
13449            );
13450            if p.is_null() || n == 0 {
13451                &[]
13452            } else {
13453                core::slice::from_raw_parts(p, n)
13454            }
13455        }
13456    }
13457
13458    pub fn values_mut(&mut self, outer: usize) -> &mut [i16] {
13459        if outer >= self.values_len() {
13460            return &mut [];
13461        }
13462        // SAFETY: as above; `&mut self` rules out aliasing.
13463        unsafe {
13464            let n = ffi::whiteout_m2_M2AnimationTrackI16_get_values_inner_count(
13465                self.raw.as_ptr(),
13466                outer,
13467            );
13468            let p = ffi::whiteout_m2_M2AnimationTrackI16_get_values_inner_data(
13469                self.raw.as_ptr(),
13470                outer,
13471            ) as *mut i16;
13472            if p.is_null() || n == 0 {
13473                &mut []
13474            } else {
13475                core::slice::from_raw_parts_mut(p, n)
13476            }
13477        }
13478    }
13479
13480    pub fn set_values(&mut self, outer: usize, values: &[i16]) {
13481        // SAFETY: the native side copies `values` before returning.
13482        unsafe {
13483            ffi::whiteout_m2_M2AnimationTrackI16_assign_values_inner(
13484                self.raw.as_ptr(),
13485                outer,
13486                values.as_ptr() as *const _,
13487                values.len(),
13488            )
13489        }
13490    }
13491
13492    /// Resize the outer sequence. Do this before taking any borrow.
13493    pub fn resize_values(&mut self, count: usize) {
13494        // SAFETY: exclusive access, so no borrow is outstanding.
13495        unsafe { ffi::whiteout_m2_M2AnimationTrackI16_resize_values(self.raw.as_ptr(), count) }
13496    }
13497
13498    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
13499        // SAFETY: as above.
13500        unsafe {
13501            ffi::whiteout_m2_M2AnimationTrackI16_resize_values_inner(
13502                self.raw.as_ptr(),
13503                outer,
13504                count,
13505            )
13506        }
13507    }
13508}
13509
13510impl Default for AnimationTrackI16 {
13511    fn default() -> Self {
13512        Self::new()
13513    }
13514}
13515
13516/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
13517pub struct AnimationTrackQuaternion {
13518    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackQuaternion>,
13519}
13520
13521impl Drop for AnimationTrackQuaternion {
13522    fn drop(&mut self) {
13523        // SAFETY: `raw` came from a native constructor and Drop runs once.
13524        unsafe { ffi::whiteout_m2_M2AnimationTrackQuaternion_delete(self.raw.as_ptr()) }
13525    }
13526}
13527
13528impl AnimationTrackQuaternion {
13529    /// # Safety
13530    /// `raw` must be a live handle this value takes ownership of.
13531    #[allow(dead_code)] // used by whichever methods return this type
13532    pub(crate) unsafe fn from_raw(
13533        raw: *mut ffi::whiteout_M2AnimationTrackQuaternion,
13534    ) -> Option<Self> {
13535        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackQuaternion { raw })
13536    }
13537}
13538
13539// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13540// is deliberately NOT implemented — the C++ types make no documented
13541// guarantee about concurrent use, and claiming one we haven't verified
13542// would be unsound. See `@bind thread_safe` in the plan.
13543unsafe impl Send for AnimationTrackQuaternion {}
13544
13545impl core::fmt::Debug for AnimationTrackQuaternion {
13546    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13547        f.debug_struct("AnimationTrackQuaternion")
13548            .finish_non_exhaustive()
13549    }
13550}
13551
13552impl AnimationTrackQuaternion {
13553    /// # Panics
13554    /// Panics if the native allocation fails.
13555    pub fn new() -> Self {
13556        // SAFETY: the native constructor returns a live handle; a null here
13557        // means the library is unusable.
13558        unsafe {
13559            let raw = ffi::whiteout_m2_M2AnimationTrackQuaternion_new();
13560            Self::from_raw(raw).expect("native AnimationTrackQuaternion allocation failed")
13561        }
13562    }
13563
13564    pub fn interpolation_type(&self) -> InterpolationType {
13565        // SAFETY: scalar read; the discriminant is validated below.
13566        unsafe {
13567            ffi::whiteout_m2_M2AnimationTrackQuaternion_get_interpolationType(self.raw.as_ptr())
13568        }
13569        .try_into()
13570        .expect("unknown enum discriminant from the native library")
13571    }
13572
13573    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
13574        // SAFETY: scalar write through a live handle.
13575        unsafe {
13576            ffi::whiteout_m2_M2AnimationTrackQuaternion_set_interpolationType(
13577                self.raw.as_ptr(),
13578                value as i32,
13579            )
13580        }
13581    }
13582
13583    pub fn global_sequence_id(&self) -> u16 {
13584        // SAFETY: plain scalar read through a live handle.
13585        unsafe {
13586            ffi::whiteout_m2_M2AnimationTrackQuaternion_get_globalSequenceId(self.raw.as_ptr())
13587        }
13588    }
13589
13590    pub fn set_global_sequence_id(&mut self, value: u16) {
13591        // SAFETY: plain scalar write through a live handle.
13592        unsafe {
13593            ffi::whiteout_m2_M2AnimationTrackQuaternion_set_globalSequenceId(
13594                self.raw.as_ptr(),
13595                value,
13596            )
13597        }
13598    }
13599
13600    /// Number of inner sequences.
13601    pub fn timestamps_len(&self) -> usize {
13602        // SAFETY: scalar read through a live handle.
13603        unsafe {
13604            ffi::whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_count(self.raw.as_ptr())
13605        }
13606    }
13607
13608    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13609    ///
13610    /// Each inner vector is contiguous on its own, but the outer one
13611    /// is a vector of vectors — so this borrows per sequence rather
13612    /// than handing back one flat slice.
13613    pub fn timestamps(&self, outer: usize) -> &[u32] {
13614        if outer >= self.timestamps_len() {
13615            return &[];
13616        }
13617        // SAFETY: index checked; the pointer borrows `self`.
13618        unsafe {
13619            let n = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_count(
13620                self.raw.as_ptr(),
13621                outer,
13622            );
13623            let p = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_data(
13624                self.raw.as_ptr(),
13625                outer,
13626            );
13627            if p.is_null() || n == 0 {
13628                &[]
13629            } else {
13630                core::slice::from_raw_parts(p, n)
13631            }
13632        }
13633    }
13634
13635    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
13636        if outer >= self.timestamps_len() {
13637            return &mut [];
13638        }
13639        // SAFETY: as above; `&mut self` rules out aliasing.
13640        unsafe {
13641            let n = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_count(
13642                self.raw.as_ptr(),
13643                outer,
13644            );
13645            let p = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_data(
13646                self.raw.as_ptr(),
13647                outer,
13648            ) as *mut u32;
13649            if p.is_null() || n == 0 {
13650                &mut []
13651            } else {
13652                core::slice::from_raw_parts_mut(p, n)
13653            }
13654        }
13655    }
13656
13657    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
13658        // SAFETY: the native side copies `values` before returning.
13659        unsafe {
13660            ffi::whiteout_m2_M2AnimationTrackQuaternion_assign_timestamps_inner(
13661                self.raw.as_ptr(),
13662                outer,
13663                values.as_ptr() as *const _,
13664                values.len(),
13665            )
13666        }
13667    }
13668
13669    /// Resize the outer sequence. Do this before taking any borrow.
13670    pub fn resize_timestamps(&mut self, count: usize) {
13671        // SAFETY: exclusive access, so no borrow is outstanding.
13672        unsafe {
13673            ffi::whiteout_m2_M2AnimationTrackQuaternion_resize_timestamps(self.raw.as_ptr(), count)
13674        }
13675    }
13676
13677    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
13678        // SAFETY: as above.
13679        unsafe {
13680            ffi::whiteout_m2_M2AnimationTrackQuaternion_resize_timestamps_inner(
13681                self.raw.as_ptr(),
13682                outer,
13683                count,
13684            )
13685        }
13686    }
13687
13688    /// Number of inner sequences.
13689    pub fn values_len(&self) -> usize {
13690        // SAFETY: scalar read through a live handle.
13691        unsafe { ffi::whiteout_m2_M2AnimationTrackQuaternion_get_values_count(self.raw.as_ptr()) }
13692    }
13693
13694    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13695    ///
13696    /// Each inner vector is contiguous on its own, but the outer one
13697    /// is a vector of vectors — so this borrows per sequence rather
13698    /// than handing back one flat slice.
13699    pub fn values(&self, outer: usize) -> &[crate::math::Quaternion] {
13700        if outer >= self.values_len() {
13701            return &[];
13702        }
13703        // SAFETY: index checked; the pointer borrows `self`.
13704        unsafe {
13705            let n = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_count(
13706                self.raw.as_ptr(),
13707                outer,
13708            );
13709            let p = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_data(
13710                self.raw.as_ptr(),
13711                outer,
13712            ) as *const crate::math::Quaternion;
13713            if p.is_null() || n == 0 {
13714                &[]
13715            } else {
13716                core::slice::from_raw_parts(p, n)
13717            }
13718        }
13719    }
13720
13721    pub fn values_mut(&mut self, outer: usize) -> &mut [crate::math::Quaternion] {
13722        if outer >= self.values_len() {
13723            return &mut [];
13724        }
13725        // SAFETY: as above; `&mut self` rules out aliasing.
13726        unsafe {
13727            let n = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_count(
13728                self.raw.as_ptr(),
13729                outer,
13730            );
13731            let p = ffi::whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_data(
13732                self.raw.as_ptr(),
13733                outer,
13734            ) as *const crate::math::Quaternion as *mut crate::math::Quaternion;
13735            if p.is_null() || n == 0 {
13736                &mut []
13737            } else {
13738                core::slice::from_raw_parts_mut(p, n)
13739            }
13740        }
13741    }
13742
13743    pub fn set_values(&mut self, outer: usize, values: &[crate::math::Quaternion]) {
13744        // SAFETY: the native side copies `values` before returning.
13745        unsafe {
13746            ffi::whiteout_m2_M2AnimationTrackQuaternion_assign_values_inner(
13747                self.raw.as_ptr(),
13748                outer,
13749                values.as_ptr() as *const _,
13750                values.len(),
13751            )
13752        }
13753    }
13754
13755    /// Resize the outer sequence. Do this before taking any borrow.
13756    pub fn resize_values(&mut self, count: usize) {
13757        // SAFETY: exclusive access, so no borrow is outstanding.
13758        unsafe {
13759            ffi::whiteout_m2_M2AnimationTrackQuaternion_resize_values(self.raw.as_ptr(), count)
13760        }
13761    }
13762
13763    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
13764        // SAFETY: as above.
13765        unsafe {
13766            ffi::whiteout_m2_M2AnimationTrackQuaternion_resize_values_inner(
13767                self.raw.as_ptr(),
13768                outer,
13769                count,
13770            )
13771        }
13772    }
13773}
13774
13775impl Default for AnimationTrackQuaternion {
13776    fn default() -> Self {
13777        Self::new()
13778    }
13779}
13780
13781/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
13782pub struct AnimationTrackF32 {
13783    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackF32>,
13784}
13785
13786impl Drop for AnimationTrackF32 {
13787    fn drop(&mut self) {
13788        // SAFETY: `raw` came from a native constructor and Drop runs once.
13789        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_delete(self.raw.as_ptr()) }
13790    }
13791}
13792
13793impl AnimationTrackF32 {
13794    /// # Safety
13795    /// `raw` must be a live handle this value takes ownership of.
13796    #[allow(dead_code)] // used by whichever methods return this type
13797    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2AnimationTrackF32) -> Option<Self> {
13798        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackF32 { raw })
13799    }
13800}
13801
13802// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
13803// is deliberately NOT implemented — the C++ types make no documented
13804// guarantee about concurrent use, and claiming one we haven't verified
13805// would be unsound. See `@bind thread_safe` in the plan.
13806unsafe impl Send for AnimationTrackF32 {}
13807
13808impl core::fmt::Debug for AnimationTrackF32 {
13809    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13810        f.debug_struct("AnimationTrackF32").finish_non_exhaustive()
13811    }
13812}
13813
13814impl AnimationTrackF32 {
13815    /// # Panics
13816    /// Panics if the native allocation fails.
13817    pub fn new() -> Self {
13818        // SAFETY: the native constructor returns a live handle; a null here
13819        // means the library is unusable.
13820        unsafe {
13821            let raw = ffi::whiteout_m2_M2AnimationTrackF32_new();
13822            Self::from_raw(raw).expect("native AnimationTrackF32 allocation failed")
13823        }
13824    }
13825
13826    pub fn interpolation_type(&self) -> InterpolationType {
13827        // SAFETY: scalar read; the discriminant is validated below.
13828        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_get_interpolationType(self.raw.as_ptr()) }
13829            .try_into()
13830            .expect("unknown enum discriminant from the native library")
13831    }
13832
13833    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
13834        // SAFETY: scalar write through a live handle.
13835        unsafe {
13836            ffi::whiteout_m2_M2AnimationTrackF32_set_interpolationType(
13837                self.raw.as_ptr(),
13838                value as i32,
13839            )
13840        }
13841    }
13842
13843    pub fn global_sequence_id(&self) -> u16 {
13844        // SAFETY: plain scalar read through a live handle.
13845        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_get_globalSequenceId(self.raw.as_ptr()) }
13846    }
13847
13848    pub fn set_global_sequence_id(&mut self, value: u16) {
13849        // SAFETY: plain scalar write through a live handle.
13850        unsafe {
13851            ffi::whiteout_m2_M2AnimationTrackF32_set_globalSequenceId(self.raw.as_ptr(), value)
13852        }
13853    }
13854
13855    /// Number of inner sequences.
13856    pub fn timestamps_len(&self) -> usize {
13857        // SAFETY: scalar read through a live handle.
13858        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_get_timestamps_count(self.raw.as_ptr()) }
13859    }
13860
13861    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13862    ///
13863    /// Each inner vector is contiguous on its own, but the outer one
13864    /// is a vector of vectors — so this borrows per sequence rather
13865    /// than handing back one flat slice.
13866    pub fn timestamps(&self, outer: usize) -> &[u32] {
13867        if outer >= self.timestamps_len() {
13868            return &[];
13869        }
13870        // SAFETY: index checked; the pointer borrows `self`.
13871        unsafe {
13872            let n = ffi::whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_count(
13873                self.raw.as_ptr(),
13874                outer,
13875            );
13876            let p = ffi::whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_data(
13877                self.raw.as_ptr(),
13878                outer,
13879            );
13880            if p.is_null() || n == 0 {
13881                &[]
13882            } else {
13883                core::slice::from_raw_parts(p, n)
13884            }
13885        }
13886    }
13887
13888    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
13889        if outer >= self.timestamps_len() {
13890            return &mut [];
13891        }
13892        // SAFETY: as above; `&mut self` rules out aliasing.
13893        unsafe {
13894            let n = ffi::whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_count(
13895                self.raw.as_ptr(),
13896                outer,
13897            );
13898            let p = ffi::whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_data(
13899                self.raw.as_ptr(),
13900                outer,
13901            ) as *mut u32;
13902            if p.is_null() || n == 0 {
13903                &mut []
13904            } else {
13905                core::slice::from_raw_parts_mut(p, n)
13906            }
13907        }
13908    }
13909
13910    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
13911        // SAFETY: the native side copies `values` before returning.
13912        unsafe {
13913            ffi::whiteout_m2_M2AnimationTrackF32_assign_timestamps_inner(
13914                self.raw.as_ptr(),
13915                outer,
13916                values.as_ptr() as *const _,
13917                values.len(),
13918            )
13919        }
13920    }
13921
13922    /// Resize the outer sequence. Do this before taking any borrow.
13923    pub fn resize_timestamps(&mut self, count: usize) {
13924        // SAFETY: exclusive access, so no borrow is outstanding.
13925        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_resize_timestamps(self.raw.as_ptr(), count) }
13926    }
13927
13928    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
13929        // SAFETY: as above.
13930        unsafe {
13931            ffi::whiteout_m2_M2AnimationTrackF32_resize_timestamps_inner(
13932                self.raw.as_ptr(),
13933                outer,
13934                count,
13935            )
13936        }
13937    }
13938
13939    /// Number of inner sequences.
13940    pub fn values_len(&self) -> usize {
13941        // SAFETY: scalar read through a live handle.
13942        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_get_values_count(self.raw.as_ptr()) }
13943    }
13944
13945    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
13946    ///
13947    /// Each inner vector is contiguous on its own, but the outer one
13948    /// is a vector of vectors — so this borrows per sequence rather
13949    /// than handing back one flat slice.
13950    pub fn values(&self, outer: usize) -> &[f32] {
13951        if outer >= self.values_len() {
13952            return &[];
13953        }
13954        // SAFETY: index checked; the pointer borrows `self`.
13955        unsafe {
13956            let n = ffi::whiteout_m2_M2AnimationTrackF32_get_values_inner_count(
13957                self.raw.as_ptr(),
13958                outer,
13959            );
13960            let p = ffi::whiteout_m2_M2AnimationTrackF32_get_values_inner_data(
13961                self.raw.as_ptr(),
13962                outer,
13963            );
13964            if p.is_null() || n == 0 {
13965                &[]
13966            } else {
13967                core::slice::from_raw_parts(p, n)
13968            }
13969        }
13970    }
13971
13972    pub fn values_mut(&mut self, outer: usize) -> &mut [f32] {
13973        if outer >= self.values_len() {
13974            return &mut [];
13975        }
13976        // SAFETY: as above; `&mut self` rules out aliasing.
13977        unsafe {
13978            let n = ffi::whiteout_m2_M2AnimationTrackF32_get_values_inner_count(
13979                self.raw.as_ptr(),
13980                outer,
13981            );
13982            let p = ffi::whiteout_m2_M2AnimationTrackF32_get_values_inner_data(
13983                self.raw.as_ptr(),
13984                outer,
13985            ) as *mut f32;
13986            if p.is_null() || n == 0 {
13987                &mut []
13988            } else {
13989                core::slice::from_raw_parts_mut(p, n)
13990            }
13991        }
13992    }
13993
13994    pub fn set_values(&mut self, outer: usize, values: &[f32]) {
13995        // SAFETY: the native side copies `values` before returning.
13996        unsafe {
13997            ffi::whiteout_m2_M2AnimationTrackF32_assign_values_inner(
13998                self.raw.as_ptr(),
13999                outer,
14000                values.as_ptr() as *const _,
14001                values.len(),
14002            )
14003        }
14004    }
14005
14006    /// Resize the outer sequence. Do this before taking any borrow.
14007    pub fn resize_values(&mut self, count: usize) {
14008        // SAFETY: exclusive access, so no borrow is outstanding.
14009        unsafe { ffi::whiteout_m2_M2AnimationTrackF32_resize_values(self.raw.as_ptr(), count) }
14010    }
14011
14012    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
14013        // SAFETY: as above.
14014        unsafe {
14015            ffi::whiteout_m2_M2AnimationTrackF32_resize_values_inner(
14016                self.raw.as_ptr(),
14017                outer,
14018                count,
14019            )
14020        }
14021    }
14022}
14023
14024impl Default for AnimationTrackF32 {
14025    fn default() -> Self {
14026        Self::new()
14027    }
14028}
14029
14030/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
14031pub struct AnimationTrackU8 {
14032    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackU8>,
14033}
14034
14035impl Drop for AnimationTrackU8 {
14036    fn drop(&mut self) {
14037        // SAFETY: `raw` came from a native constructor and Drop runs once.
14038        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_delete(self.raw.as_ptr()) }
14039    }
14040}
14041
14042impl AnimationTrackU8 {
14043    /// # Safety
14044    /// `raw` must be a live handle this value takes ownership of.
14045    #[allow(dead_code)] // used by whichever methods return this type
14046    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2AnimationTrackU8) -> Option<Self> {
14047        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackU8 { raw })
14048    }
14049}
14050
14051// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14052// is deliberately NOT implemented — the C++ types make no documented
14053// guarantee about concurrent use, and claiming one we haven't verified
14054// would be unsound. See `@bind thread_safe` in the plan.
14055unsafe impl Send for AnimationTrackU8 {}
14056
14057impl core::fmt::Debug for AnimationTrackU8 {
14058    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14059        f.debug_struct("AnimationTrackU8").finish_non_exhaustive()
14060    }
14061}
14062
14063impl AnimationTrackU8 {
14064    /// # Panics
14065    /// Panics if the native allocation fails.
14066    pub fn new() -> Self {
14067        // SAFETY: the native constructor returns a live handle; a null here
14068        // means the library is unusable.
14069        unsafe {
14070            let raw = ffi::whiteout_m2_M2AnimationTrackU8_new();
14071            Self::from_raw(raw).expect("native AnimationTrackU8 allocation failed")
14072        }
14073    }
14074
14075    pub fn interpolation_type(&self) -> InterpolationType {
14076        // SAFETY: scalar read; the discriminant is validated below.
14077        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_get_interpolationType(self.raw.as_ptr()) }
14078            .try_into()
14079            .expect("unknown enum discriminant from the native library")
14080    }
14081
14082    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
14083        // SAFETY: scalar write through a live handle.
14084        unsafe {
14085            ffi::whiteout_m2_M2AnimationTrackU8_set_interpolationType(
14086                self.raw.as_ptr(),
14087                value as i32,
14088            )
14089        }
14090    }
14091
14092    pub fn global_sequence_id(&self) -> u16 {
14093        // SAFETY: plain scalar read through a live handle.
14094        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_get_globalSequenceId(self.raw.as_ptr()) }
14095    }
14096
14097    pub fn set_global_sequence_id(&mut self, value: u16) {
14098        // SAFETY: plain scalar write through a live handle.
14099        unsafe {
14100            ffi::whiteout_m2_M2AnimationTrackU8_set_globalSequenceId(self.raw.as_ptr(), value)
14101        }
14102    }
14103
14104    /// Number of inner sequences.
14105    pub fn timestamps_len(&self) -> usize {
14106        // SAFETY: scalar read through a live handle.
14107        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_get_timestamps_count(self.raw.as_ptr()) }
14108    }
14109
14110    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
14111    ///
14112    /// Each inner vector is contiguous on its own, but the outer one
14113    /// is a vector of vectors — so this borrows per sequence rather
14114    /// than handing back one flat slice.
14115    pub fn timestamps(&self, outer: usize) -> &[u32] {
14116        if outer >= self.timestamps_len() {
14117            return &[];
14118        }
14119        // SAFETY: index checked; the pointer borrows `self`.
14120        unsafe {
14121            let n = ffi::whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_count(
14122                self.raw.as_ptr(),
14123                outer,
14124            );
14125            let p = ffi::whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_data(
14126                self.raw.as_ptr(),
14127                outer,
14128            );
14129            if p.is_null() || n == 0 {
14130                &[]
14131            } else {
14132                core::slice::from_raw_parts(p, n)
14133            }
14134        }
14135    }
14136
14137    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
14138        if outer >= self.timestamps_len() {
14139            return &mut [];
14140        }
14141        // SAFETY: as above; `&mut self` rules out aliasing.
14142        unsafe {
14143            let n = ffi::whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_count(
14144                self.raw.as_ptr(),
14145                outer,
14146            );
14147            let p = ffi::whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_data(
14148                self.raw.as_ptr(),
14149                outer,
14150            ) as *mut u32;
14151            if p.is_null() || n == 0 {
14152                &mut []
14153            } else {
14154                core::slice::from_raw_parts_mut(p, n)
14155            }
14156        }
14157    }
14158
14159    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
14160        // SAFETY: the native side copies `values` before returning.
14161        unsafe {
14162            ffi::whiteout_m2_M2AnimationTrackU8_assign_timestamps_inner(
14163                self.raw.as_ptr(),
14164                outer,
14165                values.as_ptr() as *const _,
14166                values.len(),
14167            )
14168        }
14169    }
14170
14171    /// Resize the outer sequence. Do this before taking any borrow.
14172    pub fn resize_timestamps(&mut self, count: usize) {
14173        // SAFETY: exclusive access, so no borrow is outstanding.
14174        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_resize_timestamps(self.raw.as_ptr(), count) }
14175    }
14176
14177    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
14178        // SAFETY: as above.
14179        unsafe {
14180            ffi::whiteout_m2_M2AnimationTrackU8_resize_timestamps_inner(
14181                self.raw.as_ptr(),
14182                outer,
14183                count,
14184            )
14185        }
14186    }
14187
14188    /// Number of inner sequences.
14189    pub fn values_len(&self) -> usize {
14190        // SAFETY: scalar read through a live handle.
14191        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_get_values_count(self.raw.as_ptr()) }
14192    }
14193
14194    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
14195    ///
14196    /// Each inner vector is contiguous on its own, but the outer one
14197    /// is a vector of vectors — so this borrows per sequence rather
14198    /// than handing back one flat slice.
14199    pub fn values(&self, outer: usize) -> &[u8] {
14200        if outer >= self.values_len() {
14201            return &[];
14202        }
14203        // SAFETY: index checked; the pointer borrows `self`.
14204        unsafe {
14205            let n = ffi::whiteout_m2_M2AnimationTrackU8_get_values_inner_count(
14206                self.raw.as_ptr(),
14207                outer,
14208            );
14209            let p =
14210                ffi::whiteout_m2_M2AnimationTrackU8_get_values_inner_data(self.raw.as_ptr(), outer);
14211            if p.is_null() || n == 0 {
14212                &[]
14213            } else {
14214                core::slice::from_raw_parts(p, n)
14215            }
14216        }
14217    }
14218
14219    pub fn values_mut(&mut self, outer: usize) -> &mut [u8] {
14220        if outer >= self.values_len() {
14221            return &mut [];
14222        }
14223        // SAFETY: as above; `&mut self` rules out aliasing.
14224        unsafe {
14225            let n = ffi::whiteout_m2_M2AnimationTrackU8_get_values_inner_count(
14226                self.raw.as_ptr(),
14227                outer,
14228            );
14229            let p =
14230                ffi::whiteout_m2_M2AnimationTrackU8_get_values_inner_data(self.raw.as_ptr(), outer)
14231                    as *mut u8;
14232            if p.is_null() || n == 0 {
14233                &mut []
14234            } else {
14235                core::slice::from_raw_parts_mut(p, n)
14236            }
14237        }
14238    }
14239
14240    pub fn set_values(&mut self, outer: usize, values: &[u8]) {
14241        // SAFETY: the native side copies `values` before returning.
14242        unsafe {
14243            ffi::whiteout_m2_M2AnimationTrackU8_assign_values_inner(
14244                self.raw.as_ptr(),
14245                outer,
14246                values.as_ptr() as *const _,
14247                values.len(),
14248            )
14249        }
14250    }
14251
14252    /// Resize the outer sequence. Do this before taking any borrow.
14253    pub fn resize_values(&mut self, count: usize) {
14254        // SAFETY: exclusive access, so no borrow is outstanding.
14255        unsafe { ffi::whiteout_m2_M2AnimationTrackU8_resize_values(self.raw.as_ptr(), count) }
14256    }
14257
14258    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
14259        // SAFETY: as above.
14260        unsafe {
14261            ffi::whiteout_m2_M2AnimationTrackU8_resize_values_inner(self.raw.as_ptr(), outer, count)
14262        }
14263    }
14264}
14265
14266impl Default for AnimationTrackU8 {
14267    fn default() -> Self {
14268        Self::new()
14269    }
14270}
14271
14272/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
14273pub struct AnimationTrackM2CameraSpline {
14274    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackM2CameraSpline>,
14275}
14276
14277impl Drop for AnimationTrackM2CameraSpline {
14278    fn drop(&mut self) {
14279        // SAFETY: `raw` came from a native constructor and Drop runs once.
14280        unsafe { ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_delete(self.raw.as_ptr()) }
14281    }
14282}
14283
14284impl AnimationTrackM2CameraSpline {
14285    /// # Safety
14286    /// `raw` must be a live handle this value takes ownership of.
14287    #[allow(dead_code)] // used by whichever methods return this type
14288    pub(crate) unsafe fn from_raw(
14289        raw: *mut ffi::whiteout_M2AnimationTrackM2CameraSpline,
14290    ) -> Option<Self> {
14291        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackM2CameraSpline { raw })
14292    }
14293}
14294
14295// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14296// is deliberately NOT implemented — the C++ types make no documented
14297// guarantee about concurrent use, and claiming one we haven't verified
14298// would be unsound. See `@bind thread_safe` in the plan.
14299unsafe impl Send for AnimationTrackM2CameraSpline {}
14300
14301impl core::fmt::Debug for AnimationTrackM2CameraSpline {
14302    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14303        f.debug_struct("AnimationTrackM2CameraSpline")
14304            .finish_non_exhaustive()
14305    }
14306}
14307
14308impl AnimationTrackM2CameraSpline {
14309    /// # Panics
14310    /// Panics if the native allocation fails.
14311    pub fn new() -> Self {
14312        // SAFETY: the native constructor returns a live handle; a null here
14313        // means the library is unusable.
14314        unsafe {
14315            let raw = ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_new();
14316            Self::from_raw(raw).expect("native AnimationTrackM2CameraSpline allocation failed")
14317        }
14318    }
14319
14320    pub fn interpolation_type(&self) -> InterpolationType {
14321        // SAFETY: scalar read; the discriminant is validated below.
14322        unsafe {
14323            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_interpolationType(self.raw.as_ptr())
14324        }
14325        .try_into()
14326        .expect("unknown enum discriminant from the native library")
14327    }
14328
14329    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
14330        // SAFETY: scalar write through a live handle.
14331        unsafe {
14332            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_set_interpolationType(
14333                self.raw.as_ptr(),
14334                value as i32,
14335            )
14336        }
14337    }
14338
14339    pub fn global_sequence_id(&self) -> u16 {
14340        // SAFETY: plain scalar read through a live handle.
14341        unsafe {
14342            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_globalSequenceId(self.raw.as_ptr())
14343        }
14344    }
14345
14346    pub fn set_global_sequence_id(&mut self, value: u16) {
14347        // SAFETY: plain scalar write through a live handle.
14348        unsafe {
14349            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_set_globalSequenceId(
14350                self.raw.as_ptr(),
14351                value,
14352            )
14353        }
14354    }
14355
14356    /// Number of inner sequences.
14357    pub fn timestamps_len(&self) -> usize {
14358        // SAFETY: scalar read through a live handle.
14359        unsafe {
14360            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_count(self.raw.as_ptr())
14361        }
14362    }
14363
14364    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
14365    ///
14366    /// Each inner vector is contiguous on its own, but the outer one
14367    /// is a vector of vectors — so this borrows per sequence rather
14368    /// than handing back one flat slice.
14369    pub fn timestamps(&self, outer: usize) -> &[u32] {
14370        if outer >= self.timestamps_len() {
14371            return &[];
14372        }
14373        // SAFETY: index checked; the pointer borrows `self`.
14374        unsafe {
14375            let n = ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_count(
14376                self.raw.as_ptr(),
14377                outer,
14378            );
14379            let p = ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_data(
14380                self.raw.as_ptr(),
14381                outer,
14382            );
14383            if p.is_null() || n == 0 {
14384                &[]
14385            } else {
14386                core::slice::from_raw_parts(p, n)
14387            }
14388        }
14389    }
14390
14391    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
14392        if outer >= self.timestamps_len() {
14393            return &mut [];
14394        }
14395        // SAFETY: as above; `&mut self` rules out aliasing.
14396        unsafe {
14397            let n = ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_count(
14398                self.raw.as_ptr(),
14399                outer,
14400            );
14401            let p = ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_data(
14402                self.raw.as_ptr(),
14403                outer,
14404            ) as *mut u32;
14405            if p.is_null() || n == 0 {
14406                &mut []
14407            } else {
14408                core::slice::from_raw_parts_mut(p, n)
14409            }
14410        }
14411    }
14412
14413    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
14414        // SAFETY: the native side copies `values` before returning.
14415        unsafe {
14416            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_assign_timestamps_inner(
14417                self.raw.as_ptr(),
14418                outer,
14419                values.as_ptr() as *const _,
14420                values.len(),
14421            )
14422        }
14423    }
14424
14425    /// Resize the outer sequence. Do this before taking any borrow.
14426    pub fn resize_timestamps(&mut self, count: usize) {
14427        // SAFETY: exclusive access, so no borrow is outstanding.
14428        unsafe {
14429            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_resize_timestamps(
14430                self.raw.as_ptr(),
14431                count,
14432            )
14433        }
14434    }
14435
14436    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
14437        // SAFETY: as above.
14438        unsafe {
14439            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_resize_timestamps_inner(
14440                self.raw.as_ptr(),
14441                outer,
14442                count,
14443            )
14444        }
14445    }
14446
14447    /// Number of inner sequences.
14448    pub fn values_len(&self) -> usize {
14449        // SAFETY: scalar read through a live handle.
14450        unsafe {
14451            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_count(self.raw.as_ptr())
14452        }
14453    }
14454
14455    /// Length of inner sequence `outer`.
14456    pub fn values_inner_len(&self, outer: usize) -> usize {
14457        if outer >= self.values_len() {
14458            return 0;
14459        }
14460        // SAFETY: index checked above.
14461        unsafe {
14462            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_inner_count(
14463                self.raw.as_ptr(),
14464                outer,
14465            )
14466        }
14467    }
14468
14469    /// Borrow element `inner` of sequence `outer` in place.
14470    pub fn values(
14471        &self,
14472        outer: usize,
14473        inner: usize,
14474    ) -> Option<crate::support::Ref<'_, CameraSpline>> {
14475        if inner >= self.values_inner_len(outer) {
14476            return None;
14477        }
14478        // SAFETY: both indices checked; the pointer is
14479        // interior to `self`.
14480        unsafe {
14481            Some(crate::support::Ref::new(CameraSpline {
14482                raw: core::ptr::NonNull::new_unchecked(
14483                    ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_at(
14484                        self.raw.as_ptr(),
14485                        outer,
14486                        inner,
14487                    ),
14488                ),
14489            }))
14490        }
14491    }
14492
14493    pub fn values_mut(
14494        &mut self,
14495        outer: usize,
14496        inner: usize,
14497    ) -> Option<crate::support::RefMut<'_, CameraSpline>> {
14498        if inner >= self.values_inner_len(outer) {
14499            return None;
14500        }
14501        // SAFETY: as above; `&mut self` guarantees exclusivity.
14502        unsafe {
14503            Some(crate::support::RefMut::new(CameraSpline {
14504                raw: core::ptr::NonNull::new_unchecked(
14505                    ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_at(
14506                        self.raw.as_ptr(),
14507                        outer,
14508                        inner,
14509                    ),
14510                ),
14511            }))
14512        }
14513    }
14514
14515    /// Resize the outer sequence. Do this before taking a borrow.
14516    pub fn resize_values(&mut self, count: usize) {
14517        // SAFETY: exclusive access, so no borrow is outstanding.
14518        unsafe {
14519            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_resize_values(self.raw.as_ptr(), count)
14520        }
14521    }
14522
14523    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
14524        // SAFETY: as above.
14525        unsafe {
14526            ffi::whiteout_m2_M2AnimationTrackM2CameraSpline_resize_values_inner(
14527                self.raw.as_ptr(),
14528                outer,
14529                count,
14530            )
14531        }
14532    }
14533}
14534
14535impl Default for AnimationTrackM2CameraSpline {
14536    fn default() -> Self {
14537        Self::new()
14538    }
14539}
14540
14541/// instantiate=Vector3f;CompatQuaternion;Quaternion;i16;u8;u16;f32;CameraSpline
14542pub struct AnimationTrackU16 {
14543    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2AnimationTrackU16>,
14544}
14545
14546impl Drop for AnimationTrackU16 {
14547    fn drop(&mut self) {
14548        // SAFETY: `raw` came from a native constructor and Drop runs once.
14549        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_delete(self.raw.as_ptr()) }
14550    }
14551}
14552
14553impl AnimationTrackU16 {
14554    /// # Safety
14555    /// `raw` must be a live handle this value takes ownership of.
14556    #[allow(dead_code)] // used by whichever methods return this type
14557    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_M2AnimationTrackU16) -> Option<Self> {
14558        core::ptr::NonNull::new(raw).map(|raw| AnimationTrackU16 { raw })
14559    }
14560}
14561
14562// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14563// is deliberately NOT implemented — the C++ types make no documented
14564// guarantee about concurrent use, and claiming one we haven't verified
14565// would be unsound. See `@bind thread_safe` in the plan.
14566unsafe impl Send for AnimationTrackU16 {}
14567
14568impl core::fmt::Debug for AnimationTrackU16 {
14569    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14570        f.debug_struct("AnimationTrackU16").finish_non_exhaustive()
14571    }
14572}
14573
14574impl AnimationTrackU16 {
14575    /// # Panics
14576    /// Panics if the native allocation fails.
14577    pub fn new() -> Self {
14578        // SAFETY: the native constructor returns a live handle; a null here
14579        // means the library is unusable.
14580        unsafe {
14581            let raw = ffi::whiteout_m2_M2AnimationTrackU16_new();
14582            Self::from_raw(raw).expect("native AnimationTrackU16 allocation failed")
14583        }
14584    }
14585
14586    pub fn interpolation_type(&self) -> InterpolationType {
14587        // SAFETY: scalar read; the discriminant is validated below.
14588        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_get_interpolationType(self.raw.as_ptr()) }
14589            .try_into()
14590            .expect("unknown enum discriminant from the native library")
14591    }
14592
14593    pub fn set_interpolation_type(&mut self, value: InterpolationType) {
14594        // SAFETY: scalar write through a live handle.
14595        unsafe {
14596            ffi::whiteout_m2_M2AnimationTrackU16_set_interpolationType(
14597                self.raw.as_ptr(),
14598                value as i32,
14599            )
14600        }
14601    }
14602
14603    pub fn global_sequence_id(&self) -> u16 {
14604        // SAFETY: plain scalar read through a live handle.
14605        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_get_globalSequenceId(self.raw.as_ptr()) }
14606    }
14607
14608    pub fn set_global_sequence_id(&mut self, value: u16) {
14609        // SAFETY: plain scalar write through a live handle.
14610        unsafe {
14611            ffi::whiteout_m2_M2AnimationTrackU16_set_globalSequenceId(self.raw.as_ptr(), value)
14612        }
14613    }
14614
14615    /// Number of inner sequences.
14616    pub fn timestamps_len(&self) -> usize {
14617        // SAFETY: scalar read through a live handle.
14618        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_get_timestamps_count(self.raw.as_ptr()) }
14619    }
14620
14621    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
14622    ///
14623    /// Each inner vector is contiguous on its own, but the outer one
14624    /// is a vector of vectors — so this borrows per sequence rather
14625    /// than handing back one flat slice.
14626    pub fn timestamps(&self, outer: usize) -> &[u32] {
14627        if outer >= self.timestamps_len() {
14628            return &[];
14629        }
14630        // SAFETY: index checked; the pointer borrows `self`.
14631        unsafe {
14632            let n = ffi::whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_count(
14633                self.raw.as_ptr(),
14634                outer,
14635            );
14636            let p = ffi::whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_data(
14637                self.raw.as_ptr(),
14638                outer,
14639            );
14640            if p.is_null() || n == 0 {
14641                &[]
14642            } else {
14643                core::slice::from_raw_parts(p, n)
14644            }
14645        }
14646    }
14647
14648    pub fn timestamps_mut(&mut self, outer: usize) -> &mut [u32] {
14649        if outer >= self.timestamps_len() {
14650            return &mut [];
14651        }
14652        // SAFETY: as above; `&mut self` rules out aliasing.
14653        unsafe {
14654            let n = ffi::whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_count(
14655                self.raw.as_ptr(),
14656                outer,
14657            );
14658            let p = ffi::whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_data(
14659                self.raw.as_ptr(),
14660                outer,
14661            ) as *mut u32;
14662            if p.is_null() || n == 0 {
14663                &mut []
14664            } else {
14665                core::slice::from_raw_parts_mut(p, n)
14666            }
14667        }
14668    }
14669
14670    pub fn set_timestamps(&mut self, outer: usize, values: &[u32]) {
14671        // SAFETY: the native side copies `values` before returning.
14672        unsafe {
14673            ffi::whiteout_m2_M2AnimationTrackU16_assign_timestamps_inner(
14674                self.raw.as_ptr(),
14675                outer,
14676                values.as_ptr() as *const _,
14677                values.len(),
14678            )
14679        }
14680    }
14681
14682    /// Resize the outer sequence. Do this before taking any borrow.
14683    pub fn resize_timestamps(&mut self, count: usize) {
14684        // SAFETY: exclusive access, so no borrow is outstanding.
14685        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_resize_timestamps(self.raw.as_ptr(), count) }
14686    }
14687
14688    pub fn resize_timestamps_inner(&mut self, outer: usize, count: usize) {
14689        // SAFETY: as above.
14690        unsafe {
14691            ffi::whiteout_m2_M2AnimationTrackU16_resize_timestamps_inner(
14692                self.raw.as_ptr(),
14693                outer,
14694                count,
14695            )
14696        }
14697    }
14698
14699    /// Number of inner sequences.
14700    pub fn values_len(&self) -> usize {
14701        // SAFETY: scalar read through a live handle.
14702        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_get_values_count(self.raw.as_ptr()) }
14703    }
14704
14705    /// Zero-copy view of inner sequence `outer`. Empty when out of range.
14706    ///
14707    /// Each inner vector is contiguous on its own, but the outer one
14708    /// is a vector of vectors — so this borrows per sequence rather
14709    /// than handing back one flat slice.
14710    pub fn values(&self, outer: usize) -> &[u16] {
14711        if outer >= self.values_len() {
14712            return &[];
14713        }
14714        // SAFETY: index checked; the pointer borrows `self`.
14715        unsafe {
14716            let n = ffi::whiteout_m2_M2AnimationTrackU16_get_values_inner_count(
14717                self.raw.as_ptr(),
14718                outer,
14719            );
14720            let p = ffi::whiteout_m2_M2AnimationTrackU16_get_values_inner_data(
14721                self.raw.as_ptr(),
14722                outer,
14723            );
14724            if p.is_null() || n == 0 {
14725                &[]
14726            } else {
14727                core::slice::from_raw_parts(p, n)
14728            }
14729        }
14730    }
14731
14732    pub fn values_mut(&mut self, outer: usize) -> &mut [u16] {
14733        if outer >= self.values_len() {
14734            return &mut [];
14735        }
14736        // SAFETY: as above; `&mut self` rules out aliasing.
14737        unsafe {
14738            let n = ffi::whiteout_m2_M2AnimationTrackU16_get_values_inner_count(
14739                self.raw.as_ptr(),
14740                outer,
14741            );
14742            let p = ffi::whiteout_m2_M2AnimationTrackU16_get_values_inner_data(
14743                self.raw.as_ptr(),
14744                outer,
14745            ) as *mut u16;
14746            if p.is_null() || n == 0 {
14747                &mut []
14748            } else {
14749                core::slice::from_raw_parts_mut(p, n)
14750            }
14751        }
14752    }
14753
14754    pub fn set_values(&mut self, outer: usize, values: &[u16]) {
14755        // SAFETY: the native side copies `values` before returning.
14756        unsafe {
14757            ffi::whiteout_m2_M2AnimationTrackU16_assign_values_inner(
14758                self.raw.as_ptr(),
14759                outer,
14760                values.as_ptr() as *const _,
14761                values.len(),
14762            )
14763        }
14764    }
14765
14766    /// Resize the outer sequence. Do this before taking any borrow.
14767    pub fn resize_values(&mut self, count: usize) {
14768        // SAFETY: exclusive access, so no borrow is outstanding.
14769        unsafe { ffi::whiteout_m2_M2AnimationTrackU16_resize_values(self.raw.as_ptr(), count) }
14770    }
14771
14772    pub fn resize_values_inner(&mut self, outer: usize, count: usize) {
14773        // SAFETY: as above.
14774        unsafe {
14775            ffi::whiteout_m2_M2AnimationTrackU16_resize_values_inner(
14776                self.raw.as_ptr(),
14777                outer,
14778                count,
14779            )
14780        }
14781    }
14782}
14783
14784impl Default for AnimationTrackU16 {
14785    fn default() -> Self {
14786        Self::new()
14787    }
14788}
14789
14790pub struct ParticleAnimationTrackVector3f {
14791    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ParticleAnimationTrackVector3f>,
14792}
14793
14794impl Drop for ParticleAnimationTrackVector3f {
14795    fn drop(&mut self) {
14796        // SAFETY: `raw` came from a native constructor and Drop runs once.
14797        unsafe { ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_delete(self.raw.as_ptr()) }
14798    }
14799}
14800
14801impl ParticleAnimationTrackVector3f {
14802    /// # Safety
14803    /// `raw` must be a live handle this value takes ownership of.
14804    #[allow(dead_code)] // used by whichever methods return this type
14805    pub(crate) unsafe fn from_raw(
14806        raw: *mut ffi::whiteout_M2ParticleAnimationTrackVector3f,
14807    ) -> Option<Self> {
14808        core::ptr::NonNull::new(raw).map(|raw| ParticleAnimationTrackVector3f { raw })
14809    }
14810}
14811
14812// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14813// is deliberately NOT implemented — the C++ types make no documented
14814// guarantee about concurrent use, and claiming one we haven't verified
14815// would be unsound. See `@bind thread_safe` in the plan.
14816unsafe impl Send for ParticleAnimationTrackVector3f {}
14817
14818impl core::fmt::Debug for ParticleAnimationTrackVector3f {
14819    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14820        f.debug_struct("ParticleAnimationTrackVector3f")
14821            .finish_non_exhaustive()
14822    }
14823}
14824
14825impl ParticleAnimationTrackVector3f {
14826    /// # Panics
14827    /// Panics if the native allocation fails.
14828    pub fn new() -> Self {
14829        // SAFETY: the native constructor returns a live handle; a null here
14830        // means the library is unusable.
14831        unsafe {
14832            let raw = ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_new();
14833            Self::from_raw(raw).expect("native ParticleAnimationTrackVector3f allocation failed")
14834        }
14835    }
14836
14837    /// Zero-copy view of the underlying `std::vector`.
14838    pub fn values(&self) -> &[crate::math::Vector3f] {
14839        // SAFETY: `_data`/`_count` describe one contiguous C++
14840        // allocation, borrowed for as long as `self` is.
14841        unsafe {
14842            let n = ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_count(
14843                self.raw.as_ptr(),
14844            );
14845            let p = ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_data(
14846                self.raw.as_ptr(),
14847            ) as *const crate::math::Vector3f;
14848            if p.is_null() || n == 0 {
14849                &[]
14850            } else {
14851                core::slice::from_raw_parts(p, n)
14852            }
14853        }
14854    }
14855
14856    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14857    pub fn values_mut(&mut self) -> &mut [crate::math::Vector3f] {
14858        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14859        unsafe {
14860            let n = ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_count(
14861                self.raw.as_ptr(),
14862            );
14863            let p = ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_data(
14864                self.raw.as_ptr(),
14865            ) as *const crate::math::Vector3f as *mut crate::math::Vector3f;
14866            if p.is_null() || n == 0 {
14867                &mut []
14868            } else {
14869                core::slice::from_raw_parts_mut(p, n)
14870            }
14871        }
14872    }
14873
14874    pub fn set_values(&mut self, values: &[crate::math::Vector3f]) {
14875        // SAFETY: the native side copies `values` before returning.
14876        unsafe {
14877            ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_assign_values(
14878                self.raw.as_ptr(),
14879                values.as_ptr() as *const _,
14880                values.len(),
14881            )
14882        }
14883    }
14884
14885    pub fn resize_values(&mut self, count: usize) {
14886        // SAFETY: reallocation is safe here precisely because
14887        // `&mut self` means no slice borrow is outstanding.
14888        unsafe {
14889            ffi::whiteout_m2_M2ParticleAnimationTrackVector3f_resize_values(
14890                self.raw.as_ptr(),
14891                count,
14892            )
14893        }
14894    }
14895}
14896
14897impl Default for ParticleAnimationTrackVector3f {
14898    fn default() -> Self {
14899        Self::new()
14900    }
14901}
14902
14903pub struct ParticleAnimationTrackVector2f {
14904    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_M2ParticleAnimationTrackVector2f>,
14905}
14906
14907impl Drop for ParticleAnimationTrackVector2f {
14908    fn drop(&mut self) {
14909        // SAFETY: `raw` came from a native constructor and Drop runs once.
14910        unsafe { ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_delete(self.raw.as_ptr()) }
14911    }
14912}
14913
14914impl ParticleAnimationTrackVector2f {
14915    /// # Safety
14916    /// `raw` must be a live handle this value takes ownership of.
14917    #[allow(dead_code)] // used by whichever methods return this type
14918    pub(crate) unsafe fn from_raw(
14919        raw: *mut ffi::whiteout_M2ParticleAnimationTrackVector2f,
14920    ) -> Option<Self> {
14921        core::ptr::NonNull::new(raw).map(|raw| ParticleAnimationTrackVector2f { raw })
14922    }
14923}
14924
14925// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
14926// is deliberately NOT implemented — the C++ types make no documented
14927// guarantee about concurrent use, and claiming one we haven't verified
14928// would be unsound. See `@bind thread_safe` in the plan.
14929unsafe impl Send for ParticleAnimationTrackVector2f {}
14930
14931impl core::fmt::Debug for ParticleAnimationTrackVector2f {
14932    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14933        f.debug_struct("ParticleAnimationTrackVector2f")
14934            .finish_non_exhaustive()
14935    }
14936}
14937
14938impl ParticleAnimationTrackVector2f {
14939    /// # Panics
14940    /// Panics if the native allocation fails.
14941    pub fn new() -> Self {
14942        // SAFETY: the native constructor returns a live handle; a null here
14943        // means the library is unusable.
14944        unsafe {
14945            let raw = ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_new();
14946            Self::from_raw(raw).expect("native ParticleAnimationTrackVector2f allocation failed")
14947        }
14948    }
14949
14950    /// Zero-copy view of the underlying `std::vector`.
14951    pub fn values(&self) -> &[crate::math::Vector2f] {
14952        // SAFETY: `_data`/`_count` describe one contiguous C++
14953        // allocation, borrowed for as long as `self` is.
14954        unsafe {
14955            let n = ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_count(
14956                self.raw.as_ptr(),
14957            );
14958            let p = ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_data(
14959                self.raw.as_ptr(),
14960            ) as *const crate::math::Vector2f;
14961            if p.is_null() || n == 0 {
14962                &[]
14963            } else {
14964                core::slice::from_raw_parts(p, n)
14965            }
14966        }
14967    }
14968
14969    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
14970    pub fn values_mut(&mut self) -> &mut [crate::math::Vector2f] {
14971        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
14972        unsafe {
14973            let n = ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_count(
14974                self.raw.as_ptr(),
14975            );
14976            let p = ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_data(
14977                self.raw.as_ptr(),
14978            ) as *const crate::math::Vector2f as *mut crate::math::Vector2f;
14979            if p.is_null() || n == 0 {
14980                &mut []
14981            } else {
14982                core::slice::from_raw_parts_mut(p, n)
14983            }
14984        }
14985    }
14986
14987    pub fn set_values(&mut self, values: &[crate::math::Vector2f]) {
14988        // SAFETY: the native side copies `values` before returning.
14989        unsafe {
14990            ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_assign_values(
14991                self.raw.as_ptr(),
14992                values.as_ptr() as *const _,
14993                values.len(),
14994            )
14995        }
14996    }
14997
14998    pub fn resize_values(&mut self, count: usize) {
14999        // SAFETY: reallocation is safe here precisely because
15000        // `&mut self` means no slice borrow is outstanding.
15001        unsafe {
15002            ffi::whiteout_m2_M2ParticleAnimationTrackVector2f_resize_values(
15003                self.raw.as_ptr(),
15004                count,
15005            )
15006        }
15007    }
15008}
15009
15010impl Default for ParticleAnimationTrackVector2f {
15011    fn default() -> Self {
15012        Self::new()
15013    }
15014}
15015
15016#[doc(hidden)]
15017pub mod ffi {
15018    #![allow(missing_debug_implementations)]
15019
15020    #[allow(unused_imports)]
15021    use crate::support::{RawBytes, RawCString};
15022
15023    #[repr(C)]
15024    pub struct whiteout_M2CompatQuaternion {
15025        _private: [u8; 0],
15026    }
15027    #[repr(C)]
15028    pub struct whiteout_M2ColorBGRA {
15029        _private: [u8; 0],
15030    }
15031    #[repr(C)]
15032    pub struct whiteout_M2Extent {
15033        _private: [u8; 0],
15034    }
15035    #[repr(C)]
15036    pub struct whiteout_M2KeySpanRef {
15037        _private: [u8; 0],
15038    }
15039    #[repr(C)]
15040    pub struct whiteout_M2AnimationTrackBase {
15041        _private: [u8; 0],
15042    }
15043    #[repr(C)]
15044    pub struct whiteout_M2ParticleEmitterExtension {
15045        _private: [u8; 0],
15046    }
15047    #[repr(C)]
15048    pub struct whiteout_M2LodProfile {
15049        _private: [u8; 0],
15050    }
15051    #[repr(C)]
15052    pub struct whiteout_M2WaterfallData {
15053        _private: [u8; 0],
15054    }
15055    #[repr(C)]
15056    pub struct whiteout_M2ParticleGeosetData {
15057        _private: [u8; 0],
15058    }
15059    #[repr(C)]
15060    pub struct whiteout_M2EdgeFadeData {
15061        _private: [u8; 0],
15062    }
15063    #[repr(C)]
15064    pub struct whiteout_M2DistanceFadeData {
15065        _private: [u8; 0],
15066    }
15067    #[repr(C)]
15068    pub struct whiteout_M2DetailedLightData {
15069        _private: [u8; 0],
15070    }
15071    #[repr(C)]
15072    pub struct whiteout_M2DebugOcclusionData {
15073        _private: [u8; 0],
15074    }
15075    #[repr(C)]
15076    pub struct whiteout_M2TexturedLightData {
15077        _private: [u8; 0],
15078    }
15079    #[repr(C)]
15080    pub struct whiteout_M2PivotDisplacementData {
15081        _private: [u8; 0],
15082    }
15083    #[repr(C)]
15084    pub struct whiteout_M2PhysicsCollision {
15085        _private: [u8; 0],
15086    }
15087    #[repr(C)]
15088    pub struct whiteout_M2SkinSection {
15089        _private: [u8; 0],
15090    }
15091    #[repr(C)]
15092    pub struct whiteout_M2Batch {
15093        _private: [u8; 0],
15094    }
15095    #[repr(C)]
15096    pub struct whiteout_M2ShadowBatch {
15097        _private: [u8; 0],
15098    }
15099    #[repr(C)]
15100    pub struct whiteout_M2SkinProfile {
15101        _private: [u8; 0],
15102    }
15103    #[repr(C)]
15104    pub struct whiteout_M2GlobalFlags {
15105        _private: [u8; 0],
15106    }
15107    #[repr(C)]
15108    pub struct whiteout_M2GlobalSequence {
15109        _private: [u8; 0],
15110    }
15111    #[repr(C)]
15112    pub struct whiteout_M2Sequence {
15113        _private: [u8; 0],
15114    }
15115    #[repr(C)]
15116    pub struct whiteout_M2Vertex {
15117        _private: [u8; 0],
15118    }
15119    #[repr(C)]
15120    pub struct whiteout_M2Bone {
15121        _private: [u8; 0],
15122    }
15123    #[repr(C)]
15124    pub struct whiteout_M2Texture {
15125        _private: [u8; 0],
15126    }
15127    #[repr(C)]
15128    pub struct whiteout_M2Material {
15129        _private: [u8; 0],
15130    }
15131    #[repr(C)]
15132    pub struct whiteout_M2TextureWeight {
15133        _private: [u8; 0],
15134    }
15135    #[repr(C)]
15136    pub struct whiteout_M2TextureTransform {
15137        _private: [u8; 0],
15138    }
15139    #[repr(C)]
15140    pub struct whiteout_M2ColorAnimation {
15141        _private: [u8; 0],
15142    }
15143    #[repr(C)]
15144    pub struct whiteout_M2Light {
15145        _private: [u8; 0],
15146    }
15147    #[repr(C)]
15148    pub struct whiteout_M2CameraSpline {
15149        _private: [u8; 0],
15150    }
15151    #[repr(C)]
15152    pub struct whiteout_M2Camera {
15153        _private: [u8; 0],
15154    }
15155    #[repr(C)]
15156    pub struct whiteout_M2Attachment {
15157        _private: [u8; 0],
15158    }
15159    #[repr(C)]
15160    pub struct whiteout_M2RibbonEmitter {
15161        _private: [u8; 0],
15162    }
15163    #[repr(C)]
15164    pub struct whiteout_M2Box {
15165        _private: [u8; 0],
15166    }
15167    #[repr(C)]
15168    pub struct whiteout_M2ParticleEmitter {
15169        _private: [u8; 0],
15170    }
15171    #[repr(C)]
15172    pub struct whiteout_M2Event {
15173        _private: [u8; 0],
15174    }
15175    #[repr(C)]
15176    pub struct whiteout_M2PhysicsFrame {
15177        _private: [u8; 0],
15178    }
15179    #[repr(C)]
15180    pub struct whiteout_M2PhysicsBody {
15181        _private: [u8; 0],
15182    }
15183    #[repr(C)]
15184    pub struct whiteout_M2PhysicsShape {
15185        _private: [u8; 0],
15186    }
15187    #[repr(C)]
15188    pub struct whiteout_M2BoxShape {
15189        _private: [u8; 0],
15190    }
15191    #[repr(C)]
15192    pub struct whiteout_M2CapsuleShape {
15193        _private: [u8; 0],
15194    }
15195    #[repr(C)]
15196    pub struct whiteout_M2SphereShape {
15197        _private: [u8; 0],
15198    }
15199    #[repr(C)]
15200    pub struct whiteout_M2PolytopeHalfEdge {
15201        _private: [u8; 0],
15202    }
15203    #[repr(C)]
15204    pub struct whiteout_M2PolytopeShape {
15205        _private: [u8; 0],
15206    }
15207    #[repr(C)]
15208    pub struct whiteout_M2PhysicsJoint {
15209        _private: [u8; 0],
15210    }
15211    #[repr(C)]
15212    pub struct whiteout_M2WeldJoint {
15213        _private: [u8; 0],
15214    }
15215    #[repr(C)]
15216    pub struct whiteout_M2SphericalJoint {
15217        _private: [u8; 0],
15218    }
15219    #[repr(C)]
15220    pub struct whiteout_M2ShoulderJoint {
15221        _private: [u8; 0],
15222    }
15223    #[repr(C)]
15224    pub struct whiteout_M2PrismaticJoint {
15225        _private: [u8; 0],
15226    }
15227    #[repr(C)]
15228    pub struct whiteout_M2RevoluteJoint {
15229        _private: [u8; 0],
15230    }
15231    #[repr(C)]
15232    pub struct whiteout_M2DistanceJoint {
15233        _private: [u8; 0],
15234    }
15235    #[repr(C)]
15236    pub struct whiteout_M2PhysicsTuning {
15237        _private: [u8; 0],
15238    }
15239    #[repr(C)]
15240    pub struct whiteout_M2PhysicsUnknownChunk {
15241        _private: [u8; 0],
15242    }
15243    #[repr(C)]
15244    pub struct whiteout_M2PhysicsData {
15245        _private: [u8; 0],
15246    }
15247    #[repr(C)]
15248    pub struct whiteout_M2BoneOverride {
15249        _private: [u8; 0],
15250    }
15251    #[repr(C)]
15252    pub struct whiteout_M2BoneOverrideSet {
15253        _private: [u8; 0],
15254    }
15255    #[repr(C)]
15256    pub struct whiteout_M2Model {
15257        _private: [u8; 0],
15258    }
15259    #[repr(C)]
15260    pub struct whiteout_M2Parser {
15261        _private: [u8; 0],
15262    }
15263    #[repr(C)]
15264    pub struct whiteout_M2WriteOptions {
15265        _private: [u8; 0],
15266    }
15267    #[repr(C)]
15268    pub struct whiteout_M2SerializeResult {
15269        _private: [u8; 0],
15270    }
15271    #[repr(C)]
15272    pub struct whiteout_M2Writer {
15273        _private: [u8; 0],
15274    }
15275    #[repr(C)]
15276    pub struct whiteout_M2AnimationTrackVector3f {
15277        _private: [u8; 0],
15278    }
15279    #[repr(C)]
15280    pub struct whiteout_M2AnimationTrackM2CompatQuaternion {
15281        _private: [u8; 0],
15282    }
15283    #[repr(C)]
15284    pub struct whiteout_M2AnimationTrackI16 {
15285        _private: [u8; 0],
15286    }
15287    #[repr(C)]
15288    pub struct whiteout_M2AnimationTrackQuaternion {
15289        _private: [u8; 0],
15290    }
15291    #[repr(C)]
15292    pub struct whiteout_M2AnimationTrackF32 {
15293        _private: [u8; 0],
15294    }
15295    #[repr(C)]
15296    pub struct whiteout_M2AnimationTrackU8 {
15297        _private: [u8; 0],
15298    }
15299    #[repr(C)]
15300    pub struct whiteout_M2AnimationTrackM2CameraSpline {
15301        _private: [u8; 0],
15302    }
15303    #[repr(C)]
15304    pub struct whiteout_M2AnimationTrackU16 {
15305        _private: [u8; 0],
15306    }
15307    #[repr(C)]
15308    pub struct whiteout_M2ParticleAnimationTrackVector3f {
15309        _private: [u8; 0],
15310    }
15311    #[repr(C)]
15312    pub struct whiteout_M2ParticleAnimationTrackVector2f {
15313        _private: [u8; 0],
15314    }
15315
15316    extern "C" {
15317        // CompatQuaternion
15318        pub fn whiteout_m2_M2CompatQuaternion_new() -> *mut whiteout_M2CompatQuaternion;
15319        pub fn whiteout_m2_M2CompatQuaternion_delete(self_: *mut whiteout_M2CompatQuaternion);
15320        // ColorBGRA
15321        pub fn whiteout_m2_M2ColorBGRA_new() -> *mut whiteout_M2ColorBGRA;
15322        pub fn whiteout_m2_M2ColorBGRA_delete(self_: *mut whiteout_M2ColorBGRA);
15323        // Extent
15324        pub fn whiteout_m2_M2Extent_new() -> *mut whiteout_M2Extent;
15325        pub fn whiteout_m2_M2Extent_delete(self_: *mut whiteout_M2Extent);
15326        pub fn whiteout_m2_M2Extent_get_minimum(
15327            self_: *mut whiteout_M2Extent,
15328        ) -> *mut core::ffi::c_void;
15329        pub fn whiteout_m2_M2Extent_set_minimum(
15330            self_: *mut whiteout_M2Extent,
15331            value: *const core::ffi::c_void,
15332        );
15333        pub fn whiteout_m2_M2Extent_get_maximum(
15334            self_: *mut whiteout_M2Extent,
15335        ) -> *mut core::ffi::c_void;
15336        pub fn whiteout_m2_M2Extent_set_maximum(
15337            self_: *mut whiteout_M2Extent,
15338            value: *const core::ffi::c_void,
15339        );
15340        pub fn whiteout_m2_M2Extent_get_sphereRadius(self_: *mut whiteout_M2Extent) -> f32;
15341        pub fn whiteout_m2_M2Extent_set_sphereRadius(self_: *mut whiteout_M2Extent, value: f32);
15342        // KeySpanRef
15343        pub fn whiteout_m2_M2KeySpanRef_new() -> *mut whiteout_M2KeySpanRef;
15344        pub fn whiteout_m2_M2KeySpanRef_delete(self_: *mut whiteout_M2KeySpanRef);
15345        pub fn whiteout_m2_M2KeySpanRef_get_count(self_: *mut whiteout_M2KeySpanRef) -> u32;
15346        pub fn whiteout_m2_M2KeySpanRef_set_count(self_: *mut whiteout_M2KeySpanRef, value: u32);
15347        pub fn whiteout_m2_M2KeySpanRef_get_offset(self_: *mut whiteout_M2KeySpanRef) -> u32;
15348        pub fn whiteout_m2_M2KeySpanRef_set_offset(self_: *mut whiteout_M2KeySpanRef, value: u32);
15349        // AnimationTrackBase
15350        pub fn whiteout_m2_M2AnimationTrackBase_new() -> *mut whiteout_M2AnimationTrackBase;
15351        pub fn whiteout_m2_M2AnimationTrackBase_delete(self_: *mut whiteout_M2AnimationTrackBase);
15352        pub fn whiteout_m2_M2AnimationTrackBase_get_interpolationType(
15353            self_: *mut whiteout_M2AnimationTrackBase,
15354        ) -> i32;
15355        pub fn whiteout_m2_M2AnimationTrackBase_set_interpolationType(
15356            self_: *mut whiteout_M2AnimationTrackBase,
15357            value: i32,
15358        );
15359        pub fn whiteout_m2_M2AnimationTrackBase_get_globalSequenceId(
15360            self_: *mut whiteout_M2AnimationTrackBase,
15361        ) -> u16;
15362        pub fn whiteout_m2_M2AnimationTrackBase_set_globalSequenceId(
15363            self_: *mut whiteout_M2AnimationTrackBase,
15364            value: u16,
15365        );
15366        pub fn whiteout_m2_M2AnimationTrackBase_get_timestamps_count(
15367            self_: *mut whiteout_M2AnimationTrackBase,
15368        ) -> usize;
15369        pub fn whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_count(
15370            self_: *mut whiteout_M2AnimationTrackBase,
15371            outer: usize,
15372        ) -> usize;
15373        pub fn whiteout_m2_M2AnimationTrackBase_resize_timestamps(
15374            self_: *mut whiteout_M2AnimationTrackBase,
15375            count: usize,
15376        );
15377        pub fn whiteout_m2_M2AnimationTrackBase_resize_timestamps_inner(
15378            self_: *mut whiteout_M2AnimationTrackBase,
15379            outer: usize,
15380            count: usize,
15381        );
15382        pub fn whiteout_m2_M2AnimationTrackBase_get_timestamps_inner_data(
15383            self_: *mut whiteout_M2AnimationTrackBase,
15384            outer: usize,
15385        ) -> *const u32;
15386        pub fn whiteout_m2_M2AnimationTrackBase_assign_timestamps_inner(
15387            self_: *mut whiteout_M2AnimationTrackBase,
15388            outer: usize,
15389            data: *const u32,
15390            count: usize,
15391        );
15392        // ParticleEmitterExtension
15393        pub fn whiteout_m2_M2ParticleEmitterExtension_new(
15394        ) -> *mut whiteout_M2ParticleEmitterExtension;
15395        pub fn whiteout_m2_M2ParticleEmitterExtension_delete(
15396            self_: *mut whiteout_M2ParticleEmitterExtension,
15397        );
15398        pub fn whiteout_m2_M2ParticleEmitterExtension_get_zSource(
15399            self_: *mut whiteout_M2ParticleEmitterExtension,
15400        ) -> f32;
15401        pub fn whiteout_m2_M2ParticleEmitterExtension_set_zSource(
15402            self_: *mut whiteout_M2ParticleEmitterExtension,
15403            value: f32,
15404        );
15405        pub fn whiteout_m2_M2ParticleEmitterExtension_get_colorMult(
15406            self_: *mut whiteout_M2ParticleEmitterExtension,
15407        ) -> f32;
15408        pub fn whiteout_m2_M2ParticleEmitterExtension_set_colorMult(
15409            self_: *mut whiteout_M2ParticleEmitterExtension,
15410            value: f32,
15411        );
15412        pub fn whiteout_m2_M2ParticleEmitterExtension_get_alphaMult(
15413            self_: *mut whiteout_M2ParticleEmitterExtension,
15414        ) -> f32;
15415        pub fn whiteout_m2_M2ParticleEmitterExtension_set_alphaMult(
15416            self_: *mut whiteout_M2ParticleEmitterExtension,
15417            value: f32,
15418        );
15419        // LodProfile
15420        pub fn whiteout_m2_M2LodProfile_new() -> *mut whiteout_M2LodProfile;
15421        pub fn whiteout_m2_M2LodProfile_delete(self_: *mut whiteout_M2LodProfile);
15422        pub fn whiteout_m2_M2LodProfile_get_flags(self_: *mut whiteout_M2LodProfile) -> u16;
15423        pub fn whiteout_m2_M2LodProfile_set_flags(self_: *mut whiteout_M2LodProfile, value: u16);
15424        pub fn whiteout_m2_M2LodProfile_get_numLodLevels(self_: *mut whiteout_M2LodProfile) -> u16;
15425        pub fn whiteout_m2_M2LodProfile_set_numLodLevels(
15426            self_: *mut whiteout_M2LodProfile,
15427            value: u16,
15428        );
15429        pub fn whiteout_m2_M2LodProfile_get_lodDistance(self_: *mut whiteout_M2LodProfile) -> f32;
15430        pub fn whiteout_m2_M2LodProfile_set_lodDistance(
15431            self_: *mut whiteout_M2LodProfile,
15432            value: f32,
15433        );
15434        pub fn whiteout_m2_M2LodProfile_particleBoneLod_size() -> usize;
15435        pub fn whiteout_m2_M2LodProfile_get_particleBoneLod_at(
15436            self_: *mut whiteout_M2LodProfile,
15437            index: usize,
15438        ) -> u8;
15439        pub fn whiteout_m2_M2LodProfile_set_particleBoneLod_at(
15440            self_: *mut whiteout_M2LodProfile,
15441            index: usize,
15442            value: u8,
15443        );
15444        pub fn whiteout_m2_M2LodProfile_get_lodScaleRaw(self_: *mut whiteout_M2LodProfile) -> u16;
15445        pub fn whiteout_m2_M2LodProfile_set_lodScaleRaw(
15446            self_: *mut whiteout_M2LodProfile,
15447            value: u16,
15448        );
15449        pub fn whiteout_m2_M2LodProfile_get_lodBatchCount(self_: *mut whiteout_M2LodProfile) -> u8;
15450        pub fn whiteout_m2_M2LodProfile_set_lodBatchCount(
15451            self_: *mut whiteout_M2LodProfile,
15452            value: u8,
15453        );
15454        pub fn whiteout_m2_M2LodProfile_get_reserved1(self_: *mut whiteout_M2LodProfile) -> u8;
15455        pub fn whiteout_m2_M2LodProfile_set_reserved1(self_: *mut whiteout_M2LodProfile, value: u8);
15456        // WaterfallData
15457        pub fn whiteout_m2_M2WaterfallData_new() -> *mut whiteout_M2WaterfallData;
15458        pub fn whiteout_m2_M2WaterfallData_delete(self_: *mut whiteout_M2WaterfallData);
15459        pub fn whiteout_m2_M2WaterfallData_get_bumpScale(
15460            self_: *mut whiteout_M2WaterfallData,
15461        ) -> f32;
15462        pub fn whiteout_m2_M2WaterfallData_set_bumpScale(
15463            self_: *mut whiteout_M2WaterfallData,
15464            value: f32,
15465        );
15466        pub fn whiteout_m2_M2WaterfallData_get_value0_x(
15467            self_: *mut whiteout_M2WaterfallData,
15468        ) -> f32;
15469        pub fn whiteout_m2_M2WaterfallData_set_value0_x(
15470            self_: *mut whiteout_M2WaterfallData,
15471            value: f32,
15472        );
15473        pub fn whiteout_m2_M2WaterfallData_get_value0_y(
15474            self_: *mut whiteout_M2WaterfallData,
15475        ) -> f32;
15476        pub fn whiteout_m2_M2WaterfallData_set_value0_y(
15477            self_: *mut whiteout_M2WaterfallData,
15478            value: f32,
15479        );
15480        pub fn whiteout_m2_M2WaterfallData_get_value0_z(
15481            self_: *mut whiteout_M2WaterfallData,
15482        ) -> f32;
15483        pub fn whiteout_m2_M2WaterfallData_set_value0_z(
15484            self_: *mut whiteout_M2WaterfallData,
15485            value: f32,
15486        );
15487        pub fn whiteout_m2_M2WaterfallData_get_value1_w(
15488            self_: *mut whiteout_M2WaterfallData,
15489        ) -> f32;
15490        pub fn whiteout_m2_M2WaterfallData_set_value1_w(
15491            self_: *mut whiteout_M2WaterfallData,
15492            value: f32,
15493        );
15494        pub fn whiteout_m2_M2WaterfallData_get_value0_w(
15495            self_: *mut whiteout_M2WaterfallData,
15496        ) -> f32;
15497        pub fn whiteout_m2_M2WaterfallData_set_value0_w(
15498            self_: *mut whiteout_M2WaterfallData,
15499            value: f32,
15500        );
15501        pub fn whiteout_m2_M2WaterfallData_get_value1_x(
15502            self_: *mut whiteout_M2WaterfallData,
15503        ) -> f32;
15504        pub fn whiteout_m2_M2WaterfallData_set_value1_x(
15505            self_: *mut whiteout_M2WaterfallData,
15506            value: f32,
15507        );
15508        pub fn whiteout_m2_M2WaterfallData_get_value1_y(
15509            self_: *mut whiteout_M2WaterfallData,
15510        ) -> f32;
15511        pub fn whiteout_m2_M2WaterfallData_set_value1_y(
15512            self_: *mut whiteout_M2WaterfallData,
15513            value: f32,
15514        );
15515        pub fn whiteout_m2_M2WaterfallData_get_value2_w(
15516            self_: *mut whiteout_M2WaterfallData,
15517        ) -> f32;
15518        pub fn whiteout_m2_M2WaterfallData_set_value2_w(
15519            self_: *mut whiteout_M2WaterfallData,
15520            value: f32,
15521        );
15522        pub fn whiteout_m2_M2WaterfallData_get_value3_y(
15523            self_: *mut whiteout_M2WaterfallData,
15524        ) -> f32;
15525        pub fn whiteout_m2_M2WaterfallData_set_value3_y(
15526            self_: *mut whiteout_M2WaterfallData,
15527            value: f32,
15528        );
15529        pub fn whiteout_m2_M2WaterfallData_get_value3_x(
15530            self_: *mut whiteout_M2WaterfallData,
15531        ) -> f32;
15532        pub fn whiteout_m2_M2WaterfallData_set_value3_x(
15533            self_: *mut whiteout_M2WaterfallData,
15534            value: f32,
15535        );
15536        pub fn whiteout_m2_M2WaterfallData_get_baseColor(
15537            self_: *mut whiteout_M2WaterfallData,
15538        ) -> *mut core::ffi::c_void;
15539        pub fn whiteout_m2_M2WaterfallData_set_baseColor(
15540            self_: *mut whiteout_M2WaterfallData,
15541            value: *const core::ffi::c_void,
15542        );
15543        pub fn whiteout_m2_M2WaterfallData_get_flags(self_: *mut whiteout_M2WaterfallData) -> u16;
15544        pub fn whiteout_m2_M2WaterfallData_set_flags(
15545            self_: *mut whiteout_M2WaterfallData,
15546            value: u16,
15547        );
15548        pub fn whiteout_m2_M2WaterfallData_get_unknown0(
15549            self_: *mut whiteout_M2WaterfallData,
15550        ) -> u16;
15551        pub fn whiteout_m2_M2WaterfallData_set_unknown0(
15552            self_: *mut whiteout_M2WaterfallData,
15553            value: u16,
15554        );
15555        pub fn whiteout_m2_M2WaterfallData_get_value3_w(
15556            self_: *mut whiteout_M2WaterfallData,
15557        ) -> f32;
15558        pub fn whiteout_m2_M2WaterfallData_set_value3_w(
15559            self_: *mut whiteout_M2WaterfallData,
15560            value: f32,
15561        );
15562        pub fn whiteout_m2_M2WaterfallData_get_value3_z(
15563            self_: *mut whiteout_M2WaterfallData,
15564        ) -> f32;
15565        pub fn whiteout_m2_M2WaterfallData_set_value3_z(
15566            self_: *mut whiteout_M2WaterfallData,
15567            value: f32,
15568        );
15569        pub fn whiteout_m2_M2WaterfallData_get_value4_y(
15570            self_: *mut whiteout_M2WaterfallData,
15571        ) -> f32;
15572        pub fn whiteout_m2_M2WaterfallData_set_value4_y(
15573            self_: *mut whiteout_M2WaterfallData,
15574            value: f32,
15575        );
15576        pub fn whiteout_m2_M2WaterfallData_get_unknown1(
15577            self_: *mut whiteout_M2WaterfallData,
15578        ) -> f32;
15579        pub fn whiteout_m2_M2WaterfallData_set_unknown1(
15580            self_: *mut whiteout_M2WaterfallData,
15581            value: f32,
15582        );
15583        pub fn whiteout_m2_M2WaterfallData_get_unknown2(
15584            self_: *mut whiteout_M2WaterfallData,
15585        ) -> f32;
15586        pub fn whiteout_m2_M2WaterfallData_set_unknown2(
15587            self_: *mut whiteout_M2WaterfallData,
15588            value: f32,
15589        );
15590        pub fn whiteout_m2_M2WaterfallData_get_unknown3(
15591            self_: *mut whiteout_M2WaterfallData,
15592        ) -> f32;
15593        pub fn whiteout_m2_M2WaterfallData_set_unknown3(
15594            self_: *mut whiteout_M2WaterfallData,
15595            value: f32,
15596        );
15597        pub fn whiteout_m2_M2WaterfallData_get_unknown4(
15598            self_: *mut whiteout_M2WaterfallData,
15599        ) -> f32;
15600        pub fn whiteout_m2_M2WaterfallData_set_unknown4(
15601            self_: *mut whiteout_M2WaterfallData,
15602            value: f32,
15603        );
15604        // ParticleGeosetData
15605        pub fn whiteout_m2_M2ParticleGeosetData_new() -> *mut whiteout_M2ParticleGeosetData;
15606        pub fn whiteout_m2_M2ParticleGeosetData_delete(self_: *mut whiteout_M2ParticleGeosetData);
15607        pub fn whiteout_m2_M2ParticleGeosetData_get_geoset(
15608            self_: *mut whiteout_M2ParticleGeosetData,
15609        ) -> u16;
15610        pub fn whiteout_m2_M2ParticleGeosetData_set_geoset(
15611            self_: *mut whiteout_M2ParticleGeosetData,
15612            value: u16,
15613        );
15614        // EdgeFadeData
15615        pub fn whiteout_m2_M2EdgeFadeData_new() -> *mut whiteout_M2EdgeFadeData;
15616        pub fn whiteout_m2_M2EdgeFadeData_delete(self_: *mut whiteout_M2EdgeFadeData);
15617        pub fn whiteout_m2_M2EdgeFadeData_value0_size() -> usize;
15618        pub fn whiteout_m2_M2EdgeFadeData_get_value0_at(
15619            self_: *mut whiteout_M2EdgeFadeData,
15620            index: usize,
15621        ) -> f32;
15622        pub fn whiteout_m2_M2EdgeFadeData_set_value0_at(
15623            self_: *mut whiteout_M2EdgeFadeData,
15624            index: usize,
15625            value: f32,
15626        );
15627        pub fn whiteout_m2_M2EdgeFadeData_get_value8(self_: *mut whiteout_M2EdgeFadeData) -> f32;
15628        pub fn whiteout_m2_M2EdgeFadeData_set_value8(
15629            self_: *mut whiteout_M2EdgeFadeData,
15630            value: f32,
15631        );
15632        pub fn whiteout_m2_M2EdgeFadeData_valueC_size() -> usize;
15633        pub fn whiteout_m2_M2EdgeFadeData_get_valueC_at(
15634            self_: *mut whiteout_M2EdgeFadeData,
15635            index: usize,
15636        ) -> u8;
15637        pub fn whiteout_m2_M2EdgeFadeData_set_valueC_at(
15638            self_: *mut whiteout_M2EdgeFadeData,
15639            index: usize,
15640            value: u8,
15641        );
15642        // DistanceFadeData
15643        pub fn whiteout_m2_M2DistanceFadeData_new() -> *mut whiteout_M2DistanceFadeData;
15644        pub fn whiteout_m2_M2DistanceFadeData_delete(self_: *mut whiteout_M2DistanceFadeData);
15645        pub fn whiteout_m2_M2DistanceFadeData_get_squaredFarDist(
15646            self_: *mut whiteout_M2DistanceFadeData,
15647        ) -> f32;
15648        pub fn whiteout_m2_M2DistanceFadeData_set_squaredFarDist(
15649            self_: *mut whiteout_M2DistanceFadeData,
15650            value: f32,
15651        );
15652        pub fn whiteout_m2_M2DistanceFadeData_get_squaredNearDist(
15653            self_: *mut whiteout_M2DistanceFadeData,
15654        ) -> f32;
15655        pub fn whiteout_m2_M2DistanceFadeData_set_squaredNearDist(
15656            self_: *mut whiteout_M2DistanceFadeData,
15657            value: f32,
15658        );
15659        pub fn whiteout_m2_M2DistanceFadeData_reserved_size() -> usize;
15660        pub fn whiteout_m2_M2DistanceFadeData_get_reserved_at(
15661            self_: *mut whiteout_M2DistanceFadeData,
15662            index: usize,
15663        ) -> u32;
15664        pub fn whiteout_m2_M2DistanceFadeData_set_reserved_at(
15665            self_: *mut whiteout_M2DistanceFadeData,
15666            index: usize,
15667            value: u32,
15668        );
15669        // DetailedLightData
15670        pub fn whiteout_m2_M2DetailedLightData_new() -> *mut whiteout_M2DetailedLightData;
15671        pub fn whiteout_m2_M2DetailedLightData_delete(self_: *mut whiteout_M2DetailedLightData);
15672        pub fn whiteout_m2_M2DetailedLightData_get_flags(
15673            self_: *mut whiteout_M2DetailedLightData,
15674        ) -> u16;
15675        pub fn whiteout_m2_M2DetailedLightData_set_flags(
15676            self_: *mut whiteout_M2DetailedLightData,
15677            value: u16,
15678        );
15679        pub fn whiteout_m2_M2DetailedLightData_get_unknown0(
15680            self_: *mut whiteout_M2DetailedLightData,
15681        ) -> u16;
15682        pub fn whiteout_m2_M2DetailedLightData_set_unknown0(
15683            self_: *mut whiteout_M2DetailedLightData,
15684            value: u16,
15685        );
15686        pub fn whiteout_m2_M2DetailedLightData_get_unknown1(
15687            self_: *mut whiteout_M2DetailedLightData,
15688        ) -> u32;
15689        pub fn whiteout_m2_M2DetailedLightData_set_unknown1(
15690            self_: *mut whiteout_M2DetailedLightData,
15691            value: u32,
15692        );
15693        // DebugOcclusionData
15694        pub fn whiteout_m2_M2DebugOcclusionData_new() -> *mut whiteout_M2DebugOcclusionData;
15695        pub fn whiteout_m2_M2DebugOcclusionData_delete(self_: *mut whiteout_M2DebugOcclusionData);
15696        pub fn whiteout_m2_M2DebugOcclusionData_get_unknown1_1(
15697            self_: *mut whiteout_M2DebugOcclusionData,
15698        ) -> f32;
15699        pub fn whiteout_m2_M2DebugOcclusionData_set_unknown1_1(
15700            self_: *mut whiteout_M2DebugOcclusionData,
15701            value: f32,
15702        );
15703        pub fn whiteout_m2_M2DebugOcclusionData_get_unknown1_2(
15704            self_: *mut whiteout_M2DebugOcclusionData,
15705        ) -> f32;
15706        pub fn whiteout_m2_M2DebugOcclusionData_set_unknown1_2(
15707            self_: *mut whiteout_M2DebugOcclusionData,
15708            value: f32,
15709        );
15710        pub fn whiteout_m2_M2DebugOcclusionData_get_unknown1_3(
15711            self_: *mut whiteout_M2DebugOcclusionData,
15712        ) -> u32;
15713        pub fn whiteout_m2_M2DebugOcclusionData_set_unknown1_3(
15714            self_: *mut whiteout_M2DebugOcclusionData,
15715            value: u32,
15716        );
15717        pub fn whiteout_m2_M2DebugOcclusionData_get_unknown1_4(
15718            self_: *mut whiteout_M2DebugOcclusionData,
15719        ) -> u32;
15720        pub fn whiteout_m2_M2DebugOcclusionData_set_unknown1_4(
15721            self_: *mut whiteout_M2DebugOcclusionData,
15722            value: u32,
15723        );
15724        // TexturedLightData
15725        pub fn whiteout_m2_M2TexturedLightData_new() -> *mut whiteout_M2TexturedLightData;
15726        pub fn whiteout_m2_M2TexturedLightData_delete(self_: *mut whiteout_M2TexturedLightData);
15727        pub fn whiteout_m2_M2TexturedLightData_get_unknown0(
15728            self_: *mut whiteout_M2TexturedLightData,
15729        ) -> f32;
15730        pub fn whiteout_m2_M2TexturedLightData_set_unknown0(
15731            self_: *mut whiteout_M2TexturedLightData,
15732            value: f32,
15733        );
15734        pub fn whiteout_m2_M2TexturedLightData_get_unknown1(
15735            self_: *mut whiteout_M2TexturedLightData,
15736        ) -> f32;
15737        pub fn whiteout_m2_M2TexturedLightData_set_unknown1(
15738            self_: *mut whiteout_M2TexturedLightData,
15739            value: f32,
15740        );
15741        pub fn whiteout_m2_M2TexturedLightData_get_textureLookup(
15742            self_: *mut whiteout_M2TexturedLightData,
15743        ) -> i32;
15744        pub fn whiteout_m2_M2TexturedLightData_set_textureLookup(
15745            self_: *mut whiteout_M2TexturedLightData,
15746            value: i32,
15747        );
15748        pub fn whiteout_m2_M2TexturedLightData_get_unknown2(
15749            self_: *mut whiteout_M2TexturedLightData,
15750        ) -> i32;
15751        pub fn whiteout_m2_M2TexturedLightData_set_unknown2(
15752            self_: *mut whiteout_M2TexturedLightData,
15753            value: i32,
15754        );
15755        // PivotDisplacementData
15756        pub fn whiteout_m2_M2PivotDisplacementData_new() -> *mut whiteout_M2PivotDisplacementData;
15757        pub fn whiteout_m2_M2PivotDisplacementData_delete(
15758            self_: *mut whiteout_M2PivotDisplacementData,
15759        );
15760        pub fn whiteout_m2_M2PivotDisplacementData_get_offset(
15761            self_: *mut whiteout_M2PivotDisplacementData,
15762        ) -> *mut core::ffi::c_void;
15763        pub fn whiteout_m2_M2PivotDisplacementData_set_offset(
15764            self_: *mut whiteout_M2PivotDisplacementData,
15765            value: *const core::ffi::c_void,
15766        );
15767        pub fn whiteout_m2_M2PivotDisplacementData_get_flags(
15768            self_: *mut whiteout_M2PivotDisplacementData,
15769        ) -> u32;
15770        pub fn whiteout_m2_M2PivotDisplacementData_set_flags(
15771            self_: *mut whiteout_M2PivotDisplacementData,
15772            value: u32,
15773        );
15774        pub fn whiteout_m2_M2PivotDisplacementData_reserved_size() -> usize;
15775        pub fn whiteout_m2_M2PivotDisplacementData_get_reserved_at(
15776            self_: *mut whiteout_M2PivotDisplacementData,
15777            index: usize,
15778        ) -> u32;
15779        pub fn whiteout_m2_M2PivotDisplacementData_set_reserved_at(
15780            self_: *mut whiteout_M2PivotDisplacementData,
15781            index: usize,
15782            value: u32,
15783        );
15784        // PhysicsCollision
15785        pub fn whiteout_m2_M2PhysicsCollision_new() -> *mut whiteout_M2PhysicsCollision;
15786        pub fn whiteout_m2_M2PhysicsCollision_delete(self_: *mut whiteout_M2PhysicsCollision);
15787        pub fn whiteout_m2_M2PhysicsCollision_get_vertexPositions_count(
15788            self_: *mut whiteout_M2PhysicsCollision,
15789        ) -> usize;
15790        pub fn whiteout_m2_M2PhysicsCollision_resize_vertexPositions(
15791            self_: *mut whiteout_M2PhysicsCollision,
15792            count: usize,
15793        );
15794        pub fn whiteout_m2_M2PhysicsCollision_get_vertexPositions_data(
15795            self_: *mut whiteout_M2PhysicsCollision,
15796        ) -> *const f32;
15797        pub fn whiteout_m2_M2PhysicsCollision_assign_vertexPositions(
15798            self_: *mut whiteout_M2PhysicsCollision,
15799            data: *const f32,
15800            count: usize,
15801        );
15802        pub fn whiteout_m2_M2PhysicsCollision_get_faceNormals_count(
15803            self_: *mut whiteout_M2PhysicsCollision,
15804        ) -> usize;
15805        pub fn whiteout_m2_M2PhysicsCollision_resize_faceNormals(
15806            self_: *mut whiteout_M2PhysicsCollision,
15807            count: usize,
15808        );
15809        pub fn whiteout_m2_M2PhysicsCollision_get_faceNormals_data(
15810            self_: *mut whiteout_M2PhysicsCollision,
15811        ) -> *const f32;
15812        pub fn whiteout_m2_M2PhysicsCollision_assign_faceNormals(
15813            self_: *mut whiteout_M2PhysicsCollision,
15814            data: *const f32,
15815            count: usize,
15816        );
15817        pub fn whiteout_m2_M2PhysicsCollision_get_indices_count(
15818            self_: *mut whiteout_M2PhysicsCollision,
15819        ) -> usize;
15820        pub fn whiteout_m2_M2PhysicsCollision_resize_indices(
15821            self_: *mut whiteout_M2PhysicsCollision,
15822            count: usize,
15823        );
15824        pub fn whiteout_m2_M2PhysicsCollision_get_indices_data(
15825            self_: *mut whiteout_M2PhysicsCollision,
15826        ) -> *const i16;
15827        pub fn whiteout_m2_M2PhysicsCollision_assign_indices(
15828            self_: *mut whiteout_M2PhysicsCollision,
15829            data: *const i16,
15830            count: usize,
15831        );
15832        pub fn whiteout_m2_M2PhysicsCollision_get_flags_count(
15833            self_: *mut whiteout_M2PhysicsCollision,
15834        ) -> usize;
15835        pub fn whiteout_m2_M2PhysicsCollision_resize_flags(
15836            self_: *mut whiteout_M2PhysicsCollision,
15837            count: usize,
15838        );
15839        pub fn whiteout_m2_M2PhysicsCollision_get_flags_data(
15840            self_: *mut whiteout_M2PhysicsCollision,
15841        ) -> *const i16;
15842        pub fn whiteout_m2_M2PhysicsCollision_assign_flags(
15843            self_: *mut whiteout_M2PhysicsCollision,
15844            data: *const i16,
15845            count: usize,
15846        );
15847        // SkinSection
15848        pub fn whiteout_m2_M2SkinSection_new() -> *mut whiteout_M2SkinSection;
15849        pub fn whiteout_m2_M2SkinSection_delete(self_: *mut whiteout_M2SkinSection);
15850        pub fn whiteout_m2_M2SkinSection_get_skinSectionId(
15851            self_: *mut whiteout_M2SkinSection,
15852        ) -> u16;
15853        pub fn whiteout_m2_M2SkinSection_set_skinSectionId(
15854            self_: *mut whiteout_M2SkinSection,
15855            value: u16,
15856        );
15857        pub fn whiteout_m2_M2SkinSection_get_level(self_: *mut whiteout_M2SkinSection) -> u16;
15858        pub fn whiteout_m2_M2SkinSection_set_level(self_: *mut whiteout_M2SkinSection, value: u16);
15859        pub fn whiteout_m2_M2SkinSection_get_vertexStart(self_: *mut whiteout_M2SkinSection)
15860            -> u16;
15861        pub fn whiteout_m2_M2SkinSection_set_vertexStart(
15862            self_: *mut whiteout_M2SkinSection,
15863            value: u16,
15864        );
15865        pub fn whiteout_m2_M2SkinSection_get_vertexCount(self_: *mut whiteout_M2SkinSection)
15866            -> u16;
15867        pub fn whiteout_m2_M2SkinSection_set_vertexCount(
15868            self_: *mut whiteout_M2SkinSection,
15869            value: u16,
15870        );
15871        pub fn whiteout_m2_M2SkinSection_get_indexStart(self_: *mut whiteout_M2SkinSection) -> u16;
15872        pub fn whiteout_m2_M2SkinSection_set_indexStart(
15873            self_: *mut whiteout_M2SkinSection,
15874            value: u16,
15875        );
15876        pub fn whiteout_m2_M2SkinSection_get_indexCount(self_: *mut whiteout_M2SkinSection) -> u16;
15877        pub fn whiteout_m2_M2SkinSection_set_indexCount(
15878            self_: *mut whiteout_M2SkinSection,
15879            value: u16,
15880        );
15881        pub fn whiteout_m2_M2SkinSection_get_boneCount(self_: *mut whiteout_M2SkinSection) -> u16;
15882        pub fn whiteout_m2_M2SkinSection_set_boneCount(
15883            self_: *mut whiteout_M2SkinSection,
15884            value: u16,
15885        );
15886        pub fn whiteout_m2_M2SkinSection_get_boneComboIndex(
15887            self_: *mut whiteout_M2SkinSection,
15888        ) -> u16;
15889        pub fn whiteout_m2_M2SkinSection_set_boneComboIndex(
15890            self_: *mut whiteout_M2SkinSection,
15891            value: u16,
15892        );
15893        pub fn whiteout_m2_M2SkinSection_get_boneInfluences(
15894            self_: *mut whiteout_M2SkinSection,
15895        ) -> u16;
15896        pub fn whiteout_m2_M2SkinSection_set_boneInfluences(
15897            self_: *mut whiteout_M2SkinSection,
15898            value: u16,
15899        );
15900        pub fn whiteout_m2_M2SkinSection_get_centerBoneIndex(
15901            self_: *mut whiteout_M2SkinSection,
15902        ) -> u16;
15903        pub fn whiteout_m2_M2SkinSection_set_centerBoneIndex(
15904            self_: *mut whiteout_M2SkinSection,
15905            value: u16,
15906        );
15907        pub fn whiteout_m2_M2SkinSection_get_centerPosition(
15908            self_: *mut whiteout_M2SkinSection,
15909        ) -> *mut core::ffi::c_void;
15910        pub fn whiteout_m2_M2SkinSection_set_centerPosition(
15911            self_: *mut whiteout_M2SkinSection,
15912            value: *const core::ffi::c_void,
15913        );
15914        pub fn whiteout_m2_M2SkinSection_get_sortCenterPosition(
15915            self_: *mut whiteout_M2SkinSection,
15916        ) -> *mut core::ffi::c_void;
15917        pub fn whiteout_m2_M2SkinSection_set_sortCenterPosition(
15918            self_: *mut whiteout_M2SkinSection,
15919            value: *const core::ffi::c_void,
15920        );
15921        pub fn whiteout_m2_M2SkinSection_get_sortRadius(self_: *mut whiteout_M2SkinSection) -> f32;
15922        pub fn whiteout_m2_M2SkinSection_set_sortRadius(
15923            self_: *mut whiteout_M2SkinSection,
15924            value: f32,
15925        );
15926        // Batch
15927        pub fn whiteout_m2_M2Batch_new() -> *mut whiteout_M2Batch;
15928        pub fn whiteout_m2_M2Batch_delete(self_: *mut whiteout_M2Batch);
15929        pub fn whiteout_m2_M2Batch_get_flags(self_: *mut whiteout_M2Batch) -> u8;
15930        pub fn whiteout_m2_M2Batch_set_flags(self_: *mut whiteout_M2Batch, value: u8);
15931        pub fn whiteout_m2_M2Batch_get_priorityPlane(self_: *mut whiteout_M2Batch) -> i8;
15932        pub fn whiteout_m2_M2Batch_set_priorityPlane(self_: *mut whiteout_M2Batch, value: i8);
15933        pub fn whiteout_m2_M2Batch_get_shaderId(self_: *mut whiteout_M2Batch) -> u16;
15934        pub fn whiteout_m2_M2Batch_set_shaderId(self_: *mut whiteout_M2Batch, value: u16);
15935        pub fn whiteout_m2_M2Batch_get_skinSectionIndex(self_: *mut whiteout_M2Batch) -> u16;
15936        pub fn whiteout_m2_M2Batch_set_skinSectionIndex(self_: *mut whiteout_M2Batch, value: u16);
15937        pub fn whiteout_m2_M2Batch_get_geosetIndex(self_: *mut whiteout_M2Batch) -> u16;
15938        pub fn whiteout_m2_M2Batch_set_geosetIndex(self_: *mut whiteout_M2Batch, value: u16);
15939        pub fn whiteout_m2_M2Batch_get_colorIndex(self_: *mut whiteout_M2Batch) -> i16;
15940        pub fn whiteout_m2_M2Batch_set_colorIndex(self_: *mut whiteout_M2Batch, value: i16);
15941        pub fn whiteout_m2_M2Batch_get_materialIndex(self_: *mut whiteout_M2Batch) -> u16;
15942        pub fn whiteout_m2_M2Batch_set_materialIndex(self_: *mut whiteout_M2Batch, value: u16);
15943        pub fn whiteout_m2_M2Batch_get_materialLayer(self_: *mut whiteout_M2Batch) -> u16;
15944        pub fn whiteout_m2_M2Batch_set_materialLayer(self_: *mut whiteout_M2Batch, value: u16);
15945        pub fn whiteout_m2_M2Batch_get_textureCount(self_: *mut whiteout_M2Batch) -> u16;
15946        pub fn whiteout_m2_M2Batch_set_textureCount(self_: *mut whiteout_M2Batch, value: u16);
15947        pub fn whiteout_m2_M2Batch_get_textureComboIndex(self_: *mut whiteout_M2Batch) -> u16;
15948        pub fn whiteout_m2_M2Batch_set_textureComboIndex(self_: *mut whiteout_M2Batch, value: u16);
15949        pub fn whiteout_m2_M2Batch_get_textureCoordComboIndex(self_: *mut whiteout_M2Batch) -> u16;
15950        pub fn whiteout_m2_M2Batch_set_textureCoordComboIndex(
15951            self_: *mut whiteout_M2Batch,
15952            value: u16,
15953        );
15954        pub fn whiteout_m2_M2Batch_get_textureWeightComboIndex(self_: *mut whiteout_M2Batch)
15955            -> u16;
15956        pub fn whiteout_m2_M2Batch_set_textureWeightComboIndex(
15957            self_: *mut whiteout_M2Batch,
15958            value: u16,
15959        );
15960        pub fn whiteout_m2_M2Batch_get_textureTransformComboIndex(
15961            self_: *mut whiteout_M2Batch,
15962        ) -> u16;
15963        pub fn whiteout_m2_M2Batch_set_textureTransformComboIndex(
15964            self_: *mut whiteout_M2Batch,
15965            value: u16,
15966        );
15967        // ShadowBatch
15968        pub fn whiteout_m2_M2ShadowBatch_new() -> *mut whiteout_M2ShadowBatch;
15969        pub fn whiteout_m2_M2ShadowBatch_delete(self_: *mut whiteout_M2ShadowBatch);
15970        pub fn whiteout_m2_M2ShadowBatch_get_flags(self_: *mut whiteout_M2ShadowBatch) -> u8;
15971        pub fn whiteout_m2_M2ShadowBatch_set_flags(self_: *mut whiteout_M2ShadowBatch, value: u8);
15972        pub fn whiteout_m2_M2ShadowBatch_get_flags2(self_: *mut whiteout_M2ShadowBatch) -> u8;
15973        pub fn whiteout_m2_M2ShadowBatch_set_flags2(self_: *mut whiteout_M2ShadowBatch, value: u8);
15974        pub fn whiteout_m2_M2ShadowBatch_get_unknown0(self_: *mut whiteout_M2ShadowBatch) -> u16;
15975        pub fn whiteout_m2_M2ShadowBatch_set_unknown0(
15976            self_: *mut whiteout_M2ShadowBatch,
15977            value: u16,
15978        );
15979        pub fn whiteout_m2_M2ShadowBatch_get_submeshId(self_: *mut whiteout_M2ShadowBatch) -> u16;
15980        pub fn whiteout_m2_M2ShadowBatch_set_submeshId(
15981            self_: *mut whiteout_M2ShadowBatch,
15982            value: u16,
15983        );
15984        pub fn whiteout_m2_M2ShadowBatch_get_textureId(self_: *mut whiteout_M2ShadowBatch) -> u16;
15985        pub fn whiteout_m2_M2ShadowBatch_set_textureId(
15986            self_: *mut whiteout_M2ShadowBatch,
15987            value: u16,
15988        );
15989        pub fn whiteout_m2_M2ShadowBatch_get_colorId(self_: *mut whiteout_M2ShadowBatch) -> u16;
15990        pub fn whiteout_m2_M2ShadowBatch_set_colorId(
15991            self_: *mut whiteout_M2ShadowBatch,
15992            value: u16,
15993        );
15994        pub fn whiteout_m2_M2ShadowBatch_get_transparencyId(
15995            self_: *mut whiteout_M2ShadowBatch,
15996        ) -> u16;
15997        pub fn whiteout_m2_M2ShadowBatch_set_transparencyId(
15998            self_: *mut whiteout_M2ShadowBatch,
15999            value: u16,
16000        );
16001        // SkinProfile
16002        pub fn whiteout_m2_M2SkinProfile_new() -> *mut whiteout_M2SkinProfile;
16003        pub fn whiteout_m2_M2SkinProfile_delete(self_: *mut whiteout_M2SkinProfile);
16004        pub fn whiteout_m2_M2SkinProfile_get_vertices_count(
16005            self_: *mut whiteout_M2SkinProfile,
16006        ) -> usize;
16007        pub fn whiteout_m2_M2SkinProfile_resize_vertices(
16008            self_: *mut whiteout_M2SkinProfile,
16009            count: usize,
16010        );
16011        pub fn whiteout_m2_M2SkinProfile_get_vertices_data(
16012            self_: *mut whiteout_M2SkinProfile,
16013        ) -> *const u16;
16014        pub fn whiteout_m2_M2SkinProfile_assign_vertices(
16015            self_: *mut whiteout_M2SkinProfile,
16016            data: *const u16,
16017            count: usize,
16018        );
16019        pub fn whiteout_m2_M2SkinProfile_get_indices_count(
16020            self_: *mut whiteout_M2SkinProfile,
16021        ) -> usize;
16022        pub fn whiteout_m2_M2SkinProfile_resize_indices(
16023            self_: *mut whiteout_M2SkinProfile,
16024            count: usize,
16025        );
16026        pub fn whiteout_m2_M2SkinProfile_get_indices_data(
16027            self_: *mut whiteout_M2SkinProfile,
16028        ) -> *const u16;
16029        pub fn whiteout_m2_M2SkinProfile_assign_indices(
16030            self_: *mut whiteout_M2SkinProfile,
16031            data: *const u16,
16032            count: usize,
16033        );
16034        pub fn whiteout_m2_M2SkinProfile_get_submeshes_count(
16035            self_: *mut whiteout_M2SkinProfile,
16036        ) -> usize;
16037        pub fn whiteout_m2_M2SkinProfile_resize_submeshes(
16038            self_: *mut whiteout_M2SkinProfile,
16039            count: usize,
16040        );
16041        pub fn whiteout_m2_M2SkinProfile_get_submeshes_at(
16042            self_: *mut whiteout_M2SkinProfile,
16043            index: usize,
16044        ) -> *mut whiteout_M2SkinSection;
16045        pub fn whiteout_m2_M2SkinProfile_get_batches_count(
16046            self_: *mut whiteout_M2SkinProfile,
16047        ) -> usize;
16048        pub fn whiteout_m2_M2SkinProfile_resize_batches(
16049            self_: *mut whiteout_M2SkinProfile,
16050            count: usize,
16051        );
16052        pub fn whiteout_m2_M2SkinProfile_get_batches_at(
16053            self_: *mut whiteout_M2SkinProfile,
16054            index: usize,
16055        ) -> *mut whiteout_M2Batch;
16056        pub fn whiteout_m2_M2SkinProfile_get_lodVertexBase(
16057            self_: *mut whiteout_M2SkinProfile,
16058        ) -> u32;
16059        pub fn whiteout_m2_M2SkinProfile_set_lodVertexBase(
16060            self_: *mut whiteout_M2SkinProfile,
16061            value: u32,
16062        );
16063        pub fn whiteout_m2_M2SkinProfile_get_shadowBatches_count(
16064            self_: *mut whiteout_M2SkinProfile,
16065        ) -> usize;
16066        pub fn whiteout_m2_M2SkinProfile_resize_shadowBatches(
16067            self_: *mut whiteout_M2SkinProfile,
16068            count: usize,
16069        );
16070        pub fn whiteout_m2_M2SkinProfile_get_shadowBatches_at(
16071            self_: *mut whiteout_M2SkinProfile,
16072            index: usize,
16073        ) -> *mut whiteout_M2ShadowBatch;
16074        // GlobalFlags
16075        pub fn whiteout_m2_M2GlobalFlags_new() -> *mut whiteout_M2GlobalFlags;
16076        pub fn whiteout_m2_M2GlobalFlags_delete(self_: *mut whiteout_M2GlobalFlags);
16077        pub fn whiteout_m2_M2GlobalFlags_get_value(self_: *mut whiteout_M2GlobalFlags) -> i32;
16078        pub fn whiteout_m2_M2GlobalFlags_set_value(self_: *mut whiteout_M2GlobalFlags, value: i32);
16079        // GlobalSequence
16080        pub fn whiteout_m2_M2GlobalSequence_new() -> *mut whiteout_M2GlobalSequence;
16081        pub fn whiteout_m2_M2GlobalSequence_delete(self_: *mut whiteout_M2GlobalSequence);
16082        pub fn whiteout_m2_M2GlobalSequence_get_timestamp(
16083            self_: *mut whiteout_M2GlobalSequence,
16084        ) -> u32;
16085        pub fn whiteout_m2_M2GlobalSequence_set_timestamp(
16086            self_: *mut whiteout_M2GlobalSequence,
16087            value: u32,
16088        );
16089        // Sequence
16090        pub fn whiteout_m2_M2Sequence_new() -> *mut whiteout_M2Sequence;
16091        pub fn whiteout_m2_M2Sequence_delete(self_: *mut whiteout_M2Sequence);
16092        pub fn whiteout_m2_M2Sequence_get_id(self_: *mut whiteout_M2Sequence) -> u16;
16093        pub fn whiteout_m2_M2Sequence_set_id(self_: *mut whiteout_M2Sequence, value: u16);
16094        pub fn whiteout_m2_M2Sequence_get_variationIndex(self_: *mut whiteout_M2Sequence) -> u16;
16095        pub fn whiteout_m2_M2Sequence_set_variationIndex(
16096            self_: *mut whiteout_M2Sequence,
16097            value: u16,
16098        );
16099        pub fn whiteout_m2_M2Sequence_get_duration(self_: *mut whiteout_M2Sequence) -> u32;
16100        pub fn whiteout_m2_M2Sequence_set_duration(self_: *mut whiteout_M2Sequence, value: u32);
16101        pub fn whiteout_m2_M2Sequence_get_movespeed(self_: *mut whiteout_M2Sequence) -> f32;
16102        pub fn whiteout_m2_M2Sequence_set_movespeed(self_: *mut whiteout_M2Sequence, value: f32);
16103        pub fn whiteout_m2_M2Sequence_get_flags(self_: *mut whiteout_M2Sequence) -> i32;
16104        pub fn whiteout_m2_M2Sequence_set_flags(self_: *mut whiteout_M2Sequence, value: i32);
16105        pub fn whiteout_m2_M2Sequence_get_frequency(self_: *mut whiteout_M2Sequence) -> i16;
16106        pub fn whiteout_m2_M2Sequence_set_frequency(self_: *mut whiteout_M2Sequence, value: i16);
16107        pub fn whiteout_m2_M2Sequence_get_padding(self_: *mut whiteout_M2Sequence) -> u16;
16108        pub fn whiteout_m2_M2Sequence_set_padding(self_: *mut whiteout_M2Sequence, value: u16);
16109        pub fn whiteout_m2_M2Sequence_get_replayMin(self_: *mut whiteout_M2Sequence) -> u32;
16110        pub fn whiteout_m2_M2Sequence_set_replayMin(self_: *mut whiteout_M2Sequence, value: u32);
16111        pub fn whiteout_m2_M2Sequence_get_replayMax(self_: *mut whiteout_M2Sequence) -> u32;
16112        pub fn whiteout_m2_M2Sequence_set_replayMax(self_: *mut whiteout_M2Sequence, value: u32);
16113        pub fn whiteout_m2_M2Sequence_get_blendTimeIn(self_: *mut whiteout_M2Sequence) -> u16;
16114        pub fn whiteout_m2_M2Sequence_set_blendTimeIn(self_: *mut whiteout_M2Sequence, value: u16);
16115        pub fn whiteout_m2_M2Sequence_get_blendTimeOut(self_: *mut whiteout_M2Sequence) -> u16;
16116        pub fn whiteout_m2_M2Sequence_set_blendTimeOut(self_: *mut whiteout_M2Sequence, value: u16);
16117        pub fn whiteout_m2_M2Sequence_get_bounding(
16118            self_: *mut whiteout_M2Sequence,
16119        ) -> *mut whiteout_M2Extent;
16120        pub fn whiteout_m2_M2Sequence_set_bounding(
16121            self_: *mut whiteout_M2Sequence,
16122            value: *const whiteout_M2Extent,
16123        );
16124        pub fn whiteout_m2_M2Sequence_get_variationNext(self_: *mut whiteout_M2Sequence) -> i16;
16125        pub fn whiteout_m2_M2Sequence_set_variationNext(
16126            self_: *mut whiteout_M2Sequence,
16127            value: i16,
16128        );
16129        pub fn whiteout_m2_M2Sequence_get_aliasNext(self_: *mut whiteout_M2Sequence) -> u16;
16130        pub fn whiteout_m2_M2Sequence_set_aliasNext(self_: *mut whiteout_M2Sequence, value: u16);
16131        // Vertex
16132        pub fn whiteout_m2_M2Vertex_new() -> *mut whiteout_M2Vertex;
16133        pub fn whiteout_m2_M2Vertex_delete(self_: *mut whiteout_M2Vertex);
16134        pub fn whiteout_m2_M2Vertex_get_position(
16135            self_: *mut whiteout_M2Vertex,
16136        ) -> *mut core::ffi::c_void;
16137        pub fn whiteout_m2_M2Vertex_set_position(
16138            self_: *mut whiteout_M2Vertex,
16139            value: *const core::ffi::c_void,
16140        );
16141        pub fn whiteout_m2_M2Vertex_boneWeights_size() -> usize;
16142        pub fn whiteout_m2_M2Vertex_get_boneWeights_at(
16143            self_: *mut whiteout_M2Vertex,
16144            index: usize,
16145        ) -> u8;
16146        pub fn whiteout_m2_M2Vertex_set_boneWeights_at(
16147            self_: *mut whiteout_M2Vertex,
16148            index: usize,
16149            value: u8,
16150        );
16151        pub fn whiteout_m2_M2Vertex_boneIndices_size() -> usize;
16152        pub fn whiteout_m2_M2Vertex_get_boneIndices_at(
16153            self_: *mut whiteout_M2Vertex,
16154            index: usize,
16155        ) -> u8;
16156        pub fn whiteout_m2_M2Vertex_set_boneIndices_at(
16157            self_: *mut whiteout_M2Vertex,
16158            index: usize,
16159            value: u8,
16160        );
16161        pub fn whiteout_m2_M2Vertex_get_normal(
16162            self_: *mut whiteout_M2Vertex,
16163        ) -> *mut core::ffi::c_void;
16164        pub fn whiteout_m2_M2Vertex_set_normal(
16165            self_: *mut whiteout_M2Vertex,
16166            value: *const core::ffi::c_void,
16167        );
16168        pub fn whiteout_m2_M2Vertex_texCoords_size() -> usize;
16169        pub fn whiteout_m2_M2Vertex_get_texCoords_at(
16170            self_: *mut whiteout_M2Vertex,
16171            index: usize,
16172        ) -> *mut core::ffi::c_void;
16173        // Bone
16174        pub fn whiteout_m2_M2Bone_new() -> *mut whiteout_M2Bone;
16175        pub fn whiteout_m2_M2Bone_delete(self_: *mut whiteout_M2Bone);
16176        pub fn whiteout_m2_M2Bone_get_keyBoneId(self_: *mut whiteout_M2Bone) -> i32;
16177        pub fn whiteout_m2_M2Bone_set_keyBoneId(self_: *mut whiteout_M2Bone, value: i32);
16178        pub fn whiteout_m2_M2Bone_get_flags(self_: *mut whiteout_M2Bone) -> u32;
16179        pub fn whiteout_m2_M2Bone_set_flags(self_: *mut whiteout_M2Bone, value: u32);
16180        pub fn whiteout_m2_M2Bone_get_parentBoneId(self_: *mut whiteout_M2Bone) -> i16;
16181        pub fn whiteout_m2_M2Bone_set_parentBoneId(self_: *mut whiteout_M2Bone, value: i16);
16182        pub fn whiteout_m2_M2Bone_get_submeshId(self_: *mut whiteout_M2Bone) -> u16;
16183        pub fn whiteout_m2_M2Bone_set_submeshId(self_: *mut whiteout_M2Bone, value: u16);
16184        pub fn whiteout_m2_M2Bone_get_boneNameCRC(self_: *mut whiteout_M2Bone) -> u32;
16185        pub fn whiteout_m2_M2Bone_set_boneNameCRC(self_: *mut whiteout_M2Bone, value: u32);
16186        pub fn whiteout_m2_M2Bone_get_translation(
16187            self_: *mut whiteout_M2Bone,
16188        ) -> *mut whiteout_M2AnimationTrackVector3f;
16189        pub fn whiteout_m2_M2Bone_set_translation(
16190            self_: *mut whiteout_M2Bone,
16191            value: *const whiteout_M2AnimationTrackVector3f,
16192        );
16193        pub fn whiteout_m2_M2Bone_get_rotation(
16194            self_: *mut whiteout_M2Bone,
16195        ) -> *mut whiteout_M2AnimationTrackM2CompatQuaternion;
16196        pub fn whiteout_m2_M2Bone_set_rotation(
16197            self_: *mut whiteout_M2Bone,
16198            value: *const whiteout_M2AnimationTrackM2CompatQuaternion,
16199        );
16200        pub fn whiteout_m2_M2Bone_get_scale(
16201            self_: *mut whiteout_M2Bone,
16202        ) -> *mut whiteout_M2AnimationTrackVector3f;
16203        pub fn whiteout_m2_M2Bone_set_scale(
16204            self_: *mut whiteout_M2Bone,
16205            value: *const whiteout_M2AnimationTrackVector3f,
16206        );
16207        pub fn whiteout_m2_M2Bone_get_pivot(self_: *mut whiteout_M2Bone) -> *mut core::ffi::c_void;
16208        pub fn whiteout_m2_M2Bone_set_pivot(
16209            self_: *mut whiteout_M2Bone,
16210            value: *const core::ffi::c_void,
16211        );
16212        // Texture
16213        pub fn whiteout_m2_M2Texture_new() -> *mut whiteout_M2Texture;
16214        pub fn whiteout_m2_M2Texture_delete(self_: *mut whiteout_M2Texture);
16215        pub fn whiteout_m2_M2Texture_get_type(self_: *mut whiteout_M2Texture) -> u32;
16216        pub fn whiteout_m2_M2Texture_set_type(self_: *mut whiteout_M2Texture, value: u32);
16217        pub fn whiteout_m2_M2Texture_get_flags(self_: *mut whiteout_M2Texture) -> u32;
16218        pub fn whiteout_m2_M2Texture_set_flags(self_: *mut whiteout_M2Texture, value: u32);
16219        pub fn whiteout_m2_M2Texture_get_filename(self_: *mut whiteout_M2Texture) -> RawCString;
16220        pub fn whiteout_m2_M2Texture_set_filename(
16221            self_: *mut whiteout_M2Texture,
16222            value: *const core::ffi::c_char,
16223        );
16224        // Material
16225        pub fn whiteout_m2_M2Material_new() -> *mut whiteout_M2Material;
16226        pub fn whiteout_m2_M2Material_delete(self_: *mut whiteout_M2Material);
16227        pub fn whiteout_m2_M2Material_get_flags(self_: *mut whiteout_M2Material) -> u16;
16228        pub fn whiteout_m2_M2Material_set_flags(self_: *mut whiteout_M2Material, value: u16);
16229        pub fn whiteout_m2_M2Material_get_blendingMode(self_: *mut whiteout_M2Material) -> u16;
16230        pub fn whiteout_m2_M2Material_set_blendingMode(self_: *mut whiteout_M2Material, value: u16);
16231        // TextureWeight
16232        pub fn whiteout_m2_M2TextureWeight_new() -> *mut whiteout_M2TextureWeight;
16233        pub fn whiteout_m2_M2TextureWeight_delete(self_: *mut whiteout_M2TextureWeight);
16234        pub fn whiteout_m2_M2TextureWeight_get_weight(
16235            self_: *mut whiteout_M2TextureWeight,
16236        ) -> *mut whiteout_M2AnimationTrackI16;
16237        pub fn whiteout_m2_M2TextureWeight_set_weight(
16238            self_: *mut whiteout_M2TextureWeight,
16239            value: *const whiteout_M2AnimationTrackI16,
16240        );
16241        // TextureTransform
16242        pub fn whiteout_m2_M2TextureTransform_new() -> *mut whiteout_M2TextureTransform;
16243        pub fn whiteout_m2_M2TextureTransform_delete(self_: *mut whiteout_M2TextureTransform);
16244        pub fn whiteout_m2_M2TextureTransform_get_translation(
16245            self_: *mut whiteout_M2TextureTransform,
16246        ) -> *mut whiteout_M2AnimationTrackVector3f;
16247        pub fn whiteout_m2_M2TextureTransform_set_translation(
16248            self_: *mut whiteout_M2TextureTransform,
16249            value: *const whiteout_M2AnimationTrackVector3f,
16250        );
16251        pub fn whiteout_m2_M2TextureTransform_get_rotation(
16252            self_: *mut whiteout_M2TextureTransform,
16253        ) -> *mut whiteout_M2AnimationTrackQuaternion;
16254        pub fn whiteout_m2_M2TextureTransform_set_rotation(
16255            self_: *mut whiteout_M2TextureTransform,
16256            value: *const whiteout_M2AnimationTrackQuaternion,
16257        );
16258        pub fn whiteout_m2_M2TextureTransform_get_scaling(
16259            self_: *mut whiteout_M2TextureTransform,
16260        ) -> *mut whiteout_M2AnimationTrackVector3f;
16261        pub fn whiteout_m2_M2TextureTransform_set_scaling(
16262            self_: *mut whiteout_M2TextureTransform,
16263            value: *const whiteout_M2AnimationTrackVector3f,
16264        );
16265        // ColorAnimation
16266        pub fn whiteout_m2_M2ColorAnimation_new() -> *mut whiteout_M2ColorAnimation;
16267        pub fn whiteout_m2_M2ColorAnimation_delete(self_: *mut whiteout_M2ColorAnimation);
16268        pub fn whiteout_m2_M2ColorAnimation_get_color(
16269            self_: *mut whiteout_M2ColorAnimation,
16270        ) -> *mut whiteout_M2AnimationTrackVector3f;
16271        pub fn whiteout_m2_M2ColorAnimation_set_color(
16272            self_: *mut whiteout_M2ColorAnimation,
16273            value: *const whiteout_M2AnimationTrackVector3f,
16274        );
16275        pub fn whiteout_m2_M2ColorAnimation_get_alpha(
16276            self_: *mut whiteout_M2ColorAnimation,
16277        ) -> *mut whiteout_M2AnimationTrackI16;
16278        pub fn whiteout_m2_M2ColorAnimation_set_alpha(
16279            self_: *mut whiteout_M2ColorAnimation,
16280            value: *const whiteout_M2AnimationTrackI16,
16281        );
16282        // Light
16283        pub fn whiteout_m2_M2Light_new() -> *mut whiteout_M2Light;
16284        pub fn whiteout_m2_M2Light_delete(self_: *mut whiteout_M2Light);
16285        pub fn whiteout_m2_M2Light_get_type(self_: *mut whiteout_M2Light) -> u16;
16286        pub fn whiteout_m2_M2Light_set_type(self_: *mut whiteout_M2Light, value: u16);
16287        pub fn whiteout_m2_M2Light_get_boneId(self_: *mut whiteout_M2Light) -> i16;
16288        pub fn whiteout_m2_M2Light_set_boneId(self_: *mut whiteout_M2Light, value: i16);
16289        pub fn whiteout_m2_M2Light_get_position(
16290            self_: *mut whiteout_M2Light,
16291        ) -> *mut core::ffi::c_void;
16292        pub fn whiteout_m2_M2Light_set_position(
16293            self_: *mut whiteout_M2Light,
16294            value: *const core::ffi::c_void,
16295        );
16296        pub fn whiteout_m2_M2Light_get_ambientColor(
16297            self_: *mut whiteout_M2Light,
16298        ) -> *mut whiteout_M2AnimationTrackVector3f;
16299        pub fn whiteout_m2_M2Light_set_ambientColor(
16300            self_: *mut whiteout_M2Light,
16301            value: *const whiteout_M2AnimationTrackVector3f,
16302        );
16303        pub fn whiteout_m2_M2Light_get_ambientIntensity(
16304            self_: *mut whiteout_M2Light,
16305        ) -> *mut whiteout_M2AnimationTrackF32;
16306        pub fn whiteout_m2_M2Light_set_ambientIntensity(
16307            self_: *mut whiteout_M2Light,
16308            value: *const whiteout_M2AnimationTrackF32,
16309        );
16310        pub fn whiteout_m2_M2Light_get_diffuseColor(
16311            self_: *mut whiteout_M2Light,
16312        ) -> *mut whiteout_M2AnimationTrackVector3f;
16313        pub fn whiteout_m2_M2Light_set_diffuseColor(
16314            self_: *mut whiteout_M2Light,
16315            value: *const whiteout_M2AnimationTrackVector3f,
16316        );
16317        pub fn whiteout_m2_M2Light_get_diffuseIntensity(
16318            self_: *mut whiteout_M2Light,
16319        ) -> *mut whiteout_M2AnimationTrackF32;
16320        pub fn whiteout_m2_M2Light_set_diffuseIntensity(
16321            self_: *mut whiteout_M2Light,
16322            value: *const whiteout_M2AnimationTrackF32,
16323        );
16324        pub fn whiteout_m2_M2Light_get_attenuationStart(
16325            self_: *mut whiteout_M2Light,
16326        ) -> *mut whiteout_M2AnimationTrackF32;
16327        pub fn whiteout_m2_M2Light_set_attenuationStart(
16328            self_: *mut whiteout_M2Light,
16329            value: *const whiteout_M2AnimationTrackF32,
16330        );
16331        pub fn whiteout_m2_M2Light_get_attenuationEnd(
16332            self_: *mut whiteout_M2Light,
16333        ) -> *mut whiteout_M2AnimationTrackF32;
16334        pub fn whiteout_m2_M2Light_set_attenuationEnd(
16335            self_: *mut whiteout_M2Light,
16336            value: *const whiteout_M2AnimationTrackF32,
16337        );
16338        pub fn whiteout_m2_M2Light_get_visibility(
16339            self_: *mut whiteout_M2Light,
16340        ) -> *mut whiteout_M2AnimationTrackU8;
16341        pub fn whiteout_m2_M2Light_set_visibility(
16342            self_: *mut whiteout_M2Light,
16343            value: *const whiteout_M2AnimationTrackU8,
16344        );
16345        // CameraSpline
16346        pub fn whiteout_m2_M2CameraSpline_new() -> *mut whiteout_M2CameraSpline;
16347        pub fn whiteout_m2_M2CameraSpline_delete(self_: *mut whiteout_M2CameraSpline);
16348        pub fn whiteout_m2_M2CameraSpline_get_value(
16349            self_: *mut whiteout_M2CameraSpline,
16350        ) -> *mut core::ffi::c_void;
16351        pub fn whiteout_m2_M2CameraSpline_set_value(
16352            self_: *mut whiteout_M2CameraSpline,
16353            value: *const core::ffi::c_void,
16354        );
16355        pub fn whiteout_m2_M2CameraSpline_get_inTangent(
16356            self_: *mut whiteout_M2CameraSpline,
16357        ) -> *mut core::ffi::c_void;
16358        pub fn whiteout_m2_M2CameraSpline_set_inTangent(
16359            self_: *mut whiteout_M2CameraSpline,
16360            value: *const core::ffi::c_void,
16361        );
16362        pub fn whiteout_m2_M2CameraSpline_get_outTangent(
16363            self_: *mut whiteout_M2CameraSpline,
16364        ) -> *mut core::ffi::c_void;
16365        pub fn whiteout_m2_M2CameraSpline_set_outTangent(
16366            self_: *mut whiteout_M2CameraSpline,
16367            value: *const core::ffi::c_void,
16368        );
16369        // Camera
16370        pub fn whiteout_m2_M2Camera_new() -> *mut whiteout_M2Camera;
16371        pub fn whiteout_m2_M2Camera_delete(self_: *mut whiteout_M2Camera);
16372        pub fn whiteout_m2_M2Camera_get_type(self_: *mut whiteout_M2Camera) -> u32;
16373        pub fn whiteout_m2_M2Camera_set_type(self_: *mut whiteout_M2Camera, value: u32);
16374        pub fn whiteout_m2_M2Camera_get_fieldOfView(self_: *mut whiteout_M2Camera) -> f32;
16375        pub fn whiteout_m2_M2Camera_set_fieldOfView(self_: *mut whiteout_M2Camera, value: f32);
16376        pub fn whiteout_m2_M2Camera_get_farClip(self_: *mut whiteout_M2Camera) -> f32;
16377        pub fn whiteout_m2_M2Camera_set_farClip(self_: *mut whiteout_M2Camera, value: f32);
16378        pub fn whiteout_m2_M2Camera_get_nearClip(self_: *mut whiteout_M2Camera) -> f32;
16379        pub fn whiteout_m2_M2Camera_set_nearClip(self_: *mut whiteout_M2Camera, value: f32);
16380        pub fn whiteout_m2_M2Camera_get_positions(
16381            self_: *mut whiteout_M2Camera,
16382        ) -> *mut whiteout_M2AnimationTrackM2CameraSpline;
16383        pub fn whiteout_m2_M2Camera_set_positions(
16384            self_: *mut whiteout_M2Camera,
16385            value: *const whiteout_M2AnimationTrackM2CameraSpline,
16386        );
16387        pub fn whiteout_m2_M2Camera_get_positionBase(
16388            self_: *mut whiteout_M2Camera,
16389        ) -> *mut core::ffi::c_void;
16390        pub fn whiteout_m2_M2Camera_set_positionBase(
16391            self_: *mut whiteout_M2Camera,
16392            value: *const core::ffi::c_void,
16393        );
16394        pub fn whiteout_m2_M2Camera_get_targetPositions(
16395            self_: *mut whiteout_M2Camera,
16396        ) -> *mut whiteout_M2AnimationTrackM2CameraSpline;
16397        pub fn whiteout_m2_M2Camera_set_targetPositions(
16398            self_: *mut whiteout_M2Camera,
16399            value: *const whiteout_M2AnimationTrackM2CameraSpline,
16400        );
16401        pub fn whiteout_m2_M2Camera_get_targetPositionBase(
16402            self_: *mut whiteout_M2Camera,
16403        ) -> *mut core::ffi::c_void;
16404        pub fn whiteout_m2_M2Camera_set_targetPositionBase(
16405            self_: *mut whiteout_M2Camera,
16406            value: *const core::ffi::c_void,
16407        );
16408        pub fn whiteout_m2_M2Camera_get_roll(
16409            self_: *mut whiteout_M2Camera,
16410        ) -> *mut whiteout_M2AnimationTrackF32;
16411        pub fn whiteout_m2_M2Camera_set_roll(
16412            self_: *mut whiteout_M2Camera,
16413            value: *const whiteout_M2AnimationTrackF32,
16414        );
16415        pub fn whiteout_m2_M2Camera_get_fieldOfViewTrack(
16416            self_: *mut whiteout_M2Camera,
16417        ) -> *mut whiteout_M2AnimationTrackF32;
16418        pub fn whiteout_m2_M2Camera_set_fieldOfViewTrack(
16419            self_: *mut whiteout_M2Camera,
16420            value: *const whiteout_M2AnimationTrackF32,
16421        );
16422        // Attachment
16423        pub fn whiteout_m2_M2Attachment_new() -> *mut whiteout_M2Attachment;
16424        pub fn whiteout_m2_M2Attachment_delete(self_: *mut whiteout_M2Attachment);
16425        pub fn whiteout_m2_M2Attachment_get_id(self_: *mut whiteout_M2Attachment) -> u32;
16426        pub fn whiteout_m2_M2Attachment_set_id(self_: *mut whiteout_M2Attachment, value: u32);
16427        pub fn whiteout_m2_M2Attachment_get_boneId(self_: *mut whiteout_M2Attachment) -> u16;
16428        pub fn whiteout_m2_M2Attachment_set_boneId(self_: *mut whiteout_M2Attachment, value: u16);
16429        pub fn whiteout_m2_M2Attachment_get_unknown(self_: *mut whiteout_M2Attachment) -> u16;
16430        pub fn whiteout_m2_M2Attachment_set_unknown(self_: *mut whiteout_M2Attachment, value: u16);
16431        pub fn whiteout_m2_M2Attachment_get_position(
16432            self_: *mut whiteout_M2Attachment,
16433        ) -> *mut core::ffi::c_void;
16434        pub fn whiteout_m2_M2Attachment_set_position(
16435            self_: *mut whiteout_M2Attachment,
16436            value: *const core::ffi::c_void,
16437        );
16438        pub fn whiteout_m2_M2Attachment_get_animate(
16439            self_: *mut whiteout_M2Attachment,
16440        ) -> *mut whiteout_M2AnimationTrackU8;
16441        pub fn whiteout_m2_M2Attachment_set_animate(
16442            self_: *mut whiteout_M2Attachment,
16443            value: *const whiteout_M2AnimationTrackU8,
16444        );
16445        // RibbonEmitter
16446        pub fn whiteout_m2_M2RibbonEmitter_new() -> *mut whiteout_M2RibbonEmitter;
16447        pub fn whiteout_m2_M2RibbonEmitter_delete(self_: *mut whiteout_M2RibbonEmitter);
16448        pub fn whiteout_m2_M2RibbonEmitter_get_ribbonId(
16449            self_: *mut whiteout_M2RibbonEmitter,
16450        ) -> u32;
16451        pub fn whiteout_m2_M2RibbonEmitter_set_ribbonId(
16452            self_: *mut whiteout_M2RibbonEmitter,
16453            value: u32,
16454        );
16455        pub fn whiteout_m2_M2RibbonEmitter_get_boneId(self_: *mut whiteout_M2RibbonEmitter) -> u32;
16456        pub fn whiteout_m2_M2RibbonEmitter_set_boneId(
16457            self_: *mut whiteout_M2RibbonEmitter,
16458            value: u32,
16459        );
16460        pub fn whiteout_m2_M2RibbonEmitter_get_position(
16461            self_: *mut whiteout_M2RibbonEmitter,
16462        ) -> *mut core::ffi::c_void;
16463        pub fn whiteout_m2_M2RibbonEmitter_set_position(
16464            self_: *mut whiteout_M2RibbonEmitter,
16465            value: *const core::ffi::c_void,
16466        );
16467        pub fn whiteout_m2_M2RibbonEmitter_get_textureIndices_count(
16468            self_: *mut whiteout_M2RibbonEmitter,
16469        ) -> usize;
16470        pub fn whiteout_m2_M2RibbonEmitter_resize_textureIndices(
16471            self_: *mut whiteout_M2RibbonEmitter,
16472            count: usize,
16473        );
16474        pub fn whiteout_m2_M2RibbonEmitter_get_textureIndices_data(
16475            self_: *mut whiteout_M2RibbonEmitter,
16476        ) -> *const u16;
16477        pub fn whiteout_m2_M2RibbonEmitter_assign_textureIndices(
16478            self_: *mut whiteout_M2RibbonEmitter,
16479            data: *const u16,
16480            count: usize,
16481        );
16482        pub fn whiteout_m2_M2RibbonEmitter_get_materialIndices_count(
16483            self_: *mut whiteout_M2RibbonEmitter,
16484        ) -> usize;
16485        pub fn whiteout_m2_M2RibbonEmitter_resize_materialIndices(
16486            self_: *mut whiteout_M2RibbonEmitter,
16487            count: usize,
16488        );
16489        pub fn whiteout_m2_M2RibbonEmitter_get_materialIndices_data(
16490            self_: *mut whiteout_M2RibbonEmitter,
16491        ) -> *const u16;
16492        pub fn whiteout_m2_M2RibbonEmitter_assign_materialIndices(
16493            self_: *mut whiteout_M2RibbonEmitter,
16494            data: *const u16,
16495            count: usize,
16496        );
16497        pub fn whiteout_m2_M2RibbonEmitter_get_colorTrack(
16498            self_: *mut whiteout_M2RibbonEmitter,
16499        ) -> *mut whiteout_M2AnimationTrackVector3f;
16500        pub fn whiteout_m2_M2RibbonEmitter_set_colorTrack(
16501            self_: *mut whiteout_M2RibbonEmitter,
16502            value: *const whiteout_M2AnimationTrackVector3f,
16503        );
16504        pub fn whiteout_m2_M2RibbonEmitter_get_alphaTrack(
16505            self_: *mut whiteout_M2RibbonEmitter,
16506        ) -> *mut whiteout_M2AnimationTrackI16;
16507        pub fn whiteout_m2_M2RibbonEmitter_set_alphaTrack(
16508            self_: *mut whiteout_M2RibbonEmitter,
16509            value: *const whiteout_M2AnimationTrackI16,
16510        );
16511        pub fn whiteout_m2_M2RibbonEmitter_get_heightAbove(
16512            self_: *mut whiteout_M2RibbonEmitter,
16513        ) -> *mut whiteout_M2AnimationTrackF32;
16514        pub fn whiteout_m2_M2RibbonEmitter_set_heightAbove(
16515            self_: *mut whiteout_M2RibbonEmitter,
16516            value: *const whiteout_M2AnimationTrackF32,
16517        );
16518        pub fn whiteout_m2_M2RibbonEmitter_get_heightBelow(
16519            self_: *mut whiteout_M2RibbonEmitter,
16520        ) -> *mut whiteout_M2AnimationTrackF32;
16521        pub fn whiteout_m2_M2RibbonEmitter_set_heightBelow(
16522            self_: *mut whiteout_M2RibbonEmitter,
16523            value: *const whiteout_M2AnimationTrackF32,
16524        );
16525        pub fn whiteout_m2_M2RibbonEmitter_get_edgesPerSecond(
16526            self_: *mut whiteout_M2RibbonEmitter,
16527        ) -> f32;
16528        pub fn whiteout_m2_M2RibbonEmitter_set_edgesPerSecond(
16529            self_: *mut whiteout_M2RibbonEmitter,
16530            value: f32,
16531        );
16532        pub fn whiteout_m2_M2RibbonEmitter_get_edgeLifetime(
16533            self_: *mut whiteout_M2RibbonEmitter,
16534        ) -> f32;
16535        pub fn whiteout_m2_M2RibbonEmitter_set_edgeLifetime(
16536            self_: *mut whiteout_M2RibbonEmitter,
16537            value: f32,
16538        );
16539        pub fn whiteout_m2_M2RibbonEmitter_get_gravity(self_: *mut whiteout_M2RibbonEmitter)
16540            -> f32;
16541        pub fn whiteout_m2_M2RibbonEmitter_set_gravity(
16542            self_: *mut whiteout_M2RibbonEmitter,
16543            value: f32,
16544        );
16545        pub fn whiteout_m2_M2RibbonEmitter_get_textureRows(
16546            self_: *mut whiteout_M2RibbonEmitter,
16547        ) -> u16;
16548        pub fn whiteout_m2_M2RibbonEmitter_set_textureRows(
16549            self_: *mut whiteout_M2RibbonEmitter,
16550            value: u16,
16551        );
16552        pub fn whiteout_m2_M2RibbonEmitter_get_textureCols(
16553            self_: *mut whiteout_M2RibbonEmitter,
16554        ) -> u16;
16555        pub fn whiteout_m2_M2RibbonEmitter_set_textureCols(
16556            self_: *mut whiteout_M2RibbonEmitter,
16557            value: u16,
16558        );
16559        pub fn whiteout_m2_M2RibbonEmitter_get_texSlot(
16560            self_: *mut whiteout_M2RibbonEmitter,
16561        ) -> *mut whiteout_M2AnimationTrackU16;
16562        pub fn whiteout_m2_M2RibbonEmitter_set_texSlot(
16563            self_: *mut whiteout_M2RibbonEmitter,
16564            value: *const whiteout_M2AnimationTrackU16,
16565        );
16566        pub fn whiteout_m2_M2RibbonEmitter_get_visibility(
16567            self_: *mut whiteout_M2RibbonEmitter,
16568        ) -> *mut whiteout_M2AnimationTrackU8;
16569        pub fn whiteout_m2_M2RibbonEmitter_set_visibility(
16570            self_: *mut whiteout_M2RibbonEmitter,
16571            value: *const whiteout_M2AnimationTrackU8,
16572        );
16573        pub fn whiteout_m2_M2RibbonEmitter_get_priorityPlane(
16574            self_: *mut whiteout_M2RibbonEmitter,
16575        ) -> i16;
16576        pub fn whiteout_m2_M2RibbonEmitter_set_priorityPlane(
16577            self_: *mut whiteout_M2RibbonEmitter,
16578            value: i16,
16579        );
16580        pub fn whiteout_m2_M2RibbonEmitter_get_ribbonColorIndex(
16581            self_: *mut whiteout_M2RibbonEmitter,
16582        ) -> i8;
16583        pub fn whiteout_m2_M2RibbonEmitter_set_ribbonColorIndex(
16584            self_: *mut whiteout_M2RibbonEmitter,
16585            value: i8,
16586        );
16587        pub fn whiteout_m2_M2RibbonEmitter_get_textureTransformIndex(
16588            self_: *mut whiteout_M2RibbonEmitter,
16589        ) -> i8;
16590        pub fn whiteout_m2_M2RibbonEmitter_set_textureTransformIndex(
16591            self_: *mut whiteout_M2RibbonEmitter,
16592            value: i8,
16593        );
16594        // Box
16595        pub fn whiteout_m2_M2Box_new() -> *mut whiteout_M2Box;
16596        pub fn whiteout_m2_M2Box_delete(self_: *mut whiteout_M2Box);
16597        pub fn whiteout_m2_M2Box_get_minimum(self_: *mut whiteout_M2Box) -> *mut core::ffi::c_void;
16598        pub fn whiteout_m2_M2Box_set_minimum(
16599            self_: *mut whiteout_M2Box,
16600            value: *const core::ffi::c_void,
16601        );
16602        pub fn whiteout_m2_M2Box_get_maximum(self_: *mut whiteout_M2Box) -> *mut core::ffi::c_void;
16603        pub fn whiteout_m2_M2Box_set_maximum(
16604            self_: *mut whiteout_M2Box,
16605            value: *const core::ffi::c_void,
16606        );
16607        // ParticleEmitter
16608        pub fn whiteout_m2_M2ParticleEmitter_new() -> *mut whiteout_M2ParticleEmitter;
16609        pub fn whiteout_m2_M2ParticleEmitter_delete(self_: *mut whiteout_M2ParticleEmitter);
16610        pub fn whiteout_m2_M2ParticleEmitter_get_particleId(
16611            self_: *mut whiteout_M2ParticleEmitter,
16612        ) -> u32;
16613        pub fn whiteout_m2_M2ParticleEmitter_set_particleId(
16614            self_: *mut whiteout_M2ParticleEmitter,
16615            value: u32,
16616        );
16617        pub fn whiteout_m2_M2ParticleEmitter_get_flags(
16618            self_: *mut whiteout_M2ParticleEmitter,
16619        ) -> i32;
16620        pub fn whiteout_m2_M2ParticleEmitter_set_flags(
16621            self_: *mut whiteout_M2ParticleEmitter,
16622            value: i32,
16623        );
16624        pub fn whiteout_m2_M2ParticleEmitter_get_position(
16625            self_: *mut whiteout_M2ParticleEmitter,
16626        ) -> *mut core::ffi::c_void;
16627        pub fn whiteout_m2_M2ParticleEmitter_set_position(
16628            self_: *mut whiteout_M2ParticleEmitter,
16629            value: *const core::ffi::c_void,
16630        );
16631        pub fn whiteout_m2_M2ParticleEmitter_get_boneId(
16632            self_: *mut whiteout_M2ParticleEmitter,
16633        ) -> u16;
16634        pub fn whiteout_m2_M2ParticleEmitter_set_boneId(
16635            self_: *mut whiteout_M2ParticleEmitter,
16636            value: u16,
16637        );
16638        pub fn whiteout_m2_M2ParticleEmitter_get_particleModelFilename(
16639            self_: *mut whiteout_M2ParticleEmitter,
16640        ) -> RawCString;
16641        pub fn whiteout_m2_M2ParticleEmitter_set_particleModelFilename(
16642            self_: *mut whiteout_M2ParticleEmitter,
16643            value: *const core::ffi::c_char,
16644        );
16645        pub fn whiteout_m2_M2ParticleEmitter_get_childEmittersModelFilename(
16646            self_: *mut whiteout_M2ParticleEmitter,
16647        ) -> RawCString;
16648        pub fn whiteout_m2_M2ParticleEmitter_set_childEmittersModelFilename(
16649            self_: *mut whiteout_M2ParticleEmitter,
16650            value: *const core::ffi::c_char,
16651        );
16652        pub fn whiteout_m2_M2ParticleEmitter_get_blendingType(
16653            self_: *mut whiteout_M2ParticleEmitter,
16654        ) -> i32;
16655        pub fn whiteout_m2_M2ParticleEmitter_set_blendingType(
16656            self_: *mut whiteout_M2ParticleEmitter,
16657            value: i32,
16658        );
16659        pub fn whiteout_m2_M2ParticleEmitter_get_emitterType(
16660            self_: *mut whiteout_M2ParticleEmitter,
16661        ) -> i32;
16662        pub fn whiteout_m2_M2ParticleEmitter_set_emitterType(
16663            self_: *mut whiteout_M2ParticleEmitter,
16664            value: i32,
16665        );
16666        pub fn whiteout_m2_M2ParticleEmitter_get_particleColorIndex(
16667            self_: *mut whiteout_M2ParticleEmitter,
16668        ) -> u16;
16669        pub fn whiteout_m2_M2ParticleEmitter_set_particleColorIndex(
16670            self_: *mut whiteout_M2ParticleEmitter,
16671            value: u16,
16672        );
16673        pub fn whiteout_m2_M2ParticleEmitter_get_particleType(
16674            self_: *mut whiteout_M2ParticleEmitter,
16675        ) -> u8;
16676        pub fn whiteout_m2_M2ParticleEmitter_set_particleType(
16677            self_: *mut whiteout_M2ParticleEmitter,
16678            value: u8,
16679        );
16680        pub fn whiteout_m2_M2ParticleEmitter_get_headOrTail(
16681            self_: *mut whiteout_M2ParticleEmitter,
16682        ) -> u8;
16683        pub fn whiteout_m2_M2ParticleEmitter_set_headOrTail(
16684            self_: *mut whiteout_M2ParticleEmitter,
16685            value: u8,
16686        );
16687        pub fn whiteout_m2_M2ParticleEmitter_get_textureTilerotation(
16688            self_: *mut whiteout_M2ParticleEmitter,
16689        ) -> i16;
16690        pub fn whiteout_m2_M2ParticleEmitter_set_textureTilerotation(
16691            self_: *mut whiteout_M2ParticleEmitter,
16692            value: i16,
16693        );
16694        pub fn whiteout_m2_M2ParticleEmitter_get_rows(
16695            self_: *mut whiteout_M2ParticleEmitter,
16696        ) -> u16;
16697        pub fn whiteout_m2_M2ParticleEmitter_set_rows(
16698            self_: *mut whiteout_M2ParticleEmitter,
16699            value: u16,
16700        );
16701        pub fn whiteout_m2_M2ParticleEmitter_get_columns(
16702            self_: *mut whiteout_M2ParticleEmitter,
16703        ) -> u16;
16704        pub fn whiteout_m2_M2ParticleEmitter_set_columns(
16705            self_: *mut whiteout_M2ParticleEmitter,
16706            value: u16,
16707        );
16708        pub fn whiteout_m2_M2ParticleEmitter_get_emissionSpeed(
16709            self_: *mut whiteout_M2ParticleEmitter,
16710        ) -> *mut whiteout_M2AnimationTrackF32;
16711        pub fn whiteout_m2_M2ParticleEmitter_set_emissionSpeed(
16712            self_: *mut whiteout_M2ParticleEmitter,
16713            value: *const whiteout_M2AnimationTrackF32,
16714        );
16715        pub fn whiteout_m2_M2ParticleEmitter_get_speedVariation(
16716            self_: *mut whiteout_M2ParticleEmitter,
16717        ) -> *mut whiteout_M2AnimationTrackF32;
16718        pub fn whiteout_m2_M2ParticleEmitter_set_speedVariation(
16719            self_: *mut whiteout_M2ParticleEmitter,
16720            value: *const whiteout_M2AnimationTrackF32,
16721        );
16722        pub fn whiteout_m2_M2ParticleEmitter_get_verticalRange(
16723            self_: *mut whiteout_M2ParticleEmitter,
16724        ) -> *mut whiteout_M2AnimationTrackF32;
16725        pub fn whiteout_m2_M2ParticleEmitter_set_verticalRange(
16726            self_: *mut whiteout_M2ParticleEmitter,
16727            value: *const whiteout_M2AnimationTrackF32,
16728        );
16729        pub fn whiteout_m2_M2ParticleEmitter_get_horizontalRange(
16730            self_: *mut whiteout_M2ParticleEmitter,
16731        ) -> *mut whiteout_M2AnimationTrackF32;
16732        pub fn whiteout_m2_M2ParticleEmitter_set_horizontalRange(
16733            self_: *mut whiteout_M2ParticleEmitter,
16734            value: *const whiteout_M2AnimationTrackF32,
16735        );
16736        pub fn whiteout_m2_M2ParticleEmitter_get_gravity(
16737            self_: *mut whiteout_M2ParticleEmitter,
16738        ) -> *mut whiteout_M2AnimationTrackF32;
16739        pub fn whiteout_m2_M2ParticleEmitter_set_gravity(
16740            self_: *mut whiteout_M2ParticleEmitter,
16741            value: *const whiteout_M2AnimationTrackF32,
16742        );
16743        pub fn whiteout_m2_M2ParticleEmitter_get_lifespan(
16744            self_: *mut whiteout_M2ParticleEmitter,
16745        ) -> *mut whiteout_M2AnimationTrackF32;
16746        pub fn whiteout_m2_M2ParticleEmitter_set_lifespan(
16747            self_: *mut whiteout_M2ParticleEmitter,
16748            value: *const whiteout_M2AnimationTrackF32,
16749        );
16750        pub fn whiteout_m2_M2ParticleEmitter_get_lifespanVariation(
16751            self_: *mut whiteout_M2ParticleEmitter,
16752        ) -> f32;
16753        pub fn whiteout_m2_M2ParticleEmitter_set_lifespanVariation(
16754            self_: *mut whiteout_M2ParticleEmitter,
16755            value: f32,
16756        );
16757        pub fn whiteout_m2_M2ParticleEmitter_get_emissionRate(
16758            self_: *mut whiteout_M2ParticleEmitter,
16759        ) -> *mut whiteout_M2AnimationTrackF32;
16760        pub fn whiteout_m2_M2ParticleEmitter_set_emissionRate(
16761            self_: *mut whiteout_M2ParticleEmitter,
16762            value: *const whiteout_M2AnimationTrackF32,
16763        );
16764        pub fn whiteout_m2_M2ParticleEmitter_get_emissionRateVariation(
16765            self_: *mut whiteout_M2ParticleEmitter,
16766        ) -> f32;
16767        pub fn whiteout_m2_M2ParticleEmitter_set_emissionRateVariation(
16768            self_: *mut whiteout_M2ParticleEmitter,
16769            value: f32,
16770        );
16771        pub fn whiteout_m2_M2ParticleEmitter_get_emissionAreaWidth(
16772            self_: *mut whiteout_M2ParticleEmitter,
16773        ) -> *mut whiteout_M2AnimationTrackF32;
16774        pub fn whiteout_m2_M2ParticleEmitter_set_emissionAreaWidth(
16775            self_: *mut whiteout_M2ParticleEmitter,
16776            value: *const whiteout_M2AnimationTrackF32,
16777        );
16778        pub fn whiteout_m2_M2ParticleEmitter_get_emissionAreaLength(
16779            self_: *mut whiteout_M2ParticleEmitter,
16780        ) -> *mut whiteout_M2AnimationTrackF32;
16781        pub fn whiteout_m2_M2ParticleEmitter_set_emissionAreaLength(
16782            self_: *mut whiteout_M2ParticleEmitter,
16783            value: *const whiteout_M2AnimationTrackF32,
16784        );
16785        pub fn whiteout_m2_M2ParticleEmitter_get_zSource(
16786            self_: *mut whiteout_M2ParticleEmitter,
16787        ) -> *mut whiteout_M2AnimationTrackF32;
16788        pub fn whiteout_m2_M2ParticleEmitter_set_zSource(
16789            self_: *mut whiteout_M2ParticleEmitter,
16790            value: *const whiteout_M2AnimationTrackF32,
16791        );
16792        pub fn whiteout_m2_M2ParticleEmitter_get_colorTrack(
16793            self_: *mut whiteout_M2ParticleEmitter,
16794        ) -> *mut whiteout_M2ParticleAnimationTrackVector3f;
16795        pub fn whiteout_m2_M2ParticleEmitter_set_colorTrack(
16796            self_: *mut whiteout_M2ParticleEmitter,
16797            value: *const whiteout_M2ParticleAnimationTrackVector3f,
16798        );
16799        pub fn whiteout_m2_M2ParticleEmitter_get_scaleTrack(
16800            self_: *mut whiteout_M2ParticleEmitter,
16801        ) -> *mut whiteout_M2ParticleAnimationTrackVector2f;
16802        pub fn whiteout_m2_M2ParticleEmitter_set_scaleTrack(
16803            self_: *mut whiteout_M2ParticleEmitter,
16804            value: *const whiteout_M2ParticleAnimationTrackVector2f,
16805        );
16806        pub fn whiteout_m2_M2ParticleEmitter_get_scaleVary(
16807            self_: *mut whiteout_M2ParticleEmitter,
16808        ) -> *mut core::ffi::c_void;
16809        pub fn whiteout_m2_M2ParticleEmitter_set_scaleVary(
16810            self_: *mut whiteout_M2ParticleEmitter,
16811            value: *const core::ffi::c_void,
16812        );
16813        pub fn whiteout_m2_M2ParticleEmitter_get_tailLength(
16814            self_: *mut whiteout_M2ParticleEmitter,
16815        ) -> f32;
16816        pub fn whiteout_m2_M2ParticleEmitter_set_tailLength(
16817            self_: *mut whiteout_M2ParticleEmitter,
16818            value: f32,
16819        );
16820        pub fn whiteout_m2_M2ParticleEmitter_get_twinkleSpeed(
16821            self_: *mut whiteout_M2ParticleEmitter,
16822        ) -> f32;
16823        pub fn whiteout_m2_M2ParticleEmitter_set_twinkleSpeed(
16824            self_: *mut whiteout_M2ParticleEmitter,
16825            value: f32,
16826        );
16827        pub fn whiteout_m2_M2ParticleEmitter_get_twinklePercent(
16828            self_: *mut whiteout_M2ParticleEmitter,
16829        ) -> f32;
16830        pub fn whiteout_m2_M2ParticleEmitter_set_twinklePercent(
16831            self_: *mut whiteout_M2ParticleEmitter,
16832            value: f32,
16833        );
16834        pub fn whiteout_m2_M2ParticleEmitter_get_twinkleScale(
16835            self_: *mut whiteout_M2ParticleEmitter,
16836        ) -> *mut core::ffi::c_void;
16837        pub fn whiteout_m2_M2ParticleEmitter_set_twinkleScale(
16838            self_: *mut whiteout_M2ParticleEmitter,
16839            value: *const core::ffi::c_void,
16840        );
16841        pub fn whiteout_m2_M2ParticleEmitter_get_inheritVelocityScale(
16842            self_: *mut whiteout_M2ParticleEmitter,
16843        ) -> f32;
16844        pub fn whiteout_m2_M2ParticleEmitter_set_inheritVelocityScale(
16845            self_: *mut whiteout_M2ParticleEmitter,
16846            value: f32,
16847        );
16848        pub fn whiteout_m2_M2ParticleEmitter_get_drag(
16849            self_: *mut whiteout_M2ParticleEmitter,
16850        ) -> f32;
16851        pub fn whiteout_m2_M2ParticleEmitter_set_drag(
16852            self_: *mut whiteout_M2ParticleEmitter,
16853            value: f32,
16854        );
16855        pub fn whiteout_m2_M2ParticleEmitter_get_baseSpin(
16856            self_: *mut whiteout_M2ParticleEmitter,
16857        ) -> f32;
16858        pub fn whiteout_m2_M2ParticleEmitter_set_baseSpin(
16859            self_: *mut whiteout_M2ParticleEmitter,
16860            value: f32,
16861        );
16862        pub fn whiteout_m2_M2ParticleEmitter_get_baseSpinVariation(
16863            self_: *mut whiteout_M2ParticleEmitter,
16864        ) -> f32;
16865        pub fn whiteout_m2_M2ParticleEmitter_set_baseSpinVariation(
16866            self_: *mut whiteout_M2ParticleEmitter,
16867            value: f32,
16868        );
16869        pub fn whiteout_m2_M2ParticleEmitter_get_spinSpeed(
16870            self_: *mut whiteout_M2ParticleEmitter,
16871        ) -> f32;
16872        pub fn whiteout_m2_M2ParticleEmitter_set_spinSpeed(
16873            self_: *mut whiteout_M2ParticleEmitter,
16874            value: f32,
16875        );
16876        pub fn whiteout_m2_M2ParticleEmitter_get_spinSpeedVariation(
16877            self_: *mut whiteout_M2ParticleEmitter,
16878        ) -> f32;
16879        pub fn whiteout_m2_M2ParticleEmitter_set_spinSpeedVariation(
16880            self_: *mut whiteout_M2ParticleEmitter,
16881            value: f32,
16882        );
16883        pub fn whiteout_m2_M2ParticleEmitter_get_tumble(
16884            self_: *mut whiteout_M2ParticleEmitter,
16885        ) -> *mut whiteout_M2Box;
16886        pub fn whiteout_m2_M2ParticleEmitter_set_tumble(
16887            self_: *mut whiteout_M2ParticleEmitter,
16888            value: *const whiteout_M2Box,
16889        );
16890        pub fn whiteout_m2_M2ParticleEmitter_get_windVector(
16891            self_: *mut whiteout_M2ParticleEmitter,
16892        ) -> *mut core::ffi::c_void;
16893        pub fn whiteout_m2_M2ParticleEmitter_set_windVector(
16894            self_: *mut whiteout_M2ParticleEmitter,
16895            value: *const core::ffi::c_void,
16896        );
16897        pub fn whiteout_m2_M2ParticleEmitter_get_windTime(
16898            self_: *mut whiteout_M2ParticleEmitter,
16899        ) -> f32;
16900        pub fn whiteout_m2_M2ParticleEmitter_set_windTime(
16901            self_: *mut whiteout_M2ParticleEmitter,
16902            value: f32,
16903        );
16904        pub fn whiteout_m2_M2ParticleEmitter_get_followSpeed1(
16905            self_: *mut whiteout_M2ParticleEmitter,
16906        ) -> f32;
16907        pub fn whiteout_m2_M2ParticleEmitter_set_followSpeed1(
16908            self_: *mut whiteout_M2ParticleEmitter,
16909            value: f32,
16910        );
16911        pub fn whiteout_m2_M2ParticleEmitter_get_followScale1(
16912            self_: *mut whiteout_M2ParticleEmitter,
16913        ) -> f32;
16914        pub fn whiteout_m2_M2ParticleEmitter_set_followScale1(
16915            self_: *mut whiteout_M2ParticleEmitter,
16916            value: f32,
16917        );
16918        pub fn whiteout_m2_M2ParticleEmitter_get_followSpeed2(
16919            self_: *mut whiteout_M2ParticleEmitter,
16920        ) -> f32;
16921        pub fn whiteout_m2_M2ParticleEmitter_set_followSpeed2(
16922            self_: *mut whiteout_M2ParticleEmitter,
16923            value: f32,
16924        );
16925        pub fn whiteout_m2_M2ParticleEmitter_get_followScale2(
16926            self_: *mut whiteout_M2ParticleEmitter,
16927        ) -> f32;
16928        pub fn whiteout_m2_M2ParticleEmitter_set_followScale2(
16929            self_: *mut whiteout_M2ParticleEmitter,
16930            value: f32,
16931        );
16932        pub fn whiteout_m2_M2ParticleEmitter_get_splinePoints_count(
16933            self_: *mut whiteout_M2ParticleEmitter,
16934        ) -> usize;
16935        pub fn whiteout_m2_M2ParticleEmitter_resize_splinePoints(
16936            self_: *mut whiteout_M2ParticleEmitter,
16937            count: usize,
16938        );
16939        pub fn whiteout_m2_M2ParticleEmitter_get_splinePoints_data(
16940            self_: *mut whiteout_M2ParticleEmitter,
16941        ) -> *const f32;
16942        pub fn whiteout_m2_M2ParticleEmitter_assign_splinePoints(
16943            self_: *mut whiteout_M2ParticleEmitter,
16944            data: *const f32,
16945            count: usize,
16946        );
16947        pub fn whiteout_m2_M2ParticleEmitter_get_enabledIn(
16948            self_: *mut whiteout_M2ParticleEmitter,
16949        ) -> *mut whiteout_M2AnimationTrackU8;
16950        pub fn whiteout_m2_M2ParticleEmitter_set_enabledIn(
16951            self_: *mut whiteout_M2ParticleEmitter,
16952            value: *const whiteout_M2AnimationTrackU8,
16953        );
16954        // Event
16955        pub fn whiteout_m2_M2Event_new() -> *mut whiteout_M2Event;
16956        pub fn whiteout_m2_M2Event_delete(self_: *mut whiteout_M2Event);
16957        pub fn whiteout_m2_M2Event_get_identifier(self_: *mut whiteout_M2Event) -> u32;
16958        pub fn whiteout_m2_M2Event_set_identifier(self_: *mut whiteout_M2Event, value: u32);
16959        pub fn whiteout_m2_M2Event_get_data(self_: *mut whiteout_M2Event) -> u32;
16960        pub fn whiteout_m2_M2Event_set_data(self_: *mut whiteout_M2Event, value: u32);
16961        pub fn whiteout_m2_M2Event_get_boneId(self_: *mut whiteout_M2Event) -> u32;
16962        pub fn whiteout_m2_M2Event_set_boneId(self_: *mut whiteout_M2Event, value: u32);
16963        pub fn whiteout_m2_M2Event_get_position(
16964            self_: *mut whiteout_M2Event,
16965        ) -> *mut core::ffi::c_void;
16966        pub fn whiteout_m2_M2Event_set_position(
16967            self_: *mut whiteout_M2Event,
16968            value: *const core::ffi::c_void,
16969        );
16970        pub fn whiteout_m2_M2Event_get_enabled(
16971            self_: *mut whiteout_M2Event,
16972        ) -> *mut whiteout_M2AnimationTrackBase;
16973        pub fn whiteout_m2_M2Event_set_enabled(
16974            self_: *mut whiteout_M2Event,
16975            value: *const whiteout_M2AnimationTrackBase,
16976        );
16977        // PhysicsFrame
16978        pub fn whiteout_m2_M2PhysicsFrame_new() -> *mut whiteout_M2PhysicsFrame;
16979        pub fn whiteout_m2_M2PhysicsFrame_delete(self_: *mut whiteout_M2PhysicsFrame);
16980        pub fn whiteout_m2_M2PhysicsFrame_get_axisX(
16981            self_: *mut whiteout_M2PhysicsFrame,
16982        ) -> *mut core::ffi::c_void;
16983        pub fn whiteout_m2_M2PhysicsFrame_set_axisX(
16984            self_: *mut whiteout_M2PhysicsFrame,
16985            value: *const core::ffi::c_void,
16986        );
16987        pub fn whiteout_m2_M2PhysicsFrame_get_axisY(
16988            self_: *mut whiteout_M2PhysicsFrame,
16989        ) -> *mut core::ffi::c_void;
16990        pub fn whiteout_m2_M2PhysicsFrame_set_axisY(
16991            self_: *mut whiteout_M2PhysicsFrame,
16992            value: *const core::ffi::c_void,
16993        );
16994        pub fn whiteout_m2_M2PhysicsFrame_get_axisZ(
16995            self_: *mut whiteout_M2PhysicsFrame,
16996        ) -> *mut core::ffi::c_void;
16997        pub fn whiteout_m2_M2PhysicsFrame_set_axisZ(
16998            self_: *mut whiteout_M2PhysicsFrame,
16999            value: *const core::ffi::c_void,
17000        );
17001        pub fn whiteout_m2_M2PhysicsFrame_get_origin(
17002            self_: *mut whiteout_M2PhysicsFrame,
17003        ) -> *mut core::ffi::c_void;
17004        pub fn whiteout_m2_M2PhysicsFrame_set_origin(
17005            self_: *mut whiteout_M2PhysicsFrame,
17006            value: *const core::ffi::c_void,
17007        );
17008        // PhysicsBody
17009        pub fn whiteout_m2_M2PhysicsBody_new() -> *mut whiteout_M2PhysicsBody;
17010        pub fn whiteout_m2_M2PhysicsBody_delete(self_: *mut whiteout_M2PhysicsBody);
17011        pub fn whiteout_m2_M2PhysicsBody_get_type(self_: *mut whiteout_M2PhysicsBody) -> i32;
17012        pub fn whiteout_m2_M2PhysicsBody_set_type(self_: *mut whiteout_M2PhysicsBody, value: i32);
17013        pub fn whiteout_m2_M2PhysicsBody_get_boneIndex(self_: *mut whiteout_M2PhysicsBody) -> u16;
17014        pub fn whiteout_m2_M2PhysicsBody_set_boneIndex(
17015            self_: *mut whiteout_M2PhysicsBody,
17016            value: u16,
17017        );
17018        pub fn whiteout_m2_M2PhysicsBody_get_position(
17019            self_: *mut whiteout_M2PhysicsBody,
17020        ) -> *mut core::ffi::c_void;
17021        pub fn whiteout_m2_M2PhysicsBody_set_position(
17022            self_: *mut whiteout_M2PhysicsBody,
17023            value: *const core::ffi::c_void,
17024        );
17025        pub fn whiteout_m2_M2PhysicsBody_get_shapeIndex(self_: *mut whiteout_M2PhysicsBody) -> i32;
17026        pub fn whiteout_m2_M2PhysicsBody_set_shapeIndex(
17027            self_: *mut whiteout_M2PhysicsBody,
17028            value: i32,
17029        );
17030        pub fn whiteout_m2_M2PhysicsBody_get_shapeCount(self_: *mut whiteout_M2PhysicsBody) -> i32;
17031        pub fn whiteout_m2_M2PhysicsBody_set_shapeCount(
17032            self_: *mut whiteout_M2PhysicsBody,
17033            value: i32,
17034        );
17035        pub fn whiteout_m2_M2PhysicsBody_get_gravityScale(
17036            self_: *mut whiteout_M2PhysicsBody,
17037        ) -> f32;
17038        pub fn whiteout_m2_M2PhysicsBody_set_gravityScale(
17039            self_: *mut whiteout_M2PhysicsBody,
17040            value: f32,
17041        );
17042        pub fn whiteout_m2_M2PhysicsBody_get_inertiaScale(
17043            self_: *mut whiteout_M2PhysicsBody,
17044        ) -> f32;
17045        pub fn whiteout_m2_M2PhysicsBody_set_inertiaScale(
17046            self_: *mut whiteout_M2PhysicsBody,
17047            value: f32,
17048        );
17049        pub fn whiteout_m2_M2PhysicsBody_get_linearDamping(
17050            self_: *mut whiteout_M2PhysicsBody,
17051        ) -> f32;
17052        pub fn whiteout_m2_M2PhysicsBody_set_linearDamping(
17053            self_: *mut whiteout_M2PhysicsBody,
17054            value: f32,
17055        );
17056        pub fn whiteout_m2_M2PhysicsBody_get_angularDamping(
17057            self_: *mut whiteout_M2PhysicsBody,
17058        ) -> f32;
17059        pub fn whiteout_m2_M2PhysicsBody_set_angularDamping(
17060            self_: *mut whiteout_M2PhysicsBody,
17061            value: f32,
17062        );
17063        pub fn whiteout_m2_M2PhysicsBody_get_unknown28(self_: *mut whiteout_M2PhysicsBody) -> f32;
17064        pub fn whiteout_m2_M2PhysicsBody_set_unknown28(
17065            self_: *mut whiteout_M2PhysicsBody,
17066            value: f32,
17067        );
17068        pub fn whiteout_m2_M2PhysicsBody_get_unknown2c(self_: *mut whiteout_M2PhysicsBody) -> u16;
17069        pub fn whiteout_m2_M2PhysicsBody_set_unknown2c(
17070            self_: *mut whiteout_M2PhysicsBody,
17071            value: u16,
17072        );
17073        pub fn whiteout_m2_M2PhysicsBody_get_padding2e(self_: *mut whiteout_M2PhysicsBody) -> u16;
17074        pub fn whiteout_m2_M2PhysicsBody_set_padding2e(
17075            self_: *mut whiteout_M2PhysicsBody,
17076            value: u16,
17077        );
17078        // PhysicsShape
17079        pub fn whiteout_m2_M2PhysicsShape_new() -> *mut whiteout_M2PhysicsShape;
17080        pub fn whiteout_m2_M2PhysicsShape_delete(self_: *mut whiteout_M2PhysicsShape);
17081        pub fn whiteout_m2_M2PhysicsShape_get_shapeType(self_: *mut whiteout_M2PhysicsShape)
17082            -> i32;
17083        pub fn whiteout_m2_M2PhysicsShape_set_shapeType(
17084            self_: *mut whiteout_M2PhysicsShape,
17085            value: i32,
17086        );
17087        pub fn whiteout_m2_M2PhysicsShape_get_shapeIndex(
17088            self_: *mut whiteout_M2PhysicsShape,
17089        ) -> i16;
17090        pub fn whiteout_m2_M2PhysicsShape_set_shapeIndex(
17091            self_: *mut whiteout_M2PhysicsShape,
17092            value: i16,
17093        );
17094        pub fn whiteout_m2_M2PhysicsShape_get_padding04(self_: *mut whiteout_M2PhysicsShape)
17095            -> u32;
17096        pub fn whiteout_m2_M2PhysicsShape_set_padding04(
17097            self_: *mut whiteout_M2PhysicsShape,
17098            value: u32,
17099        );
17100        pub fn whiteout_m2_M2PhysicsShape_get_friction(self_: *mut whiteout_M2PhysicsShape) -> f32;
17101        pub fn whiteout_m2_M2PhysicsShape_set_friction(
17102            self_: *mut whiteout_M2PhysicsShape,
17103            value: f32,
17104        );
17105        pub fn whiteout_m2_M2PhysicsShape_get_restitution(
17106            self_: *mut whiteout_M2PhysicsShape,
17107        ) -> f32;
17108        pub fn whiteout_m2_M2PhysicsShape_set_restitution(
17109            self_: *mut whiteout_M2PhysicsShape,
17110            value: f32,
17111        );
17112        pub fn whiteout_m2_M2PhysicsShape_get_density(self_: *mut whiteout_M2PhysicsShape) -> f32;
17113        pub fn whiteout_m2_M2PhysicsShape_set_density(
17114            self_: *mut whiteout_M2PhysicsShape,
17115            value: f32,
17116        );
17117        pub fn whiteout_m2_M2PhysicsShape_get_unknown14(self_: *mut whiteout_M2PhysicsShape)
17118            -> f32;
17119        pub fn whiteout_m2_M2PhysicsShape_set_unknown14(
17120            self_: *mut whiteout_M2PhysicsShape,
17121            value: f32,
17122        );
17123        pub fn whiteout_m2_M2PhysicsShape_get_scale(self_: *mut whiteout_M2PhysicsShape) -> f32;
17124        pub fn whiteout_m2_M2PhysicsShape_set_scale(
17125            self_: *mut whiteout_M2PhysicsShape,
17126            value: f32,
17127        );
17128        pub fn whiteout_m2_M2PhysicsShape_get_unknown1c(self_: *mut whiteout_M2PhysicsShape)
17129            -> u16;
17130        pub fn whiteout_m2_M2PhysicsShape_set_unknown1c(
17131            self_: *mut whiteout_M2PhysicsShape,
17132            value: u16,
17133        );
17134        pub fn whiteout_m2_M2PhysicsShape_get_padding1e(self_: *mut whiteout_M2PhysicsShape)
17135            -> u16;
17136        pub fn whiteout_m2_M2PhysicsShape_set_padding1e(
17137            self_: *mut whiteout_M2PhysicsShape,
17138            value: u16,
17139        );
17140        // BoxShape
17141        pub fn whiteout_m2_M2BoxShape_new() -> *mut whiteout_M2BoxShape;
17142        pub fn whiteout_m2_M2BoxShape_delete(self_: *mut whiteout_M2BoxShape);
17143        pub fn whiteout_m2_M2BoxShape_get_frame(
17144            self_: *mut whiteout_M2BoxShape,
17145        ) -> *mut whiteout_M2PhysicsFrame;
17146        pub fn whiteout_m2_M2BoxShape_set_frame(
17147            self_: *mut whiteout_M2BoxShape,
17148            value: *const whiteout_M2PhysicsFrame,
17149        );
17150        pub fn whiteout_m2_M2BoxShape_get_halfExtents(
17151            self_: *mut whiteout_M2BoxShape,
17152        ) -> *mut core::ffi::c_void;
17153        pub fn whiteout_m2_M2BoxShape_set_halfExtents(
17154            self_: *mut whiteout_M2BoxShape,
17155            value: *const core::ffi::c_void,
17156        );
17157        // CapsuleShape
17158        pub fn whiteout_m2_M2CapsuleShape_new() -> *mut whiteout_M2CapsuleShape;
17159        pub fn whiteout_m2_M2CapsuleShape_delete(self_: *mut whiteout_M2CapsuleShape);
17160        pub fn whiteout_m2_M2CapsuleShape_get_localPosition1(
17161            self_: *mut whiteout_M2CapsuleShape,
17162        ) -> *mut core::ffi::c_void;
17163        pub fn whiteout_m2_M2CapsuleShape_set_localPosition1(
17164            self_: *mut whiteout_M2CapsuleShape,
17165            value: *const core::ffi::c_void,
17166        );
17167        pub fn whiteout_m2_M2CapsuleShape_get_localPosition2(
17168            self_: *mut whiteout_M2CapsuleShape,
17169        ) -> *mut core::ffi::c_void;
17170        pub fn whiteout_m2_M2CapsuleShape_set_localPosition2(
17171            self_: *mut whiteout_M2CapsuleShape,
17172            value: *const core::ffi::c_void,
17173        );
17174        pub fn whiteout_m2_M2CapsuleShape_get_radius(self_: *mut whiteout_M2CapsuleShape) -> f32;
17175        pub fn whiteout_m2_M2CapsuleShape_set_radius(
17176            self_: *mut whiteout_M2CapsuleShape,
17177            value: f32,
17178        );
17179        // SphereShape
17180        pub fn whiteout_m2_M2SphereShape_new() -> *mut whiteout_M2SphereShape;
17181        pub fn whiteout_m2_M2SphereShape_delete(self_: *mut whiteout_M2SphereShape);
17182        pub fn whiteout_m2_M2SphereShape_get_localPosition(
17183            self_: *mut whiteout_M2SphereShape,
17184        ) -> *mut core::ffi::c_void;
17185        pub fn whiteout_m2_M2SphereShape_set_localPosition(
17186            self_: *mut whiteout_M2SphereShape,
17187            value: *const core::ffi::c_void,
17188        );
17189        pub fn whiteout_m2_M2SphereShape_get_radius(self_: *mut whiteout_M2SphereShape) -> f32;
17190        pub fn whiteout_m2_M2SphereShape_set_radius(self_: *mut whiteout_M2SphereShape, value: f32);
17191        // PolytopeHalfEdge
17192        pub fn whiteout_m2_M2PolytopeHalfEdge_new() -> *mut whiteout_M2PolytopeHalfEdge;
17193        pub fn whiteout_m2_M2PolytopeHalfEdge_delete(self_: *mut whiteout_M2PolytopeHalfEdge);
17194        pub fn whiteout_m2_M2PolytopeHalfEdge_get_twinOffset(
17195            self_: *mut whiteout_M2PolytopeHalfEdge,
17196        ) -> i8;
17197        pub fn whiteout_m2_M2PolytopeHalfEdge_set_twinOffset(
17198            self_: *mut whiteout_M2PolytopeHalfEdge,
17199            value: i8,
17200        );
17201        pub fn whiteout_m2_M2PolytopeHalfEdge_get_originVertex(
17202            self_: *mut whiteout_M2PolytopeHalfEdge,
17203        ) -> u8;
17204        pub fn whiteout_m2_M2PolytopeHalfEdge_set_originVertex(
17205            self_: *mut whiteout_M2PolytopeHalfEdge,
17206            value: u8,
17207        );
17208        pub fn whiteout_m2_M2PolytopeHalfEdge_get_faceIndex(
17209            self_: *mut whiteout_M2PolytopeHalfEdge,
17210        ) -> u8;
17211        pub fn whiteout_m2_M2PolytopeHalfEdge_set_faceIndex(
17212            self_: *mut whiteout_M2PolytopeHalfEdge,
17213            value: u8,
17214        );
17215        pub fn whiteout_m2_M2PolytopeHalfEdge_get_nextEdge(
17216            self_: *mut whiteout_M2PolytopeHalfEdge,
17217        ) -> u8;
17218        pub fn whiteout_m2_M2PolytopeHalfEdge_set_nextEdge(
17219            self_: *mut whiteout_M2PolytopeHalfEdge,
17220            value: u8,
17221        );
17222        // PolytopeShape
17223        pub fn whiteout_m2_M2PolytopeShape_new() -> *mut whiteout_M2PolytopeShape;
17224        pub fn whiteout_m2_M2PolytopeShape_delete(self_: *mut whiteout_M2PolytopeShape);
17225        pub fn whiteout_m2_M2PolytopeShape_get_vertices_count(
17226            self_: *mut whiteout_M2PolytopeShape,
17227        ) -> usize;
17228        pub fn whiteout_m2_M2PolytopeShape_resize_vertices(
17229            self_: *mut whiteout_M2PolytopeShape,
17230            count: usize,
17231        );
17232        pub fn whiteout_m2_M2PolytopeShape_get_vertices_data(
17233            self_: *mut whiteout_M2PolytopeShape,
17234        ) -> *const f32;
17235        pub fn whiteout_m2_M2PolytopeShape_assign_vertices(
17236            self_: *mut whiteout_M2PolytopeShape,
17237            data: *const f32,
17238            count: usize,
17239        );
17240        pub fn whiteout_m2_M2PolytopeShape_get_facePlanes_count(
17241            self_: *mut whiteout_M2PolytopeShape,
17242        ) -> usize;
17243        pub fn whiteout_m2_M2PolytopeShape_resize_facePlanes(
17244            self_: *mut whiteout_M2PolytopeShape,
17245            count: usize,
17246        );
17247        pub fn whiteout_m2_M2PolytopeShape_get_facePlanes_data(
17248            self_: *mut whiteout_M2PolytopeShape,
17249        ) -> *const f32;
17250        pub fn whiteout_m2_M2PolytopeShape_assign_facePlanes(
17251            self_: *mut whiteout_M2PolytopeShape,
17252            data: *const f32,
17253            count: usize,
17254        );
17255        pub fn whiteout_m2_M2PolytopeShape_get_faceFirstEdges_count(
17256            self_: *mut whiteout_M2PolytopeShape,
17257        ) -> usize;
17258        pub fn whiteout_m2_M2PolytopeShape_resize_faceFirstEdges(
17259            self_: *mut whiteout_M2PolytopeShape,
17260            count: usize,
17261        );
17262        pub fn whiteout_m2_M2PolytopeShape_get_faceFirstEdges_data(
17263            self_: *mut whiteout_M2PolytopeShape,
17264        ) -> *const u8;
17265        pub fn whiteout_m2_M2PolytopeShape_assign_faceFirstEdges(
17266            self_: *mut whiteout_M2PolytopeShape,
17267            data: *const u8,
17268            count: usize,
17269        );
17270        pub fn whiteout_m2_M2PolytopeShape_get_edges_count(
17271            self_: *mut whiteout_M2PolytopeShape,
17272        ) -> usize;
17273        pub fn whiteout_m2_M2PolytopeShape_resize_edges(
17274            self_: *mut whiteout_M2PolytopeShape,
17275            count: usize,
17276        );
17277        pub fn whiteout_m2_M2PolytopeShape_get_edges_at(
17278            self_: *mut whiteout_M2PolytopeShape,
17279            index: usize,
17280        ) -> *mut whiteout_M2PolytopeHalfEdge;
17281        pub fn whiteout_m2_M2PolytopeShape_get_centroid(
17282            self_: *mut whiteout_M2PolytopeShape,
17283        ) -> *mut core::ffi::c_void;
17284        pub fn whiteout_m2_M2PolytopeShape_set_centroid(
17285            self_: *mut whiteout_M2PolytopeShape,
17286            value: *const core::ffi::c_void,
17287        );
17288        pub fn whiteout_m2_M2PolytopeShape_get_volume(self_: *mut whiteout_M2PolytopeShape) -> f32;
17289        pub fn whiteout_m2_M2PolytopeShape_set_volume(
17290            self_: *mut whiteout_M2PolytopeShape,
17291            value: f32,
17292        );
17293        pub fn whiteout_m2_M2PolytopeShape_get_surfaceArea(
17294            self_: *mut whiteout_M2PolytopeShape,
17295        ) -> f32;
17296        pub fn whiteout_m2_M2PolytopeShape_set_surfaceArea(
17297            self_: *mut whiteout_M2PolytopeShape,
17298            value: f32,
17299        );
17300        pub fn whiteout_m2_M2PolytopeShape_get_padding04(
17301            self_: *mut whiteout_M2PolytopeShape,
17302        ) -> u32;
17303        pub fn whiteout_m2_M2PolytopeShape_set_padding04(
17304            self_: *mut whiteout_M2PolytopeShape,
17305            value: u32,
17306        );
17307        pub fn whiteout_m2_M2PolytopeShape_get_padding14(
17308            self_: *mut whiteout_M2PolytopeShape,
17309        ) -> u32;
17310        pub fn whiteout_m2_M2PolytopeShape_set_padding14(
17311            self_: *mut whiteout_M2PolytopeShape,
17312            value: u32,
17313        );
17314        pub fn whiteout_m2_M2PolytopeShape_get_padding2c(
17315            self_: *mut whiteout_M2PolytopeShape,
17316        ) -> u32;
17317        pub fn whiteout_m2_M2PolytopeShape_set_padding2c(
17318            self_: *mut whiteout_M2PolytopeShape,
17319            value: u32,
17320        );
17321        pub fn whiteout_m2_M2PolytopeShape_get_padding4c(
17322            self_: *mut whiteout_M2PolytopeShape,
17323        ) -> u32;
17324        pub fn whiteout_m2_M2PolytopeShape_set_padding4c(
17325            self_: *mut whiteout_M2PolytopeShape,
17326            value: u32,
17327        );
17328        // PhysicsJoint
17329        pub fn whiteout_m2_M2PhysicsJoint_new() -> *mut whiteout_M2PhysicsJoint;
17330        pub fn whiteout_m2_M2PhysicsJoint_delete(self_: *mut whiteout_M2PhysicsJoint);
17331        pub fn whiteout_m2_M2PhysicsJoint_get_bodyAIndex(
17332            self_: *mut whiteout_M2PhysicsJoint,
17333        ) -> u32;
17334        pub fn whiteout_m2_M2PhysicsJoint_set_bodyAIndex(
17335            self_: *mut whiteout_M2PhysicsJoint,
17336            value: u32,
17337        );
17338        pub fn whiteout_m2_M2PhysicsJoint_get_bodyBIndex(
17339            self_: *mut whiteout_M2PhysicsJoint,
17340        ) -> u32;
17341        pub fn whiteout_m2_M2PhysicsJoint_set_bodyBIndex(
17342            self_: *mut whiteout_M2PhysicsJoint,
17343            value: u32,
17344        );
17345        pub fn whiteout_m2_M2PhysicsJoint_get_padding08(self_: *mut whiteout_M2PhysicsJoint)
17346            -> u32;
17347        pub fn whiteout_m2_M2PhysicsJoint_set_padding08(
17348            self_: *mut whiteout_M2PhysicsJoint,
17349            value: u32,
17350        );
17351        pub fn whiteout_m2_M2PhysicsJoint_get_jointType(self_: *mut whiteout_M2PhysicsJoint)
17352            -> i32;
17353        pub fn whiteout_m2_M2PhysicsJoint_set_jointType(
17354            self_: *mut whiteout_M2PhysicsJoint,
17355            value: i32,
17356        );
17357        pub fn whiteout_m2_M2PhysicsJoint_get_jointId(self_: *mut whiteout_M2PhysicsJoint) -> i16;
17358        pub fn whiteout_m2_M2PhysicsJoint_set_jointId(
17359            self_: *mut whiteout_M2PhysicsJoint,
17360            value: i16,
17361        );
17362        // WeldJoint
17363        pub fn whiteout_m2_M2WeldJoint_new() -> *mut whiteout_M2WeldJoint;
17364        pub fn whiteout_m2_M2WeldJoint_delete(self_: *mut whiteout_M2WeldJoint);
17365        pub fn whiteout_m2_M2WeldJoint_get_frameA(
17366            self_: *mut whiteout_M2WeldJoint,
17367        ) -> *mut whiteout_M2PhysicsFrame;
17368        pub fn whiteout_m2_M2WeldJoint_set_frameA(
17369            self_: *mut whiteout_M2WeldJoint,
17370            value: *const whiteout_M2PhysicsFrame,
17371        );
17372        pub fn whiteout_m2_M2WeldJoint_get_frameB(
17373            self_: *mut whiteout_M2WeldJoint,
17374        ) -> *mut whiteout_M2PhysicsFrame;
17375        pub fn whiteout_m2_M2WeldJoint_set_frameB(
17376            self_: *mut whiteout_M2WeldJoint,
17377            value: *const whiteout_M2PhysicsFrame,
17378        );
17379        pub fn whiteout_m2_M2WeldJoint_get_angularFrequencyHz(
17380            self_: *mut whiteout_M2WeldJoint,
17381        ) -> f32;
17382        pub fn whiteout_m2_M2WeldJoint_set_angularFrequencyHz(
17383            self_: *mut whiteout_M2WeldJoint,
17384            value: f32,
17385        );
17386        pub fn whiteout_m2_M2WeldJoint_get_angularDampingRatio(
17387            self_: *mut whiteout_M2WeldJoint,
17388        ) -> f32;
17389        pub fn whiteout_m2_M2WeldJoint_set_angularDampingRatio(
17390            self_: *mut whiteout_M2WeldJoint,
17391            value: f32,
17392        );
17393        pub fn whiteout_m2_M2WeldJoint_get_linearFrequencyHz(
17394            self_: *mut whiteout_M2WeldJoint,
17395        ) -> f32;
17396        pub fn whiteout_m2_M2WeldJoint_set_linearFrequencyHz(
17397            self_: *mut whiteout_M2WeldJoint,
17398            value: f32,
17399        );
17400        pub fn whiteout_m2_M2WeldJoint_get_linearDampingRatio(
17401            self_: *mut whiteout_M2WeldJoint,
17402        ) -> f32;
17403        pub fn whiteout_m2_M2WeldJoint_set_linearDampingRatio(
17404            self_: *mut whiteout_M2WeldJoint,
17405            value: f32,
17406        );
17407        pub fn whiteout_m2_M2WeldJoint_get_unknown70(self_: *mut whiteout_M2WeldJoint) -> f32;
17408        pub fn whiteout_m2_M2WeldJoint_set_unknown70(self_: *mut whiteout_M2WeldJoint, value: f32);
17409        // SphericalJoint
17410        pub fn whiteout_m2_M2SphericalJoint_new() -> *mut whiteout_M2SphericalJoint;
17411        pub fn whiteout_m2_M2SphericalJoint_delete(self_: *mut whiteout_M2SphericalJoint);
17412        pub fn whiteout_m2_M2SphericalJoint_get_anchorA(
17413            self_: *mut whiteout_M2SphericalJoint,
17414        ) -> *mut core::ffi::c_void;
17415        pub fn whiteout_m2_M2SphericalJoint_set_anchorA(
17416            self_: *mut whiteout_M2SphericalJoint,
17417            value: *const core::ffi::c_void,
17418        );
17419        pub fn whiteout_m2_M2SphericalJoint_get_anchorB(
17420            self_: *mut whiteout_M2SphericalJoint,
17421        ) -> *mut core::ffi::c_void;
17422        pub fn whiteout_m2_M2SphericalJoint_set_anchorB(
17423            self_: *mut whiteout_M2SphericalJoint,
17424            value: *const core::ffi::c_void,
17425        );
17426        pub fn whiteout_m2_M2SphericalJoint_get_frictionTorque(
17427            self_: *mut whiteout_M2SphericalJoint,
17428        ) -> f32;
17429        pub fn whiteout_m2_M2SphericalJoint_set_frictionTorque(
17430            self_: *mut whiteout_M2SphericalJoint,
17431            value: f32,
17432        );
17433        // ShoulderJoint
17434        pub fn whiteout_m2_M2ShoulderJoint_new() -> *mut whiteout_M2ShoulderJoint;
17435        pub fn whiteout_m2_M2ShoulderJoint_delete(self_: *mut whiteout_M2ShoulderJoint);
17436        pub fn whiteout_m2_M2ShoulderJoint_get_frameA(
17437            self_: *mut whiteout_M2ShoulderJoint,
17438        ) -> *mut whiteout_M2PhysicsFrame;
17439        pub fn whiteout_m2_M2ShoulderJoint_set_frameA(
17440            self_: *mut whiteout_M2ShoulderJoint,
17441            value: *const whiteout_M2PhysicsFrame,
17442        );
17443        pub fn whiteout_m2_M2ShoulderJoint_get_frameB(
17444            self_: *mut whiteout_M2ShoulderJoint,
17445        ) -> *mut whiteout_M2PhysicsFrame;
17446        pub fn whiteout_m2_M2ShoulderJoint_set_frameB(
17447            self_: *mut whiteout_M2ShoulderJoint,
17448            value: *const whiteout_M2PhysicsFrame,
17449        );
17450        pub fn whiteout_m2_M2ShoulderJoint_get_lowerTwistAngle(
17451            self_: *mut whiteout_M2ShoulderJoint,
17452        ) -> f32;
17453        pub fn whiteout_m2_M2ShoulderJoint_set_lowerTwistAngle(
17454            self_: *mut whiteout_M2ShoulderJoint,
17455            value: f32,
17456        );
17457        pub fn whiteout_m2_M2ShoulderJoint_get_upperTwistAngle(
17458            self_: *mut whiteout_M2ShoulderJoint,
17459        ) -> f32;
17460        pub fn whiteout_m2_M2ShoulderJoint_set_upperTwistAngle(
17461            self_: *mut whiteout_M2ShoulderJoint,
17462            value: f32,
17463        );
17464        pub fn whiteout_m2_M2ShoulderJoint_get_coneAngle(
17465            self_: *mut whiteout_M2ShoulderJoint,
17466        ) -> f32;
17467        pub fn whiteout_m2_M2ShoulderJoint_set_coneAngle(
17468            self_: *mut whiteout_M2ShoulderJoint,
17469            value: f32,
17470        );
17471        pub fn whiteout_m2_M2ShoulderJoint_get_maxMotorTorque(
17472            self_: *mut whiteout_M2ShoulderJoint,
17473        ) -> f32;
17474        pub fn whiteout_m2_M2ShoulderJoint_set_maxMotorTorque(
17475            self_: *mut whiteout_M2ShoulderJoint,
17476            value: f32,
17477        );
17478        pub fn whiteout_m2_M2ShoulderJoint_get_motorMode(
17479            self_: *mut whiteout_M2ShoulderJoint,
17480        ) -> u32;
17481        pub fn whiteout_m2_M2ShoulderJoint_set_motorMode(
17482            self_: *mut whiteout_M2ShoulderJoint,
17483            value: u32,
17484        );
17485        pub fn whiteout_m2_M2ShoulderJoint_get_motorFrequencyHz(
17486            self_: *mut whiteout_M2ShoulderJoint,
17487        ) -> f32;
17488        pub fn whiteout_m2_M2ShoulderJoint_set_motorFrequencyHz(
17489            self_: *mut whiteout_M2ShoulderJoint,
17490            value: f32,
17491        );
17492        pub fn whiteout_m2_M2ShoulderJoint_get_motorDampingRatio(
17493            self_: *mut whiteout_M2ShoulderJoint,
17494        ) -> f32;
17495        pub fn whiteout_m2_M2ShoulderJoint_set_motorDampingRatio(
17496            self_: *mut whiteout_M2ShoulderJoint,
17497            value: f32,
17498        );
17499        // PrismaticJoint
17500        pub fn whiteout_m2_M2PrismaticJoint_new() -> *mut whiteout_M2PrismaticJoint;
17501        pub fn whiteout_m2_M2PrismaticJoint_delete(self_: *mut whiteout_M2PrismaticJoint);
17502        pub fn whiteout_m2_M2PrismaticJoint_get_frameA(
17503            self_: *mut whiteout_M2PrismaticJoint,
17504        ) -> *mut whiteout_M2PhysicsFrame;
17505        pub fn whiteout_m2_M2PrismaticJoint_set_frameA(
17506            self_: *mut whiteout_M2PrismaticJoint,
17507            value: *const whiteout_M2PhysicsFrame,
17508        );
17509        pub fn whiteout_m2_M2PrismaticJoint_get_frameB(
17510            self_: *mut whiteout_M2PrismaticJoint,
17511        ) -> *mut whiteout_M2PhysicsFrame;
17512        pub fn whiteout_m2_M2PrismaticJoint_set_frameB(
17513            self_: *mut whiteout_M2PrismaticJoint,
17514            value: *const whiteout_M2PhysicsFrame,
17515        );
17516        pub fn whiteout_m2_M2PrismaticJoint_get_lowerLimit(
17517            self_: *mut whiteout_M2PrismaticJoint,
17518        ) -> f32;
17519        pub fn whiteout_m2_M2PrismaticJoint_set_lowerLimit(
17520            self_: *mut whiteout_M2PrismaticJoint,
17521            value: f32,
17522        );
17523        pub fn whiteout_m2_M2PrismaticJoint_get_upperLimit(
17524            self_: *mut whiteout_M2PrismaticJoint,
17525        ) -> f32;
17526        pub fn whiteout_m2_M2PrismaticJoint_set_upperLimit(
17527            self_: *mut whiteout_M2PrismaticJoint,
17528            value: f32,
17529        );
17530        pub fn whiteout_m2_M2PrismaticJoint_get_unknown68(
17531            self_: *mut whiteout_M2PrismaticJoint,
17532        ) -> f32;
17533        pub fn whiteout_m2_M2PrismaticJoint_set_unknown68(
17534            self_: *mut whiteout_M2PrismaticJoint,
17535            value: f32,
17536        );
17537        pub fn whiteout_m2_M2PrismaticJoint_get_maxMotorForce(
17538            self_: *mut whiteout_M2PrismaticJoint,
17539        ) -> f32;
17540        pub fn whiteout_m2_M2PrismaticJoint_set_maxMotorForce(
17541            self_: *mut whiteout_M2PrismaticJoint,
17542            value: f32,
17543        );
17544        pub fn whiteout_m2_M2PrismaticJoint_get_unknown70(
17545            self_: *mut whiteout_M2PrismaticJoint,
17546        ) -> f32;
17547        pub fn whiteout_m2_M2PrismaticJoint_set_unknown70(
17548            self_: *mut whiteout_M2PrismaticJoint,
17549            value: f32,
17550        );
17551        pub fn whiteout_m2_M2PrismaticJoint_get_motorMode(
17552            self_: *mut whiteout_M2PrismaticJoint,
17553        ) -> u32;
17554        pub fn whiteout_m2_M2PrismaticJoint_set_motorMode(
17555            self_: *mut whiteout_M2PrismaticJoint,
17556            value: u32,
17557        );
17558        pub fn whiteout_m2_M2PrismaticJoint_get_motorFrequencyHz(
17559            self_: *mut whiteout_M2PrismaticJoint,
17560        ) -> f32;
17561        pub fn whiteout_m2_M2PrismaticJoint_set_motorFrequencyHz(
17562            self_: *mut whiteout_M2PrismaticJoint,
17563            value: f32,
17564        );
17565        pub fn whiteout_m2_M2PrismaticJoint_get_motorDampingRatio(
17566            self_: *mut whiteout_M2PrismaticJoint,
17567        ) -> f32;
17568        pub fn whiteout_m2_M2PrismaticJoint_set_motorDampingRatio(
17569            self_: *mut whiteout_M2PrismaticJoint,
17570            value: f32,
17571        );
17572        // RevoluteJoint
17573        pub fn whiteout_m2_M2RevoluteJoint_new() -> *mut whiteout_M2RevoluteJoint;
17574        pub fn whiteout_m2_M2RevoluteJoint_delete(self_: *mut whiteout_M2RevoluteJoint);
17575        pub fn whiteout_m2_M2RevoluteJoint_get_frameA(
17576            self_: *mut whiteout_M2RevoluteJoint,
17577        ) -> *mut whiteout_M2PhysicsFrame;
17578        pub fn whiteout_m2_M2RevoluteJoint_set_frameA(
17579            self_: *mut whiteout_M2RevoluteJoint,
17580            value: *const whiteout_M2PhysicsFrame,
17581        );
17582        pub fn whiteout_m2_M2RevoluteJoint_get_frameB(
17583            self_: *mut whiteout_M2RevoluteJoint,
17584        ) -> *mut whiteout_M2PhysicsFrame;
17585        pub fn whiteout_m2_M2RevoluteJoint_set_frameB(
17586            self_: *mut whiteout_M2RevoluteJoint,
17587            value: *const whiteout_M2PhysicsFrame,
17588        );
17589        pub fn whiteout_m2_M2RevoluteJoint_get_lowerAngle(
17590            self_: *mut whiteout_M2RevoluteJoint,
17591        ) -> f32;
17592        pub fn whiteout_m2_M2RevoluteJoint_set_lowerAngle(
17593            self_: *mut whiteout_M2RevoluteJoint,
17594            value: f32,
17595        );
17596        pub fn whiteout_m2_M2RevoluteJoint_get_upperAngle(
17597            self_: *mut whiteout_M2RevoluteJoint,
17598        ) -> f32;
17599        pub fn whiteout_m2_M2RevoluteJoint_set_upperAngle(
17600            self_: *mut whiteout_M2RevoluteJoint,
17601            value: f32,
17602        );
17603        pub fn whiteout_m2_M2RevoluteJoint_get_maxMotorTorque(
17604            self_: *mut whiteout_M2RevoluteJoint,
17605        ) -> f32;
17606        pub fn whiteout_m2_M2RevoluteJoint_set_maxMotorTorque(
17607            self_: *mut whiteout_M2RevoluteJoint,
17608            value: f32,
17609        );
17610        pub fn whiteout_m2_M2RevoluteJoint_get_motorMode(
17611            self_: *mut whiteout_M2RevoluteJoint,
17612        ) -> u32;
17613        pub fn whiteout_m2_M2RevoluteJoint_set_motorMode(
17614            self_: *mut whiteout_M2RevoluteJoint,
17615            value: u32,
17616        );
17617        pub fn whiteout_m2_M2RevoluteJoint_get_motorFrequencyHz(
17618            self_: *mut whiteout_M2RevoluteJoint,
17619        ) -> f32;
17620        pub fn whiteout_m2_M2RevoluteJoint_set_motorFrequencyHz(
17621            self_: *mut whiteout_M2RevoluteJoint,
17622            value: f32,
17623        );
17624        pub fn whiteout_m2_M2RevoluteJoint_get_motorDampingRatio(
17625            self_: *mut whiteout_M2RevoluteJoint,
17626        ) -> f32;
17627        pub fn whiteout_m2_M2RevoluteJoint_set_motorDampingRatio(
17628            self_: *mut whiteout_M2RevoluteJoint,
17629            value: f32,
17630        );
17631        // DistanceJoint
17632        pub fn whiteout_m2_M2DistanceJoint_new() -> *mut whiteout_M2DistanceJoint;
17633        pub fn whiteout_m2_M2DistanceJoint_delete(self_: *mut whiteout_M2DistanceJoint);
17634        pub fn whiteout_m2_M2DistanceJoint_get_localAnchorA(
17635            self_: *mut whiteout_M2DistanceJoint,
17636        ) -> *mut core::ffi::c_void;
17637        pub fn whiteout_m2_M2DistanceJoint_set_localAnchorA(
17638            self_: *mut whiteout_M2DistanceJoint,
17639            value: *const core::ffi::c_void,
17640        );
17641        pub fn whiteout_m2_M2DistanceJoint_get_localAnchorB(
17642            self_: *mut whiteout_M2DistanceJoint,
17643        ) -> *mut core::ffi::c_void;
17644        pub fn whiteout_m2_M2DistanceJoint_set_localAnchorB(
17645            self_: *mut whiteout_M2DistanceJoint,
17646            value: *const core::ffi::c_void,
17647        );
17648        pub fn whiteout_m2_M2DistanceJoint_get_distance(
17649            self_: *mut whiteout_M2DistanceJoint,
17650        ) -> f32;
17651        pub fn whiteout_m2_M2DistanceJoint_set_distance(
17652            self_: *mut whiteout_M2DistanceJoint,
17653            value: f32,
17654        );
17655        // PhysicsTuning
17656        pub fn whiteout_m2_M2PhysicsTuning_new() -> *mut whiteout_M2PhysicsTuning;
17657        pub fn whiteout_m2_M2PhysicsTuning_delete(self_: *mut whiteout_M2PhysicsTuning);
17658        pub fn whiteout_m2_M2PhysicsTuning_values_size() -> usize;
17659        pub fn whiteout_m2_M2PhysicsTuning_get_values_at(
17660            self_: *mut whiteout_M2PhysicsTuning,
17661            index: usize,
17662        ) -> f32;
17663        pub fn whiteout_m2_M2PhysicsTuning_set_values_at(
17664            self_: *mut whiteout_M2PhysicsTuning,
17665            index: usize,
17666            value: f32,
17667        );
17668        // PhysicsUnknownChunk
17669        pub fn whiteout_m2_M2PhysicsUnknownChunk_new() -> *mut whiteout_M2PhysicsUnknownChunk;
17670        pub fn whiteout_m2_M2PhysicsUnknownChunk_delete(self_: *mut whiteout_M2PhysicsUnknownChunk);
17671        pub fn whiteout_m2_M2PhysicsUnknownChunk_tag_size() -> usize;
17672        pub fn whiteout_m2_M2PhysicsUnknownChunk_get_tag_at(
17673            self_: *mut whiteout_M2PhysicsUnknownChunk,
17674            index: usize,
17675        ) -> i8;
17676        pub fn whiteout_m2_M2PhysicsUnknownChunk_set_tag_at(
17677            self_: *mut whiteout_M2PhysicsUnknownChunk,
17678            index: usize,
17679            value: i8,
17680        );
17681        pub fn whiteout_m2_M2PhysicsUnknownChunk_get_data_count(
17682            self_: *mut whiteout_M2PhysicsUnknownChunk,
17683        ) -> usize;
17684        pub fn whiteout_m2_M2PhysicsUnknownChunk_resize_data(
17685            self_: *mut whiteout_M2PhysicsUnknownChunk,
17686            count: usize,
17687        );
17688        pub fn whiteout_m2_M2PhysicsUnknownChunk_get_data_data(
17689            self_: *mut whiteout_M2PhysicsUnknownChunk,
17690        ) -> *const u8;
17691        pub fn whiteout_m2_M2PhysicsUnknownChunk_assign_data(
17692            self_: *mut whiteout_M2PhysicsUnknownChunk,
17693            data: *const u8,
17694            count: usize,
17695        );
17696        // PhysicsData
17697        pub fn whiteout_m2_M2PhysicsData_new() -> *mut whiteout_M2PhysicsData;
17698        pub fn whiteout_m2_M2PhysicsData_delete(self_: *mut whiteout_M2PhysicsData);
17699        pub fn whiteout_m2_M2PhysicsData_get_version(self_: *mut whiteout_M2PhysicsData) -> u16;
17700        pub fn whiteout_m2_M2PhysicsData_set_version(
17701            self_: *mut whiteout_M2PhysicsData,
17702            value: u16,
17703        );
17704        pub fn whiteout_m2_M2PhysicsData_get_bodies_count(
17705            self_: *mut whiteout_M2PhysicsData,
17706        ) -> usize;
17707        pub fn whiteout_m2_M2PhysicsData_resize_bodies(
17708            self_: *mut whiteout_M2PhysicsData,
17709            count: usize,
17710        );
17711        pub fn whiteout_m2_M2PhysicsData_get_bodies_at(
17712            self_: *mut whiteout_M2PhysicsData,
17713            index: usize,
17714        ) -> *mut whiteout_M2PhysicsBody;
17715        pub fn whiteout_m2_M2PhysicsData_get_shapes_count(
17716            self_: *mut whiteout_M2PhysicsData,
17717        ) -> usize;
17718        pub fn whiteout_m2_M2PhysicsData_resize_shapes(
17719            self_: *mut whiteout_M2PhysicsData,
17720            count: usize,
17721        );
17722        pub fn whiteout_m2_M2PhysicsData_get_shapes_at(
17723            self_: *mut whiteout_M2PhysicsData,
17724            index: usize,
17725        ) -> *mut whiteout_M2PhysicsShape;
17726        pub fn whiteout_m2_M2PhysicsData_get_boxShapes_count(
17727            self_: *mut whiteout_M2PhysicsData,
17728        ) -> usize;
17729        pub fn whiteout_m2_M2PhysicsData_resize_boxShapes(
17730            self_: *mut whiteout_M2PhysicsData,
17731            count: usize,
17732        );
17733        pub fn whiteout_m2_M2PhysicsData_get_boxShapes_at(
17734            self_: *mut whiteout_M2PhysicsData,
17735            index: usize,
17736        ) -> *mut whiteout_M2BoxShape;
17737        pub fn whiteout_m2_M2PhysicsData_get_capsuleShapes_count(
17738            self_: *mut whiteout_M2PhysicsData,
17739        ) -> usize;
17740        pub fn whiteout_m2_M2PhysicsData_resize_capsuleShapes(
17741            self_: *mut whiteout_M2PhysicsData,
17742            count: usize,
17743        );
17744        pub fn whiteout_m2_M2PhysicsData_get_capsuleShapes_at(
17745            self_: *mut whiteout_M2PhysicsData,
17746            index: usize,
17747        ) -> *mut whiteout_M2CapsuleShape;
17748        pub fn whiteout_m2_M2PhysicsData_get_sphereShapes_count(
17749            self_: *mut whiteout_M2PhysicsData,
17750        ) -> usize;
17751        pub fn whiteout_m2_M2PhysicsData_resize_sphereShapes(
17752            self_: *mut whiteout_M2PhysicsData,
17753            count: usize,
17754        );
17755        pub fn whiteout_m2_M2PhysicsData_get_sphereShapes_at(
17756            self_: *mut whiteout_M2PhysicsData,
17757            index: usize,
17758        ) -> *mut whiteout_M2SphereShape;
17759        pub fn whiteout_m2_M2PhysicsData_get_polytopeShapes_count(
17760            self_: *mut whiteout_M2PhysicsData,
17761        ) -> usize;
17762        pub fn whiteout_m2_M2PhysicsData_resize_polytopeShapes(
17763            self_: *mut whiteout_M2PhysicsData,
17764            count: usize,
17765        );
17766        pub fn whiteout_m2_M2PhysicsData_get_polytopeShapes_at(
17767            self_: *mut whiteout_M2PhysicsData,
17768            index: usize,
17769        ) -> *mut whiteout_M2PolytopeShape;
17770        pub fn whiteout_m2_M2PhysicsData_get_joints_count(
17771            self_: *mut whiteout_M2PhysicsData,
17772        ) -> usize;
17773        pub fn whiteout_m2_M2PhysicsData_resize_joints(
17774            self_: *mut whiteout_M2PhysicsData,
17775            count: usize,
17776        );
17777        pub fn whiteout_m2_M2PhysicsData_get_joints_at(
17778            self_: *mut whiteout_M2PhysicsData,
17779            index: usize,
17780        ) -> *mut whiteout_M2PhysicsJoint;
17781        pub fn whiteout_m2_M2PhysicsData_get_weldJoints_count(
17782            self_: *mut whiteout_M2PhysicsData,
17783        ) -> usize;
17784        pub fn whiteout_m2_M2PhysicsData_resize_weldJoints(
17785            self_: *mut whiteout_M2PhysicsData,
17786            count: usize,
17787        );
17788        pub fn whiteout_m2_M2PhysicsData_get_weldJoints_at(
17789            self_: *mut whiteout_M2PhysicsData,
17790            index: usize,
17791        ) -> *mut whiteout_M2WeldJoint;
17792        pub fn whiteout_m2_M2PhysicsData_get_sphericalJoints_count(
17793            self_: *mut whiteout_M2PhysicsData,
17794        ) -> usize;
17795        pub fn whiteout_m2_M2PhysicsData_resize_sphericalJoints(
17796            self_: *mut whiteout_M2PhysicsData,
17797            count: usize,
17798        );
17799        pub fn whiteout_m2_M2PhysicsData_get_sphericalJoints_at(
17800            self_: *mut whiteout_M2PhysicsData,
17801            index: usize,
17802        ) -> *mut whiteout_M2SphericalJoint;
17803        pub fn whiteout_m2_M2PhysicsData_get_shoulderJoints_count(
17804            self_: *mut whiteout_M2PhysicsData,
17805        ) -> usize;
17806        pub fn whiteout_m2_M2PhysicsData_resize_shoulderJoints(
17807            self_: *mut whiteout_M2PhysicsData,
17808            count: usize,
17809        );
17810        pub fn whiteout_m2_M2PhysicsData_get_shoulderJoints_at(
17811            self_: *mut whiteout_M2PhysicsData,
17812            index: usize,
17813        ) -> *mut whiteout_M2ShoulderJoint;
17814        pub fn whiteout_m2_M2PhysicsData_get_prismaticJoints_count(
17815            self_: *mut whiteout_M2PhysicsData,
17816        ) -> usize;
17817        pub fn whiteout_m2_M2PhysicsData_resize_prismaticJoints(
17818            self_: *mut whiteout_M2PhysicsData,
17819            count: usize,
17820        );
17821        pub fn whiteout_m2_M2PhysicsData_get_prismaticJoints_at(
17822            self_: *mut whiteout_M2PhysicsData,
17823            index: usize,
17824        ) -> *mut whiteout_M2PrismaticJoint;
17825        pub fn whiteout_m2_M2PhysicsData_get_revoluteJoints_count(
17826            self_: *mut whiteout_M2PhysicsData,
17827        ) -> usize;
17828        pub fn whiteout_m2_M2PhysicsData_resize_revoluteJoints(
17829            self_: *mut whiteout_M2PhysicsData,
17830            count: usize,
17831        );
17832        pub fn whiteout_m2_M2PhysicsData_get_revoluteJoints_at(
17833            self_: *mut whiteout_M2PhysicsData,
17834            index: usize,
17835        ) -> *mut whiteout_M2RevoluteJoint;
17836        pub fn whiteout_m2_M2PhysicsData_get_distanceJoints_count(
17837            self_: *mut whiteout_M2PhysicsData,
17838        ) -> usize;
17839        pub fn whiteout_m2_M2PhysicsData_resize_distanceJoints(
17840            self_: *mut whiteout_M2PhysicsData,
17841            count: usize,
17842        );
17843        pub fn whiteout_m2_M2PhysicsData_get_distanceJoints_at(
17844            self_: *mut whiteout_M2PhysicsData,
17845            index: usize,
17846        ) -> *mut whiteout_M2DistanceJoint;
17847        pub fn whiteout_m2_M2PhysicsData_get_tuning_count(
17848            self_: *mut whiteout_M2PhysicsData,
17849        ) -> usize;
17850        pub fn whiteout_m2_M2PhysicsData_resize_tuning(
17851            self_: *mut whiteout_M2PhysicsData,
17852            count: usize,
17853        );
17854        pub fn whiteout_m2_M2PhysicsData_get_tuning_at(
17855            self_: *mut whiteout_M2PhysicsData,
17856            index: usize,
17857        ) -> *mut whiteout_M2PhysicsTuning;
17858        // BoneOverride
17859        pub fn whiteout_m2_M2BoneOverride_new() -> *mut whiteout_M2BoneOverride;
17860        pub fn whiteout_m2_M2BoneOverride_delete(self_: *mut whiteout_M2BoneOverride);
17861        pub fn whiteout_m2_M2BoneOverride_get_boneIndex(self_: *mut whiteout_M2BoneOverride)
17862            -> u16;
17863        pub fn whiteout_m2_M2BoneOverride_set_boneIndex(
17864            self_: *mut whiteout_M2BoneOverride,
17865            value: u16,
17866        );
17867        // BoneOverrideSet
17868        pub fn whiteout_m2_M2BoneOverrideSet_new() -> *mut whiteout_M2BoneOverrideSet;
17869        pub fn whiteout_m2_M2BoneOverrideSet_delete(self_: *mut whiteout_M2BoneOverrideSet);
17870        pub fn whiteout_m2_M2BoneOverrideSet_get_version(
17871            self_: *mut whiteout_M2BoneOverrideSet,
17872        ) -> u32;
17873        pub fn whiteout_m2_M2BoneOverrideSet_set_version(
17874            self_: *mut whiteout_M2BoneOverrideSet,
17875            value: u32,
17876        );
17877        pub fn whiteout_m2_M2BoneOverrideSet_get_overrides_count(
17878            self_: *mut whiteout_M2BoneOverrideSet,
17879        ) -> usize;
17880        pub fn whiteout_m2_M2BoneOverrideSet_resize_overrides(
17881            self_: *mut whiteout_M2BoneOverrideSet,
17882            count: usize,
17883        );
17884        pub fn whiteout_m2_M2BoneOverrideSet_get_overrides_at(
17885            self_: *mut whiteout_M2BoneOverrideSet,
17886            index: usize,
17887        ) -> *mut whiteout_M2BoneOverride;
17888        // Model
17889        pub fn whiteout_m2_M2Model_new() -> *mut whiteout_M2Model;
17890        pub fn whiteout_m2_M2Model_delete(self_: *mut whiteout_M2Model);
17891        pub fn whiteout_m2_M2Model_get_modelName(self_: *mut whiteout_M2Model) -> RawCString;
17892        pub fn whiteout_m2_M2Model_set_modelName(
17893            self_: *mut whiteout_M2Model,
17894            value: *const core::ffi::c_char,
17895        );
17896        pub fn whiteout_m2_M2Model_get_globalFlags(
17897            self_: *mut whiteout_M2Model,
17898        ) -> *mut whiteout_M2GlobalFlags;
17899        pub fn whiteout_m2_M2Model_set_globalFlags(
17900            self_: *mut whiteout_M2Model,
17901            value: *const whiteout_M2GlobalFlags,
17902        );
17903        pub fn whiteout_m2_M2Model_get_globalLoops_count(self_: *mut whiteout_M2Model) -> usize;
17904        pub fn whiteout_m2_M2Model_resize_globalLoops(self_: *mut whiteout_M2Model, count: usize);
17905        pub fn whiteout_m2_M2Model_get_globalLoops_at(
17906            self_: *mut whiteout_M2Model,
17907            index: usize,
17908        ) -> *mut whiteout_M2GlobalSequence;
17909        pub fn whiteout_m2_M2Model_get_sequences_count(self_: *mut whiteout_M2Model) -> usize;
17910        pub fn whiteout_m2_M2Model_resize_sequences(self_: *mut whiteout_M2Model, count: usize);
17911        pub fn whiteout_m2_M2Model_get_sequences_at(
17912            self_: *mut whiteout_M2Model,
17913            index: usize,
17914        ) -> *mut whiteout_M2Sequence;
17915        pub fn whiteout_m2_M2Model_get_sequenceIdxHashById_count(
17916            self_: *mut whiteout_M2Model,
17917        ) -> usize;
17918        pub fn whiteout_m2_M2Model_resize_sequenceIdxHashById(
17919            self_: *mut whiteout_M2Model,
17920            count: usize,
17921        );
17922        pub fn whiteout_m2_M2Model_get_sequenceIdxHashById_data(
17923            self_: *mut whiteout_M2Model,
17924        ) -> *const u16;
17925        pub fn whiteout_m2_M2Model_assign_sequenceIdxHashById(
17926            self_: *mut whiteout_M2Model,
17927            data: *const u16,
17928            count: usize,
17929        );
17930        pub fn whiteout_m2_M2Model_get_bones_count(self_: *mut whiteout_M2Model) -> usize;
17931        pub fn whiteout_m2_M2Model_resize_bones(self_: *mut whiteout_M2Model, count: usize);
17932        pub fn whiteout_m2_M2Model_get_bones_at(
17933            self_: *mut whiteout_M2Model,
17934            index: usize,
17935        ) -> *mut whiteout_M2Bone;
17936        pub fn whiteout_m2_M2Model_get_keyBoneIds_count(self_: *mut whiteout_M2Model) -> usize;
17937        pub fn whiteout_m2_M2Model_resize_keyBoneIds(self_: *mut whiteout_M2Model, count: usize);
17938        pub fn whiteout_m2_M2Model_get_keyBoneIds_data(self_: *mut whiteout_M2Model) -> *const u16;
17939        pub fn whiteout_m2_M2Model_assign_keyBoneIds(
17940            self_: *mut whiteout_M2Model,
17941            data: *const u16,
17942            count: usize,
17943        );
17944        pub fn whiteout_m2_M2Model_get_vertices_count(self_: *mut whiteout_M2Model) -> usize;
17945        pub fn whiteout_m2_M2Model_resize_vertices(self_: *mut whiteout_M2Model, count: usize);
17946        pub fn whiteout_m2_M2Model_get_vertices_at(
17947            self_: *mut whiteout_M2Model,
17948            index: usize,
17949        ) -> *mut whiteout_M2Vertex;
17950        pub fn whiteout_m2_M2Model_get_skinProfiles_count(self_: *mut whiteout_M2Model) -> usize;
17951        pub fn whiteout_m2_M2Model_resize_skinProfiles(self_: *mut whiteout_M2Model, count: usize);
17952        pub fn whiteout_m2_M2Model_get_skinProfiles_at(
17953            self_: *mut whiteout_M2Model,
17954            index: usize,
17955        ) -> *mut whiteout_M2SkinProfile;
17956        pub fn whiteout_m2_M2Model_get_lodProfiles_count(self_: *mut whiteout_M2Model) -> usize;
17957        pub fn whiteout_m2_M2Model_resize_lodProfiles(self_: *mut whiteout_M2Model, count: usize);
17958        pub fn whiteout_m2_M2Model_get_lodProfiles_at(
17959            self_: *mut whiteout_M2Model,
17960            index: usize,
17961        ) -> *mut whiteout_M2SkinProfile;
17962        pub fn whiteout_m2_M2Model_get_numSkinProfiles(self_: *mut whiteout_M2Model) -> u32;
17963        pub fn whiteout_m2_M2Model_set_numSkinProfiles(self_: *mut whiteout_M2Model, value: u32);
17964        pub fn whiteout_m2_M2Model_get_colors_count(self_: *mut whiteout_M2Model) -> usize;
17965        pub fn whiteout_m2_M2Model_resize_colors(self_: *mut whiteout_M2Model, count: usize);
17966        pub fn whiteout_m2_M2Model_get_colors_at(
17967            self_: *mut whiteout_M2Model,
17968            index: usize,
17969        ) -> *mut whiteout_M2ColorAnimation;
17970        pub fn whiteout_m2_M2Model_get_textures_count(self_: *mut whiteout_M2Model) -> usize;
17971        pub fn whiteout_m2_M2Model_resize_textures(self_: *mut whiteout_M2Model, count: usize);
17972        pub fn whiteout_m2_M2Model_get_textures_at(
17973            self_: *mut whiteout_M2Model,
17974            index: usize,
17975        ) -> *mut whiteout_M2Texture;
17976        pub fn whiteout_m2_M2Model_get_textureWeights_count(self_: *mut whiteout_M2Model) -> usize;
17977        pub fn whiteout_m2_M2Model_resize_textureWeights(
17978            self_: *mut whiteout_M2Model,
17979            count: usize,
17980        );
17981        pub fn whiteout_m2_M2Model_get_textureWeights_at(
17982            self_: *mut whiteout_M2Model,
17983            index: usize,
17984        ) -> *mut whiteout_M2TextureWeight;
17985        pub fn whiteout_m2_M2Model_get_textureTransforms_count(
17986            self_: *mut whiteout_M2Model,
17987        ) -> usize;
17988        pub fn whiteout_m2_M2Model_resize_textureTransforms(
17989            self_: *mut whiteout_M2Model,
17990            count: usize,
17991        );
17992        pub fn whiteout_m2_M2Model_get_textureTransforms_at(
17993            self_: *mut whiteout_M2Model,
17994            index: usize,
17995        ) -> *mut whiteout_M2TextureTransform;
17996        pub fn whiteout_m2_M2Model_get_textureIndicesById_count(
17997            self_: *mut whiteout_M2Model,
17998        ) -> usize;
17999        pub fn whiteout_m2_M2Model_resize_textureIndicesById(
18000            self_: *mut whiteout_M2Model,
18001            count: usize,
18002        );
18003        pub fn whiteout_m2_M2Model_get_textureIndicesById_data(
18004            self_: *mut whiteout_M2Model,
18005        ) -> *const u16;
18006        pub fn whiteout_m2_M2Model_assign_textureIndicesById(
18007            self_: *mut whiteout_M2Model,
18008            data: *const u16,
18009            count: usize,
18010        );
18011        pub fn whiteout_m2_M2Model_get_materials_count(self_: *mut whiteout_M2Model) -> usize;
18012        pub fn whiteout_m2_M2Model_resize_materials(self_: *mut whiteout_M2Model, count: usize);
18013        pub fn whiteout_m2_M2Model_get_materials_at(
18014            self_: *mut whiteout_M2Model,
18015            index: usize,
18016        ) -> *mut whiteout_M2Material;
18017        pub fn whiteout_m2_M2Model_get_boneCombos_count(self_: *mut whiteout_M2Model) -> usize;
18018        pub fn whiteout_m2_M2Model_resize_boneCombos(self_: *mut whiteout_M2Model, count: usize);
18019        pub fn whiteout_m2_M2Model_get_boneCombos_data(self_: *mut whiteout_M2Model) -> *const u16;
18020        pub fn whiteout_m2_M2Model_assign_boneCombos(
18021            self_: *mut whiteout_M2Model,
18022            data: *const u16,
18023            count: usize,
18024        );
18025        pub fn whiteout_m2_M2Model_get_textureCombos_count(self_: *mut whiteout_M2Model) -> usize;
18026        pub fn whiteout_m2_M2Model_resize_textureCombos(self_: *mut whiteout_M2Model, count: usize);
18027        pub fn whiteout_m2_M2Model_get_textureCombos_data(
18028            self_: *mut whiteout_M2Model,
18029        ) -> *const u16;
18030        pub fn whiteout_m2_M2Model_assign_textureCombos(
18031            self_: *mut whiteout_M2Model,
18032            data: *const u16,
18033            count: usize,
18034        );
18035        pub fn whiteout_m2_M2Model_get_textureCoordCombos_count(
18036            self_: *mut whiteout_M2Model,
18037        ) -> usize;
18038        pub fn whiteout_m2_M2Model_resize_textureCoordCombos(
18039            self_: *mut whiteout_M2Model,
18040            count: usize,
18041        );
18042        pub fn whiteout_m2_M2Model_get_textureCoordCombos_data(
18043            self_: *mut whiteout_M2Model,
18044        ) -> *const u16;
18045        pub fn whiteout_m2_M2Model_assign_textureCoordCombos(
18046            self_: *mut whiteout_M2Model,
18047            data: *const u16,
18048            count: usize,
18049        );
18050        pub fn whiteout_m2_M2Model_get_textureWeightCombos_count(
18051            self_: *mut whiteout_M2Model,
18052        ) -> usize;
18053        pub fn whiteout_m2_M2Model_resize_textureWeightCombos(
18054            self_: *mut whiteout_M2Model,
18055            count: usize,
18056        );
18057        pub fn whiteout_m2_M2Model_get_textureWeightCombos_data(
18058            self_: *mut whiteout_M2Model,
18059        ) -> *const u16;
18060        pub fn whiteout_m2_M2Model_assign_textureWeightCombos(
18061            self_: *mut whiteout_M2Model,
18062            data: *const u16,
18063            count: usize,
18064        );
18065        pub fn whiteout_m2_M2Model_get_textureTransformCombos_count(
18066            self_: *mut whiteout_M2Model,
18067        ) -> usize;
18068        pub fn whiteout_m2_M2Model_resize_textureTransformCombos(
18069            self_: *mut whiteout_M2Model,
18070            count: usize,
18071        );
18072        pub fn whiteout_m2_M2Model_get_textureTransformCombos_data(
18073            self_: *mut whiteout_M2Model,
18074        ) -> *const u16;
18075        pub fn whiteout_m2_M2Model_assign_textureTransformCombos(
18076            self_: *mut whiteout_M2Model,
18077            data: *const u16,
18078            count: usize,
18079        );
18080        pub fn whiteout_m2_M2Model_get_bounding(
18081            self_: *mut whiteout_M2Model,
18082        ) -> *mut whiteout_M2Extent;
18083        pub fn whiteout_m2_M2Model_set_bounding(
18084            self_: *mut whiteout_M2Model,
18085            value: *const whiteout_M2Extent,
18086        );
18087        pub fn whiteout_m2_M2Model_get_collision(
18088            self_: *mut whiteout_M2Model,
18089        ) -> *mut whiteout_M2Extent;
18090        pub fn whiteout_m2_M2Model_set_collision(
18091            self_: *mut whiteout_M2Model,
18092            value: *const whiteout_M2Extent,
18093        );
18094        pub fn whiteout_m2_M2Model_get_collisionTriangleIndices_count(
18095            self_: *mut whiteout_M2Model,
18096        ) -> usize;
18097        pub fn whiteout_m2_M2Model_resize_collisionTriangleIndices(
18098            self_: *mut whiteout_M2Model,
18099            count: usize,
18100        );
18101        pub fn whiteout_m2_M2Model_get_collisionTriangleIndices_data(
18102            self_: *mut whiteout_M2Model,
18103        ) -> *const u16;
18104        pub fn whiteout_m2_M2Model_assign_collisionTriangleIndices(
18105            self_: *mut whiteout_M2Model,
18106            data: *const u16,
18107            count: usize,
18108        );
18109        pub fn whiteout_m2_M2Model_get_collisionVertices_count(
18110            self_: *mut whiteout_M2Model,
18111        ) -> usize;
18112        pub fn whiteout_m2_M2Model_resize_collisionVertices(
18113            self_: *mut whiteout_M2Model,
18114            count: usize,
18115        );
18116        pub fn whiteout_m2_M2Model_get_collisionVertices_data(
18117            self_: *mut whiteout_M2Model,
18118        ) -> *const f32;
18119        pub fn whiteout_m2_M2Model_assign_collisionVertices(
18120            self_: *mut whiteout_M2Model,
18121            data: *const f32,
18122            count: usize,
18123        );
18124        pub fn whiteout_m2_M2Model_get_collisionFaceNormals_count(
18125            self_: *mut whiteout_M2Model,
18126        ) -> usize;
18127        pub fn whiteout_m2_M2Model_resize_collisionFaceNormals(
18128            self_: *mut whiteout_M2Model,
18129            count: usize,
18130        );
18131        pub fn whiteout_m2_M2Model_get_collisionFaceNormals_data(
18132            self_: *mut whiteout_M2Model,
18133        ) -> *const f32;
18134        pub fn whiteout_m2_M2Model_assign_collisionFaceNormals(
18135            self_: *mut whiteout_M2Model,
18136            data: *const f32,
18137            count: usize,
18138        );
18139        pub fn whiteout_m2_M2Model_get_attachments_count(self_: *mut whiteout_M2Model) -> usize;
18140        pub fn whiteout_m2_M2Model_resize_attachments(self_: *mut whiteout_M2Model, count: usize);
18141        pub fn whiteout_m2_M2Model_get_attachments_at(
18142            self_: *mut whiteout_M2Model,
18143            index: usize,
18144        ) -> *mut whiteout_M2Attachment;
18145        pub fn whiteout_m2_M2Model_get_attachmentIndicesById_count(
18146            self_: *mut whiteout_M2Model,
18147        ) -> usize;
18148        pub fn whiteout_m2_M2Model_resize_attachmentIndicesById(
18149            self_: *mut whiteout_M2Model,
18150            count: usize,
18151        );
18152        pub fn whiteout_m2_M2Model_get_attachmentIndicesById_data(
18153            self_: *mut whiteout_M2Model,
18154        ) -> *const u16;
18155        pub fn whiteout_m2_M2Model_assign_attachmentIndicesById(
18156            self_: *mut whiteout_M2Model,
18157            data: *const u16,
18158            count: usize,
18159        );
18160        pub fn whiteout_m2_M2Model_get_events_count(self_: *mut whiteout_M2Model) -> usize;
18161        pub fn whiteout_m2_M2Model_resize_events(self_: *mut whiteout_M2Model, count: usize);
18162        pub fn whiteout_m2_M2Model_get_events_at(
18163            self_: *mut whiteout_M2Model,
18164            index: usize,
18165        ) -> *mut whiteout_M2Event;
18166        pub fn whiteout_m2_M2Model_get_lights_count(self_: *mut whiteout_M2Model) -> usize;
18167        pub fn whiteout_m2_M2Model_resize_lights(self_: *mut whiteout_M2Model, count: usize);
18168        pub fn whiteout_m2_M2Model_get_lights_at(
18169            self_: *mut whiteout_M2Model,
18170            index: usize,
18171        ) -> *mut whiteout_M2Light;
18172        pub fn whiteout_m2_M2Model_get_cameras_count(self_: *mut whiteout_M2Model) -> usize;
18173        pub fn whiteout_m2_M2Model_resize_cameras(self_: *mut whiteout_M2Model, count: usize);
18174        pub fn whiteout_m2_M2Model_get_cameras_at(
18175            self_: *mut whiteout_M2Model,
18176            index: usize,
18177        ) -> *mut whiteout_M2Camera;
18178        pub fn whiteout_m2_M2Model_get_cameraIndicesById_count(
18179            self_: *mut whiteout_M2Model,
18180        ) -> usize;
18181        pub fn whiteout_m2_M2Model_resize_cameraIndicesById(
18182            self_: *mut whiteout_M2Model,
18183            count: usize,
18184        );
18185        pub fn whiteout_m2_M2Model_get_cameraIndicesById_data(
18186            self_: *mut whiteout_M2Model,
18187        ) -> *const u16;
18188        pub fn whiteout_m2_M2Model_assign_cameraIndicesById(
18189            self_: *mut whiteout_M2Model,
18190            data: *const u16,
18191            count: usize,
18192        );
18193        pub fn whiteout_m2_M2Model_get_ribbonEmitters_count(self_: *mut whiteout_M2Model) -> usize;
18194        pub fn whiteout_m2_M2Model_resize_ribbonEmitters(
18195            self_: *mut whiteout_M2Model,
18196            count: usize,
18197        );
18198        pub fn whiteout_m2_M2Model_get_ribbonEmitters_at(
18199            self_: *mut whiteout_M2Model,
18200            index: usize,
18201        ) -> *mut whiteout_M2RibbonEmitter;
18202        pub fn whiteout_m2_M2Model_get_particleEmitters_count(
18203            self_: *mut whiteout_M2Model,
18204        ) -> usize;
18205        pub fn whiteout_m2_M2Model_resize_particleEmitters(
18206            self_: *mut whiteout_M2Model,
18207            count: usize,
18208        );
18209        pub fn whiteout_m2_M2Model_get_particleEmitters_at(
18210            self_: *mut whiteout_M2Model,
18211            index: usize,
18212        ) -> *mut whiteout_M2ParticleEmitter;
18213        pub fn whiteout_m2_M2Model_get_textureCombinerCombos_count(
18214            self_: *mut whiteout_M2Model,
18215        ) -> usize;
18216        pub fn whiteout_m2_M2Model_resize_textureCombinerCombos(
18217            self_: *mut whiteout_M2Model,
18218            count: usize,
18219        );
18220        pub fn whiteout_m2_M2Model_get_textureCombinerCombos_data(
18221            self_: *mut whiteout_M2Model,
18222        ) -> *const u16;
18223        pub fn whiteout_m2_M2Model_assign_textureCombinerCombos(
18224            self_: *mut whiteout_M2Model,
18225            data: *const u16,
18226            count: usize,
18227        );
18228        pub fn whiteout_m2_M2Model_get_playableAnimationLookup_count(
18229            self_: *mut whiteout_M2Model,
18230        ) -> usize;
18231        pub fn whiteout_m2_M2Model_resize_playableAnimationLookup(
18232            self_: *mut whiteout_M2Model,
18233            count: usize,
18234        );
18235        pub fn whiteout_m2_M2Model_get_playableAnimationLookup_data(
18236            self_: *mut whiteout_M2Model,
18237        ) -> *const u32;
18238        pub fn whiteout_m2_M2Model_assign_playableAnimationLookup(
18239            self_: *mut whiteout_M2Model,
18240            data: *const u32,
18241            count: usize,
18242        );
18243        pub fn whiteout_m2_M2Model_get_textureFlipbooks_count(
18244            self_: *mut whiteout_M2Model,
18245        ) -> usize;
18246        pub fn whiteout_m2_M2Model_resize_textureFlipbooks(
18247            self_: *mut whiteout_M2Model,
18248            count: usize,
18249        );
18250        pub fn whiteout_m2_M2Model_get_textureFlipbooks_data(
18251            self_: *mut whiteout_M2Model,
18252        ) -> *const u16;
18253        pub fn whiteout_m2_M2Model_assign_textureFlipbooks(
18254            self_: *mut whiteout_M2Model,
18255            data: *const u16,
18256            count: usize,
18257        );
18258        pub fn whiteout_m2_M2Model_get_texture_ids_count(self_: *mut whiteout_M2Model) -> usize;
18259        pub fn whiteout_m2_M2Model_resize_texture_ids(self_: *mut whiteout_M2Model, count: usize);
18260        pub fn whiteout_m2_M2Model_get_texture_ids_data(self_: *mut whiteout_M2Model)
18261            -> *const u32;
18262        pub fn whiteout_m2_M2Model_assign_texture_ids(
18263            self_: *mut whiteout_M2Model,
18264            data: *const u32,
18265            count: usize,
18266        );
18267        pub fn whiteout_m2_M2Model_get_parentSequenceReplacements_count(
18268            self_: *mut whiteout_M2Model,
18269        ) -> usize;
18270        pub fn whiteout_m2_M2Model_resize_parentSequenceReplacements(
18271            self_: *mut whiteout_M2Model,
18272            count: usize,
18273        );
18274        pub fn whiteout_m2_M2Model_get_parentSequenceReplacements_data(
18275            self_: *mut whiteout_M2Model,
18276        ) -> *const u16;
18277        pub fn whiteout_m2_M2Model_assign_parentSequenceReplacements(
18278            self_: *mut whiteout_M2Model,
18279            data: *const u16,
18280            count: usize,
18281        );
18282        pub fn whiteout_m2_M2Model_get_parentTextureWeights_count(
18283            self_: *mut whiteout_M2Model,
18284        ) -> usize;
18285        pub fn whiteout_m2_M2Model_resize_parentTextureWeights(
18286            self_: *mut whiteout_M2Model,
18287            count: usize,
18288        );
18289        pub fn whiteout_m2_M2Model_get_parentTextureWeights_at(
18290            self_: *mut whiteout_M2Model,
18291            index: usize,
18292        ) -> *mut whiteout_M2TextureWeight;
18293        pub fn whiteout_m2_M2Model_get_parentSequenceBounds_count(
18294            self_: *mut whiteout_M2Model,
18295        ) -> usize;
18296        pub fn whiteout_m2_M2Model_resize_parentSequenceBounds(
18297            self_: *mut whiteout_M2Model,
18298            count: usize,
18299        );
18300        pub fn whiteout_m2_M2Model_get_parentSequenceBounds_at(
18301            self_: *mut whiteout_M2Model,
18302            index: usize,
18303        ) -> *mut whiteout_M2Extent;
18304        pub fn whiteout_m2_M2Model_get_parentEventData_count(self_: *mut whiteout_M2Model)
18305            -> usize;
18306        pub fn whiteout_m2_M2Model_resize_parentEventData(
18307            self_: *mut whiteout_M2Model,
18308            count: usize,
18309        );
18310        pub fn whiteout_m2_M2Model_get_parentEventData_at(
18311            self_: *mut whiteout_M2Model,
18312            index: usize,
18313        ) -> *mut whiteout_M2AnimationTrackBase;
18314        pub fn whiteout_m2_M2Model_get_recursiveParticleModelIds_count(
18315            self_: *mut whiteout_M2Model,
18316        ) -> usize;
18317        pub fn whiteout_m2_M2Model_resize_recursiveParticleModelIds(
18318            self_: *mut whiteout_M2Model,
18319            count: usize,
18320        );
18321        pub fn whiteout_m2_M2Model_get_recursiveParticleModelIds_data(
18322            self_: *mut whiteout_M2Model,
18323        ) -> *const u32;
18324        pub fn whiteout_m2_M2Model_assign_recursiveParticleModelIds(
18325            self_: *mut whiteout_M2Model,
18326            data: *const u32,
18327            count: usize,
18328        );
18329        pub fn whiteout_m2_M2Model_get_geometryParticleModelIds_count(
18330            self_: *mut whiteout_M2Model,
18331        ) -> usize;
18332        pub fn whiteout_m2_M2Model_resize_geometryParticleModelIds(
18333            self_: *mut whiteout_M2Model,
18334            count: usize,
18335        );
18336        pub fn whiteout_m2_M2Model_get_geometryParticleModelIds_data(
18337            self_: *mut whiteout_M2Model,
18338        ) -> *const u32;
18339        pub fn whiteout_m2_M2Model_assign_geometryParticleModelIds(
18340            self_: *mut whiteout_M2Model,
18341            data: *const u32,
18342            count: usize,
18343        );
18344        pub fn whiteout_m2_M2Model_get_particleGeosets_count(self_: *mut whiteout_M2Model)
18345            -> usize;
18346        pub fn whiteout_m2_M2Model_resize_particleGeosets(
18347            self_: *mut whiteout_M2Model,
18348            count: usize,
18349        );
18350        pub fn whiteout_m2_M2Model_get_particleGeosets_at(
18351            self_: *mut whiteout_M2Model,
18352            index: usize,
18353        ) -> *mut whiteout_M2ParticleGeosetData;
18354        pub fn whiteout_m2_M2Model_get_boneOverrides_count(self_: *mut whiteout_M2Model) -> usize;
18355        pub fn whiteout_m2_M2Model_resize_boneOverrides(self_: *mut whiteout_M2Model, count: usize);
18356        pub fn whiteout_m2_M2Model_get_boneOverrides_at(
18357            self_: *mut whiteout_M2Model,
18358            index: usize,
18359        ) -> *mut whiteout_M2BoneOverrideSet;
18360        pub fn whiteout_m2_M2Model_get_boneFileIds_count(self_: *mut whiteout_M2Model) -> usize;
18361        pub fn whiteout_m2_M2Model_resize_boneFileIds(self_: *mut whiteout_M2Model, count: usize);
18362        pub fn whiteout_m2_M2Model_get_boneFileIds_data(self_: *mut whiteout_M2Model)
18363            -> *const u32;
18364        pub fn whiteout_m2_M2Model_assign_boneFileIds(
18365            self_: *mut whiteout_M2Model,
18366            data: *const u32,
18367            count: usize,
18368        );
18369        pub fn whiteout_m2_M2Model_get_edgeFadeEntries_count(self_: *mut whiteout_M2Model)
18370            -> usize;
18371        pub fn whiteout_m2_M2Model_resize_edgeFadeEntries(
18372            self_: *mut whiteout_M2Model,
18373            count: usize,
18374        );
18375        pub fn whiteout_m2_M2Model_get_edgeFadeEntries_at(
18376            self_: *mut whiteout_M2Model,
18377            index: usize,
18378        ) -> *mut whiteout_M2EdgeFadeData;
18379        pub fn whiteout_m2_M2Model_get_nerfEntries_count(self_: *mut whiteout_M2Model) -> usize;
18380        pub fn whiteout_m2_M2Model_resize_nerfEntries(self_: *mut whiteout_M2Model, count: usize);
18381        pub fn whiteout_m2_M2Model_get_nerfEntries_at(
18382            self_: *mut whiteout_M2Model,
18383            index: usize,
18384        ) -> *mut whiteout_M2DistanceFadeData;
18385        pub fn whiteout_m2_M2Model_get_detailedLightEntries_count(
18386            self_: *mut whiteout_M2Model,
18387        ) -> usize;
18388        pub fn whiteout_m2_M2Model_resize_detailedLightEntries(
18389            self_: *mut whiteout_M2Model,
18390            count: usize,
18391        );
18392        pub fn whiteout_m2_M2Model_get_detailedLightEntries_at(
18393            self_: *mut whiteout_M2Model,
18394            index: usize,
18395        ) -> *mut whiteout_M2DetailedLightData;
18396        pub fn whiteout_m2_M2Model_get_debugOcclusionEntries_count(
18397            self_: *mut whiteout_M2Model,
18398        ) -> usize;
18399        pub fn whiteout_m2_M2Model_resize_debugOcclusionEntries(
18400            self_: *mut whiteout_M2Model,
18401            count: usize,
18402        );
18403        pub fn whiteout_m2_M2Model_get_debugOcclusionEntries_at(
18404            self_: *mut whiteout_M2Model,
18405            index: usize,
18406        ) -> *mut whiteout_M2DebugOcclusionData;
18407        pub fn whiteout_m2_M2Model_get_animFrameData_count(self_: *mut whiteout_M2Model) -> usize;
18408        pub fn whiteout_m2_M2Model_resize_animFrameData(self_: *mut whiteout_M2Model, count: usize);
18409        pub fn whiteout_m2_M2Model_get_animFrameData_data(
18410            self_: *mut whiteout_M2Model,
18411        ) -> *const u8;
18412        pub fn whiteout_m2_M2Model_assign_animFrameData(
18413            self_: *mut whiteout_M2Model,
18414            data: *const u8,
18415            count: usize,
18416        );
18417        pub fn whiteout_m2_M2Model_get_dpivData_count(self_: *mut whiteout_M2Model) -> usize;
18418        pub fn whiteout_m2_M2Model_resize_dpivData(self_: *mut whiteout_M2Model, count: usize);
18419        pub fn whiteout_m2_M2Model_get_dpivData_at(
18420            self_: *mut whiteout_M2Model,
18421            index: usize,
18422        ) -> *mut whiteout_M2PivotDisplacementData;
18423        pub fn whiteout_m2_M2Model_get_texturedLightEntries_count(
18424            self_: *mut whiteout_M2Model,
18425        ) -> usize;
18426        pub fn whiteout_m2_M2Model_resize_texturedLightEntries(
18427            self_: *mut whiteout_M2Model,
18428            count: usize,
18429        );
18430        pub fn whiteout_m2_M2Model_get_texturedLightEntries_at(
18431            self_: *mut whiteout_M2Model,
18432            index: usize,
18433        ) -> *mut whiteout_M2TexturedLightData;
18434        // Parser
18435        pub fn whiteout_m2_M2Parser_new() -> *mut whiteout_M2Parser;
18436        pub fn whiteout_m2_M2Parser_delete(self_: *mut whiteout_M2Parser);
18437        pub fn whiteout_m2_M2Parser_parse(
18438            self_: *mut whiteout_M2Parser,
18439            fs: *mut core::ffi::c_void,
18440            file_path: *const core::ffi::c_char,
18441        ) -> *mut whiteout_M2Model;
18442        pub fn whiteout_m2_M2Parser_parse_cascFs_buffer(
18443            self_: *mut whiteout_M2Parser,
18444            casc_fs: *const u8,
18445            casc_fs_size: usize,
18446            buffer: *const u8,
18447            buffer_size: usize,
18448        ) -> *mut whiteout_M2Model;
18449        pub fn whiteout_m2_M2Parser_setLazyAnimations(self_: *mut whiteout_M2Parser, enable: i32);
18450        pub fn whiteout_m2_M2Parser_hasIssues(self_: *mut whiteout_M2Parser) -> i32;
18451        pub fn whiteout_m2_M2Parser_getIssues_count(self_: *mut whiteout_M2Parser) -> usize;
18452        pub fn whiteout_m2_M2Parser_getIssues_at(
18453            self_: *mut whiteout_M2Parser,
18454            index: usize,
18455        ) -> RawCString;
18456        // WriteOptions
18457        pub fn whiteout_m2_M2WriteOptions_new() -> *mut whiteout_M2WriteOptions;
18458        pub fn whiteout_m2_M2WriteOptions_delete(self_: *mut whiteout_M2WriteOptions);
18459        pub fn whiteout_m2_M2WriteOptions_get_m2Version(self_: *mut whiteout_M2WriteOptions)
18460            -> u32;
18461        pub fn whiteout_m2_M2WriteOptions_set_m2Version(
18462            self_: *mut whiteout_M2WriteOptions,
18463            value: u32,
18464        );
18465        pub fn whiteout_m2_M2WriteOptions_get_emitSkeleton(
18466            self_: *mut whiteout_M2WriteOptions,
18467        ) -> i32;
18468        pub fn whiteout_m2_M2WriteOptions_set_emitSkeleton(
18469            self_: *mut whiteout_M2WriteOptions,
18470            value: i32,
18471        );
18472        pub fn whiteout_m2_M2WriteOptions_get_baseStem(
18473            self_: *mut whiteout_M2WriteOptions,
18474        ) -> RawCString;
18475        pub fn whiteout_m2_M2WriteOptions_set_baseStem(
18476            self_: *mut whiteout_M2WriteOptions,
18477            value: *const core::ffi::c_char,
18478        );
18479        // SerializeResult
18480        pub fn whiteout_m2_M2SerializeResult_new() -> *mut whiteout_M2SerializeResult;
18481        pub fn whiteout_m2_M2SerializeResult_delete(self_: *mut whiteout_M2SerializeResult);
18482        pub fn whiteout_m2_M2SerializeResult_get_m2Data_count(
18483            self_: *mut whiteout_M2SerializeResult,
18484        ) -> usize;
18485        pub fn whiteout_m2_M2SerializeResult_resize_m2Data(
18486            self_: *mut whiteout_M2SerializeResult,
18487            count: usize,
18488        );
18489        pub fn whiteout_m2_M2SerializeResult_get_m2Data_data(
18490            self_: *mut whiteout_M2SerializeResult,
18491        ) -> *const u8;
18492        pub fn whiteout_m2_M2SerializeResult_assign_m2Data(
18493            self_: *mut whiteout_M2SerializeResult,
18494            data: *const u8,
18495            count: usize,
18496        );
18497        // Writer
18498        pub fn whiteout_m2_M2Writer_new() -> *mut whiteout_M2Writer;
18499        pub fn whiteout_m2_M2Writer_new_options(
18500            _0: *mut core::ffi::c_void,
18501        ) -> *mut whiteout_M2Writer;
18502        pub fn whiteout_m2_M2Writer_delete(self_: *mut whiteout_M2Writer);
18503        pub fn whiteout_m2_M2Writer_write(
18504            self_: *mut whiteout_M2Writer,
18505            fs: *mut core::ffi::c_void,
18506            file_path: *const core::ffi::c_char,
18507            model: *mut whiteout_M2Model,
18508        );
18509        pub fn whiteout_m2_M2Writer_write_cascFs_model(
18510            self_: *mut whiteout_M2Writer,
18511            casc_fs: *mut core::ffi::c_void,
18512            model: *mut whiteout_M2Model,
18513        );
18514        pub fn whiteout_m2_M2Writer_write_model(
18515            self_: *mut whiteout_M2Writer,
18516            model: *mut whiteout_M2Model,
18517        ) -> *mut whiteout_M2SerializeResult;
18518        pub fn whiteout_m2_M2Writer_hasIssues(self_: *mut whiteout_M2Writer) -> i32;
18519        pub fn whiteout_m2_M2Writer_getIssues_count(self_: *mut whiteout_M2Writer) -> usize;
18520        pub fn whiteout_m2_M2Writer_getIssues_at(
18521            self_: *mut whiteout_M2Writer,
18522            index: usize,
18523        ) -> RawCString;
18524        // AnimationTrackVector3f
18525        pub fn whiteout_m2_M2AnimationTrackVector3f_new() -> *mut whiteout_M2AnimationTrackVector3f;
18526        pub fn whiteout_m2_M2AnimationTrackVector3f_delete(
18527            self_: *mut whiteout_M2AnimationTrackVector3f,
18528        );
18529        pub fn whiteout_m2_M2AnimationTrackVector3f_get_interpolationType(
18530            self_: *mut whiteout_M2AnimationTrackVector3f,
18531        ) -> i32;
18532        pub fn whiteout_m2_M2AnimationTrackVector3f_set_interpolationType(
18533            self_: *mut whiteout_M2AnimationTrackVector3f,
18534            value: i32,
18535        );
18536        pub fn whiteout_m2_M2AnimationTrackVector3f_get_globalSequenceId(
18537            self_: *mut whiteout_M2AnimationTrackVector3f,
18538        ) -> u16;
18539        pub fn whiteout_m2_M2AnimationTrackVector3f_set_globalSequenceId(
18540            self_: *mut whiteout_M2AnimationTrackVector3f,
18541            value: u16,
18542        );
18543        pub fn whiteout_m2_M2AnimationTrackVector3f_get_timestamps_count(
18544            self_: *mut whiteout_M2AnimationTrackVector3f,
18545        ) -> usize;
18546        pub fn whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_count(
18547            self_: *mut whiteout_M2AnimationTrackVector3f,
18548            outer: usize,
18549        ) -> usize;
18550        pub fn whiteout_m2_M2AnimationTrackVector3f_resize_timestamps(
18551            self_: *mut whiteout_M2AnimationTrackVector3f,
18552            count: usize,
18553        );
18554        pub fn whiteout_m2_M2AnimationTrackVector3f_resize_timestamps_inner(
18555            self_: *mut whiteout_M2AnimationTrackVector3f,
18556            outer: usize,
18557            count: usize,
18558        );
18559        pub fn whiteout_m2_M2AnimationTrackVector3f_get_timestamps_inner_data(
18560            self_: *mut whiteout_M2AnimationTrackVector3f,
18561            outer: usize,
18562        ) -> *const u32;
18563        pub fn whiteout_m2_M2AnimationTrackVector3f_assign_timestamps_inner(
18564            self_: *mut whiteout_M2AnimationTrackVector3f,
18565            outer: usize,
18566            data: *const u32,
18567            count: usize,
18568        );
18569        pub fn whiteout_m2_M2AnimationTrackVector3f_get_values_count(
18570            self_: *mut whiteout_M2AnimationTrackVector3f,
18571        ) -> usize;
18572        pub fn whiteout_m2_M2AnimationTrackVector3f_get_values_inner_count(
18573            self_: *mut whiteout_M2AnimationTrackVector3f,
18574            outer: usize,
18575        ) -> usize;
18576        pub fn whiteout_m2_M2AnimationTrackVector3f_resize_values(
18577            self_: *mut whiteout_M2AnimationTrackVector3f,
18578            count: usize,
18579        );
18580        pub fn whiteout_m2_M2AnimationTrackVector3f_resize_values_inner(
18581            self_: *mut whiteout_M2AnimationTrackVector3f,
18582            outer: usize,
18583            count: usize,
18584        );
18585        pub fn whiteout_m2_M2AnimationTrackVector3f_get_values_inner_data(
18586            self_: *mut whiteout_M2AnimationTrackVector3f,
18587            outer: usize,
18588        ) -> *const f32;
18589        pub fn whiteout_m2_M2AnimationTrackVector3f_assign_values_inner(
18590            self_: *mut whiteout_M2AnimationTrackVector3f,
18591            outer: usize,
18592            data: *const f32,
18593            count: usize,
18594        );
18595        // AnimationTrackM2CompatQuaternion
18596        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_new(
18597        ) -> *mut whiteout_M2AnimationTrackM2CompatQuaternion;
18598        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_delete(
18599            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18600        );
18601        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_interpolationType(
18602            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18603        ) -> i32;
18604        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_set_interpolationType(
18605            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18606            value: i32,
18607        );
18608        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_globalSequenceId(
18609            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18610        ) -> u16;
18611        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_set_globalSequenceId(
18612            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18613            value: u16,
18614        );
18615        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_count(
18616            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18617        ) -> usize;
18618        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_count(
18619            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18620            outer: usize,
18621        ) -> usize;
18622        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_timestamps(
18623            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18624            count: usize,
18625        );
18626        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_timestamps_inner(
18627            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18628            outer: usize,
18629            count: usize,
18630        );
18631        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_timestamps_inner_data(
18632            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18633            outer: usize,
18634        ) -> *const u32;
18635        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_assign_timestamps_inner(
18636            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18637            outer: usize,
18638            data: *const u32,
18639            count: usize,
18640        );
18641        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_count(
18642            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18643        ) -> usize;
18644        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_inner_count(
18645            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18646            outer: usize,
18647        ) -> usize;
18648        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_values(
18649            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18650            count: usize,
18651        );
18652        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_resize_values_inner(
18653            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18654            outer: usize,
18655            count: usize,
18656        );
18657        pub fn whiteout_m2_M2AnimationTrackM2CompatQuaternion_get_values_at(
18658            self_: *mut whiteout_M2AnimationTrackM2CompatQuaternion,
18659            outer: usize,
18660            inner: usize,
18661        ) -> *mut whiteout_M2CompatQuaternion;
18662        // AnimationTrackI16
18663        pub fn whiteout_m2_M2AnimationTrackI16_new() -> *mut whiteout_M2AnimationTrackI16;
18664        pub fn whiteout_m2_M2AnimationTrackI16_delete(self_: *mut whiteout_M2AnimationTrackI16);
18665        pub fn whiteout_m2_M2AnimationTrackI16_get_interpolationType(
18666            self_: *mut whiteout_M2AnimationTrackI16,
18667        ) -> i32;
18668        pub fn whiteout_m2_M2AnimationTrackI16_set_interpolationType(
18669            self_: *mut whiteout_M2AnimationTrackI16,
18670            value: i32,
18671        );
18672        pub fn whiteout_m2_M2AnimationTrackI16_get_globalSequenceId(
18673            self_: *mut whiteout_M2AnimationTrackI16,
18674        ) -> u16;
18675        pub fn whiteout_m2_M2AnimationTrackI16_set_globalSequenceId(
18676            self_: *mut whiteout_M2AnimationTrackI16,
18677            value: u16,
18678        );
18679        pub fn whiteout_m2_M2AnimationTrackI16_get_timestamps_count(
18680            self_: *mut whiteout_M2AnimationTrackI16,
18681        ) -> usize;
18682        pub fn whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_count(
18683            self_: *mut whiteout_M2AnimationTrackI16,
18684            outer: usize,
18685        ) -> usize;
18686        pub fn whiteout_m2_M2AnimationTrackI16_resize_timestamps(
18687            self_: *mut whiteout_M2AnimationTrackI16,
18688            count: usize,
18689        );
18690        pub fn whiteout_m2_M2AnimationTrackI16_resize_timestamps_inner(
18691            self_: *mut whiteout_M2AnimationTrackI16,
18692            outer: usize,
18693            count: usize,
18694        );
18695        pub fn whiteout_m2_M2AnimationTrackI16_get_timestamps_inner_data(
18696            self_: *mut whiteout_M2AnimationTrackI16,
18697            outer: usize,
18698        ) -> *const u32;
18699        pub fn whiteout_m2_M2AnimationTrackI16_assign_timestamps_inner(
18700            self_: *mut whiteout_M2AnimationTrackI16,
18701            outer: usize,
18702            data: *const u32,
18703            count: usize,
18704        );
18705        pub fn whiteout_m2_M2AnimationTrackI16_get_values_count(
18706            self_: *mut whiteout_M2AnimationTrackI16,
18707        ) -> usize;
18708        pub fn whiteout_m2_M2AnimationTrackI16_get_values_inner_count(
18709            self_: *mut whiteout_M2AnimationTrackI16,
18710            outer: usize,
18711        ) -> usize;
18712        pub fn whiteout_m2_M2AnimationTrackI16_resize_values(
18713            self_: *mut whiteout_M2AnimationTrackI16,
18714            count: usize,
18715        );
18716        pub fn whiteout_m2_M2AnimationTrackI16_resize_values_inner(
18717            self_: *mut whiteout_M2AnimationTrackI16,
18718            outer: usize,
18719            count: usize,
18720        );
18721        pub fn whiteout_m2_M2AnimationTrackI16_get_values_inner_data(
18722            self_: *mut whiteout_M2AnimationTrackI16,
18723            outer: usize,
18724        ) -> *const i16;
18725        pub fn whiteout_m2_M2AnimationTrackI16_assign_values_inner(
18726            self_: *mut whiteout_M2AnimationTrackI16,
18727            outer: usize,
18728            data: *const i16,
18729            count: usize,
18730        );
18731        // AnimationTrackQuaternion
18732        pub fn whiteout_m2_M2AnimationTrackQuaternion_new(
18733        ) -> *mut whiteout_M2AnimationTrackQuaternion;
18734        pub fn whiteout_m2_M2AnimationTrackQuaternion_delete(
18735            self_: *mut whiteout_M2AnimationTrackQuaternion,
18736        );
18737        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_interpolationType(
18738            self_: *mut whiteout_M2AnimationTrackQuaternion,
18739        ) -> i32;
18740        pub fn whiteout_m2_M2AnimationTrackQuaternion_set_interpolationType(
18741            self_: *mut whiteout_M2AnimationTrackQuaternion,
18742            value: i32,
18743        );
18744        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_globalSequenceId(
18745            self_: *mut whiteout_M2AnimationTrackQuaternion,
18746        ) -> u16;
18747        pub fn whiteout_m2_M2AnimationTrackQuaternion_set_globalSequenceId(
18748            self_: *mut whiteout_M2AnimationTrackQuaternion,
18749            value: u16,
18750        );
18751        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_count(
18752            self_: *mut whiteout_M2AnimationTrackQuaternion,
18753        ) -> usize;
18754        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_count(
18755            self_: *mut whiteout_M2AnimationTrackQuaternion,
18756            outer: usize,
18757        ) -> usize;
18758        pub fn whiteout_m2_M2AnimationTrackQuaternion_resize_timestamps(
18759            self_: *mut whiteout_M2AnimationTrackQuaternion,
18760            count: usize,
18761        );
18762        pub fn whiteout_m2_M2AnimationTrackQuaternion_resize_timestamps_inner(
18763            self_: *mut whiteout_M2AnimationTrackQuaternion,
18764            outer: usize,
18765            count: usize,
18766        );
18767        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_timestamps_inner_data(
18768            self_: *mut whiteout_M2AnimationTrackQuaternion,
18769            outer: usize,
18770        ) -> *const u32;
18771        pub fn whiteout_m2_M2AnimationTrackQuaternion_assign_timestamps_inner(
18772            self_: *mut whiteout_M2AnimationTrackQuaternion,
18773            outer: usize,
18774            data: *const u32,
18775            count: usize,
18776        );
18777        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_values_count(
18778            self_: *mut whiteout_M2AnimationTrackQuaternion,
18779        ) -> usize;
18780        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_count(
18781            self_: *mut whiteout_M2AnimationTrackQuaternion,
18782            outer: usize,
18783        ) -> usize;
18784        pub fn whiteout_m2_M2AnimationTrackQuaternion_resize_values(
18785            self_: *mut whiteout_M2AnimationTrackQuaternion,
18786            count: usize,
18787        );
18788        pub fn whiteout_m2_M2AnimationTrackQuaternion_resize_values_inner(
18789            self_: *mut whiteout_M2AnimationTrackQuaternion,
18790            outer: usize,
18791            count: usize,
18792        );
18793        pub fn whiteout_m2_M2AnimationTrackQuaternion_get_values_inner_data(
18794            self_: *mut whiteout_M2AnimationTrackQuaternion,
18795            outer: usize,
18796        ) -> *const f32;
18797        pub fn whiteout_m2_M2AnimationTrackQuaternion_assign_values_inner(
18798            self_: *mut whiteout_M2AnimationTrackQuaternion,
18799            outer: usize,
18800            data: *const f32,
18801            count: usize,
18802        );
18803        // AnimationTrackF32
18804        pub fn whiteout_m2_M2AnimationTrackF32_new() -> *mut whiteout_M2AnimationTrackF32;
18805        pub fn whiteout_m2_M2AnimationTrackF32_delete(self_: *mut whiteout_M2AnimationTrackF32);
18806        pub fn whiteout_m2_M2AnimationTrackF32_get_interpolationType(
18807            self_: *mut whiteout_M2AnimationTrackF32,
18808        ) -> i32;
18809        pub fn whiteout_m2_M2AnimationTrackF32_set_interpolationType(
18810            self_: *mut whiteout_M2AnimationTrackF32,
18811            value: i32,
18812        );
18813        pub fn whiteout_m2_M2AnimationTrackF32_get_globalSequenceId(
18814            self_: *mut whiteout_M2AnimationTrackF32,
18815        ) -> u16;
18816        pub fn whiteout_m2_M2AnimationTrackF32_set_globalSequenceId(
18817            self_: *mut whiteout_M2AnimationTrackF32,
18818            value: u16,
18819        );
18820        pub fn whiteout_m2_M2AnimationTrackF32_get_timestamps_count(
18821            self_: *mut whiteout_M2AnimationTrackF32,
18822        ) -> usize;
18823        pub fn whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_count(
18824            self_: *mut whiteout_M2AnimationTrackF32,
18825            outer: usize,
18826        ) -> usize;
18827        pub fn whiteout_m2_M2AnimationTrackF32_resize_timestamps(
18828            self_: *mut whiteout_M2AnimationTrackF32,
18829            count: usize,
18830        );
18831        pub fn whiteout_m2_M2AnimationTrackF32_resize_timestamps_inner(
18832            self_: *mut whiteout_M2AnimationTrackF32,
18833            outer: usize,
18834            count: usize,
18835        );
18836        pub fn whiteout_m2_M2AnimationTrackF32_get_timestamps_inner_data(
18837            self_: *mut whiteout_M2AnimationTrackF32,
18838            outer: usize,
18839        ) -> *const u32;
18840        pub fn whiteout_m2_M2AnimationTrackF32_assign_timestamps_inner(
18841            self_: *mut whiteout_M2AnimationTrackF32,
18842            outer: usize,
18843            data: *const u32,
18844            count: usize,
18845        );
18846        pub fn whiteout_m2_M2AnimationTrackF32_get_values_count(
18847            self_: *mut whiteout_M2AnimationTrackF32,
18848        ) -> usize;
18849        pub fn whiteout_m2_M2AnimationTrackF32_get_values_inner_count(
18850            self_: *mut whiteout_M2AnimationTrackF32,
18851            outer: usize,
18852        ) -> usize;
18853        pub fn whiteout_m2_M2AnimationTrackF32_resize_values(
18854            self_: *mut whiteout_M2AnimationTrackF32,
18855            count: usize,
18856        );
18857        pub fn whiteout_m2_M2AnimationTrackF32_resize_values_inner(
18858            self_: *mut whiteout_M2AnimationTrackF32,
18859            outer: usize,
18860            count: usize,
18861        );
18862        pub fn whiteout_m2_M2AnimationTrackF32_get_values_inner_data(
18863            self_: *mut whiteout_M2AnimationTrackF32,
18864            outer: usize,
18865        ) -> *const f32;
18866        pub fn whiteout_m2_M2AnimationTrackF32_assign_values_inner(
18867            self_: *mut whiteout_M2AnimationTrackF32,
18868            outer: usize,
18869            data: *const f32,
18870            count: usize,
18871        );
18872        // AnimationTrackU8
18873        pub fn whiteout_m2_M2AnimationTrackU8_new() -> *mut whiteout_M2AnimationTrackU8;
18874        pub fn whiteout_m2_M2AnimationTrackU8_delete(self_: *mut whiteout_M2AnimationTrackU8);
18875        pub fn whiteout_m2_M2AnimationTrackU8_get_interpolationType(
18876            self_: *mut whiteout_M2AnimationTrackU8,
18877        ) -> i32;
18878        pub fn whiteout_m2_M2AnimationTrackU8_set_interpolationType(
18879            self_: *mut whiteout_M2AnimationTrackU8,
18880            value: i32,
18881        );
18882        pub fn whiteout_m2_M2AnimationTrackU8_get_globalSequenceId(
18883            self_: *mut whiteout_M2AnimationTrackU8,
18884        ) -> u16;
18885        pub fn whiteout_m2_M2AnimationTrackU8_set_globalSequenceId(
18886            self_: *mut whiteout_M2AnimationTrackU8,
18887            value: u16,
18888        );
18889        pub fn whiteout_m2_M2AnimationTrackU8_get_timestamps_count(
18890            self_: *mut whiteout_M2AnimationTrackU8,
18891        ) -> usize;
18892        pub fn whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_count(
18893            self_: *mut whiteout_M2AnimationTrackU8,
18894            outer: usize,
18895        ) -> usize;
18896        pub fn whiteout_m2_M2AnimationTrackU8_resize_timestamps(
18897            self_: *mut whiteout_M2AnimationTrackU8,
18898            count: usize,
18899        );
18900        pub fn whiteout_m2_M2AnimationTrackU8_resize_timestamps_inner(
18901            self_: *mut whiteout_M2AnimationTrackU8,
18902            outer: usize,
18903            count: usize,
18904        );
18905        pub fn whiteout_m2_M2AnimationTrackU8_get_timestamps_inner_data(
18906            self_: *mut whiteout_M2AnimationTrackU8,
18907            outer: usize,
18908        ) -> *const u32;
18909        pub fn whiteout_m2_M2AnimationTrackU8_assign_timestamps_inner(
18910            self_: *mut whiteout_M2AnimationTrackU8,
18911            outer: usize,
18912            data: *const u32,
18913            count: usize,
18914        );
18915        pub fn whiteout_m2_M2AnimationTrackU8_get_values_count(
18916            self_: *mut whiteout_M2AnimationTrackU8,
18917        ) -> usize;
18918        pub fn whiteout_m2_M2AnimationTrackU8_get_values_inner_count(
18919            self_: *mut whiteout_M2AnimationTrackU8,
18920            outer: usize,
18921        ) -> usize;
18922        pub fn whiteout_m2_M2AnimationTrackU8_resize_values(
18923            self_: *mut whiteout_M2AnimationTrackU8,
18924            count: usize,
18925        );
18926        pub fn whiteout_m2_M2AnimationTrackU8_resize_values_inner(
18927            self_: *mut whiteout_M2AnimationTrackU8,
18928            outer: usize,
18929            count: usize,
18930        );
18931        pub fn whiteout_m2_M2AnimationTrackU8_get_values_inner_data(
18932            self_: *mut whiteout_M2AnimationTrackU8,
18933            outer: usize,
18934        ) -> *const u8;
18935        pub fn whiteout_m2_M2AnimationTrackU8_assign_values_inner(
18936            self_: *mut whiteout_M2AnimationTrackU8,
18937            outer: usize,
18938            data: *const u8,
18939            count: usize,
18940        );
18941        // AnimationTrackM2CameraSpline
18942        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_new(
18943        ) -> *mut whiteout_M2AnimationTrackM2CameraSpline;
18944        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_delete(
18945            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18946        );
18947        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_interpolationType(
18948            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18949        ) -> i32;
18950        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_set_interpolationType(
18951            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18952            value: i32,
18953        );
18954        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_globalSequenceId(
18955            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18956        ) -> u16;
18957        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_set_globalSequenceId(
18958            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18959            value: u16,
18960        );
18961        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_count(
18962            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18963        ) -> usize;
18964        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_count(
18965            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18966            outer: usize,
18967        ) -> usize;
18968        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_resize_timestamps(
18969            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18970            count: usize,
18971        );
18972        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_resize_timestamps_inner(
18973            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18974            outer: usize,
18975            count: usize,
18976        );
18977        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_timestamps_inner_data(
18978            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18979            outer: usize,
18980        ) -> *const u32;
18981        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_assign_timestamps_inner(
18982            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18983            outer: usize,
18984            data: *const u32,
18985            count: usize,
18986        );
18987        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_count(
18988            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18989        ) -> usize;
18990        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_inner_count(
18991            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18992            outer: usize,
18993        ) -> usize;
18994        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_resize_values(
18995            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
18996            count: usize,
18997        );
18998        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_resize_values_inner(
18999            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
19000            outer: usize,
19001            count: usize,
19002        );
19003        pub fn whiteout_m2_M2AnimationTrackM2CameraSpline_get_values_at(
19004            self_: *mut whiteout_M2AnimationTrackM2CameraSpline,
19005            outer: usize,
19006            inner: usize,
19007        ) -> *mut whiteout_M2CameraSpline;
19008        // AnimationTrackU16
19009        pub fn whiteout_m2_M2AnimationTrackU16_new() -> *mut whiteout_M2AnimationTrackU16;
19010        pub fn whiteout_m2_M2AnimationTrackU16_delete(self_: *mut whiteout_M2AnimationTrackU16);
19011        pub fn whiteout_m2_M2AnimationTrackU16_get_interpolationType(
19012            self_: *mut whiteout_M2AnimationTrackU16,
19013        ) -> i32;
19014        pub fn whiteout_m2_M2AnimationTrackU16_set_interpolationType(
19015            self_: *mut whiteout_M2AnimationTrackU16,
19016            value: i32,
19017        );
19018        pub fn whiteout_m2_M2AnimationTrackU16_get_globalSequenceId(
19019            self_: *mut whiteout_M2AnimationTrackU16,
19020        ) -> u16;
19021        pub fn whiteout_m2_M2AnimationTrackU16_set_globalSequenceId(
19022            self_: *mut whiteout_M2AnimationTrackU16,
19023            value: u16,
19024        );
19025        pub fn whiteout_m2_M2AnimationTrackU16_get_timestamps_count(
19026            self_: *mut whiteout_M2AnimationTrackU16,
19027        ) -> usize;
19028        pub fn whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_count(
19029            self_: *mut whiteout_M2AnimationTrackU16,
19030            outer: usize,
19031        ) -> usize;
19032        pub fn whiteout_m2_M2AnimationTrackU16_resize_timestamps(
19033            self_: *mut whiteout_M2AnimationTrackU16,
19034            count: usize,
19035        );
19036        pub fn whiteout_m2_M2AnimationTrackU16_resize_timestamps_inner(
19037            self_: *mut whiteout_M2AnimationTrackU16,
19038            outer: usize,
19039            count: usize,
19040        );
19041        pub fn whiteout_m2_M2AnimationTrackU16_get_timestamps_inner_data(
19042            self_: *mut whiteout_M2AnimationTrackU16,
19043            outer: usize,
19044        ) -> *const u32;
19045        pub fn whiteout_m2_M2AnimationTrackU16_assign_timestamps_inner(
19046            self_: *mut whiteout_M2AnimationTrackU16,
19047            outer: usize,
19048            data: *const u32,
19049            count: usize,
19050        );
19051        pub fn whiteout_m2_M2AnimationTrackU16_get_values_count(
19052            self_: *mut whiteout_M2AnimationTrackU16,
19053        ) -> usize;
19054        pub fn whiteout_m2_M2AnimationTrackU16_get_values_inner_count(
19055            self_: *mut whiteout_M2AnimationTrackU16,
19056            outer: usize,
19057        ) -> usize;
19058        pub fn whiteout_m2_M2AnimationTrackU16_resize_values(
19059            self_: *mut whiteout_M2AnimationTrackU16,
19060            count: usize,
19061        );
19062        pub fn whiteout_m2_M2AnimationTrackU16_resize_values_inner(
19063            self_: *mut whiteout_M2AnimationTrackU16,
19064            outer: usize,
19065            count: usize,
19066        );
19067        pub fn whiteout_m2_M2AnimationTrackU16_get_values_inner_data(
19068            self_: *mut whiteout_M2AnimationTrackU16,
19069            outer: usize,
19070        ) -> *const u16;
19071        pub fn whiteout_m2_M2AnimationTrackU16_assign_values_inner(
19072            self_: *mut whiteout_M2AnimationTrackU16,
19073            outer: usize,
19074            data: *const u16,
19075            count: usize,
19076        );
19077        // ParticleAnimationTrackVector3f
19078        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_new(
19079        ) -> *mut whiteout_M2ParticleAnimationTrackVector3f;
19080        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_delete(
19081            self_: *mut whiteout_M2ParticleAnimationTrackVector3f,
19082        );
19083        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_count(
19084            self_: *mut whiteout_M2ParticleAnimationTrackVector3f,
19085        ) -> usize;
19086        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_resize_values(
19087            self_: *mut whiteout_M2ParticleAnimationTrackVector3f,
19088            count: usize,
19089        );
19090        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_get_values_data(
19091            self_: *mut whiteout_M2ParticleAnimationTrackVector3f,
19092        ) -> *const f32;
19093        pub fn whiteout_m2_M2ParticleAnimationTrackVector3f_assign_values(
19094            self_: *mut whiteout_M2ParticleAnimationTrackVector3f,
19095            data: *const f32,
19096            count: usize,
19097        );
19098        // ParticleAnimationTrackVector2f
19099        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_new(
19100        ) -> *mut whiteout_M2ParticleAnimationTrackVector2f;
19101        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_delete(
19102            self_: *mut whiteout_M2ParticleAnimationTrackVector2f,
19103        );
19104        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_count(
19105            self_: *mut whiteout_M2ParticleAnimationTrackVector2f,
19106        ) -> usize;
19107        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_resize_values(
19108            self_: *mut whiteout_M2ParticleAnimationTrackVector2f,
19109            count: usize,
19110        );
19111        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_get_values_data(
19112            self_: *mut whiteout_M2ParticleAnimationTrackVector2f,
19113        ) -> *const f32;
19114        pub fn whiteout_m2_M2ParticleAnimationTrackVector2f_assign_values(
19115            self_: *mut whiteout_M2ParticleAnimationTrackVector2f,
19116            data: *const f32,
19117            count: usize,
19118        );
19119    }
19120}