summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/core_bind.cpp45
-rw-r--r--core/core_bind.h5
-rw-r--r--core/input/input_event.cpp6
-rw-r--r--core/input/input_map.cpp2
-rw-r--r--core/io/image.cpp8
-rw-r--r--core/io/packet_peer.cpp46
-rw-r--r--core/io/packet_peer.h23
-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/bvh_cull.inc2
-rw-r--r--core/math/bvh_debug.inc27
-rw-r--r--core/math/bvh_split.inc16
-rw-r--r--core/math/static_raycaster.cpp40
-rw-r--r--core/math/static_raycaster.h111
-rw-r--r--core/multiplayer/multiplayer_peer.cpp181
-rw-r--r--core/multiplayer/multiplayer_peer.h80
-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/translation.cpp13
-rw-r--r--core/string/translation.h5
-rw-r--r--core/templates/rid_owner.h16
-rw-r--r--core/variant/native_ptr.h3
26 files changed, 648 insertions, 90 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 242a2f3638..1f028702f6 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;
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/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 8bec80a99e..1ec4299093 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -467,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>>();
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/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_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/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/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/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/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/translation.cpp b/core/string/translation.cpp
index cb7d924556..5c0eb388f5 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -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);
}
@@ -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/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/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)