1 | /**************************************************************************/ |
2 | /* core_bind.cpp */ |
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 | #include "core_bind.h" |
32 | |
33 | #include "core/config/project_settings.h" |
34 | #include "core/crypto/crypto_core.h" |
35 | #include "core/debugger/engine_debugger.h" |
36 | #include "core/io/file_access_compressed.h" |
37 | #include "core/io/file_access_encrypted.h" |
38 | #include "core/io/marshalls.h" |
39 | #include "core/math/geometry_2d.h" |
40 | #include "core/math/geometry_3d.h" |
41 | #include "core/os/keyboard.h" |
42 | #include "core/os/thread_safe.h" |
43 | #include "core/variant/typed_array.h" |
44 | |
45 | namespace core_bind { |
46 | |
47 | ////// ResourceLoader ////// |
48 | |
49 | ResourceLoader *ResourceLoader::singleton = nullptr; |
50 | |
51 | Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) { |
52 | return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode)); |
53 | } |
54 | |
55 | ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) { |
56 | float progress = 0; |
57 | ::ResourceLoader::ThreadLoadStatus tls = ::ResourceLoader::load_threaded_get_status(p_path, &progress); |
58 | r_progress.resize(1); |
59 | r_progress[0] = progress; |
60 | return (ThreadLoadStatus)tls; |
61 | } |
62 | |
63 | Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path) { |
64 | Error error; |
65 | Ref<Resource> res = ::ResourceLoader::load_threaded_get(p_path, &error); |
66 | return res; |
67 | } |
68 | |
69 | Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hint, CacheMode p_cache_mode) { |
70 | Error err = OK; |
71 | Ref<Resource> ret = ::ResourceLoader::load(p_path, p_type_hint, ResourceFormatLoader::CacheMode(p_cache_mode), &err); |
72 | |
73 | ERR_FAIL_COND_V_MSG(err != OK, ret, "Error loading resource: '" + p_path + "'." ); |
74 | return ret; |
75 | } |
76 | |
77 | Vector<String> ResourceLoader::get_recognized_extensions_for_type(const String &p_type) { |
78 | List<String> exts; |
79 | ::ResourceLoader::get_recognized_extensions_for_type(p_type, &exts); |
80 | Vector<String> ret; |
81 | for (const String &E : exts) { |
82 | ret.push_back(E); |
83 | } |
84 | |
85 | return ret; |
86 | } |
87 | |
88 | void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) { |
89 | ::ResourceLoader::add_resource_format_loader(p_format_loader, p_at_front); |
90 | } |
91 | |
92 | void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) { |
93 | ::ResourceLoader::remove_resource_format_loader(p_format_loader); |
94 | } |
95 | |
96 | void ResourceLoader::set_abort_on_missing_resources(bool p_abort) { |
97 | ::ResourceLoader::set_abort_on_missing_resources(p_abort); |
98 | } |
99 | |
100 | PackedStringArray ResourceLoader::get_dependencies(const String &p_path) { |
101 | List<String> deps; |
102 | ::ResourceLoader::get_dependencies(p_path, &deps); |
103 | |
104 | PackedStringArray ret; |
105 | for (const String &E : deps) { |
106 | ret.push_back(E); |
107 | } |
108 | |
109 | return ret; |
110 | } |
111 | |
112 | bool ResourceLoader::has_cached(const String &p_path) { |
113 | String local_path = ProjectSettings::get_singleton()->localize_path(p_path); |
114 | return ResourceCache::has(local_path); |
115 | } |
116 | |
117 | bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) { |
118 | return ::ResourceLoader::exists(p_path, p_type_hint); |
119 | } |
120 | |
121 | ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) { |
122 | return ::ResourceLoader::get_resource_uid(p_path); |
123 | } |
124 | |
125 | void ResourceLoader::_bind_methods() { |
126 | ClassDB::bind_method(D_METHOD("load_threaded_request" , "path" , "type_hint" , "use_sub_threads" , "cache_mode" ), &ResourceLoader::load_threaded_request, DEFVAL("" ), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE)); |
127 | ClassDB::bind_method(D_METHOD("load_threaded_get_status" , "path" , "progress" ), &ResourceLoader::load_threaded_get_status, DEFVAL(Array())); |
128 | ClassDB::bind_method(D_METHOD("load_threaded_get" , "path" ), &ResourceLoader::load_threaded_get); |
129 | |
130 | ClassDB::bind_method(D_METHOD("load" , "path" , "type_hint" , "cache_mode" ), &ResourceLoader::load, DEFVAL("" ), DEFVAL(CACHE_MODE_REUSE)); |
131 | ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type" , "type" ), &ResourceLoader::get_recognized_extensions_for_type); |
132 | ClassDB::bind_method(D_METHOD("add_resource_format_loader" , "format_loader" , "at_front" ), &ResourceLoader::add_resource_format_loader, DEFVAL(false)); |
133 | ClassDB::bind_method(D_METHOD("remove_resource_format_loader" , "format_loader" ), &ResourceLoader::remove_resource_format_loader); |
134 | ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources" , "abort" ), &ResourceLoader::set_abort_on_missing_resources); |
135 | ClassDB::bind_method(D_METHOD("get_dependencies" , "path" ), &ResourceLoader::get_dependencies); |
136 | ClassDB::bind_method(D_METHOD("has_cached" , "path" ), &ResourceLoader::has_cached); |
137 | ClassDB::bind_method(D_METHOD("exists" , "path" , "type_hint" ), &ResourceLoader::exists, DEFVAL("" )); |
138 | ClassDB::bind_method(D_METHOD("get_resource_uid" , "path" ), &ResourceLoader::get_resource_uid); |
139 | |
140 | BIND_ENUM_CONSTANT(THREAD_LOAD_INVALID_RESOURCE); |
141 | BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS); |
142 | BIND_ENUM_CONSTANT(THREAD_LOAD_FAILED); |
143 | BIND_ENUM_CONSTANT(THREAD_LOAD_LOADED); |
144 | |
145 | BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE); |
146 | BIND_ENUM_CONSTANT(CACHE_MODE_REUSE); |
147 | BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE); |
148 | } |
149 | |
150 | ////// ResourceSaver ////// |
151 | |
152 | Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags) { |
153 | ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + p_path + "'." ); |
154 | return ::ResourceSaver::save(p_resource, p_path, p_flags); |
155 | } |
156 | |
157 | Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_resource) { |
158 | ERR_FAIL_COND_V_MSG(p_resource.is_null(), Vector<String>(), "It's not a reference to a valid Resource object." ); |
159 | List<String> exts; |
160 | ::ResourceSaver::get_recognized_extensions(p_resource, &exts); |
161 | Vector<String> ret; |
162 | for (const String &E : exts) { |
163 | ret.push_back(E); |
164 | } |
165 | return ret; |
166 | } |
167 | |
168 | void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) { |
169 | ::ResourceSaver::add_resource_format_saver(p_format_saver, p_at_front); |
170 | } |
171 | |
172 | void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) { |
173 | ::ResourceSaver::remove_resource_format_saver(p_format_saver); |
174 | } |
175 | |
176 | ResourceSaver *ResourceSaver::singleton = nullptr; |
177 | |
178 | void ResourceSaver::_bind_methods() { |
179 | ClassDB::bind_method(D_METHOD("save" , "resource" , "path" , "flags" ), &ResourceSaver::save, DEFVAL("" ), DEFVAL((uint32_t)FLAG_NONE)); |
180 | ClassDB::bind_method(D_METHOD("get_recognized_extensions" , "type" ), &ResourceSaver::get_recognized_extensions); |
181 | ClassDB::bind_method(D_METHOD("add_resource_format_saver" , "format_saver" , "at_front" ), &ResourceSaver::add_resource_format_saver, DEFVAL(false)); |
182 | ClassDB::bind_method(D_METHOD("remove_resource_format_saver" , "format_saver" ), &ResourceSaver::remove_resource_format_saver); |
183 | |
184 | BIND_BITFIELD_FLAG(FLAG_NONE); |
185 | BIND_BITFIELD_FLAG(FLAG_RELATIVE_PATHS); |
186 | BIND_BITFIELD_FLAG(FLAG_BUNDLE_RESOURCES); |
187 | BIND_BITFIELD_FLAG(FLAG_CHANGE_PATH); |
188 | BIND_BITFIELD_FLAG(FLAG_OMIT_EDITOR_PROPERTIES); |
189 | BIND_BITFIELD_FLAG(FLAG_SAVE_BIG_ENDIAN); |
190 | BIND_BITFIELD_FLAG(FLAG_COMPRESS); |
191 | BIND_BITFIELD_FLAG(FLAG_REPLACE_SUBRESOURCE_PATHS); |
192 | } |
193 | |
194 | ////// OS ////// |
195 | |
196 | PackedStringArray OS::get_connected_midi_inputs() { |
197 | return ::OS::get_singleton()->get_connected_midi_inputs(); |
198 | } |
199 | |
200 | void OS::open_midi_inputs() { |
201 | ::OS::get_singleton()->open_midi_inputs(); |
202 | } |
203 | |
204 | void OS::close_midi_inputs() { |
205 | ::OS::get_singleton()->close_midi_inputs(); |
206 | } |
207 | |
208 | void OS::set_use_file_access_save_and_swap(bool p_enable) { |
209 | FileAccess::set_backup_save(p_enable); |
210 | } |
211 | |
212 | void OS::set_low_processor_usage_mode(bool p_enabled) { |
213 | ::OS::get_singleton()->set_low_processor_usage_mode(p_enabled); |
214 | } |
215 | |
216 | bool OS::is_in_low_processor_usage_mode() const { |
217 | return ::OS::get_singleton()->is_in_low_processor_usage_mode(); |
218 | } |
219 | |
220 | void OS::set_low_processor_usage_mode_sleep_usec(int p_usec) { |
221 | ::OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(p_usec); |
222 | } |
223 | |
224 | int OS::get_low_processor_usage_mode_sleep_usec() const { |
225 | return ::OS::get_singleton()->get_low_processor_usage_mode_sleep_usec(); |
226 | } |
227 | |
228 | void OS::set_delta_smoothing(bool p_enabled) { |
229 | ::OS::get_singleton()->set_delta_smoothing(p_enabled); |
230 | } |
231 | |
232 | bool OS::is_delta_smoothing_enabled() const { |
233 | return ::OS::get_singleton()->is_delta_smoothing_enabled(); |
234 | } |
235 | |
236 | void OS::alert(const String &p_alert, const String &p_title) { |
237 | ::OS::get_singleton()->alert(p_alert, p_title); |
238 | } |
239 | |
240 | void OS::crash(const String &p_message) { |
241 | CRASH_NOW_MSG(p_message); |
242 | } |
243 | |
244 | Vector<String> OS::get_system_fonts() const { |
245 | return ::OS::get_singleton()->get_system_fonts(); |
246 | } |
247 | |
248 | String OS::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const { |
249 | return ::OS::get_singleton()->get_system_font_path(p_font_name, p_weight, p_stretch, p_italic); |
250 | } |
251 | |
252 | Vector<String> OS::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const { |
253 | return ::OS::get_singleton()->get_system_font_path_for_text(p_font_name, p_text, p_locale, p_script, p_weight, p_stretch, p_italic); |
254 | } |
255 | |
256 | String OS::get_executable_path() const { |
257 | return ::OS::get_singleton()->get_executable_path(); |
258 | } |
259 | |
260 | Error OS::shell_open(String p_uri) { |
261 | if (p_uri.begins_with("res://" )) { |
262 | WARN_PRINT("Attempting to open an URL with the \"res://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`." ); |
263 | } else if (p_uri.begins_with("user://" )) { |
264 | WARN_PRINT("Attempting to open an URL with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`." ); |
265 | } |
266 | return ::OS::get_singleton()->shell_open(p_uri); |
267 | } |
268 | |
269 | Error OS::shell_show_in_file_manager(String p_path, bool p_open_folder) { |
270 | if (p_path.begins_with("res://" )) { |
271 | WARN_PRINT("Attempting to explore file path with the \"res://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_show_in_file_manager()`." ); |
272 | } else if (p_path.begins_with("user://" )) { |
273 | WARN_PRINT("Attempting to explore file path with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_show_in_file_manager()`." ); |
274 | } |
275 | return ::OS::get_singleton()->shell_show_in_file_manager(p_path, p_open_folder); |
276 | } |
277 | |
278 | String OS::read_string_from_stdin() { |
279 | return ::OS::get_singleton()->get_stdin_string(); |
280 | } |
281 | |
282 | int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr, bool p_open_console) { |
283 | List<String> args; |
284 | for (int i = 0; i < p_arguments.size(); i++) { |
285 | args.push_back(p_arguments[i]); |
286 | } |
287 | String pipe; |
288 | int exitcode = 0; |
289 | Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr, nullptr, p_open_console); |
290 | r_output.push_back(pipe); |
291 | if (err != OK) { |
292 | return -1; |
293 | } |
294 | return exitcode; |
295 | } |
296 | |
297 | int OS::create_instance(const Vector<String> &p_arguments) { |
298 | List<String> args; |
299 | for (int i = 0; i < p_arguments.size(); i++) { |
300 | args.push_back(p_arguments[i]); |
301 | } |
302 | ::OS::ProcessID pid = 0; |
303 | Error err = ::OS::get_singleton()->create_instance(args, &pid); |
304 | if (err != OK) { |
305 | return -1; |
306 | } |
307 | return pid; |
308 | } |
309 | |
310 | int OS::create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console) { |
311 | List<String> args; |
312 | for (int i = 0; i < p_arguments.size(); i++) { |
313 | args.push_back(p_arguments[i]); |
314 | } |
315 | ::OS::ProcessID pid = 0; |
316 | Error err = ::OS::get_singleton()->create_process(p_path, args, &pid, p_open_console); |
317 | if (err != OK) { |
318 | return -1; |
319 | } |
320 | return pid; |
321 | } |
322 | |
323 | Error OS::kill(int p_pid) { |
324 | return ::OS::get_singleton()->kill(p_pid); |
325 | } |
326 | |
327 | bool OS::is_process_running(int p_pid) const { |
328 | return ::OS::get_singleton()->is_process_running(p_pid); |
329 | } |
330 | |
331 | int OS::get_process_id() const { |
332 | return ::OS::get_singleton()->get_process_id(); |
333 | } |
334 | |
335 | bool OS::has_environment(const String &p_var) const { |
336 | return ::OS::get_singleton()->has_environment(p_var); |
337 | } |
338 | |
339 | String OS::get_environment(const String &p_var) const { |
340 | return ::OS::get_singleton()->get_environment(p_var); |
341 | } |
342 | |
343 | void OS::set_environment(const String &p_var, const String &p_value) const { |
344 | ::OS::get_singleton()->set_environment(p_var, p_value); |
345 | } |
346 | |
347 | void OS::unset_environment(const String &p_var) const { |
348 | ::OS::get_singleton()->unset_environment(p_var); |
349 | } |
350 | |
351 | String OS::get_name() const { |
352 | return ::OS::get_singleton()->get_name(); |
353 | } |
354 | |
355 | String OS::get_distribution_name() const { |
356 | return ::OS::get_singleton()->get_distribution_name(); |
357 | } |
358 | |
359 | String OS::get_version() const { |
360 | return ::OS::get_singleton()->get_version(); |
361 | } |
362 | |
363 | Vector<String> OS::get_video_adapter_driver_info() const { |
364 | return ::OS::get_singleton()->get_video_adapter_driver_info(); |
365 | } |
366 | |
367 | Vector<String> OS::get_cmdline_args() { |
368 | List<String> cmdline = ::OS::get_singleton()->get_cmdline_args(); |
369 | Vector<String> cmdlinev; |
370 | for (const String &E : cmdline) { |
371 | cmdlinev.push_back(E); |
372 | } |
373 | |
374 | return cmdlinev; |
375 | } |
376 | |
377 | Vector<String> OS::get_cmdline_user_args() { |
378 | List<String> cmdline = ::OS::get_singleton()->get_cmdline_user_args(); |
379 | Vector<String> cmdlinev; |
380 | for (const String &E : cmdline) { |
381 | cmdlinev.push_back(E); |
382 | } |
383 | |
384 | return cmdlinev; |
385 | } |
386 | |
387 | void OS::set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments) { |
388 | List<String> args_list; |
389 | for (const String &restart_argument : p_restart_arguments) { |
390 | args_list.push_back(restart_argument); |
391 | } |
392 | |
393 | ::OS::get_singleton()->set_restart_on_exit(p_restart, args_list); |
394 | } |
395 | |
396 | bool OS::is_restart_on_exit_set() const { |
397 | return ::OS::get_singleton()->is_restart_on_exit_set(); |
398 | } |
399 | |
400 | Vector<String> OS::get_restart_on_exit_arguments() const { |
401 | List<String> args = ::OS::get_singleton()->get_restart_on_exit_arguments(); |
402 | Vector<String> args_vector; |
403 | for (List<String>::Element *E = args.front(); E; E = E->next()) { |
404 | args_vector.push_back(E->get()); |
405 | } |
406 | |
407 | return args_vector; |
408 | } |
409 | |
410 | String OS::get_locale() const { |
411 | return ::OS::get_singleton()->get_locale(); |
412 | } |
413 | |
414 | String OS::get_locale_language() const { |
415 | return ::OS::get_singleton()->get_locale_language(); |
416 | } |
417 | |
418 | String OS::get_model_name() const { |
419 | return ::OS::get_singleton()->get_model_name(); |
420 | } |
421 | |
422 | Error OS::set_thread_name(const String &p_name) { |
423 | return ::Thread::set_name(p_name); |
424 | } |
425 | |
426 | ::Thread::ID OS::get_thread_caller_id() const { |
427 | return ::Thread::get_caller_id(); |
428 | }; |
429 | |
430 | ::Thread::ID OS::get_main_thread_id() const { |
431 | return ::Thread::get_main_id(); |
432 | }; |
433 | |
434 | bool OS::has_feature(const String &p_feature) const { |
435 | const bool *value_ptr = feature_cache.getptr(p_feature); |
436 | if (value_ptr) { |
437 | return *value_ptr; |
438 | } else { |
439 | const bool has = ::OS::get_singleton()->has_feature(p_feature); |
440 | feature_cache[p_feature] = has; |
441 | return has; |
442 | } |
443 | } |
444 | |
445 | bool OS::is_sandboxed() const { |
446 | return ::OS::get_singleton()->is_sandboxed(); |
447 | } |
448 | |
449 | uint64_t OS::get_static_memory_usage() const { |
450 | return ::OS::get_singleton()->get_static_memory_usage(); |
451 | } |
452 | |
453 | uint64_t OS::get_static_memory_peak_usage() const { |
454 | return ::OS::get_singleton()->get_static_memory_peak_usage(); |
455 | } |
456 | |
457 | Dictionary OS::get_memory_info() const { |
458 | return ::OS::get_singleton()->get_memory_info(); |
459 | } |
460 | |
461 | /** This method uses a signed argument for better error reporting as it's used from the scripting API. */ |
462 | void OS::delay_usec(int p_usec) const { |
463 | ERR_FAIL_COND_MSG( |
464 | p_usec < 0, |
465 | vformat("Can't sleep for %d microseconds. The delay provided must be greater than or equal to 0 microseconds." , p_usec)); |
466 | ::OS::get_singleton()->delay_usec(p_usec); |
467 | } |
468 | |
469 | /** This method uses a signed argument for better error reporting as it's used from the scripting API. */ |
470 | void OS::delay_msec(int p_msec) const { |
471 | ERR_FAIL_COND_MSG( |
472 | p_msec < 0, |
473 | vformat("Can't sleep for %d milliseconds. The delay provided must be greater than or equal to 0 milliseconds." , p_msec)); |
474 | ::OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000); |
475 | } |
476 | |
477 | bool OS::is_userfs_persistent() const { |
478 | return ::OS::get_singleton()->is_userfs_persistent(); |
479 | } |
480 | |
481 | int OS::get_processor_count() const { |
482 | return ::OS::get_singleton()->get_processor_count(); |
483 | } |
484 | |
485 | String OS::get_processor_name() const { |
486 | return ::OS::get_singleton()->get_processor_name(); |
487 | } |
488 | |
489 | bool OS::is_stdout_verbose() const { |
490 | return ::OS::get_singleton()->is_stdout_verbose(); |
491 | } |
492 | |
493 | Error OS::move_to_trash(const String &p_path) const { |
494 | return ::OS::get_singleton()->move_to_trash(p_path); |
495 | } |
496 | |
497 | String OS::get_user_data_dir() const { |
498 | return ::OS::get_singleton()->get_user_data_dir(); |
499 | } |
500 | |
501 | String OS::get_config_dir() const { |
502 | // Exposed as `get_config_dir()` instead of `get_config_path()` for consistency with other exposed OS methods. |
503 | return ::OS::get_singleton()->get_config_path(); |
504 | } |
505 | |
506 | String OS::get_data_dir() const { |
507 | // Exposed as `get_data_dir()` instead of `get_data_path()` for consistency with other exposed OS methods. |
508 | return ::OS::get_singleton()->get_data_path(); |
509 | } |
510 | |
511 | String OS::get_cache_dir() const { |
512 | // Exposed as `get_cache_dir()` instead of `get_cache_path()` for consistency with other exposed OS methods. |
513 | return ::OS::get_singleton()->get_cache_path(); |
514 | } |
515 | |
516 | bool OS::is_debug_build() const { |
517 | #ifdef DEBUG_ENABLED |
518 | return true; |
519 | #else |
520 | return false; |
521 | #endif |
522 | } |
523 | |
524 | String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const { |
525 | return ::OS::get_singleton()->get_system_dir(::OS::SystemDir(p_dir), p_shared_storage); |
526 | } |
527 | |
528 | String OS::get_keycode_string(Key p_code) const { |
529 | return ::keycode_get_string(p_code); |
530 | } |
531 | |
532 | bool OS::is_keycode_unicode(char32_t p_unicode) const { |
533 | return ::keycode_has_unicode((Key)p_unicode); |
534 | } |
535 | |
536 | Key OS::find_keycode_from_string(const String &p_code) const { |
537 | return find_keycode(p_code); |
538 | } |
539 | |
540 | bool OS::request_permission(const String &p_name) { |
541 | return ::OS::get_singleton()->request_permission(p_name); |
542 | } |
543 | |
544 | bool OS::request_permissions() { |
545 | return ::OS::get_singleton()->request_permissions(); |
546 | } |
547 | |
548 | Vector<String> OS::get_granted_permissions() const { |
549 | return ::OS::get_singleton()->get_granted_permissions(); |
550 | } |
551 | |
552 | void OS::revoke_granted_permissions() { |
553 | ::OS::get_singleton()->revoke_granted_permissions(); |
554 | } |
555 | |
556 | String OS::get_unique_id() const { |
557 | return ::OS::get_singleton()->get_unique_id(); |
558 | } |
559 | |
560 | OS *OS::singleton = nullptr; |
561 | |
562 | void OS::_bind_methods() { |
563 | ClassDB::bind_method(D_METHOD("get_connected_midi_inputs" ), &OS::get_connected_midi_inputs); |
564 | ClassDB::bind_method(D_METHOD("open_midi_inputs" ), &OS::open_midi_inputs); |
565 | ClassDB::bind_method(D_METHOD("close_midi_inputs" ), &OS::close_midi_inputs); |
566 | |
567 | ClassDB::bind_method(D_METHOD("alert" , "text" , "title" ), &OS::alert, DEFVAL("Alert!" )); |
568 | ClassDB::bind_method(D_METHOD("crash" , "message" ), &OS::crash); |
569 | |
570 | ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode" , "enable" ), &OS::set_low_processor_usage_mode); |
571 | ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode" ), &OS::is_in_low_processor_usage_mode); |
572 | |
573 | ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode_sleep_usec" , "usec" ), &OS::set_low_processor_usage_mode_sleep_usec); |
574 | ClassDB::bind_method(D_METHOD("get_low_processor_usage_mode_sleep_usec" ), &OS::get_low_processor_usage_mode_sleep_usec); |
575 | |
576 | ClassDB::bind_method(D_METHOD("set_delta_smoothing" , "delta_smoothing_enabled" ), &OS::set_delta_smoothing); |
577 | ClassDB::bind_method(D_METHOD("is_delta_smoothing_enabled" ), &OS::is_delta_smoothing_enabled); |
578 | |
579 | ClassDB::bind_method(D_METHOD("get_processor_count" ), &OS::get_processor_count); |
580 | ClassDB::bind_method(D_METHOD("get_processor_name" ), &OS::get_processor_name); |
581 | |
582 | ClassDB::bind_method(D_METHOD("get_system_fonts" ), &OS::get_system_fonts); |
583 | ClassDB::bind_method(D_METHOD("get_system_font_path" , "font_name" , "weight" , "stretch" , "italic" ), &OS::get_system_font_path, DEFVAL(400), DEFVAL(100), DEFVAL(false)); |
584 | ClassDB::bind_method(D_METHOD("get_system_font_path_for_text" , "font_name" , "text" , "locale" , "script" , "weight" , "stretch" , "italic" ), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false)); |
585 | ClassDB::bind_method(D_METHOD("get_executable_path" ), &OS::get_executable_path); |
586 | ClassDB::bind_method(D_METHOD("read_string_from_stdin" ), &OS::read_string_from_stdin); |
587 | ClassDB::bind_method(D_METHOD("execute" , "path" , "arguments" , "output" , "read_stderr" , "open_console" ), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false)); |
588 | ClassDB::bind_method(D_METHOD("create_process" , "path" , "arguments" , "open_console" ), &OS::create_process, DEFVAL(false)); |
589 | ClassDB::bind_method(D_METHOD("create_instance" , "arguments" ), &OS::create_instance); |
590 | ClassDB::bind_method(D_METHOD("kill" , "pid" ), &OS::kill); |
591 | ClassDB::bind_method(D_METHOD("shell_open" , "uri" ), &OS::shell_open); |
592 | ClassDB::bind_method(D_METHOD("shell_show_in_file_manager" , "file_or_dir_path" , "open_folder" ), &OS::shell_show_in_file_manager, DEFVAL(true)); |
593 | ClassDB::bind_method(D_METHOD("is_process_running" , "pid" ), &OS::is_process_running); |
594 | ClassDB::bind_method(D_METHOD("get_process_id" ), &OS::get_process_id); |
595 | |
596 | ClassDB::bind_method(D_METHOD("has_environment" , "variable" ), &OS::has_environment); |
597 | ClassDB::bind_method(D_METHOD("get_environment" , "variable" ), &OS::get_environment); |
598 | ClassDB::bind_method(D_METHOD("set_environment" , "variable" , "value" ), &OS::set_environment); |
599 | ClassDB::bind_method(D_METHOD("unset_environment" , "variable" ), &OS::unset_environment); |
600 | |
601 | ClassDB::bind_method(D_METHOD("get_name" ), &OS::get_name); |
602 | ClassDB::bind_method(D_METHOD("get_distribution_name" ), &OS::get_distribution_name); |
603 | ClassDB::bind_method(D_METHOD("get_version" ), &OS::get_version); |
604 | ClassDB::bind_method(D_METHOD("get_cmdline_args" ), &OS::get_cmdline_args); |
605 | ClassDB::bind_method(D_METHOD("get_cmdline_user_args" ), &OS::get_cmdline_user_args); |
606 | |
607 | ClassDB::bind_method(D_METHOD("get_video_adapter_driver_info" ), &OS::get_video_adapter_driver_info); |
608 | |
609 | ClassDB::bind_method(D_METHOD("set_restart_on_exit" , "restart" , "arguments" ), &OS::set_restart_on_exit, DEFVAL(Vector<String>())); |
610 | ClassDB::bind_method(D_METHOD("is_restart_on_exit_set" ), &OS::is_restart_on_exit_set); |
611 | ClassDB::bind_method(D_METHOD("get_restart_on_exit_arguments" ), &OS::get_restart_on_exit_arguments); |
612 | |
613 | ClassDB::bind_method(D_METHOD("delay_usec" , "usec" ), &OS::delay_usec); |
614 | ClassDB::bind_method(D_METHOD("delay_msec" , "msec" ), &OS::delay_msec); |
615 | ClassDB::bind_method(D_METHOD("get_locale" ), &OS::get_locale); |
616 | ClassDB::bind_method(D_METHOD("get_locale_language" ), &OS::get_locale_language); |
617 | ClassDB::bind_method(D_METHOD("get_model_name" ), &OS::get_model_name); |
618 | |
619 | ClassDB::bind_method(D_METHOD("is_userfs_persistent" ), &OS::is_userfs_persistent); |
620 | ClassDB::bind_method(D_METHOD("is_stdout_verbose" ), &OS::is_stdout_verbose); |
621 | |
622 | ClassDB::bind_method(D_METHOD("is_debug_build" ), &OS::is_debug_build); |
623 | |
624 | ClassDB::bind_method(D_METHOD("get_static_memory_usage" ), &OS::get_static_memory_usage); |
625 | ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage" ), &OS::get_static_memory_peak_usage); |
626 | ClassDB::bind_method(D_METHOD("get_memory_info" ), &OS::get_memory_info); |
627 | |
628 | ClassDB::bind_method(D_METHOD("move_to_trash" , "path" ), &OS::move_to_trash); |
629 | ClassDB::bind_method(D_METHOD("get_user_data_dir" ), &OS::get_user_data_dir); |
630 | ClassDB::bind_method(D_METHOD("get_system_dir" , "dir" , "shared_storage" ), &OS::get_system_dir, DEFVAL(true)); |
631 | ClassDB::bind_method(D_METHOD("get_config_dir" ), &OS::get_config_dir); |
632 | ClassDB::bind_method(D_METHOD("get_data_dir" ), &OS::get_data_dir); |
633 | ClassDB::bind_method(D_METHOD("get_cache_dir" ), &OS::get_cache_dir); |
634 | ClassDB::bind_method(D_METHOD("get_unique_id" ), &OS::get_unique_id); |
635 | |
636 | ClassDB::bind_method(D_METHOD("get_keycode_string" , "code" ), &OS::get_keycode_string); |
637 | ClassDB::bind_method(D_METHOD("is_keycode_unicode" , "code" ), &OS::is_keycode_unicode); |
638 | ClassDB::bind_method(D_METHOD("find_keycode_from_string" , "string" ), &OS::find_keycode_from_string); |
639 | |
640 | ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap" , "enabled" ), &OS::set_use_file_access_save_and_swap); |
641 | |
642 | ClassDB::bind_method(D_METHOD("set_thread_name" , "name" ), &OS::set_thread_name); |
643 | ClassDB::bind_method(D_METHOD("get_thread_caller_id" ), &OS::get_thread_caller_id); |
644 | ClassDB::bind_method(D_METHOD("get_main_thread_id" ), &OS::get_main_thread_id); |
645 | |
646 | ClassDB::bind_method(D_METHOD("has_feature" , "tag_name" ), &OS::has_feature); |
647 | ClassDB::bind_method(D_METHOD("is_sandboxed" ), &OS::is_sandboxed); |
648 | |
649 | ClassDB::bind_method(D_METHOD("request_permission" , "name" ), &OS::request_permission); |
650 | ClassDB::bind_method(D_METHOD("request_permissions" ), &OS::request_permissions); |
651 | ClassDB::bind_method(D_METHOD("get_granted_permissions" ), &OS::get_granted_permissions); |
652 | ClassDB::bind_method(D_METHOD("revoke_granted_permissions" ), &OS::revoke_granted_permissions); |
653 | |
654 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode" ), "set_low_processor_usage_mode" , "is_in_low_processor_usage_mode" ); |
655 | ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec" ), "set_low_processor_usage_mode_sleep_usec" , "get_low_processor_usage_mode_sleep_usec" ); |
656 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "delta_smoothing" ), "set_delta_smoothing" , "is_delta_smoothing_enabled" ); |
657 | |
658 | // Those default values need to be specified for the docs generator, |
659 | // to avoid using values from the documentation writer's own OS instance. |
660 | ADD_PROPERTY_DEFAULT("low_processor_usage_mode" , false); |
661 | ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec" , 6900); |
662 | |
663 | BIND_ENUM_CONSTANT(RENDERING_DRIVER_VULKAN); |
664 | BIND_ENUM_CONSTANT(RENDERING_DRIVER_OPENGL3); |
665 | |
666 | BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP); |
667 | BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM); |
668 | BIND_ENUM_CONSTANT(SYSTEM_DIR_DOCUMENTS); |
669 | BIND_ENUM_CONSTANT(SYSTEM_DIR_DOWNLOADS); |
670 | BIND_ENUM_CONSTANT(SYSTEM_DIR_MOVIES); |
671 | BIND_ENUM_CONSTANT(SYSTEM_DIR_MUSIC); |
672 | BIND_ENUM_CONSTANT(SYSTEM_DIR_PICTURES); |
673 | BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES); |
674 | } |
675 | |
676 | ////// Geometry2D ////// |
677 | |
678 | Geometry2D *Geometry2D::singleton = nullptr; |
679 | |
680 | Geometry2D *Geometry2D::get_singleton() { |
681 | return singleton; |
682 | } |
683 | |
684 | bool Geometry2D::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) { |
685 | return ::Geometry2D::is_point_in_circle(p_point, p_circle_pos, p_circle_radius); |
686 | } |
687 | |
688 | real_t Geometry2D::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) { |
689 | return ::Geometry2D::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius); |
690 | } |
691 | |
692 | Variant Geometry2D::segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) { |
693 | Vector2 result; |
694 | if (::Geometry2D::segment_intersects_segment(p_from_a, p_to_a, p_from_b, p_to_b, &result)) { |
695 | return result; |
696 | } else { |
697 | return Variant(); |
698 | } |
699 | } |
700 | |
701 | Variant Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) { |
702 | Vector2 result; |
703 | if (::Geometry2D::line_intersects_line(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) { |
704 | return result; |
705 | } else { |
706 | return Variant(); |
707 | } |
708 | } |
709 | |
710 | Vector<Vector2> Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) { |
711 | Vector2 r1, r2; |
712 | ::Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2); |
713 | Vector<Vector2> r = { r1, r2 }; |
714 | return r; |
715 | } |
716 | |
717 | Vector2 Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { |
718 | Vector2 s[2] = { p_a, p_b }; |
719 | return ::Geometry2D::get_closest_point_to_segment(p_point, s); |
720 | } |
721 | |
722 | Vector2 Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { |
723 | Vector2 s[2] = { p_a, p_b }; |
724 | return ::Geometry2D::get_closest_point_to_segment_uncapped(p_point, s); |
725 | } |
726 | |
727 | bool Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const { |
728 | return ::Geometry2D::is_point_in_triangle(s, a, b, c); |
729 | } |
730 | |
731 | bool Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) { |
732 | return ::Geometry2D::is_polygon_clockwise(p_polygon); |
733 | } |
734 | |
735 | bool Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) { |
736 | return ::Geometry2D::is_point_in_polygon(p_point, p_polygon); |
737 | } |
738 | |
739 | Vector<int> Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) { |
740 | return ::Geometry2D::triangulate_polygon(p_polygon); |
741 | } |
742 | |
743 | Vector<int> Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) { |
744 | return ::Geometry2D::triangulate_delaunay(p_points); |
745 | } |
746 | |
747 | Vector<Point2> Geometry2D::convex_hull(const Vector<Point2> &p_points) { |
748 | return ::Geometry2D::convex_hull(p_points); |
749 | } |
750 | |
751 | TypedArray<PackedVector2Array> Geometry2D::decompose_polygon_in_convex(const Vector<Vector2> &p_polygon) { |
752 | Vector<Vector<Point2>> decomp = ::Geometry2D::decompose_polygon_in_convex(p_polygon); |
753 | |
754 | TypedArray<PackedVector2Array> ret; |
755 | |
756 | for (int i = 0; i < decomp.size(); ++i) { |
757 | ret.push_back(decomp[i]); |
758 | } |
759 | return ret; |
760 | } |
761 | |
762 | TypedArray<PackedVector2Array> Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { |
763 | Vector<Vector<Point2>> polys = ::Geometry2D::merge_polygons(p_polygon_a, p_polygon_b); |
764 | |
765 | TypedArray<PackedVector2Array> ret; |
766 | |
767 | for (int i = 0; i < polys.size(); ++i) { |
768 | ret.push_back(polys[i]); |
769 | } |
770 | return ret; |
771 | } |
772 | |
773 | TypedArray<PackedVector2Array> Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { |
774 | Vector<Vector<Point2>> polys = ::Geometry2D::clip_polygons(p_polygon_a, p_polygon_b); |
775 | |
776 | TypedArray<PackedVector2Array> ret; |
777 | |
778 | for (int i = 0; i < polys.size(); ++i) { |
779 | ret.push_back(polys[i]); |
780 | } |
781 | return ret; |
782 | } |
783 | |
784 | TypedArray<PackedVector2Array> Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { |
785 | Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b); |
786 | |
787 | TypedArray<PackedVector2Array> ret; |
788 | |
789 | for (int i = 0; i < polys.size(); ++i) { |
790 | ret.push_back(polys[i]); |
791 | } |
792 | return ret; |
793 | } |
794 | |
795 | TypedArray<PackedVector2Array> Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { |
796 | Vector<Vector<Point2>> polys = ::Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b); |
797 | |
798 | TypedArray<PackedVector2Array> ret; |
799 | |
800 | for (int i = 0; i < polys.size(); ++i) { |
801 | ret.push_back(polys[i]); |
802 | } |
803 | return ret; |
804 | } |
805 | |
806 | TypedArray<PackedVector2Array> Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { |
807 | Vector<Vector<Point2>> polys = ::Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon); |
808 | |
809 | TypedArray<PackedVector2Array> ret; |
810 | |
811 | for (int i = 0; i < polys.size(); ++i) { |
812 | ret.push_back(polys[i]); |
813 | } |
814 | return ret; |
815 | } |
816 | |
817 | TypedArray<PackedVector2Array> Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { |
818 | Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon); |
819 | |
820 | TypedArray<PackedVector2Array> ret; |
821 | |
822 | for (int i = 0; i < polys.size(); ++i) { |
823 | ret.push_back(polys[i]); |
824 | } |
825 | return ret; |
826 | } |
827 | |
828 | TypedArray<PackedVector2Array> Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { |
829 | Vector<Vector<Point2>> polys = ::Geometry2D::offset_polygon(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type)); |
830 | |
831 | TypedArray<PackedVector2Array> ret; |
832 | |
833 | for (int i = 0; i < polys.size(); ++i) { |
834 | ret.push_back(polys[i]); |
835 | } |
836 | return ret; |
837 | } |
838 | |
839 | TypedArray<PackedVector2Array> Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { |
840 | Vector<Vector<Point2>> polys = ::Geometry2D::offset_polyline(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type), ::Geometry2D::PolyEndType(p_end_type)); |
841 | |
842 | TypedArray<PackedVector2Array> ret; |
843 | |
844 | for (int i = 0; i < polys.size(); ++i) { |
845 | ret.push_back(polys[i]); |
846 | } |
847 | return ret; |
848 | } |
849 | |
850 | Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) { |
851 | Dictionary ret; |
852 | |
853 | Vector<Size2i> rects; |
854 | for (int i = 0; i < p_rects.size(); i++) { |
855 | rects.push_back(p_rects[i]); |
856 | } |
857 | |
858 | Vector<Point2i> result; |
859 | Size2i size; |
860 | |
861 | ::Geometry2D::make_atlas(rects, result, size); |
862 | |
863 | Vector<Point2> r_result; |
864 | for (int i = 0; i < result.size(); i++) { |
865 | r_result.push_back(result[i]); |
866 | } |
867 | |
868 | ret["points" ] = r_result; |
869 | ret["size" ] = size; |
870 | |
871 | return ret; |
872 | } |
873 | |
874 | void Geometry2D::_bind_methods() { |
875 | ClassDB::bind_method(D_METHOD("is_point_in_circle" , "point" , "circle_position" , "circle_radius" ), &Geometry2D::is_point_in_circle); |
876 | ClassDB::bind_method(D_METHOD("segment_intersects_circle" , "segment_from" , "segment_to" , "circle_position" , "circle_radius" ), &Geometry2D::segment_intersects_circle); |
877 | ClassDB::bind_method(D_METHOD("segment_intersects_segment" , "from_a" , "to_a" , "from_b" , "to_b" ), &Geometry2D::segment_intersects_segment); |
878 | ClassDB::bind_method(D_METHOD("line_intersects_line" , "from_a" , "dir_a" , "from_b" , "dir_b" ), &Geometry2D::line_intersects_line); |
879 | |
880 | ClassDB::bind_method(D_METHOD("get_closest_points_between_segments" , "p1" , "q1" , "p2" , "q2" ), &Geometry2D::get_closest_points_between_segments); |
881 | |
882 | ClassDB::bind_method(D_METHOD("get_closest_point_to_segment" , "point" , "s1" , "s2" ), &Geometry2D::get_closest_point_to_segment); |
883 | |
884 | ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped" , "point" , "s1" , "s2" ), &Geometry2D::get_closest_point_to_segment_uncapped); |
885 | |
886 | ClassDB::bind_method(D_METHOD("point_is_inside_triangle" , "point" , "a" , "b" , "c" ), &Geometry2D::point_is_inside_triangle); |
887 | |
888 | ClassDB::bind_method(D_METHOD("is_polygon_clockwise" , "polygon" ), &Geometry2D::is_polygon_clockwise); |
889 | ClassDB::bind_method(D_METHOD("is_point_in_polygon" , "point" , "polygon" ), &Geometry2D::is_point_in_polygon); |
890 | ClassDB::bind_method(D_METHOD("triangulate_polygon" , "polygon" ), &Geometry2D::triangulate_polygon); |
891 | ClassDB::bind_method(D_METHOD("triangulate_delaunay" , "points" ), &Geometry2D::triangulate_delaunay); |
892 | ClassDB::bind_method(D_METHOD("convex_hull" , "points" ), &Geometry2D::convex_hull); |
893 | ClassDB::bind_method(D_METHOD("decompose_polygon_in_convex" , "polygon" ), &Geometry2D::decompose_polygon_in_convex); |
894 | |
895 | ClassDB::bind_method(D_METHOD("merge_polygons" , "polygon_a" , "polygon_b" ), &Geometry2D::merge_polygons); |
896 | ClassDB::bind_method(D_METHOD("clip_polygons" , "polygon_a" , "polygon_b" ), &Geometry2D::clip_polygons); |
897 | ClassDB::bind_method(D_METHOD("intersect_polygons" , "polygon_a" , "polygon_b" ), &Geometry2D::intersect_polygons); |
898 | ClassDB::bind_method(D_METHOD("exclude_polygons" , "polygon_a" , "polygon_b" ), &Geometry2D::exclude_polygons); |
899 | |
900 | ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon" , "polyline" , "polygon" ), &Geometry2D::clip_polyline_with_polygon); |
901 | ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon" , "polyline" , "polygon" ), &Geometry2D::intersect_polyline_with_polygon); |
902 | |
903 | ClassDB::bind_method(D_METHOD("offset_polygon" , "polygon" , "delta" , "join_type" ), &Geometry2D::offset_polygon, DEFVAL(JOIN_SQUARE)); |
904 | ClassDB::bind_method(D_METHOD("offset_polyline" , "polyline" , "delta" , "join_type" , "end_type" ), &Geometry2D::offset_polyline, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE)); |
905 | |
906 | ClassDB::bind_method(D_METHOD("make_atlas" , "sizes" ), &Geometry2D::make_atlas); |
907 | |
908 | BIND_ENUM_CONSTANT(OPERATION_UNION); |
909 | BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE); |
910 | BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); |
911 | BIND_ENUM_CONSTANT(OPERATION_XOR); |
912 | |
913 | BIND_ENUM_CONSTANT(JOIN_SQUARE); |
914 | BIND_ENUM_CONSTANT(JOIN_ROUND); |
915 | BIND_ENUM_CONSTANT(JOIN_MITER); |
916 | |
917 | BIND_ENUM_CONSTANT(END_POLYGON); |
918 | BIND_ENUM_CONSTANT(END_JOINED); |
919 | BIND_ENUM_CONSTANT(END_BUTT); |
920 | BIND_ENUM_CONSTANT(END_SQUARE); |
921 | BIND_ENUM_CONSTANT(END_ROUND); |
922 | } |
923 | |
924 | ////// Geometry3D ////// |
925 | |
926 | Geometry3D *Geometry3D::singleton = nullptr; |
927 | |
928 | Geometry3D *Geometry3D::get_singleton() { |
929 | return singleton; |
930 | } |
931 | |
932 | Vector<Vector3> Geometry3D::compute_convex_mesh_points(const TypedArray<Plane> &p_planes) { |
933 | Vector<Plane> planes_vec; |
934 | int size = p_planes.size(); |
935 | planes_vec.resize(size); |
936 | for (int i = 0; i < size; ++i) { |
937 | planes_vec.set(i, p_planes[i]); |
938 | } |
939 | Variant ret = ::Geometry3D::compute_convex_mesh_points(planes_vec.ptr(), size); |
940 | return ret; |
941 | } |
942 | |
943 | TypedArray<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) { |
944 | Variant ret = ::Geometry3D::build_box_planes(p_extents); |
945 | return ret; |
946 | } |
947 | |
948 | TypedArray<Plane> Geometry3D::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { |
949 | Variant ret = ::Geometry3D::build_cylinder_planes(p_radius, p_height, p_sides, p_axis); |
950 | return ret; |
951 | } |
952 | |
953 | TypedArray<Plane> Geometry3D::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { |
954 | Variant ret = ::Geometry3D::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis); |
955 | return ret; |
956 | } |
957 | |
958 | Vector<Vector3> Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) { |
959 | Vector3 r1, r2; |
960 | ::Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2); |
961 | Vector<Vector3> r = { r1, r2 }; |
962 | return r; |
963 | } |
964 | |
965 | Vector3 Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { |
966 | Vector3 s[2] = { p_a, p_b }; |
967 | return ::Geometry3D::get_closest_point_to_segment(p_point, s); |
968 | } |
969 | |
970 | Vector3 Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { |
971 | Vector3 s[2] = { p_a, p_b }; |
972 | return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, s); |
973 | } |
974 | |
975 | Vector3 Geometry3D::get_triangle_barycentric_coords(const Vector3 &p_point, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { |
976 | Vector3 res = ::Geometry3D::triangle_get_barycentric_coords(p_v0, p_v1, p_v2, p_point); |
977 | return res; |
978 | } |
979 | |
980 | Variant Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { |
981 | Vector3 res; |
982 | if (::Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) { |
983 | return res; |
984 | } else { |
985 | return Variant(); |
986 | } |
987 | } |
988 | |
989 | Variant Geometry3D::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { |
990 | Vector3 res; |
991 | if (::Geometry3D::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) { |
992 | return res; |
993 | } else { |
994 | return Variant(); |
995 | } |
996 | } |
997 | |
998 | Vector<Vector3> Geometry3D::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) { |
999 | Vector<Vector3> r; |
1000 | Vector3 res, norm; |
1001 | if (!::Geometry3D::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) { |
1002 | return r; |
1003 | } |
1004 | |
1005 | r.resize(2); |
1006 | r.set(0, res); |
1007 | r.set(1, norm); |
1008 | return r; |
1009 | } |
1010 | |
1011 | Vector<Vector3> Geometry3D::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) { |
1012 | Vector<Vector3> r; |
1013 | Vector3 res, norm; |
1014 | if (!::Geometry3D::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) { |
1015 | return r; |
1016 | } |
1017 | |
1018 | r.resize(2); |
1019 | r.set(0, res); |
1020 | r.set(1, norm); |
1021 | return r; |
1022 | } |
1023 | |
1024 | Vector<Vector3> Geometry3D::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const TypedArray<Plane> &p_planes) { |
1025 | Vector<Vector3> r; |
1026 | Vector3 res, norm; |
1027 | Vector<Plane> planes = Variant(p_planes); |
1028 | if (!::Geometry3D::segment_intersects_convex(p_from, p_to, planes.ptr(), planes.size(), &res, &norm)) { |
1029 | return r; |
1030 | } |
1031 | |
1032 | r.resize(2); |
1033 | r.set(0, res); |
1034 | r.set(1, norm); |
1035 | return r; |
1036 | } |
1037 | |
1038 | Vector<Vector3> Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) { |
1039 | return ::Geometry3D::clip_polygon(p_points, p_plane); |
1040 | } |
1041 | |
1042 | void Geometry3D::_bind_methods() { |
1043 | ClassDB::bind_method(D_METHOD("compute_convex_mesh_points" , "planes" ), &Geometry3D::compute_convex_mesh_points); |
1044 | ClassDB::bind_method(D_METHOD("build_box_planes" , "extents" ), &Geometry3D::build_box_planes); |
1045 | ClassDB::bind_method(D_METHOD("build_cylinder_planes" , "radius" , "height" , "sides" , "axis" ), &Geometry3D::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z)); |
1046 | ClassDB::bind_method(D_METHOD("build_capsule_planes" , "radius" , "height" , "sides" , "lats" , "axis" ), &Geometry3D::build_capsule_planes, DEFVAL(Vector3::AXIS_Z)); |
1047 | |
1048 | ClassDB::bind_method(D_METHOD("get_closest_points_between_segments" , "p1" , "p2" , "q1" , "q2" ), &Geometry3D::get_closest_points_between_segments); |
1049 | |
1050 | ClassDB::bind_method(D_METHOD("get_closest_point_to_segment" , "point" , "s1" , "s2" ), &Geometry3D::get_closest_point_to_segment); |
1051 | |
1052 | ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped" , "point" , "s1" , "s2" ), &Geometry3D::get_closest_point_to_segment_uncapped); |
1053 | |
1054 | ClassDB::bind_method(D_METHOD("get_triangle_barycentric_coords" , "point" , "a" , "b" , "c" ), &Geometry3D::get_triangle_barycentric_coords); |
1055 | |
1056 | ClassDB::bind_method(D_METHOD("ray_intersects_triangle" , "from" , "dir" , "a" , "b" , "c" ), &Geometry3D::ray_intersects_triangle); |
1057 | ClassDB::bind_method(D_METHOD("segment_intersects_triangle" , "from" , "to" , "a" , "b" , "c" ), &Geometry3D::segment_intersects_triangle); |
1058 | ClassDB::bind_method(D_METHOD("segment_intersects_sphere" , "from" , "to" , "sphere_position" , "sphere_radius" ), &Geometry3D::segment_intersects_sphere); |
1059 | ClassDB::bind_method(D_METHOD("segment_intersects_cylinder" , "from" , "to" , "height" , "radius" ), &Geometry3D::segment_intersects_cylinder); |
1060 | ClassDB::bind_method(D_METHOD("segment_intersects_convex" , "from" , "to" , "planes" ), &Geometry3D::segment_intersects_convex); |
1061 | |
1062 | ClassDB::bind_method(D_METHOD("clip_polygon" , "points" , "plane" ), &Geometry3D::clip_polygon); |
1063 | } |
1064 | |
1065 | ////// Marshalls ////// |
1066 | |
1067 | Marshalls *Marshalls::singleton = nullptr; |
1068 | |
1069 | Marshalls *Marshalls::get_singleton() { |
1070 | return singleton; |
1071 | } |
1072 | |
1073 | String Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) { |
1074 | int len; |
1075 | Error err = encode_variant(p_var, nullptr, len, p_full_objects); |
1076 | ERR_FAIL_COND_V_MSG(err != OK, "" , "Error when trying to encode Variant." ); |
1077 | |
1078 | Vector<uint8_t> buff; |
1079 | buff.resize(len); |
1080 | uint8_t *w = buff.ptrw(); |
1081 | |
1082 | err = encode_variant(p_var, &w[0], len, p_full_objects); |
1083 | ERR_FAIL_COND_V_MSG(err != OK, "" , "Error when trying to encode Variant." ); |
1084 | |
1085 | String ret = CryptoCore::b64_encode_str(&w[0], len); |
1086 | ERR_FAIL_COND_V(ret.is_empty(), ret); |
1087 | |
1088 | return ret; |
1089 | } |
1090 | |
1091 | Variant Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) { |
1092 | int strlen = p_str.length(); |
1093 | CharString cstr = p_str.ascii(); |
1094 | |
1095 | Vector<uint8_t> buf; |
1096 | buf.resize(strlen / 4 * 3 + 1); |
1097 | uint8_t *w = buf.ptrw(); |
1098 | |
1099 | size_t len = 0; |
1100 | ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, Variant()); |
1101 | |
1102 | Variant v; |
1103 | Error err = decode_variant(v, &w[0], len, nullptr, p_allow_objects); |
1104 | ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant." ); |
1105 | |
1106 | return v; |
1107 | } |
1108 | |
1109 | String Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) { |
1110 | String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size()); |
1111 | ERR_FAIL_COND_V(ret.is_empty(), ret); |
1112 | return ret; |
1113 | } |
1114 | |
1115 | Vector<uint8_t> Marshalls::base64_to_raw(const String &p_str) { |
1116 | int strlen = p_str.length(); |
1117 | CharString cstr = p_str.ascii(); |
1118 | |
1119 | size_t arr_len = 0; |
1120 | Vector<uint8_t> buf; |
1121 | { |
1122 | buf.resize(strlen / 4 * 3 + 1); |
1123 | uint8_t *w = buf.ptrw(); |
1124 | |
1125 | ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &arr_len, (unsigned char *)cstr.get_data(), strlen) != OK, Vector<uint8_t>()); |
1126 | } |
1127 | buf.resize(arr_len); |
1128 | |
1129 | return buf; |
1130 | } |
1131 | |
1132 | String Marshalls::utf8_to_base64(const String &p_str) { |
1133 | CharString cstr = p_str.utf8(); |
1134 | String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length()); |
1135 | ERR_FAIL_COND_V(ret.is_empty(), ret); |
1136 | return ret; |
1137 | } |
1138 | |
1139 | String Marshalls::base64_to_utf8(const String &p_str) { |
1140 | int strlen = p_str.length(); |
1141 | CharString cstr = p_str.ascii(); |
1142 | |
1143 | Vector<uint8_t> buf; |
1144 | buf.resize(strlen / 4 * 3 + 1 + 1); |
1145 | uint8_t *w = buf.ptrw(); |
1146 | |
1147 | size_t len = 0; |
1148 | ERR_FAIL_COND_V(CryptoCore::b64_decode(&w[0], buf.size(), &len, (unsigned char *)cstr.get_data(), strlen) != OK, String()); |
1149 | |
1150 | w[len] = 0; |
1151 | String ret = String::utf8((char *)&w[0]); |
1152 | |
1153 | return ret; |
1154 | } |
1155 | |
1156 | void Marshalls::_bind_methods() { |
1157 | ClassDB::bind_method(D_METHOD("variant_to_base64" , "variant" , "full_objects" ), &Marshalls::variant_to_base64, DEFVAL(false)); |
1158 | ClassDB::bind_method(D_METHOD("base64_to_variant" , "base64_str" , "allow_objects" ), &Marshalls::base64_to_variant, DEFVAL(false)); |
1159 | |
1160 | ClassDB::bind_method(D_METHOD("raw_to_base64" , "array" ), &Marshalls::raw_to_base64); |
1161 | ClassDB::bind_method(D_METHOD("base64_to_raw" , "base64_str" ), &Marshalls::base64_to_raw); |
1162 | |
1163 | ClassDB::bind_method(D_METHOD("utf8_to_base64" , "utf8_str" ), &Marshalls::utf8_to_base64); |
1164 | ClassDB::bind_method(D_METHOD("base64_to_utf8" , "base64_str" ), &Marshalls::base64_to_utf8); |
1165 | } |
1166 | |
1167 | ////// Semaphore ////// |
1168 | |
1169 | void Semaphore::wait() { |
1170 | semaphore.wait(); |
1171 | } |
1172 | |
1173 | bool Semaphore::try_wait() { |
1174 | return semaphore.try_wait(); |
1175 | } |
1176 | |
1177 | void Semaphore::post() { |
1178 | semaphore.post(); |
1179 | } |
1180 | |
1181 | void Semaphore::_bind_methods() { |
1182 | ClassDB::bind_method(D_METHOD("wait" ), &Semaphore::wait); |
1183 | ClassDB::bind_method(D_METHOD("try_wait" ), &Semaphore::try_wait); |
1184 | ClassDB::bind_method(D_METHOD("post" ), &Semaphore::post); |
1185 | } |
1186 | |
1187 | ////// Mutex ////// |
1188 | |
1189 | void Mutex::lock() { |
1190 | mutex.lock(); |
1191 | } |
1192 | |
1193 | bool Mutex::try_lock() { |
1194 | return mutex.try_lock(); |
1195 | } |
1196 | |
1197 | void Mutex::unlock() { |
1198 | mutex.unlock(); |
1199 | } |
1200 | |
1201 | void Mutex::_bind_methods() { |
1202 | ClassDB::bind_method(D_METHOD("lock" ), &Mutex::lock); |
1203 | ClassDB::bind_method(D_METHOD("try_lock" ), &Mutex::try_lock); |
1204 | ClassDB::bind_method(D_METHOD("unlock" ), &Mutex::unlock); |
1205 | } |
1206 | |
1207 | ////// Thread ////// |
1208 | |
1209 | void Thread::_start_func(void *ud) { |
1210 | Ref<Thread> *tud = (Ref<Thread> *)ud; |
1211 | Ref<Thread> t = *tud; |
1212 | memdelete(tud); |
1213 | |
1214 | Object *target_instance = t->target_callable.get_object(); |
1215 | if (!target_instance) { |
1216 | t->running.clear(); |
1217 | ERR_FAIL_MSG(vformat("Could not call function '%s' on previously freed instance to start thread %s." , t->target_callable.get_method(), t->get_id())); |
1218 | } |
1219 | |
1220 | // Finding out a suitable name for the thread can involve querying a node, if the target is one. |
1221 | // We know this is safe (unless the user is causing life cycle race conditions, which would be a bug on their part). |
1222 | set_current_thread_safe_for_nodes(true); |
1223 | String func_name = t->target_callable.is_custom() ? t->target_callable.get_custom()->get_as_text() : String(t->target_callable.get_method()); |
1224 | set_current_thread_safe_for_nodes(false); |
1225 | ::Thread::set_name(func_name); |
1226 | |
1227 | // To avoid a circular reference between the thread and the script which can possibly contain a reference |
1228 | // to the thread, we will do the call (keeping a reference up to that point) and then break chains with it. |
1229 | // When the call returns, we will reference the thread again if possible. |
1230 | ObjectID th_instance_id = t->get_instance_id(); |
1231 | Callable target_callable = t->target_callable; |
1232 | t = Ref<Thread>(); |
1233 | |
1234 | Callable::CallError ce; |
1235 | Variant ret; |
1236 | target_callable.callp(nullptr, 0, ret, ce); |
1237 | // If script properly kept a reference to the thread, we should be able to re-reference it now |
1238 | // (well, or if the call failed, since we had to break chains anyway because the outcome isn't known upfront). |
1239 | t = Ref<Thread>(ObjectDB::get_instance(th_instance_id)); |
1240 | if (t.is_valid()) { |
1241 | t->ret = ret; |
1242 | t->running.clear(); |
1243 | } else { |
1244 | // We could print a warning here, but the Thread object will be eventually destroyed |
1245 | // noticing wait_to_finish() hasn't been called on it, and it will print a warning itself. |
1246 | } |
1247 | |
1248 | if (ce.error != Callable::CallError::CALL_OK) { |
1249 | ERR_FAIL_MSG("Could not call function '" + func_name + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + "." ); |
1250 | } |
1251 | } |
1252 | |
1253 | Error Thread::start(const Callable &p_callable, Priority p_priority) { |
1254 | ERR_FAIL_COND_V_MSG(is_started(), ERR_ALREADY_IN_USE, "Thread already started." ); |
1255 | ERR_FAIL_COND_V(!p_callable.is_valid(), ERR_INVALID_PARAMETER); |
1256 | ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER); |
1257 | |
1258 | ret = Variant(); |
1259 | target_callable = p_callable; |
1260 | running.set(); |
1261 | |
1262 | Ref<Thread> *ud = memnew(Ref<Thread>(this)); |
1263 | |
1264 | ::Thread::Settings s; |
1265 | s.priority = (::Thread::Priority)p_priority; |
1266 | thread.start(_start_func, ud, s); |
1267 | |
1268 | return OK; |
1269 | } |
1270 | |
1271 | String Thread::get_id() const { |
1272 | return itos(thread.get_id()); |
1273 | } |
1274 | |
1275 | bool Thread::is_started() const { |
1276 | return thread.is_started(); |
1277 | } |
1278 | |
1279 | bool Thread::is_alive() const { |
1280 | return running.is_set(); |
1281 | } |
1282 | |
1283 | Variant Thread::wait_to_finish() { |
1284 | ERR_FAIL_COND_V_MSG(!is_started(), Variant(), "Thread must have been started to wait for its completion." ); |
1285 | thread.wait_to_finish(); |
1286 | Variant r = ret; |
1287 | target_callable = Callable(); |
1288 | |
1289 | return r; |
1290 | } |
1291 | |
1292 | void Thread::set_thread_safety_checks_enabled(bool p_enabled) { |
1293 | ERR_FAIL_COND_MSG(::Thread::is_main_thread(), "This call is forbidden on the main thread." ); |
1294 | set_current_thread_safe_for_nodes(!p_enabled); |
1295 | } |
1296 | |
1297 | void Thread::_bind_methods() { |
1298 | ClassDB::bind_method(D_METHOD("start" , "callable" , "priority" ), &Thread::start, DEFVAL(PRIORITY_NORMAL)); |
1299 | ClassDB::bind_method(D_METHOD("get_id" ), &Thread::get_id); |
1300 | ClassDB::bind_method(D_METHOD("is_started" ), &Thread::is_started); |
1301 | ClassDB::bind_method(D_METHOD("is_alive" ), &Thread::is_alive); |
1302 | ClassDB::bind_method(D_METHOD("wait_to_finish" ), &Thread::wait_to_finish); |
1303 | |
1304 | ClassDB::bind_static_method("Thread" , D_METHOD("set_thread_safety_checks_enabled" , "enabled" ), &Thread::set_thread_safety_checks_enabled); |
1305 | |
1306 | BIND_ENUM_CONSTANT(PRIORITY_LOW); |
1307 | BIND_ENUM_CONSTANT(PRIORITY_NORMAL); |
1308 | BIND_ENUM_CONSTANT(PRIORITY_HIGH); |
1309 | } |
1310 | |
1311 | namespace special { |
1312 | |
1313 | ////// ClassDB ////// |
1314 | |
1315 | PackedStringArray ClassDB::get_class_list() const { |
1316 | List<StringName> classes; |
1317 | ::ClassDB::get_class_list(&classes); |
1318 | |
1319 | PackedStringArray ret; |
1320 | ret.resize(classes.size()); |
1321 | int idx = 0; |
1322 | for (const StringName &E : classes) { |
1323 | ret.set(idx++, E); |
1324 | } |
1325 | |
1326 | return ret; |
1327 | } |
1328 | |
1329 | PackedStringArray ClassDB::get_inheriters_from_class(const StringName &p_class) const { |
1330 | List<StringName> classes; |
1331 | ::ClassDB::get_inheriters_from_class(p_class, &classes); |
1332 | |
1333 | PackedStringArray ret; |
1334 | ret.resize(classes.size()); |
1335 | int idx = 0; |
1336 | for (const StringName &E : classes) { |
1337 | ret.set(idx++, E); |
1338 | } |
1339 | |
1340 | return ret; |
1341 | } |
1342 | |
1343 | StringName ClassDB::get_parent_class(const StringName &p_class) const { |
1344 | return ::ClassDB::get_parent_class(p_class); |
1345 | } |
1346 | |
1347 | bool ClassDB::class_exists(const StringName &p_class) const { |
1348 | return ::ClassDB::class_exists(p_class); |
1349 | } |
1350 | |
1351 | bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) const { |
1352 | return ::ClassDB::is_parent_class(p_class, p_inherits); |
1353 | } |
1354 | |
1355 | bool ClassDB::can_instantiate(const StringName &p_class) const { |
1356 | return ::ClassDB::can_instantiate(p_class); |
1357 | } |
1358 | |
1359 | Variant ClassDB::instantiate(const StringName &p_class) const { |
1360 | Object *obj = ::ClassDB::instantiate(p_class); |
1361 | if (!obj) { |
1362 | return Variant(); |
1363 | } |
1364 | |
1365 | RefCounted *r = Object::cast_to<RefCounted>(obj); |
1366 | if (r) { |
1367 | return Ref<RefCounted>(r); |
1368 | } else { |
1369 | return obj; |
1370 | } |
1371 | } |
1372 | |
1373 | bool ClassDB::class_has_signal(StringName p_class, StringName p_signal) const { |
1374 | return ::ClassDB::has_signal(p_class, p_signal); |
1375 | } |
1376 | |
1377 | Dictionary ClassDB::class_get_signal(StringName p_class, StringName p_signal) const { |
1378 | MethodInfo signal; |
1379 | if (::ClassDB::get_signal(p_class, p_signal, &signal)) { |
1380 | return signal.operator Dictionary(); |
1381 | } else { |
1382 | return Dictionary(); |
1383 | } |
1384 | } |
1385 | |
1386 | TypedArray<Dictionary> ClassDB::class_get_signal_list(StringName p_class, bool p_no_inheritance) const { |
1387 | List<MethodInfo> signals; |
1388 | ::ClassDB::get_signal_list(p_class, &signals, p_no_inheritance); |
1389 | TypedArray<Dictionary> ret; |
1390 | |
1391 | for (const MethodInfo &E : signals) { |
1392 | ret.push_back(E.operator Dictionary()); |
1393 | } |
1394 | |
1395 | return ret; |
1396 | } |
1397 | |
1398 | TypedArray<Dictionary> ClassDB::class_get_property_list(StringName p_class, bool p_no_inheritance) const { |
1399 | List<PropertyInfo> plist; |
1400 | ::ClassDB::get_property_list(p_class, &plist, p_no_inheritance); |
1401 | TypedArray<Dictionary> ret; |
1402 | for (const PropertyInfo &E : plist) { |
1403 | ret.push_back(E.operator Dictionary()); |
1404 | } |
1405 | |
1406 | return ret; |
1407 | } |
1408 | |
1409 | Variant ClassDB::class_get_property(Object *p_object, const StringName &p_property) const { |
1410 | Variant ret; |
1411 | ::ClassDB::get_property(p_object, p_property, ret); |
1412 | return ret; |
1413 | } |
1414 | |
1415 | Error ClassDB::class_set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const { |
1416 | Variant ret; |
1417 | bool valid; |
1418 | if (!::ClassDB::set_property(p_object, p_property, p_value, &valid)) { |
1419 | return ERR_UNAVAILABLE; |
1420 | } else if (!valid) { |
1421 | return ERR_INVALID_DATA; |
1422 | } |
1423 | return OK; |
1424 | } |
1425 | |
1426 | bool ClassDB::class_has_method(StringName p_class, StringName p_method, bool p_no_inheritance) const { |
1427 | return ::ClassDB::has_method(p_class, p_method, p_no_inheritance); |
1428 | } |
1429 | |
1430 | TypedArray<Dictionary> ClassDB::class_get_method_list(StringName p_class, bool p_no_inheritance) const { |
1431 | List<MethodInfo> methods; |
1432 | ::ClassDB::get_method_list(p_class, &methods, p_no_inheritance); |
1433 | TypedArray<Dictionary> ret; |
1434 | |
1435 | for (const MethodInfo &E : methods) { |
1436 | #ifdef DEBUG_METHODS_ENABLED |
1437 | ret.push_back(E.operator Dictionary()); |
1438 | #else |
1439 | Dictionary dict; |
1440 | dict["name" ] = E.name; |
1441 | ret.push_back(dict); |
1442 | #endif |
1443 | } |
1444 | |
1445 | return ret; |
1446 | } |
1447 | |
1448 | PackedStringArray ClassDB::class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const { |
1449 | List<String> constants; |
1450 | ::ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance); |
1451 | |
1452 | PackedStringArray ret; |
1453 | ret.resize(constants.size()); |
1454 | int idx = 0; |
1455 | for (const String &E : constants) { |
1456 | ret.set(idx++, E); |
1457 | } |
1458 | |
1459 | return ret; |
1460 | } |
1461 | |
1462 | bool ClassDB::class_has_integer_constant(const StringName &p_class, const StringName &p_name) const { |
1463 | bool success; |
1464 | ::ClassDB::get_integer_constant(p_class, p_name, &success); |
1465 | return success; |
1466 | } |
1467 | |
1468 | int64_t ClassDB::class_get_integer_constant(const StringName &p_class, const StringName &p_name) const { |
1469 | bool found; |
1470 | int64_t c = ::ClassDB::get_integer_constant(p_class, p_name, &found); |
1471 | ERR_FAIL_COND_V(!found, 0); |
1472 | return c; |
1473 | } |
1474 | |
1475 | bool ClassDB::class_has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) const { |
1476 | return ::ClassDB::has_enum(p_class, p_name, p_no_inheritance); |
1477 | } |
1478 | |
1479 | PackedStringArray ClassDB::class_get_enum_list(const StringName &p_class, bool p_no_inheritance) const { |
1480 | List<StringName> enums; |
1481 | ::ClassDB::get_enum_list(p_class, &enums, p_no_inheritance); |
1482 | |
1483 | PackedStringArray ret; |
1484 | ret.resize(enums.size()); |
1485 | int idx = 0; |
1486 | for (const StringName &E : enums) { |
1487 | ret.set(idx++, E); |
1488 | } |
1489 | |
1490 | return ret; |
1491 | } |
1492 | |
1493 | PackedStringArray ClassDB::class_get_enum_constants(const StringName &p_class, const StringName &p_enum, bool p_no_inheritance) const { |
1494 | List<StringName> constants; |
1495 | ::ClassDB::get_enum_constants(p_class, p_enum, &constants, p_no_inheritance); |
1496 | |
1497 | PackedStringArray ret; |
1498 | ret.resize(constants.size()); |
1499 | int idx = 0; |
1500 | for (const StringName &E : constants) { |
1501 | ret.set(idx++, E); |
1502 | } |
1503 | |
1504 | return ret; |
1505 | } |
1506 | |
1507 | StringName ClassDB::class_get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) const { |
1508 | return ::ClassDB::get_integer_constant_enum(p_class, p_name, p_no_inheritance); |
1509 | } |
1510 | |
1511 | bool ClassDB::is_class_enabled(StringName p_class) const { |
1512 | return ::ClassDB::is_class_enabled(p_class); |
1513 | } |
1514 | |
1515 | void ClassDB::_bind_methods() { |
1516 | ::ClassDB::bind_method(D_METHOD("get_class_list" ), &ClassDB::get_class_list); |
1517 | ::ClassDB::bind_method(D_METHOD("get_inheriters_from_class" , "class" ), &ClassDB::get_inheriters_from_class); |
1518 | ::ClassDB::bind_method(D_METHOD("get_parent_class" , "class" ), &ClassDB::get_parent_class); |
1519 | ::ClassDB::bind_method(D_METHOD("class_exists" , "class" ), &ClassDB::class_exists); |
1520 | ::ClassDB::bind_method(D_METHOD("is_parent_class" , "class" , "inherits" ), &ClassDB::is_parent_class); |
1521 | ::ClassDB::bind_method(D_METHOD("can_instantiate" , "class" ), &ClassDB::can_instantiate); |
1522 | ::ClassDB::bind_method(D_METHOD("instantiate" , "class" ), &ClassDB::instantiate); |
1523 | |
1524 | ::ClassDB::bind_method(D_METHOD("class_has_signal" , "class" , "signal" ), &ClassDB::class_has_signal); |
1525 | ::ClassDB::bind_method(D_METHOD("class_get_signal" , "class" , "signal" ), &ClassDB::class_get_signal); |
1526 | ::ClassDB::bind_method(D_METHOD("class_get_signal_list" , "class" , "no_inheritance" ), &ClassDB::class_get_signal_list, DEFVAL(false)); |
1527 | |
1528 | ::ClassDB::bind_method(D_METHOD("class_get_property_list" , "class" , "no_inheritance" ), &ClassDB::class_get_property_list, DEFVAL(false)); |
1529 | ::ClassDB::bind_method(D_METHOD("class_get_property" , "object" , "property" ), &ClassDB::class_get_property); |
1530 | ::ClassDB::bind_method(D_METHOD("class_set_property" , "object" , "property" , "value" ), &ClassDB::class_set_property); |
1531 | |
1532 | ::ClassDB::bind_method(D_METHOD("class_has_method" , "class" , "method" , "no_inheritance" ), &ClassDB::class_has_method, DEFVAL(false)); |
1533 | |
1534 | ::ClassDB::bind_method(D_METHOD("class_get_method_list" , "class" , "no_inheritance" ), &ClassDB::class_get_method_list, DEFVAL(false)); |
1535 | |
1536 | ::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list" , "class" , "no_inheritance" ), &ClassDB::class_get_integer_constant_list, DEFVAL(false)); |
1537 | |
1538 | ::ClassDB::bind_method(D_METHOD("class_has_integer_constant" , "class" , "name" ), &ClassDB::class_has_integer_constant); |
1539 | ::ClassDB::bind_method(D_METHOD("class_get_integer_constant" , "class" , "name" ), &ClassDB::class_get_integer_constant); |
1540 | |
1541 | ::ClassDB::bind_method(D_METHOD("class_has_enum" , "class" , "name" , "no_inheritance" ), &ClassDB::class_has_enum, DEFVAL(false)); |
1542 | ::ClassDB::bind_method(D_METHOD("class_get_enum_list" , "class" , "no_inheritance" ), &ClassDB::class_get_enum_list, DEFVAL(false)); |
1543 | ::ClassDB::bind_method(D_METHOD("class_get_enum_constants" , "class" , "enum" , "no_inheritance" ), &ClassDB::class_get_enum_constants, DEFVAL(false)); |
1544 | ::ClassDB::bind_method(D_METHOD("class_get_integer_constant_enum" , "class" , "name" , "no_inheritance" ), &ClassDB::class_get_integer_constant_enum, DEFVAL(false)); |
1545 | |
1546 | ::ClassDB::bind_method(D_METHOD("is_class_enabled" , "class" ), &ClassDB::is_class_enabled); |
1547 | } |
1548 | |
1549 | } // namespace special |
1550 | |
1551 | ////// Engine ////// |
1552 | |
1553 | void Engine::set_physics_ticks_per_second(int p_ips) { |
1554 | ::Engine::get_singleton()->set_physics_ticks_per_second(p_ips); |
1555 | } |
1556 | |
1557 | int Engine::get_physics_ticks_per_second() const { |
1558 | return ::Engine::get_singleton()->get_physics_ticks_per_second(); |
1559 | } |
1560 | |
1561 | void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) { |
1562 | ::Engine::get_singleton()->set_max_physics_steps_per_frame(p_max_physics_steps); |
1563 | } |
1564 | |
1565 | int Engine::get_max_physics_steps_per_frame() const { |
1566 | return ::Engine::get_singleton()->get_max_physics_steps_per_frame(); |
1567 | } |
1568 | |
1569 | void Engine::set_physics_jitter_fix(double p_threshold) { |
1570 | ::Engine::get_singleton()->set_physics_jitter_fix(p_threshold); |
1571 | } |
1572 | |
1573 | double Engine::get_physics_jitter_fix() const { |
1574 | return ::Engine::get_singleton()->get_physics_jitter_fix(); |
1575 | } |
1576 | |
1577 | double Engine::get_physics_interpolation_fraction() const { |
1578 | return ::Engine::get_singleton()->get_physics_interpolation_fraction(); |
1579 | } |
1580 | |
1581 | void Engine::set_max_fps(int p_fps) { |
1582 | ::Engine::get_singleton()->set_max_fps(p_fps); |
1583 | } |
1584 | |
1585 | int Engine::get_max_fps() const { |
1586 | return ::Engine::get_singleton()->get_max_fps(); |
1587 | } |
1588 | |
1589 | double Engine::get_frames_per_second() const { |
1590 | return ::Engine::get_singleton()->get_frames_per_second(); |
1591 | } |
1592 | |
1593 | uint64_t Engine::get_physics_frames() const { |
1594 | return ::Engine::get_singleton()->get_physics_frames(); |
1595 | } |
1596 | |
1597 | uint64_t Engine::get_process_frames() const { |
1598 | return ::Engine::get_singleton()->get_process_frames(); |
1599 | } |
1600 | |
1601 | void Engine::set_time_scale(double p_scale) { |
1602 | ::Engine::get_singleton()->set_time_scale(p_scale); |
1603 | } |
1604 | |
1605 | double Engine::get_time_scale() { |
1606 | return ::Engine::get_singleton()->get_time_scale(); |
1607 | } |
1608 | |
1609 | int Engine::get_frames_drawn() { |
1610 | return ::Engine::get_singleton()->get_frames_drawn(); |
1611 | } |
1612 | |
1613 | MainLoop *Engine::get_main_loop() const { |
1614 | // Needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here |
1615 | return ::OS::get_singleton()->get_main_loop(); |
1616 | } |
1617 | |
1618 | Dictionary Engine::get_version_info() const { |
1619 | return ::Engine::get_singleton()->get_version_info(); |
1620 | } |
1621 | |
1622 | Dictionary Engine::get_author_info() const { |
1623 | return ::Engine::get_singleton()->get_author_info(); |
1624 | } |
1625 | |
1626 | TypedArray<Dictionary> Engine::get_copyright_info() const { |
1627 | return ::Engine::get_singleton()->get_copyright_info(); |
1628 | } |
1629 | |
1630 | Dictionary Engine::get_donor_info() const { |
1631 | return ::Engine::get_singleton()->get_donor_info(); |
1632 | } |
1633 | |
1634 | Dictionary Engine::get_license_info() const { |
1635 | return ::Engine::get_singleton()->get_license_info(); |
1636 | } |
1637 | |
1638 | String Engine::get_license_text() const { |
1639 | return ::Engine::get_singleton()->get_license_text(); |
1640 | } |
1641 | |
1642 | String Engine::get_architecture_name() const { |
1643 | return ::Engine::get_singleton()->get_architecture_name(); |
1644 | } |
1645 | |
1646 | bool Engine::is_in_physics_frame() const { |
1647 | return ::Engine::get_singleton()->is_in_physics_frame(); |
1648 | } |
1649 | |
1650 | bool Engine::has_singleton(const StringName &p_name) const { |
1651 | return ::Engine::get_singleton()->has_singleton(p_name); |
1652 | } |
1653 | |
1654 | Object *Engine::get_singleton_object(const StringName &p_name) const { |
1655 | return ::Engine::get_singleton()->get_singleton_object(p_name); |
1656 | } |
1657 | |
1658 | void Engine::register_singleton(const StringName &p_name, Object *p_object) { |
1659 | ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name)); |
1660 | ERR_FAIL_COND_MSG(!String(p_name).is_valid_identifier(), "Singleton name is not a valid identifier: " + p_name); |
1661 | ::Engine::Singleton s; |
1662 | s.class_name = p_name; |
1663 | s.name = p_name; |
1664 | s.ptr = p_object; |
1665 | s.user_created = true; |
1666 | ::Engine::get_singleton()->add_singleton(s); |
1667 | } |
1668 | |
1669 | void Engine::unregister_singleton(const StringName &p_name) { |
1670 | ERR_FAIL_COND_MSG(!has_singleton(p_name), "Attempt to remove unregistered singleton: " + String(p_name)); |
1671 | ERR_FAIL_COND_MSG(!::Engine::get_singleton()->is_singleton_user_created(p_name), "Attempt to remove non-user created singleton: " + String(p_name)); |
1672 | ::Engine::get_singleton()->remove_singleton(p_name); |
1673 | } |
1674 | |
1675 | Vector<String> Engine::get_singleton_list() const { |
1676 | List<::Engine::Singleton> singletons; |
1677 | ::Engine::get_singleton()->get_singletons(&singletons); |
1678 | Vector<String> ret; |
1679 | for (List<::Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) { |
1680 | ret.push_back(E->get().name); |
1681 | } |
1682 | return ret; |
1683 | } |
1684 | |
1685 | Error Engine::register_script_language(ScriptLanguage *p_language) { |
1686 | return ScriptServer::register_language(p_language); |
1687 | } |
1688 | |
1689 | Error Engine::unregister_script_language(const ScriptLanguage *p_language) { |
1690 | return ScriptServer::unregister_language(p_language); |
1691 | } |
1692 | |
1693 | int Engine::get_script_language_count() { |
1694 | return ScriptServer::get_language_count(); |
1695 | } |
1696 | |
1697 | ScriptLanguage *Engine::get_script_language(int p_index) const { |
1698 | return ScriptServer::get_language(p_index); |
1699 | } |
1700 | |
1701 | void Engine::set_editor_hint(bool p_enabled) { |
1702 | ::Engine::get_singleton()->set_editor_hint(p_enabled); |
1703 | } |
1704 | |
1705 | bool Engine::is_editor_hint() const { |
1706 | return ::Engine::get_singleton()->is_editor_hint(); |
1707 | } |
1708 | |
1709 | String Engine::get_write_movie_path() const { |
1710 | return ::Engine::get_singleton()->get_write_movie_path(); |
1711 | } |
1712 | |
1713 | void Engine::set_print_error_messages(bool p_enabled) { |
1714 | ::Engine::get_singleton()->set_print_error_messages(p_enabled); |
1715 | } |
1716 | |
1717 | bool Engine::is_printing_error_messages() const { |
1718 | return ::Engine::get_singleton()->is_printing_error_messages(); |
1719 | } |
1720 | |
1721 | void Engine::_bind_methods() { |
1722 | ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second" , "physics_ticks_per_second" ), &Engine::set_physics_ticks_per_second); |
1723 | ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second" ), &Engine::get_physics_ticks_per_second); |
1724 | ClassDB::bind_method(D_METHOD("set_max_physics_steps_per_frame" , "max_physics_steps" ), &Engine::set_max_physics_steps_per_frame); |
1725 | ClassDB::bind_method(D_METHOD("get_max_physics_steps_per_frame" ), &Engine::get_max_physics_steps_per_frame); |
1726 | ClassDB::bind_method(D_METHOD("set_physics_jitter_fix" , "physics_jitter_fix" ), &Engine::set_physics_jitter_fix); |
1727 | ClassDB::bind_method(D_METHOD("get_physics_jitter_fix" ), &Engine::get_physics_jitter_fix); |
1728 | ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction" ), &Engine::get_physics_interpolation_fraction); |
1729 | ClassDB::bind_method(D_METHOD("set_max_fps" , "max_fps" ), &Engine::set_max_fps); |
1730 | ClassDB::bind_method(D_METHOD("get_max_fps" ), &Engine::get_max_fps); |
1731 | |
1732 | ClassDB::bind_method(D_METHOD("set_time_scale" , "time_scale" ), &Engine::set_time_scale); |
1733 | ClassDB::bind_method(D_METHOD("get_time_scale" ), &Engine::get_time_scale); |
1734 | |
1735 | ClassDB::bind_method(D_METHOD("get_frames_drawn" ), &Engine::get_frames_drawn); |
1736 | ClassDB::bind_method(D_METHOD("get_frames_per_second" ), &Engine::get_frames_per_second); |
1737 | ClassDB::bind_method(D_METHOD("get_physics_frames" ), &Engine::get_physics_frames); |
1738 | ClassDB::bind_method(D_METHOD("get_process_frames" ), &Engine::get_process_frames); |
1739 | |
1740 | ClassDB::bind_method(D_METHOD("get_main_loop" ), &Engine::get_main_loop); |
1741 | |
1742 | ClassDB::bind_method(D_METHOD("get_version_info" ), &Engine::get_version_info); |
1743 | ClassDB::bind_method(D_METHOD("get_author_info" ), &Engine::get_author_info); |
1744 | ClassDB::bind_method(D_METHOD("get_copyright_info" ), &Engine::get_copyright_info); |
1745 | ClassDB::bind_method(D_METHOD("get_donor_info" ), &Engine::get_donor_info); |
1746 | ClassDB::bind_method(D_METHOD("get_license_info" ), &Engine::get_license_info); |
1747 | ClassDB::bind_method(D_METHOD("get_license_text" ), &Engine::get_license_text); |
1748 | |
1749 | ClassDB::bind_method(D_METHOD("get_architecture_name" ), &Engine::get_architecture_name); |
1750 | |
1751 | ClassDB::bind_method(D_METHOD("is_in_physics_frame" ), &Engine::is_in_physics_frame); |
1752 | |
1753 | ClassDB::bind_method(D_METHOD("has_singleton" , "name" ), &Engine::has_singleton); |
1754 | ClassDB::bind_method(D_METHOD("get_singleton" , "name" ), &Engine::get_singleton_object); |
1755 | |
1756 | ClassDB::bind_method(D_METHOD("register_singleton" , "name" , "instance" ), &Engine::register_singleton); |
1757 | ClassDB::bind_method(D_METHOD("unregister_singleton" , "name" ), &Engine::unregister_singleton); |
1758 | ClassDB::bind_method(D_METHOD("get_singleton_list" ), &Engine::get_singleton_list); |
1759 | |
1760 | ClassDB::bind_method(D_METHOD("register_script_language" , "language" ), &Engine::register_script_language); |
1761 | ClassDB::bind_method(D_METHOD("unregister_script_language" , "language" ), &Engine::unregister_script_language); |
1762 | ClassDB::bind_method(D_METHOD("get_script_language_count" ), &Engine::get_script_language_count); |
1763 | ClassDB::bind_method(D_METHOD("get_script_language" , "index" ), &Engine::get_script_language); |
1764 | |
1765 | ClassDB::bind_method(D_METHOD("is_editor_hint" ), &Engine::is_editor_hint); |
1766 | |
1767 | ClassDB::bind_method(D_METHOD("get_write_movie_path" ), &Engine::get_write_movie_path); |
1768 | |
1769 | ClassDB::bind_method(D_METHOD("set_print_error_messages" , "enabled" ), &Engine::set_print_error_messages); |
1770 | ClassDB::bind_method(D_METHOD("is_printing_error_messages" ), &Engine::is_printing_error_messages); |
1771 | |
1772 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages" ), "set_print_error_messages" , "is_printing_error_messages" ); |
1773 | ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second" ), "set_physics_ticks_per_second" , "get_physics_ticks_per_second" ); |
1774 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame" ), "set_max_physics_steps_per_frame" , "get_max_physics_steps_per_frame" ); |
1775 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps" ), "set_max_fps" , "get_max_fps" ); |
1776 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_scale" ), "set_time_scale" , "get_time_scale" ); |
1777 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix" ), "set_physics_jitter_fix" , "get_physics_jitter_fix" ); |
1778 | } |
1779 | |
1780 | Engine *Engine::singleton = nullptr; |
1781 | |
1782 | ////// EngineDebugger ////// |
1783 | |
1784 | bool EngineDebugger::is_active() { |
1785 | return ::EngineDebugger::is_active(); |
1786 | } |
1787 | |
1788 | void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) { |
1789 | ERR_FAIL_COND(p_profiler.is_null()); |
1790 | ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered." ); |
1791 | ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler name already in use: " + p_name); |
1792 | Error err = p_profiler->bind(p_name); |
1793 | ERR_FAIL_COND_MSG(err != OK, "Profiler failed to register with error: " + itos(err)); |
1794 | profilers.insert(p_name, p_profiler); |
1795 | } |
1796 | |
1797 | void EngineDebugger::unregister_profiler(const StringName &p_name) { |
1798 | ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name); |
1799 | profilers[p_name]->unbind(); |
1800 | profilers.erase(p_name); |
1801 | } |
1802 | |
1803 | bool EngineDebugger::is_profiling(const StringName &p_name) { |
1804 | return ::EngineDebugger::is_profiling(p_name); |
1805 | } |
1806 | |
1807 | bool EngineDebugger::has_profiler(const StringName &p_name) { |
1808 | return ::EngineDebugger::has_profiler(p_name); |
1809 | } |
1810 | |
1811 | void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) { |
1812 | ::EngineDebugger::profiler_add_frame_data(p_name, p_data); |
1813 | } |
1814 | |
1815 | void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) { |
1816 | if (::EngineDebugger::get_singleton()) { |
1817 | ::EngineDebugger::get_singleton()->profiler_enable(p_name, p_enabled, p_opts); |
1818 | } |
1819 | } |
1820 | |
1821 | void EngineDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) { |
1822 | ERR_FAIL_COND_MSG(captures.has(p_name) || has_capture(p_name), "Capture already registered: " + p_name); |
1823 | captures.insert(p_name, p_callable); |
1824 | Callable &c = captures[p_name]; |
1825 | ::EngineDebugger::Capture capture(&c, &EngineDebugger::call_capture); |
1826 | ::EngineDebugger::register_message_capture(p_name, capture); |
1827 | } |
1828 | |
1829 | void EngineDebugger::unregister_message_capture(const StringName &p_name) { |
1830 | ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name); |
1831 | ::EngineDebugger::unregister_message_capture(p_name); |
1832 | captures.erase(p_name); |
1833 | } |
1834 | |
1835 | bool EngineDebugger::has_capture(const StringName &p_name) { |
1836 | return ::EngineDebugger::has_capture(p_name); |
1837 | } |
1838 | |
1839 | void EngineDebugger::send_message(const String &p_msg, const Array &p_data) { |
1840 | ERR_FAIL_COND_MSG(!::EngineDebugger::is_active(), "Can't send message. No active debugger" ); |
1841 | ::EngineDebugger::get_singleton()->send_message(p_msg, p_data); |
1842 | } |
1843 | |
1844 | Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) { |
1845 | Callable &capture = *(Callable *)p_user; |
1846 | if (capture.is_null()) { |
1847 | return FAILED; |
1848 | } |
1849 | Variant cmd = p_cmd, data = p_data; |
1850 | const Variant *args[2] = { &cmd, &data }; |
1851 | Variant retval; |
1852 | Callable::CallError err; |
1853 | capture.callp(args, 2, retval, err); |
1854 | ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, FAILED, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(capture, args, 2, err)); |
1855 | ERR_FAIL_COND_V_MSG(retval.get_type() != Variant::BOOL, FAILED, "Error calling 'capture' to callable: " + String(capture) + ". Return type is not bool." ); |
1856 | r_captured = retval; |
1857 | return OK; |
1858 | } |
1859 | |
1860 | EngineDebugger::~EngineDebugger() { |
1861 | for (const KeyValue<StringName, Callable> &E : captures) { |
1862 | ::EngineDebugger::unregister_message_capture(E.key); |
1863 | } |
1864 | captures.clear(); |
1865 | } |
1866 | |
1867 | EngineDebugger *EngineDebugger::singleton = nullptr; |
1868 | |
1869 | void EngineDebugger::_bind_methods() { |
1870 | ClassDB::bind_method(D_METHOD("is_active" ), &EngineDebugger::is_active); |
1871 | |
1872 | ClassDB::bind_method(D_METHOD("register_profiler" , "name" , "profiler" ), &EngineDebugger::register_profiler); |
1873 | ClassDB::bind_method(D_METHOD("unregister_profiler" , "name" ), &EngineDebugger::unregister_profiler); |
1874 | |
1875 | ClassDB::bind_method(D_METHOD("is_profiling" , "name" ), &EngineDebugger::is_profiling); |
1876 | ClassDB::bind_method(D_METHOD("has_profiler" , "name" ), &EngineDebugger::has_profiler); |
1877 | |
1878 | ClassDB::bind_method(D_METHOD("profiler_add_frame_data" , "name" , "data" ), &EngineDebugger::profiler_add_frame_data); |
1879 | ClassDB::bind_method(D_METHOD("profiler_enable" , "name" , "enable" , "arguments" ), &EngineDebugger::profiler_enable, DEFVAL(Array())); |
1880 | |
1881 | ClassDB::bind_method(D_METHOD("register_message_capture" , "name" , "callable" ), &EngineDebugger::register_message_capture); |
1882 | ClassDB::bind_method(D_METHOD("unregister_message_capture" , "name" ), &EngineDebugger::unregister_message_capture); |
1883 | ClassDB::bind_method(D_METHOD("has_capture" , "name" ), &EngineDebugger::has_capture); |
1884 | |
1885 | ClassDB::bind_method(D_METHOD("send_message" , "message" , "data" ), &EngineDebugger::send_message); |
1886 | } |
1887 | |
1888 | } // namespace core_bind |
1889 | |