11#include " jsb_script_instance.h"
2+ #include " jsb_script.h"
23#include " jsb_script_language.h"
4+ #include " modules/gdscript/gdscript_rpc_callable.h"
35
46GodotJSScriptInstanceBase::ScriptCallProfilingScope::ScriptCallProfilingScope (const ScriptProfilingInfo& p_info, const StringName& p_method)
57 : info_(p_info), method_(p_method)
@@ -56,10 +58,31 @@ void GodotJSScriptInstance::cache_property(const StringName& name, const Variant
5658
5759bool GodotJSScriptInstance::set (const StringName& p_name, const Variant& p_value)
5860{
59- if (const auto & it = script_->script_class_info_ .properties .find (p_name); it)
61+ GodotJSScript* sptr = script_.ptr ();
62+ while (sptr)
6063 {
61- return env_->set_script_property_value (object_id_, it->value , p_value);
64+ if (const auto & it = sptr->script_class_info_ .properties .find (p_name); it)
65+ {
66+ return env_->set_script_property_value (object_id_, it->value , p_value);
67+ }
68+
69+ // TODO: Static variable?
70+
71+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_set)); it)
72+ {
73+ Variant name = p_name;
74+ const Variant *args[2 ] = { &name, &p_value };
75+
76+ Callable::CallError err;
77+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_set), (const Variant **)args, 2 , err);
78+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () == Variant::BOOL && ret.operator bool ()) {
79+ return true ;
80+ }
81+ }
82+
83+ sptr = sptr->base .ptr ();
6284 }
85+
6386 return false ;
6487}
6588
@@ -73,17 +96,110 @@ bool GodotJSScriptInstance::get(const StringName& p_name, Variant& r_ret) const
7396 return true ;
7497 }
7598
76- if (const auto & it = script_->script_class_info_ .properties .find (p_name); it)
99+ GodotJSScript* sptr = script_.ptr ();
100+ while (sptr)
77101 {
78- return env_->get_script_property_value (object_id_, it->value , r_ret);
102+ if (const auto & it = sptr->script_class_info_ .properties .find (p_name); it)
103+ {
104+ return env_->get_script_property_value (object_id_, it->value , r_ret);
105+ }
106+
107+ // TODO: constant?
108+ // TODO: static variable?
109+ // TODO: Inner class?
110+
111+ if (const auto & it = sptr->script_class_info_ .signals .find (p_name); it)
112+ {
113+ r_ret = Signal (owner_, p_name);
114+ return true ;
115+ }
116+
117+ if (const auto & it = sptr->script_class_info_ .methods .find (p_name); it)
118+ {
119+ if (sptr->script_class_info_ .rpc_config .has (p_name)) {
120+ r_ret = Callable (memnew (GDScriptRPCCallable (owner_, p_name)));
121+ return true ;
122+ } else {
123+ if (!it->value .is_static ())
124+ {
125+ r_ret = Callable (owner_, p_name);
126+ return true ;
127+ } else {
128+ // TODO: Warp static method to Callable
129+ }
130+ }
131+ }
132+
133+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_get)); it)
134+ {
135+ Variant name = p_name;
136+ const Variant *args[1 ] = { &name };
137+
138+ Callable::CallError err;
139+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_get), (const Variant **)args, 1 , err);
140+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () != Variant::NIL )
141+ {
142+ r_ret = ret;
143+ return true ;
144+ }
145+ }
146+
147+ sptr = sptr->base .ptr ();
79148 }
80149
81150 return false ;
82151}
83152
84153void GodotJSScriptInstance::get_property_list (List<PropertyInfo>* p_properties) const
85154{
86- script_->get_script_property_list (p_properties);
155+ GodotJSScript* sptr = script_.ptr ();
156+ HashSet<String> properties;
157+
158+ while (sptr)
159+ {
160+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_get_property_list)); it)
161+ {
162+ Callable::CallError err;
163+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_get_property_list), nullptr , 0 , err);
164+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () != Variant::NIL )
165+ {
166+ ERR_FAIL_COND_MSG (ret.get_type () != Variant::ARRAY , " Wrong type for _get_property_list, must be an array of dictionaries." );
167+
168+ Array arr = ret;
169+ for (int i = 0 ; i < arr.size (); i++)
170+ {
171+ Dictionary d = arr[i];
172+ ERR_CONTINUE (!d.has (" name" ));
173+ ERR_CONTINUE (!d.has (" type" ));
174+
175+ PropertyInfo pinfo = PropertyInfo::from_dict (d);
176+
177+ ERR_CONTINUE (pinfo.name .is_empty () && (pinfo.usage & PROPERTY_USAGE_STORAGE ));
178+ ERR_CONTINUE (pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX );
179+
180+ ERR_CONTINUE_MSG (properties.has (pinfo.name ), vformat (" Duplicate property \" %s\" in script: %s" , pinfo.name , script_->get_path ()));
181+
182+ p_properties->push_back (pinfo);
183+ properties.insert (pinfo.name );
184+ }
185+ }
186+ }
187+
188+ #ifdef TOOLS_ENABLED
189+ p_properties->push_back (sptr->get_class_category ());
190+ #endif
191+ for (const auto & it : sptr->script_class_info_ .properties )
192+ {
193+ ERR_CONTINUE_MSG (properties.has (it.value .name ), vformat (" Duplicate property \" %s\" in script: %s" , it.value .name , script_->get_path ()));
194+ p_properties->push_back ((PropertyInfo) it.value );
195+ }
196+
197+ sptr = sptr->base .ptr ();
198+ }
199+
200+ for (PropertyInfo &prop : *p_properties) {
201+ validate_property (prop);
202+ }
87203}
88204
89205const Variant GodotJSScriptInstance::get_rpc_config () const
@@ -93,31 +209,88 @@ const Variant GodotJSScriptInstance::get_rpc_config() const
93209
94210Variant::Type GodotJSScriptInstance::get_property_type (const StringName& p_name, bool * r_is_valid) const
95211{
96- const jsb::ScriptClassInfoPtr class_info = get_script_class ();
97- if (const HashMap<StringName, jsb::ScriptPropertyInfo>::ConstIterator it = class_info->properties .find (p_name))
98- {
99- if (r_is_valid) *r_is_valid = true ;
100- return it->value .type ;
212+ GodotJSScript* sptr = script_.ptr ();
213+ while (sptr) {
214+ if (const HashMap<StringName, jsb::ScriptPropertyInfo>::ConstIterator it = sptr->script_class_info_ .properties .find (p_name))
215+ {
216+ if (r_is_valid) *r_is_valid = true ;
217+ return it->value .type ;
218+ }
219+
220+ sptr = sptr->base .ptr ();
101221 }
222+
102223 if (r_is_valid) *r_is_valid = false ;
103224 return Variant::NIL ;
104225}
105226
106227void GodotJSScriptInstance::validate_property (PropertyInfo& p_property) const
107228{
108- // TODO
229+ GodotJSScript* sptr = script_.ptr ();
230+ while (sptr)
231+ {
232+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_validate_property)); it)
233+ {
234+ Variant property = (Dictionary)p_property;
235+ const Variant *args[1 ] = { &property };
236+
237+ Callable::CallError err;
238+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_validate_property), (const Variant **)args, 1 , err);
239+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () != Variant::NIL )
240+ {
241+ p_property = PropertyInfo::from_dict (property);
242+ }
243+ }
244+
245+ sptr = sptr->base .ptr ();
246+ }
109247}
110248
111249bool GodotJSScriptInstance::property_can_revert (const StringName& p_name) const
112250{
113- // TODO
114- return false ;
251+ GodotJSScript* sptr = script_.ptr ();
252+ while (sptr)
253+ {
254+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_property_can_revert)); it)
255+ {
256+ Variant name = p_name;
257+ const Variant *args[1 ] = { &name };
258+
259+ Callable::CallError err;
260+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_property_can_revert), args, 1 , err);
261+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () == Variant::BOOL && ret.operator bool ()) {
262+ return true ;
263+ }
264+ }
265+
266+ sptr = sptr->base .ptr ();
267+ }
268+
269+ return false ;
115270}
116271
117272bool GodotJSScriptInstance::property_get_revert (const StringName& p_name, Variant& r_ret) const
118273{
119- // TODO
120- return false ;
274+ GodotJSScript* sptr = script_.ptr ();
275+ while (sptr)
276+ {
277+ if (const auto & it = sptr->script_class_info_ .methods .find (jsb_string_name (_property_get_revert)); it)
278+ {
279+ Variant name = p_name;
280+ const Variant *args[1 ] = { &name };
281+
282+ Callable::CallError err;
283+ Variant ret = env_->call_script_method (class_id_, object_id_, jsb_string_name (_property_get_revert), args, 1 , err);
284+ if (err.error == Callable::CallError::CALL_OK && ret.get_type () == Variant::BOOL && ret.operator bool ()) {
285+ r_ret = ret;
286+ return true ;
287+ }
288+ }
289+
290+ sptr = sptr->base .ptr ();
291+ }
292+
293+ return false ;
121294}
122295
123296void GodotJSScriptInstance::get_method_list (List<MethodInfo>* p_list) const
0 commit comments