il2cpp_bridge_rs/structs/components/core/mono_behaviour.rs
1//! Unity MonoBehaviour wrapper
2//!
3//! This module provides a wrapper for Unity's MonoBehaviour class,
4//! with support for starting and stopping coroutines.
5
6use super::component::{Component, ComponentTrait};
7use crate::structs::core::runtime::coroutine::Coroutine;
8use crate::structs::Il2cppString;
9use std::ffi::c_void;
10use std::ops::Deref;
11
12/// Wrapper around Unity's MonoBehaviour component
13///
14/// MonoBehaviour is the base class from which every Unity script derives.
15/// This wrapper provides access to coroutine functionality.
16#[repr(C)]
17#[derive(Debug, Clone, Copy)]
18pub struct MonoBehaviour {
19 /// Base Component structure
20 pub component: Component,
21}
22
23impl ComponentTrait for MonoBehaviour {
24 fn from_ptr(ptr: *mut c_void) -> Self {
25 Self {
26 component: Component::from_ptr(ptr),
27 }
28 }
29}
30
31impl MonoBehaviour {
32 /// Creates a MonoBehaviour from a raw pointer
33 ///
34 /// # Arguments
35 /// * `ptr` - The raw pointer to the MonoBehaviour
36 ///
37 /// # Returns
38 /// * `Self` - The created MonoBehaviour wrapper
39 pub fn from_ptr(ptr: *mut c_void) -> Self {
40 <Self as ComponentTrait>::from_ptr(ptr)
41 }
42
43 /// Returns the raw pointer to the MonoBehaviour
44 ///
45 /// # Returns
46 /// * `*mut c_void` - The raw pointer
47 pub fn as_ptr(&self) -> *mut c_void {
48 self.component.as_ptr()
49 }
50
51 /// Starts a coroutine with the given IEnumerator
52 ///
53 /// This calls `MonoBehaviour.StartCoroutine(IEnumerator routine)` on the
54 /// Unity side. The IEnumerator should be created from a method that
55 /// returns IEnumerator (e.g., a generator method).
56 ///
57 /// # Arguments
58 /// * `enumerator` - Pointer to the IEnumerator object
59 ///
60 /// # Returns
61 /// * `Result<Coroutine, String>` - The started Coroutine, or an error
62 pub fn start_coroutine(&self, enumerator: *mut c_void) -> Result<Coroutine, String> {
63 if enumerator.is_null() {
64 return Err("Enumerator is null".to_string());
65 }
66
67 unsafe {
68 let method = self
69 .method(("StartCoroutine", ["System.Collections.IEnumerator"]))
70 .ok_or("Method 'StartCoroutine(IEnumerator)' not found")?;
71
72 let result = method.call::<*mut c_void>(&[enumerator])?;
73
74 if result.is_null() {
75 return Err("StartCoroutine returned null".to_string());
76 }
77
78 Ok(Coroutine::from_ptr(result))
79 }
80 }
81
82 /// Starts a coroutine by method name
83 ///
84 /// This calls `MonoBehaviour.StartCoroutine(string methodName)` on the
85 /// Unity side.
86 ///
87 /// # Arguments
88 /// * `method_name` - The name of the coroutine method to start
89 ///
90 /// # Returns
91 /// * `Result<Coroutine, String>` - The started Coroutine, or an error
92 pub fn start_coroutine_by_name(&self, method_name: &str) -> Result<Coroutine, String> {
93 unsafe {
94 let name_str = Il2cppString::new(method_name);
95
96 let method = self
97 .method(("StartCoroutine", ["System.String"]))
98 .ok_or("Method 'StartCoroutine(String)' not found")?;
99
100 let result = method.call::<*mut c_void>(&[name_str as *mut c_void])?;
101
102 if result.is_null() {
103 return Err("StartCoroutine returned null".to_string());
104 }
105
106 Ok(Coroutine::from_ptr(result))
107 }
108 }
109
110 /// Stops a specific coroutine
111 ///
112 /// # Arguments
113 /// * `coroutine` - The Coroutine to stop
114 ///
115 /// # Returns
116 /// * `Result<(), String>` - Ok if successful, or an error
117 pub fn stop_coroutine(&self, coroutine: Coroutine) -> Result<(), String> {
118 if coroutine.is_null() {
119 return Err("Coroutine is null".to_string());
120 }
121
122 unsafe {
123 let method = self
124 .method(("StopCoroutine", ["UnityEngine.Coroutine"]))
125 .ok_or("Method 'StopCoroutine(Coroutine)' not found")?;
126
127 method.call::<()>(&[coroutine.as_ptr()])?;
128
129 Ok(())
130 }
131 }
132
133 /// Stops a coroutine by method name
134 ///
135 /// # Arguments
136 /// * `method_name` - The name of the coroutine method to stop
137 ///
138 /// # Returns
139 /// * `Result<(), String>` - Ok if successful, or an error
140 pub fn stop_coroutine_by_name(&self, method_name: &str) -> Result<(), String> {
141 unsafe {
142 let name_str = Il2cppString::new(method_name);
143
144 let method = self
145 .method(("StopCoroutine", ["System.String"]))
146 .ok_or("Method 'StopCoroutine(String)' not found")?;
147
148 method.call::<()>(&[name_str as *mut c_void])?;
149
150 Ok(())
151 }
152 }
153
154 /// Stops all coroutines running on this MonoBehaviour
155 ///
156 /// # Returns
157 /// * `Result<(), String>` - Ok if successful, or an error
158 pub fn stop_all_coroutines(&self) -> Result<(), String> {
159 unsafe {
160 let method = self
161 .method("StopAllCoroutines")
162 .ok_or("Method 'StopAllCoroutines' not found")?;
163
164 method.call::<()>(&[])?;
165
166 Ok(())
167 }
168 }
169
170 /// Checks if the MonoBehaviour is enabled
171 ///
172 /// # Returns
173 /// * `Result<bool, String>` - True if enabled
174 pub fn get_enabled(&self) -> Result<bool, String> {
175 unsafe {
176 self.method("get_enabled")
177 .ok_or("Method 'get_enabled' not found")?
178 .call::<bool>(&[])
179 }
180 }
181
182 /// Sets the enabled state of the MonoBehaviour
183 ///
184 /// # Arguments
185 /// * `enabled` - Whether the MonoBehaviour should be enabled
186 ///
187 /// # Returns
188 /// * `Result<(), String>` - Ok if successful
189 pub fn set_enabled(&self, enabled: bool) -> Result<(), String> {
190 unsafe {
191 let mut arg = enabled;
192 self.method("set_enabled")
193 .ok_or("Method 'set_enabled' not found")?
194 .call::<()>(&[&mut arg as *mut bool as *mut c_void])?;
195
196 Ok(())
197 }
198 }
199}
200
201impl Deref for MonoBehaviour {
202 type Target = Component;
203
204 fn deref(&self) -> &Self::Target {
205 &self.component
206 }
207}