summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/engine.h2
-rw-r--r--core/core_bind.cpp25
-rw-r--r--core/core_bind.h10
-rw-r--r--core/debugger/engine_profiler.cpp6
-rw-r--r--core/debugger/local_debugger.cpp4
-rw-r--r--core/debugger/remote_debugger.cpp11
-rw-r--r--core/debugger/remote_debugger_peer.cpp4
-rw-r--r--core/debugger/remote_debugger_peer.h14
-rw-r--r--core/doc_data.h2
-rw-r--r--core/error/error_macros.cpp2
-rw-r--r--core/error/error_macros.h2
-rw-r--r--core/extension/SCsub6
-rw-r--r--core/extension/extension_api_dump.cpp2
-rw-r--r--core/extension/gdnative_interface.cpp12
-rw-r--r--core/extension/gdnative_interface.h90
-rw-r--r--core/extension/make_wrappers.py93
-rw-r--r--core/extension/native_extension.cpp16
-rw-r--r--core/input/input.cpp16
-rw-r--r--core/input/input.h10
-rw-r--r--core/input/input_event.cpp32
-rw-r--r--core/io/dir_access.h4
-rw-r--r--core/io/file_access.h6
-rw-r--r--core/io/file_access_network.cpp2
-rw-r--r--core/io/file_access_pack.h10
-rw-r--r--core/io/file_access_zip.h4
-rw-r--r--core/io/image.cpp21
-rw-r--r--core/io/image.h3
-rw-r--r--core/io/ip.cpp10
-rw-r--r--core/io/ip.h5
-rw-r--r--core/io/packed_data_container.cpp2
-rw-r--r--core/io/resource.h1
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/io/resource_uid.h2
-rw-r--r--core/io/stream_peer.h1
-rw-r--r--core/io/stream_peer_tcp.h1
-rw-r--r--core/io/translation_loader_po.cpp439
-rw-r--r--core/io/udp_server.h2
-rw-r--r--core/math/a_star.cpp144
-rw-r--r--core/math/a_star.h12
-rw-r--r--core/math/basis.cpp2
-rw-r--r--core/math/bvh.h43
-rw-r--r--core/math/bvh_structs.inc20
-rw-r--r--core/math/bvh_tree.h6
-rw-r--r--core/math/expression.h2
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/face3.h2
-rw-r--r--core/math/math_funcs.h25
-rw-r--r--core/math/octree.h37
-rw-r--r--core/object/callable_method_pointer.h2
-rw-r--r--core/object/class_db.cpp18
-rw-r--r--core/object/class_db.h91
-rw-r--r--core/object/make_virtuals.py2
-rw-r--r--core/object/message_queue.h4
-rw-r--r--core/object/method_bind.cpp4
-rw-r--r--core/object/method_bind.h263
-rw-r--r--core/object/object.cpp96
-rw-r--r--core/object/object.h32
-rw-r--r--core/object/ref_counted.h2
-rw-r--r--core/object/script_language.cpp2
-rw-r--r--core/object/script_language.h142
-rw-r--r--core/object/script_language_extension.cpp180
-rw-r--r--core/object/script_language_extension.h835
-rw-r--r--core/object/undo_redo.cpp18
-rw-r--r--core/object/undo_redo.h4
-rw-r--r--core/os/main_loop.h1
-rw-r--r--core/os/memory.h6
-rw-r--r--core/os/os.h2
-rw-r--r--core/os/pool_allocator.cpp4
-rw-r--r--core/os/pool_allocator.h10
-rw-r--r--core/register_core_types.cpp8
-rw-r--r--core/string/print_string.cpp2
-rw-r--r--core/string/print_string.h2
-rw-r--r--core/string/string_name.h2
-rw-r--r--core/string/translation.cpp4
-rw-r--r--core/string/translation.h2
-rw-r--r--core/string/ustring.h4
-rw-r--r--core/templates/command_queue_mt.h10
-rw-r--r--core/templates/map.h6
-rw-r--r--core/templates/oa_hash_map.h2
-rw-r--r--core/templates/safe_list.h8
-rw-r--r--core/templates/self_list.h2
-rw-r--r--core/templates/set.h4
-rw-r--r--core/templates/thread_work_pool.h4
-rw-r--r--core/templates/vector.h19
-rw-r--r--core/variant/array.cpp27
-rw-r--r--core/variant/array.h4
-rw-r--r--core/variant/callable.cpp10
-rw-r--r--core/variant/callable.h6
-rw-r--r--core/variant/callable_bind.cpp16
-rw-r--r--core/variant/callable_bind.h32
-rw-r--r--core/variant/variant_call.cpp2
-rw-r--r--core/variant/variant_construct.h6
-rw-r--r--core/variant/variant_parser.h12
-rw-r--r--core/variant/variant_utility.cpp72
94 files changed, 2335 insertions, 818 deletions
diff --git a/core/config/engine.h b/core/config/engine.h
index 1adab9b96f..eac96852b3 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -40,7 +40,7 @@ class Engine {
public:
struct Singleton {
StringName name;
- Object *ptr;
+ Object *ptr = nullptr;
StringName class_name; //used for binding generation hinting
bool user_created = false;
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 2d0eaadbdf..706395afa9 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1334,7 +1334,7 @@ void File::store_buffer(const Vector<uint8_t> &p_buffer) {
f->store_buffer(&r[0], len);
}
-bool File::file_exists(const String &p_name) const {
+bool File::file_exists(const String &p_name) {
return FileAccess::exists(p_name);
}
@@ -1424,7 +1424,7 @@ void File::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &File::store_pascal_string);
ClassDB::bind_method(D_METHOD("get_pascal_string"), &File::get_pascal_string);
- ClassDB::bind_method(D_METHOD("file_exists", "path"), &File::file_exists);
+ ClassDB::bind_static_method("File", D_METHOD("file_exists", "path"), &File::file_exists);
ClassDB::bind_method(D_METHOD("get_modified_time", "file"), &File::get_modified_time);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
@@ -2093,10 +2093,6 @@ int ClassDB::get_integer_constant(const StringName &p_class, const StringName &p
return c;
}
-StringName ClassDB::get_category(const StringName &p_node) const {
- return ::ClassDB::get_category(p_node);
-}
-
bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) const {
return ::ClassDB::has_enum(p_class, p_name, p_no_inheritance);
}
@@ -2168,7 +2164,6 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("class_get_enum_constants", "class", "enum", "no_inheritance"), &ClassDB::get_enum_constants, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("class_get_integer_constant_enum", "class", "name", "no_inheritance"), &ClassDB::get_integer_constant_enum, DEFVAL(false));
- ::ClassDB::bind_method(D_METHOD("class_get_category", "class"), &ClassDB::get_category);
::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
}
@@ -2296,6 +2291,18 @@ Vector<String> Engine::get_singleton_list() const {
return ret;
}
+void Engine::register_script_language(ScriptLanguage *p_language) {
+ ScriptServer::register_language(p_language);
+}
+
+int Engine::get_script_language_count() {
+ return ScriptServer::get_language_count();
+}
+
+ScriptLanguage *Engine::get_script_language(int p_index) const {
+ return ScriptServer::get_language(p_index);
+}
+
void Engine::set_editor_hint(bool p_enabled) {
::Engine::get_singleton()->set_editor_hint(p_enabled);
}
@@ -2347,6 +2354,10 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("unregister_singleton", "name"), &Engine::unregister_singleton);
ClassDB::bind_method(D_METHOD("get_singleton_list"), &Engine::get_singleton_list);
+ ClassDB::bind_method(D_METHOD("register_script_language", "language"), &Engine::register_script_language);
+ ClassDB::bind_method(D_METHOD("get_script_language_count"), &Engine::get_script_language_count);
+ ClassDB::bind_method(D_METHOD("get_script_language", "index"), &Engine::get_script_language);
+
ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
diff --git a/core/core_bind.h b/core/core_bind.h
index 4a7eb718f1..4d26698f99 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -38,6 +38,7 @@
#include "core/io/image.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
+#include "core/object/script_language.h"
#include "core/os/os.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
@@ -436,7 +437,7 @@ public:
void store_var(const Variant &p_var, bool p_full_objects = false);
- bool file_exists(const String &p_name) const; // Return true if a file exists.
+ static bool file_exists(const String &p_name); // Return true if a file exists.
uint64_t get_modified_time(const String &p_file) const;
@@ -446,7 +447,7 @@ public:
class Directory : public RefCounted {
GDCLASS(Directory, RefCounted);
- DirAccess *d;
+ DirAccess *d = nullptr;
bool dir_open = false;
bool include_navigational = false;
@@ -604,7 +605,6 @@ public:
PackedStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
bool has_integer_constant(const StringName &p_class, const StringName &p_name) const;
int get_integer_constant(const StringName &p_class, const StringName &p_name) const;
- StringName get_category(const StringName &p_node) const;
bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const;
PackedStringArray get_enum_list(const StringName &p_class, bool p_no_inheritance = false) const;
@@ -664,6 +664,10 @@ public:
void unregister_singleton(const StringName &p_name);
Vector<String> get_singleton_list() const;
+ void register_script_language(ScriptLanguage *p_language);
+ int get_script_language_count();
+ ScriptLanguage *get_script_language(int p_index) const;
+
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
diff --git a/core/debugger/engine_profiler.cpp b/core/debugger/engine_profiler.cpp
index c858b1febd..6235d19405 100644
--- a/core/debugger/engine_profiler.cpp
+++ b/core/debugger/engine_profiler.cpp
@@ -55,13 +55,13 @@ Error EngineProfiler::bind(const String &p_name) {
EngineDebugger::Profiler prof(
this,
[](void *p_user, bool p_enable, const Array &p_opts) {
- ((EngineProfiler *)p_user)->toggle(p_enable, p_opts);
+ static_cast<EngineProfiler *>(p_user)->toggle(p_enable, p_opts);
},
[](void *p_user, const Array &p_data) {
- ((EngineProfiler *)p_user)->add(p_data);
+ static_cast<EngineProfiler *>(p_user)->add(p_data);
},
[](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- ((EngineProfiler *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+ static_cast<EngineProfiler *>(p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
});
registration = p_name;
EngineDebugger::register_profiler(p_name, prof);
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index c9f7d81a90..131cbaed6c 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -369,11 +369,11 @@ LocalDebugger::LocalDebugger() {
Profiler scr_prof(
scripts_profiler,
[](void *p_user, bool p_enable, const Array &p_opts) {
- ((ScriptsProfiler *)p_user)->toggle(p_enable, p_opts);
+ static_cast<ScriptsProfiler *>(p_user)->toggle(p_enable, p_opts);
},
nullptr,
[](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- ((ScriptsProfiler *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+ static_cast<ScriptsProfiler *>(p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
});
register_profiler("scripts", scr_prof);
}
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 2fce23d003..425261aa6c 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -161,8 +161,9 @@ public:
if (!monitor_value.is_num()) {
ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number");
arr[i + max] = Variant();
+ } else {
+ arr[i + max] = monitor_value;
}
- arr[i + max] = monitor_value;
}
EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr);
@@ -189,7 +190,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *
return; //ignore script errors, those go through debugger
}
- RemoteDebugger *rd = (RemoteDebugger *)p_this;
+ RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this);
if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive errors during flush.
return;
}
@@ -208,7 +209,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *
}
void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) {
- RemoteDebugger *rd = (RemoteDebugger *)p_this;
+ RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this);
if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive prints during flush.
return;
@@ -656,12 +657,12 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
// Core and profiler captures.
Capture core_cap(this,
[](void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
- return ((RemoteDebugger *)p_user)->_core_capture(p_cmd, p_data, r_captured);
+ return static_cast<RemoteDebugger *>(p_user)->_core_capture(p_cmd, p_data, r_captured);
});
register_message_capture("core", core_cap);
Capture profiler_cap(this,
[](void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
- return ((RemoteDebugger *)p_user)->_profiler_capture(p_cmd, p_data, r_captured);
+ return static_cast<RemoteDebugger *>(p_user)->_profiler_capture(p_cmd, p_data, r_captured);
});
register_message_capture("profiler", profiler_cap);
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index 7c7d38ab0a..950500884e 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -162,7 +162,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
int port = p_port;
const int tries = 6;
- int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
+ const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
tcp_client->connect_to_host(ip, port);
@@ -192,7 +192,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) {
// Update in time for 144hz monitors
const uint64_t min_tick = 6900;
- RemoteDebuggerPeerTCP *peer = (RemoteDebuggerPeerTCP *)p_ud;
+ RemoteDebuggerPeerTCP *peer = static_cast<RemoteDebuggerPeerTCP *>(p_ud);
while (peer->running && peer->is_peer_connected()) {
uint64_t ticks_usec = OS::get_singleton()->get_ticks_usec();
peer->_poll();
diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h
index 010336ffd3..473fd8d712 100644
--- a/core/debugger/remote_debugger_peer.h
+++ b/core/debugger/remote_debugger_peer.h
@@ -81,13 +81,13 @@ public:
Error connect_to_host(const String &p_host, uint16_t p_port);
- void poll();
- bool is_peer_connected();
- bool has_message();
- Array get_message();
- Error put_message(const Array &p_arr);
- int get_max_message_size() const;
- void close();
+ void poll() override;
+ bool is_peer_connected() override;
+ bool has_message() override;
+ Array get_message() override;
+ Error put_message(const Array &p_arr) override;
+ int get_max_message_size() const override;
+ void close() override;
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
~RemoteDebuggerPeerTCP();
diff --git a/core/doc_data.h b/core/doc_data.h
index 9286b843be..194a39a729 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -152,7 +152,7 @@ public:
struct ClassDoc {
String name;
String inherits;
- String category;
+ String category; // FIXME: Wrongly used by VisualScriptPropertySelector, should be removed.
String brief_description;
String description;
Vector<TutorialDoc> tutorials;
diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp
index ceccd43259..8add4b9a3a 100644
--- a/core/error/error_macros.cpp
+++ b/core/error/error_macros.cpp
@@ -50,7 +50,7 @@ void add_error_handler(ErrorHandlerList *p_handler) {
_global_unlock();
}
-void remove_error_handler(ErrorHandlerList *p_handler) {
+void remove_error_handler(const ErrorHandlerList *p_handler) {
_global_lock();
ErrorHandlerList *prev = nullptr;
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index 01e22e84b7..2cfb5421c6 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -58,7 +58,7 @@ struct ErrorHandlerList {
};
void add_error_handler(ErrorHandlerList *p_handler);
-void remove_error_handler(ErrorHandlerList *p_handler);
+void remove_error_handler(const ErrorHandlerList *p_handler);
// Functions used by the error macros.
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
diff --git a/core/extension/SCsub b/core/extension/SCsub
index a3a54250c1..23727c1b76 100644
--- a/core/extension/SCsub
+++ b/core/extension/SCsub
@@ -2,6 +2,12 @@
Import("env")
+import make_wrappers
+from platform_methods import run_in_subprocess
+
+env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run))
+
+
env_extension = env.Clone()
env_extension.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 31af28b783..9acc28f51e 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -666,6 +666,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Dictionary d2;
d2["name"] = String(method_name);
d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false;
+ d2["is_static"] = (F.flags & METHOD_FLAG_STATIC) ? true : false;
d2["is_vararg"] = false;
d2["is_virtual"] = true;
// virtual functions have no hash since no MethodBind is involved
@@ -708,6 +709,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
d2["is_const"] = method->is_const();
d2["is_vararg"] = method->is_vararg();
+ d2["is_static"] = method->is_static();
d2["is_virtual"] = false;
d2["hash"] = method->get_hash();
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index d0461611ec..b5b340731d 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/object/class_db.h"
+#include "core/object/script_language_extension.h"
#include "core/os/memory.h"
#include "core/variant/variant.h"
#include "core/version.h"
@@ -864,6 +865,13 @@ static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPt
return (GDObjectInstanceID)o->get_instance_id();
}
+static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data) {
+ ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
+ script_instance_extension->instance = p_instance_data;
+ script_instance_extension->native_info = p_info;
+ return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension);
+}
+
static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) {
MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname));
ERR_FAIL_COND_V(!mb, nullptr);
@@ -1032,6 +1040,10 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
gdni.object_get_instance_id = gdnative_object_get_instance_id;
+ /* SCRIPT INSTANCE */
+
+ gdni.script_instance_create = gdnative_script_instance_create;
+
/* CLASSDB */
gdni.classdb_construct_object = gdnative_classdb_construct_object;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index cc2957ec56..732a1b5af0 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -205,10 +205,21 @@ typedef struct {
uint32_t usage;
} GDNativePropertyInfo;
+typedef struct {
+ const char *name;
+ GDNativePropertyInfo return_value;
+ uint32_t flags; // From GDNativeExtensionClassMethodFlags
+ int32_t id;
+ GDNativePropertyInfo *arguments;
+ uint32_t argument_count;
+ GDNativeVariantPtr default_arguments;
+ uint32_t default_argument_count;
+} GDNativeMethodInfo;
+
typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
-typedef const char *(*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance);
+typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out);
typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
@@ -289,6 +300,79 @@ typedef struct {
GDNativeVariantPtr *default_arguments;
} GDNativeExtensionClassMethodInfo;
+/* SCRIPT INSTANCE EXTENSION */
+
+typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation
+
+typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
+typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
+typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
+typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
+typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid);
+
+typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata);
+typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
+
+typedef const GDNativeMethodInfo *(*GDNativeExtensionScriptInstanceGetMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
+typedef void (*GDNativeExtensionScriptInstanceFreeMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeMethodInfo *p_list);
+
+typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
+
+typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
+typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid);
+
+typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+
+typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetScript)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+typedef GDNativeBool (*GDNativeExtensionScriptInstanceIsPlaceholder)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+
+typedef void *GDNativeExtensionScriptLanguagePtr;
+
+typedef GDNativeExtensionScriptLanguagePtr (*GDNativeExtensionScriptInstanceGetLanguage)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+
+typedef void (*GDNativeExtensionScriptInstanceFree)(GDNativeExtensionScriptInstanceDataPtr p_instance);
+
+typedef void *GDNativeScriptInstancePtr; // Pointer to ScriptInstance.
+
+typedef struct {
+ GDNativeExtensionScriptInstanceSet set_func;
+ GDNativeExtensionScriptInstanceGet get_func;
+ GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func;
+ GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func;
+ GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func;
+
+ GDNativeExtensionScriptInstanceGetOwner get_owner_func;
+ GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func;
+
+ GDNativeExtensionScriptInstanceGetMethodList get_method_list_func;
+ GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func;
+
+ GDNativeExtensionScriptInstanceHasMethod has_method_func;
+
+ GDNativeExtensionScriptInstanceCall call_func;
+ GDNativeExtensionScriptInstanceNotification notification_func;
+
+ GDNativeExtensionScriptInstanceToString to_string_func;
+
+ GDNativeExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
+ GDNativeExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
+
+ GDNativeExtensionScriptInstanceGetScript get_script_func;
+
+ GDNativeExtensionScriptInstanceIsPlaceholder is_placeholder_func;
+
+ GDNativeExtensionScriptInstanceSet set_fallback_func;
+ GDNativeExtensionScriptInstanceGet get_fallback_func;
+
+ GDNativeExtensionScriptInstanceGetLanguage get_language_func;
+
+ GDNativeExtensionScriptInstanceFree free_func;
+
+} GDNativeExtensionScriptInstanceInfo;
+
/* INTERFACE */
typedef struct {
@@ -441,6 +525,10 @@ typedef struct {
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object);
+ /* SCRIPT INSTANCE */
+
+ GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data);
+
/* CLASSDB */
GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
diff --git a/core/extension/make_wrappers.py b/core/extension/make_wrappers.py
new file mode 100644
index 0000000000..862d313fba
--- /dev/null
+++ b/core/extension/make_wrappers.py
@@ -0,0 +1,93 @@
+proto = """
+#define EXBIND$VER($RETTYPE m_name$ARG) \\
+GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
+virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
+ $RETPRE\\
+ GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\
+ $RETPOST\\
+}
+"""
+
+
+def generate_version(argcount, const=False, returns=False):
+ s = proto
+ sproto = str(argcount)
+ method_info = ""
+ if returns:
+ sproto += "R"
+ s = s.replace("$RETTYPE", "m_ret, ")
+ s = s.replace("$RETVAL", "m_ret")
+ s = s.replace("$RETPRE", "m_ret ret; ZeroInitializer<m_ret>::initialize(ret);\\\n")
+ s = s.replace("$RETPOST", "return ret;\\\n")
+
+ else:
+ s = s.replace("$RETTYPE", "")
+ s = s.replace("$RETVAL", "void")
+ s = s.replace("$RETPRE", "")
+ s = s.replace("$RETPOST", "return;")
+
+ if const:
+ sproto += "C"
+ s = s.replace("$CONST", "const")
+ else:
+ s = s.replace("$CONST", "")
+
+ s = s.replace("$VER", sproto)
+ argtext = ""
+ funcargs = ""
+ callargs = ""
+
+ for i in range(argcount):
+ if i > 0:
+ funcargs += ", "
+
+ argtext += ", m_type" + str(i + 1)
+ funcargs += "m_type" + str(i + 1) + " arg" + str(i + 1)
+ callargs += ", arg" + str(i + 1)
+
+ if argcount:
+ s = s.replace("$ARG", argtext)
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+ else:
+ s = s.replace("$ARG", "")
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+
+ if returns:
+ s = s.replace("$RETREF", ", ret")
+ else:
+ s = s.replace("$RETREF", "")
+
+ return s
+
+
+def run(target, source, env):
+
+ max_versions = 12
+
+ txt = """
+#ifndef GDEXTENSION_WRAPPERS_GEN_H
+#define GDEXTENSION_WRAPPERS_GEN_H
+
+
+"""
+
+ for i in range(max_versions + 1):
+
+ txt += "/* " + str(i) + " Arguments */\n\n"
+ txt += generate_version(i, False, False)
+ txt += generate_version(i, False, True)
+ txt += generate_version(i, True, False)
+ txt += generate_version(i, True, True)
+
+ txt += "#endif"
+
+ with open(target[0], "w") as f:
+ f.write(txt)
+
+
+if __name__ == "__main__":
+ from platform_methods import subprocess_main
+
+ subprocess_main(globals())
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 1a39c937e8..34a11758f8 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -112,7 +112,7 @@ public:
static GDNativeInterface gdnative_interface;
void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
@@ -163,7 +163,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
ClassDB::register_extension_class(&extension->native_extension);
}
void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
StringName method_name = p_method_info->name;
@@ -177,7 +177,7 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
ClassDB::bind_method_custom(class_name, method);
}
void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
@@ -188,7 +188,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
}
void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
@@ -206,7 +206,7 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
}
void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'.");
@@ -215,7 +215,7 @@ void NativeExtension::_register_extension_class_property_group(const GDNativeExt
}
void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'.");
@@ -224,7 +224,7 @@ void NativeExtension::_register_extension_class_property_subgroup(const GDNative
}
void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
@@ -245,7 +245,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
}
void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) {
- NativeExtension *self = (NativeExtension *)p_library;
+ NativeExtension *self = static_cast<NativeExtension *>(p_library);
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 656bb92203..343076b4e1 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -72,7 +72,7 @@ Input *Input::singleton = nullptr;
void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr;
Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr;
-void (*Input::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr;
+void (*Input::warp_mouse_func)(const Vector2 &p_position) = nullptr;
Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr;
void (*Input::set_custom_mouse_cursor_func)(const RES &, Input::CursorShape, const Vector2 &) = nullptr;
@@ -126,7 +126,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
- ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &Input::warp_mouse);
ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f));
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW));
@@ -733,8 +733,8 @@ MouseButton Input::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
}
-void Input::warp_mouse_position(const Vector2 &p_to) {
- warp_mouse_func(p_to);
+void Input::warp_mouse(const Vector2 &p_position) {
+ warp_mouse_func(p_position);
}
Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
@@ -756,7 +756,7 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con
const Point2i pos_local = p_motion->get_global_position() - p_rect.position;
const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
if (pos_warped != pos_local) {
- warp_mouse_position(pos_warped + p_rect.position);
+ warp_mouse(pos_warped + p_rect.position);
}
return rel_warped;
@@ -772,6 +772,8 @@ void Input::action_press(const StringName &p_action, float p_strength) {
action.process_frame = Engine::get_singleton()->get_process_frames();
action.pressed = true;
action.strength = p_strength;
+ action.raw_strength = p_strength;
+ action.exact = true;
action_state[p_action] = action;
}
@@ -783,6 +785,8 @@ void Input::action_release(const StringName &p_action) {
action.process_frame = Engine::get_singleton()->get_process_frames();
action.pressed = false;
action.strength = 0.f;
+ action.raw_strength = 0.f;
+ action.exact = true;
action_state[p_action] = action;
}
@@ -1070,7 +1074,6 @@ void Input::_axis_event(int p_device, JoyAxis p_axis, float p_value) {
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
JoyEvent event;
- event.type = TYPE_MAX;
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
@@ -1106,7 +1109,6 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping,
Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, JoyAxis p_axis, float p_value) {
JoyEvent event;
- event.type = TYPE_MAX;
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
diff --git a/core/input/input.h b/core/input/input.h
index ab2cd377f4..bbdac46805 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -157,9 +157,9 @@ private:
};
struct JoyEvent {
- int type;
- int index; // Can be either JoyAxis or JoyButton.
- float value;
+ int type = TYPE_MAX;
+ int index = -1; // Can be either JoyAxis or JoyButton.
+ float value = 0.f;
};
struct JoyBinding {
@@ -216,7 +216,7 @@ private:
static void (*set_mouse_mode_func)(MouseMode);
static MouseMode (*get_mouse_mode_func)();
- static void (*warp_mouse_func)(const Vector2 &p_to_pos);
+ static void (*warp_mouse_func)(const Vector2 &p_position);
static CursorShape (*get_current_cursor_shape_func)();
static void (*set_custom_mouse_cursor_func)(const RES &, CursorShape, const Vector2 &);
@@ -273,7 +273,7 @@ public:
Vector2 get_last_mouse_velocity();
MouseButton get_mouse_button_mask() const;
- void warp_mouse_position(const Vector2 &p_to);
+ void warp_mouse(const Vector2 &p_position);
Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect);
void parse_input_event(const Ref<InputEvent> &p_event);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 52c7c69315..2d4c203748 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -47,30 +47,30 @@ int InputEvent::get_device() const {
}
bool InputEvent::is_action(const StringName &p_action, bool p_exact_match) const {
- return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match);
+ return InputMap::get_singleton()->event_is_action(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match);
}
bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && pressed && (p_allow_echo || !is_echo());
}
bool InputEvent::is_action_released(const StringName &p_action, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && !pressed;
}
float InputEvent::get_action_strength(const StringName &p_action, bool p_exact_match) const {
float strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, &strength, nullptr);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, nullptr, &strength, nullptr);
return valid ? strength : 0.0f;
}
float InputEvent::get_action_raw_strength(const StringName &p_action, bool p_exact_match) const {
float raw_strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, nullptr, &raw_strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, nullptr, nullptr, &raw_strength);
return valid ? raw_strength : 0.0f;
}
@@ -83,7 +83,7 @@ bool InputEvent::is_echo() const {
}
Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
- return Ref<InputEvent>((InputEvent *)this);
+ return Ref<InputEvent>(const_cast<InputEvent *>(this));
}
bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
@@ -382,7 +382,7 @@ String InputEventKey::to_string() {
}
String mods = InputEventWithModifiers::as_text();
- mods = mods.is_empty() ? TTR("none") : mods;
+ mods = mods.is_empty() ? "none" : mods;
return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e);
}
@@ -690,14 +690,14 @@ String InputEventMouseButton::to_string() {
case MouseButton::WHEEL_RIGHT:
case MouseButton::MB_XBUTTON1:
case MouseButton::MB_XBUTTON2:
- button_string += " (" + RTR(_mouse_button_descriptions[(size_t)idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1
+ button_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)idx - 1])); // button index starts from 1, array index starts from 0, so subtract 1
break;
default:
break;
}
String mods = InputEventWithModifiers::as_text();
- mods = mods.is_empty() ? TTR("none") : mods;
+ mods = mods.is_empty() ? "none" : mods;
// Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
String index_and_mods = vformat("button_index=%s, mods=%s", button_index, mods);
@@ -787,19 +787,19 @@ String InputEventMouseMotion::to_string() {
String button_mask_string = itos((int64_t)button_mask);
switch (button_mask) {
case MouseButton::MASK_LEFT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]) + ")";
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
break;
case MouseButton::MASK_MIDDLE:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]) + ")";
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
break;
case MouseButton::MASK_RIGHT:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]) + ")";
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
break;
case MouseButton::MASK_XBUTTON1:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]) + ")";
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
break;
case MouseButton::MASK_XBUTTON2:
- button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]) + ")";
+ button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
break;
default:
break;
@@ -961,9 +961,9 @@ static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX] = {
};
String InputEventJoypadMotion::as_text() const {
- String desc = axis < JoyAxis::MAX ? RTR(_joy_axis_descriptions[(size_t)axis]) : TTR("Unknown Joypad Axis");
+ String desc = axis < JoyAxis::MAX ? TTRGET(_joy_axis_descriptions[(size_t)axis]) : RTR("Unknown Joypad Axis");
- return vformat(TTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
+ return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
}
String InputEventJoypadMotion::to_string() {
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index d63453e947..b97d097842 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -137,6 +137,10 @@ struct DirAccessRef {
DirAccess *f = nullptr;
DirAccessRef(DirAccess *fa) { f = fa; }
+ DirAccessRef(DirAccessRef &&other) {
+ f = other.f;
+ other.f = nullptr;
+ }
~DirAccessRef() {
if (f) {
memdelete(f);
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 5413665440..a5150010da 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -183,11 +183,15 @@ struct FileAccessRef {
operator bool() const { return f != nullptr; }
- FileAccess *f;
+ FileAccess *f = nullptr;
operator FileAccess *() { return f; }
FileAccessRef(FileAccess *fa) { f = fa; }
+ FileAccessRef(FileAccessRef &&other) {
+ f = other.f;
+ other.f = nullptr;
+ }
~FileAccessRef() {
if (f) {
memdelete(f);
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index cb38ac0928..612181f8d5 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -165,7 +165,7 @@ void FileAccessNetworkClient::_thread_func() {
}
void FileAccessNetworkClient::_thread_func(void *s) {
- FileAccessNetworkClient *self = (FileAccessNetworkClient *)s;
+ FileAccessNetworkClient *self = static_cast<FileAccessNetworkClient *>(s);
self->_thread_func();
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 6eee2f593d..d4b32df2c7 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -64,7 +64,7 @@ public:
uint64_t offset; //if offset is ZERO, the file was ERASED
uint64_t size;
uint8_t md5[16];
- PackSource *src;
+ PackSource *src = nullptr;
bool encrypted;
};
@@ -103,7 +103,7 @@ private:
Vector<PackSource *> sources;
- PackedDir *root;
+ PackedDir *root = nullptr;
static PackedData *singleton;
bool disabled = false;
@@ -139,8 +139,8 @@ public:
class PackedSourcePCK : public PackSource {
public:
- virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
- virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
+ virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
};
class FileAccessPack : public FileAccess {
@@ -150,7 +150,7 @@ class FileAccessPack : public FileAccess {
mutable bool eof;
uint64_t off;
- FileAccess *f;
+ FileAccess *f = nullptr;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 7cd5893101..a238c66437 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -67,8 +67,8 @@ public:
bool file_exists(String p_name) const;
- virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
- FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
+ virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
+ FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
static ZipArchive *get_singleton();
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 5376b78a89..fad9942017 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -378,25 +378,25 @@ Image::Image3DValidateError Image::validate_3d_image(Image::Format p_format, int
String Image::get_3d_image_validation_error_text(Image3DValidateError p_error) {
switch (p_error) {
case VALIDATE_3D_OK: {
- return TTR("Ok");
+ return "Ok";
} break;
case VALIDATE_3D_ERR_IMAGE_EMPTY: {
- return TTR("Empty Image found");
+ return "Empty Image found";
} break;
case VALIDATE_3D_ERR_MISSING_IMAGES: {
- return TTR("Missing Images");
+ return "Missing Images";
} break;
case VALIDATE_3D_ERR_EXTRA_IMAGES: {
- return TTR("Too many Images");
+ return "Too many Images";
} break;
case VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH: {
- return TTR("Image size mismatch");
+ return "Image size mismatch";
} break;
case VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH: {
- return TTR("Image format mismatch");
+ return "Image format mismatch";
} break;
case VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS: {
- return TTR("Image has included mipmaps");
+ return "Image has included mipmaps";
} break;
}
return String();
@@ -2726,6 +2726,7 @@ Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr;
Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr;
Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr;
Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr;
+Ref<Image> (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr;
void Image::_set_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("width"));
@@ -3008,7 +3009,7 @@ void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation)
}
}
-Image::UsedChannels Image::detect_used_channels(CompressSource p_source) {
+Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA);
ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA);
bool r = false, g = false, b = false, a = false, c = false;
@@ -3613,6 +3614,10 @@ Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
if (is_empty() && _jpg_mem_loader_func) {
copy_internals_from(_jpg_mem_loader_func(p_mem_png_jpg, p_len));
}
+
+ if (is_empty() && _webp_mem_loader_func) {
+ copy_internals_from(_webp_mem_loader_func(p_mem_png_jpg, p_len));
+ }
}
Ref<Resource> Image::duplicate(bool p_subresources) const {
diff --git a/core/io/image.h b/core/io/image.h
index 39c700565b..7e1e853244 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -147,6 +147,7 @@ public:
static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer);
static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels);
static Ref<Image> (*basis_universal_unpacker)(const Vector<uint8_t> &p_buffer);
+ static Ref<Image> (*basis_universal_unpacker_ptr)(const uint8_t *p_data, int p_size);
_FORCE_INLINE_ Color _get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const;
_FORCE_INLINE_ void _set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color);
@@ -379,7 +380,7 @@ public:
virtual Ref<Resource> duplicate(bool p_subresources = false) const override;
- UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC);
+ UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC) const;
void optimize_channels();
Color get_pixelv(const Point2i &p_point) const;
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 8e0d47e762..52674150bb 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -109,7 +109,7 @@ struct _IP_ResolverPrivate {
}
static void _thread_function(void *self) {
- _IP_ResolverPrivate *ipr = (_IP_ResolverPrivate *)self;
+ _IP_ResolverPrivate *ipr = static_cast<_IP_ResolverPrivate *>(self);
while (!ipr->thread_abort) {
ipr->sem.wait();
@@ -186,7 +186,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
}
IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
- ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE);
+ ERR_FAIL_INDEX_V_MSG(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE, vformat("Too many concurrent DNS resolver queries (%d, but should be %d at most). Try performing less network requests at once.", p_id, IP::RESOLVER_MAX_QUERIES));
IP::ResolverStatus res = resolver->queue[p_id].status.get();
if (res == IP::RESOLVER_STATUS_NONE) {
@@ -197,7 +197,7 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
}
IPAddress IP::get_resolve_item_address(ResolverID p_id) const {
- ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IPAddress());
+ ERR_FAIL_INDEX_V_MSG(p_id, IP::RESOLVER_MAX_QUERIES, IPAddress(), vformat("Too many concurrent DNS resolver queries (%d, but should be %d at most). Try performing less network requests at once.", p_id, IP::RESOLVER_MAX_QUERIES));
MutexLock lock(resolver->mutex);
@@ -217,7 +217,7 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const {
}
Array IP::get_resolve_item_addresses(ResolverID p_id) const {
- ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, Array());
+ ERR_FAIL_INDEX_V_MSG(p_id, IP::RESOLVER_MAX_QUERIES, Array(), vformat("Too many concurrent DNS resolver queries (%d, but should be %d at most). Try performing less network requests at once.", p_id, IP::RESOLVER_MAX_QUERIES));
MutexLock lock(resolver->mutex);
if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) {
@@ -237,7 +237,7 @@ Array IP::get_resolve_item_addresses(ResolverID p_id) const {
}
void IP::erase_resolve_item(ResolverID p_id) {
- ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES);
+ ERR_FAIL_INDEX_MSG(p_id, IP::RESOLVER_MAX_QUERIES, vformat("Too many concurrent DNS resolver queries (%d, but should be %d at most). Try performing less network requests at once.", p_id, IP::RESOLVER_MAX_QUERIES));
resolver->queue[p_id].status.set(IP::RESOLVER_STATUS_NONE);
}
diff --git a/core/io/ip.h b/core/io/ip.h
index 5602710550..06ff8a4d70 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -38,7 +38,6 @@ struct _IP_ResolverPrivate;
class IP : public Object {
GDCLASS(IP, Object);
- OBJ_CATEGORY("Networking");
public:
enum ResolverStatus {
@@ -56,14 +55,14 @@ public:
};
enum {
- RESOLVER_MAX_QUERIES = 32,
+ RESOLVER_MAX_QUERIES = 256,
RESOLVER_INVALID_ID = -1
};
typedef int ResolverID;
private:
- _IP_ResolverPrivate *resolver;
+ _IP_ResolverPrivate *resolver = nullptr;
protected:
static IP *singleton;
diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp
index 14183b472b..027fdd51aa 100644
--- a/core/io/packed_data_container.cpp
+++ b/core/io/packed_data_container.cpp
@@ -105,7 +105,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b
if (type == TYPE_ARRAY || type == TYPE_DICT) {
Ref<PackedDataContainerRef> pdcr = memnew(PackedDataContainerRef);
- Ref<PackedDataContainer> pdc = Ref<PackedDataContainer>((PackedDataContainer *)this);
+ Ref<PackedDataContainer> pdc = Ref<PackedDataContainer>(const_cast<PackedDataContainer *>(this));
pdcr->from = pdc;
pdcr->offset = p_ofs;
diff --git a/core/io/resource.h b/core/io/resource.h
index b1e1c15541..8068000f32 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -48,7 +48,6 @@ private:
class Resource : public RefCounted {
GDCLASS(Resource, RefCounted);
- OBJ_CATEGORY("Resources");
public:
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index c80c9b0ac9..5403168a53 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -127,7 +127,7 @@ class ResourceFormatSaverBinaryInstance {
bool skip_editor;
bool big_endian;
bool takeover_paths;
- FileAccess *f;
+ FileAccess *f = nullptr;
String magic;
Set<RES> resource_set;
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index 1ea44b9d06..0b7ffdf6d0 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -46,7 +46,7 @@ public:
static String get_cache_file();
private:
- void *crypto; // CryptoCore::RandomGenerator (avoid including crypto_core.h)
+ void *crypto = nullptr; // CryptoCore::RandomGenerator (avoid including crypto_core.h)
Mutex mutex;
struct Cache {
CharString cs;
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index e71941b7e1..4609e52aa2 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -39,7 +39,6 @@
class StreamPeer : public RefCounted {
GDCLASS(StreamPeer, RefCounted);
- OBJ_CATEGORY("Networking");
protected:
static void _bind_methods();
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index f2c47b25cf..bf49cc8a5f 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -38,7 +38,6 @@
class StreamPeerTCP : public StreamPeer {
GDCLASS(StreamPeerTCP, StreamPeer);
- OBJ_CATEGORY("Networking");
public:
enum Status {
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 8d3e58cad1..30df46a6b4 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -35,98 +35,160 @@
#include "core/string/translation_po.h"
RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
- enum Status {
- STATUS_NONE,
- STATUS_READING_ID,
- STATUS_READING_STRING,
- STATUS_READING_CONTEXT,
- STATUS_READING_PLURAL,
- };
-
- Status status = STATUS_NONE;
-
- String msg_id;
- String msg_str;
- String msg_context;
- Vector<String> msgs_plural;
- String config;
-
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
- Ref<TranslationPO> translation = Ref<TranslationPO>(memnew(TranslationPO));
- int line = 1;
- int plural_forms = 0;
- int plural_index = -1;
- bool entered_context = false;
- bool skip_this = false;
- bool skip_next = false;
- bool is_eof = false;
const String path = f->get_path();
+ Ref<TranslationPO> translation = Ref<TranslationPO>(memnew(TranslationPO));
+ String config;
- while (!is_eof) {
- String l = f->get_line().strip_edges();
- is_eof = f->eof_reached();
+ uint32_t magic = f->get_32();
+ if (magic == 0x950412de) {
+ // Load binary MO file.
- // If we reached last line and it's not a content line, break, otherwise let processing that last loop
- if (is_eof && l.is_empty()) {
- if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
- } else {
- break;
- }
+ uint16_t version_maj = f->get_16();
+ uint16_t version_min = f->get_16();
+ if (version_maj > 1) {
+ ERR_FAIL_V_MSG(RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
}
- if (l.begins_with("msgctxt")) {
- if (status != STATUS_READING_STRING && status != STATUS_READING_PLURAL) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
+ uint32_t num_strings = f->get_32();
+ uint32_t id_table_offset = f->get_32();
+ uint32_t trans_table_offset = f->get_32();
+
+ // Read string tables.
+ for (uint32_t i = 0; i < num_strings; i++) {
+ String msg_id;
+ String msg_id_plural;
+ String msg_context;
+
+ // Read id strings and context.
+ {
+ Vector<uint8_t> data;
+ f->seek(id_table_offset + i * 8);
+ uint32_t str_start = 0;
+ uint32_t str_len = f->get_32();
+ uint32_t str_offset = f->get_32();
+
+ data.resize(str_len + 1);
+ f->seek(str_offset);
+ f->get_buffer(data.ptrw(), str_len);
+ data.write[str_len] = 0;
+
+ bool is_plural = false;
+ for (uint32_t j = 0; j < str_len + 1; j++) {
+ if (data[j] == 0x04) {
+ msg_context.parse_utf8((const char *)data.ptr(), j);
+ str_start = j + 1;
+ }
+ if (data[j] == 0x00) {
+ if (is_plural) {
+ msg_id_plural.parse_utf8((const char *)(data.ptr() + str_start), j - str_start);
+ } else {
+ msg_id.parse_utf8((const char *)(data.ptr() + str_start), j - str_start);
+ is_plural = true;
+ }
+ str_start = j + 1;
+ }
+ }
}
- // In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
- // and set "entered_context" to true to prevent adding twice.
- if (!skip_this && !msg_id.is_empty()) {
- if (status == STATUS_READING_STRING) {
- translation->add_message(msg_id, msg_str, msg_context);
- } else if (status == STATUS_READING_PLURAL) {
- if (plural_index != plural_forms - 1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ // Read translated strings.
+ {
+ Vector<uint8_t> data;
+ f->seek(trans_table_offset + i * 8);
+ uint32_t str_len = f->get_32();
+ uint32_t str_offset = f->get_32();
+
+ data.resize(str_len + 1);
+ f->seek(str_offset);
+ f->get_buffer(data.ptrw(), str_len);
+ data.write[str_len] = 0;
+
+ if (msg_id.is_empty()) {
+ config = String::utf8((const char *)data.ptr(), str_len);
+ // Record plural rule.
+ int p_start = config.find("Plural-Forms");
+ if (p_start != -1) {
+ int p_end = config.find("\n", p_start);
+ translation->set_plural_rule(config.substr(p_start, p_end - p_start));
+ }
+ } else {
+ uint32_t str_start = 0;
+ Vector<String> plural_msg;
+ for (uint32_t j = 0; j < str_len + 1; j++) {
+ if (data[j] == 0x00) {
+ if (msg_id_plural.is_empty()) {
+ translation->add_message(msg_id, String::utf8((const char *)(data.ptr() + str_start), j - str_start), msg_context);
+ } else {
+ plural_msg.push_back(String::utf8((const char *)(data.ptr() + str_start), j - str_start));
+ }
+ str_start = j + 1;
+ }
+ }
+ if (!plural_msg.is_empty()) {
+ translation->add_plural_message(msg_id, plural_msg, msg_context);
}
- translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
- msg_context = "";
- l = l.substr(7, l.length()).strip_edges();
- status = STATUS_READING_CONTEXT;
- entered_context = true;
}
- if (l.begins_with("msgid_plural")) {
- if (plural_forms == 0) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
- } else if (status != STATUS_READING_ID) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
- }
- // We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
- // We just have to reset variables related to plurals for "msgstr[]" later on.
- l = l.substr(12, l.length()).strip_edges();
- plural_index = -1;
- msgs_plural.clear();
- msgs_plural.resize(plural_forms);
- status = STATUS_READING_PLURAL;
- } else if (l.begins_with("msgid")) {
- if (status == STATUS_READING_ID) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
+ memdelete(f);
+ } else {
+ // Try to load as text PO file.
+ f->seek(0);
+
+ enum Status {
+ STATUS_NONE,
+ STATUS_READING_ID,
+ STATUS_READING_STRING,
+ STATUS_READING_CONTEXT,
+ STATUS_READING_PLURAL,
+ };
+
+ Status status = STATUS_NONE;
+
+ String msg_id;
+ String msg_str;
+ String msg_context;
+ Vector<String> msgs_plural;
+
+ if (r_error) {
+ *r_error = ERR_FILE_CORRUPT;
+ }
+
+ int line = 1;
+ int plural_forms = 0;
+ int plural_index = -1;
+ bool entered_context = false;
+ bool skip_this = false;
+ bool skip_next = false;
+ bool is_eof = false;
+
+ while (!is_eof) {
+ String l = f->get_line().strip_edges();
+ is_eof = f->eof_reached();
+
+ // If we reached last line and it's not a content line, break, otherwise let processing that last loop
+ if (is_eof && l.is_empty()) {
+ if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
+ } else {
+ break;
+ }
}
- if (!msg_id.is_empty()) {
- if (!skip_this && !entered_context) {
+ if (l.begins_with("msgctxt")) {
+ if (status != STATUS_READING_STRING && status != STATUS_READING_PLURAL) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
+ }
+
+ // In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
+ // and set "entered_context" to true to prevent adding twice.
+ if (!skip_this && !msg_id.is_empty()) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
@@ -137,119 +199,163 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
- } else if (config.is_empty()) {
- config = msg_str;
- // Record plural rule.
- int p_start = config.find("Plural-Forms");
- if (p_start != -1) {
- int p_end = config.find("\n", p_start);
- translation->set_plural_rule(config.substr(p_start, p_end - p_start));
- plural_forms = translation->get_plural_forms();
+ msg_context = "";
+ l = l.substr(7, l.length()).strip_edges();
+ status = STATUS_READING_CONTEXT;
+ entered_context = true;
+ }
+
+ if (l.begins_with("msgid_plural")) {
+ if (plural_forms == 0) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
+ } else if (status != STATUS_READING_ID) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
+ }
+ // We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
+ // We just have to reset variables related to plurals for "msgstr[]" later on.
+ l = l.substr(12, l.length()).strip_edges();
+ plural_index = -1;
+ msgs_plural.clear();
+ msgs_plural.resize(plural_forms);
+ status = STATUS_READING_PLURAL;
+ } else if (l.begins_with("msgid")) {
+ if (status == STATUS_READING_ID) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
}
+
+ if (!msg_id.is_empty()) {
+ if (!skip_this && !entered_context) {
+ if (status == STATUS_READING_STRING) {
+ translation->add_message(msg_id, msg_str, msg_context);
+ } else if (status == STATUS_READING_PLURAL) {
+ if (plural_index != plural_forms - 1) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ }
+ translation->add_plural_message(msg_id, msgs_plural, msg_context);
+ }
+ }
+ } else if (config.is_empty()) {
+ config = msg_str;
+ // Record plural rule.
+ int p_start = config.find("Plural-Forms");
+ if (p_start != -1) {
+ int p_end = config.find("\n", p_start);
+ translation->set_plural_rule(config.substr(p_start, p_end - p_start));
+ plural_forms = translation->get_plural_forms();
+ }
+ }
+
+ l = l.substr(5, l.length()).strip_edges();
+ status = STATUS_READING_ID;
+ // If we did not encounter msgctxt, we reset context to empty to reset it.
+ if (!entered_context) {
+ msg_context = "";
+ }
+ msg_id = "";
+ msg_str = "";
+ skip_this = skip_next;
+ skip_next = false;
+ entered_context = false;
}
- l = l.substr(5, l.length()).strip_edges();
- status = STATUS_READING_ID;
- // If we did not encounter msgctxt, we reset context to empty to reset it.
- if (!entered_context) {
- msg_context = "";
+ if (l.begins_with("msgstr[")) {
+ if (status != STATUS_READING_PLURAL) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
+ }
+ plural_index++; // Increment to add to the next slot in vector msgs_plural.
+ l = l.substr(9, l.length()).strip_edges();
+ } else if (l.begins_with("msgstr")) {
+ if (status != STATUS_READING_ID) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
+ }
+
+ l = l.substr(6, l.length()).strip_edges();
+ status = STATUS_READING_STRING;
}
- msg_id = "";
- msg_str = "";
- skip_this = skip_next;
- skip_next = false;
- entered_context = false;
- }
- if (l.begins_with("msgstr[")) {
- if (status != STATUS_READING_PLURAL) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
+ if (l.is_empty() || l.begins_with("#")) {
+ if (l.contains("fuzzy")) {
+ skip_next = true;
+ }
+ line++;
+ continue; // Nothing to read or comment.
}
- plural_index++; // Increment to add to the next slot in vector msgs_plural.
- l = l.substr(9, l.length()).strip_edges();
- } else if (l.begins_with("msgstr")) {
- if (status != STATUS_READING_ID) {
+
+ if (!l.begins_with("\"") || status == STATUS_NONE) {
memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_V_MSG(RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
}
- l = l.substr(6, l.length()).strip_edges();
- status = STATUS_READING_STRING;
- }
-
- if (l.is_empty() || l.begins_with("#")) {
- if (l.contains("fuzzy")) {
- skip_next = true;
- }
- line++;
- continue; // Nothing to read or comment.
- }
+ l = l.substr(1, l.length());
+ // Find final quote, ignoring escaped ones (\").
+ // The escape_next logic is necessary to properly parse things like \\"
+ // where the backslash is the one being escaped, not the quote.
+ int end_pos = -1;
+ bool escape_next = false;
+ for (int i = 0; i < l.length(); i++) {
+ if (l[i] == '\\' && !escape_next) {
+ escape_next = true;
+ continue;
+ }
- if (!l.begins_with("\"") || status == STATUS_NONE) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
- }
+ if (l[i] == '"' && !escape_next) {
+ end_pos = i;
+ break;
+ }
- l = l.substr(1, l.length());
- // Find final quote, ignoring escaped ones (\").
- // The escape_next logic is necessary to properly parse things like \\"
- // where the backslash is the one being escaped, not the quote.
- int end_pos = -1;
- bool escape_next = false;
- for (int i = 0; i < l.length(); i++) {
- if (l[i] == '\\' && !escape_next) {
- escape_next = true;
- continue;
+ escape_next = false;
}
- if (l[i] == '"' && !escape_next) {
- end_pos = i;
- break;
+ if (end_pos == -1) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
}
- escape_next = false;
- }
+ l = l.substr(0, end_pos);
+ l = l.c_unescape();
- if (end_pos == -1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
- }
+ if (status == STATUS_READING_ID) {
+ msg_id += l;
+ } else if (status == STATUS_READING_STRING) {
+ msg_str += l;
+ } else if (status == STATUS_READING_CONTEXT) {
+ msg_context += l;
+ } else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
+ if (plural_index >= plural_forms) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
+ }
+ msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
+ }
- l = l.substr(0, end_pos);
- l = l.c_unescape();
-
- if (status == STATUS_READING_ID) {
- msg_id += l;
- } else if (status == STATUS_READING_STRING) {
- msg_str += l;
- } else if (status == STATUS_READING_CONTEXT) {
- msg_context += l;
- } else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
- msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
+ line++;
}
- line++;
- }
-
- memdelete(f);
+ memdelete(f);
- // Add the last set of data from last iteration.
- if (status == STATUS_READING_STRING) {
- if (!msg_id.is_empty()) {
- if (!skip_this) {
- translation->add_message(msg_id, msg_str, msg_context);
+ // Add the last set of data from last iteration.
+ if (status == STATUS_READING_STRING) {
+ if (!msg_id.is_empty()) {
+ if (!skip_this) {
+ translation->add_message(msg_id, msg_str, msg_context);
+ }
+ } else if (config.is_empty()) {
+ config = msg_str;
}
- } else if (config.is_empty()) {
- config = msg_str;
- }
- } else if (status == STATUS_READING_PLURAL) {
- if (!skip_this && !msg_id.is_empty()) {
- if (plural_index != plural_forms - 1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ } else if (status == STATUS_READING_PLURAL) {
+ if (!skip_this && !msg_id.is_empty()) {
+ if (plural_index != plural_forms - 1) {
+ memdelete(f);
+ ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ }
+ translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
- translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -290,6 +396,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String &p_original_pat
void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("po");
+ p_extensions->push_back("mo");
}
bool TranslationLoaderPO::handles_type(const String &p_type) const {
@@ -297,7 +404,7 @@ bool TranslationLoaderPO::handles_type(const String &p_type) const {
}
String TranslationLoaderPO::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "po") {
+ if (p_path.get_extension().to_lower() == "po" || p_path.get_extension().to_lower() == "mo") {
return "Translation";
}
return "";
diff --git a/core/io/udp_server.h b/core/io/udp_server.h
index 4a7546fddf..47f06b2490 100644
--- a/core/io/udp_server.h
+++ b/core/io/udp_server.h
@@ -43,7 +43,7 @@ protected:
};
struct Peer {
- PacketPeerUDP *peer;
+ PacketPeerUDP *peer = nullptr;
IPAddress ip;
uint16_t port = 0;
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 14057b96be..4212b43621 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -33,7 +33,7 @@
#include "core/math/geometry_3d.h"
#include "core/object/script_language.h"
-int AStar::get_available_point_id() const {
+int AStar3D::get_available_point_id() const {
if (points.has(last_free_id)) {
int cur_new_id = last_free_id + 1;
while (points.has(cur_new_id)) {
@@ -45,7 +45,7 @@ int AStar::get_available_point_id() const {
return last_free_id;
}
-void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
+void AStar3D::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
ERR_FAIL_COND_MSG(p_id < 0, vformat("Can't add a point with negative id: %d.", p_id));
ERR_FAIL_COND_MSG(p_weight_scale < 1, vformat("Can't add a point with weight scale less than one: %f.", p_weight_scale));
@@ -68,7 +68,7 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
}
}
-Vector3 AStar::get_point_position(int p_id) const {
+Vector3 AStar3D::get_point_position(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
@@ -76,7 +76,7 @@ Vector3 AStar::get_point_position(int p_id) const {
return p->pos;
}
-void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
+void AStar3D::set_point_position(int p_id, const Vector3 &p_pos) {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
@@ -84,7 +84,7 @@ void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
p->pos = p_pos;
}
-real_t AStar::get_point_weight_scale(int p_id) const {
+real_t AStar3D::get_point_weight_scale(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
@@ -92,7 +92,7 @@ real_t AStar::get_point_weight_scale(int p_id) const {
return p->weight_scale;
}
-void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
+void AStar3D::set_point_weight_scale(int p_id, real_t p_weight_scale) {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
@@ -101,7 +101,7 @@ void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
p->weight_scale = p_weight_scale;
}
-void AStar::remove_point(int p_id) {
+void AStar3D::remove_point(int p_id) {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
@@ -127,7 +127,7 @@ void AStar::remove_point(int p_id) {
last_free_id = p_id;
}
-void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
+void AStar3D::connect_points(int p_id, int p_with_id, bool bidirectional) {
ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
Point *a;
@@ -165,7 +165,7 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
segments.insert(s);
}
-void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) {
+void AStar3D::disconnect_points(int p_id, int p_with_id, bool bidirectional) {
Point *a;
bool a_exists = points.lookup(p_id, a);
ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
@@ -205,11 +205,11 @@ void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) {
}
}
-bool AStar::has_point(int p_id) const {
+bool AStar3D::has_point(int p_id) const {
return points.has(p_id);
}
-Array AStar::get_point_ids() {
+Array AStar3D::get_point_ids() {
Array point_list;
for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
@@ -219,7 +219,7 @@ Array AStar::get_point_ids() {
return point_list;
}
-Vector<int> AStar::get_point_connections(int p_id) {
+Vector<int> AStar3D::get_point_connections(int p_id) {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector<int>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
@@ -233,7 +233,7 @@ Vector<int> AStar::get_point_connections(int p_id) {
return point_list;
}
-bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) const {
+bool AStar3D::are_points_connected(int p_id, int p_with_id, bool bidirectional) const {
Segment s(p_id, p_with_id);
const Set<Segment>::Element *element = segments.find(s);
@@ -241,7 +241,7 @@ bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) co
(bidirectional || (element->get().direction & s.direction) == s.direction);
}
-void AStar::clear() {
+void AStar3D::clear() {
last_free_id = 0;
for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) {
memdelete(*(it.value));
@@ -250,21 +250,21 @@ void AStar::clear() {
points.clear();
}
-int AStar::get_point_count() const {
+int AStar3D::get_point_count() const {
return points.get_num_elements();
}
-int AStar::get_point_capacity() const {
+int AStar3D::get_point_capacity() const {
return points.get_capacity();
}
-void AStar::reserve_space(int p_num_nodes) {
+void AStar3D::reserve_space(int p_num_nodes) {
ERR_FAIL_COND_MSG(p_num_nodes <= 0, vformat("New capacity must be greater than 0, new was: %d.", p_num_nodes));
ERR_FAIL_COND_MSG((uint32_t)p_num_nodes < points.get_capacity(), vformat("New capacity must be greater than current capacity: %d, new was: %d.", points.get_capacity(), p_num_nodes));
points.reserve(p_num_nodes);
}
-int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) const {
+int AStar3D::get_closest_point(const Vector3 &p_point, bool p_include_disabled) const {
int closest_id = -1;
real_t closest_dist = 1e20;
@@ -289,7 +289,7 @@ int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) co
return closest_id;
}
-Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
+Vector3 AStar3D::get_closest_position_in_segment(const Vector3 &p_point) const {
real_t closest_dist = 1e20;
Vector3 closest_point;
@@ -318,7 +318,7 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
return closest_point;
}
-bool AStar::_solve(Point *begin_point, Point *end_point) {
+bool AStar3D::_solve(Point *begin_point, Point *end_point) {
pass++;
if (!end_point->enabled) {
@@ -380,7 +380,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
return found_route;
}
-real_t AStar::_estimate_cost(int p_from_id, int p_to_id) {
+real_t AStar3D::_estimate_cost(int p_from_id, int p_to_id) {
real_t scost;
if (GDVIRTUAL_CALL(_estimate_cost, p_from_id, p_to_id, scost)) {
return scost;
@@ -397,7 +397,7 @@ real_t AStar::_estimate_cost(int p_from_id, int p_to_id) {
return from_point->pos.distance_to(to_point->pos);
}
-real_t AStar::_compute_cost(int p_from_id, int p_to_id) {
+real_t AStar3D::_compute_cost(int p_from_id, int p_to_id) {
real_t scost;
if (GDVIRTUAL_CALL(_compute_cost, p_from_id, p_to_id, scost)) {
return scost;
@@ -414,7 +414,7 @@ real_t AStar::_compute_cost(int p_from_id, int p_to_id) {
return from_point->pos.distance_to(to_point->pos);
}
-Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
+Vector<Vector3> AStar3D::get_point_path(int p_from_id, int p_to_id) {
Point *a;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
@@ -463,7 +463,7 @@ Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
return path;
}
-Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
+Vector<int> AStar3D::get_id_path(int p_from_id, int p_to_id) {
Point *a;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
@@ -512,7 +512,7 @@ Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
return path;
}
-void AStar::set_point_disabled(int p_id, bool p_disabled) {
+void AStar3D::set_point_disabled(int p_id, bool p_disabled) {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -520,7 +520,7 @@ void AStar::set_point_disabled(int p_id, bool p_disabled) {
p->enabled = !p_disabled;
}
-bool AStar::is_point_disabled(int p_id) const {
+bool AStar3D::is_point_disabled(int p_id) const {
Point *p;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -528,41 +528,41 @@ bool AStar::is_point_disabled(int p_id) const {
return !p->enabled;
}
-void AStar::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar::get_available_point_id);
- ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar::add_point, DEFVAL(1.0));
- ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar::get_point_position);
- ClassDB::bind_method(D_METHOD("set_point_position", "id", "position"), &AStar::set_point_position);
- ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar::get_point_weight_scale);
- ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar::set_point_weight_scale);
- ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point);
- ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point);
- ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections);
- ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar::get_point_ids);
+void AStar3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar3D::get_available_point_id);
+ ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar3D::add_point, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar3D::get_point_position);
+ ClassDB::bind_method(D_METHOD("set_point_position", "id", "position"), &AStar3D::set_point_position);
+ ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar3D::get_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar3D::set_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar3D::remove_point);
+ ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar3D::has_point);
+ ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar3D::get_point_connections);
+ ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar3D::get_point_ids);
- ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar::set_point_disabled, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled);
+ ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar3D::set_point_disabled, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar3D::is_point_disabled);
- ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id", "bidirectional"), &AStar::disconnect_points, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id", "bidirectional"), &AStar::are_points_connected, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar3D::connect_points, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id", "bidirectional"), &AStar3D::disconnect_points, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id", "bidirectional"), &AStar3D::are_points_connected, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("get_point_count"), &AStar::get_point_count);
- ClassDB::bind_method(D_METHOD("get_point_capacity"), &AStar::get_point_capacity);
- ClassDB::bind_method(D_METHOD("reserve_space", "num_nodes"), &AStar::reserve_space);
- ClassDB::bind_method(D_METHOD("clear"), &AStar::clear);
+ ClassDB::bind_method(D_METHOD("get_point_count"), &AStar3D::get_point_count);
+ ClassDB::bind_method(D_METHOD("get_point_capacity"), &AStar3D::get_point_capacity);
+ ClassDB::bind_method(D_METHOD("reserve_space", "num_nodes"), &AStar3D::reserve_space);
+ ClassDB::bind_method(D_METHOD("clear"), &AStar3D::clear);
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_position", "include_disabled"), &AStar::get_closest_point, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar::get_closest_position_in_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_position", "include_disabled"), &AStar3D::get_closest_point, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar3D::get_closest_position_in_segment);
- ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
- ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar::get_id_path);
+ ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar3D::get_point_path);
+ ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar3D::get_id_path);
GDVIRTUAL_BIND(_estimate_cost, "from_id", "to_id")
GDVIRTUAL_BIND(_compute_cost, "from_id", "to_id")
}
-AStar::~AStar() {
+AStar3D::~AStar3D() {
clear();
}
@@ -660,11 +660,11 @@ real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) {
return scost;
}
- AStar::Point *from_point;
+ AStar3D::Point *from_point;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
- AStar::Point *to_point;
+ AStar3D::Point *to_point;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
@@ -677,11 +677,11 @@ real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) {
return scost;
}
- AStar::Point *from_point;
+ AStar3D::Point *from_point;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
- AStar::Point *to_point;
+ AStar3D::Point *to_point;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
@@ -689,11 +689,11 @@ real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) {
}
Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
- AStar::Point *a;
+ AStar3D::Point *a;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
- AStar::Point *b;
+ AStar3D::Point *b;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
@@ -702,15 +702,15 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
return ret;
}
- AStar::Point *begin_point = a;
- AStar::Point *end_point = b;
+ AStar3D::Point *begin_point = a;
+ AStar3D::Point *end_point = b;
bool found_route = _solve(begin_point, end_point);
if (!found_route) {
return Vector<Vector2>();
}
- AStar::Point *p = end_point;
+ AStar3D::Point *p = end_point;
int pc = 1; // Begin point
while (p != begin_point) {
pc++;
@@ -723,7 +723,7 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
{
Vector2 *w = path.ptrw();
- AStar::Point *p2 = end_point;
+ AStar3D::Point *p2 = end_point;
int idx = pc - 1;
while (p2 != begin_point) {
w[idx--] = Vector2(p2->pos.x, p2->pos.y);
@@ -737,11 +737,11 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) {
}
Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) {
- AStar::Point *a;
+ AStar3D::Point *a;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
- AStar::Point *b;
+ AStar3D::Point *b;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
@@ -751,15 +751,15 @@ Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) {
return ret;
}
- AStar::Point *begin_point = a;
- AStar::Point *end_point = b;
+ AStar3D::Point *begin_point = a;
+ AStar3D::Point *end_point = b;
bool found_route = _solve(begin_point, end_point);
if (!found_route) {
return Vector<int>();
}
- AStar::Point *p = end_point;
+ AStar3D::Point *p = end_point;
int pc = 1; // Begin point
while (p != begin_point) {
pc++;
@@ -785,7 +785,7 @@ Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) {
return path;
}
-bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) {
+bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point) {
astar.pass++;
if (!end_point->enabled) {
@@ -794,15 +794,15 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) {
bool found_route = false;
- Vector<AStar::Point *> open_list;
- SortArray<AStar::Point *, AStar::SortPoints> sorter;
+ Vector<AStar3D::Point *> open_list;
+ SortArray<AStar3D::Point *, AStar3D::SortPoints> sorter;
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
open_list.push_back(begin_point);
while (!open_list.is_empty()) {
- AStar::Point *p = open_list[0]; // The currently processed point
+ AStar3D::Point *p = open_list[0]; // The currently processed point
if (p == end_point) {
found_route = true;
@@ -813,8 +813,8 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) {
open_list.remove_at(open_list.size() - 1);
p->closed_pass = astar.pass; // Mark the point as closed
- for (OAHashMap<int, AStar::Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
- AStar::Point *e = *(it.value); // The neighbour point
+ for (OAHashMap<int, AStar3D::Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
+ AStar3D::Point *e = *(it.value); // The neighbour point
if (!e->enabled || e->closed_pass == astar.pass) {
continue;
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 130c202a61..bb7112fb09 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -40,8 +40,8 @@
A* pathfinding algorithm.
*/
-class AStar : public RefCounted {
- GDCLASS(AStar, RefCounted);
+class AStar3D : public RefCounted {
+ GDCLASS(AStar3D, RefCounted);
friend class AStar2D;
struct Point {
@@ -156,15 +156,15 @@ public:
Vector<Vector3> get_point_path(int p_from_id, int p_to_id);
Vector<int> get_id_path(int p_from_id, int p_to_id);
- AStar() {}
- ~AStar();
+ AStar3D() {}
+ ~AStar3D();
};
class AStar2D : public RefCounted {
GDCLASS(AStar2D, RefCounted);
- AStar astar;
+ AStar3D astar;
- bool _solve(AStar::Point *begin_point, AStar::Point *end_point);
+ bool _solve(AStar3D::Point *begin_point, AStar3D::Point *end_point);
protected:
static void _bind_methods();
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 84f9d12bb1..eb6703aff2 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -1002,7 +1002,7 @@ void Basis::rotate_sh(real_t *p_values) {
const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv;
const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv;
- real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] };
+ const real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] };
real_t m00 = elements[0][0];
real_t m01 = elements[0][1];
diff --git a/core/math/bvh.h b/core/math/bvh.h
index e686e27445..9f6ab9f736 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -196,6 +196,7 @@ public:
////////////////////////////////////////////////////
void move(BVHHandle p_handle, const BOUNDS &p_aabb) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
if (tree.item_move(p_handle, p_aabb)) {
if (USE_PAIRS) {
@@ -205,10 +206,12 @@ public:
}
void recheck_pairs(BVHHandle p_handle) {
+ DEV_ASSERT(!p_handle.is_invalid());
force_collision_check(p_handle);
}
void erase(BVHHandle p_handle) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
// call unpair and remove all references to the item
// before deleting from the tree
@@ -225,6 +228,7 @@ public:
// set pairable has never been called.
// (deferred collision checks are a workaround for visual server for historical reasons)
void force_collision_check(BVHHandle p_handle) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
if (USE_PAIRS) {
// the aabb should already be up to date in the BVH
@@ -243,6 +247,7 @@ public:
// but generically this makes items add or remove from the
// tree internally, to speed things up by ignoring inactive items
bool activate(BVHHandle p_handle, const BOUNDS &p_aabb, bool p_delay_collision_check = false) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
// sending the aabb here prevents the need for the BVH to maintain
// a redundant copy of the aabb.
@@ -267,6 +272,7 @@ public:
}
bool deactivate(BVHHandle p_handle) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
// returns success
if (tree.item_deactivate(p_handle)) {
@@ -285,6 +291,7 @@ public:
}
bool get_active(BVHHandle p_handle) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
return tree.item_get_active(p_handle);
}
@@ -307,6 +314,7 @@ public:
// prefer calling this directly as type safe
void set_tree(const BVHHandle &p_handle, uint32_t p_tree_id, uint32_t p_tree_collision_mask, bool p_force_collision_check = true) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVH_LOCKED_FUNCTION
// Returns true if the pairing state has changed.
bool state_changed = tree.item_set_tree(p_handle, p_tree_id, p_tree_collision_mask);
@@ -465,13 +473,6 @@ private:
continue;
}
-#ifdef BVH_CHECKS
- // if neither are pairable, they should ignore each other
- // THIS SHOULD NEVER HAPPEN .. now we only test the pairable tree
- // if the changed item is not pairable
- CRASH_COND(params.test_pairable_only && !tree._extra[ref_id].pairable);
-#endif
-
// checkmasks is already done in the cull routine.
BVHHandle h_collidee;
h_collidee.set_id(ref_id);
@@ -485,6 +486,7 @@ private:
public:
void item_get_AABB(BVHHandle p_handle, BOUNDS &r_aabb) {
+ DEV_ASSERT(!p_handle.is_invalid());
BVHABB_CLASS abb;
tree.item_get_ABB(p_handle, abb);
abb.to(r_aabb);
@@ -761,19 +763,19 @@ private:
tree._extra[p_handle.id()].last_updated_tick = 0;
}
- PairCallback pair_callback;
- UnpairCallback unpair_callback;
- CheckPairCallback check_pair_callback;
- void *pair_callback_userdata;
- void *unpair_callback_userdata;
- void *check_pair_callback_userdata;
+ PairCallback pair_callback = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ CheckPairCallback check_pair_callback = nullptr;
+ void *pair_callback_userdata = nullptr;
+ void *unpair_callback_userdata = nullptr;
+ void *check_pair_callback_userdata = nullptr;
BVHTREE_CLASS tree;
// for collision pairing,
// maintain a list of all items moved etc on each frame / tick
LocalVector<BVHHandle, uint32_t, true> changed_items;
- uint32_t _tick;
+ uint32_t _tick = 1; // Start from 1 so items with 0 indicate never updated.
class BVHLockedFunction {
public:
@@ -799,23 +801,16 @@ private:
}
private:
- Mutex *_mutex;
+ Mutex *_mutex = nullptr;
};
Mutex _mutex;
// local toggle for turning on and off thread safety in project settings
- bool _thread_safe;
+ bool _thread_safe = BVH_THREAD_SAFE;
public:
- BVH_Manager() {
- _tick = 1; // start from 1 so items with 0 indicate never updated
- pair_callback = nullptr;
- unpair_callback = nullptr;
- pair_callback_userdata = nullptr;
- unpair_callback_userdata = nullptr;
- _thread_safe = BVH_THREAD_SAFE;
- }
+ BVH_Manager() {}
};
#undef BVHTREE_CLASS
diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc
index b0d9ae3615..58c8f0479a 100644
--- a/core/math/bvh_structs.inc
+++ b/core/math/bvh_structs.inc
@@ -60,11 +60,23 @@ private:
public:
// accessors
- BVHABB_CLASS &get_aabb(uint32_t p_id) { return aabbs[p_id]; }
- const BVHABB_CLASS &get_aabb(uint32_t p_id) const { return aabbs[p_id]; }
+ BVHABB_CLASS &get_aabb(uint32_t p_id) {
+ BVH_ASSERT(p_id < MAX_ITEMS);
+ return aabbs[p_id];
+ }
+ const BVHABB_CLASS &get_aabb(uint32_t p_id) const {
+ BVH_ASSERT(p_id < MAX_ITEMS);
+ return aabbs[p_id];
+ }
- uint32_t &get_item_ref_id(uint32_t p_id) { return item_ref_ids[p_id]; }
- const uint32_t &get_item_ref_id(uint32_t p_id) const { return item_ref_ids[p_id]; }
+ uint32_t &get_item_ref_id(uint32_t p_id) {
+ BVH_ASSERT(p_id < MAX_ITEMS);
+ return item_ref_ids[p_id];
+ }
+ const uint32_t &get_item_ref_id(uint32_t p_id) const {
+ BVH_ASSERT(p_id < MAX_ITEMS);
+ return item_ref_ids[p_id];
+ }
bool is_dirty() const { return dirty; }
void set_dirty(bool p) { dirty = p; }
diff --git a/core/math/bvh_tree.h b/core/math/bvh_tree.h
index da9b307778..cdb2bb4413 100644
--- a/core/math/bvh_tree.h
+++ b/core/math/bvh_tree.h
@@ -54,7 +54,7 @@
#define BVH_EXPAND_LEAF_AABBS
// never do these checks in release
-#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED)
+#ifdef DEV_ENABLED
//#define BVH_VERBOSE
//#define BVH_VERBOSE_TREE
//#define BVH_VERBOSE_PAIRING
@@ -217,7 +217,7 @@ private:
BVH_ASSERT(!parent.is_leaf());
int child_num = parent.find_child(p_old_child_id);
- BVH_ASSERT(child_num != BVHCommon::INVALID);
+ BVH_ASSERT(child_num != -1);
parent.children[child_num] = p_new_child_id;
TNode &new_child = _nodes[p_new_child_id];
@@ -229,7 +229,7 @@ private:
BVH_ASSERT(!parent.is_leaf());
int child_num = parent.find_child(p_child_id);
- BVH_ASSERT(child_num != BVHCommon::INVALID);
+ BVH_ASSERT(child_num != -1);
parent.remove_child_internal(child_num);
diff --git a/core/math/expression.h b/core/math/expression.h
index 9b87bdd6ec..d43cc4091a 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -147,7 +147,7 @@ private:
bool is_op = false;
union {
Variant::Operator op;
- ENode *node;
+ ENode *node = nullptr;
};
};
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 5bc1bc25e6..fb92f6b0df 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -208,7 +208,7 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const {
/** TEST ALL EDGES **/
- Vector3 edge_norms[3] = {
+ const Vector3 edge_norms[3] = {
vertex[0] - vertex[1],
vertex[1] - vertex[2],
vertex[2] - vertex[0],
diff --git a/core/math/face3.h b/core/math/face3.h
index c61d6ad66e..23260336fa 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -133,7 +133,7 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const {
#undef TEST_AXIS
- Vector3 edge_norms[3] = {
+ const Vector3 edge_norms[3] = {
vertex[0] - vertex[1],
vertex[1] - vertex[2],
vertex[2] - vertex[0],
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 44340b97ae..b741277872 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -473,16 +473,16 @@ public:
uint32_t x = ci.ui;
uint32_t sign = (unsigned short)(x >> 31);
uint32_t mantissa;
- uint32_t exp;
+ uint32_t exponent;
uint16_t hf;
// get mantissa
mantissa = x & ((1 << 23) - 1);
// get exponent bits
- exp = x & (0xFF << 23);
- if (exp >= 0x47800000) {
+ exponent = x & (0xFF << 23);
+ if (exponent >= 0x47800000) {
// check if the original single precision float number is a NaN
- if (mantissa && (exp == (0xFF << 23))) {
+ if (mantissa && (exponent == (0xFF << 23))) {
// we have a single precision NaN
mantissa = (1 << 23) - 1;
} else {
@@ -493,17 +493,18 @@ public:
(uint16_t)(mantissa >> 13);
}
// check if exponent is <= -15
- else if (exp <= 0x38000000) {
- /*// store a denorm half-float value or zero
- exp = (0x38000000 - exp) >> 23;
- mantissa >>= (14 + exp);
-
- hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa);
- */
+ else if (exponent <= 0x38000000) {
+ /*
+ // store a denorm half-float value or zero
+ exponent = (0x38000000 - exponent) >> 23;
+ mantissa >>= (14 + exponent);
+
+ hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa);
+ */
hf = 0; //denormals do not work for 3D, convert to zero
} else {
hf = (((uint16_t)sign) << 15) |
- (uint16_t)((exp - 0x38000000) >> 13) |
+ (uint16_t)((exponent - 0x38000000) >> 13) |
(uint16_t)(mantissa >> 13);
}
diff --git a/core/math/octree.h b/core/math/octree.h
index e73f8213b3..65ab9e2292 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -134,7 +134,7 @@ private:
List<PairData *, AL> pair_list;
struct OctantOwner {
- Octant *octant;
+ Octant *octant = nullptr;
typename List<Element *, AL>::Element *E;
}; // an element can be in max 8 octants
@@ -147,7 +147,7 @@ private:
int refcount;
bool intersect;
Element *A, *B;
- void *ud;
+ void *ud = nullptr;
typename List<PairData *, AL>::Element *eA, *eB;
};
@@ -156,18 +156,18 @@ private:
ElementMap element_map;
PairMap pair_map;
- PairCallback pair_callback;
- UnpairCallback unpair_callback;
- void *pair_callback_userdata;
- void *unpair_callback_userdata;
+ PairCallback pair_callback = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ void *pair_callback_userdata = nullptr;
+ void *unpair_callback_userdata = nullptr;
- OctreeElementID last_element_id;
- uint64_t pass;
+ OctreeElementID last_element_id = 1;
+ uint64_t pass = 1;
- real_t unit_size;
- Octant *root;
- int octant_count;
- int pair_count;
+ real_t unit_size = 1.0;
+ Octant *root = nullptr;
+ int octant_count = 0;
+ int pair_count = 0;
_FORCE_INLINE_ void _pair_check(PairData *p_pair) {
bool intersect = p_pair->A->aabb.intersects_inclusive(p_pair->B->aabb);
@@ -294,7 +294,7 @@ private:
const Vector3 *points;
int point_count;
T **result_array;
- int *result_idx;
+ int *result_idx = nullptr;
int result_max;
uint32_t mask;
};
@@ -1265,18 +1265,7 @@ void Octree<T, use_pairs, AL>::set_unpair_callback(UnpairCallback p_callback, vo
template <class T, bool use_pairs, class AL>
Octree<T, use_pairs, AL>::Octree(real_t p_unit_size) {
- last_element_id = 1;
- pass = 1;
unit_size = p_unit_size;
- root = nullptr;
-
- octant_count = 0;
- pair_count = 0;
-
- pair_callback = nullptr;
- unpair_callback = nullptr;
- pair_callback_userdata = nullptr;
- unpair_callback_userdata = nullptr;
}
#endif // OCTREE_H
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index 3cd9ad3819..577d4b9fbd 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -38,7 +38,7 @@
#include "core/variant/callable.h"
class CallableCustomMethodPointerBase : public CallableCustom {
- uint32_t *comp_ptr;
+ uint32_t *comp_ptr = nullptr;
uint32_t comp_size;
uint32_t h;
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index e09c6cb97c..fd86a02b90 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1485,9 +1485,10 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
if (p_object_core) {
mi.flags |= METHOD_FLAG_OBJECT_CORE;
}
- if (p_arg_names.size()) {
+
+ if (!p_object_core) {
if (p_arg_names.size() != mi.arguments.size()) {
- WARN_PRINT("Mismatch argument name count for virtual function: " + String(p_class) + "::" + p_method.name);
+ WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name);
} else {
for (int i = 0; i < p_arg_names.size(); i++) {
mi.arguments[i].name = p_arg_names[i];
@@ -1495,6 +1496,10 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
}
}
+ if (classes[p_class].virtual_methods_map.has(p_method.name)) {
+ // overloading not supported
+ ERR_FAIL_MSG("Virtual method already bound '" + String(p_class) + "::" + p_method.name + "'.");
+ }
classes[p_class].virtual_methods.push_back(mi);
classes[p_class].virtual_methods_map[p_method.name] = mi;
@@ -1551,15 +1556,6 @@ bool ClassDB::is_class_exposed(const StringName &p_class) {
return ti->exposed;
}
-StringName ClassDB::get_category(const StringName &p_node) {
- ERR_FAIL_COND_V(!classes.has(p_node), StringName());
-#ifdef DEBUG_ENABLED
- return classes[p_node].category;
-#else
- return StringName();
-#endif
-}
-
void ClassDB::add_resource_base_extension(const StringName &p_extension, const StringName &p_class) {
if (resource_base_extensions.has(p_extension)) {
return;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 32e4bf7644..5da8523743 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -85,8 +85,8 @@ public:
int index;
StringName setter;
StringName getter;
- MethodBind *_setptr;
- MethodBind *_getptr;
+ MethodBind *_setptr = nullptr;
+ MethodBind *_getptr = nullptr;
Variant::Type type;
};
@@ -109,7 +109,6 @@ public:
Set<StringName> methods_in_properties;
List<MethodInfo> virtual_methods;
Map<StringName, MethodInfo> virtual_methods_map;
- StringName category;
Map<StringName, Vector<Error>> method_error_values;
#endif
HashMap<StringName, PropertySetGet> property_setget;
@@ -227,75 +226,27 @@ public:
static uint64_t get_api_hash(APIType p_api);
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method) {
- MethodBind *bind = create_method_bind(p_method);
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, nullptr, 0); //use static function, much smaller binary usage
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[1] = { &p_def1 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[2] = { &p_def1, &p_def2 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
- }
-
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7) {
+ template <class N, class M, typename... VarArgs>
+ static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[7] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 7);
+ return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M>
- static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7, const Variant &p_def8) {
- MethodBind *bind = create_method_bind(p_method);
- const Variant *ptr[8] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7, &p_def8 };
-
- return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 8);
+ template <class N, class M, typename... VarArgs>
+ static MethodBind *bind_static_method(const StringName &p_class, N p_method_name, M p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ MethodBind *bind = create_static_method_bind(p_method);
+ bind->set_instance_class(p_class);
+ return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
template <class M>
@@ -379,8 +330,6 @@ public:
static Vector<Error> get_method_error_return_values(const StringName &p_class, const StringName &p_method);
static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid = nullptr);
- static StringName get_category(const StringName &p_node);
-
static void set_class_enabled(const StringName &p_class, bool p_enable);
static bool is_class_enabled(const StringName &p_class);
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 64ee5940b0..c18d70d9f6 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -28,7 +28,7 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
}\\
\\
if (required) {\\
- ERR_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\
+ ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");\\
$RVOID\\
}\\
\\
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index eaab01d0aa..2219cdb8f6 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -62,10 +62,10 @@ class MessageQueue {
};
};
- uint8_t *buffer;
+ uint8_t *buffer = nullptr;
uint32_t buffer_end = 0;
uint32_t buffer_max_used = 0;
- uint32_t buffer_size;
+ uint32_t buffer_size = 0;
void _call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error);
diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp
index 32269b5f19..a79adb7c6c 100644
--- a/core/object/method_bind.cpp
+++ b/core/object/method_bind.cpp
@@ -83,6 +83,10 @@ void MethodBind::_set_const(bool p_const) {
_const = p_const;
}
+void MethodBind::_set_static(bool p_static) {
+ _static = p_static;
+}
+
void MethodBind::_set_returns(bool p_returns) {
_returns = p_returns;
}
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 02b73fa273..bde6cba199 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -60,6 +60,7 @@ class MethodBind {
int default_argument_count = 0;
int argument_count = 0;
+ bool _static = false;
bool _const = false;
bool _returns = false;
@@ -69,6 +70,7 @@ protected:
Vector<StringName> arg_names;
#endif
void _set_const(bool p_const);
+ void _set_static(bool p_static);
void _set_returns(bool p_returns);
virtual Variant::Type _gen_argument_type(int p_arg) const = 0;
virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0;
@@ -116,7 +118,7 @@ public:
#endif
void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; }
- uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); }
+ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0) | (is_static() ? METHOD_FLAG_STATIC : 0); }
_FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
_FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; }
@@ -129,6 +131,7 @@ public:
void set_name(const StringName &p_name);
_FORCE_INLINE_ int get_method_id() const { return method_id; }
_FORCE_INLINE_ bool is_const() const { return _const; }
+ _FORCE_INLINE_ bool is_static() const { return _static; }
_FORCE_INLINE_ bool has_return() const { return _returns; }
virtual bool is_vararg() const { return false; }
@@ -140,21 +143,20 @@ public:
virtual ~MethodBind();
};
-template <class T>
-class MethodBindVarArg : public MethodBind {
-public:
- typedef Variant (T::*NativeCall)(const Variant **, int, Callable::CallError &);
-
+// MethodBindVarArg base CRTP
+template <class Derived, class T, class R, bool should_returns>
+class MethodBindVarArgBase : public MethodBind {
protected:
- NativeCall call_method = nullptr;
- MethodInfo arguments;
+ R(T::*method)
+ (const Variant **, int, Callable::CallError &);
+ MethodInfo method_info;
public:
virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
if (p_arg < 0) {
- return arguments.return_val;
- } else if (p_arg < arguments.arguments.size()) {
- return arguments.arguments[p_arg];
+ return _gen_return_type_info();
+ } else if (p_arg < method_info.arguments.size()) {
+ return method_info.arguments[p_arg];
} else {
return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
@@ -170,24 +172,31 @@ public:
}
#endif
- virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- T *instance = static_cast<T *>(p_object);
- return (instance->*call_method)(p_args, p_arg_count, r_error);
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
+ ERR_FAIL(); // Can't call.
}
- void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) {
- set_argument_count(p_info.arguments.size());
- Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1);
- at[0] = p_info.return_val.type;
- if (p_info.arguments.size()) {
+ virtual bool is_const() const { return false; }
+
+ virtual bool is_vararg() const { return true; }
+
+ MethodBindVarArgBase(
+ R (T::*p_method)(const Variant **, int, Callable::CallError &),
+ const MethodInfo &p_method_info,
+ bool p_return_nil_is_variant) :
+ method(p_method), method_info(p_method_info) {
+ set_argument_count(method_info.arguments.size());
+ Variant::Type *at = memnew_arr(Variant::Type, method_info.arguments.size() + 1);
+ at[0] = _gen_return_type_info().type;
+ if (method_info.arguments.size()) {
#ifdef DEBUG_METHODS_ENABLED
Vector<StringName> names;
- names.resize(p_info.arguments.size());
+ names.resize(method_info.arguments.size());
#endif
- for (int i = 0; i < p_info.arguments.size(); i++) {
- at[i + 1] = p_info.arguments[i].type;
+ for (int i = 0; i < method_info.arguments.size(); i++) {
+ at[i + 1] = method_info.arguments[i].type;
#ifdef DEBUG_METHODS_ENABLED
- names.write[i] = p_info.arguments[i].name;
+ names.write[i] = method_info.arguments[i].name;
#endif
}
@@ -196,31 +205,76 @@ public:
#endif
}
argument_types = at;
- arguments = p_info;
if (p_return_nil_is_variant) {
- arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
}
+
+ _set_returns(should_returns);
}
- virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
- ERR_FAIL(); // Can't call.
+private:
+ PropertyInfo _gen_return_type_info() const {
+ return Derived::_gen_return_type_info_impl();
}
+};
- void set_method(NativeCall p_method) { call_method = p_method; }
- virtual bool is_const() const { return false; }
+// variadic, no return
+template <class T>
+class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
+ friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
- virtual bool is_vararg() const { return true; }
+public:
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error);
+ return {};
+ }
- MethodBindVarArg() {
- _set_returns(true);
+ MethodBindVarArgT(
+ void (T::*p_method)(const Variant **, int, Callable::CallError &),
+ const MethodInfo &p_method_info,
+ bool p_return_nil_is_variant) :
+ MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) {
+ }
+
+private:
+ static PropertyInfo _gen_return_type_info_impl() {
+ return {};
}
};
template <class T>
-MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
- MethodBindVarArg<T> *a = memnew((MethodBindVarArg<T>));
- a->set_method(p_method);
- a->set_method_info(p_info, p_return_nil_is_variant);
+MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
+ MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
+ a->set_instance_class(T::get_class_static());
+ return a;
+}
+
+// variadic, return
+template <class T, class R>
+class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
+ friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
+
+public:
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error);
+ }
+
+ MethodBindVarArgTR(
+ R (T::*p_method)(const Variant **, int, Callable::CallError &),
+ const MethodInfo &p_info,
+ bool p_return_nil_is_variant) :
+ MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) {
+ }
+
+private:
+ static PropertyInfo _gen_return_type_info_impl() {
+ return GetTypeInfo<R>::get_class_info();
+ }
+};
+
+template <class T, class R>
+MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
+ MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
return a;
}
@@ -308,7 +362,7 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
return a;
}
-// no return, not const
+// no return, const
#ifdef TYPED_METHOD_BIND
template <class T, class... P>
@@ -558,4 +612,139 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
return a;
}
+/* STATIC BINDS */
+
+// no return
+
+template <class... P>
+class MethodBindTS : public MethodBind {
+ void (*function)(P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+ virtual Variant::Type _gen_argument_type(int p_arg) const {
+ if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+ return call_get_argument_type<P...>(p_arg);
+ } else {
+ return Variant::NIL;
+ }
+ }
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+ virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
+ PropertyInfo pi;
+ call_get_argument_type_info<P...>(p_arg, pi);
+ return pi;
+ }
+
+public:
+#ifdef DEBUG_METHODS_ENABLED
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ return call_get_argument_metadata<P...>(p_arg);
+ }
+
+#endif
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ (void)p_object; // unused
+ call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
+ return Variant();
+ }
+
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
+ (void)p_object;
+ (void)r_ret;
+ call_with_ptr_args_static_method(function, p_args);
+ }
+
+ MethodBindTS(void (*p_function)(P...)) {
+ function = p_function;
+ _generate_argument_types(sizeof...(P));
+ set_argument_count(sizeof...(P));
+ _set_static(true);
+ }
+};
+
+template <class... P>
+MethodBind *create_static_method_bind(void (*p_method)(P...)) {
+ MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
+ return a;
+}
+
+// return
+
+template <class R, class... P>
+class MethodBindTRS : public MethodBind {
+ R(*function)
+ (P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+ virtual Variant::Type _gen_argument_type(int p_arg) const {
+ if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+ return call_get_argument_type<P...>(p_arg);
+ } else {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+ }
+ }
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+ virtual PropertyInfo _gen_argument_type_info(int p_arg) const {
+ if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+ PropertyInfo pi;
+ call_get_argument_type_info<P...>(p_arg, pi);
+ return pi;
+ } else {
+ return GetTypeInfo<R>::get_class_info();
+ }
+ }
+
+public:
+#ifdef DEBUG_METHODS_ENABLED
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ if (p_arg >= 0) {
+ return call_get_argument_metadata<P...>(p_arg);
+ } else {
+ return GetTypeInfo<R>::METADATA;
+ }
+ }
+
+#endif
+ virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ Variant ret;
+ call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
+ return ret;
+ }
+
+ virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
+ (void)p_object;
+ call_with_ptr_args_static_method_ret(function, p_args, r_ret);
+ }
+
+ MethodBindTRS(R (*p_function)(P...)) {
+ function = p_function;
+ _generate_argument_types(sizeof...(P));
+ set_argument_count(sizeof...(P));
+ _set_static(true);
+ _set_returns(true);
+ }
+};
+
+template <class R, class... P>
+MethodBind *create_static_method_bind(R (*p_method)(P...)) {
+ MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
+ return a;
+}
+
#endif // METHOD_BIND_H
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 096edd4e60..c2cd42ff91 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -416,12 +416,22 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
return;
- } else if (p_name == CoreStringNames::get_singleton()->_meta) {
- metadata = p_value.duplicate();
- if (r_valid) {
- *r_valid = true;
+ } else {
+ OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name);
+ if (E) {
+ E->get() = p_value;
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return;
+ } else if (p_name.operator String().begins_with("metadata/")) {
+ // Must exist, otherwise duplicate() will not work.
+ set_meta(p_name.operator String().replace_first("metadata/", ""), p_value);
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return;
}
- return;
}
// Something inside the object... :|
@@ -496,9 +506,12 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
*r_valid = true;
}
return ret;
+ }
+
+ const OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name);
- } else if (p_name == CoreStringNames::get_singleton()->_meta) {
- ret = metadata;
+ if (E) {
+ ret = E->get();
if (r_valid) {
*r_valid = true;
}
@@ -648,13 +661,20 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
- if (!metadata.is_empty()) {
- p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
- }
+
if (script_instance && !p_reversed) {
p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
script_instance->get_property_list(p_list);
}
+
+ for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
+ PropertyInfo pi = PropertyInfo(K.value().get_type(), "metadata/" + K.key().operator String());
+ if (K.value().get_type() == Variant::OBJECT) {
+ pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string = "Resource";
+ }
+ p_list->push_back(pi);
+ }
}
void Object::_validate_property(PropertyInfo &property) const {
@@ -845,7 +865,9 @@ String Object::to_string() {
}
}
if (_extension && _extension->to_string) {
- return _extension->to_string(_extension_instance);
+ String ret;
+ _extension->to_string(_extension_instance, &ret);
+ return ret;
}
return "[" + get_class() + ":" + itos(get_instance_id()) + "]";
}
@@ -915,20 +937,38 @@ bool Object::has_meta(const StringName &p_name) const {
void Object::set_meta(const StringName &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
- metadata.erase(p_name);
+ if (metadata.has(p_name)) {
+ metadata.erase(p_name);
+ metadata_properties.erase("metadata/" + p_name.operator String());
+ notify_property_list_changed();
+ }
return;
}
- metadata[p_name] = p_value;
+ OrderedHashMap<StringName, Variant>::Element E = metadata.find(p_name);
+ if (E) {
+ E.value() = p_value;
+ } else {
+ ERR_FAIL_COND(!p_name.operator String().is_valid_identifier());
+ E = metadata.insert(p_name, p_value);
+ metadata_properties["metadata/" + p_name.operator String()] = E;
+ notify_property_list_changed();
+ }
}
-Variant Object::get_meta(const StringName &p_name) const {
- ERR_FAIL_COND_V_MSG(!metadata.has(p_name), Variant(), "The object does not have any 'meta' values with the key '" + p_name + "'.");
+Variant Object::get_meta(const StringName &p_name, const Variant &p_default) const {
+ if (!metadata.has(p_name)) {
+ if (p_default != Variant()) {
+ return p_default;
+ } else {
+ ERR_FAIL_V_MSG(Variant(), "The object does not have any 'meta' values with the key '" + p_name + "'.");
+ }
+ }
return metadata[p_name];
}
void Object::remove_meta(const StringName &p_name) {
- metadata.erase(p_name);
+ set_meta(p_name, Variant());
}
Array Object::_get_property_list_bind() const {
@@ -954,20 +994,16 @@ Array Object::_get_method_list_bind() const {
Vector<StringName> Object::_get_meta_list_bind() const {
Vector<StringName> _metaret;
- List<Variant> keys;
- metadata.get_key_list(&keys);
- for (const Variant &E : keys) {
- _metaret.push_back(E);
+ for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
+ _metaret.push_back(K.key());
}
return _metaret;
}
void Object::get_meta_list(List<StringName> *p_list) const {
- List<Variant> keys;
- metadata.get_key_list(&keys);
- for (const Variant &E : keys) {
- p_list->push_back(E);
+ for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
+ p_list->push_back(K.key());
}
}
@@ -992,15 +1028,15 @@ struct _ObjectSignalDisconnectData {
Callable callable;
};
-Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Error Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- ERR_FAIL_COND_V(p_argcount < 1, Variant());
+ ERR_FAIL_COND_V(p_argcount < 1, Error::ERR_INVALID_PARAMETER);
if (p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::STRING_NAME;
- ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING, Variant());
+ ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING, Error::ERR_INVALID_PARAMETER);
}
r_error.error = Callable::CallError::CALL_OK;
@@ -1014,9 +1050,7 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::C
args = &p_args[1];
}
- emit_signalp(signal, args, argc);
-
- return Variant();
+ return emit_signalp(signal, args, argc);
}
Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount) {
@@ -1529,7 +1563,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_meta", "name", "value"), &Object::set_meta);
ClassDB::bind_method(D_METHOD("remove_meta", "name"), &Object::remove_meta);
- ClassDB::bind_method(D_METHOD("get_meta", "name"), &Object::get_meta);
+ ClassDB::bind_method(D_METHOD("get_meta", "name", "default"), &Object::get_meta, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("has_meta", "name"), &Object::has_meta);
ClassDB::bind_method(D_METHOD("get_meta_list"), &Object::_get_meta_list_bind);
diff --git a/core/object/object.h b/core/object/object.h
index 6b4f1c81e6..eeef03dcb9 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -39,6 +39,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
+#include "core/templates/ordered_hash_map.h"
#include "core/templates/safe_refcount.h"
#include "core/templates/set.h"
#include "core/templates/vmap.h"
@@ -343,16 +344,6 @@ public:
m_inherits::get_inheritance_list_static(p_inheritance_list); \
p_inheritance_list->push_back(String(#m_class)); \
} \
- static String get_category_static() { \
- String category = m_inherits::get_category_static(); \
- if (_get_category != m_inherits::_get_category) { \
- if (!category.is_empty()) { \
- category += "/"; \
- } \
- category += _get_category(); \
- } \
- return category; \
- } \
virtual bool is_class(const String &p_class) const override { \
if (_get_extension() && _get_extension()->is_class(p_class)) { \
return true; \
@@ -453,12 +444,6 @@ protected:
\
private:
-#define OBJ_CATEGORY(m_category) \
-protected: \
- _FORCE_INLINE_ static String _get_category() { return m_category; } \
- \
-private:
-
#define OBJ_SAVE_TYPE(m_class) \
public: \
virtual String get_save_class() const override { return #m_class; } \
@@ -530,13 +515,14 @@ private:
#endif
ScriptInstance *script_instance = nullptr;
Variant script; // Reference does not exist yet, store it in a Variant.
- Dictionary metadata;
+ OrderedHashMap<StringName, Variant> metadata;
+ HashMap<StringName, OrderedHashMap<StringName, Variant>::Element> metadata_properties;
mutable StringName _class_name;
mutable const StringName *_class_ptr = nullptr;
void _add_user_signal(const String &p_name, const Array &p_args = Array());
bool _has_user_signal(const StringName &p_name) const;
- Variant _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Error _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Array _get_signal_list() const;
Array _get_signal_connection_list(const String &p_signal) const;
Array _get_incoming_connections() const;
@@ -552,8 +538,8 @@ private:
std::mutex _instance_binding_mutex;
struct InstanceBinding {
- void *binding;
- void *token;
+ void *binding = nullptr;
+ void *token = nullptr;
GDNativeInstanceBindingFreeCallback free_callback = nullptr;
GDNativeInstanceBindingReferenceCallback reference_callback = nullptr;
};
@@ -588,7 +574,6 @@ protected:
virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {};
virtual void _notificationv(int p_notification, bool p_reversed) {}
- static String _get_category() { return ""; }
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_property) { return false; };
bool _get(const StringName &p_name, Variant &r_property) const { return false; };
@@ -692,7 +677,6 @@ public:
static String get_class_static() { return "Object"; }
static String get_parent_class_static() { return String(); }
- static String get_category_static() { return String(); }
virtual String get_class() const {
if (_extension) {
@@ -761,7 +745,7 @@ public:
bool has_meta(const StringName &p_name) const;
void set_meta(const StringName &p_name, const Variant &p_value);
void remove_meta(const StringName &p_name);
- Variant get_meta(const StringName &p_name) const;
+ Variant get_meta(const StringName &p_name, const Variant &p_default = Variant()) const;
void get_meta_list(List<StringName> *p_list) const;
#ifdef TOOLS_ENABLED
@@ -865,7 +849,7 @@ class ObjectDB {
uint64_t validator : OBJECTDB_VALIDATOR_BITS;
uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
uint64_t is_ref_counted : 1;
- Object *object;
+ Object *object = nullptr;
};
static SpinLock spin_lock;
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 8eb1c97cce..dcacf19890 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -261,7 +261,7 @@ struct PtrToArg<Ref<T>> {
typedef Ref<T> EncodeT;
_FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
- *(Ref<RefCounted> *)p_ptr = p_val;
+ *(const_cast<Ref<RefCounted> *>(reinterpret_cast<const Ref<RefCounted> *>(p_ptr))) = p_val;
}
};
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 11440c37fe..a5d25bf533 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -144,7 +144,7 @@ void ScriptServer::register_language(ScriptLanguage *p_language) {
_languages[_language_count++] = p_language;
}
-void ScriptServer::unregister_language(ScriptLanguage *p_language) {
+void ScriptServer::unregister_language(const ScriptLanguage *p_language) {
for (int i = 0; i < _language_count; i++) {
if (_languages[i] == p_language) {
_language_count--;
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 2122f785b6..69002c81f4 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -68,7 +68,7 @@ public:
_FORCE_INLINE_ static int get_language_count() { return _language_count; }
static ScriptLanguage *get_language(int p_idx);
static void register_language(ScriptLanguage *p_language);
- static void unregister_language(ScriptLanguage *p_language);
+ static void unregister_language(const ScriptLanguage *p_language);
static void set_reload_scripts_on_save(bool p_enable);
static bool is_reload_scripts_on_save_enabled();
@@ -132,7 +132,7 @@ public:
virtual Error reload(bool p_keep_state = false) = 0;
#ifdef TOOLS_ENABLED
- virtual const Vector<DocData::ClassDoc> &get_documentation() const = 0;
+ virtual Vector<DocData::ClassDoc> get_documentation() const = 0;
#endif // TOOLS_ENABLED
virtual bool has_method(const StringName &p_method) const = 0;
@@ -212,44 +212,12 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid);
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const = 0;
+ virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const { return get_script()->get_rpc_methods(); }
virtual ScriptLanguage *get_language() = 0;
virtual ~ScriptInstance();
};
-struct ScriptCodeCompletionOption {
- /* Keep enum in Sync with: */
- /* /scene/gui/code_edit.h - CodeEdit::CodeCompletionKind */
- enum Kind {
- KIND_CLASS,
- KIND_FUNCTION,
- KIND_SIGNAL,
- KIND_VARIABLE,
- KIND_MEMBER,
- KIND_ENUM,
- KIND_CONSTANT,
- KIND_NODE_PATH,
- KIND_FILE_PATH,
- KIND_PLAIN_TEXT,
- };
- Kind kind = KIND_PLAIN_TEXT;
- String display;
- String insert_text;
- Color font_color;
- RES icon;
- Variant default_value;
- Vector<Pair<int, int>> matches;
-
- ScriptCodeCompletionOption() {}
-
- ScriptCodeCompletionOption(const String &p_text, Kind p_kind) {
- display = p_text;
- insert_text = p_text;
- kind = p_kind;
- }
-};
-
class ScriptCodeCompletionCache {
static ScriptCodeCompletionCache *singleton;
@@ -261,7 +229,8 @@ public:
virtual ~ScriptCodeCompletionCache() {}
};
-class ScriptLanguage {
+class ScriptLanguage : public Object {
+ GDCLASS(ScriptLanguage, Object)
public:
virtual String get_name() const = 0;
@@ -326,19 +295,64 @@ public:
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual bool overrides_external_editor() { return false; }
- virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
+ /* Keep enum in Sync with: */
+ /* /scene/gui/code_edit.h - CodeEdit::CodeCompletionKind */
+ enum CodeCompletionKind {
+ CODE_COMPLETION_KIND_CLASS,
+ CODE_COMPLETION_KIND_FUNCTION,
+ CODE_COMPLETION_KIND_SIGNAL,
+ CODE_COMPLETION_KIND_VARIABLE,
+ CODE_COMPLETION_KIND_MEMBER,
+ CODE_COMPLETION_KIND_ENUM,
+ CODE_COMPLETION_KIND_CONSTANT,
+ CODE_COMPLETION_KIND_NODE_PATH,
+ CODE_COMPLETION_KIND_FILE_PATH,
+ CODE_COMPLETION_KIND_PLAIN_TEXT,
+ CODE_COMPLETION_KIND_MAX
+ };
+
+ enum CodeCompletionLocation {
+ LOCATION_LOCAL = 0,
+ LOCATION_PARENT_MASK = 1 << 8,
+ LOCATION_OTHER_USER_CODE = 1 << 9,
+ LOCATION_OTHER = 1 << 10,
+ };
+
+ struct CodeCompletionOption {
+ CodeCompletionKind kind = CODE_COMPLETION_KIND_PLAIN_TEXT;
+ String display;
+ String insert_text;
+ Color font_color;
+ RES icon;
+ Variant default_value;
+ Vector<Pair<int, int>> matches;
+ int location = LOCATION_OTHER;
+
+ CodeCompletionOption() {}
+
+ CodeCompletionOption(const String &p_text, CodeCompletionKind p_kind, int p_location = LOCATION_OTHER) {
+ display = p_text;
+ insert_text = p_text;
+ kind = p_kind;
+ location = p_location;
+ }
+ };
+
+ 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) { return ERR_UNAVAILABLE; }
+
+ enum LookupResultType {
+ LOOKUP_RESULT_SCRIPT_LOCATION,
+ LOOKUP_RESULT_CLASS,
+ LOOKUP_RESULT_CLASS_CONSTANT,
+ LOOKUP_RESULT_CLASS_PROPERTY,
+ LOOKUP_RESULT_CLASS_METHOD,
+ LOOKUP_RESULT_CLASS_ENUM,
+ LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE,
+ LOOKUP_RESULT_MAX
+ };
struct LookupResult {
- enum Type {
- RESULT_SCRIPT_LOCATION,
- RESULT_CLASS,
- RESULT_CLASS_CONSTANT,
- RESULT_CLASS_PROPERTY,
- RESULT_CLASS_METHOD,
- RESULT_CLASS_ENUM,
- RESULT_CLASS_TBD_GLOBALSCOPE
- };
- Type type;
+ LookupResultType type;
Ref<Script> script;
String class_name;
String class_member;
@@ -416,42 +430,42 @@ public:
extern uint8_t script_encryption_key[32];
class PlaceHolderScriptInstance : public ScriptInstance {
- Object *owner;
+ Object *owner = nullptr;
List<PropertyInfo> properties;
Map<StringName, Variant> values;
Map<StringName, Variant> constants;
- ScriptLanguage *language;
+ ScriptLanguage *language = nullptr;
Ref<Script> script;
public:
- virtual bool set(const StringName &p_name, const Variant &p_value);
- virtual bool get(const StringName &p_name, Variant &r_ret) const;
- virtual void get_property_list(List<PropertyInfo> *p_properties) const;
- virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const;
+ virtual bool set(const StringName &p_name, const Variant &p_value) override;
+ virtual bool get(const StringName &p_name, Variant &r_ret) const override;
+ virtual void get_property_list(List<PropertyInfo> *p_properties) const override;
+ virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override;
- virtual void get_method_list(List<MethodInfo> *p_list) const;
- virtual bool has_method(const StringName &p_method) const;
+ virtual void get_method_list(List<MethodInfo> *p_list) const override;
+ virtual bool has_method(const StringName &p_method) const override;
- virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
- virtual void notification(int p_notification) {}
+ virtual void notification(int p_notification) override {}
- virtual Ref<Script> get_script() const { return script; }
+ virtual Ref<Script> get_script() const override { return script; }
- virtual ScriptLanguage *get_language() { return language; }
+ virtual ScriptLanguage *get_language() override { return language; }
- Object *get_owner() { return owner; }
+ Object *get_owner() override { return owner; }
void update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values); //likely changed in editor
- virtual bool is_placeholder() const { return true; }
+ virtual bool is_placeholder() const override { return true; }
- virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr);
- virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr);
+ virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr) override;
+ virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr) override;
- virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const { return Vector<Multiplayer::RPCConfig>(); }
+ virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override { return Vector<Multiplayer::RPCConfig>(); }
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
~PlaceHolderScriptInstance();
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
new file mode 100644
index 0000000000..21d7685674
--- /dev/null
+++ b/core/object/script_language_extension.cpp
@@ -0,0 +1,180 @@
+/*************************************************************************/
+/* script_language_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "script_language_extension.h"
+
+void ScriptExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_editor_can_reload_from_file);
+ GDVIRTUAL_BIND(_placeholder_erased, "placeholder");
+
+ GDVIRTUAL_BIND(_can_instantiate);
+ GDVIRTUAL_BIND(_get_base_script);
+ GDVIRTUAL_BIND(_inherits_script, "script");
+
+ GDVIRTUAL_BIND(_get_instance_base_type);
+ GDVIRTUAL_BIND(_instance_create, "for_object");
+ GDVIRTUAL_BIND(_placeholder_instance_create, "for_object");
+
+ GDVIRTUAL_BIND(_instance_has, "object");
+
+ GDVIRTUAL_BIND(_has_source_code);
+ GDVIRTUAL_BIND(_get_source_code);
+
+ GDVIRTUAL_BIND(_set_source_code, "code");
+ GDVIRTUAL_BIND(_reload, "keep_state");
+
+ GDVIRTUAL_BIND(_get_documentation);
+
+ GDVIRTUAL_BIND(_has_method, "method");
+ GDVIRTUAL_BIND(_get_method_info, "method");
+
+ GDVIRTUAL_BIND(_is_tool);
+ GDVIRTUAL_BIND(_is_valid);
+ GDVIRTUAL_BIND(_get_language);
+
+ GDVIRTUAL_BIND(_has_script_signal, "signal");
+ GDVIRTUAL_BIND(_get_script_signal_list);
+
+ GDVIRTUAL_BIND(_get_property_default_value, "property");
+
+ GDVIRTUAL_BIND(_update_exports);
+ GDVIRTUAL_BIND(_get_script_method_list);
+ GDVIRTUAL_BIND(_get_script_property_list);
+
+ GDVIRTUAL_BIND(_get_member_line, "member");
+
+ GDVIRTUAL_BIND(_get_constants);
+ GDVIRTUAL_BIND(_get_members);
+ GDVIRTUAL_BIND(_is_placeholder_fallback_enabled);
+
+ GDVIRTUAL_BIND(_get_rpc_methods);
+}
+
+void ScriptLanguageExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_init);
+ GDVIRTUAL_BIND(_get_type);
+ GDVIRTUAL_BIND(_get_extension);
+ GDVIRTUAL_BIND(_execute_file, "path");
+ GDVIRTUAL_BIND(_finish);
+
+ GDVIRTUAL_BIND(_get_reserved_words);
+ GDVIRTUAL_BIND(_is_control_flow_keyword, "keyword");
+ GDVIRTUAL_BIND(_get_comment_delimiters);
+ GDVIRTUAL_BIND(_get_string_delimiters);
+ GDVIRTUAL_BIND(_make_template, "template", "class_name", "base_class_name");
+ GDVIRTUAL_BIND(_get_built_in_templates, "object");
+ GDVIRTUAL_BIND(_is_using_templates);
+ GDVIRTUAL_BIND(_validate, "script", "path", "validate_functions", "validate_errors", "validate_warnings", "validate_safe_lines");
+
+ GDVIRTUAL_BIND(_validate_path, "path");
+ GDVIRTUAL_BIND(_create_script);
+ GDVIRTUAL_BIND(_has_named_classes);
+ GDVIRTUAL_BIND(_supports_builtin_mode);
+ GDVIRTUAL_BIND(_supports_documentation);
+ GDVIRTUAL_BIND(_can_inherit_from_file);
+ GDVIRTUAL_BIND(_find_function, "class_name", "function_name");
+ GDVIRTUAL_BIND(_make_function, "class_name", "function_name", "function_args");
+ GDVIRTUAL_BIND(_open_in_external_editor, "script", "line", "column");
+ GDVIRTUAL_BIND(_overrides_external_editor);
+
+ GDVIRTUAL_BIND(_complete_code, "code", "path", "owner");
+ GDVIRTUAL_BIND(_lookup_code, "code", "symbol", "path", "owner");
+ GDVIRTUAL_BIND(_auto_indent_code, "code", "from_line", "to_line");
+
+ GDVIRTUAL_BIND(_add_global_constant, "name", "value");
+ GDVIRTUAL_BIND(_add_named_global_constant, "name", "value");
+ GDVIRTUAL_BIND(_remove_named_global_constant, "name");
+
+ GDVIRTUAL_BIND(_thread_enter);
+ GDVIRTUAL_BIND(_thread_exit);
+ GDVIRTUAL_BIND(_debug_get_error);
+ GDVIRTUAL_BIND(_debug_get_stack_level_count);
+
+ GDVIRTUAL_BIND(_debug_get_stack_level_line, "level");
+ GDVIRTUAL_BIND(_debug_get_stack_level_function, "level");
+ GDVIRTUAL_BIND(_debug_get_stack_level_locals, "level", "max_subitems", "max_depth");
+ GDVIRTUAL_BIND(_debug_get_stack_level_members, "level", "max_subitems", "max_depth");
+ GDVIRTUAL_BIND(_debug_get_stack_level_instance, "level");
+ GDVIRTUAL_BIND(_debug_get_globals, "max_subitems", "max_depth");
+ GDVIRTUAL_BIND(_debug_parse_stack_level_expression, "level", "expression", "max_subitems", "max_depth");
+
+ GDVIRTUAL_BIND(_debug_get_current_stack_info);
+
+ GDVIRTUAL_BIND(_reload_all_scripts);
+ GDVIRTUAL_BIND(_reload_tool_script, "script", "soft_reload");
+
+ GDVIRTUAL_BIND(_get_recognized_extensions);
+ GDVIRTUAL_BIND(_get_public_functions);
+ GDVIRTUAL_BIND(_get_public_constants);
+
+ GDVIRTUAL_BIND(_profiling_start);
+ GDVIRTUAL_BIND(_profiling_stop);
+
+ GDVIRTUAL_BIND(_profiling_get_accumulated_data, "info_array", "info_max");
+ GDVIRTUAL_BIND(_profiling_get_frame_data, "info_array", "info_max");
+
+ GDVIRTUAL_BIND(_alloc_instance_binding_data, "object");
+ GDVIRTUAL_BIND(_free_instance_binding_data, "data");
+
+ GDVIRTUAL_BIND(_refcount_incremented_instance_binding, "object");
+ GDVIRTUAL_BIND(_refcount_decremented_instance_binding, "object");
+
+ GDVIRTUAL_BIND(_frame);
+
+ GDVIRTUAL_BIND(_handles_global_class_type, "type");
+ GDVIRTUAL_BIND(_get_global_class_name, "path");
+
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_SCRIPT_LOCATION);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_CONSTANT);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_PROPERTY);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_METHOD);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ENUM);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX);
+
+ BIND_ENUM_CONSTANT(LOCATION_LOCAL);
+ BIND_ENUM_CONSTANT(LOCATION_PARENT_MASK);
+ BIND_ENUM_CONSTANT(LOCATION_OTHER_USER_CODE);
+ BIND_ENUM_CONSTANT(LOCATION_OTHER);
+
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_CLASS);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_FUNCTION);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_SIGNAL);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_VARIABLE);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_MEMBER);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_ENUM);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_CONSTANT);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_NODE_PATH);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_FILE_PATH);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_PLAIN_TEXT);
+ BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_MAX);
+}
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
new file mode 100644
index 0000000000..40f18ab30d
--- /dev/null
+++ b/core/object/script_language_extension.h
@@ -0,0 +1,835 @@
+/*************************************************************************/
+/* script_language_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SCRIPT_LANGUAGE_EXTENSION_H
+#define SCRIPT_LANGUAGE_EXTENSION_H
+
+#include "core/extension/ext_wrappers.gen.inc"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+#include "core/variant/typed_array.h"
+
+class ScriptExtension : public Script {
+ GDCLASS(ScriptExtension, Script)
+
+protected:
+ EXBIND0R(bool, editor_can_reload_from_file)
+
+ GDVIRTUAL1(_placeholder_erased, GDNativePtr<void>)
+ virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override {
+ GDVIRTUAL_CALL(_placeholder_erased, p_placeholder);
+ }
+
+ static void _bind_methods();
+
+public:
+ EXBIND0RC(bool, can_instantiate)
+ EXBIND0RC(Ref<Script>, get_base_script)
+ EXBIND1RC(bool, inherits_script, const Ref<Script> &)
+ EXBIND0RC(StringName, get_instance_base_type)
+
+ GDVIRTUAL1RC(GDNativePtr<void>, _instance_create, Object *)
+ virtual ScriptInstance *instance_create(Object *p_this) override {
+ GDNativePtr<void> ret = nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_instance_create, p_this, ret);
+ return reinterpret_cast<ScriptInstance *>(ret.operator void *());
+ }
+ GDVIRTUAL1RC(GDNativePtr<void>, _placeholder_instance_create, Object *)
+ PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override {
+ GDNativePtr<void> ret = nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_placeholder_instance_create, p_this, ret);
+ return reinterpret_cast<PlaceHolderScriptInstance *>(ret.operator void *());
+ }
+
+ EXBIND1RC(bool, instance_has, const Object *)
+ EXBIND0RC(bool, has_source_code)
+ EXBIND0RC(String, get_source_code)
+ EXBIND1(set_source_code, const String &)
+ EXBIND1R(Error, reload, bool)
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_documentation)
+#ifdef TOOLS_ENABLED
+ virtual Vector<DocData::ClassDoc> get_documentation() const override {
+ TypedArray<Dictionary> doc;
+ GDVIRTUAL_REQUIRED_CALL(_get_documentation, doc);
+
+ Vector<DocData::ClassDoc> class_doc;
+#ifndef _MSC_VER
+#warning missing conversion from documentation to ClassDoc
+#endif
+ return class_doc;
+ }
+#endif // TOOLS_ENABLED
+
+ EXBIND1RC(bool, has_method, const StringName &)
+
+ GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
+ virtual MethodInfo get_method_info(const StringName &p_method) const override {
+ Dictionary mi;
+ GDVIRTUAL_REQUIRED_CALL(_get_method_info, p_method, mi);
+ return MethodInfo::from_dict(mi);
+ }
+
+ EXBIND0RC(bool, is_tool)
+ EXBIND0RC(bool, is_valid)
+
+ EXBIND0RC(ScriptLanguage *, get_language)
+ EXBIND1RC(bool, has_script_signal, const StringName &)
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_signal_list)
+
+ virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override {
+ TypedArray<Dictionary> sl;
+ GDVIRTUAL_REQUIRED_CALL(_get_script_signal_list, sl);
+ for (int i = 0; i < sl.size(); i++) {
+ r_signals->push_back(MethodInfo::from_dict(sl[i]));
+ }
+ }
+
+ GDVIRTUAL1RC(bool, _has_property_default_value, const StringName &)
+ GDVIRTUAL1RC(Variant, _get_property_default_value, const StringName &)
+
+ virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const override {
+ bool has_dv = false;
+ if (!GDVIRTUAL_REQUIRED_CALL(_has_property_default_value, p_property, has_dv) || !has_dv) {
+ return false;
+ }
+ Variant ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_property_default_value, p_property, ret);
+ return ret;
+ }
+
+ EXBIND0(update_exports)
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_method_list)
+
+ virtual void get_script_method_list(List<MethodInfo> *r_methods) const override {
+ TypedArray<Dictionary> sl;
+ GDVIRTUAL_REQUIRED_CALL(_get_script_method_list, sl);
+ for (int i = 0; i < sl.size(); i++) {
+ r_methods->push_back(MethodInfo::from_dict(sl[i]));
+ }
+ }
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_property_list)
+
+ virtual void get_script_property_list(List<PropertyInfo> *r_propertys) const override {
+ TypedArray<Dictionary> sl;
+ GDVIRTUAL_REQUIRED_CALL(_get_script_property_list, sl);
+ for (int i = 0; i < sl.size(); i++) {
+ r_propertys->push_back(PropertyInfo::from_dict(sl[i]));
+ }
+ }
+
+ EXBIND1RC(int, get_member_line, const StringName &)
+
+ GDVIRTUAL0RC(Dictionary, _get_constants)
+
+ virtual void get_constants(Map<StringName, Variant> *p_constants) override {
+ Dictionary constants;
+ GDVIRTUAL_REQUIRED_CALL(_get_constants, constants);
+ List<Variant> keys;
+ constants.get_key_list(&keys);
+ for (const Variant &K : keys) {
+ p_constants->insert(K, constants[K]);
+ }
+ }
+ GDVIRTUAL0RC(TypedArray<StringName>, _get_members)
+ virtual void get_members(Set<StringName> *p_members) override {
+ TypedArray<StringName> members;
+ GDVIRTUAL_REQUIRED_CALL(_get_members, members);
+ for (int i = 0; i < members.size(); i++) {
+ p_members->insert(members[i]);
+ }
+ }
+
+ EXBIND0RC(bool, is_placeholder_fallback_enabled)
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_rpc_methods)
+
+ virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override {
+ TypedArray<Dictionary> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_rpc_methods, ret);
+ Vector<Multiplayer::RPCConfig> rpcret;
+ for (int i = 0; i < ret.size(); i++) {
+ Dictionary d = ret[i];
+ Multiplayer::RPCConfig rpc;
+ ERR_CONTINUE(!d.has("name"));
+ rpc.name = d["name"];
+ ERR_CONTINUE(!d.has("rpc_mode"));
+ rpc.rpc_mode = Multiplayer::RPCMode(int(d["rpc_mode"]));
+ ERR_CONTINUE(!d.has("call_local"));
+ rpc.call_local = d["call_local"];
+ ERR_CONTINUE(!d.has("transfer_mode"));
+ rpc.transfer_mode = Multiplayer::TransferMode(int(d["transfer_mode"]));
+ ERR_CONTINUE(!d.has("channel"));
+ rpc.channel = d["channel"];
+ rpcret.push_back(rpc);
+ }
+ return rpcret;
+ }
+
+ ScriptExtension() {}
+};
+
+typedef ScriptLanguage::ProfilingInfo ScriptLanguageExtensionProfilingInfo;
+
+GDVIRTUAL_NATIVE_PTR(ScriptLanguageExtensionProfilingInfo)
+
+class ScriptLanguageExtension : public ScriptLanguage {
+ GDCLASS(ScriptLanguageExtension, ScriptLanguage)
+protected:
+ static void _bind_methods();
+
+public:
+ EXBIND0RC(String, get_name)
+
+ EXBIND0(init)
+ EXBIND0RC(String, get_type)
+ EXBIND0RC(String, get_extension)
+ EXBIND1R(Error, execute_file, const String &)
+ EXBIND0(finish)
+
+ /* EDITOR FUNCTIONS */
+
+ GDVIRTUAL0RC(Vector<String>, _get_reserved_words)
+
+ virtual void get_reserved_words(List<String> *p_words) const override {
+ Vector<String> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_reserved_words, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_words->push_back(ret[i]);
+ }
+ }
+ EXBIND1RC(bool, is_control_flow_keyword, String)
+
+ GDVIRTUAL0RC(Vector<String>, _get_comment_delimiters)
+
+ virtual void get_comment_delimiters(List<String> *p_words) const override {
+ Vector<String> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_comment_delimiters, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_words->push_back(ret[i]);
+ }
+ }
+
+ GDVIRTUAL0RC(Vector<String>, _get_string_delimiters)
+
+ virtual void get_string_delimiters(List<String> *p_words) const override {
+ Vector<String> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_string_delimiters, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_words->push_back(ret[i]);
+ }
+ }
+
+ EXBIND3RC(Ref<Script>, make_template, const String &, const String &, const String &)
+
+ GDVIRTUAL1RC(TypedArray<Dictionary>, _get_built_in_templates, StringName)
+
+ virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override {
+ TypedArray<Dictionary> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_built_in_templates, p_object, ret);
+ Vector<ScriptTemplate> stret;
+ for (int i = 0; i < ret.size(); i++) {
+ Dictionary d = ret[i];
+ ScriptTemplate st;
+ ERR_CONTINUE(!d.has("inherit"));
+ st.inherit = d["inherit"];
+ ERR_CONTINUE(!d.has("name"));
+ st.name = d["name"];
+ ERR_CONTINUE(!d.has("description"));
+ st.description = d["description"];
+ ERR_CONTINUE(!d.has("content"));
+ st.content = d["content"];
+ ERR_CONTINUE(!d.has("id"));
+ st.id = d["id"];
+ ERR_CONTINUE(!d.has("origin"));
+ st.origin = TemplateLocation(int(d["origin"]));
+ stret.push_back(st);
+ }
+ return stret;
+ }
+
+ EXBIND0R(bool, is_using_templates)
+
+ GDVIRTUAL6RC(Dictionary, _validate, const String &, const String &, bool, bool, bool, bool)
+ 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, Set<int> *r_safe_lines = nullptr) const override {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_validate, p_script, p_path, r_functions != nullptr, r_errors != nullptr, r_warnings != nullptr, r_safe_lines != nullptr, ret);
+ if (!ret.has("valid")) {
+ return false;
+ }
+ if (r_functions != nullptr && ret.has("functions")) {
+ Vector<String> functions = ret["functions"];
+ for (int i = 0; i < functions.size(); i++) {
+ r_functions->push_back(functions[i]);
+ }
+ }
+ if (r_errors != nullptr && ret.has("errors")) {
+ Array errors = ret["errors"];
+ for (int i = 0; i < errors.size(); i++) {
+ Dictionary err = errors[i];
+ ERR_CONTINUE(!err.has("line"));
+ ERR_CONTINUE(!err.has("column"));
+ ERR_CONTINUE(!err.has("message"));
+
+ ScriptError serr;
+ serr.line = err["line"];
+ serr.column = err["column"];
+ serr.message = err["message"];
+
+ r_errors->push_back(serr);
+ }
+ }
+ if (r_warnings != nullptr && ret.has("warnings")) {
+ ERR_FAIL_COND_V(!ret.has("warnings"), false);
+ Array warnings = ret["warnings"];
+ for (int i = 0; i < warnings.size(); i++) {
+ Dictionary warn = warnings[i];
+ ERR_CONTINUE(!warn.has("start_line"));
+ ERR_CONTINUE(!warn.has("end_line"));
+ ERR_CONTINUE(!warn.has("leftmost_column"));
+ ERR_CONTINUE(!warn.has("rightmost_column"));
+ ERR_CONTINUE(!warn.has("code"));
+ ERR_CONTINUE(!warn.has("string_code"));
+ ERR_CONTINUE(!warn.has("message"));
+
+ Warning swarn;
+ swarn.start_line = warn["start_line"];
+ swarn.end_line = warn["end_line"];
+ swarn.leftmost_column = warn["leftmost_column"];
+ swarn.rightmost_column = warn["rightmost_column"];
+ swarn.code = warn["code"];
+ swarn.string_code = warn["string_code"];
+ swarn.message = warn["message"];
+
+ r_warnings->push_back(swarn);
+ }
+ }
+ if (r_safe_lines != nullptr && ret.has("safe_lines")) {
+ PackedInt32Array safe_lines = ret["safe_lines"];
+ for (int i = 0; i < safe_lines.size(); i++) {
+ r_safe_lines->insert(safe_lines[i]);
+ }
+ }
+ return ret["valid"];
+ }
+
+ EXBIND1RC(String, validate_path, const String &)
+ GDVIRTUAL0RC(Object *, _create_script)
+ Script *create_script() const override {
+ Object *ret = nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_create_script, ret);
+ return Object::cast_to<Script>(ret);
+ }
+ EXBIND0RC(bool, has_named_classes)
+ EXBIND0RC(bool, supports_builtin_mode)
+ EXBIND0RC(bool, supports_documentation)
+ EXBIND0RC(bool, can_inherit_from_file)
+
+ EXBIND2RC(int, find_function, const String &, const String &)
+ EXBIND3RC(String, make_function, const String &, const String &, const PackedStringArray &)
+ EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int)
+ EXBIND0R(bool, overrides_external_editor)
+
+ GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *)
+
+ 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 {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_complete_code, p_code, p_path, p_owner, ret);
+ if (!ret.has("result")) {
+ return ERR_UNAVAILABLE;
+ }
+
+ if (r_options != nullptr && ret.has("options")) {
+ Array options = ret["options"];
+ for (int i = 0; i < options.size(); i++) {
+ Dictionary op = options[i];
+ CodeCompletionOption option;
+ ERR_CONTINUE(!op.has("kind"));
+ option.kind = CodeCompletionKind(int(op["kind"]));
+ ERR_CONTINUE(!op.has("display"));
+ option.display = op["display"];
+ ERR_CONTINUE(!op.has("insert_text"));
+ option.insert_text = op["insert_text"];
+ ERR_CONTINUE(!op.has("font_color"));
+ option.font_color = op["font_color"];
+ ERR_CONTINUE(!op.has("icon"));
+ option.icon = op["icon"];
+ ERR_CONTINUE(!op.has("default_value"));
+ option.default_value = op["default_value"];
+ ERR_CONTINUE(!op.has("location"));
+ option.location = op["location"];
+ if (op.has("matches")) {
+ PackedInt32Array matches = op["matches"];
+ ERR_CONTINUE(matches.size() & 1);
+ for (int j = 0; j < matches.size(); j += 2) {
+ option.matches.push_back(Pair<int, int>(matches[j], matches[j + 1]));
+ }
+ }
+ r_options->push_back(option);
+ }
+ }
+
+ ERR_FAIL_COND_V(!ret.has("force"), ERR_UNAVAILABLE);
+ r_force = ret["force"];
+ ERR_FAIL_COND_V(!ret.has("call_hint"), ERR_UNAVAILABLE);
+ r_call_hint = ret["call_hint"];
+ ERR_FAIL_COND_V(!ret.has("result"), ERR_UNAVAILABLE);
+ Error result = Error(int(ret["result"]));
+
+ return result;
+ }
+
+ GDVIRTUAL4RC(Dictionary, _lookup_code, const String &, const String &, const String &, Object *)
+
+ virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) override {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_lookup_code, p_code, p_symbol, p_path, p_owner, ret);
+ if (!ret.has("result")) {
+ return ERR_UNAVAILABLE;
+ }
+
+ ERR_FAIL_COND_V(!ret.has("type"), ERR_UNAVAILABLE);
+ r_result.type = LookupResultType(int(ret["type"]));
+ ERR_FAIL_COND_V(!ret.has("script"), ERR_UNAVAILABLE);
+ r_result.script = ret["script"];
+ ERR_FAIL_COND_V(!ret.has("class_name"), ERR_UNAVAILABLE);
+ r_result.class_name = ret["class_name"];
+ ERR_FAIL_COND_V(!ret.has("class_path"), ERR_UNAVAILABLE);
+ r_result.class_path = ret["class_path"];
+ ERR_FAIL_COND_V(!ret.has("location"), ERR_UNAVAILABLE);
+ r_result.location = ret["location"];
+
+ Error result = Error(int(ret["result"]));
+
+ return result;
+ }
+
+ GDVIRTUAL3RC(String, _auto_indent_code, const String &, int, int)
+ virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const override {
+ String ret;
+ GDVIRTUAL_REQUIRED_CALL(_auto_indent_code, p_code, p_from_line, p_to_line, ret);
+ p_code = ret;
+ }
+ EXBIND2(add_global_constant, const StringName &, const Variant &)
+ EXBIND2(add_named_global_constant, const StringName &, const Variant &)
+ EXBIND1(remove_named_global_constant, const StringName &)
+
+ /* MULTITHREAD FUNCTIONS */
+
+ //some VMs need to be notified of thread creation/exiting to allocate a stack
+ EXBIND0(thread_enter)
+ EXBIND0(thread_exit)
+
+ EXBIND0RC(String, debug_get_error)
+ EXBIND0RC(int, debug_get_stack_level_count)
+ EXBIND1RC(int, debug_get_stack_level_line, int)
+ EXBIND1RC(String, debug_get_stack_level_function, int)
+ EXBIND1RC(String, debug_get_stack_level_source, int)
+
+ GDVIRTUAL3R(Dictionary, _debug_get_stack_level_locals, int, int, int)
+ 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 {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_locals, p_level, p_max_subitems, p_max_depth, ret);
+ if (ret.size() == 0) {
+ return;
+ }
+ if (p_locals != nullptr && ret.has("locals")) {
+ PackedStringArray strings = ret["locals"];
+ for (int i = 0; i < strings.size(); i++) {
+ p_locals->push_back(strings[i]);
+ }
+ }
+ if (p_values != nullptr && ret.has("values")) {
+ Array values = ret["values"];
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+ }
+ GDVIRTUAL3R(Dictionary, _debug_get_stack_level_members, int, int, int)
+ 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 {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_members, p_level, p_max_subitems, p_max_depth, ret);
+ if (ret.size() == 0) {
+ return;
+ }
+ if (p_members != nullptr && ret.has("members")) {
+ PackedStringArray strings = ret["members"];
+ for (int i = 0; i < strings.size(); i++) {
+ p_members->push_back(strings[i]);
+ }
+ }
+ if (p_values != nullptr && ret.has("values")) {
+ Array values = ret["values"];
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+ }
+ GDVIRTUAL1R(GDNativePtr<void>, _debug_get_stack_level_instance, int)
+
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level) override {
+ GDNativePtr<void> ret = nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_instance, p_level, ret);
+ return reinterpret_cast<ScriptInstance *>(ret.operator void *());
+ }
+ GDVIRTUAL2R(Dictionary, _debug_get_globals, int, int)
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_debug_get_globals, p_max_subitems, p_max_depth, ret);
+ if (ret.size() == 0) {
+ return;
+ }
+ if (p_globals != nullptr && ret.has("globals")) {
+ PackedStringArray strings = ret["globals"];
+ for (int i = 0; i < strings.size(); i++) {
+ p_globals->push_back(strings[i]);
+ }
+ }
+ if (p_values != nullptr && ret.has("values")) {
+ Array values = ret["values"];
+ for (int i = 0; i < values.size(); i++) {
+ p_values->push_back(values[i]);
+ }
+ }
+ }
+
+ EXBIND4R(String, debug_parse_stack_level_expression, int, const String &, int, int)
+
+ GDVIRTUAL0R(TypedArray<Dictionary>, _debug_get_current_stack_info)
+ virtual Vector<StackInfo> debug_get_current_stack_info() override {
+ TypedArray<Dictionary> ret;
+ GDVIRTUAL_REQUIRED_CALL(_debug_get_current_stack_info, ret);
+ Vector<StackInfo> sret;
+ for (int i = 0; i < ret.size(); i++) {
+ StackInfo si;
+ Dictionary d = ret[i];
+ ERR_CONTINUE(!d.has("file"));
+ ERR_CONTINUE(!d.has("func"));
+ ERR_CONTINUE(!d.has("line"));
+ si.file = d["file"];
+ si.func = d["func"];
+ si.line = d["line"];
+ sret.push_back(si);
+ }
+ return sret;
+ }
+
+ EXBIND0(reload_all_scripts)
+ EXBIND2(reload_tool_script, const Ref<Script> &, bool)
+ /* LOADER FUNCTIONS */
+
+ GDVIRTUAL0RC(PackedStringArray, _get_recognized_extensions)
+
+ virtual void get_recognized_extensions(List<String> *p_extensions) const override {
+ PackedStringArray ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_recognized_extensions, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_extensions->push_back(ret[i]);
+ }
+ }
+
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_functions)
+ virtual void get_public_functions(List<MethodInfo> *p_functions) const override {
+ TypedArray<Dictionary> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_public_functions, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ MethodInfo mi = MethodInfo::from_dict(ret[i]);
+ p_functions->push_back(mi);
+ }
+ }
+ GDVIRTUAL0RC(Dictionary, _get_public_constants)
+ virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_public_constants, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ Dictionary d = ret[i];
+ ERR_CONTINUE(!d.has("name"));
+ ERR_CONTINUE(!d.has("value"));
+ p_constants->push_back(Pair<String, Variant>(d["name"], d["value"]));
+ }
+ }
+
+ EXBIND0(profiling_start)
+ EXBIND0(profiling_stop)
+
+ GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int)
+
+ virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
+ return ret;
+ }
+
+ GDVIRTUAL2R(int, _profiling_get_frame_data, GDNativePtr<ScriptLanguageExtensionProfilingInfo>, int)
+
+ virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override {
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
+ return ret;
+ }
+
+ GDVIRTUAL1R(GDNativePtr<void>, _alloc_instance_binding_data, Object *)
+
+ virtual void *alloc_instance_binding_data(Object *p_object) override {
+ GDNativePtr<void> ret = nullptr;
+ GDVIRTUAL_REQUIRED_CALL(_alloc_instance_binding_data, p_object, ret);
+ return ret.operator void *();
+ }
+
+ GDVIRTUAL1(_free_instance_binding_data, GDNativePtr<void>)
+
+ virtual void free_instance_binding_data(void *p_data) override {
+ GDVIRTUAL_REQUIRED_CALL(_free_instance_binding_data, p_data);
+ }
+
+ EXBIND1(refcount_incremented_instance_binding, Object *)
+ EXBIND1R(bool, refcount_decremented_instance_binding, Object *)
+
+ EXBIND0(frame)
+
+ EXBIND1RC(bool, handles_global_class_type, const String &)
+
+ GDVIRTUAL1RC(Dictionary, _get_global_class_name, const String &)
+
+ virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const override {
+ Dictionary ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_global_class_name, p_path, ret);
+ if (!ret.has("name")) {
+ return String();
+ }
+ if (r_base_type != nullptr && ret.has("base_type")) {
+ *r_base_type = ret["base_type"];
+ }
+ if (r_icon_path != nullptr && ret.has("icon_path")) {
+ *r_icon_path = ret["icon_path"];
+ }
+ return ret["name"];
+ }
+};
+
+VARIANT_ENUM_CAST(ScriptLanguageExtension::LookupResultType)
+VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionKind)
+VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
+
+class ScriptInstanceExtension : public ScriptInstance {
+public:
+ const GDNativeExtensionScriptInstanceInfo *native_info;
+ GDNativeExtensionScriptInstanceDataPtr instance = nullptr;
+
+// There should not be warnings on explicit casts.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+
+ virtual bool set(const StringName &p_name, const Variant &p_value) override {
+ if (native_info->set_func) {
+ return native_info->set_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value);
+ }
+ return false;
+ }
+ virtual bool get(const StringName &p_name, Variant &r_ret) const override {
+ if (native_info->get_func) {
+ return native_info->get_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret);
+ }
+ return false;
+ }
+ virtual void get_property_list(List<PropertyInfo> *p_list) const override {
+ if (native_info->get_property_list_func) {
+ uint32_t pcount;
+ const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
+ for (uint32_t i = 0; i < pcount; i++) {
+ p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
+ }
+ if (native_info->free_property_list_func) {
+ native_info->free_property_list_func(instance, pinfo);
+ }
+ }
+ }
+ virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override {
+ if (native_info->get_property_type_func) {
+ GDNativeBool is_valid = 0;
+ GDNativeVariantType type = native_info->get_property_type_func(instance, (const GDNativeStringNamePtr)&p_name, &is_valid);
+ if (r_is_valid) {
+ *r_is_valid = is_valid != 0;
+ }
+
+ return Variant::Type(type);
+ }
+ return Variant::NIL;
+ }
+
+ virtual Object *get_owner() override {
+ if (native_info->get_owner_func) {
+ return (Object *)native_info->get_owner_func(instance);
+ }
+ return nullptr;
+ }
+ static void _add_property_with_state(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata) {
+ List<Pair<StringName, Variant>> *state = (List<Pair<StringName, Variant>> *)p_userdata;
+ state->push_back(Pair<StringName, Variant>(*(const StringName *)p_name, *(const Variant *)p_value));
+ }
+ virtual void get_property_state(List<Pair<StringName, Variant>> &state) override {
+ if (native_info->get_property_state_func) {
+ native_info->get_property_state_func(instance, _add_property_with_state, &state);
+ }
+ }
+
+ virtual void get_method_list(List<MethodInfo> *p_list) const override {
+ if (native_info->get_method_list_func) {
+ uint32_t mcount;
+ const GDNativeMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount);
+ for (uint32_t i = 0; i < mcount; i++) {
+ MethodInfo m;
+ m.name = minfo[i].name;
+ m.flags = minfo[i].flags;
+ m.id = minfo[i].id;
+ m.return_val = PropertyInfo(Variant::Type(minfo[i].return_value.type), minfo[i].return_value.class_name, PropertyHint(minfo[i].return_value.hint), minfo[i].return_value.hint_string, minfo[i].return_value.usage, minfo[i].return_value.class_name);
+ for (uint32_t j = 0; j < minfo[i].argument_count; j++) {
+ m.arguments.push_back(PropertyInfo(Variant::Type(minfo[i].arguments[j].type), minfo[i].arguments[j].class_name, PropertyHint(minfo[i].arguments[j].hint), minfo[i].arguments[j].hint_string, minfo[i].arguments[j].usage, minfo[i].arguments[j].class_name));
+ }
+ const Variant *def_values = (const Variant *)minfo[i].default_arguments;
+ for (uint32_t j = 0; j < minfo[i].default_argument_count; j++) {
+ m.default_arguments.push_back(def_values[j]);
+ }
+ p_list->push_back(m);
+ }
+ if (native_info->free_method_list_func) {
+ native_info->free_method_list_func(instance, minfo);
+ }
+ }
+ }
+ virtual bool has_method(const StringName &p_method) const override {
+ if (native_info->has_method_func) {
+ return native_info->has_method_func(instance, (GDNativeStringNamePtr)&p_method);
+ }
+ return false;
+ }
+
+ virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
+ Variant ret;
+ if (native_info->call_func) {
+ GDNativeCallError ce;
+ native_info->call_func(instance, (const GDNativeStringNamePtr)&p_method, (const GDNativeVariantPtr *)p_args, p_argcount, (GDNativeVariantPtr)&ret, &ce);
+ r_error.error = Callable::CallError::Error(ce.error);
+ r_error.argument = ce.argument;
+ r_error.expected = ce.expected;
+ }
+ return ret;
+ }
+
+ virtual void notification(int p_notification) override {
+ if (native_info->notification_func) {
+ native_info->notification_func(instance, p_notification);
+ }
+ }
+ virtual String to_string(bool *r_valid) override {
+ if (native_info->to_string_func) {
+ GDNativeBool valid;
+ String ret = native_info->to_string_func(instance, &valid);
+ if (r_valid) {
+ *r_valid = valid != 0;
+ }
+ return ret;
+ }
+ return String();
+ }
+
+ virtual void refcount_incremented() override {
+ if (native_info->refcount_incremented_func) {
+ native_info->refcount_incremented_func(instance);
+ }
+ }
+ virtual bool refcount_decremented() override {
+ if (native_info->refcount_decremented_func) {
+ return native_info->refcount_decremented_func(instance);
+ }
+ return false;
+ }
+
+ virtual Ref<Script> get_script() const override {
+ if (native_info->get_script_func) {
+ GDNativeObjectPtr script = native_info->get_script_func(instance);
+ return Ref<Script>(reinterpret_cast<Script *>(script));
+ }
+ return Ref<Script>();
+ }
+
+ virtual bool is_placeholder() const override {
+ if (native_info->is_placeholder_func) {
+ return native_info->is_placeholder_func(instance);
+ }
+ return false;
+ }
+
+ virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) override {
+ if (native_info->set_fallback_func) {
+ bool ret = native_info->set_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value);
+ if (r_valid) {
+ *r_valid = ret;
+ }
+ }
+ }
+ virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid) override {
+ Variant ret;
+ if (native_info->get_fallback_func) {
+ bool valid = native_info->get_fallback_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret);
+ if (r_valid) {
+ *r_valid = valid;
+ }
+ }
+ return ret;
+ }
+
+ virtual ScriptLanguage *get_language() override {
+ if (native_info->get_language_func) {
+ GDNativeExtensionScriptLanguagePtr lang = native_info->get_language_func(instance);
+ return reinterpret_cast<ScriptLanguage *>(lang);
+ }
+ return nullptr;
+ ;
+ }
+ virtual ~ScriptInstanceExtension() {
+ if (native_info->free_func) {
+ native_info->free_func(instance);
+ }
+ }
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+};
+
+#endif // SCRIPT_LANGUAGE_EXTENSION_H
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index ee8eb97a93..d3c48853f1 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -444,25 +444,25 @@ UndoRedo::~UndoRedo() {
clear_history();
}
-Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+void UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 0;
- return Variant();
+ return;
}
if (p_args[0]->get_type() != Variant::OBJECT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
- return Variant();
+ return;
}
if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
- return Variant();
+ return;
}
r_error.error = Callable::CallError::CALL_OK;
@@ -471,28 +471,27 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl
StringName method = *p_args[1];
add_do_methodp(object, method, p_args + 2, p_argcount - 2);
- return Variant();
}
-Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+void UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 2) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 0;
- return Variant();
+ return;
}
if (p_args[0]->get_type() != Variant::OBJECT) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::OBJECT;
- return Variant();
+ return;
}
if (p_args[1]->get_type() != Variant::STRING_NAME && p_args[1]->get_type() != Variant::STRING) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 1;
r_error.expected = Variant::STRING_NAME;
- return Variant();
+ return;
}
r_error.error = Callable::CallError::CALL_OK;
@@ -501,7 +500,6 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
StringName method = *p_args[1];
add_undo_methodp(object, method, p_args + 2, p_argcount - 2);
- return Variant();
}
void UndoRedo::_bind_methods() {
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index ecd7a21167..63cf3e5cbe 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -46,8 +46,8 @@ public:
};
typedef void (*CommitNotifyCallback)(void *p_ud, const String &p_name);
- Variant _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant _add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ void _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ void _add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
typedef void (*PropertyNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index a6a32f0138..2bb1ea2ef4 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -38,7 +38,6 @@
class MainLoop : public Object {
GDCLASS(MainLoop, Object);
- OBJ_CATEGORY("Main Loop");
Ref<Script> initialize_script;
diff --git a/core/os/memory.h b/core/os/memory.h
index 27eaad5010..baa96ef3e9 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -186,9 +186,9 @@ void memdelete_arr(T *p_class) {
struct _GlobalNil {
int color = 1;
- _GlobalNil *right;
- _GlobalNil *left;
- _GlobalNil *parent;
+ _GlobalNil *right = nullptr;
+ _GlobalNil *left = nullptr;
+ _GlobalNil *parent = nullptr;
_GlobalNil();
};
diff --git a/core/os/os.h b/core/os/os.h
index 808d704b3d..b3c66ff18c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -60,8 +60,6 @@ class OS {
bool _stdout_enabled = true;
bool _stderr_enabled = true;
- char *last_error;
-
CompositeLogger *_logger = nullptr;
bool restart_on_exit = false;
diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp
index 190617f967..f622e2c7c5 100644
--- a/core/os/pool_allocator.cpp
+++ b/core/os/pool_allocator.cpp
@@ -149,7 +149,7 @@ void PoolAllocator::compact_up(int p_from) {
}
}
-bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, Entry *p_entry) {
+bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, const Entry *p_entry) {
EntryArrayPos entry_pos = entry_max;
for (int i = 0; i < entry_count; i++) {
@@ -424,7 +424,7 @@ bool PoolAllocator::is_locked(ID p_mem) const {
}
mt_lock();
- const Entry *e = ((PoolAllocator *)(this))->get_entry(p_mem);
+ const Entry *e = const_cast<PoolAllocator *>(this)->get_entry(p_mem);
if (!e) {
mt_unlock();
ERR_PRINT("!e");
diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h
index 11a252bc54..27a936ed78 100644
--- a/core/os/pool_allocator.h
+++ b/core/os/pool_allocator.h
@@ -75,13 +75,13 @@ private:
typedef int EntryArrayPos;
typedef int EntryIndicesPos;
- Entry *entry_array;
- int *entry_indices;
+ Entry *entry_array = nullptr;
+ int *entry_indices = nullptr;
int entry_max;
int entry_count;
- uint8_t *pool;
- void *mem_ptr;
+ uint8_t *pool = nullptr;
+ void *mem_ptr = nullptr;
int pool_size;
int free_mem;
@@ -108,7 +108,7 @@ private:
void compact_up(int p_from = 0);
bool get_free_entry(EntryArrayPos *p_pos);
bool find_hole(EntryArrayPos *p_pos, int p_for_size);
- bool find_entry_index(EntryIndicesPos *p_map_pos, Entry *p_entry);
+ bool find_entry_index(EntryIndicesPos *p_map_pos, const Entry *p_entry);
Entry *get_entry(ID p_mem);
const Entry *get_entry(ID p_mem) const;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index d05280f6a5..415b56cd83 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -71,6 +71,7 @@
#include "core/multiplayer/multiplayer_api.h"
#include "core/multiplayer/multiplayer_peer.h"
#include "core/object/class_db.h"
+#include "core/object/script_language_extension.h"
#include "core/object/undo_redo.h"
#include "core/os/main_loop.h"
#include "core/os/time.h"
@@ -142,6 +143,10 @@ void register_core_types() {
GDREGISTER_CLASS(Object);
GDREGISTER_ABSTRACT_CLASS(Script);
+ GDREGISTER_ABSTRACT_CLASS(ScriptLanguage);
+
+ GDREGISTER_VIRTUAL_CLASS(ScriptExtension);
+ GDREGISTER_VIRTUAL_CLASS(ScriptLanguageExtension);
GDREGISTER_CLASS(RefCounted);
GDREGISTER_CLASS(WeakRef);
@@ -227,7 +232,7 @@ void register_core_types() {
GDREGISTER_CLASS(PackedDataContainer);
GDREGISTER_ABSTRACT_CLASS(PackedDataContainerRef);
- GDREGISTER_CLASS(AStar);
+ GDREGISTER_CLASS(AStar3D);
GDREGISTER_CLASS(AStar2D);
GDREGISTER_CLASS(EncodedObjectAsID);
GDREGISTER_CLASS(RandomNumberGenerator);
@@ -263,6 +268,7 @@ void register_core_types() {
_engine_debugger = memnew(core_bind::EngineDebugger);
GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right");
+ GDREGISTER_NATIVE_STRUCT(ScriptLanguageExtensionProfilingInfo, "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time");
}
void register_core_settings() {
diff --git a/core/string/print_string.cpp b/core/string/print_string.cpp
index 97e119bcf6..919c9e08e3 100644
--- a/core/string/print_string.cpp
+++ b/core/string/print_string.cpp
@@ -45,7 +45,7 @@ void add_print_handler(PrintHandlerList *p_handler) {
_global_unlock();
}
-void remove_print_handler(PrintHandlerList *p_handler) {
+void remove_print_handler(const PrintHandlerList *p_handler) {
_global_lock();
PrintHandlerList *prev = nullptr;
diff --git a/core/string/print_string.h b/core/string/print_string.h
index 669d2ea316..f19573ad45 100644
--- a/core/string/print_string.h
+++ b/core/string/print_string.h
@@ -54,7 +54,7 @@ String stringify_variants(Variant p_var, Args... p_args) {
}
void add_print_handler(PrintHandlerList *p_handler);
-void remove_print_handler(PrintHandlerList *p_handler);
+void remove_print_handler(const PrintHandlerList *p_handler);
extern bool _print_line_enabled;
extern bool _print_error_enabled;
diff --git a/core/string/string_name.h b/core/string/string_name.h
index 6f08d32981..f4233854ac 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -70,7 +70,7 @@ class StringName {
_Data *_data = nullptr;
union _HashUnion {
- _Data *ptr;
+ _Data *ptr = nullptr;
uint32_t hash;
};
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index c41828de05..d6d361b5f1 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -891,7 +891,7 @@ String TranslationServer::wrap_with_fakebidi_characters(String &p_message) const
return res;
}
-String TranslationServer::add_padding(String &p_message, int p_length) const {
+String TranslationServer::add_padding(const String &p_message, int p_length) const {
String res;
String prefix = pseudolocalization_prefix;
String suffix;
@@ -921,7 +921,7 @@ const char32_t *TranslationServer::get_accented_version(char32_t p_character) co
}
bool TranslationServer::is_placeholder(String &p_message, int p_index) const {
- return p_message[p_index] == '%' && p_index < p_message.size() - 1 &&
+ return p_index < p_message.size() - 1 && p_message[p_index] == '%' &&
(p_message[p_index + 1] == 's' || p_message[p_index + 1] == 'c' || p_message[p_index + 1] == 'd' ||
p_message[p_index + 1] == 'o' || p_message[p_index + 1] == 'x' || p_message[p_index + 1] == 'X' || p_message[p_index + 1] == 'f');
}
diff --git a/core/string/translation.h b/core/string/translation.h
index 947ca4c6d8..ded6ed5925 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -96,7 +96,7 @@ class TranslationServer : public Object {
String double_vowels(String &p_message) const;
String replace_with_accented_string(String &p_message) const;
String wrap_with_fakebidi_characters(String &p_message) const;
- String add_padding(String &p_message, int p_length) const;
+ String add_padding(const String &p_message, int p_length) const;
const char32_t *get_accented_version(char32_t p_character) const;
bool is_placeholder(String &p_message, int p_index) const;
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 5e7904d827..48f2e45105 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -523,10 +523,6 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
#define TTRGET(m_value) TTR(m_value)
#else
-#define TTR(m_value) String()
-#define TTRN(m_value) String()
-#define DTR(m_value) String()
-#define DTRN(m_value) String()
#define TTRC(m_value) (m_value)
#define TTRGET(m_value) (m_value)
#endif
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index 1ecb81c2a2..7d3e31b5bc 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -215,7 +215,7 @@
T *instance; \
M method; \
SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() { \
+ virtual void call() override { \
(instance->*method)(COMMA_SEP_LIST(ARG, N)); \
} \
};
@@ -227,7 +227,7 @@
T *instance; \
M method; \
SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() { \
+ virtual void call() override { \
*ret = (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
} \
};
@@ -238,7 +238,7 @@
T *instance; \
M method; \
SEMIC_SEP_LIST(PARAM_DECL, N); \
- virtual void call() { \
+ virtual void call() override { \
(instance->*method)(COMMA_SEP_LIST(ARG, N)); \
} \
};
@@ -311,9 +311,9 @@ class CommandQueueMT {
};
struct SyncCommand : public CommandBase {
- SyncSemaphore *sync_sem;
+ SyncSemaphore *sync_sem = nullptr;
- virtual void post() {
+ virtual void post() override {
sync_sem->sem.post();
}
};
diff --git a/core/templates/map.h b/core/templates/map.h
index f228640a1e..c54da1dc03 100644
--- a/core/templates/map.h
+++ b/core/templates/map.h
@@ -178,7 +178,7 @@ public:
private:
struct _Data {
Element *_root = nullptr;
- Element *_nil;
+ Element *_nil = nullptr;
int size_cache = 0;
_FORCE_INLINE_ _Data() {
@@ -344,7 +344,7 @@ private:
void _insert_rb_fix(Element *p_new_node) {
Element *node = p_new_node;
Element *nparent = node->parent;
- Element *ngrand_parent;
+ Element *ngrand_parent = nullptr;
while (nparent->color == RED) {
ngrand_parent = nparent->parent;
@@ -500,7 +500,7 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- Element *sibling;
+ Element *sibling = nullptr;
if (rp == rp->parent->left) {
rp->parent->left = node;
sibling = rp->parent->right;
diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h
index 4e712fccf2..e4d9323c45 100644
--- a/core/templates/oa_hash_map.h
+++ b/core/templates/oa_hash_map.h
@@ -306,7 +306,7 @@ public:
bool valid;
const TKey *key;
- TValue *value;
+ TValue *value = nullptr;
private:
uint32_t pos;
diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h
index 53fc3fe5f9..ae31525dd0 100644
--- a/core/templates/safe_list.h
+++ b/core/templates/safe_list.h
@@ -75,8 +75,8 @@ public:
class Iterator {
friend class SafeList;
- SafeListNode *cursor;
- SafeList *list;
+ SafeListNode *cursor = nullptr;
+ SafeList *list = nullptr;
Iterator(SafeListNode *p_cursor, SafeList *p_list) :
cursor(p_cursor), list(p_list) {
@@ -253,8 +253,8 @@ public:
class Iterator {
friend class SafeList;
- SafeListNode *cursor;
- SafeList *list;
+ SafeListNode *cursor = nullptr;
+ SafeList *list = nullptr;
public:
Iterator(SafeListNode *p_cursor, SafeList *p_list) :
diff --git a/core/templates/self_list.h b/core/templates/self_list.h
index 7f2236fa3a..719b5f2e63 100644
--- a/core/templates/self_list.h
+++ b/core/templates/self_list.h
@@ -108,7 +108,7 @@ public:
private:
List *_root = nullptr;
- T *_self;
+ T *_self = nullptr;
SelfList<T> *_next = nullptr;
SelfList<T> *_prev = nullptr;
diff --git a/core/templates/set.h b/core/templates/set.h
index cdc6e8447d..a8a0a77712 100644
--- a/core/templates/set.h
+++ b/core/templates/set.h
@@ -328,7 +328,7 @@ private:
void _insert_rb_fix(Element *p_new_node) {
Element *node = p_new_node;
Element *nparent = node->parent;
- Element *ngrand_parent;
+ Element *ngrand_parent = nullptr;
while (nparent->color == RED) {
ngrand_parent = nparent->parent;
@@ -482,7 +482,7 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- Element *sibling;
+ Element *sibling = nullptr;
if (rp == rp->parent->left) {
rp->parent->left = node;
sibling = rp->parent->right;
diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h
index 957af44f48..b0cebf04f1 100644
--- a/core/templates/thread_work_pool.h
+++ b/core/templates/thread_work_pool.h
@@ -52,7 +52,7 @@ class ThreadWorkPool {
C *instance;
M method;
U userdata;
- virtual void work() {
+ virtual void work() override {
while (true) {
uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed);
if (work_index >= max_elements) {
@@ -68,7 +68,7 @@ class ThreadWorkPool {
Semaphore start;
Semaphore completed;
std::atomic<bool> exit;
- BaseWork *work;
+ BaseWork *work = nullptr;
};
ThreadData *threads = nullptr;
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 0877e04e01..d87e76139b 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -97,24 +97,29 @@ public:
_FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; }
- template <class C>
- void sort_custom() {
+ void sort() {
+ sort_custom<_DefaultComparator<T>>();
+ }
+
+ template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args>
+ void sort_custom(Args &&...args) {
int len = _cowdata.size();
if (len == 0) {
return;
}
T *data = ptrw();
- SortArray<T, C> sorter;
+ SortArray<T, Comparator, Validate> sorter{ args... };
sorter.sort(data, len);
}
- void sort() {
- sort_custom<_DefaultComparator<T>>();
+ int bsearch(const T &p_value, bool p_before) {
+ return bsearch_custom<_DefaultComparator<T>>(p_value, p_before);
}
- int bsearch(const T &p_value, bool p_before) {
- SearchArray<T> search;
+ template <class Comparator, class Value, class... Args>
+ int bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
+ SearchArray<T, Comparator> search{ args... };
return search.bisect(ptrw(), size(), p_value, p_before);
}
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 1b39558dff..afc4acadf9 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -484,24 +484,8 @@ void Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
}
-struct _ArrayVariantSortCustom {
- Callable func;
-
- _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
- const Variant *args[2] = { &p_l, &p_r };
- Callable::CallError err;
- Variant res;
- func.call(args, 2, res, err);
- ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
- "Error calling sorting method: " + Variant::get_callable_error_text(func, args, 1, err));
- return res;
- }
-};
-
-void Array::sort_custom(Callable p_callable) {
- SortArray<Variant, _ArrayVariantSortCustom, true> avs;
- avs.compare.func = p_callable;
- avs.sort(_p->array.ptrw(), _p->array.size());
+void Array::sort_custom(const Callable &p_callable) {
+ _p->array.sort_custom<CallableComparator, true>(p_callable);
}
void Array::shuffle() {
@@ -524,13 +508,10 @@ int Array::bsearch(const Variant &p_value, bool p_before) {
return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
-int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
+int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- SearchArray<Variant, _ArrayVariantSortCustom> avs;
- avs.compare.func = p_callable;
-
- return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
+ return _p->array.bsearch_custom<CallableComparator>(p_value, p_before, p_callable);
}
void Array::reverse() {
diff --git a/core/variant/array.h b/core/variant/array.h
index 72bed5932c..ab5f7cd50f 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -82,10 +82,10 @@ public:
Variant back() const;
void sort();
- void sort_custom(Callable p_callable);
+ void sort_custom(const Callable &p_callable);
void shuffle();
int bsearch(const Variant &p_value, bool p_before = true);
- int bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before = true);
+ int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true);
void reverse();
int find(const Variant &p_value, int p_from = 0) const;
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 48ed48d120..516b8f2d51 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -429,3 +429,13 @@ Signal::Signal(ObjectID p_object, const StringName &p_name) {
object = p_object;
name = p_name;
}
+
+bool CallableComparator::operator()(const Variant &p_l, const Variant &p_r) const {
+ const Variant *args[2] = { &p_l, &p_r };
+ Callable::CallError err;
+ Variant res;
+ func.call(args, 2, res, err);
+ ERR_FAIL_COND_V_MSG(err.error != Callable::CallError::CALL_OK, false,
+ "Error calling compare method: " + Variant::get_callable_error_text(func, args, 1, err));
+ return res;
+}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index c61870f194..6a760958d6 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -170,4 +170,10 @@ public:
Signal() {}
};
+struct CallableComparator {
+ const Callable &func;
+
+ bool operator()(const Variant &p_l, const Variant &p_r) const;
+};
+
#endif // CALLABLE_H
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 797e8afede..1a400b4360 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -40,8 +40,8 @@ String CallableCustomBind::get_as_text() const {
}
bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomBind *a = (const CallableCustomBind *)p_a;
- const CallableCustomBind *b = (const CallableCustomBind *)p_b;
+ const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
+ const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
@@ -55,8 +55,8 @@ bool CallableCustomBind::_equal_func(const CallableCustom *p_a, const CallableCu
}
bool CallableCustomBind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomBind *a = (const CallableCustomBind *)p_a;
- const CallableCustomBind *b = (const CallableCustomBind *)p_b;
+ const CallableCustomBind *a = static_cast<const CallableCustomBind *>(p_a);
+ const CallableCustomBind *b = static_cast<const CallableCustomBind *>(p_b);
if (a->callable < b->callable) {
return true;
@@ -117,8 +117,8 @@ String CallableCustomUnbind::get_as_text() const {
}
bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomUnbind *a = (const CallableCustomUnbind *)p_a;
- const CallableCustomUnbind *b = (const CallableCustomUnbind *)p_b;
+ const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
+ const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (!(a->callable != b->callable)) {
return false;
@@ -132,8 +132,8 @@ bool CallableCustomUnbind::_equal_func(const CallableCustom *p_a, const Callable
}
bool CallableCustomUnbind::_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
- const CallableCustomUnbind *a = (const CallableCustomUnbind *)p_a;
- const CallableCustomUnbind *b = (const CallableCustomUnbind *)p_b;
+ const CallableCustomUnbind *a = static_cast<const CallableCustomUnbind *>(p_a);
+ const CallableCustomUnbind *b = static_cast<const CallableCustomUnbind *>(p_b);
if (a->callable < b->callable) {
return true;
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index 4f79a29629..a5c830e109 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -43,14 +43,14 @@ class CallableCustomBind : public CallableCustom {
public:
//for every type that inherits, these must always be the same for this type
- virtual uint32_t hash() const;
- virtual String get_as_text() const;
- virtual CompareEqualFunc get_compare_equal_func() const;
- virtual CompareLessFunc get_compare_less_func() const;
- virtual StringName get_method() const;
- virtual ObjectID get_object() const; //must always be able to provide an object
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
- virtual const Callable *get_base_comparator() const;
+ virtual uint32_t hash() const override;
+ virtual String get_as_text() const override;
+ virtual CompareEqualFunc get_compare_equal_func() const override;
+ virtual CompareLessFunc get_compare_less_func() const override;
+ virtual StringName get_method() const override;
+ virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual const Callable *get_base_comparator() const override;
Callable get_callable() { return callable; }
Vector<Variant> get_binds() { return binds; }
@@ -68,14 +68,14 @@ class CallableCustomUnbind : public CallableCustom {
public:
//for every type that inherits, these must always be the same for this type
- virtual uint32_t hash() const;
- virtual String get_as_text() const;
- virtual CompareEqualFunc get_compare_equal_func() const;
- virtual CompareLessFunc get_compare_less_func() const;
- virtual StringName get_method() const;
- virtual ObjectID get_object() const; //must always be able to provide an object
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const;
- virtual const Callable *get_base_comparator() const;
+ virtual uint32_t hash() const override;
+ virtual String get_as_text() const override;
+ virtual CompareEqualFunc get_compare_equal_func() const override;
+ virtual CompareLessFunc get_compare_less_func() const override;
+ virtual StringName get_method() const override;
+ virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+ virtual const Callable *get_base_comparator() const override;
Callable get_callable() { return callable; }
int get_unbinds() { return argcount; }
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index a02f9c5823..c11925fa8c 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1656,6 +1656,8 @@ static void _register_variant_builtin_methods() {
bind_method(Color, darkened, sarray("amount"), varray());
bind_method(Color, blend, sarray("over"), varray());
bind_method(Color, get_luminance, sarray(), varray());
+ bind_method(Color, to_linear, sarray(), varray());
+ bind_method(Color, to_srgb, sarray(), varray());
bind_method(Color, is_equal_approx, sarray("to"), varray());
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 6027cb027e..ce2e9af04f 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -543,14 +543,12 @@ public:
class VariantConstructNoArgsObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
- VariantInternal::clear(&r_ret);
- VariantInternal::object_assign_null(&r_ret);
+ r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
r_error.error = Callable::CallError::CALL_OK;
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantInternal::clear(r_ret);
- VariantInternal::object_assign_null(r_ret);
+ *r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr.
}
static void ptr_construct(void *base, const void **p_args) {
PtrConstruct<Object *>::construct(nullptr, base);
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index e5585076c2..b297babd6f 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -51,9 +51,9 @@ public:
struct StreamFile : public Stream {
FileAccess *f = nullptr;
- virtual char32_t get_char();
- virtual bool is_utf8() const;
- virtual bool is_eof() const;
+ virtual char32_t get_char() override;
+ virtual bool is_utf8() const override;
+ virtual bool is_eof() const override;
StreamFile() {}
};
@@ -62,9 +62,9 @@ public:
String s;
int pos = 0;
- virtual char32_t get_char();
- virtual bool is_utf8() const;
- virtual bool is_eof() const;
+ virtual char32_t get_char() override;
+ virtual bool is_utf8() const override;
+ virtual bool is_eof() const override;
StreamString() {}
};
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 05fb577e2c..6ed85815be 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -470,20 +470,20 @@ struct VariantUtilityFunctions {
r_error.argument = 1;
return String();
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
r_error.error = Callable::CallError::CALL_OK;
- return str;
+ return s;
}
static inline String error_string(Error error) {
@@ -495,98 +495,98 @@ struct VariantUtilityFunctions {
}
static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void print_verbose(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
if (OS::get_singleton()->is_stdout_verbose()) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
// No need to use `print_verbose()` as this call already only happens
// when verbose mode is enabled. This avoids performing string argument concatenation
// when not needed.
- print_line(str);
+ print_line(s);
}
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- print_error(str);
+ print_error(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
- str += "\t";
+ s += "\t";
}
- str += p_args[i]->operator String();
+ s += p_args[i]->operator String();
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
- str += " ";
+ s += " ";
}
- str += p_args[i]->operator String();
+ s += p_args[i]->operator String();
}
- print_line(str);
+ print_line(s);
r_error.error = Callable::CallError::CALL_OK;
}
static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- OS::get_singleton()->print("%s", str.utf8().get_data());
+ OS::get_singleton()->print("%s", s.utf8().get_data());
r_error.error = Callable::CallError::CALL_OK;
}
@@ -595,18 +595,18 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- ERR_PRINT(str);
+ ERR_PRINT(s);
r_error.error = Callable::CallError::CALL_OK;
}
@@ -615,18 +615,18 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
}
- String str;
+ String s;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
if (i == 0) {
- str = os;
+ s = os;
} else {
- str += os;
+ s += os;
}
}
- WARN_PRINT(str);
+ WARN_PRINT(s);
r_error.error = Callable::CallError::CALL_OK;
}