Skip to main content

il2cpp_bridge_rs/structs/components/core/
transform.rs

1//! Unity `Transform` wrapper.
2use crate::structs::core::{Il2cppObject, Object};
3use crate::structs::math::{Quaternion, Vector3};
4use std::ffi::c_void;
5
6use super::component::ComponentTrait;
7use super::game_object::GameObject;
8
9/// Wrapper for a managed `UnityEngine.Transform`.
10#[repr(transparent)]
11#[derive(Debug, Clone, Copy)]
12pub struct Transform {
13    /// Pointer to the internal IL2CPP object
14    pub ptr: *mut Il2cppObject,
15}
16
17impl ComponentTrait for Transform {
18    fn from_ptr(ptr: *mut c_void) -> Self {
19        Self {
20            ptr: ptr as *mut Il2cppObject,
21        }
22    }
23}
24
25impl Transform {
26    /// Creates a `Transform` from a raw managed pointer.
27    pub unsafe fn from_ptr(ptr: *mut c_void) -> Self {
28        <Self as ComponentTrait>::from_ptr(ptr)
29    }
30
31    /// Returns the raw managed pointer.
32    pub fn as_ptr(&self) -> *mut c_void {
33        self.ptr as *mut c_void
34    }
35
36    /// Returns the `GameObject` attached to this transform.
37    pub fn get_game_object(&self) -> Result<GameObject, String> {
38        unsafe {
39            let obj = Object::from_ptr(self.as_ptr());
40            let ptr = obj
41                .method("get_gameObject")
42                .ok_or("Method 'get_gameObject' not found")?
43                .call::<*mut c_void>(&[])?;
44
45            if ptr.is_null() {
46                return Err("Transform.gameObject is null".to_string());
47            }
48
49            Ok(GameObject::from_ptr(ptr))
50        }
51    }
52
53    /// Returns the world position.
54    pub fn get_position(&self) -> Result<Vector3, String> {
55        unsafe {
56            let obj = Object::from_ptr(self.as_ptr());
57            obj.method("get_position")
58                .ok_or("Method 'get_position' not found")?
59                .call::<Vector3>(&[])
60        }
61    }
62
63    /// Sets the world position.
64    pub fn set_position(&self, value: Vector3) -> Result<(), String> {
65        unsafe {
66            let obj = Object::from_ptr(self.as_ptr());
67            let params = [&value as *const Vector3 as *mut c_void];
68            obj.method("set_position")
69                .ok_or("Method 'set_position' not found")?
70                .call::<()>(&params)
71        }
72    }
73
74    /// Returns the local position relative to the parent transform.
75    pub fn local_position(&self) -> Result<Vector3, String> {
76        unsafe {
77            let obj = Object::from_ptr(self.as_ptr());
78            obj.method("get_localPosition")
79                .ok_or("Method 'get_localPosition' not found")?
80                .call::<Vector3>(&[])
81        }
82    }
83
84    /// Sets the local position relative to the parent transform.
85    pub fn set_local_position(&self, value: Vector3) -> Result<(), String> {
86        unsafe {
87            let obj = Object::from_ptr(self.as_ptr());
88            let params = [&value as *const Vector3 as *mut c_void];
89            obj.method("set_localPosition")
90                .ok_or("Method 'set_localPosition' not found")?
91                .call::<()>(&params)
92        }
93    }
94
95    /// Returns the world rotation.
96    pub fn get_rotation(&self) -> Result<Quaternion, String> {
97        unsafe {
98            let obj = Object::from_ptr(self.as_ptr());
99            obj.method("get_rotation")
100                .ok_or("Method 'get_rotation' not found")?
101                .call::<Quaternion>(&[])
102        }
103    }
104
105    /// Sets the world rotation.
106    pub fn set_rotation(&self, value: Quaternion) -> Result<(), String> {
107        unsafe {
108            let obj = Object::from_ptr(self.as_ptr());
109            let params = [&value as *const Quaternion as *mut c_void];
110            obj.method("set_rotation")
111                .ok_or("Method 'set_rotation' not found")?
112                .call::<()>(&params)
113        }
114    }
115
116    /// Returns the local rotation relative to the parent transform.
117    pub fn local_rotation(&self) -> Result<Quaternion, String> {
118        unsafe {
119            let obj = Object::from_ptr(self.as_ptr());
120            obj.method("get_localRotation")
121                .ok_or("Method 'get_localRotation' not found")?
122                .call::<Quaternion>(&[])
123        }
124    }
125
126    /// Sets the local rotation relative to the parent transform.
127    pub fn set_local_rotation(&self, value: Quaternion) -> Result<(), String> {
128        unsafe {
129            let obj = Object::from_ptr(self.as_ptr());
130            let params = [&value as *const Quaternion as *mut c_void];
131            obj.method("set_localRotation")
132                .ok_or("Method 'set_localRotation' not found")?
133                .call::<()>(&params)
134        }
135    }
136
137    /// Returns the local scale.
138    pub fn get_local_scale(&self) -> Result<Vector3, String> {
139        unsafe {
140            let obj = Object::from_ptr(self.as_ptr());
141            obj.method("get_localScale")
142                .ok_or("Method 'get_localScale' not found")?
143                .call::<Vector3>(&[])
144        }
145    }
146
147    /// Sets the local scale.
148    pub fn set_local_scale(&self, value: Vector3) -> Result<(), String> {
149        unsafe {
150            let obj = Object::from_ptr(self.as_ptr());
151            let params = [&value as *const Vector3 as *mut c_void];
152            obj.method("set_localScale")
153                .ok_or("Method 'set_localScale' not found")?
154                .call::<()>(&params)
155        }
156    }
157
158    /// Returns the lossy world scale approximation.
159    pub fn get_lossy_scale(&self) -> Result<Vector3, String> {
160        unsafe {
161            let obj = Object::from_ptr(self.as_ptr());
162            obj.method("get_lossyScale")
163                .ok_or("Method 'get_lossyScale' not found")?
164                .call::<Vector3>(&[])
165        }
166    }
167
168    /// Returns the number of direct child transforms.
169    pub fn get_child_count(&self) -> i32 {
170        unsafe {
171            let obj = Object::from_ptr(self.as_ptr());
172            if let Some(method) = obj.method("get_childCount") {
173                return method.call::<i32>(&[]).unwrap_or(0);
174            }
175            0
176        }
177    }
178
179    /// Returns the child transform at `index`.
180    pub fn get_child(&self, index: i32) -> Result<Transform, String> {
181        unsafe {
182            let obj = Object::from_ptr(self.as_ptr());
183            let params = [&index as *const i32 as *mut c_void];
184            let ptr = obj
185                .method(("GetChild", ["System.Int32"]))
186                .ok_or("Method 'GetChild' not found")?
187                .call::<*mut c_void>(&params)?;
188
189            if ptr.is_null() {
190                return Err("Child is null".to_string());
191            }
192
193            Ok(Transform::from_ptr(ptr))
194        }
195    }
196}