il2cpp_bridge_rs/structs/components/scene/
scene_management.rs1use crate::logger;
3use crate::{
4 api::cache,
5 structs::{
6 collections::{Il2cppArray, Il2cppString},
7 components::GameObject,
8 core::Class,
9 },
10};
11use std::ffi::c_void;
12
13#[repr(C)]
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct Scene {
16 pub handle: i32,
18}
19
20impl Scene {
21 fn get_class() -> Option<Class> {
23 cache::coremodule().class("UnityEngine.SceneManagement.Scene")
24 }
25
26 pub fn is_valid(&self) -> bool {
31 unsafe {
32 if let Some(class) = Self::get_class() {
33 if let Some(method) = class.method("IsValidInternal") {
34 return method
35 .call::<bool>(&[&self.handle as *const i32 as *mut c_void])
36 .unwrap_or(false);
37 }
38 }
39 false
40 }
41 }
42
43 pub fn build_index(&self) -> i32 {
48 unsafe {
49 if let Some(class) = Self::get_class() {
50 if let Some(method) = class.method("GetBuildIndexInternal") {
51 return method
52 .call::<i32>(&[&self.handle as *const i32 as *mut c_void])
53 .unwrap_or(-1);
54 }
55 }
56 -1
57 }
58 }
59
60 pub fn is_loaded(&self) -> bool {
65 unsafe {
66 if let Some(class) = Self::get_class() {
67 if let Some(method) = class.method("GetIsLoadedInternal") {
68 return method
69 .call::<bool>(&[&self.handle as *const i32 as *mut c_void])
70 .unwrap_or(false);
71 }
72 }
73 false
74 }
75 }
76
77 pub fn name(&self) -> String {
82 unsafe {
83 if let Some(class) = Self::get_class() {
84 if let Some(method) = class.method("GetNameInternal") {
85 if let Ok(ptr) = method
86 .call::<*mut Il2cppString>(&[&self.handle as *const i32 as *mut c_void])
87 {
88 if !ptr.is_null() {
89 return (*ptr).to_string().unwrap_or_default();
90 }
91 }
92 }
93 }
94 String::new()
95 }
96 }
97
98 pub fn path(&self) -> String {
103 unsafe {
104 if let Some(class) = Self::get_class() {
105 if let Some(method) = class.method("GetPathInternal") {
106 if let Ok(ptr) = method
107 .call::<*mut Il2cppString>(&[&self.handle as *const i32 as *mut c_void])
108 {
109 if !ptr.is_null() {
110 return (*ptr).to_string().unwrap_or_default();
111 }
112 }
113 }
114 }
115 String::new()
116 }
117 }
118
119 pub fn root_count(&self) -> i32 {
124 unsafe {
125 if let Some(class) = Self::get_class() {
126 if let Some(method) = class.method("GetRootCountInternal") {
127 return method
128 .call::<i32>(&[&self.handle as *const i32 as *mut c_void])
129 .unwrap_or(0);
130 }
131 }
132 0
133 }
134 }
135
136 pub fn root_game_objects(&self) -> Vec<GameObject> {
141 unsafe {
142 let class = match Self::get_class() {
143 Some(c) => c,
144 None => return Vec::new(),
145 };
146
147 let mut method = match class.method(("GetRootGameObjects", 0)) {
148 Some(m) => m,
149 None => {
150 logger::error("Method 'GetRootGameObjects' with 0 args not found");
151 return Vec::new();
152 }
153 };
154
155 method.instance = Some(&self.handle as *const i32 as *mut c_void);
156
157 let ptr = method
158 .call::<*mut Il2cppArray<*mut c_void>>(&[])
159 .unwrap_or(std::ptr::null_mut());
160
161 if ptr.is_null() {
162 return Vec::new();
163 }
164
165 let array_ptr = ptr;
166 let mut objects = Vec::new();
167 let array = &*array_ptr;
168
169 for i in 0..array.max_length {
170 let obj_ptr = array.at(i);
171 if !obj_ptr.is_null() {
172 objects.push(GameObject::from_ptr(obj_ptr));
173 }
174 }
175 objects
176 }
177 }
178}
179
180pub struct SceneManager;
181
182impl SceneManager {
183 fn get_class() -> Option<Class> {
185 cache::coremodule().class("UnityEngine.SceneManagement.SceneManager")
186 }
187
188 pub fn scene_count() -> i32 {
193 unsafe {
194 if let Some(class) = Self::get_class() {
195 if let Some(method) = class.method("get_sceneCount") {
196 return method.call::<i32>(&[]).unwrap_or(0);
197 }
198 }
199 0
200 }
201 }
202
203 pub fn get_active_scene() -> Result<Scene, String> {
208 let class = Self::get_class()
209 .ok_or("Class 'UnityEngine.SceneManagement.SceneManager' not found")?;
210
211 let method = class
212 .method("GetActiveScene")
213 .ok_or("Method 'GetActiveScene' not found")?;
214
215 unsafe { method.call::<Scene>(&[]) }
216 }
217
218 pub fn get_scene_at(index: i32) -> Result<Scene, String> {
226 let class = Self::get_class()
227 .ok_or("Class 'UnityEngine.SceneManagement.SceneManager' not found")?;
228
229 let method = class
230 .method("GetSceneAt")
231 .ok_or("Method 'GetSceneAt' not found")?;
232
233 unsafe { method.call::<Scene>(&[&index as *const i32 as *mut c_void]) }
234 }
235
236 pub fn get_scene_by_name(name: &str) -> Result<Scene, String> {
244 let class = Self::get_class()
245 .ok_or("Class 'UnityEngine.SceneManagement.SceneManager' not found")?;
246
247 let method = class
248 .method("GetSceneByName")
249 .ok_or("Method 'GetSceneByName' not found")?;
250
251 let name_str = Il2cppString::new(name);
252 if name_str.is_null() {
253 return Err("Failed to create Il2cppString".to_string());
254 }
255
256 unsafe { method.call::<Scene>(&[name_str as *mut c_void]) }
257 }
258
259 pub fn load_scene_at(index: i32) -> Result<(), String> {
267 let class = Self::get_class()
268 .ok_or("Class 'UnityEngine.SceneManagement.SceneManager' not found")?;
269
270 let method = class
271 .method(("LoadScene", ["System.Int32"]))
272 .ok_or("Method 'LoadScene(int)' not found")?;
273
274 unsafe {
275 method.call::<()>(&[&index as *const i32 as *mut c_void])?;
276 }
277 Ok(())
278 }
279
280 pub fn load_scene_name(name: &str) -> Result<(), String> {
288 let class = Self::get_class()
289 .ok_or("Class 'UnityEngine.SceneManagement.SceneManager' not found")?;
290
291 let method = class
292 .method(("LoadScene", ["System.String"]))
293 .ok_or("Method 'LoadScene(string)' not found")?;
294
295 let name_str = Il2cppString::new(name);
296 if name_str.is_null() {
297 return Err("Failed to create Il2cppString".to_string());
298 }
299
300 unsafe {
301 method.call::<()>(&[name_str as *mut c_void])?;
302 }
303 Ok(())
304 }
305}