44 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
55 */
66
7- use std:: { collections:: HashMap , rc:: Rc } ;
7+ use core:: panic;
8+ use std:: { collections:: HashMap , fmt:: Debug , ops:: DerefMut , pin:: Pin } ;
89
910use godot:: {
1011 builtin:: meta:: { MethodInfo , PropertyInfo } ,
1112 engine:: { Script , ScriptInstance , SiMut } ,
1213 prelude:: { GString , Gd , Object , StringName , Variant , VariantType } ,
1314} ;
15+ use godot_cell:: GdCell ;
1416
1517use crate :: script_registry:: GodotScriptObject ;
1618
1719use super :: { rust_script:: RustScript , rust_script_language:: RustScriptLanguage , SCRIPT_REGISTRY } ;
1820
19- fn script_method_list ( script : & Gd < RustScript > ) -> Rc < [ MethodInfo ] > {
21+ fn script_method_list ( script : & Gd < RustScript > ) -> Box < [ MethodInfo ] > {
2022 let rs = script. bind ( ) ;
2123 let class_name = rs. str_class_name ( ) ;
2224
@@ -25,7 +27,7 @@ fn script_method_list(script: &Gd<RustScript>) -> Rc<[MethodInfo]> {
2527 . expect ( "script registry is inaccessible" )
2628 . get ( & class_name)
2729 . map ( |meta| meta. methods ( ) . iter ( ) . map ( MethodInfo :: from) . collect ( ) )
28- . unwrap_or_else ( || Rc :: new ( [ ] ) as Rc < [ MethodInfo ] > ) ;
30+ . unwrap_or_else ( || Box :: new ( [ ] ) as Box < [ MethodInfo ] > ) ;
2931
3032 methods
3133}
@@ -34,7 +36,7 @@ fn script_class_name(script: &Gd<RustScript>) -> GString {
3436 script. bind ( ) . get_class_name ( )
3537}
3638
37- fn script_property_list ( script : & Gd < RustScript > ) -> Rc < [ PropertyInfo ] > {
39+ fn script_property_list ( script : & Gd < RustScript > ) -> Box < [ PropertyInfo ] > {
3840 let rs = script. bind ( ) ;
3941 let class_name = rs. str_class_name ( ) ;
4042
@@ -43,18 +45,67 @@ fn script_property_list(script: &Gd<RustScript>) -> Rc<[PropertyInfo]> {
4345 . expect ( "script registry is inaccessible" )
4446 . get ( & class_name)
4547 . map ( |meta| meta. properties ( ) . iter ( ) . map ( PropertyInfo :: from) . collect ( ) )
46- . unwrap_or_else ( || Rc :: new ( [ ] ) as Rc < [ PropertyInfo ] > ) ;
48+ . unwrap_or_else ( || Box :: new ( [ ] ) as Box < [ PropertyInfo ] > ) ;
4749
4850 props
4951}
5052
53+ pub struct Context < ' a > {
54+ cell : Pin < & ' a GdCell < Box < dyn GodotScriptObject > > > ,
55+ data_ptr : * mut Box < dyn GodotScriptObject > ,
56+ }
57+
58+ impl < ' a > Debug for Context < ' a > {
59+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
60+ f. write_str ( "Context { <Call Context> }" )
61+ }
62+ }
63+
64+ impl < ' a > Context < ' a > {
65+ unsafe fn new (
66+ cell : Pin < & ' a GdCell < Box < dyn GodotScriptObject > > > ,
67+ data_ptr : * mut Box < dyn GodotScriptObject > ,
68+ ) -> Self {
69+ Self { cell, data_ptr }
70+ }
71+
72+ pub fn reentrant_scope < T : GodotScriptObject + ' static , R > (
73+ & mut self ,
74+ self_ref : & mut T ,
75+ cb : impl FnOnce ( ) -> R ,
76+ ) -> R {
77+ let known_ptr = unsafe {
78+ let any = ( * self . data_ptr ) . as_any_mut ( ) ;
79+
80+ any. downcast_mut :: < T > ( ) . unwrap ( ) as * mut T
81+ } ;
82+
83+ let self_ptr = self_ref as * mut _ ;
84+
85+ if known_ptr != self_ptr {
86+ panic ! ( "unable to create reentrant scope with unrelated self reference!" ) ;
87+ }
88+
89+ let guard = self
90+ . cell
91+ . make_inaccessible ( unsafe { & mut * self . data_ptr } )
92+ . unwrap ( ) ;
93+
94+ let result = cb ( ) ;
95+
96+ drop ( guard) ;
97+
98+ result
99+ }
100+ }
101+
51102pub ( super ) struct RustScriptInstance {
52- data : Box < dyn GodotScriptObject > ,
103+ data : Pin < Box < GdCell < Box < dyn GodotScriptObject > > > > ,
53104
54105 script : Gd < RustScript > ,
55106 generic_script : Gd < Script > ,
56- property_list : Rc < [ PropertyInfo ] > ,
57- method_list : Rc < [ MethodInfo ] > ,
107+ property_list : Box < [ PropertyInfo ] > ,
108+ method_list : Box < [ MethodInfo ] > ,
58109}
59110
60111impl RustScriptInstance {
@@ -64,7 +115,7 @@ impl RustScriptInstance {
64115 script : Gd < RustScript > ,
65116 ) -> Self {
66117 Self {
67- data,
118+ data : GdCell :: new ( data ) ,
68119 generic_script : script. clone ( ) . upcast ( ) ,
69120 property_list : script_property_list ( & script) ,
70121 method_list : script_method_list ( & script) ,
@@ -80,12 +131,17 @@ impl ScriptInstance for RustScriptInstance {
80131 script_class_name ( & self . script )
81132 }
82133
83- fn set_property ( mut this : SiMut < Self > , name : StringName , value : & Variant ) -> bool {
84- this. data . set ( name, value. to_owned ( ) )
134+ fn set_property ( this : SiMut < Self > , name : StringName , value : & Variant ) -> bool {
135+ let cell_ref = this. data . as_ref ( ) ;
136+ let mut mut_data = cell_ref. borrow_mut ( ) . unwrap ( ) ;
137+
138+ mut_data. set ( name, value. to_owned ( ) )
85139 }
86140
87141 fn get_property ( & self , name : StringName ) -> Option < Variant > {
88- self . data . get ( name)
142+ let guard = self . data . as_ref ( ) . borrow ( ) . unwrap ( ) ;
143+
144+ guard. get ( name)
89145 }
90146
91147 fn get_property_list ( & self ) -> Vec < PropertyInfo > {
@@ -97,11 +153,18 @@ impl ScriptInstance for RustScriptInstance {
97153 }
98154
99155 fn call (
100- mut this : SiMut < Self > ,
156+ this : SiMut < Self > ,
101157 method : StringName ,
102158 args : & [ & Variant ] ,
103159 ) -> Result < Variant , godot:: sys:: GDExtensionCallErrorType > {
104- this. data . call ( method, args)
160+ let cell = this. data . as_ref ( ) ;
161+ let mut data_guard = cell. borrow_mut ( ) . unwrap ( ) ;
162+ let data = data_guard. deref_mut ( ) ;
163+ let data_ptr = data as * mut _ ;
164+
165+ let context = unsafe { Context :: new ( cell, data_ptr) } ;
166+
167+ data. call ( method, args, context)
105168 }
106169
107170 fn get_script ( & self ) -> & Gd < Script > {
@@ -127,7 +190,8 @@ impl ScriptInstance for RustScriptInstance {
127190 }
128191
129192 fn to_string ( & self ) -> GString {
130- self . data . to_string ( ) . into ( )
193+ // self.data.to_string().into()
194+ GString :: new ( )
131195 }
132196
133197 fn get_property_state ( & self ) -> Vec < ( StringName , Variant ) > {
@@ -166,8 +230,8 @@ pub(super) struct RustScriptPlaceholder {
166230 script : Gd < RustScript > ,
167231 generic_script : Gd < Script > ,
168232 properties : HashMap < StringName , Variant > ,
169- property_list : Rc < [ PropertyInfo ] > ,
170- method_list : Rc < [ MethodInfo ] > ,
233+ property_list : Box < [ PropertyInfo ] > ,
234+ method_list : Box < [ MethodInfo ] > ,
171235}
172236
173237impl RustScriptPlaceholder {
0 commit comments