1use std::ptr;
2
3use crate::animated_value_types::{
4 AnimatedMatrix4x4, AnimatedQuaternion, AnimatedScalar, AnimatedValue, AnimatedVector3,
5};
6use crate::error::Result;
7use crate::ffi;
8use crate::handle::ObjectHandle;
9use crate::object::Object;
10use crate::protocols::Component;
11use crate::types::TransformOpRotationOrder;
12use crate::util::{c_string, required_handle, take_string};
13
14fn copy_matrix(
15 handle: *mut core::ffi::c_void,
16 getter: unsafe extern "C" fn(*mut core::ffi::c_void, *mut f32),
17) -> [f32; 16] {
18 let mut matrix = [0.0_f32; 16];
19 unsafe { getter(handle, matrix.as_mut_ptr()) };
21 matrix
22}
23
24fn array_objects<T, F>(
25 array_ptr: *mut core::ffi::c_void,
26 context: &'static str,
27 mut map: F,
28) -> Result<Vec<T>>
29where
30 F: FnMut(ObjectHandle) -> T,
31{
32 let array = required_handle(array_ptr, context)?;
33 let count = unsafe { ffi::mdl_array_count(array.as_ptr()) as usize };
35 let mut values = Vec::with_capacity(count);
36 for index in 0..count {
37 let ptr = unsafe { ffi::mdl_array_object_at(array.as_ptr(), index as u64) };
39 if let Some(handle) = unsafe { ObjectHandle::from_retained_ptr(ptr) } {
41 values.push(map(handle));
42 }
43 }
44 Ok(values)
45}
46
47#[derive(Debug, Clone)]
48pub struct TransformComponent {
50 handle: ObjectHandle,
51}
52
53impl TransformComponent {
54 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
56 Self { handle }
57 }
58
59 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
61 self.handle.as_ptr()
62 }
63
64 #[must_use]
65 pub fn matrix(&self) -> [f32; 16] {
67 copy_matrix(self.handle.as_ptr(), ffi::mdl_transform_component_matrix)
68 }
69
70 pub fn set_matrix(&self, matrix: [f32; 16]) {
72 unsafe { ffi::mdl_transform_component_set_matrix(self.handle.as_ptr(), matrix.as_ptr()) };
74 }
75
76 #[must_use]
77 pub fn resets_transform(&self) -> bool {
79 unsafe { ffi::mdl_transform_component_resets_transform(self.handle.as_ptr()) != 0 }
81 }
82
83 pub fn set_resets_transform(&self, resets_transform: bool) {
85 unsafe {
87 ffi::mdl_transform_component_set_resets_transform(
88 self.handle.as_ptr(),
89 i32::from(resets_transform),
90 );
91 }
92 }
93
94 #[must_use]
95 pub fn minimum_time(&self) -> f64 {
97 unsafe { ffi::mdl_transform_component_minimum_time(self.handle.as_ptr()) }
99 }
100
101 #[must_use]
102 pub fn maximum_time(&self) -> f64 {
104 unsafe { ffi::mdl_transform_component_maximum_time(self.handle.as_ptr()) }
106 }
107
108 #[must_use]
109 pub fn key_times(&self) -> Vec<f64> {
111 let count =
112 unsafe { ffi::mdl_transform_component_key_time_count(self.handle.as_ptr()) as usize };
114 let mut values = vec![0.0_f64; count];
115 if values.is_empty() {
116 return values;
117 }
118 let written = unsafe {
120 ffi::mdl_transform_component_copy_key_times(
121 self.handle.as_ptr(),
122 values.as_mut_ptr(),
123 values.len() as u64,
124 )
125 } as usize;
126 values.truncate(written);
127 values
128 }
129
130 #[must_use]
131 pub fn local_transform_at_time(&self, time: f64) -> [f32; 16] {
133 let mut matrix = [0.0_f32; 16];
134 unsafe {
136 ffi::mdl_transform_component_local_transform_at_time(
137 self.handle.as_ptr(),
138 time,
139 matrix.as_mut_ptr(),
140 );
141 }
142 matrix
143 }
144
145 #[must_use]
146 pub fn as_transform(&self) -> Option<Transform> {
148 (unsafe { ffi::mdl_transform_component_is_transform(self.handle.as_ptr()) != 0 })
150 .then(|| Transform::from_handle(self.handle.clone()))
151 }
152
153 #[must_use]
154 pub fn as_transform_stack(&self) -> Option<TransformStack> {
156 (unsafe { ffi::mdl_transform_component_is_transform_stack(self.handle.as_ptr()) != 0 })
158 .then(|| TransformStack::from_handle(self.handle.clone()))
159 }
160
161 #[must_use]
162 pub fn global_transform_with_object(object: &Object, time: f64) -> [f32; 16] {
164 let mut matrix = [0.0_f32; 16];
165 unsafe {
167 ffi::mdl_transform_component_global_transform_with_object(
168 object.as_ptr(),
169 time,
170 matrix.as_mut_ptr(),
171 );
172 }
173 matrix
174 }
175}
176
177#[derive(Debug, Clone)]
178pub struct Transform {
180 handle: ObjectHandle,
181}
182
183impl Component for Transform {}
184
185impl Transform {
186 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
188 Self { handle }
189 }
190
191 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
193 self.handle.as_ptr()
194 }
195
196 pub fn new() -> Result<Self> {
198 let mut out_transform = ptr::null_mut();
199 let mut out_error = ptr::null_mut();
200 let status = unsafe { ffi::mdl_transform_new(&mut out_transform, &mut out_error) };
202 crate::util::status_result(status, out_error)?;
203 Ok(Self::from_handle(required_handle(
204 out_transform,
205 "MDLTransform",
206 )?))
207 }
208
209 pub fn from_component(component: &TransformComponent) -> Result<Self> {
211 let mut out_transform = ptr::null_mut();
212 let mut out_error = ptr::null_mut();
213 let status = unsafe {
215 ffi::mdl_transform_new_with_component(
216 component.as_ptr(),
217 &mut out_transform,
218 &mut out_error,
219 )
220 };
221 crate::util::status_result(status, out_error)?;
222 Ok(Self::from_handle(required_handle(
223 out_transform,
224 "MDLTransform",
225 )?))
226 }
227
228 pub fn from_component_with_resets_transform(
230 component: &TransformComponent,
231 resets_transform: bool,
232 ) -> Result<Self> {
233 let mut out_transform = ptr::null_mut();
234 let mut out_error = ptr::null_mut();
235 let status = unsafe {
237 ffi::mdl_transform_new_with_component_resets_transform(
238 component.as_ptr(),
239 i32::from(resets_transform),
240 &mut out_transform,
241 &mut out_error,
242 )
243 };
244 crate::util::status_result(status, out_error)?;
245 Ok(Self::from_handle(required_handle(
246 out_transform,
247 "MDLTransform",
248 )?))
249 }
250
251 pub fn from_matrix(matrix: [f32; 16]) -> Result<Self> {
253 let mut out_transform = ptr::null_mut();
254 let mut out_error = ptr::null_mut();
255 let status = unsafe {
257 ffi::mdl_transform_new_with_matrix(matrix.as_ptr(), &mut out_transform, &mut out_error)
258 };
259 crate::util::status_result(status, out_error)?;
260 Ok(Self::from_handle(required_handle(
261 out_transform,
262 "MDLTransform",
263 )?))
264 }
265
266 pub fn from_matrix_with_resets_transform(
268 matrix: [f32; 16],
269 resets_transform: bool,
270 ) -> Result<Self> {
271 let mut out_transform = ptr::null_mut();
272 let mut out_error = ptr::null_mut();
273 let status = unsafe {
275 ffi::mdl_transform_new_with_matrix_resets_transform(
276 matrix.as_ptr(),
277 i32::from(resets_transform),
278 &mut out_transform,
279 &mut out_error,
280 )
281 };
282 crate::util::status_result(status, out_error)?;
283 Ok(Self::from_handle(required_handle(
284 out_transform,
285 "MDLTransform",
286 )?))
287 }
288
289 #[must_use]
290 pub fn matrix(&self) -> [f32; 16] {
292 self.as_transform_component().matrix()
293 }
294
295 pub fn set_matrix(&self, matrix: [f32; 16]) {
297 self.as_transform_component().set_matrix(matrix);
298 }
299
300 #[must_use]
301 pub fn resets_transform(&self) -> bool {
303 self.as_transform_component().resets_transform()
304 }
305
306 pub fn set_resets_transform(&self, resets_transform: bool) {
308 self.as_transform_component()
309 .set_resets_transform(resets_transform);
310 }
311
312 #[must_use]
313 pub fn minimum_time(&self) -> f64 {
315 self.as_transform_component().minimum_time()
316 }
317
318 #[must_use]
319 pub fn maximum_time(&self) -> f64 {
321 self.as_transform_component().maximum_time()
322 }
323
324 #[must_use]
325 pub fn key_times(&self) -> Vec<f64> {
327 self.as_transform_component().key_times()
328 }
329
330 #[must_use]
331 pub fn local_transform_at_time(&self, time: f64) -> [f32; 16] {
333 self.as_transform_component().local_transform_at_time(time)
334 }
335
336 pub fn set_identity(&self) {
338 unsafe { ffi::mdl_transform_set_identity(self.handle.as_ptr()) };
340 }
341
342 #[must_use]
343 pub fn translation_at_time(&self, time: f64) -> [f32; 3] {
345 let mut value = [0.0_f32; 3];
346 unsafe {
348 ffi::mdl_transform_translation_at_time(self.handle.as_ptr(), time, value.as_mut_ptr());
349 }
350 value
351 }
352
353 #[must_use]
354 pub fn rotation_at_time(&self, time: f64) -> [f32; 3] {
356 let mut value = [0.0_f32; 3];
357 unsafe {
359 ffi::mdl_transform_rotation_at_time(self.handle.as_ptr(), time, value.as_mut_ptr());
360 }
361 value
362 }
363
364 #[must_use]
365 pub fn shear_at_time(&self, time: f64) -> [f32; 3] {
367 let mut value = [0.0_f32; 3];
368 unsafe {
370 ffi::mdl_transform_shear_at_time(self.handle.as_ptr(), time, value.as_mut_ptr());
371 }
372 value
373 }
374
375 #[must_use]
376 pub fn scale_at_time(&self, time: f64) -> [f32; 3] {
378 let mut value = [0.0_f32; 3];
379 unsafe {
381 ffi::mdl_transform_scale_at_time(self.handle.as_ptr(), time, value.as_mut_ptr());
382 }
383 value
384 }
385
386 pub fn set_matrix_for_time(&self, matrix: [f32; 16], time: f64) {
388 unsafe {
390 ffi::mdl_transform_set_matrix_for_time(self.handle.as_ptr(), matrix.as_ptr(), time);
391 };
392 }
393
394 pub fn set_translation_for_time(&self, translation: [f32; 3], time: f64) {
396 unsafe {
398 ffi::mdl_transform_set_translation_for_time(
399 self.handle.as_ptr(),
400 translation[0],
401 translation[1],
402 translation[2],
403 time,
404 );
405 }
406 }
407
408 pub fn set_rotation_for_time(&self, rotation: [f32; 3], time: f64) {
410 unsafe {
412 ffi::mdl_transform_set_rotation_for_time(
413 self.handle.as_ptr(),
414 rotation[0],
415 rotation[1],
416 rotation[2],
417 time,
418 );
419 }
420 }
421
422 pub fn set_shear_for_time(&self, shear: [f32; 3], time: f64) {
424 unsafe {
426 ffi::mdl_transform_set_shear_for_time(
427 self.handle.as_ptr(),
428 shear[0],
429 shear[1],
430 shear[2],
431 time,
432 );
433 }
434 }
435
436 pub fn set_scale_for_time(&self, scale: [f32; 3], time: f64) {
438 unsafe {
440 ffi::mdl_transform_set_scale_for_time(
441 self.handle.as_ptr(),
442 scale[0],
443 scale[1],
444 scale[2],
445 time,
446 );
447 }
448 }
449
450 #[must_use]
451 pub fn rotation_matrix_at_time(&self, time: f64) -> [f32; 16] {
453 let mut matrix = [0.0_f32; 16];
454 unsafe {
456 ffi::mdl_transform_rotation_matrix_at_time(
457 self.handle.as_ptr(),
458 time,
459 matrix.as_mut_ptr(),
460 );
461 }
462 matrix
463 }
464
465 #[must_use]
466 pub fn translation(&self) -> [f32; 3] {
468 let mut value = [0.0_f32; 3];
469 unsafe { ffi::mdl_transform_translation(self.handle.as_ptr(), value.as_mut_ptr()) };
471 value
472 }
473
474 pub fn set_translation(&self, translation: [f32; 3]) {
476 unsafe {
478 ffi::mdl_transform_set_translation(
479 self.handle.as_ptr(),
480 translation[0],
481 translation[1],
482 translation[2],
483 );
484 }
485 }
486
487 #[must_use]
488 pub fn rotation(&self) -> [f32; 3] {
490 let mut value = [0.0_f32; 3];
491 unsafe { ffi::mdl_transform_rotation(self.handle.as_ptr(), value.as_mut_ptr()) };
493 value
494 }
495
496 pub fn set_rotation(&self, rotation: [f32; 3]) {
498 unsafe {
500 ffi::mdl_transform_set_rotation(
501 self.handle.as_ptr(),
502 rotation[0],
503 rotation[1],
504 rotation[2],
505 );
506 }
507 }
508
509 #[must_use]
510 pub fn shear(&self) -> [f32; 3] {
512 let mut value = [0.0_f32; 3];
513 unsafe { ffi::mdl_transform_shear(self.handle.as_ptr(), value.as_mut_ptr()) };
515 value
516 }
517
518 pub fn set_shear(&self, shear: [f32; 3]) {
520 unsafe {
522 ffi::mdl_transform_set_shear(self.handle.as_ptr(), shear[0], shear[1], shear[2]);
523 }
524 }
525
526 #[must_use]
527 pub fn scale(&self) -> [f32; 3] {
529 let mut value = [0.0_f32; 3];
530 unsafe { ffi::mdl_transform_scale(self.handle.as_ptr(), value.as_mut_ptr()) };
532 value
533 }
534
535 pub fn set_scale(&self, scale: [f32; 3]) {
537 unsafe {
539 ffi::mdl_transform_set_scale(self.handle.as_ptr(), scale[0], scale[1], scale[2]);
540 }
541 }
542
543 #[must_use]
544 pub fn as_transform_component(&self) -> TransformComponent {
546 TransformComponent::from_handle(self.handle.clone())
547 }
548}
549
550#[derive(Debug, Clone)]
551pub struct TransformOp {
553 handle: ObjectHandle,
554}
555
556impl TransformOp {
557 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
559 Self { handle }
560 }
561
562 #[must_use]
563 pub fn name(&self) -> Option<String> {
565 take_string(unsafe { ffi::mdl_transform_op_name_string(self.handle.as_ptr()) })
567 }
568
569 #[must_use]
570 pub fn is_inverse(&self) -> bool {
572 unsafe { ffi::mdl_transform_op_is_inverse(self.handle.as_ptr()) != 0 }
574 }
575
576 #[must_use]
577 pub fn float4x4_at_time(&self, time: f64) -> [f32; 16] {
579 let mut matrix = [0.0_f32; 16];
580 unsafe {
582 ffi::mdl_transform_op_copy_float4x4_at_time(
583 self.handle.as_ptr(),
584 time,
585 matrix.as_mut_ptr(),
586 );
587 };
588 matrix
589 }
590}
591
592macro_rules! define_transform_op {
593 ($name:ident, $ffi_name:ident, $animated:ty) => {
594 #[derive(Debug, Clone)]
595 pub struct $name {
597 handle: ObjectHandle,
598 }
599
600 impl $name {
601 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
603 Self { handle }
604 }
605
606 #[must_use]
607 pub fn name(&self) -> Option<String> {
609 TransformOp::from_handle(self.handle.clone()).name()
610 }
611
612 #[must_use]
613 pub fn is_inverse(&self) -> bool {
615 TransformOp::from_handle(self.handle.clone()).is_inverse()
616 }
617
618 #[must_use]
619 pub fn float4x4_at_time(&self, time: f64) -> [f32; 16] {
621 TransformOp::from_handle(self.handle.clone()).float4x4_at_time(time)
622 }
623
624 #[must_use]
625 pub fn animated_value(&self) -> Option<$animated> {
627 let ptr = unsafe { ffi::$ffi_name(self.handle.as_ptr()) };
629 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(<$animated>::from_handle)
631 }
632
633 #[must_use]
634 pub fn as_transform_op(&self) -> TransformOp {
636 TransformOp::from_handle(self.handle.clone())
637 }
638 }
639 };
640}
641
642define_transform_op!(
643 TransformRotateXOp,
644 mdl_transform_rotate_x_op_animated_value,
645 AnimatedScalar
646);
647define_transform_op!(
648 TransformRotateYOp,
649 mdl_transform_rotate_y_op_animated_value,
650 AnimatedScalar
651);
652define_transform_op!(
653 TransformRotateZOp,
654 mdl_transform_rotate_z_op_animated_value,
655 AnimatedScalar
656);
657define_transform_op!(
658 TransformRotateOp,
659 mdl_transform_rotate_op_animated_value,
660 AnimatedVector3
661);
662define_transform_op!(
663 TransformTranslateOp,
664 mdl_transform_translate_op_animated_value,
665 AnimatedVector3
666);
667define_transform_op!(
668 TransformScaleOp,
669 mdl_transform_scale_op_animated_value,
670 AnimatedVector3
671);
672define_transform_op!(
673 TransformMatrixOp,
674 mdl_transform_matrix_op_animated_value,
675 AnimatedMatrix4x4
676);
677define_transform_op!(
678 TransformOrientOp,
679 mdl_transform_orient_op_animated_value,
680 AnimatedQuaternion
681);
682
683#[derive(Debug, Clone)]
684pub struct TransformStack {
686 handle: ObjectHandle,
687}
688
689impl TransformStack {
690 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
692 Self { handle }
693 }
694
695 pub fn new() -> Result<Self> {
697 let mut out_stack = ptr::null_mut();
698 let mut out_error = ptr::null_mut();
699 let status = unsafe { ffi::mdl_transform_stack_new(&mut out_stack, &mut out_error) };
701 crate::util::status_result(status, out_error)?;
702 Ok(Self::from_handle(required_handle(
703 out_stack,
704 "MDLTransformStack",
705 )?))
706 }
707
708 #[must_use]
709 pub fn matrix(&self) -> [f32; 16] {
711 self.as_transform_component().matrix()
712 }
713
714 pub fn set_matrix(&self, matrix: [f32; 16]) {
716 self.as_transform_component().set_matrix(matrix);
717 }
718
719 #[must_use]
720 pub fn resets_transform(&self) -> bool {
722 self.as_transform_component().resets_transform()
723 }
724
725 pub fn set_resets_transform(&self, resets_transform: bool) {
727 self.as_transform_component()
728 .set_resets_transform(resets_transform);
729 }
730
731 #[must_use]
732 pub fn minimum_time(&self) -> f64 {
734 self.as_transform_component().minimum_time()
735 }
736
737 #[must_use]
738 pub fn maximum_time(&self) -> f64 {
740 self.as_transform_component().maximum_time()
741 }
742
743 #[must_use]
744 pub fn key_times(&self) -> Vec<f64> {
746 self.as_transform_component().key_times()
747 }
748
749 #[must_use]
750 pub fn local_transform_at_time(&self, time: f64) -> [f32; 16] {
752 self.as_transform_component().local_transform_at_time(time)
753 }
754
755 pub fn add_translate_op(&self, name: &str, inverse: bool) -> Result<TransformTranslateOp> {
757 let name = c_string(name)?;
758 let ptr = unsafe {
760 ffi::mdl_transform_stack_add_translate_op(
761 self.handle.as_ptr(),
762 name.as_ptr(),
763 i32::from(inverse),
764 )
765 };
766 Ok(TransformTranslateOp::from_handle(required_handle(
767 ptr,
768 "MDLTransformTranslateOp",
769 )?))
770 }
771
772 pub fn add_rotate_x_op(&self, name: &str, inverse: bool) -> Result<TransformRotateXOp> {
774 let name = c_string(name)?;
775 let ptr = unsafe {
777 ffi::mdl_transform_stack_add_rotate_x_op(
778 self.handle.as_ptr(),
779 name.as_ptr(),
780 i32::from(inverse),
781 )
782 };
783 Ok(TransformRotateXOp::from_handle(required_handle(
784 ptr,
785 "MDLTransformRotateXOp",
786 )?))
787 }
788
789 pub fn add_rotate_y_op(&self, name: &str, inverse: bool) -> Result<TransformRotateYOp> {
791 let name = c_string(name)?;
792 let ptr = unsafe {
794 ffi::mdl_transform_stack_add_rotate_y_op(
795 self.handle.as_ptr(),
796 name.as_ptr(),
797 i32::from(inverse),
798 )
799 };
800 Ok(TransformRotateYOp::from_handle(required_handle(
801 ptr,
802 "MDLTransformRotateYOp",
803 )?))
804 }
805
806 pub fn add_rotate_z_op(&self, name: &str, inverse: bool) -> Result<TransformRotateZOp> {
808 let name = c_string(name)?;
809 let ptr = unsafe {
811 ffi::mdl_transform_stack_add_rotate_z_op(
812 self.handle.as_ptr(),
813 name.as_ptr(),
814 i32::from(inverse),
815 )
816 };
817 Ok(TransformRotateZOp::from_handle(required_handle(
818 ptr,
819 "MDLTransformRotateZOp",
820 )?))
821 }
822
823 pub fn add_rotate_op(
825 &self,
826 name: &str,
827 rotation_order: TransformOpRotationOrder,
828 inverse: bool,
829 ) -> Result<TransformRotateOp> {
830 let name = c_string(name)?;
831 let ptr = unsafe {
833 ffi::mdl_transform_stack_add_rotate_op(
834 self.handle.as_ptr(),
835 name.as_ptr(),
836 rotation_order.as_raw(),
837 i32::from(inverse),
838 )
839 };
840 Ok(TransformRotateOp::from_handle(required_handle(
841 ptr,
842 "MDLTransformRotateOp",
843 )?))
844 }
845
846 pub fn add_scale_op(&self, name: &str, inverse: bool) -> Result<TransformScaleOp> {
848 let name = c_string(name)?;
849 let ptr = unsafe {
851 ffi::mdl_transform_stack_add_scale_op(
852 self.handle.as_ptr(),
853 name.as_ptr(),
854 i32::from(inverse),
855 )
856 };
857 Ok(TransformScaleOp::from_handle(required_handle(
858 ptr,
859 "MDLTransformScaleOp",
860 )?))
861 }
862
863 pub fn add_matrix_op(&self, name: &str, inverse: bool) -> Result<TransformMatrixOp> {
865 let name = c_string(name)?;
866 let ptr = unsafe {
868 ffi::mdl_transform_stack_add_matrix_op(
869 self.handle.as_ptr(),
870 name.as_ptr(),
871 i32::from(inverse),
872 )
873 };
874 Ok(TransformMatrixOp::from_handle(required_handle(
875 ptr,
876 "MDLTransformMatrixOp",
877 )?))
878 }
879
880 pub fn add_orient_op(&self, name: &str, inverse: bool) -> Result<TransformOrientOp> {
882 let name = c_string(name)?;
883 let ptr = unsafe {
885 ffi::mdl_transform_stack_add_orient_op(
886 self.handle.as_ptr(),
887 name.as_ptr(),
888 i32::from(inverse),
889 )
890 };
891 Ok(TransformOrientOp::from_handle(required_handle(
892 ptr,
893 "MDLTransformOrientOp",
894 )?))
895 }
896
897 pub fn animated_value_named(&self, name: &str) -> Result<Option<AnimatedValue>> {
899 let name = c_string(name)?;
900 let ptr = unsafe {
902 ffi::mdl_transform_stack_animated_value_named(self.handle.as_ptr(), name.as_ptr())
903 };
904 Ok(unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(AnimatedValue::from_handle))
906 }
907
908 #[must_use]
909 pub fn float4x4_at_time(&self, time: f64) -> [f32; 16] {
911 let mut matrix = [0.0_f32; 16];
912 unsafe {
914 ffi::mdl_transform_stack_copy_float4x4_at_time(
915 self.handle.as_ptr(),
916 time,
917 matrix.as_mut_ptr(),
918 );
919 };
920 matrix
921 }
922
923 #[must_use]
924 pub fn count(&self) -> usize {
926 unsafe { ffi::mdl_transform_stack_count(self.handle.as_ptr()) as usize }
928 }
929
930 pub fn transform_ops(&self) -> Result<Vec<TransformOp>> {
932 let ptr = unsafe { ffi::mdl_transform_stack_transform_ops(self.handle.as_ptr()) };
934 if ptr.is_null() {
935 return Ok(Vec::new());
936 }
937 array_objects(
938 ptr,
939 "MDLTransformStack transformOps",
940 TransformOp::from_handle,
941 )
942 }
943
944 #[must_use]
945 pub fn as_transform_component(&self) -> TransformComponent {
947 TransformComponent::from_handle(self.handle.clone())
948 }
949}
950
951impl Object {
952 #[must_use]
953 pub fn transform_component(&self) -> Option<TransformComponent> {
955 let ptr = unsafe { ffi::mdl_object_transform_component(self.as_ptr()) };
957 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(TransformComponent::from_handle)
959 }
960
961 pub fn set_transform_component(&self, component: Option<&TransformComponent>) {
963 unsafe {
965 ffi::mdl_object_set_transform_component(
966 self.as_ptr(),
967 component.map_or(ptr::null_mut(), TransformComponent::as_ptr),
968 );
969 }
970 }
971}