summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/project_settings.cpp42
-rw-r--r--core/core_bind.cpp55
-rw-r--r--core/core_bind.h5
-rw-r--r--core/debugger/engine_debugger.cpp10
-rw-r--r--core/debugger/local_debugger.cpp8
-rw-r--r--core/debugger/remote_debugger.cpp4
-rw-r--r--core/extension/extension_api_dump.cpp6
-rw-r--r--core/extension/gdnative_interface.cpp10
-rw-r--r--core/extension/gdnative_interface.h4
-rw-r--r--core/extension/native_extension_manager.cpp12
-rw-r--r--core/input/input.cpp14
-rw-r--r--core/input/input_event.cpp6
-rw-r--r--core/input/input_map.cpp56
-rw-r--r--core/input/input_map.h2
-rw-r--r--core/io/file_access_pack.cpp8
-rw-r--r--core/io/image.cpp8
-rw-r--r--core/io/ip.cpp8
-rw-r--r--core/io/packet_peer.cpp46
-rw-r--r--core/io/packet_peer.h23
-rw-r--r--core/io/resource.cpp4
-rw-r--r--core/io/resource_format_binary.cpp4
-rw-r--r--core/io/resource_loader.cpp4
-rw-r--r--core/io/resource_uid.cpp3
-rw-r--r--core/io/stream_peer.cpp57
-rw-r--r--core/io/stream_peer.h25
-rw-r--r--core/math/aabb.cpp4
-rw-r--r--core/math/aabb.h4
-rw-r--r--core/math/bvh_cull.inc2
-rw-r--r--core/math/bvh_debug.inc27
-rw-r--r--core/math/bvh_split.inc16
-rw-r--r--core/math/delaunay_2d.h2
-rw-r--r--core/math/face3.cpp4
-rw-r--r--core/math/quick_hull.cpp24
-rw-r--r--core/math/rect2.h6
-rw-r--r--core/math/static_raycaster.cpp40
-rw-r--r--core/math/static_raycaster.h111
-rw-r--r--core/math/transform_2d.cpp24
-rw-r--r--core/math/transform_2d.h27
-rw-r--r--core/math/triangle_mesh.cpp8
-rw-r--r--core/math/vector2.cpp2
-rw-r--r--core/multiplayer/multiplayer_peer.cpp181
-rw-r--r--core/multiplayer/multiplayer_peer.h80
-rw-r--r--core/object/class_db.cpp9
-rw-r--r--core/object/class_db.h1
-rw-r--r--core/object/message_queue.cpp12
-rw-r--r--core/object/script_language.cpp4
-rw-r--r--core/os/os.cpp5
-rw-r--r--core/os/os.h1
-rw-r--r--core/os/thread.cpp6
-rw-r--r--core/os/thread.h9
-rw-r--r--core/register_core_types.cpp3
-rw-r--r--core/string/optimized_translation.cpp10
-rw-r--r--core/string/translation.cpp25
-rw-r--r--core/string/translation.h5
-rw-r--r--core/templates/pooled_list.h14
-rw-r--r--core/templates/rid_owner.h16
-rw-r--r--core/variant/callable.cpp4
-rw-r--r--core/variant/callable.h2
-rw-r--r--core/variant/native_ptr.h3
-rw-r--r--core/variant/variant_call.cpp16
-rw-r--r--core/variant/variant_construct.cpp1
-rw-r--r--core/variant/variant_utility.cpp43
62 files changed, 902 insertions, 273 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 03892d1d4f..85e83ff7f2 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -55,11 +55,7 @@ String ProjectSettings::get_resource_path() const {
const String ProjectSettings::IMPORTED_FILES_PATH("res://.godot/imported");
String ProjectSettings::localize_path(const String &p_path) const {
- if (resource_path == "") {
- return p_path; //not initialized yet
- }
-
- if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
+ if (resource_path.is_empty() || p_path.begins_with("res://") || p_path.begins_with("user://") ||
(p_path.is_absolute_path() && !p_path.begins_with(resource_path))) {
return p_path.simplify_path();
}
@@ -256,15 +252,15 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
Set<_VCSort> vclist;
- for (Map<StringName, VariantContainer>::Element *E = props.front(); E; E = E->next()) {
- const VariantContainer *v = &E->get();
+ for (const KeyValue<StringName, VariantContainer> &E : props) {
+ const VariantContainer *v = &E.value;
if (v->hide_from_editor) {
continue;
}
_VCSort vc;
- vc.name = E->key();
+ vc.name = E.key;
vc.order = v->order;
vc.type = v->variant.get_type();
if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload")) {
@@ -322,14 +318,14 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f
void ProjectSettings::_convert_to_last_version(int p_from_version) {
if (p_from_version <= 3) {
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
- for (Map<StringName, ProjectSettings::VariantContainer>::Element *E = props.front(); E; E = E->next()) {
- Variant value = E->get().variant;
- if (String(E->key()).begins_with("input/") && value.get_type() == Variant::ARRAY) {
+ for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
+ Variant value = E.value.variant;
+ if (String(E.key).begins_with("input/") && value.get_type() == Variant::ARRAY) {
Array array = value;
Dictionary action;
action["deadzone"] = Variant(0.5f);
action["events"] = array;
- E->get().variant = action;
+ E.value.variant = action;
}
}
}
@@ -699,8 +695,8 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
int count = 0;
- for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
- count += E->get().size();
+ for (const KeyValue<String, List<String>> &E : props) {
+ count += E.value.size();
}
if (p_custom_features != String()) {
@@ -792,7 +788,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
}
file->store_string("\n");
- for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
+ for (const Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
if (E != props.front()) {
file->store_string("\n");
}
@@ -835,19 +831,19 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
Set<_VCSort> vclist;
if (p_merge_with_current) {
- for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) {
- const VariantContainer *v = &G->get();
+ for (const KeyValue<StringName, VariantContainer> &G : props) {
+ const VariantContainer *v = &G.value;
if (v->hide_from_editor) {
continue;
}
- if (p_custom.has(G->key())) {
+ if (p_custom.has(G.key)) {
continue;
}
_VCSort vc;
- vc.name = G->key(); //*k;
+ vc.name = G.key; //*k;
vc.order = v->order;
vc.type = v->variant.get_type();
vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
@@ -859,14 +855,14 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
}
}
- for (const Map<String, Variant>::Element *E = p_custom.front(); E; E = E->next()) {
+ for (const KeyValue<String, Variant> &E : p_custom) {
// Lookup global prop to store in the same order
- Map<StringName, VariantContainer>::Element *global_prop = props.find(E->key());
+ Map<StringName, VariantContainer>::Element *global_prop = props.find(E.key);
_VCSort vc;
- vc.name = E->key();
+ vc.name = E.key;
vc.order = global_prop ? global_prop->get().order : 0xFFFFFFF;
- vc.type = E->get().get_type();
+ vc.type = E.value.get_type();
vc.flags = PROPERTY_USAGE_STORAGE;
vclist.insert(vc);
}
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index e029b85450..0b9816932c 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1786,13 +1786,13 @@ void Thread::_start_func(void *ud) {
// We must check if we are in case b).
int target_param_count = 0;
int target_default_arg_count = 0;
- Ref<Script> script = t->target_instance->get_script();
+ Ref<Script> script = t->target_callable.get_object()->get_script();
if (script.is_valid()) {
- MethodInfo mi = script->get_method_info(t->target_method);
+ MethodInfo mi = script->get_method_info(t->target_callable.get_method());
target_param_count = mi.arguments.size();
target_default_arg_count = mi.default_arguments.size();
} else {
- MethodBind *method = ClassDB::get_method(t->target_instance->get_class_name(), t->target_method);
+ MethodBind *method = ClassDB::get_method(t->target_callable.get_object()->get_class_name(), t->target_callable.get_method());
target_param_count = method->get_argument_count();
target_default_arg_count = method->get_default_argument_count();
}
@@ -1801,41 +1801,21 @@ void Thread::_start_func(void *ud) {
}
}
- ::Thread::set_name(t->target_method);
+ ::Thread::set_name(t->target_callable.get_method());
- t->ret = t->target_instance->call(t->target_method, arg, argc, ce);
+ t->target_callable.call(arg, argc, t->ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- String reason;
- switch (ce.error) {
- case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
- reason = "Invalid Argument #" + itos(ce.argument);
- } break;
- case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
- reason = "Too Many Arguments";
- } break;
- case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
- reason = "Too Few Arguments";
- } break;
- case Callable::CallError::CALL_ERROR_INVALID_METHOD: {
- reason = "Method Not Found";
- } break;
- default: {
- }
- }
-
- ERR_FAIL_MSG("Could not call function '" + t->target_method.operator String() + "' to start thread " + t->get_id() + ": " + reason + ".");
+ ERR_FAIL_MSG("Could not call function '" + t->target_callable.get_method().operator String() + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, arg, argc, ce) + ".");
}
}
-Error Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) {
+Error Thread::start(const Callable &p_callable, const Variant &p_userdata, Priority p_priority) {
ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started.");
- ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(p_callable.is_null(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER);
ret = Variant();
- target_method = p_method;
- target_instance = p_instance;
+ target_callable = p_callable;
userdata = p_userdata;
active.set();
@@ -1861,15 +1841,14 @@ Variant Thread::wait_to_finish() {
thread.wait_to_finish();
Variant r = ret;
active.clear();
- target_method = StringName();
- target_instance = nullptr;
+ target_callable = Callable();
userdata = Variant();
return r;
}
void Thread::_bind_methods() {
- ClassDB::bind_method(D_METHOD("start", "instance", "method", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
+ ClassDB::bind_method(D_METHOD("start", "callable", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL));
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
ClassDB::bind_method(D_METHOD("is_active"), &Thread::is_active);
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
@@ -2221,7 +2200,7 @@ Object *Engine::get_singleton_object(const StringName &p_name) const {
void Engine::register_singleton(const StringName &p_name, Object *p_object) {
ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
- ERR_FAIL_COND_MSG(p_name.operator String().is_valid_identifier(), "Singleton name is not a valid identifier: " + String(p_name));
+ ERR_FAIL_COND_MSG(!String(p_name).is_valid_identifier(), "Singleton name is not a valid identifier: " + p_name);
::Engine::Singleton s;
s.class_name = p_name;
s.name = p_name;
@@ -2297,13 +2276,11 @@ 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("set_editor_hint", "enabled"), &Engine::set_editor_hint);
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);
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_hint"), "set_editor_hint", "is_editor_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
ADD_PROPERTY(PropertyInfo(Variant::INT, "target_fps"), "set_target_fps", "get_target_fps");
@@ -2434,12 +2411,12 @@ Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Arra
}
EngineDebugger::~EngineDebugger() {
- for (Map<StringName, Callable>::Element *E = captures.front(); E; E = E->next()) {
- ::EngineDebugger::unregister_message_capture(E->key());
+ for (const KeyValue<StringName, Callable> &E : captures) {
+ ::EngineDebugger::unregister_message_capture(E.key);
}
captures.clear();
- for (Map<StringName, ProfilerCallable>::Element *E = profilers.front(); E; E = E->next()) {
- ::EngineDebugger::unregister_profiler(E->key());
+ for (const KeyValue<StringName, ProfilerCallable> &E : profilers) {
+ ::EngineDebugger::unregister_profiler(E.key);
}
profilers.clear();
}
diff --git a/core/core_bind.h b/core/core_bind.h
index a5d5a7c8ce..84a284f948 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -539,8 +539,7 @@ protected:
Variant ret;
Variant userdata;
SafeFlag active;
- Object *target_instance = nullptr;
- StringName target_method;
+ Callable target_callable;
::Thread thread;
static void _bind_methods();
static void _start_func(void *ud);
@@ -553,7 +552,7 @@ public:
PRIORITY_MAX
};
- Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL);
+ Error start(const Callable &p_callable, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL);
String get_id() const;
bool is_active() const;
Variant wait_to_finish();
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index a522b1310f..059025aa8f 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -123,8 +123,8 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
physics_time = USEC_TO_SEC(p_physics_ticks);
physics_frame_time = p_physics_frame_time;
// Notify tick to running profilers
- for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
- Profiler &p = E->get();
+ for (KeyValue<StringName, Profiler> &E : profilers) {
+ Profiler &p = E.value;
if (!p.active || !p.tick) {
continue;
}
@@ -179,9 +179,9 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
void EngineDebugger::deinitialize() {
if (singleton) {
// Stop all profilers
- for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
- if (E->get().active) {
- singleton->profiler_enable(E->key(), false);
+ for (const KeyValue<StringName, Profiler> &E : profilers) {
+ if (E.value.active) {
+ singleton->profiler_enable(E.key, false);
}
}
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index b0b3f11424..f7e56351b0 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -166,8 +166,8 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (line.begins_with("set")) {
if (line.get_slice_count(" ") == 1) {
- for (Map<String, String>::Element *E = options.front(); E; E = E->next()) {
- print_line("\t" + E->key() + "=" + E->value());
+ for (const KeyValue<String, String> &E : options) {
+ print_line("\t" + E.key + "=" + E.value);
}
} else {
@@ -249,8 +249,8 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
print_line("Breakpoint(s): " + itos(breakpoints.size()));
- for (Map<int, Set<StringName>>::Element *E = breakpoints.front(); E; E = E->next()) {
- print_line("\t" + String(E->value().front()->get()) + ":" + itos(E->key()));
+ for (const KeyValue<int, Set<StringName>> &E : breakpoints) {
+ print_line("\t" + String(E.value.front()->get()) + ":" + itos(E.key));
}
} else {
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index f865dfe102..032c7d55c0 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -179,8 +179,8 @@ public:
if (pt - last_profile_time > 100) {
last_profile_time = pt;
DebuggerMarshalls::NetworkProfilerFrame frame;
- for (Map<ObjectID, NodeInfo>::Element *E = multiplayer_node_data.front(); E; E = E->next()) {
- frame.infos.push_back(E->get());
+ for (const KeyValue<ObjectID, NodeInfo> &E : multiplayer_node_data) {
+ frame.infos.push_back(E.value);
}
multiplayer_node_data.clear();
EngineDebugger::get_singleton()->send_message("network:profile_frame", frame.serialize());
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index a8547a0090..3856229eac 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -353,11 +353,11 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
api_dump["global_constants"] = constants;
Array enums;
- for (Map<String, List<Pair<String, int>>>::Element *E = enum_list.front(); E; E = E->next()) {
+ for (const KeyValue<String, List<Pair<String, int>>> &E : enum_list) {
Dictionary d1;
- d1["name"] = E->key();
+ d1["name"] = E.key;
Array values;
- for (const Pair<String, int> &F : E->get()) {
+ for (const Pair<String, int> &F : E.value) {
Dictionary d2;
d2["name"] = F.first;
d2["value"] = F.second;
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index b41f74a4bc..ff09b0b86c 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -854,14 +854,21 @@ static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_clas
return (GDNativeMethodBindPtr)mb;
}
-static GDNativeClassConstructor gdnative_classdb_get_constructor(const char *p_classname) {
+static GDNativeClassConstructor gdnative_classdb_get_constructor(const char *p_classname, GDNativeExtensionPtr *r_extension) {
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname));
if (class_info) {
+ if (r_extension) {
+ *r_extension = class_info->native_extension;
+ }
return (GDNativeClassConstructor)class_info->creation_func;
}
return nullptr;
}
+static GDNativeObjectPtr gdnative_classdb_construct_object(GDNativeClassConstructor p_constructor, GDNativeExtensionPtr p_extension) {
+ return (GDNativeObjectPtr)ClassDB::construct_object((Object * (*)()) p_constructor, (ObjectNativeExtension *)p_extension);
+}
+
static void *gdnative_classdb_get_class_tag(const char *p_classname) {
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname);
return class_info ? class_info->class_ptr : nullptr;
@@ -1010,6 +1017,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
/* CLASSDB */
gdni.classdb_get_constructor = gdnative_classdb_get_constructor;
+ gdni.classdb_construct_object = gdnative_classdb_construct_object;
gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind;
gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index df735db9b6..73f78bde54 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -137,6 +137,7 @@ typedef void *GDNativeStringNamePtr;
typedef void *GDNativeStringPtr;
typedef void *GDNativeObjectPtr;
typedef void *GDNativeTypePtr;
+typedef void *GDNativeExtensionPtr;
typedef void *GDNativeMethodBindPtr;
typedef int64_t GDNativeInt;
typedef uint8_t GDNativeBool;
@@ -431,7 +432,8 @@ typedef struct {
/* CLASSDB */
- GDNativeClassConstructor (*classdb_get_constructor)(const char *p_classname);
+ GDNativeClassConstructor (*classdb_get_constructor)(const char *p_classname, GDNativeExtensionPtr *r_extension);
+ GDNativeObjectPtr (*classdb_construct_object)(GDNativeClassConstructor p_constructor, GDNativeExtensionPtr p_extension);
GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
void *(*classdb_get_class_tag)(const char *p_classname);
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
index 8b7a9df4f1..4eac5249c9 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/native_extension_manager.cpp
@@ -84,8 +84,8 @@ bool NativeExtensionManager::is_extension_loaded(const String &p_path) const {
Vector<String> NativeExtensionManager::get_loaded_extensions() const {
Vector<String> ret;
- for (const Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- ret.push_back(E->key());
+ for (const KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ ret.push_back(E.key);
}
return ret;
}
@@ -97,16 +97,16 @@ Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path)
void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) - 1 != level);
- for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- E->get()->initialize_library(p_level);
+ for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ E.value->initialize_library(p_level);
}
level = p_level;
}
void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) {
ERR_FAIL_COND(int32_t(p_level) != level);
- for (Map<String, Ref<NativeExtension>>::Element *E = native_extension_map.front(); E; E = E->next()) {
- E->get()->deinitialize_library(p_level);
+ for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) {
+ E.value->deinitialize_library(p_level);
}
level = int32_t(p_level) - 1;
}
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 9195f7d8b5..05b02408a1 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -863,9 +863,9 @@ void Input::release_pressed_events() {
joy_buttons_pressed.clear();
_joy_axis.clear();
- for (Map<StringName, Input::Action>::Element *E = action_state.front(); E; E = E->next()) {
- if (E->get().pressed) {
- action_release(E->key());
+ for (const KeyValue<StringName, Input::Action> &E : action_state) {
+ if (E.value.pressed) {
+ action_release(E.key);
}
}
}
@@ -1322,8 +1322,8 @@ void Input::add_joy_mapping(String p_mapping, bool p_update_existing) {
if (p_update_existing) {
Vector<String> entry = p_mapping.split(",");
String uid = entry[0];
- for (Map<int, Joypad>::Element *E = joy_names.front(); E; E = E->next()) {
- Joypad &joy = E->get();
+ for (KeyValue<int, Joypad> &E : joy_names) {
+ Joypad &joy = E.value;
if (joy.uid == uid) {
joy.mapping = map_db.size() - 1;
}
@@ -1337,8 +1337,8 @@ void Input::remove_joy_mapping(String p_guid) {
map_db.remove(i);
}
}
- for (Map<int, Joypad>::Element *E = joy_names.front(); E; E = E->next()) {
- Joypad &joy = E->get();
+ for (KeyValue<int, Joypad> &E : joy_names) {
+ Joypad &joy = E.value;
if (joy.uid == p_guid) {
joy.mapping = -1;
}
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 50b2099236..1d2b5f19ee 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -864,6 +864,8 @@ void InputEventMouseMotion::_bind_methods() {
///////////////////////////////////
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
+ ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX);
+
axis = p_axis;
emit_changed();
}
@@ -1557,9 +1559,13 @@ bool InputEventShortcut::is_pressed() const {
}
String InputEventShortcut::as_text() const {
+ ERR_FAIL_COND_V(shortcut.is_null(), "None");
+
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
}
String InputEventShortcut::to_string() {
+ ERR_FAIL_COND_V(shortcut.is_null(), "None");
+
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
}
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index c6db7be53a..1ec4299093 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/os/keyboard.h"
+#include "core/os/os.h"
InputMap *InputMap::singleton = nullptr;
@@ -466,7 +467,7 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
// ///// UI Text Input Shortcuts /////
inputs = List<Ref<InputEvent>>();
- inputs.push_back(InputEventKey::create_reference(KEY_SPACE | KEY_MASK_CMD));
+ inputs.push_back(InputEventKey::create_reference(KEY_SPACE | KEY_MASK_CTRL));
default_builtin_cache.insert("ui_text_completion_query", inputs);
inputs = List<Ref<InputEvent>>();
@@ -699,34 +700,57 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
return default_builtin_cache;
}
-void InputMap::load_default() {
+const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() {
+ if (default_builtin_with_overrides_cache.size() > 0) {
+ return default_builtin_with_overrides_cache;
+ }
+
OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins();
- // List of Builtins which have an override for macOS.
- Vector<String> macos_builtins;
+ // Get a list of all built in inputs which are valid overrides for the OS
+ // Key = builtin name (e.g. ui_accept)
+ // Value = override/feature names (e.g. macos, if it was defined as "ui_accept.macos" and the platform supports that feature)
+ Map<String, Vector<String>> builtins_with_overrides;
for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
- if (String(E.key()).ends_with(".macos")) {
- // Strip .macos from name: some_input_name.macos -> some_input_name
- macos_builtins.push_back(String(E.key()).split(".")[0]);
+ String fullname = E.key();
+
+ Vector<String> split = fullname.split(".");
+ String name = split[0];
+ String override_for = split.size() > 1 ? split[1] : String();
+
+ if (override_for != String() && OS::get_singleton()->has_feature(override_for)) {
+ builtins_with_overrides[name].push_back(override_for);
}
}
for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
String fullname = E.key();
- String name = fullname.split(".")[0];
- String override_for = fullname.split(".").size() > 1 ? fullname.split(".")[1] : "";
-#ifdef APPLE_STYLE_KEYS
- if (macos_builtins.has(name) && override_for != "macos") {
- // Name has `macos` builtin but this particular one is for non-macOS systems - so skip.
+ Vector<String> split = fullname.split(".");
+ String name = split[0];
+ String override_for = split.size() > 1 ? split[1] : String();
+
+ if (builtins_with_overrides.has(name) && override_for == String()) {
+ // Builtin has an override but this particular one is not an override, so skip.
continue;
}
-#else
- if (override_for == "macos") {
- // Override for macOS - not needed on non-macOS platforms.
+
+ if (override_for != String() && !OS::get_singleton()->has_feature(override_for)) {
+ // OS does not support this override - skip.
continue;
}
-#endif
+
+ default_builtin_with_overrides_cache.insert(name, E.value());
+ }
+
+ return default_builtin_with_overrides_cache;
+}
+
+void InputMap::load_default() {
+ OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied();
+
+ for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+ String name = E.key();
add_action(name);
diff --git a/core/input/input_map.h b/core/input/input_map.h
index c724fdb142..8bef722089 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -56,6 +56,7 @@ private:
mutable OrderedHashMap<StringName, Action> input_map;
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
+ OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;
List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
@@ -93,6 +94,7 @@ public:
String get_builtin_display_name(const String &p_name) const;
// Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat.
const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins();
+ const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied();
InputMap();
~InputMap();
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 7b43daf9c0..b2832b2a75 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -110,8 +110,8 @@ PackedData::PackedData() {
}
void PackedData::_free_packed_dirs(PackedDir *p_dir) {
- for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) {
- _free_packed_dirs(E->get());
+ for (const KeyValue<String, PackedDir *> &E : p_dir->subdirs) {
+ _free_packed_dirs(E.value);
}
memdelete(p_dir);
}
@@ -395,8 +395,8 @@ Error DirAccessPack::list_dir_begin() {
list_dirs.clear();
list_files.clear();
- for (Map<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
- list_dirs.push_back(E->key());
+ for (const KeyValue<String, PackedData::PackedDir *> &E : current->subdirs) {
+ list_dirs.push_back(E.key);
}
for (Set<String>::Element *E = current->files.front(); E; E = E->next()) {
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 3112dd217f..c70f4b86bd 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -2506,7 +2506,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2561,7 +2561,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2615,7 +2615,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
@@ -2664,7 +2664,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
clipped_src_rect.position.y = ABS(p_dest.y);
}
- if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) {
+ if (clipped_src_rect.has_no_area()) {
return;
}
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index e3102508a3..68b4e4b354 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -288,8 +288,8 @@ Array IP::_get_local_interfaces() const {
Array results;
Map<String, Interface_Info> interfaces;
get_local_interfaces(&interfaces);
- for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) {
- Interface_Info &c = E->get();
+ for (KeyValue<String, Interface_Info> &E : interfaces) {
+ Interface_Info &c = E.value;
Dictionary rc;
rc["name"] = c.name;
rc["friendly"] = c.name_friendly;
@@ -310,8 +310,8 @@ Array IP::_get_local_interfaces() const {
void IP::get_local_addresses(List<IPAddress> *r_addresses) const {
Map<String, Interface_Info> interfaces;
get_local_interfaces(&interfaces);
- for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) {
- for (const IPAddress &F : E->get().ip_addresses) {
+ for (const KeyValue<String, Interface_Info> &E : interfaces) {
+ for (const IPAddress &F : E.value.ip_addresses) {
r_addresses->push_front(F);
}
}
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 8da44fd290..87d2b66e5b 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -138,6 +138,7 @@ Error PacketPeer::_get_packet_error() const {
void PacketPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &PacketPeer::_bnd_get_var, DEFVAL(false));
ClassDB::bind_method(D_METHOD("put_var", "var", "full_objects"), &PacketPeer::put_var, DEFVAL(false));
+
ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet);
ClassDB::bind_method(D_METHOD("put_packet", "buffer"), &PacketPeer::_put_packet);
ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error);
@@ -151,6 +152,51 @@ void PacketPeer::_bind_methods() {
/***************/
+int PacketPeerExtension::get_available_packet_count() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_packet_count, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_available_packet_count is unimplemented!");
+ return -1;
+}
+
+Error PacketPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_packet_native is unimplemented!");
+ return FAILED;
+}
+
+Error PacketPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_put_packet_native is unimplemented!");
+ return FAILED;
+}
+
+int PacketPeerExtension::get_max_packet_size() const {
+ int size;
+ if (GDVIRTUAL_CALL(_get_max_packet_size, size)) {
+ return size;
+ }
+ WARN_PRINT_ONCE("PacketPeerExtension::_get_max_packet_size is unimplemented!");
+ return 0;
+}
+
+void PacketPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size");
+ GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size");
+ GDVIRTUAL_BIND(_get_available_packet_count);
+ GDVIRTUAL_BIND(_get_max_packet_size);
+}
+
+/***************/
+
void PacketPeerStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::set_stream_peer);
ClassDB::bind_method(D_METHOD("get_stream_peer"), &PacketPeerStream::get_stream_peer);
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index 9a345af3d0..bc1f4aaabf 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -35,6 +35,10 @@
#include "core/object/class_db.h"
#include "core/templates/ring_buffer.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class PacketPeer : public RefCounted {
GDCLASS(PacketPeer, RefCounted);
@@ -73,6 +77,25 @@ public:
~PacketPeer() {}
};
+class PacketPeerExtension : public PacketPeer {
+ GDCLASS(PacketPeerExtension, PacketPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual int get_available_packet_count() const override;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
+ virtual int get_max_packet_size() const override;
+
+ /* GDExtension */
+ GDVIRTUAL0RC(int, _get_available_packet_count);
+ GDVIRTUAL2R(int, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL0RC(int, _get_max_packet_size);
+};
+
class PacketPeerStream : public PacketPeer {
GDCLASS(PacketPeerStream, PacketPeer);
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 87b4d7195d..1cefa52d69 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -540,9 +540,9 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
}
}
- for (Map<String, int>::Element *E = type_count.front(); E; E = E->next()) {
+ for (const KeyValue<String, int> &E : type_count) {
if (f) {
- f->store_line(E->key() + " count: " + itos(E->get()));
+ f->store_line(E.key + " count: " + itos(E.value));
}
}
if (f) {
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 84fd6496a7..cbb033f6c6 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1960,8 +1960,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Vector<RES> save_order;
save_order.resize(external_resources.size());
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
- save_order.write[E->get()] = E->key();
+ for (const KeyValue<RES, int> &E : external_resources) {
+ save_order.write[E.value] = E.key;
}
for (int i = 0; i < save_order.size(); i++) {
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 3026236f07..2198761c2a 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -156,8 +156,8 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *
Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
Dictionary deps_dict;
- for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) {
- deps_dict[E->key()] = E->value();
+ for (KeyValue<String, String> E : p_map) {
+ deps_dict[E.key] = E.value;
}
int64_t err;
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index 97d683f415..290a71043c 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -126,8 +126,7 @@ String ResourceUID::get_id_path(ID p_id) const {
MutexLock l(mutex);
ERR_FAIL_COND_V(!unique_ids.has(p_id), String());
const CharString &cs = unique_ids[p_id].cs;
- String s(cs.ptr());
- return s;
+ return String::utf8(cs.ptr());
}
void ResourceUID::remove_id(ID p_id) {
MutexLock l(mutex);
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 27f8d4e88f..8ab025dda1 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -410,6 +410,63 @@ void StreamPeer::_bind_methods() {
////////////////////////////////
+int StreamPeerExtension::get_available_bytes() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_bytes, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_available_bytes is unimplemented!");
+ return -1;
+}
+
+Error StreamPeerExtension::get_data(uint8_t *r_buffer, int p_bytes) {
+ int err;
+ int received = 0;
+ if (GDVIRTUAL_CALL(_get_data, r_buffer, p_bytes, &received, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::get_partial_data(uint8_t *r_buffer, int p_bytes, int &r_received) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_partial_data, r_buffer, p_bytes, &r_received, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_get_partial_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::put_data(const uint8_t *p_data, int p_bytes) {
+ int err;
+ int sent = 0;
+ if (GDVIRTUAL_CALL(_put_data, p_data, p_bytes, &sent, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_put_data is unimplemented!");
+ return FAILED;
+}
+
+Error StreamPeerExtension::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_data, p_data, p_bytes, &r_sent, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("StreamPeerExtension::_put_partial_data is unimplemented!");
+ return FAILED;
+}
+
+void StreamPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_data, "r_buffer", "r_bytes", "r_received");
+ GDVIRTUAL_BIND(_get_partial_data, "r_buffer", "r_bytes", "r_received");
+ GDVIRTUAL_BIND(_put_data, "p_data", "p_bytes", "r_sent");
+ GDVIRTUAL_BIND(_put_partial_data, "p_data", "p_bytes", "r_sent");
+ GDVIRTUAL_BIND(_get_available_bytes);
+}
+
+////////////////////////////////
+
void StreamPeerBuffer::_bind_methods() {
ClassDB::bind_method(D_METHOD("seek", "position"), &StreamPeerBuffer::seek);
ClassDB::bind_method(D_METHOD("get_size"), &StreamPeerBuffer::get_size);
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index effc3850af..89432951c5 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -33,6 +33,10 @@
#include "core/object/ref_counted.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class StreamPeer : public RefCounted {
GDCLASS(StreamPeer, RefCounted);
OBJ_CATEGORY("Networking");
@@ -58,6 +62,7 @@ public:
virtual int get_available_bytes() const = 0;
+ /* helpers */
void set_big_endian(bool p_big_endian);
bool is_big_endian_enabled() const;
@@ -92,6 +97,26 @@ public:
StreamPeer() {}
};
+class StreamPeerExtension : public StreamPeer {
+ GDCLASS(StreamPeerExtension, StreamPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Error put_data(const uint8_t *p_data, int p_bytes) override;
+ virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
+ virtual Error get_data(uint8_t *p_buffer, int p_bytes) override;
+ virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
+ virtual int get_available_bytes() const override;
+
+ GDVIRTUAL3R(int, _put_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _put_partial_data, GDNativeConstPtr<const uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _get_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL3R(int, _get_partial_data, GDNativePtr<uint8_t>, int, GDNativePtr<int>);
+ GDVIRTUAL0RC(int, _get_available_bytes);
+};
+
class StreamPeerBuffer : public StreamPeer {
GDCLASS(StreamPeerBuffer, StreamPeer);
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 33aa65f15d..51a1309f0e 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -52,8 +52,8 @@ void AABB::merge_with(const AABB &p_aabb) {
beg_1 = position;
beg_2 = p_aabb.position;
- end_1 = Vector3(size.x, size.y, size.z) + beg_1;
- end_2 = Vector3(p_aabb.size.x, p_aabb.size.y, p_aabb.size.z) + beg_2;
+ end_1 = size + beg_1;
+ end_2 = p_aabb.size + beg_2;
min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x;
min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y;
diff --git a/core/math/aabb.h b/core/math/aabb.h
index e16246902a..97d92fbe37 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -118,6 +118,10 @@ public:
return position + size;
}
+ _FORCE_INLINE_ Vector3 get_center() const {
+ return position + (size * 0.5);
+ }
+
operator String() const;
_FORCE_INLINE_ AABB() {}
diff --git a/core/math/bvh_cull.inc b/core/math/bvh_cull.inc
index cba8ea6cb3..d7edc8a884 100644
--- a/core/math/bvh_cull.inc
+++ b/core/math/bvh_cull.inc
@@ -14,7 +14,7 @@ struct CullParams {
uint32_t pairable_type;
// optional components for different tests
- Vector3 point;
+ Point point;
BVHABB_CLASS abb;
typename BVHABB_CLASS::ConvexHull hull;
typename BVHABB_CLASS::Segment segment;
diff --git a/core/math/bvh_debug.inc b/core/math/bvh_debug.inc
index a97304334c..55db794ee3 100644
--- a/core/math/bvh_debug.inc
+++ b/core/math/bvh_debug.inc
@@ -6,24 +6,21 @@ void _debug_recursive_print_tree(int p_tree_id) const {
}
String _debug_aabb_to_string(const BVHABB_CLASS &aabb) const {
- String sz = "(";
- sz += itos(aabb.min.x);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.x);
- sz += ") (";
+ Point size = aabb.calculate_size();
- sz += itos(aabb.min.y);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.y);
- sz += ") (";
+ String sz;
+ float vol = 0.0;
- sz += itos(aabb.min.z);
- sz += " ~ ";
- sz += itos(-aabb.neg_max.z);
- sz += ") ";
+ for (int i = 0; i < Point::AXES_COUNT; ++i) {
+ sz += "(";
+ sz += itos(aabb.min[i]);
+ sz += " ~ ";
+ sz += itos(-aabb.neg_max[i]);
+ sz += ") ";
+
+ vol += size[i];
+ }
- Vector3 size = aabb.calculate_size();
- float vol = size.x * size.y * size.z;
sz += "vol " + itos(vol);
return sz;
diff --git a/core/math/bvh_split.inc b/core/math/bvh_split.inc
index 3fcc4c7b10..6f54d06ce7 100644
--- a/core/math/bvh_split.inc
+++ b/core/math/bvh_split.inc
@@ -28,11 +28,15 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
Point centre = full_bound.calculate_centre();
Point size = full_bound.calculate_size();
- int order[3];
+ int order[Point::AXIS_COUNT];
order[0] = size.min_axis();
- order[2] = size.max_axis();
- order[1] = 3 - (order[0] + order[2]);
+ order[Point::AXIS_COUNT - 1] = size.max_axis();
+
+ static_assert(Point::AXIS_COUNT <= 3);
+ if (Point::AXIS_COUNT == 3) {
+ order[1] = 3 - (order[0] + order[2]);
+ }
// simplest case, split on the longest axis
int split_axis = order[0];
@@ -54,7 +58,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
// detect when split on longest axis failed
int min_threshold = MAX_ITEMS / 4;
- int min_group_size[3];
+ int min_group_size[Point::AXIS_COUNT];
min_group_size[0] = MIN(num_a, num_b);
if (min_group_size[0] < min_threshold) {
// slow but sure .. first move everything back into a
@@ -64,7 +68,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
num_b = 0;
// now calculate the best split
- for (int axis = 1; axis < 3; axis++) {
+ for (int axis = 1; axis < Point::AXIS_COUNT; axis++) {
split_axis = order[axis];
int count = 0;
@@ -82,7 +86,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
// best axis
int best_axis = 0;
int best_min = min_group_size[0];
- for (int axis = 1; axis < 3; axis++) {
+ for (int axis = 1; axis < Point::AXIS_COUNT; axis++) {
if (min_group_size[axis] > best_min) {
best_min = min_group_size[axis];
best_axis = axis;
diff --git a/core/math/delaunay_2d.h b/core/math/delaunay_2d.h
index 95064e5700..2f80cb5634 100644
--- a/core/math/delaunay_2d.h
+++ b/core/math/delaunay_2d.h
@@ -101,7 +101,7 @@ public:
}
float delta_max = MAX(rect.size.width, rect.size.height);
- Vector2 center = rect.position + rect.size * 0.5;
+ Vector2 center = rect.get_center();
points.push_back(Vector2(center.x - 20 * delta_max, center.y - delta_max));
points.push_back(Vector2(center.x, center.y + 20 * delta_max));
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 9af3f868d2..045ab67ce8 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -151,8 +151,8 @@ Face3::Side Face3::get_side_of(const Face3 &p_face, ClockDirection p_clock_dir)
}
Vector3 Face3::get_random_point_inside() const {
- real_t a = Math::random(0, 1);
- real_t b = Math::random(0, 1);
+ real_t a = Math::random(0.0, 1.0);
+ real_t b = Math::random(0.0, 1.0);
if (a > b) {
SWAP(a, b);
}
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index 0960fe19a6..d438a9a377 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -265,8 +265,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
//create new faces from horizon edges
List<List<Face>::Element *> new_faces; //new faces
- for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) {
- FaceConnect &fc = E->get();
+ for (KeyValue<Edge, FaceConnect> &E : lit_edges) {
+ FaceConnect &fc = E.value;
if (fc.left && fc.right) {
continue; //edge is uninteresting, not on horizon
}
@@ -275,8 +275,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
Face face;
face.vertices[0] = f.points_over[next];
- face.vertices[1] = E->key().vertices[0];
- face.vertices[2] = E->key().vertices[1];
+ face.vertices[1] = E.key.vertices[0];
+ face.vertices[2] = E.key.vertices[1];
Plane p(p_points[face.vertices[0]], p_points[face.vertices[1]], p_points[face.vertices[2]]);
@@ -418,13 +418,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
// remove all edge connections to this face
- for (Map<Edge, RetFaceConnect>::Element *G = ret_edges.front(); G; G = G->next()) {
- if (G->get().left == O) {
- G->get().left = nullptr;
+ for (KeyValue<Edge, RetFaceConnect> &G : ret_edges) {
+ if (G.value.left == O) {
+ G.value.left = nullptr;
}
- if (G->get().right == O) {
- G->get().right = nullptr;
+ if (G.value.right == O) {
+ G.value.right = nullptr;
}
}
@@ -444,10 +444,10 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
r_mesh.edges.resize(ret_edges.size());
idx = 0;
- for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
+ for (const KeyValue<Edge, RetFaceConnect> &E : ret_edges) {
Geometry3D::MeshData::Edge e;
- e.a = E->key().vertices[0];
- e.b = E->key().vertices[1];
+ e.a = E.key.vertices[0];
+ e.b = E.key.vertices[1];
r_mesh.edges.write[idx++] = e;
}
diff --git a/core/math/rect2.h b/core/math/rect2.h
index ab0b489b4a..2557959fa2 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -46,6 +46,8 @@ struct Rect2 {
real_t get_area() const { return size.width * size.height; }
+ _FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); }
+
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
if (p_include_borders) {
if (position.x > (p_rect.position.x + p_rect.size.width)) {
@@ -259,7 +261,7 @@ struct Rect2 {
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
- Vector2 center = position + size * 0.5;
+ Vector2 center = get_center();
int side_plus = 0;
int side_minus = 0;
Vector2 end = position + size;
@@ -344,6 +346,8 @@ struct Rect2i {
int get_area() const { return size.width * size.height; }
+ _FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
+
inline bool intersects(const Rect2i &p_rect) const {
if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false;
diff --git a/core/math/static_raycaster.cpp b/core/math/static_raycaster.cpp
new file mode 100644
index 0000000000..da05d49428
--- /dev/null
+++ b/core/math/static_raycaster.cpp
@@ -0,0 +1,40 @@
+/*************************************************************************/
+/* static_raycaster.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "static_raycaster.h"
+
+StaticRaycaster *(*StaticRaycaster::create_function)() = nullptr;
+
+Ref<StaticRaycaster> StaticRaycaster::create() {
+ if (create_function) {
+ return Ref<StaticRaycaster>(create_function());
+ }
+ return Ref<StaticRaycaster>();
+}
diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h
new file mode 100644
index 0000000000..3759c788a7
--- /dev/null
+++ b/core/math/static_raycaster.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* static_raycaster.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 STATIC_RAYCASTER_H
+#define STATIC_RAYCASTER_H
+
+#include "core/object/ref_counted.h"
+
+#if !defined(__aligned)
+
+#if defined(_WIN32) && defined(_MSC_VER)
+#define __aligned(...) __declspec(align(__VA_ARGS__))
+#else
+#define __aligned(...) __attribute__((aligned(__VA_ARGS__)))
+#endif
+
+#endif
+
+class StaticRaycaster : public RefCounted {
+ GDCLASS(StaticRaycaster, RefCounted)
+protected:
+ static StaticRaycaster *(*create_function)();
+
+public:
+ // compatible with embree3 rays
+ struct __aligned(16) Ray {
+ const static unsigned int INVALID_GEOMETRY_ID = ((unsigned int)-1); // from rtcore_common.h
+
+ /*! Default construction does nothing. */
+ _FORCE_INLINE_ Ray() :
+ geomID(INVALID_GEOMETRY_ID) {}
+
+ /*! Constructs a ray from origin, direction, and ray segment. Near
+ * has to be smaller than far. */
+ _FORCE_INLINE_ Ray(const Vector3 &org,
+ const Vector3 &dir,
+ float tnear = 0.0f,
+ float tfar = INFINITY) :
+ org(org),
+ tnear(tnear),
+ dir(dir),
+ time(0.0f),
+ tfar(tfar),
+ mask(-1),
+ u(0.0),
+ v(0.0),
+ primID(INVALID_GEOMETRY_ID),
+ geomID(INVALID_GEOMETRY_ID),
+ instID(INVALID_GEOMETRY_ID) {}
+
+ /*! Tests if we hit something. */
+ _FORCE_INLINE_ explicit operator bool() const { return geomID != INVALID_GEOMETRY_ID; }
+
+ public:
+ Vector3 org; //!< Ray origin + tnear
+ float tnear; //!< Start of ray segment
+ Vector3 dir; //!< Ray direction + tfar
+ float time; //!< Time of this ray for motion blur.
+ float tfar; //!< End of ray segment
+ unsigned int mask; //!< used to mask out objects during traversal
+ unsigned int id; //!< ray ID
+ unsigned int flags; //!< ray flags
+
+ Vector3 normal; //!< Not normalized geometry normal
+ float u; //!< Barycentric u coordinate of hit
+ float v; //!< Barycentric v coordinate of hit
+ unsigned int primID; //!< primitive ID
+ unsigned int geomID; //!< geometry ID
+ unsigned int instID; //!< instance ID
+ };
+
+ virtual bool intersect(Ray &p_ray) = 0;
+ virtual void intersect(Vector<Ray> &r_rays) = 0;
+
+ virtual void add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) = 0;
+ virtual void commit() = 0;
+
+ virtual void set_mesh_filter(const Set<int> &p_mesh_ids) = 0;
+ virtual void clear_mesh_filter() = 0;
+
+ static Ref<StaticRaycaster> create();
+};
+
+#endif // STATIC_RAYCASTER_H
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 16934d67df..496a557844 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -63,7 +63,7 @@ Transform2D Transform2D::affine_inverse() const {
return inv;
}
-void Transform2D::rotate(real_t p_phi) {
+void Transform2D::rotate(const real_t p_phi) {
*this = Transform2D(p_phi, Vector2()) * (*this);
}
@@ -72,7 +72,7 @@ real_t Transform2D::get_skew() const {
return Math::acos(elements[0].normalized().dot(SGN(det) * elements[1].normalized())) - Math_PI * 0.5;
}
-void Transform2D::set_skew(float p_angle) {
+void Transform2D::set_skew(const real_t p_angle) {
real_t det = basis_determinant();
elements[1] = SGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length();
}
@@ -81,7 +81,7 @@ real_t Transform2D::get_rotation() const {
return Math::atan2(elements[0].y, elements[0].x);
}
-void Transform2D::set_rotation(real_t p_rot) {
+void Transform2D::set_rotation(const real_t p_rot) {
Size2 scale = get_scale();
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
@@ -92,7 +92,7 @@ void Transform2D::set_rotation(real_t p_rot) {
set_scale(scale);
}
-Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
+Transform2D::Transform2D(const real_t p_rot, const Vector2 &p_pos) {
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
elements[0][0] = cr;
@@ -102,6 +102,14 @@ Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
elements[2] = p_pos;
}
+Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) {
+ elements[0][0] = Math::cos(p_rot) * p_scale.x;
+ elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
+ elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
+ elements[0][1] = Math::sin(p_rot) * p_scale.x;
+ elements[2] = p_pos;
+}
+
Size2 Transform2D::get_scale() const {
real_t det_sign = SGN(basis_determinant());
return Size2(elements[0].length(), det_sign * elements[1].length());
@@ -126,7 +134,7 @@ void Transform2D::scale_basis(const Size2 &p_scale) {
elements[1][1] *= p_scale.y;
}
-void Transform2D::translate(real_t p_tx, real_t p_ty) {
+void Transform2D::translate(const real_t p_tx, const real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
@@ -231,7 +239,7 @@ Transform2D Transform2D::translated(const Vector2 &p_offset) const {
return copy;
}
-Transform2D Transform2D::rotated(real_t p_phi) const {
+Transform2D Transform2D::rotated(const real_t p_phi) const {
Transform2D copy = *this;
copy.rotate(p_phi);
return copy;
@@ -241,7 +249,7 @@ real_t Transform2D::basis_determinant() const {
return elements[0].x * elements[1].y - elements[0].y * elements[1].x;
}
-Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_c) const {
+Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const {
//extract parameters
Vector2 p1 = get_origin();
Vector2 p2 = p_transform.get_origin();
@@ -271,7 +279,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
}
//construct matrix
- Transform2D res(Math::atan2(v.y, v.x), p1.lerp(p2, p_c));
+ Transform2D res(v.angle(), p1.lerp(p2, p_c));
res.scale_basis(s1.lerp(s2, p_c));
return res;
}
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 34cfd0c1a9..6ed3af2ba7 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -68,17 +68,17 @@ struct Transform2D {
void affine_invert();
Transform2D affine_inverse() const;
- void set_rotation(real_t p_rot);
+ void set_rotation(const real_t p_rot);
real_t get_rotation() const;
real_t get_skew() const;
- void set_skew(float p_angle);
- _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
- _FORCE_INLINE_ void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew);
- void rotate(real_t p_phi);
+ void set_skew(const real_t p_angle);
+ _FORCE_INLINE_ void set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale);
+ _FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew);
+ void rotate(const real_t p_phi);
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
- void translate(real_t p_tx, real_t p_ty);
+ void translate(const real_t p_tx, const real_t p_ty);
void translate(const Vector2 &p_translation);
real_t basis_determinant() const;
@@ -92,7 +92,7 @@ struct Transform2D {
Transform2D scaled(const Size2 &p_scale) const;
Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
- Transform2D rotated(real_t p_phi) const;
+ Transform2D rotated(const real_t p_phi) const;
Transform2D untranslated() const;
@@ -110,7 +110,7 @@ struct Transform2D {
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
- Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
+ Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const;
_FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const;
@@ -123,7 +123,7 @@ struct Transform2D {
operator String() const;
- Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
+ Transform2D(const real_t xx, const real_t xy, const real_t yx, const real_t yy, const real_t ox, const real_t oy) {
elements[0][0] = xx;
elements[0][1] = xy;
elements[1][0] = yx;
@@ -138,7 +138,10 @@ struct Transform2D {
elements[2] = p_origin;
}
- Transform2D(real_t p_rot, const Vector2 &p_pos);
+ Transform2D(const real_t p_rot, const Vector2 &p_pos);
+
+ Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos);
+
Transform2D() {
elements[0][0] = 1.0;
elements[1][1] = 1.0;
@@ -185,14 +188,14 @@ Rect2 Transform2D::xform(const Rect2 &p_rect) const {
return new_rect;
}
-void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
+void Transform2D::set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale) {
elements[0][0] = Math::cos(p_rot) * p_scale.x;
elements[1][1] = Math::cos(p_rot) * p_scale.y;
elements[1][0] = -Math::sin(p_rot) * p_scale.y;
elements[0][1] = Math::sin(p_rot) * p_scale.x;
}
-void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew) {
+void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) {
elements[0][0] = Math::cos(p_rot) * p_scale.x;
elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index bf06c848c5..2f3da0b6a8 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -76,7 +76,7 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in
int index = r_max_alloc++;
BVH *_new = &p_bvh[index];
_new->aabb = aabb;
- _new->center = aabb.position + aabb.size * 0.5;
+ _new->center = aabb.get_center();
_new->face_index = -1;
_new->left = left;
_new->right = right;
@@ -152,13 +152,13 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) {
bw[i].left = -1;
bw[i].right = -1;
bw[i].face_index = i;
- bw[i].center = bw[i].aabb.position + bw[i].aabb.size * 0.5;
+ bw[i].center = bw[i].aabb.get_center();
}
vertices.resize(db.size());
Vector3 *vw = vertices.ptrw();
- for (Map<Vector3, int>::Element *E = db.front(); E; E = E->next()) {
- vw[E->get()] = E->key();
+ for (const KeyValue<Vector3, int> &E : db) {
+ vw[E.value] = E.key;
}
}
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index b53dc05a00..16e43d7d06 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -79,7 +79,7 @@ real_t Vector2::angle_to(const Vector2 &p_vector2) const {
}
real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
- return Math::atan2(y - p_vector2.y, x - p_vector2.x);
+ return (*this - p_vector2).angle();
}
real_t Vector2::dot(const Vector2 &p_other) const {
diff --git a/core/multiplayer/multiplayer_peer.cpp b/core/multiplayer/multiplayer_peer.cpp
index 40847102d8..3c33948e2f 100644
--- a/core/multiplayer/multiplayer_peer.cpp
+++ b/core/multiplayer/multiplayer_peer.cpp
@@ -53,6 +53,30 @@ uint32_t MultiplayerPeer::generate_unique_id() const {
return hash;
}
+void MultiplayerPeer::set_transfer_channel(int p_channel) {
+ transfer_channel = p_channel;
+}
+
+int MultiplayerPeer::get_transfer_channel() const {
+ return transfer_channel;
+}
+
+void MultiplayerPeer::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+ transfer_mode = p_mode;
+}
+
+Multiplayer::TransferMode MultiplayerPeer::get_transfer_mode() const {
+ return transfer_mode;
+}
+
+void MultiplayerPeer::set_refuse_new_connections(bool p_enable) {
+ refuse_connections = p_enable;
+}
+
+bool MultiplayerPeer::is_refusing_new_connections() const {
+ return refuse_connections;
+}
+
void MultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &MultiplayerPeer::set_transfer_channel);
ClassDB::bind_method(D_METHOD("get_transfer_channel"), &MultiplayerPeer::get_transfer_channel);
@@ -88,3 +112,160 @@ void MultiplayerPeer::_bind_methods() {
ADD_SIGNAL(MethodInfo("connection_succeeded"));
ADD_SIGNAL(MethodInfo("connection_failed"));
}
+
+/*************/
+
+int MultiplayerPeerExtension::get_available_packet_count() const {
+ int count;
+ if (GDVIRTUAL_CALL(_get_available_packet_count, count)) {
+ return count;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_available_packet_count is unimplemented!");
+ return -1;
+}
+
+Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_native is unimplemented!");
+ return FAILED;
+}
+
+Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+ int err;
+ if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
+ return (Error)err;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!");
+ return FAILED;
+}
+
+int MultiplayerPeerExtension::get_max_packet_size() const {
+ int size;
+ if (GDVIRTUAL_CALL(_get_max_packet_size, size)) {
+ return size;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_max_packet_size is unimplemented!");
+ return 0;
+}
+
+void MultiplayerPeerExtension::set_transfer_channel(int p_channel) {
+ if (GDVIRTUAL_CALL(_set_transfer_channel, p_channel)) {
+ return;
+ }
+ MultiplayerPeer::set_transfer_channel(p_channel);
+}
+
+int MultiplayerPeerExtension::get_transfer_channel() const {
+ int channel;
+ if (GDVIRTUAL_CALL(_get_transfer_channel, channel)) {
+ return channel;
+ }
+ return MultiplayerPeer::get_transfer_channel();
+}
+
+void MultiplayerPeerExtension::set_transfer_mode(Multiplayer::TransferMode p_mode) {
+ if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) {
+ return;
+ }
+ MultiplayerPeer::set_transfer_mode(p_mode);
+}
+
+Multiplayer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
+ int mode;
+ if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) {
+ return (Multiplayer::TransferMode)mode;
+ }
+ return MultiplayerPeer::get_transfer_mode();
+}
+
+void MultiplayerPeerExtension::set_target_peer(int p_peer_id) {
+ if (GDVIRTUAL_CALL(_set_target_peer, p_peer_id)) {
+ return;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_set_target_peer is unimplemented!");
+}
+
+int MultiplayerPeerExtension::get_packet_peer() const {
+ int peer;
+ if (GDVIRTUAL_CALL(_get_packet_peer, peer)) {
+ return peer;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_peer is unimplemented!");
+ return 0;
+}
+
+bool MultiplayerPeerExtension::is_server() const {
+ bool server;
+ if (GDVIRTUAL_CALL(_is_server, server)) {
+ return server;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_is_server is unimplemented!");
+ return false;
+}
+
+void MultiplayerPeerExtension::poll() {
+ int err;
+ if (GDVIRTUAL_CALL(_poll, err)) {
+ return;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_poll is unimplemented!");
+}
+
+int MultiplayerPeerExtension::get_unique_id() const {
+ int id;
+ if (GDVIRTUAL_CALL(_get_unique_id, id)) {
+ return id;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_unique_id is unimplemented!");
+ return 0;
+}
+
+void MultiplayerPeerExtension::set_refuse_new_connections(bool p_enable) {
+ if (GDVIRTUAL_CALL(_set_refuse_new_connections, p_enable)) {
+ return;
+ }
+ MultiplayerPeer::set_refuse_new_connections(p_enable);
+}
+
+bool MultiplayerPeerExtension::is_refusing_new_connections() const {
+ bool refusing;
+ if (GDVIRTUAL_CALL(_is_refusing_new_connections, refusing)) {
+ return refusing;
+ }
+ return MultiplayerPeer::is_refusing_new_connections();
+}
+
+MultiplayerPeer::ConnectionStatus MultiplayerPeerExtension::get_connection_status() const {
+ int status;
+ if (GDVIRTUAL_CALL(_get_connection_status, status)) {
+ return (ConnectionStatus)status;
+ }
+ WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_connection_status is unimplemented!");
+ return CONNECTION_DISCONNECTED;
+}
+
+void MultiplayerPeerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size");
+ GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size");
+ GDVIRTUAL_BIND(_get_available_packet_count);
+ GDVIRTUAL_BIND(_get_max_packet_size);
+
+ GDVIRTUAL_BIND(_set_transfer_channel, "p_channel");
+ GDVIRTUAL_BIND(_get_transfer_channel);
+
+ GDVIRTUAL_BIND(_set_transfer_mode, "p_mode");
+ GDVIRTUAL_BIND(_get_transfer_mode);
+
+ GDVIRTUAL_BIND(_set_target_peer, "p_peer");
+
+ GDVIRTUAL_BIND(_get_packet_peer);
+ GDVIRTUAL_BIND(_is_server);
+ GDVIRTUAL_BIND(_poll);
+ GDVIRTUAL_BIND(_get_unique_id);
+ GDVIRTUAL_BIND(_set_refuse_new_connections, "p_enable");
+ GDVIRTUAL_BIND(_is_refusing_new_connections);
+ GDVIRTUAL_BIND(_get_connection_status);
+}
diff --git a/core/multiplayer/multiplayer_peer.h b/core/multiplayer/multiplayer_peer.h
index ba00c3b41b..126ba9e645 100644
--- a/core/multiplayer/multiplayer_peer.h
+++ b/core/multiplayer/multiplayer_peer.h
@@ -34,12 +34,21 @@
#include "core/io/packet_peer.h"
#include "core/multiplayer/multiplayer.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+
class MultiplayerPeer : public PacketPeer {
GDCLASS(MultiplayerPeer, PacketPeer);
protected:
static void _bind_methods();
+private:
+ int transfer_channel = 0;
+ Multiplayer::TransferMode transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
+ bool refuse_connections = false;
+
public:
enum {
TARGET_PEER_BROADCAST = 0,
@@ -52,10 +61,13 @@ public:
CONNECTION_CONNECTED,
};
- virtual void set_transfer_channel(int p_channel) = 0;
- virtual int get_transfer_channel() const = 0;
- virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) = 0;
- virtual Multiplayer::TransferMode get_transfer_mode() const = 0;
+ virtual void set_transfer_channel(int p_channel);
+ virtual int get_transfer_channel() const;
+ virtual void set_transfer_mode(Multiplayer::TransferMode p_mode);
+ virtual Multiplayer::TransferMode get_transfer_mode() const;
+ virtual void set_refuse_new_connections(bool p_enable);
+ virtual bool is_refusing_new_connections() const;
+
virtual void set_target_peer(int p_peer_id) = 0;
virtual int get_packet_peer() const = 0;
@@ -66,15 +78,67 @@ public:
virtual int get_unique_id() const = 0;
- virtual void set_refuse_new_connections(bool p_enable) = 0;
- virtual bool is_refusing_new_connections() const = 0;
-
virtual ConnectionStatus get_connection_status() const = 0;
+
uint32_t generate_unique_id() const;
MultiplayerPeer() {}
};
-VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus)
+VARIANT_ENUM_CAST(MultiplayerPeer::ConnectionStatus);
+
+class MultiplayerPeerExtension : public MultiplayerPeer {
+ GDCLASS(MultiplayerPeerExtension, MultiplayerPeer);
+
+protected:
+ static void _bind_methods();
+
+public:
+ /* PacketPeer */
+ virtual int get_available_packet_count() const override;
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
+ virtual int get_max_packet_size() const override;
+
+ /* MultiplayerPeer */
+ virtual void set_transfer_channel(int p_channel) override;
+ virtual int get_transfer_channel() const override;
+ virtual void set_transfer_mode(Multiplayer::TransferMode p_mode) override;
+ virtual Multiplayer::TransferMode get_transfer_mode() const override;
+ virtual void set_target_peer(int p_peer_id) override;
+
+ virtual int get_packet_peer() const override;
+
+ virtual bool is_server() const override;
+
+ virtual void poll() override;
+
+ virtual int get_unique_id() const override;
+
+ virtual void set_refuse_new_connections(bool p_enable) override;
+ virtual bool is_refusing_new_connections() const override;
+
+ virtual ConnectionStatus get_connection_status() const override;
+
+ /* PacketPeer GDExtension */
+ GDVIRTUAL0RC(int, _get_available_packet_count);
+ GDVIRTUAL2R(int, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL0RC(int, _get_max_packet_size);
+
+ /* MultiplayerPeer GDExtension */
+ GDVIRTUAL1(_set_transfer_channel, int);
+ GDVIRTUAL0RC(int, _get_transfer_channel);
+ GDVIRTUAL1(_set_transfer_mode, int);
+ GDVIRTUAL0RC(int, _get_transfer_mode);
+ GDVIRTUAL1(_set_target_peer, int);
+ GDVIRTUAL0RC(int, _get_packet_peer);
+ GDVIRTUAL0RC(bool, _is_server);
+ GDVIRTUAL0R(int, _poll);
+ GDVIRTUAL0RC(int, _get_unique_id);
+ GDVIRTUAL1(_set_refuse_new_connections, bool);
+ GDVIRTUAL0RC(bool, _is_refusing_new_connections);
+ GDVIRTUAL0RC(int, _get_connection_status);
+};
#endif // NETWORKED_MULTIPLAYER_PEER_H
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 8e92340c1e..8ba46e49eb 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -545,6 +545,15 @@ Object *ClassDB::instantiate(const StringName &p_class) {
return ti->creation_func();
}
+Object *ClassDB::construct_object(Object *(*p_create_func)(), ObjectNativeExtension *p_extension) {
+ if (p_extension) {
+ initializing_with_extension = true;
+ initializing_extension = p_extension;
+ initializing_extension_instance = p_extension->create_instance(p_extension->class_userdata);
+ }
+ return p_create_func();
+}
+
bool ClassDB::can_instantiate(const StringName &p_class) {
OBJTYPE_RLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index e89c7fffd7..3a1cbf8559 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -234,6 +234,7 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
+ static Object *construct_object(Object *(*p_create_func)(), ObjectNativeExtension *p_extension);
static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance, Object *p_base);
static APIType get_api_type(const StringName &p_class);
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 4751c69f1e..736e940846 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -227,16 +227,16 @@ void MessageQueue::statistics() {
print_line("TOTAL BYTES: " + itos(buffer_end));
print_line("NULL count: " + itos(null_count));
- for (Map<StringName, int>::Element *E = set_count.front(); E; E = E->next()) {
- print_line("SET " + E->key() + ": " + itos(E->get()));
+ for (const KeyValue<StringName, int> &E : set_count) {
+ print_line("SET " + E.key + ": " + itos(E.value));
}
- for (Map<Callable, int>::Element *E = call_count.front(); E; E = E->next()) {
- print_line("CALL " + E->key() + ": " + itos(E->get()));
+ for (const KeyValue<Callable, int> &E : call_count) {
+ print_line("CALL " + E.key + ": " + itos(E.value));
}
- for (Map<int, int>::Element *E = notify_count.front(); E; E = E->next()) {
- print_line("NOTIFY " + itos(E->key()) + ": " + itos(E->get()));
+ for (const KeyValue<int, int> &E : notify_count) {
+ print_line("NOTIFY " + itos(E.key) + ": " + itos(E.value));
}
}
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 0fb8c7350c..b0ce46ca2b 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -93,8 +93,8 @@ Dictionary Script::_get_script_constant_map() {
Dictionary ret;
Map<StringName, Variant> map;
get_constants(&map);
- for (Map<StringName, Variant>::Element *E = map.front(); E; E = E->next()) {
- ret[E->key()] = E->value();
+ for (const KeyValue<StringName, Variant> &E : map) {
+ ret[E.key] = E.value;
}
return ret;
}
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 7505f3ff34..69366f688c 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -282,6 +282,11 @@ String OS::get_bundle_resource_dir() const {
return ".";
}
+// Path to macOS .app bundle embedded icon
+String OS::get_bundle_icon_path() const {
+ return String();
+}
+
// OS specific path for user://
String OS::get_user_data_dir() const {
return ".";
diff --git a/core/os/os.h b/core/os/os.h
index c027428477..29d33ce4f0 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -252,6 +252,7 @@ public:
virtual String get_config_path() const;
virtual String get_cache_path() const;
virtual String get_bundle_resource_dir() const;
+ virtual String get_bundle_icon_path() const;
virtual String get_user_data_dir() const;
virtual String get_resource_dir() const;
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 92e43963d2..27aefc98de 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -28,9 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Define PLATFORM_CUSTOM_THREAD_H in platform_config.h
-// Overriding the platform implementation is required in some proprietary platforms
-#ifndef PLATFORM_CUSTOM_THREAD_H
+#ifndef PLATFORM_THREAD_OVERRIDE // See details in thread.h
#include "thread.h"
@@ -130,4 +128,4 @@ Thread::~Thread() {
}
#endif
-#endif // PLATFORM_CUSTOM_THREAD_H
+#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/os/thread.h b/core/os/thread.h
index 3a0938c7f7..59cb58ac57 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -28,10 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Define PLATFORM_CUSTOM_THREAD_H in platform_config.h
+// Define PLATFORM_THREAD_OVERRIDE in your platform's `platform_config.h`
+// to use a custom Thread implementation defined in `platform/[your_platform]/platform_thread.h`
// Overriding the platform implementation is required in some proprietary platforms
-#ifdef PLATFORM_CUSTOM_THREAD_H
-#include PLATFORM_CUSTOM_THREAD_H
+#ifdef PLATFORM_THREAD_OVERRIDE
+#include "platform_thread.h"
#else
#ifndef THREAD_H
#define THREAD_H
@@ -121,4 +122,4 @@ public:
};
#endif // THREAD_H
-#endif // PLATFORM_CUSTOM_THREAD_H
+#endif // PLATFORM_THREAD_OVERRIDE
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 3a037f9dd1..e33c21cc00 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -169,11 +169,13 @@ void register_core_types() {
GDREGISTER_VIRTUAL_CLASS(IP);
GDREGISTER_VIRTUAL_CLASS(StreamPeer);
+ GDREGISTER_CLASS(StreamPeerExtension);
GDREGISTER_CLASS(StreamPeerBuffer);
GDREGISTER_CLASS(StreamPeerTCP);
GDREGISTER_CLASS(TCPServer);
GDREGISTER_VIRTUAL_CLASS(PacketPeer);
+ GDREGISTER_CLASS(PacketPeerExtension);
GDREGISTER_CLASS(PacketPeerStream);
GDREGISTER_CLASS(PacketPeerUDP);
GDREGISTER_CLASS(UDPServer);
@@ -197,6 +199,7 @@ void register_core_types() {
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
+ GDREGISTER_VIRTUAL_CLASS(MultiplayerPeerExtension);
GDREGISTER_VIRTUAL_CLASS(MultiplayerReplicator);
GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index 5863bd1c46..839b7a9c01 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -162,11 +162,11 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
btw[btindex++] = t.size();
btw[btindex++] = hfunc_table[i];
- for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
- btw[btindex++] = E->key();
- btw[btindex++] = compressed[E->get()].offset;
- btw[btindex++] = compressed[E->get()].compressed.size();
- btw[btindex++] = compressed[E->get()].orig_len;
+ for (const KeyValue<uint32_t, int> &E : t) {
+ btw[btindex++] = E.key;
+ btw[btindex++] = compressed[E.value].offset;
+ btw[btindex++] = compressed[E.value].compressed.size();
+ btw[btindex++] = compressed[E.value].orig_len;
}
}
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index cb7d924556..5e3b8297aa 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -820,8 +820,8 @@ static const char *locale_renames[][2] = {
Dictionary Translation::_get_messages() const {
Dictionary d;
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- d[E->key()] = E->value();
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ d[E.key] = E.value;
}
return d;
}
@@ -830,8 +830,8 @@ Vector<String> Translation::_get_message_list() const {
Vector<String> msgs;
msgs.resize(translation_map.size());
int idx = 0;
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- msgs.set(idx, E->key());
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ msgs.set(idx, E.key);
idx += 1;
}
@@ -875,6 +875,11 @@ void Translation::add_plural_message(const StringName &p_src_text, const Vector<
}
StringName Translation::get_message(const StringName &p_src_text, const StringName &p_context) const {
+ StringName ret;
+ if (GDVIRTUAL_CALL(_get_message, p_src_text, p_context, ret)) {
+ return ret;
+ }
+
if (p_context != StringName()) {
WARN_PRINT("Translation class doesn't handle context. Using context in get_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles context, such as TranslationPO class");
}
@@ -888,6 +893,11 @@ StringName Translation::get_message(const StringName &p_src_text, const StringNa
}
StringName Translation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
+ StringName ret;
+ if (GDVIRTUAL_CALL(_get_plural_message, p_src_text, p_plural_text, p_n, p_context, ret)) {
+ return ret;
+ }
+
WARN_PRINT("Translation class doesn't handle plural messages. Calling get_plural_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles plurals, such as TranslationPO class");
return get_message(p_src_text);
}
@@ -901,8 +911,8 @@ void Translation::erase_message(const StringName &p_src_text, const StringName &
}
void Translation::get_message_list(List<StringName> *r_messages) const {
- for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
- r_messages->push_back(E->key());
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ r_messages->push_back(E.key);
}
}
@@ -923,6 +933,9 @@ void Translation::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_messages"), &Translation::_set_messages);
ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages);
+ GDVIRTUAL_BIND(_get_plural_message, "src_message", "src_plural_message", "n", "context");
+ GDVIRTUAL_BIND(_get_message, "src_message", "context");
+
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale");
}
diff --git a/core/string/translation.h b/core/string/translation.h
index 4f179ac0fe..6aec0bb8ea 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -32,6 +32,8 @@
#define TRANSLATION_H
#include "core/io/resource.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
class Translation : public Resource {
GDCLASS(Translation, Resource);
@@ -48,6 +50,9 @@ class Translation : public Resource {
protected:
static void _bind_methods();
+ GDVIRTUAL2RC(StringName, _get_message, StringName, StringName);
+ GDVIRTUAL4RC(StringName, _get_plural_message, StringName, StringName, int, StringName);
+
public:
void set_locale(const String &p_locale);
_FORCE_INLINE_ String get_locale() const { return locale; }
diff --git a/core/templates/pooled_list.h b/core/templates/pooled_list.h
index b4a6d2d1dd..b139dadb75 100644
--- a/core/templates/pooled_list.h
+++ b/core/templates/pooled_list.h
@@ -28,13 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#pragma once
+#ifndef POOLED_LIST_H
+#define POOLED_LIST_H
+
+#include "core/templates/local_vector.h"
// Simple template to provide a pool with O(1) allocate and free.
// The freelist could alternatively be a linked list placed within the unused elements
// to use less memory, however a separate freelist is probably more cache friendly.
-
-// NOTE : Take great care when using this with non POD types. The construction and destruction
+//
+// NOTE: Take great care when using this with non POD types. The construction and destruction
// is done in the LocalVector, NOT as part of the pool. So requesting a new item does not guarantee
// a constructor is run, and free does not guarantee a destructor.
// You should generally handle clearing
@@ -42,9 +45,6 @@
// This is by design for fastest use in the BVH. If you want a more general pool
// that does call constructors / destructors on request / free, this should probably be
// a separate template.
-
-#include "core/templates/local_vector.h"
-
template <class T, bool force_trivial = false>
class PooledList {
LocalVector<T, uint32_t, force_trivial> list;
@@ -93,3 +93,5 @@ public:
_used_size--;
}
};
+
+#endif // POOLED_LIST_H
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index e947d2211c..71d41eacc4 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -151,7 +151,7 @@ public:
return _allocate_rid();
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid, bool p_initialize = false) {
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid, bool p_initialize = false) {
if (p_rid == RID()) {
return nullptr;
}
@@ -210,12 +210,12 @@ public:
return ptr;
}
void initialize_rid(RID p_rid) {
- T *mem = getornull(p_rid, true);
+ T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
memnew_placement(mem, T);
}
void initialize_rid(RID p_rid, const T &p_value) {
- T *mem = getornull(p_rid, true);
+ T *mem = get_or_null(p_rid, true);
ERR_FAIL_COND(!mem);
memnew_placement(mem, T(p_value));
}
@@ -399,8 +399,8 @@ public:
alloc.initialize_rid(p_rid, p_ptr);
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid) {
- T **ptr = alloc.getornull(p_rid);
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid) {
+ T **ptr = alloc.get_or_null(p_rid);
if (unlikely(!ptr)) {
return nullptr;
}
@@ -408,7 +408,7 @@ public:
}
_FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) {
- T **ptr = alloc.getornull(p_rid);
+ T **ptr = alloc.get_or_null(p_rid);
ERR_FAIL_COND(!ptr);
*ptr = p_new_ptr;
}
@@ -469,8 +469,8 @@ public:
alloc.initialize_rid(p_rid, p_ptr);
}
- _FORCE_INLINE_ T *getornull(const RID &p_rid) {
- return alloc.getornull(p_rid);
+ _FORCE_INLINE_ T *get_or_null(const RID &p_rid) {
+ return alloc.get_or_null(p_rid);
}
_FORCE_INLINE_ bool owns(const RID &p_rid) {
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index f487e718f4..dcded6e61f 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -377,11 +377,11 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const {
return obj->emit_signal(name, p_arguments, p_argcount);
}
-Error Signal::connect(const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) {
+Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {
Object *object = get_object();
ERR_FAIL_COND_V(!object, ERR_UNCONFIGURED);
- return object->connect(name, p_callable, p_binds, p_flags);
+ return object->connect(name, p_callable, varray(), p_flags);
}
void Signal::disconnect(const Callable &p_callable) {
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 52094af3aa..de886492ea 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -159,7 +159,7 @@ public:
operator String() const;
Error emit(const Variant **p_arguments, int p_argcount) const;
- Error connect(const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
+ Error connect(const Callable &p_callable, uint32_t p_flags = 0);
void disconnect(const Callable &p_callable);
bool is_connected(const Callable &p_callable) const;
diff --git a/core/variant/native_ptr.h b/core/variant/native_ptr.h
index b4ec0df7d6..913d4d8f7c 100644
--- a/core/variant/native_ptr.h
+++ b/core/variant/native_ptr.h
@@ -55,7 +55,7 @@ struct GDNativePtr {
#define GDVIRTUAL_NATIVE_PTR(m_type) \
template <> \
- struct GDNativeConstPtr<m_type> { \
+ struct GDNativeConstPtr<const m_type> { \
const m_type *data = nullptr; \
GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \
static const char *get_name() { return "const " #m_type; } \
@@ -117,6 +117,7 @@ GDVIRTUAL_NATIVE_PTR(char16_t)
GDVIRTUAL_NATIVE_PTR(char32_t)
GDVIRTUAL_NATIVE_PTR(wchar_t)
GDVIRTUAL_NATIVE_PTR(uint8_t)
+GDVIRTUAL_NATIVE_PTR(uint8_t *)
GDVIRTUAL_NATIVE_PTR(int8_t)
GDVIRTUAL_NATIVE_PTR(uint16_t)
GDVIRTUAL_NATIVE_PTR(int16_t)
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 752195acc9..6284caae2d 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1241,8 +1241,8 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
- for (Map<StringName, int>::Element *E = cd.value.front(); E; E = E->next()) {
- p_constants->push_back(E->key());
+ for (const KeyValue<StringName, int> &E : cd.value) {
+ p_constants->push_back(E.key);
#endif
}
@@ -1250,8 +1250,8 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) {
p_constants->push_back(E->get());
#else
- for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) {
- p_constants->push_back(E->key());
+ for (const KeyValue<StringName, Variant> &E : cd.variant_value) {
+ p_constants->push_back(E.key);
#endif
}
}
@@ -1513,6 +1513,7 @@ static void _register_variant_builtin_methods() {
/* Rect2 */
+ bind_method(Rect2, get_center, sarray(), varray());
bind_method(Rect2, get_area, sarray(), varray());
bind_method(Rect2, has_no_area, sarray(), varray());
bind_method(Rect2, has_point, sarray("point"), varray());
@@ -1529,6 +1530,7 @@ static void _register_variant_builtin_methods() {
/* Rect2i */
+ bind_method(Rect2i, get_center, sarray(), varray());
bind_method(Rect2i, get_area, sarray(), varray());
bind_method(Rect2i, has_no_area, sarray(), varray());
bind_method(Rect2i, has_point, sarray("point"), varray());
@@ -1688,7 +1690,7 @@ static void _register_variant_builtin_methods() {
bind_method(Signal, get_object_id, sarray(), varray());
bind_method(Signal, get_name, sarray(), varray());
- bind_method(Signal, connect, sarray("callable", "binds", "flags"), varray(Array(), 0));
+ bind_method(Signal, connect, sarray("callable", "flags"), varray(0));
bind_method(Signal, disconnect, sarray("callable"), varray());
bind_method(Signal, is_connected, sarray("callable"), varray());
bind_method(Signal, get_connections, sarray(), varray());
@@ -1702,6 +1704,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, get_rotation, sarray(), varray());
bind_method(Transform2D, get_origin, sarray(), varray());
bind_method(Transform2D, get_scale, sarray(), varray());
+ bind_method(Transform2D, get_skew, sarray(), varray());
bind_method(Transform2D, orthonormalized, sarray(), varray());
bind_method(Transform2D, rotated, sarray("phi"), varray());
bind_method(Transform2D, scaled, sarray("scale"), varray());
@@ -1711,6 +1714,8 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform2D, is_equal_approx, sarray("xform"), varray());
bind_method(Transform2D, set_rotation, sarray("rotation"), varray());
+ bind_method(Transform2D, set_scale, sarray("scale"), varray());
+ bind_method(Transform2D, set_skew, sarray("skew"), varray());
bind_method(Transform2D, looking_at, sarray("target"), varray(Vector2()));
/* Basis */
@@ -1736,6 +1741,7 @@ static void _register_variant_builtin_methods() {
/* AABB */
bind_method(AABB, abs, sarray(), varray());
+ bind_method(AABB, get_center, sarray(), varray());
bind_method(AABB, get_area, sarray(), varray());
bind_method(AABB, has_no_area, sarray(), varray());
bind_method(AABB, has_no_surface, sarray(), varray());
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index a1a2bec369..4317b9dc98 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -114,6 +114,7 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Transform2D>>(sarray());
add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position"));
+ add_constructor<VariantConstructor<Transform2D, float, Size2, float, Vector2>>(sarray("rotation", "scale", "skew", "position"));
add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x_axis", "y_axis", "origin"));
add_constructor<VariantConstructNoArgs<Plane>>(sarray());
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 232054d0ca..55c1376031 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -487,10 +487,6 @@ struct VariantUtilityFunctions {
}
static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -506,11 +502,29 @@ struct VariantUtilityFunctions {
r_error.error = Callable::CallError::CALL_OK;
}
- static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
+ 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;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += 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);
}
+
+ 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;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -527,10 +541,6 @@ struct VariantUtilityFunctions {
}
static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
@@ -544,10 +554,6 @@ struct VariantUtilityFunctions {
}
static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
if (i) {
@@ -561,10 +567,6 @@ struct VariantUtilityFunctions {
}
static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
- if (p_arg_count < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- }
String str;
for (int i = 0; i < p_arg_count; i++) {
String os = p_args[i]->operator String();
@@ -1246,6 +1248,7 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(print_verbose, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);