1/**************************************************************************/
2/* script_language_extension.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef SCRIPT_LANGUAGE_EXTENSION_H
32#define SCRIPT_LANGUAGE_EXTENSION_H
33
34#include "core/extension/ext_wrappers.gen.inc"
35#include "core/object/gdvirtual.gen.inc"
36#include "core/object/script_language.h"
37#include "core/variant/native_ptr.h"
38#include "core/variant/typed_array.h"
39
40class ScriptExtension : public Script {
41 GDCLASS(ScriptExtension, Script)
42
43protected:
44 EXBIND0R(bool, editor_can_reload_from_file)
45
46 GDVIRTUAL1(_placeholder_erased, GDExtensionPtr<void>)
47 virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override {
48 GDVIRTUAL_CALL(_placeholder_erased, p_placeholder);
49 }
50
51 static void _bind_methods();
52
53public:
54 EXBIND0RC(bool, can_instantiate)
55 EXBIND0RC(Ref<Script>, get_base_script)
56 EXBIND0RC(StringName, get_global_name)
57 EXBIND1RC(bool, inherits_script, const Ref<Script> &)
58 EXBIND0RC(StringName, get_instance_base_type)
59
60 GDVIRTUAL1RC(GDExtensionPtr<void>, _instance_create, Object *)
61 virtual ScriptInstance *instance_create(Object *p_this) override {
62 GDExtensionPtr<void> ret = nullptr;
63 GDVIRTUAL_REQUIRED_CALL(_instance_create, p_this, ret);
64 return reinterpret_cast<ScriptInstance *>(ret.operator void *());
65 }
66 GDVIRTUAL1RC(GDExtensionPtr<void>, _placeholder_instance_create, Object *)
67 PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override {
68 GDExtensionPtr<void> ret = nullptr;
69 GDVIRTUAL_REQUIRED_CALL(_placeholder_instance_create, p_this, ret);
70 return reinterpret_cast<PlaceHolderScriptInstance *>(ret.operator void *());
71 }
72
73 EXBIND1RC(bool, instance_has, const Object *)
74 EXBIND0RC(bool, has_source_code)
75 EXBIND0RC(String, get_source_code)
76 EXBIND1(set_source_code, const String &)
77 EXBIND1R(Error, reload, bool)
78
79 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_documentation)
80 GDVIRTUAL0RC(String, _get_class_icon_path)
81#ifdef TOOLS_ENABLED
82 virtual Vector<DocData::ClassDoc> get_documentation() const override {
83 TypedArray<Dictionary> doc;
84 GDVIRTUAL_REQUIRED_CALL(_get_documentation, doc);
85
86 Vector<DocData::ClassDoc> class_doc;
87 for (int i = 0; i < doc.size(); i++) {
88 class_doc.append(DocData::ClassDoc::from_dict(doc[i]));
89 }
90
91 return class_doc;
92 }
93
94 virtual String get_class_icon_path() const override {
95 String ret;
96 GDVIRTUAL_CALL(_get_class_icon_path, ret);
97 return ret;
98 }
99#endif // TOOLS_ENABLED
100
101 EXBIND1RC(bool, has_method, const StringName &)
102
103 GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
104 virtual MethodInfo get_method_info(const StringName &p_method) const override {
105 Dictionary mi;
106 GDVIRTUAL_REQUIRED_CALL(_get_method_info, p_method, mi);
107 return MethodInfo::from_dict(mi);
108 }
109
110 EXBIND0RC(bool, is_tool)
111 EXBIND0RC(bool, is_valid)
112
113 EXBIND0RC(ScriptLanguage *, get_language)
114 EXBIND1RC(bool, has_script_signal, const StringName &)
115
116 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_signal_list)
117
118 virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override {
119 TypedArray<Dictionary> sl;
120 GDVIRTUAL_REQUIRED_CALL(_get_script_signal_list, sl);
121 for (int i = 0; i < sl.size(); i++) {
122 r_signals->push_back(MethodInfo::from_dict(sl[i]));
123 }
124 }
125
126 GDVIRTUAL1RC(bool, _has_property_default_value, const StringName &)
127 GDVIRTUAL1RC(Variant, _get_property_default_value, const StringName &)
128
129 virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const override {
130 bool has_dv = false;
131 if (!GDVIRTUAL_REQUIRED_CALL(_has_property_default_value, p_property, has_dv) || !has_dv) {
132 return false;
133 }
134 Variant ret;
135 GDVIRTUAL_REQUIRED_CALL(_get_property_default_value, p_property, ret);
136 r_value = ret;
137 return true;
138 }
139
140 EXBIND0(update_exports)
141
142 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_method_list)
143
144 virtual void get_script_method_list(List<MethodInfo> *r_methods) const override {
145 TypedArray<Dictionary> sl;
146 GDVIRTUAL_REQUIRED_CALL(_get_script_method_list, sl);
147 for (int i = 0; i < sl.size(); i++) {
148 r_methods->push_back(MethodInfo::from_dict(sl[i]));
149 }
150 }
151
152 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_property_list)
153
154 virtual void get_script_property_list(List<PropertyInfo> *r_propertys) const override {
155 TypedArray<Dictionary> sl;
156 GDVIRTUAL_REQUIRED_CALL(_get_script_property_list, sl);
157 for (int i = 0; i < sl.size(); i++) {
158 r_propertys->push_back(PropertyInfo::from_dict(sl[i]));
159 }
160 }
161
162 EXBIND1RC(int, get_member_line, const StringName &)
163
164 GDVIRTUAL0RC(Dictionary, _get_constants)
165
166 virtual void get_constants(HashMap<StringName, Variant> *p_constants) override {
167 Dictionary constants;
168 GDVIRTUAL_REQUIRED_CALL(_get_constants, constants);
169 List<Variant> keys;
170 constants.get_key_list(&keys);
171 for (const Variant &K : keys) {
172 p_constants->insert(K, constants[K]);
173 }
174 }
175 GDVIRTUAL0RC(TypedArray<StringName>, _get_members)
176 virtual void get_members(HashSet<StringName> *p_members) override {
177 TypedArray<StringName> members;
178 GDVIRTUAL_REQUIRED_CALL(_get_members, members);
179 for (int i = 0; i < members.size(); i++) {
180 p_members->insert(members[i]);
181 }
182 }
183
184 EXBIND0RC(bool, is_placeholder_fallback_enabled)
185
186 GDVIRTUAL0RC(Variant, _get_rpc_config)
187
188 virtual const Variant get_rpc_config() const override {
189 Variant ret;
190 GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret);
191 return ret;
192 }
193
194 ScriptExtension() {}
195};
196
197typedef ScriptLanguage::ProfilingInfo ScriptLanguageExtensionProfilingInfo;
198
199GDVIRTUAL_NATIVE_PTR(ScriptLanguageExtensionProfilingInfo)
200
201class ScriptLanguageExtension : public ScriptLanguage {
202 GDCLASS(ScriptLanguageExtension, ScriptLanguage)
203protected:
204 static void _bind_methods();
205
206public:
207 EXBIND0RC(String, get_name)
208
209 EXBIND0(init)
210 EXBIND0RC(String, get_type)
211 EXBIND0RC(String, get_extension)
212 EXBIND0(finish)
213
214 /* EDITOR FUNCTIONS */
215
216 GDVIRTUAL0RC(Vector<String>, _get_reserved_words)
217
218 virtual void get_reserved_words(List<String> *p_words) const override {
219 Vector<String> ret;
220 GDVIRTUAL_REQUIRED_CALL(_get_reserved_words, ret);
221 for (int i = 0; i < ret.size(); i++) {
222 p_words->push_back(ret[i]);
223 }
224 }
225 EXBIND1RC(bool, is_control_flow_keyword, String)
226
227 GDVIRTUAL0RC(Vector<String>, _get_comment_delimiters)
228
229 virtual void get_comment_delimiters(List<String> *p_words) const override {
230 Vector<String> ret;
231 GDVIRTUAL_REQUIRED_CALL(_get_comment_delimiters, ret);
232 for (int i = 0; i < ret.size(); i++) {
233 p_words->push_back(ret[i]);
234 }
235 }
236
237 GDVIRTUAL0RC(Vector<String>, _get_string_delimiters)
238
239 virtual void get_string_delimiters(List<String> *p_words) const override {
240 Vector<String> ret;
241 GDVIRTUAL_REQUIRED_CALL(_get_string_delimiters, ret);
242 for (int i = 0; i < ret.size(); i++) {
243 p_words->push_back(ret[i]);
244 }
245 }
246
247 EXBIND3RC(Ref<Script>, make_template, const String &, const String &, const String &)
248
249 GDVIRTUAL1RC(TypedArray<Dictionary>, _get_built_in_templates, StringName)
250
251 virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override {
252 TypedArray<Dictionary> ret;
253 GDVIRTUAL_REQUIRED_CALL(_get_built_in_templates, p_object, ret);
254 Vector<ScriptTemplate> stret;
255 for (int i = 0; i < ret.size(); i++) {
256 Dictionary d = ret[i];
257 ScriptTemplate st;
258 ERR_CONTINUE(!d.has("inherit"));
259 st.inherit = d["inherit"];
260 ERR_CONTINUE(!d.has("name"));
261 st.name = d["name"];
262 ERR_CONTINUE(!d.has("description"));
263 st.description = d["description"];
264 ERR_CONTINUE(!d.has("content"));
265 st.content = d["content"];
266 ERR_CONTINUE(!d.has("id"));
267 st.id = d["id"];
268 ERR_CONTINUE(!d.has("origin"));
269 st.origin = TemplateLocation(int(d["origin"]));
270 stret.push_back(st);
271 }
272 return stret;
273 }
274
275 EXBIND0R(bool, is_using_templates)
276
277 GDVIRTUAL6RC(Dictionary, _validate, const String &, const String &, bool, bool, bool, bool)
278 virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override {
279 Dictionary ret;
280 GDVIRTUAL_REQUIRED_CALL(_validate, p_script, p_path, r_functions != nullptr, r_errors != nullptr, r_warnings != nullptr, r_safe_lines != nullptr, ret);
281 if (!ret.has("valid")) {
282 return false;
283 }
284 if (r_functions != nullptr && ret.has("functions")) {
285 Vector<String> functions = ret["functions"];
286 for (int i = 0; i < functions.size(); i++) {
287 r_functions->push_back(functions[i]);
288 }
289 }
290 if (r_errors != nullptr && ret.has("errors")) {
291 Array errors = ret["errors"];
292 for (int i = 0; i < errors.size(); i++) {
293 Dictionary err = errors[i];
294 ERR_CONTINUE(!err.has("line"));
295 ERR_CONTINUE(!err.has("column"));
296 ERR_CONTINUE(!err.has("message"));
297
298 ScriptError serr;
299 serr.line = err["line"];
300 serr.column = err["column"];
301 serr.message = err["message"];
302
303 r_errors->push_back(serr);
304 }
305 }
306 if (r_warnings != nullptr && ret.has("warnings")) {
307 ERR_FAIL_COND_V(!ret.has("warnings"), false);
308 Array warnings = ret["warnings"];
309 for (int i = 0; i < warnings.size(); i++) {
310 Dictionary warn = warnings[i];
311 ERR_CONTINUE(!warn.has("start_line"));
312 ERR_CONTINUE(!warn.has("end_line"));
313 ERR_CONTINUE(!warn.has("leftmost_column"));
314 ERR_CONTINUE(!warn.has("rightmost_column"));
315 ERR_CONTINUE(!warn.has("code"));
316 ERR_CONTINUE(!warn.has("string_code"));
317 ERR_CONTINUE(!warn.has("message"));
318
319 Warning swarn;
320 swarn.start_line = warn["start_line"];
321 swarn.end_line = warn["end_line"];
322 swarn.leftmost_column = warn["leftmost_column"];
323 swarn.rightmost_column = warn["rightmost_column"];
324 swarn.code = warn["code"];
325 swarn.string_code = warn["string_code"];
326 swarn.message = warn["message"];
327
328 r_warnings->push_back(swarn);
329 }
330 }
331 if (r_safe_lines != nullptr && ret.has("safe_lines")) {
332 PackedInt32Array safe_lines = ret["safe_lines"];
333 for (int i = 0; i < safe_lines.size(); i++) {
334 r_safe_lines->insert(safe_lines[i]);
335 }
336 }
337 return ret["valid"];
338 }
339
340 EXBIND1RC(String, validate_path, const String &)
341 GDVIRTUAL0RC(Object *, _create_script)
342 Script *create_script() const override {
343 Object *ret = nullptr;
344 GDVIRTUAL_REQUIRED_CALL(_create_script, ret);
345 return Object::cast_to<Script>(ret);
346 }
347 EXBIND0RC(bool, has_named_classes)
348 EXBIND0RC(bool, supports_builtin_mode)
349 EXBIND0RC(bool, supports_documentation)
350 EXBIND0RC(bool, can_inherit_from_file)
351
352 EXBIND2RC(int, find_function, const String &, const String &)
353 EXBIND3RC(String, make_function, const String &, const String &, const PackedStringArray &)
354 EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int)
355 EXBIND0R(bool, overrides_external_editor)
356
357 GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *)
358
359 virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<CodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) override {
360 Dictionary ret;
361 GDVIRTUAL_REQUIRED_CALL(_complete_code, p_code, p_path, p_owner, ret);
362 if (!ret.has("result")) {
363 return ERR_UNAVAILABLE;
364 }
365
366 if (r_options != nullptr && ret.has("options")) {
367 Array options = ret["options"];
368 for (int i = 0; i < options.size(); i++) {
369 Dictionary op = options[i];
370 CodeCompletionOption option;
371 ERR_CONTINUE(!op.has("kind"));
372 option.kind = CodeCompletionKind(int(op["kind"]));
373 ERR_CONTINUE(!op.has("display"));
374 option.display = op["display"];
375 ERR_CONTINUE(!op.has("insert_text"));
376 option.insert_text = op["insert_text"];
377 ERR_CONTINUE(!op.has("font_color"));
378 option.font_color = op["font_color"];
379 ERR_CONTINUE(!op.has("icon"));
380 option.icon = op["icon"];
381 ERR_CONTINUE(!op.has("default_value"));
382 option.default_value = op["default_value"];
383 ERR_CONTINUE(!op.has("location"));
384 option.location = op["location"];
385 if (op.has("matches")) {
386 PackedInt32Array matches = op["matches"];
387 ERR_CONTINUE(matches.size() & 1);
388 for (int j = 0; j < matches.size(); j += 2) {
389 option.matches.push_back(Pair<int, int>(matches[j], matches[j + 1]));
390 }
391 }
392 r_options->push_back(option);
393 }
394 }
395
396 ERR_FAIL_COND_V(!ret.has("force"), ERR_UNAVAILABLE);
397 r_force = ret["force"];
398 ERR_FAIL_COND_V(!ret.has("call_hint"), ERR_UNAVAILABLE);
399 r_call_hint = ret["call_hint"];
400 ERR_FAIL_COND_V(!ret.has("result"), ERR_UNAVAILABLE);
401 Error result = Error(int(ret["result"]));
402
403 return result;
404 }
405
406 GDVIRTUAL4RC(Dictionary, _lookup_code, const String &, const String &, const String &, Object *)
407
408 virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) override {
409 Dictionary ret;
410 GDVIRTUAL_REQUIRED_CALL(_lookup_code, p_code, p_symbol, p_path, p_owner, ret);
411 if (!ret.has("result")) {
412 return ERR_UNAVAILABLE;
413 }
414
415 ERR_FAIL_COND_V(!ret.has("type"), ERR_UNAVAILABLE);
416 r_result.type = LookupResultType(int(ret["type"]));
417 ERR_FAIL_COND_V(!ret.has("script"), ERR_UNAVAILABLE);
418 r_result.script = ret["script"];
419 ERR_FAIL_COND_V(!ret.has("class_name"), ERR_UNAVAILABLE);
420 r_result.class_name = ret["class_name"];
421 ERR_FAIL_COND_V(!ret.has("class_path"), ERR_UNAVAILABLE);
422 r_result.class_path = ret["class_path"];
423 ERR_FAIL_COND_V(!ret.has("location"), ERR_UNAVAILABLE);
424 r_result.location = ret["location"];
425
426 Error result = Error(int(ret["result"]));
427
428 return result;
429 }
430
431 GDVIRTUAL3RC(String, _auto_indent_code, const String &, int, int)
432 virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const override {
433 String ret;
434 GDVIRTUAL_REQUIRED_CALL(_auto_indent_code, p_code, p_from_line, p_to_line, ret);
435 p_code = ret;
436 }
437 EXBIND2(add_global_constant, const StringName &, const Variant &)
438 EXBIND2(add_named_global_constant, const StringName &, const Variant &)
439 EXBIND1(remove_named_global_constant, const StringName &)
440
441 /* MULTITHREAD FUNCTIONS */
442
443 //some VMs need to be notified of thread creation/exiting to allocate a stack
444 EXBIND0(thread_enter)
445 EXBIND0(thread_exit)
446
447 EXBIND0RC(String, debug_get_error)
448 EXBIND0RC(int, debug_get_stack_level_count)
449 EXBIND1RC(int, debug_get_stack_level_line, int)
450 EXBIND1RC(String, debug_get_stack_level_function, int)
451 EXBIND1RC(String, debug_get_stack_level_source, int)
452
453 GDVIRTUAL3R(Dictionary, _debug_get_stack_level_locals, int, int, int)
454 virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
455 Dictionary ret;
456 GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_locals, p_level, p_max_subitems, p_max_depth, ret);
457 if (ret.size() == 0) {
458 return;
459 }
460 if (p_locals != nullptr && ret.has("locals")) {
461 PackedStringArray strings = ret["locals"];
462 for (int i = 0; i < strings.size(); i++) {
463 p_locals->push_back(strings[i]);
464 }
465 }
466 if (p_values != nullptr && ret.has("values")) {
467 Array values = ret["values"];
468 for (int i = 0; i < values.size(); i++) {
469 p_values->push_back(values[i]);
470 }
471 }
472 }
473 GDVIRTUAL3R(Dictionary, _debug_get_stack_level_members, int, int, int)
474 virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
475 Dictionary ret;
476 GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_members, p_level, p_max_subitems, p_max_depth, ret);
477 if (ret.size() == 0) {
478 return;
479 }
480 if (p_members != nullptr && ret.has("members")) {
481 PackedStringArray strings = ret["members"];
482 for (int i = 0; i < strings.size(); i++) {
483 p_members->push_back(strings[i]);
484 }
485 }
486 if (p_values != nullptr && ret.has("values")) {
487 Array values = ret["values"];
488 for (int i = 0; i < values.size(); i++) {
489 p_values->push_back(values[i]);
490 }
491 }
492 }
493 GDVIRTUAL1R(GDExtensionPtr<void>, _debug_get_stack_level_instance, int)
494
495 virtual ScriptInstance *debug_get_stack_level_instance(int p_level) override {
496 GDExtensionPtr<void> ret = nullptr;
497 GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_instance, p_level, ret);
498 return reinterpret_cast<ScriptInstance *>(ret.operator void *());
499 }
500 GDVIRTUAL2R(Dictionary, _debug_get_globals, int, int)
501 virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
502 Dictionary ret;
503 GDVIRTUAL_REQUIRED_CALL(_debug_get_globals, p_max_subitems, p_max_depth, ret);
504 if (ret.size() == 0) {
505 return;
506 }
507 if (p_globals != nullptr && ret.has("globals")) {
508 PackedStringArray strings = ret["globals"];
509 for (int i = 0; i < strings.size(); i++) {
510 p_globals->push_back(strings[i]);
511 }
512 }
513 if (p_values != nullptr && ret.has("values")) {
514 Array values = ret["values"];
515 for (int i = 0; i < values.size(); i++) {
516 p_values->push_back(values[i]);
517 }
518 }
519 }
520
521 EXBIND4R(String, debug_parse_stack_level_expression, int, const String &, int, int)
522
523 GDVIRTUAL0R(TypedArray<Dictionary>, _debug_get_current_stack_info)
524 virtual Vector<StackInfo> debug_get_current_stack_info() override {
525 TypedArray<Dictionary> ret;
526 GDVIRTUAL_REQUIRED_CALL(_debug_get_current_stack_info, ret);
527 Vector<StackInfo> sret;
528 for (int i = 0; i < ret.size(); i++) {
529 StackInfo si;
530 Dictionary d = ret[i];
531 ERR_CONTINUE(!d.has("file"));
532 ERR_CONTINUE(!d.has("func"));
533 ERR_CONTINUE(!d.has("line"));
534 si.file = d["file"];
535 si.func = d["func"];
536 si.line = d["line"];
537 sret.push_back(si);
538 }
539 return sret;
540 }
541
542 EXBIND0(reload_all_scripts)
543 EXBIND2(reload_tool_script, const Ref<Script> &, bool)
544 /* LOADER FUNCTIONS */
545
546 GDVIRTUAL0RC(PackedStringArray, _get_recognized_extensions)
547
548 virtual void get_recognized_extensions(List<String> *p_extensions) const override {
549 PackedStringArray ret;
550 GDVIRTUAL_REQUIRED_CALL(_get_recognized_extensions, ret);
551 for (int i = 0; i < ret.size(); i++) {
552 p_extensions->push_back(ret[i]);
553 }
554 }
555
556 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_functions)
557 virtual void get_public_functions(List<MethodInfo> *p_functions) const override {
558 TypedArray<Dictionary> ret;
559 GDVIRTUAL_REQUIRED_CALL(_get_public_functions, ret);
560 for (int i = 0; i < ret.size(); i++) {
561 MethodInfo mi = MethodInfo::from_dict(ret[i]);
562 p_functions->push_back(mi);
563 }
564 }
565 GDVIRTUAL0RC(Dictionary, _get_public_constants)
566 virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {
567 Dictionary ret;
568 GDVIRTUAL_REQUIRED_CALL(_get_public_constants, ret);
569 for (int i = 0; i < ret.size(); i++) {
570 Dictionary d = ret[i];
571 ERR_CONTINUE(!d.has("name"));
572 ERR_CONTINUE(!d.has("value"));
573 p_constants->push_back(Pair<String, Variant>(d["name"], d["value"]));
574 }
575 }
576 GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_annotations)
577 virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override {
578 TypedArray<Dictionary> ret;
579 GDVIRTUAL_REQUIRED_CALL(_get_public_annotations, ret);
580 for (int i = 0; i < ret.size(); i++) {
581 MethodInfo mi = MethodInfo::from_dict(ret[i]);
582 p_annotations->push_back(mi);
583 }
584 }
585
586 EXBIND0(profiling_start)
587 EXBIND0(profiling_stop)
588
589 GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
590
591 virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
592 int ret = 0;
593 GDVIRTUAL_REQUIRED_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
594 return ret;
595 }
596
597 GDVIRTUAL2R(int, _profiling_get_frame_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
598
599 virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override {
600 int ret = 0;
601 GDVIRTUAL_REQUIRED_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
602 return ret;
603 }
604
605 EXBIND0(frame)
606
607 EXBIND1RC(bool, handles_global_class_type, const String &)
608
609 GDVIRTUAL1RC(Dictionary, _get_global_class_name, const String &)
610
611 virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const override {
612 Dictionary ret;
613 GDVIRTUAL_REQUIRED_CALL(_get_global_class_name, p_path, ret);
614 if (!ret.has("name")) {
615 return String();
616 }
617 if (r_base_type != nullptr && ret.has("base_type")) {
618 *r_base_type = ret["base_type"];
619 }
620 if (r_icon_path != nullptr && ret.has("icon_path")) {
621 *r_icon_path = ret["icon_path"];
622 }
623 return ret["name"];
624 }
625};
626
627VARIANT_ENUM_CAST(ScriptLanguageExtension::LookupResultType)
628VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionKind)
629VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
630
631class ScriptInstanceExtension : public ScriptInstance {
632public:
633 const GDExtensionScriptInstanceInfo2 *native_info;
634 bool free_native_info = false;
635 struct {
636 GDExtensionClassNotification notification_func;
637 } deprecated_native_info;
638
639 GDExtensionScriptInstanceDataPtr instance = nullptr;
640
641// There should not be warnings on explicit casts.
642#if defined(__GNUC__) && !defined(__clang__)
643#pragma GCC diagnostic push
644#pragma GCC diagnostic ignored "-Wignored-qualifiers"
645#endif
646
647 virtual bool set(const StringName &p_name, const Variant &p_value) override {
648 if (native_info->set_func) {
649 return native_info->set_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value);
650 }
651 return false;
652 }
653 virtual bool get(const StringName &p_name, Variant &r_ret) const override {
654 if (native_info->get_func) {
655 return native_info->get_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret);
656 }
657 return false;
658 }
659 virtual void get_property_list(List<PropertyInfo> *p_list) const override {
660 if (native_info->get_property_list_func) {
661 uint32_t pcount;
662 const GDExtensionPropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
663
664#ifdef TOOLS_ENABLED
665 Ref<Script> script = get_script();
666 if (script.is_valid() && pcount > 0) {
667 p_list->push_back(script->get_class_category());
668 }
669#endif // TOOLS_ENABLED
670
671 for (uint32_t i = 0; i < pcount; i++) {
672 p_list->push_back(PropertyInfo(pinfo[i]));
673 }
674 if (native_info->free_property_list_func) {
675 native_info->free_property_list_func(instance, pinfo);
676 }
677 }
678 }
679 virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override {
680 if (native_info->get_property_type_func) {
681 GDExtensionBool is_valid = 0;
682 GDExtensionVariantType type = native_info->get_property_type_func(instance, (GDExtensionConstStringNamePtr)&p_name, &is_valid);
683 if (r_is_valid) {
684 *r_is_valid = is_valid != 0;
685 }
686 return Variant::Type(type);
687 }
688 return Variant::NIL;
689 }
690 virtual void validate_property(PropertyInfo &p_property) const override {
691 if (native_info->validate_property_func) {
692 // GDExtension uses a StringName rather than a String for property name.
693 StringName prop_name = p_property.name;
694 GDExtensionPropertyInfo gdext_prop = {
695 (GDExtensionVariantType)p_property.type,
696 &prop_name,
697 &p_property.class_name,
698 (uint32_t)p_property.hint,
699 &p_property.hint_string,
700 p_property.usage,
701 };
702 if (native_info->validate_property_func(instance, &gdext_prop)) {
703 p_property.type = (Variant::Type)gdext_prop.type;
704 p_property.name = *reinterpret_cast<StringName *>(gdext_prop.name);
705 p_property.class_name = *reinterpret_cast<StringName *>(gdext_prop.class_name);
706 p_property.hint = (PropertyHint)gdext_prop.hint;
707 p_property.hint_string = *reinterpret_cast<String *>(gdext_prop.hint_string);
708 p_property.usage = gdext_prop.usage;
709 }
710 }
711 }
712
713 virtual bool property_can_revert(const StringName &p_name) const override {
714 if (native_info->property_can_revert_func) {
715 return native_info->property_can_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name);
716 }
717 return false;
718 }
719 virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override {
720 if (native_info->property_get_revert_func) {
721 return native_info->property_get_revert_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&r_ret);
722 }
723 return false;
724 }
725
726 virtual Object *get_owner() override {
727 if (native_info->get_owner_func) {
728 return (Object *)native_info->get_owner_func(instance);
729 }
730 return nullptr;
731 }
732 static void _add_property_with_state(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata) {
733 List<Pair<StringName, Variant>> *state = (List<Pair<StringName, Variant>> *)p_userdata;
734 state->push_back(Pair<StringName, Variant>(*(const StringName *)p_name, *(const Variant *)p_value));
735 }
736 virtual void get_property_state(List<Pair<StringName, Variant>> &state) override {
737 if (native_info->get_property_state_func) {
738 native_info->get_property_state_func(instance, _add_property_with_state, &state);
739 }
740 }
741
742 virtual void get_method_list(List<MethodInfo> *p_list) const override {
743 if (native_info->get_method_list_func) {
744 uint32_t mcount;
745 const GDExtensionMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount);
746 for (uint32_t i = 0; i < mcount; i++) {
747 p_list->push_back(MethodInfo(minfo[i]));
748 }
749 if (native_info->free_method_list_func) {
750 native_info->free_method_list_func(instance, minfo);
751 }
752 }
753 }
754 virtual bool has_method(const StringName &p_method) const override {
755 if (native_info->has_method_func) {
756 return native_info->has_method_func(instance, (GDExtensionStringNamePtr)&p_method);
757 }
758 return false;
759 }
760
761 virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
762 Variant ret;
763 if (native_info->call_func) {
764 GDExtensionCallError ce;
765 native_info->call_func(instance, (GDExtensionConstStringNamePtr)&p_method, (GDExtensionConstVariantPtr *)p_args, p_argcount, (GDExtensionVariantPtr)&ret, &ce);
766 r_error.error = Callable::CallError::Error(ce.error);
767 r_error.argument = ce.argument;
768 r_error.expected = ce.expected;
769 }
770 return ret;
771 }
772
773 virtual void notification(int p_notification, bool p_reversed = false) override {
774 if (native_info->notification_func) {
775 native_info->notification_func(instance, p_notification, p_reversed);
776#ifndef DISABLE_DEPRECATED
777 } else if (deprecated_native_info.notification_func) {
778 deprecated_native_info.notification_func(instance, p_notification);
779#endif // DISABLE_DEPRECATED
780 }
781 }
782
783 virtual String to_string(bool *r_valid) override {
784 if (native_info->to_string_func) {
785 GDExtensionBool valid;
786 String ret;
787 native_info->to_string_func(instance, &valid, reinterpret_cast<GDExtensionStringPtr>(&ret));
788 if (r_valid) {
789 *r_valid = valid != 0;
790 }
791 return ret;
792 }
793 return String();
794 }
795
796 virtual void refcount_incremented() override {
797 if (native_info->refcount_incremented_func) {
798 native_info->refcount_incremented_func(instance);
799 }
800 }
801 virtual bool refcount_decremented() override {
802 if (native_info->refcount_decremented_func) {
803 return native_info->refcount_decremented_func(instance);
804 }
805 return false;
806 }
807
808 virtual Ref<Script> get_script() const override {
809 if (native_info->get_script_func) {
810 GDExtensionObjectPtr script = native_info->get_script_func(instance);
811 return Ref<Script>(reinterpret_cast<Script *>(script));
812 }
813 return Ref<Script>();
814 }
815
816 virtual bool is_placeholder() const override {
817 if (native_info->is_placeholder_func) {
818 return native_info->is_placeholder_func(instance);
819 }
820 return false;
821 }
822
823 virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) override {
824 if (native_info->set_fallback_func) {
825 bool ret = native_info->set_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value);
826 if (r_valid) {
827 *r_valid = ret;
828 }
829 }
830 }
831 virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid) override {
832 Variant ret;
833 if (native_info->get_fallback_func) {
834 bool valid = native_info->get_fallback_func(instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret);
835 if (r_valid) {
836 *r_valid = valid;
837 }
838 }
839 return ret;
840 }
841
842 virtual ScriptLanguage *get_language() override {
843 if (native_info->get_language_func) {
844 GDExtensionScriptLanguagePtr lang = native_info->get_language_func(instance);
845 return reinterpret_cast<ScriptLanguage *>(lang);
846 }
847 return nullptr;
848 ;
849 }
850 virtual ~ScriptInstanceExtension() {
851 if (native_info->free_func) {
852 native_info->free_func(instance);
853 }
854 if (free_native_info) {
855 memfree(const_cast<GDExtensionScriptInstanceInfo2 *>(native_info));
856 }
857 }
858
859#if defined(__GNUC__) && !defined(__clang__)
860#pragma GCC diagnostic pop
861#endif
862};
863
864#endif // SCRIPT_LANGUAGE_EXTENSION_H
865