summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md29
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml56
-rw-r--r--core/io/file_access_encrypted.cpp1
-rw-r--r--core/io/file_access_memory.cpp1
-rw-r--r--core/io/multiplayer_api.cpp314
-rw-r--r--core/io/multiplayer_api.h45
-rw-r--r--core/object/class_db.cpp62
-rw-r--r--core/object/class_db.h9
-rw-r--r--core/object/object.cpp47
-rw-r--r--core/object/object.h78
-rw-r--r--core/object/reference.cpp6
-rw-r--r--core/object/script_language.cpp8
-rw-r--r--core/object/script_language.h51
-rw-r--r--core/os/file_access.cpp1
-rw-r--r--doc/classes/BaseMaterial3D.xml5
-rw-r--r--doc/classes/CharacterBody2D.xml3
-rw-r--r--doc/classes/CharacterBody3D.xml3
-rw-r--r--doc/classes/MultiplayerAPI.xml8
-rw-r--r--doc/classes/Node.xml89
-rw-r--r--doc/classes/Skeleton2D.xml2
-rw-r--r--drivers/unix/file_access_unix.cpp2
-rw-r--r--drivers/windows/file_access_windows.cpp1
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/editor_path.cpp100
-rw-r--r--editor/editor_path.h16
-rw-r--r--editor/inspector_dock.cpp103
-rw-r--r--editor/inspector_dock.h2
-rw-r--r--editor/node_3d_editor_gizmos.cpp41
-rw-r--r--editor/plugins/editor_preview_plugins.cpp2
-rw-r--r--editor/plugins/font_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/settings_config_dialog.cpp8
-rwxr-xr-xmisc/hooks/pre-commit-clang-format7
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp24
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp278
-rw-r--r--modules/gdnative/nativescript/nativescript.h29
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.cpp38
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h12
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp91
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.h15
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp24
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h2
-rw-r--r--modules/gdscript/gdscript.cpp121
-rw-r--r--modules/gdscript/gdscript.h27
-rw-r--r--modules/mono/csharp_script.cpp135
-rw-r--r--modules/mono/csharp_script.h27
-rw-r--r--modules/visual_script/visual_script.cpp98
-rw-r--r--modules/visual_script/visual_script.h27
-rw-r--r--modules/visual_script/visual_script_editor.cpp8
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp16
-rw-r--r--platform/javascript/js/libs/library_godot_fetch.js2
-rw-r--r--scene/2d/physics_body_2d.cpp19
-rw-r--r--scene/2d/physics_body_2d.h5
-rw-r--r--scene/2d/position_2d.cpp39
-rw-r--r--scene/2d/skeleton_2d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp19
-rw-r--r--scene/3d/physics_body_3d.h5
-rw-r--r--scene/gui/base_button.cpp3
-rw-r--r--scene/main/node.cpp267
-rw-r--r--scene/main/node.h45
-rw-r--r--scene/resources/material.cpp6
-rw-r--r--scene/resources/material.h1
-rw-r--r--servers/physics_server_2d.h10
-rw-r--r--servers/physics_server_3d.h10
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp1
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl9
-rw-r--r--servers/rendering/shader_types.cpp1
-rw-r--r--tests/test_object.h31
72 files changed, 844 insertions, 1715 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index bc56cba21b..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-name: Bug report
-about: Report a bug in Godot
-title: ''
-labels: ''
-assignees: ''
-
----
-<!-- Please search existing issues for potential duplicates before filing yours:
-https://github.com/godotengine/godot/issues?q=is%3Aissue
--->
-
-**Godot version:**
-<!-- Specify commit hash if using non-official build. -->
-
-
-**OS/device including version:**
-<!-- Specify GPU model, drivers, and the backend (GLES2, GLES3, Vulkan) if graphics-related. -->
-
-
-**Issue description:**
-<!-- What happened, and what was expected. -->
-
-
-**Steps to reproduce:**
-
-
-**Minimal reproduction project:**
-<!-- A small Godot project which reproduces the issue. Drag and drop a zip archive to upload it. -->
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000..43ba5ef357
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,56 @@
+name: Bug report
+description: Report a bug in Godot
+body:
+
+- type: markdown
+ attributes:
+ value: |
+ - Read our [CONTRIBUTING.md guide](CONTRIBUTING.md#reporting-bugs) on reporting bugs.
+ - Write a descriptive issue title above.
+ - Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
+ - Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
+
+- type: input
+ attributes:
+ label: Godot version
+ description: >
+ Specify the Git commit hash if using a development or non-official build.
+ If you use a custom build, please test if your issue is reproducible in official builds too.
+ placeholder: 3.3.stable, 4.0.dev (3041becc6)
+ validations:
+ required: true
+
+- type: input
+ attributes:
+ label: System information
+ description: |
+ Specify the OS version, and when relevant hardware information.
+ For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
+ placeholder: Windows 10, GLES3, Intel HD Graphics 620 (27.20.100.9616)
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Issue description
+ description: |
+ Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
+ You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Steps to reproduce
+ description: |
+ List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
+ If you include a minimal reproduction project below, you can detail how to use it here.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Minimal reproduction project
+ description: |
+ A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
+ Drag and drop a ZIP archive to upload it.
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index b9514c8c8b..9e316291e8 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -257,6 +257,7 @@ Error FileAccessEncrypted::get_error() const {
void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
+ ERR_FAIL_COND(!p_src && p_length > 0);
if (pos < get_length()) {
for (uint64_t i = 0; i < p_length; i++) {
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 0114ab1765..d9be2a4a75 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -168,6 +168,7 @@ void FileAccessMemory::store_8(uint8_t p_byte) {
}
void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
+ ERR_FAIL_COND(!p_src && p_length > 0);
uint64_t left = length - pos;
uint64_t write = MIN(p_length, left);
if (write < p_length) {
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index fda4083804..78ec7ea21a 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -44,6 +44,56 @@
#include "core/os/os.h"
#endif
+String _get_rpc_md5(const Node *p_node) {
+ String rpc_list;
+ const Vector<MultiplayerAPI::RPCConfig> node_config = p_node->get_node_rpc_methods();
+ for (int i = 0; i < node_config.size(); i++) {
+ rpc_list += String(node_config[i].name);
+ }
+ if (p_node->get_script_instance()) {
+ const Vector<MultiplayerAPI::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
+ for (int i = 0; i < script_config.size(); i++) {
+ rpc_list += String(script_config[i].name);
+ }
+ }
+ return rpc_list.md5_text();
+}
+
+const MultiplayerAPI::RPCConfig _get_rpc_config(const Node *p_node, const StringName &p_method, uint16_t &r_id) {
+ const Vector<MultiplayerAPI::RPCConfig> node_config = p_node->get_node_rpc_methods();
+ for (int i = 0; i < node_config.size(); i++) {
+ if (node_config[i].name == p_method) {
+ r_id = ((uint16_t)i) & (1 << 15);
+ return node_config[i];
+ }
+ }
+ if (p_node->get_script_instance()) {
+ const Vector<MultiplayerAPI::RPCConfig> script_config = p_node->get_script_instance()->get_rpc_methods();
+ for (int i = 0; i < script_config.size(); i++) {
+ if (script_config[i].name == p_method) {
+ r_id = (uint16_t)i;
+ return script_config[i];
+ }
+ }
+ }
+ return MultiplayerAPI::RPCConfig();
+}
+
+const MultiplayerAPI::RPCConfig _get_rpc_config_by_id(Node *p_node, uint16_t p_id) {
+ Vector<MultiplayerAPI::RPCConfig> config;
+ uint16_t id = p_id;
+ if (id & (1 << 15)) {
+ id = id & ~(1 << 15);
+ config = p_node->get_node_rpc_methods();
+ } else {
+ config = p_node->get_script_instance()->get_rpc_methods();
+ }
+ if (id < config.size()) {
+ return config[p_id];
+ }
+ return MultiplayerAPI::RPCConfig();
+}
+
_FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) {
switch (mode) {
case MultiplayerAPI::RPC_MODE_DISABLED: {
@@ -231,8 +281,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
_process_confirm_path(p_from, p_packet, p_packet_len);
} break;
- case NETWORK_COMMAND_REMOTE_CALL:
- case NETWORK_COMMAND_REMOTE_SET: {
+ case NETWORK_COMMAND_REMOTE_CALL: {
// Extract packet meta
int packet_min_size = 1;
int name_id_offset = 1;
@@ -302,13 +351,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
}
const int packet_len = get_packet_len(node_target, p_packet_len);
- if (packet_type == NETWORK_COMMAND_REMOTE_CALL) {
- _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size);
-
- } else {
- _process_rset(node, name_id, p_from, p_packet, packet_len, packet_min_size);
- }
-
+ _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size);
} break;
case NETWORK_COMMAND_RAW: {
@@ -362,16 +405,11 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id,
ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small.");
// Check that remote can call the RPC on this node.
- StringName name = p_node->get_node_rpc_method(p_rpc_method_id);
- RPCMode rpc_mode = p_node->get_node_rpc_mode_by_id(p_rpc_method_id);
- if (name == StringName() && p_node->get_script_instance()) {
- name = p_node->get_script_instance()->get_rpc_method(p_rpc_method_id);
- rpc_mode = p_node->get_script_instance()->get_rpc_mode_by_id(p_rpc_method_id);
- }
- ERR_FAIL_COND(name == StringName());
+ const RPCConfig config = _get_rpc_config_by_id(p_node, p_rpc_method_id);
+ ERR_FAIL_COND(config.name == StringName());
- bool can_call = _can_call_mode(p_node, rpc_mode, p_from);
- ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
+ bool can_call = _can_call_mode(p_node, config.rpc_mode, p_from);
+ ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(config.name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)config.rpc_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
int argc = 0;
bool byte_only = false;
@@ -424,47 +462,14 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id,
Callable::CallError ce;
- p_node->call(name, (const Variant **)argp.ptr(), argc, ce);
+ p_node->call(config.name, (const Variant **)argp.ptr(), argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- String error = Variant::get_call_error_text(p_node, name, (const Variant **)argp.ptr(), argc, ce);
+ String error = Variant::get_call_error_text(p_node, config.name, (const Variant **)argp.ptr(), argc, ce);
error = "RPC - " + error;
ERR_PRINT(error);
}
}
-void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) {
- ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small.");
-
- // Check that remote can call the RSET on this node.
- StringName name = p_node->get_node_rset_property(p_rpc_property_id);
- RPCMode rset_mode = p_node->get_node_rset_mode_by_id(p_rpc_property_id);
- if (name == StringName() && p_node->get_script_instance()) {
- name = p_node->get_script_instance()->get_rset_property(p_rpc_property_id);
- rset_mode = p_node->get_script_instance()->get_rset_mode_by_id(p_rpc_property_id);
- }
- ERR_FAIL_COND(name == StringName());
-
- bool can_call = _can_call_mode(p_node, rset_mode, p_from);
- ERR_FAIL_COND_MSG(!can_call, "RSET '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rset_mode) + ", master is " + itos(p_node->get_network_master()) + ".");
-
-#ifdef DEBUG_ENABLED
- _profile_node_data("in_rset", p_node->get_instance_id());
-#endif
-
- Variant value;
- Error err = _decode_and_decompress_variant(value, &p_packet[p_offset], p_packet_len - p_offset, nullptr);
-
- ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RSET value.");
-
- bool valid;
-
- p_node->set(name, value, &valid);
- if (!valid) {
- String error = "Error setting remote property '" + String(name) + "', not found in object of type " + p_node->get_class() + ".";
- ERR_PRINT(error);
- }
-}
-
void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small.");
int ofs = 1;
@@ -487,7 +492,7 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
Node *node = root_node->get_node(path);
ERR_FAIL_COND(node == nullptr);
- const bool valid_rpc_checksum = node->get_rpc_md5() == methods_md5;
+ const bool valid_rpc_checksum = _get_rpc_md5(node) == methods_md5;
if (valid_rpc_checksum == false) {
ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path);
}
@@ -569,7 +574,7 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
const int path_len = encode_cstring(path.get_data(), nullptr);
// Extract MD5 from rpc methods list.
- const String methods_md5 = p_node->get_rpc_md5();
+ const String methods_md5 = _get_rpc_md5(p_node);
const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder.
Vector<uint8_t> packet;
@@ -752,7 +757,7 @@ Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const u
return OK;
}
-void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree.");
ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree.");
@@ -797,7 +802,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
// - `NetworkNameIdCompression` in the next 1 bit.
// - `byte_only_or_no_args` in the next 1 bit.
// - So we still have the last bit free!
- uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL;
+ uint8_t command_type = NETWORK_COMMAND_REMOTE_CALL;
uint8_t node_id_compression = UINT8_MAX;
uint8_t name_id_compression = UINT8_MAX;
bool byte_only_or_no_args = false;
@@ -837,81 +842,42 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
ofs += 4;
}
- if (p_set) {
- // Take the rpc property ID
- uint16_t property_id = p_from->get_node_rset_property_id(p_name);
- if (property_id == UINT16_MAX && p_from->get_script_instance()) {
- property_id = p_from->get_script_instance()->get_rset_property_id(p_name);
- }
- ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". This can only happen if this property is not marked as `remote`.");
-
- if (property_id <= UINT8_MAX) {
- // The ID fits in 1 byte
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = static_cast<uint8_t>(property_id);
- ofs += 1;
- } else {
- // The ID is larger, let's use 2 bytes
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
- MAKE_ROOM(ofs + 2);
- encode_uint16(property_id, &(packet_cache.write[ofs]));
- ofs += 2;
- }
-
- // Set argument.
- int len(0);
- Error err = _encode_and_compress_variant(*p_arg[0], nullptr, len);
- ERR_FAIL_COND_MSG(err != OK, "Unable to encode RSET value. THIS IS LIKELY A BUG IN THE ENGINE!");
- MAKE_ROOM(ofs + len);
- _encode_and_compress_variant(*p_arg[0], &(packet_cache.write[ofs]), len);
- ofs += len;
-
+ // Encode method ID
+ if (p_rpc_id <= UINT8_MAX) {
+ // The ID fits in 1 byte
+ name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
+ MAKE_ROOM(ofs + 1);
+ packet_cache.write[ofs] = static_cast<uint8_t>(p_rpc_id);
+ ofs += 1;
} else {
- // Take the rpc method ID
- uint16_t method_id = p_from->get_node_rpc_method_id(p_name);
- if (method_id == UINT16_MAX && p_from->get_script_instance()) {
- method_id = p_from->get_script_instance()->get_rpc_method_id(p_name);
- }
- ERR_FAIL_COND_MSG(method_id == UINT16_MAX,
- vformat("Unable to take the `method_id` for the function \"%s\" at path: \"%s\". This happens when the method is not marked as `remote`.", p_name, p_from->get_path()));
-
- if (method_id <= UINT8_MAX) {
- // The ID fits in 1 byte
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_8;
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = static_cast<uint8_t>(method_id);
- ofs += 1;
- } else {
- // The ID is larger, let's use 2 bytes
- name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
- MAKE_ROOM(ofs + 2);
- encode_uint16(method_id, &(packet_cache.write[ofs]));
- ofs += 2;
- }
+ // The ID is larger, let's use 2 bytes
+ name_id_compression = NETWORK_NAME_ID_COMPRESSION_16;
+ MAKE_ROOM(ofs + 2);
+ encode_uint16(p_rpc_id, &(packet_cache.write[ofs]));
+ ofs += 2;
+ }
- if (p_argcount == 0) {
- byte_only_or_no_args = true;
- } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) {
- byte_only_or_no_args = true;
- // Special optimization when only the byte vector is sent.
- const Vector<uint8_t> data = *p_arg[0];
- MAKE_ROOM(ofs + data.size());
- memcpy(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size());
- ofs += data.size();
- } else {
- // Arguments
- MAKE_ROOM(ofs + 1);
- packet_cache.write[ofs] = p_argcount;
- ofs += 1;
- for (int i = 0; i < p_argcount; i++) {
- int len(0);
- Error err = _encode_and_compress_variant(*p_arg[i], nullptr, len);
- ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
- MAKE_ROOM(ofs + len);
- _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
- ofs += len;
- }
+ if (p_argcount == 0) {
+ byte_only_or_no_args = true;
+ } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) {
+ byte_only_or_no_args = true;
+ // Special optimization when only the byte vector is sent.
+ const Vector<uint8_t> data = *p_arg[0];
+ MAKE_ROOM(ofs + data.size());
+ memcpy(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size());
+ ofs += data.size();
+ } else {
+ // Arguments
+ MAKE_ROOM(ofs + 1);
+ packet_cache.write[ofs] = p_argcount;
+ ofs += 1;
+ for (int i = 0; i < p_argcount; i++) {
+ int len(0);
+ Error err = _encode_and_compress_variant(*p_arg[i], nullptr, len);
+ ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!");
+ MAKE_ROOM(ofs + len);
+ _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len);
+ ofs += len;
}
}
@@ -927,7 +893,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p
#endif
// Take chance and set transfer mode, since all send methods will use it.
- network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ network_peer->set_transfer_mode(p_config.transfer_mode);
if (has_all_peers) {
// They all have verified paths, so send fast.
@@ -1015,19 +981,15 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
bool call_local_native = false;
bool call_local_script = false;
bool is_master = p_node->is_network_master();
-
+ uint16_t rpc_id = UINT16_MAX;
+ const RPCConfig config = _get_rpc_config(p_node, p_method, rpc_id);
+ ERR_FAIL_COND_MSG(config.name == StringName(),
+ vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path()));
if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- // Check that send mode can use local call.
-
- RPCMode rpc_mode = p_node->get_node_rpc_mode(p_method);
- call_local_native = _should_call_local(rpc_mode, is_master, skip_rpc);
-
- if (call_local_native) {
- // Done below.
- } else if (p_node->get_script_instance()) {
- // Attempt with script.
- rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method);
- call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc);
+ if (rpc_id & (1 << 15)) {
+ call_local_native = _should_call_local(config.rpc_mode, is_master, skip_rpc);
+ } else {
+ call_local_script = _should_call_local(config.rpc_mode, is_master, skip_rpc);
}
}
@@ -1036,7 +998,7 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
_profile_node_data("out_rpc", p_node->get_instance_id());
#endif
- _send_rpc(p_node, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
+ _send_rpc(p_node, p_peer_id, rpc_id, config, p_method, p_arg, p_argcount);
}
if (call_local_native) {
@@ -1071,70 +1033,6 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
ERR_FAIL_COND_MSG(skip_rpc && !(call_local_native || call_local_script), "RPC '" + p_method + "' on yourself is not allowed by selected mode.");
}
-void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to RSET while no network peer is active.");
- ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to RSET on a node which is not inside SceneTree.");
- ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to send an RSET via a network peer which is not connected.");
-
- int node_id = network_peer->get_unique_id();
- bool is_master = p_node->is_network_master();
- bool skip_rset = node_id == p_peer_id;
- bool set_local = false;
-
- if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) {
- // Check that send mode can use local call.
- RPCMode rpc_mode = p_node->get_node_rset_mode(p_property);
- set_local = _should_call_local(rpc_mode, is_master, skip_rset);
-
- if (set_local) {
- bool valid;
- int temp_id = rpc_sender_id;
-
- rpc_sender_id = get_network_unique_id();
- p_node->set(p_property, p_value, &valid);
- rpc_sender_id = temp_id;
-
- if (!valid) {
- String error = "rset() aborted in local set, property not found: - " + String(p_property) + ".";
- ERR_PRINT(error);
- return;
- }
- } else if (p_node->get_script_instance()) {
- // Attempt with script.
- rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property);
-
- set_local = _should_call_local(rpc_mode, is_master, skip_rset);
-
- if (set_local) {
- int temp_id = rpc_sender_id;
-
- rpc_sender_id = get_network_unique_id();
- bool valid = p_node->get_script_instance()->set(p_property, p_value);
- rpc_sender_id = temp_id;
-
- if (!valid) {
- String error = "rset() aborted in local script set, property not found: - " + String(p_property) + ".";
- ERR_PRINT(error);
- return;
- }
- }
- }
- }
-
- if (skip_rset) {
- ERR_FAIL_COND_MSG(!set_local, "RSET for '" + p_property + "' on yourself is not allowed by selected mode.");
- return;
- }
-
-#ifdef DEBUG_ENABLED
- _profile_node_data("out_rset", p_node->get_instance_id());
-#endif
-
- const Variant *vptr = &p_value;
-
- _send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
-}
-
Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) {
ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet.");
ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active.");
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index 7f88b53a27..6a251cf77b 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -37,6 +37,35 @@
class MultiplayerAPI : public Reference {
GDCLASS(MultiplayerAPI, Reference);
+public:
+ enum RPCMode {
+ RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
+ RPC_MODE_REMOTE, // Using rpc() on it will call method in all remote peers
+ RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
+ RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
+ RPC_MODE_REMOTESYNC, // Using rpc() on it will call method in all remote peers and locally
+ RPC_MODE_MASTERSYNC, // Using rpc() on it will call method in the master peer and locally
+ RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method in all puppets peers and locally
+ };
+
+ struct RPCConfig {
+ StringName name;
+ RPCMode rpc_mode = RPC_MODE_DISABLED;
+ NetworkedMultiplayerPeer::TransferMode transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ int channel = 0;
+
+ bool operator==(RPCConfig const &p_other) const {
+ return name == p_other.name;
+ }
+ };
+
+ struct SortRPCConfig {
+ StringName::AlphCompare compare;
+ bool operator()(const RPCConfig &p_a, const RPCConfig &p_b) const {
+ return compare(p_a.name, p_b.name);
+ }
+ };
+
private:
//path sent caches
struct PathSentCache {
@@ -72,10 +101,9 @@ protected:
void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
- void _process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
- void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
+ void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target);
Error _encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len);
@@ -84,7 +112,6 @@ protected:
public:
enum NetworkCommands {
NETWORK_COMMAND_REMOTE_CALL = 0,
- NETWORK_COMMAND_REMOTE_SET,
NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH,
NETWORK_COMMAND_RAW,
@@ -101,16 +128,6 @@ public:
NETWORK_NAME_ID_COMPRESSION_16,
};
- enum RPCMode {
- RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
- RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers
- RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
- RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
- RPC_MODE_REMOTESYNC, // Using rpc() on it will call method / set property in all remote peers and locally
- RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally
- RPC_MODE_PUPPETSYNC, // Using rpc() on it will call method / set property in all puppets peers and locally
- };
-
void poll();
void clear();
void set_root_node(Node *p_node);
@@ -121,8 +138,6 @@ public:
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
- // Called by Node.rset
- void rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
void _add_peer(int p_id);
void _del_peer(int p_id);
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index fb7eb42738..5bf874ccae 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -501,12 +501,27 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
compat_classes[p_class] = p_fallback;
}
+thread_local bool initializing_with_extension = false;
+thread_local ObjectNativeExtension *initializing_extension = nullptr;
+thread_local void *initializing_extension_instance = nullptr;
+
+void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance) {
+ if (initializing_with_extension) {
+ *r_extension = initializing_extension;
+ *r_extension_instance = initializing_extension_instance;
+ initializing_with_extension = false;
+ } else {
+ *r_extension = nullptr;
+ *r_extension_instance = nullptr;
+ }
+}
+
Object *ClassDB::instance(const StringName &p_class) {
ClassInfo *ti;
{
OBJTYPE_RLOCK;
ti = classes.getptr(p_class);
- if (!ti || ti->disabled || !ti->creation_func) {
+ if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
if (compat_classes.has(p_class)) {
ti = classes.getptr(compat_classes[p_class]);
}
@@ -521,6 +536,11 @@ Object *ClassDB::instance(const StringName &p_class) {
return nullptr;
}
#endif
+ if (ti->native_extension) {
+ initializing_with_extension = true;
+ initializing_extension = ti->native_extension;
+ initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->create_instance_userdata);
+ }
return ti->creation_func();
}
@@ -534,7 +554,7 @@ bool ClassDB::can_instance(const StringName &p_class) {
return false;
}
#endif
- return (!ti->disabled && ti->creation_func != nullptr);
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
}
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
@@ -1310,6 +1330,24 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe
return false;
}
+void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
+ ClassInfo *type = classes.getptr(p_class);
+ if (!type) {
+ ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'.");
+ }
+
+ if (type->method_map.has(p_method->get_name())) {
+ // overloading not supported
+ ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'.");
+ }
+
+#ifdef DEBUG_METHODS_ENABLED
+ type->method_order.push_back(p_method->get_name());
+#endif
+
+ type->method_map[p_method->get_name()] = p_method;
+}
+
#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
@@ -1545,6 +1583,26 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
return var;
}
+void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
+ GLOBAL_LOCK_FUNCTION;
+
+ ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
+ ERR_FAIL_COND_MSG(classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
+
+ ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
+
+ ClassInfo c;
+ c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION;
+ c.native_extension = p_extension;
+ c.name = p_extension->class_name;
+ c.creation_func = parent->creation_func;
+ c.inherits = parent->name;
+ c.class_ptr = parent->class_ptr;
+ c.inherits_ptr = parent;
+
+ classes[p_extension->class_name] = c;
+}
+
RWLock ClassDB::lock;
void ClassDB::cleanup_defaults() {
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 6fd5748dbb..4355c9b0ea 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -97,6 +97,8 @@ public:
enum APIType {
API_CORE,
API_EDITOR,
+ API_EXTENSION,
+ API_EDITOR_EXTENSION,
API_NONE
};
@@ -115,6 +117,8 @@ public:
ClassInfo *inherits_ptr = nullptr;
void *class_ptr = nullptr;
+ ObjectNativeExtension *native_extension = nullptr;
+
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int> constant_map;
HashMap<StringName, List<StringName>> enum_map;
@@ -199,6 +203,8 @@ public:
//nothing
}
+ static void register_extension_class(ObjectNativeExtension *p_extension);
+
template <class T>
static Object *_create_ptr_func() {
return T::create();
@@ -226,6 +232,7 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instance(const StringName &p_class);
static Object *instance(const StringName &p_class);
+ static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, void **r_extension_instance);
static APIType get_api_type(const StringName &p_class);
static uint64_t get_api_hash(APIType p_api);
@@ -334,6 +341,8 @@ public:
return bind;
}
+ static void bind_method_custom(const StringName &p_class, MethodBind *p_method);
+
static void add_signal(StringName p_class, const MethodInfo &p_signal);
static bool has_signal(StringName p_class, StringName p_signal, bool p_no_inheritance = false);
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index a8b2c4a939..7e1c3855c0 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -385,6 +385,15 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
}
+ if (_extension && _extension->set) {
+ if (_extension->set(_extension_instance, &p_name, &p_value)) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return;
+ }
+ }
+
//try built-in setgetter
{
if (ClassDB::set_property(this, p_name, p_value, r_valid)) {
@@ -451,6 +460,15 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
}
}
+ if (_extension && _extension->get) {
+ if (_extension->get(_extension_instance, &p_name, &ret)) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ return ret;
+ }
+ }
+
//try built-in setgetter
{
if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) {
@@ -596,6 +614,17 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
+ if (_extension && _extension->get_property_list) {
+ uint32_t pcount;
+ const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
+ for (uint32_t i = 0; i < pcount; i++) {
+ p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
+ }
+ if (_extension->free_property_list) {
+ _extension->free_property_list(_extension_instance, pinfo);
+ }
+ }
+
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
@@ -761,6 +790,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
Variant ret;
OBJ_DEBUG_LOCK
+
if (script_instance) {
ret = script_instance->call(p_method, p_args, p_argcount, r_error);
//force jumptable
@@ -778,6 +808,8 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
}
}
+ //extension does not need this, because all methods are registered in MethodBind
+
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
if (method) {
@@ -795,6 +827,10 @@ void Object::notification(int p_notification, bool p_reversed) {
if (script_instance) {
script_instance->notification(p_notification);
}
+
+ if (_extension && _extension->notification) {
+ _extension->notification(_extension_instance, p_notification);
+ }
}
String Object::to_string() {
@@ -805,6 +841,9 @@ String Object::to_string() {
return ret;
}
}
+ if (_extension && _extension->to_string) {
+ return _extension->to_string(_extension_instance);
+ }
return "[" + get_class() + ":" + itos(get_instance_id()) + "]";
}
@@ -1751,6 +1790,8 @@ void Object::_construct_object(bool p_reference) {
_instance_id = ObjectDB::add_instance(this);
memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
+ ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance);
+
#ifdef DEBUG_ENABLED
_lock_index.init(1);
#endif
@@ -1770,6 +1811,12 @@ Object::~Object() {
}
script_instance = nullptr;
+ if (_extension && _extension->free_instance) {
+ _extension->free_instance(_extension->create_instance_userdata, _extension_instance);
+ _extension = nullptr;
+ _extension_instance = nullptr;
+ }
+
const StringName *S = nullptr;
if (_emitting) {
diff --git a/core/object/object.h b/core/object/object.h
index 448a33d3bc..137025f323 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -238,6 +238,50 @@ struct MethodInfo {
////else
//return nullptr;
+// API used to extend in GDNative and other C compatible compiled languages
+class MethodBind;
+
+struct ObjectNativeExtension {
+ ObjectNativeExtension *parent = nullptr;
+ StringName parent_class_name;
+ StringName class_name;
+ bool editor_class = false;
+ bool (*set)(void *instance, const void *name, const void *value) = nullptr;
+ bool (*get)(void *instance, const void *name, void *ret_variant) = nullptr;
+ struct PInfo {
+ uint32_t type;
+ const char *name;
+ const char *class_name;
+ uint32_t hint;
+ const char *hint_string;
+ uint32_t usage;
+ };
+ const PInfo *(*get_property_list)(void *instance, uint32_t *count) = nullptr;
+ void (*free_property_list)(void *instance, const PInfo *) = nullptr;
+
+ //call is not used, as all methods registered in ClassDB
+
+ void (*notification)(void *instance, int32_t what) = nullptr;
+ const char *(*to_string)(void *instance) = nullptr;
+
+ void (*reference)(void *instance) = nullptr;
+ void (*unreference)(void *instance) = nullptr;
+
+ _FORCE_INLINE_ bool is_class(const String &p_class) const {
+ const ObjectNativeExtension *e = this;
+ while (e) {
+ if (p_class == e->class_name.operator String()) {
+ return true;
+ }
+ e = e->parent;
+ }
+ return false;
+ }
+ void *create_instance_userdata = nullptr;
+ void *(*create_instance)(void *create_instance_userdata) = nullptr;
+ void (*free_instance)(void *create_instance_userdata, void *instance) = nullptr;
+};
+
/*
the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
@@ -262,9 +306,15 @@ private:
\
public: \
virtual String get_class() const override { \
+ if (_get_extension()) { \
+ return _get_extension()->class_name.operator String(); \
+ } \
return String(#m_class); \
} \
virtual const StringName *_get_class_namev() const override { \
+ if (_get_extension()) { \
+ return &_get_extension()->class_name; \
+ } \
if (!_class_name) { \
_class_name = get_class_static(); \
} \
@@ -297,7 +347,12 @@ public:
static String inherits_static() { \
return String(#m_inherits); \
} \
- virtual bool is_class(const String &p_class) const override { return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); } \
+ virtual bool is_class(const String &p_class) const override { \
+ if (_get_extension() && _get_extension()->is_class(p_class)) { \
+ return true; \
+ } \
+ return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \
+ } \
virtual bool is_class_ptr(void *p_ptr) const override { return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); } \
\
static void get_valid_parents_static(List<String> *p_parents) { \
@@ -440,6 +495,9 @@ private:
friend bool predelete_handler(Object *);
friend void postinitialize_handler(Object *);
+ ObjectNativeExtension *_extension = nullptr;
+ void *_extension_instance = nullptr;
+
struct SignalData {
struct Slot {
int reference_count = 0;
@@ -495,6 +553,8 @@ private:
Object(bool p_reference);
protected:
+ _ALWAYS_INLINE_ const ObjectNativeExtension *_get_extension() const { return _extension; }
+ _ALWAYS_INLINE_ void *_get_extension_instance() const { return _extension_instance; }
virtual void _initialize_classv() { initialize_class(); }
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
@@ -610,13 +670,25 @@ public:
static String get_parent_class_static() { return String(); }
static String get_category_static() { return String(); }
- virtual String get_class() const { return "Object"; }
+ virtual String get_class() const {
+ if (_extension)
+ return _extension->class_name.operator String();
+ return "Object";
+ }
virtual String get_save_class() const { return get_class(); } //class stored when saving
- virtual bool is_class(const String &p_class) const { return (p_class == "Object"); }
+ virtual bool is_class(const String &p_class) const {
+ if (_extension && _extension->is_class(p_class)) {
+ return true;
+ }
+ return (p_class == "Object");
+ }
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
_FORCE_INLINE_ const StringName &get_class_name() const {
+ if (_extension) {
+ return _extension->class_name;
+ }
if (!_class_ptr) {
return *_get_class_namev();
} else {
diff --git a/core/object/reference.cpp b/core/object/reference.cpp
index 22e4e8a336..086b761e95 100644
--- a/core/object/reference.cpp
+++ b/core/object/reference.cpp
@@ -62,6 +62,9 @@ bool Reference::reference() {
if (get_script_instance()) {
get_script_instance()->refcount_incremented();
}
+ if (_get_extension() && _get_extension()->reference) {
+ _get_extension()->reference(_get_extension_instance());
+ }
if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
if (_script_instance_bindings[i]) {
@@ -83,6 +86,9 @@ bool Reference::unreference() {
bool script_ret = get_script_instance()->refcount_decremented();
die = die && script_ret;
}
+ if (_get_extension() && _get_extension()->unreference) {
+ _get_extension()->unreference(_get_extension_instance());
+ }
if (instance_binding_count.get() > 0 && !ScriptServer::are_languages_finished()) {
for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
if (_script_instance_bindings[i]) {
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 42fb0a0caf..aa91c6cbf7 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -585,14 +585,6 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam
return Variant();
}
-uint16_t PlaceHolderScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return UINT16_MAX;
-}
-
-uint16_t PlaceHolderScriptInstance::get_rset_property_id(const StringName &p_method) const {
- return UINT16_MAX;
-}
-
PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) :
owner(p_owner),
language(p_language),
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 9ed3c7e80f..a22e91870e 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -41,21 +41,6 @@ class ScriptLanguage;
typedef void (*ScriptEditRequestFunction)(const String &p_path);
-struct ScriptNetData {
- StringName name;
- MultiplayerAPI::RPCMode mode;
- bool operator==(ScriptNetData const &p_other) const {
- return name == p_other.name;
- }
-};
-
-struct SortNetData {
- StringName::AlphCompare compare;
- bool operator()(const ScriptNetData &p_a, const ScriptNetData &p_b) const {
- return compare(p_a.name, p_b.name);
- }
-};
-
class ScriptServer {
enum {
MAX_LANGUAGES = 16
@@ -174,17 +159,7 @@ public:
virtual bool is_placeholder_fallback_enabled() const { return false; }
- virtual Vector<ScriptNetData> get_rpc_methods() const = 0;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0;
-
- virtual Vector<ScriptNetData> get_rset_properties() const = 0;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const = 0;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const = 0;
Script() {}
};
@@ -225,17 +200,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid);
- virtual Vector<ScriptNetData> get_rpc_methods() const = 0;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const = 0;
- virtual StringName get_rpc_method(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const = 0;
-
- virtual Vector<ScriptNetData> get_rset_properties() const = 0;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const = 0;
- virtual StringName get_rset_property(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const = 0;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const = 0;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const = 0;
virtual ScriptLanguage *get_language() = 0;
virtual ~ScriptInstance();
@@ -447,17 +412,7 @@ public:
virtual void property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr);
virtual Variant property_get_fallback(const StringName &p_name, bool *r_valid = nullptr);
- virtual Vector<ScriptNetData> get_rpc_methods() const { return Vector<ScriptNetData>(); }
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const { return StringName(); }
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
-
- virtual Vector<ScriptNetData> get_rset_properties() const { return Vector<ScriptNetData>(); }
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const { return StringName(); }
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const { return MultiplayerAPI::RPC_MODE_DISABLED; }
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const { return Vector<MultiplayerAPI::RPCConfig>(); }
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
~PlaceHolderScriptInstance();
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 3d04e4e619..d21c0bd9a2 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -551,6 +551,7 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
}
void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
+ ERR_FAIL_COND(!p_src && p_length > 0);
for (uint64_t i = 0; i < p_length; i++) {
store_8(p_src[i]);
}
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index 3b4a001f7e..49edb4c691 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -671,10 +671,7 @@
<constant name="DIFFUSE_LAMBERT_WRAP" value="2" enum="DiffuseMode">
Extends Lambert to cover more than 90 degrees when roughness increases.
</constant>
- <constant name="DIFFUSE_OREN_NAYAR" value="3" enum="DiffuseMode">
- Attempts to use roughness to emulate microsurfacing.
- </constant>
- <constant name="DIFFUSE_TOON" value="4" enum="DiffuseMode">
+ <constant name="DIFFUSE_TOON" value="3" enum="DiffuseMode">
Uses a hard cut for lighting, with smoothing affected by roughness.
</constant>
<constant name="SPECULAR_SCHLICK_GGX" value="0" enum="SpecularMode">
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index c3bb3d28e0..0e6ca073a7 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -101,6 +101,9 @@
<member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
</member>
+ <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
+ Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
+ </member>
<member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
If [code]true[/code], the body will be able to push [RigidBody2D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
</member>
diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
index 986874df3b..790edfcad1 100644
--- a/doc/classes/CharacterBody3D.xml
+++ b/doc/classes/CharacterBody3D.xml
@@ -87,6 +87,9 @@
<member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
</member>
+ <member name="floor_max_angle_degrees" type="float" setter="set_floor_max_angle_degrees" getter="get_floor_max_angle_degrees" default="45.0">
+ Maximum angle (in degrees) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide].
+ </member>
<member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
If [code]true[/code], the body will be able to push [RigidBody3D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody3D] nodes like with [StaticBody3D].
</member>
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index c168695d61..b2be92dbbd 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -135,16 +135,16 @@
</signals>
<constants>
<constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
+ Used with [method Node.rpc_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods.
</constant>
<constant name="RPC_MODE_REMOTE" value="1" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. Calls and property changes are accepted from all remote peers, no matter if they are node's master or puppets.
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. Calls and property changes are accepted from all remote peers, no matter if they are node's master or puppets.
</constant>
<constant name="RPC_MODE_MASTER" value="2" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. Only accepts calls or property changes from the node's network puppets, see [method Node.set_network_master].
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. Only accepts calls or property changes from the node's network puppets, see [method Node.set_network_master].
</constant>
<constant name="RPC_MODE_PUPPET" value="3" enum="RPCMode">
- Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
+ Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
</constant>
<constant name="RPC_MODE_REMOTESYNC" value="4" enum="RPCMode">
Behave like [constant RPC_MODE_REMOTE] but also make the call or property change locally. Analogous to the [code]remotesync[/code] keyword.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index c4447962df..1300351e47 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -649,7 +649,7 @@
<argument index="0" name="method" type="StringName">
</argument>
<description>
- Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. See also [method rset] and [method rset_config] for properties. Returns an empty [Variant].
+ Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Returns an empty [Variant].
[b]Note:[/b] You can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [SceneTree]. You also need to keep track of the connection state, either by the [SceneTree] signals like [code]server_disconnected[/code] or by checking [code]SceneTree.network_peer.get_connection_status() == CONNECTION_CONNECTED[/code].
</description>
</method>
@@ -658,33 +658,17 @@
</return>
<argument index="0" name="method" type="StringName">
</argument>
- <argument index="1" name="mode" type="int" enum="MultiplayerAPI.RPCMode">
+ <argument index="1" name="rpc_mode" type="int" enum="MultiplayerAPI.RPCMode">
</argument>
- <description>
- Changes the RPC mode for the given [code]method[/code] to the given [code]mode[/code]. See [enum MultiplayerAPI.RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs). See also [method rset] and [method rset_config] for properties.
- </description>
- </method>
- <method name="rpc_id" qualifiers="vararg">
- <return type="Variant">
- </return>
- <argument index="0" name="peer_id" type="int">
+ <argument index="2" name="transfer_mode" type="int" enum="NetworkedMultiplayerPeer.TransferMode" default="2">
</argument>
- <argument index="1" name="method" type="StringName">
+ <argument index="3" name="channel" type="int" default="0">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
+ Changes the RPC mode for the given [code]method[/code] to the given [code]rpc_mode[/code], optionally specifying the [code]transfer_mode[/code] and [code]channel[/code] (on supported peers). See [enum MultiplayerAPI.RPCMode] and [enum NetworkedMultiplayerPeer.TransferMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, methods are not exposed to networking (and RPCs).
</description>
</method>
- <method name="rpc_unreliable" qualifiers="vararg">
- <return type="Variant">
- </return>
- <argument index="0" name="method" type="StringName">
- </argument>
- <description>
- Sends a [method rpc] using an unreliable protocol. Returns an empty [Variant].
- </description>
- </method>
- <method name="rpc_unreliable_id" qualifiers="vararg">
+ <method name="rpc_id" qualifiers="vararg">
<return type="Variant">
</return>
<argument index="0" name="peer_id" type="int">
@@ -692,66 +676,7 @@
<argument index="1" name="method" type="StringName">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
- </description>
- </method>
- <method name="rset">
- <return type="void">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes a property's value on other peers (and locally). Behaviour depends on the RPC configuration for the given property, see [method rset_config]. See also [method rpc] for RPCs for methods, most information applies to this method as well.
- </description>
- </method>
- <method name="rset_config">
- <return type="int">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="mode" type="int" enum="MultiplayerAPI.RPCMode">
- </argument>
- <description>
- Changes the RPC mode for the given [code]property[/code] to the given [code]mode[/code]. See [enum MultiplayerAPI.RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]master[/code], [code]puppet[/code], [code]remotesync[/code], [code]mastersync[/code], [code]puppetsync[/code]). By default, properties are not exposed to networking (and RPCs). See also [method rpc] and [method rpc_config] for methods.
- </description>
- </method>
- <method name="rset_id">
- <return type="void">
- </return>
- <argument index="0" name="peer_id" type="int">
- </argument>
- <argument index="1" name="property" type="StringName">
- </argument>
- <argument index="2" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes the property's value on a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]).
- </description>
- </method>
- <method name="rset_unreliable">
- <return type="void">
- </return>
- <argument index="0" name="property" type="StringName">
- </argument>
- <argument index="1" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes the property's value on other peers (and locally) using an unreliable protocol.
- </description>
- </method>
- <method name="rset_unreliable_id">
- <return type="void">
- </return>
- <argument index="0" name="peer_id" type="int">
- </argument>
- <argument index="1" name="property" type="StringName">
- </argument>
- <argument index="2" name="value" type="Variant">
- </argument>
- <description>
- Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]).
+ Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description>
</method>
<method name="set_display_folded">
diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml
index 80db57d7d0..6665a4a9f6 100644
--- a/doc/classes/Skeleton2D.xml
+++ b/doc/classes/Skeleton2D.xml
@@ -13,7 +13,7 @@
<method name="execute_modifications">
<return type="void">
</return>
- <argument index="0" name="execution_mode" type="float">
+ <argument index="0" name="delta" type="float">
</argument>
<argument index="1" name="execution_mode" type="int">
</argument>
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index ec23df62d0..6ea55219bb 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -264,7 +264,7 @@ void FileAccessUnix::store_8(uint8_t p_dest) {
void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- ERR_FAIL_COND(!p_src);
+ ERR_FAIL_COND(!p_src && p_length > 0);
ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
}
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 1f46b44f5e..d6deda7b5d 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -294,6 +294,7 @@ void FileAccessWindows::store_8(uint8_t p_dest) {
void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!f);
+ ERR_FAIL_COND(!p_src && p_length > 0);
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == READ) {
if (last_error != ERR_FILE_EOF) {
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 7527514dca..b8504ad02a 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -141,7 +141,7 @@ EditorAbout::EditorAbout() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text(VERSION_FULL_NAME + hash);
// Set the text to copy in metadata as it slightly differs from the button's text.
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2e6ec88d8c..1c2fd50f0b 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6632,7 +6632,7 @@ EditorNode::EditorNode() {
version_btn->set_text(VERSION_FULL_CONFIG);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
// Set the text to copy in metadata as it slightly differs from the button's text.
version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash);
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index d1c52b4310..63281ae1aa 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -59,15 +59,40 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
- int index = get_popup()->get_item_count();
- get_popup()->add_icon_item(icon, E->get().name.capitalize(), objects.size());
- get_popup()->set_item_h_offset(index, p_depth * 10 * EDSCALE);
+ String proper_name = "";
+ Vector<String> name_parts = E->get().name.split("/");
+
+ for (int i = 0; i < name_parts.size(); i++) {
+ if (i > 0) {
+ proper_name += " > ";
+ }
+ proper_name += name_parts[i].capitalize();
+ }
+
+ int index = sub_objects_menu->get_item_count();
+ sub_objects_menu->add_icon_item(icon, proper_name, objects.size());
+ sub_objects_menu->set_item_h_offset(index, p_depth * 10 * EDSCALE);
objects.push_back(obj->get_instance_id());
_add_children_to_popup(obj, p_depth + 1);
}
}
+void EditorPath::_show_popup() {
+ sub_objects_menu->clear();
+
+ Size2 size = get_size();
+ Point2 gp = get_screen_position();
+ gp.y += size.y;
+
+ sub_objects_menu->set_position(gp);
+ sub_objects_menu->set_size(Size2(size.width, 1));
+ sub_objects_menu->set_parent_rect(Rect2(Point2(gp - sub_objects_menu->get_position()), size));
+
+ sub_objects_menu->take_mouse_focus();
+ sub_objects_menu->popup();
+}
+
void EditorPath::_about_to_show() {
Object *obj = ObjectDB::get_instance(history->get_path_object(history->get_path_size() - 1));
if (!obj) {
@@ -75,13 +100,11 @@ void EditorPath::_about_to_show() {
}
objects.clear();
- get_popup()->clear();
- get_popup()->set_size(Size2(get_size().width, 1));
_add_children_to_popup(obj);
- if (get_popup()->get_item_count() == 0) {
- get_popup()->add_item(TTR("No sub-resources found."));
- get_popup()->set_item_disabled(0, true);
+ if (sub_objects_menu->get_item_count() == 0) {
+ sub_objects_menu->add_item(TTR("No sub-resources found."));
+ sub_objects_menu->set_item_disabled(0, true);
}
}
@@ -94,7 +117,7 @@ void EditorPath::update_path() {
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
if (icon.is_valid()) {
- set_icon(icon);
+ current_object_icon->set_texture(icon);
}
if (i == history->get_path_size() - 1) {
@@ -120,12 +143,26 @@ void EditorPath::update_path() {
name = obj->get_class();
}
- set_text(" " + name); // An extra space so the text is not too close of the icon.
+ current_object_label->set_text(" " + name); // An extra space so the text is not too close of the icon.
set_tooltip(obj->get_class());
}
}
}
+void EditorPath::clear_path() {
+ set_disabled(true);
+ set_tooltip("");
+
+ current_object_label->set_text("");
+ current_object_icon->set_texture(nullptr);
+ sub_objects_icon->set_visible(false);
+}
+
+void EditorPath::enable_path() {
+ set_disabled(false);
+ sub_objects_icon->set_visible(true);
+}
+
void EditorPath::_id_pressed(int p_idx) {
ERR_FAIL_INDEX(p_idx, objects.size());
@@ -139,8 +176,16 @@ void EditorPath::_id_pressed(int p_idx) {
void EditorPath::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
update_path();
+
+ sub_objects_icon->set_texture(get_theme_icon("select_arrow", "Tree"));
+ current_object_label->add_theme_font_override("font", get_theme_font("main", "EditorFonts"));
+ } break;
+
+ case NOTIFICATION_READY: {
+ connect("pressed", callable_mp(this, &EditorPath::_show_popup));
} break;
}
}
@@ -150,8 +195,35 @@ void EditorPath::_bind_methods() {
EditorPath::EditorPath(EditorHistory *p_history) {
history = p_history;
- set_clip_text(true);
- set_text_align(ALIGN_LEFT);
- get_popup()->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show));
- get_popup()->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed));
+
+ MarginContainer *main_mc = memnew(MarginContainer);
+ main_mc->set_anchors_and_offsets_preset(PRESET_WIDE);
+ main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE);
+ main_mc->add_theme_constant_override("margin_right", 6 * EDSCALE);
+ add_child(main_mc);
+
+ HBoxContainer *main_hb = memnew(HBoxContainer);
+ main_mc->add_child(main_hb);
+
+ current_object_icon = memnew(TextureRect);
+ current_object_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ main_hb->add_child(current_object_icon);
+
+ current_object_label = memnew(Label);
+ current_object_label->set_clip_text(true);
+ current_object_label->set_align(Label::ALIGN_LEFT);
+ current_object_label->set_h_size_flags(SIZE_EXPAND_FILL);
+ main_hb->add_child(current_object_label);
+
+ sub_objects_icon = memnew(TextureRect);
+ sub_objects_icon->set_visible(false);
+ sub_objects_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ main_hb->add_child(sub_objects_icon);
+
+ sub_objects_menu = memnew(PopupMenu);
+ add_child(sub_objects_menu);
+ sub_objects_menu->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show));
+ sub_objects_menu->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed));
+
+ set_tooltip(TTR("Open a list of sub-resources."));
}
diff --git a/editor/editor_path.h b/editor/editor_path.h
index d1090947f9..cabfa931d6 100644
--- a/editor/editor_path.h
+++ b/editor/editor_path.h
@@ -32,16 +32,24 @@
#define EDITOR_PATH_H
#include "editor_data.h"
-#include "scene/gui/menu_button.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/popup_menu.h"
-class EditorPath : public MenuButton {
- GDCLASS(EditorPath, MenuButton);
+class EditorPath : public Button {
+ GDCLASS(EditorPath, Button);
EditorHistory *history;
+ TextureRect *current_object_icon;
+ Label *current_object_label;
+ TextureRect *sub_objects_icon;
+ PopupMenu *sub_objects_menu;
+
Vector<ObjectID> objects;
EditorPath();
+ void _show_popup();
void _id_pressed(int p_idx);
void _about_to_show();
void _add_children_to_popup(Object *p_obj, int p_depth = 0);
@@ -52,6 +60,8 @@ protected:
public:
void update_path();
+ void clear_path();
+ void enable_path();
EditorPath(EditorHistory *p_history);
};
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 0e8e9a9a32..e8c01d0e0c 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -42,6 +42,14 @@ void InspectorDock::_menu_option(int p_option) {
case COLLAPSE_ALL: {
_menu_collapseall();
} break;
+
+ case RESOURCE_SAVE: {
+ _save_resource(false);
+ } break;
+ case RESOURCE_SAVE_AS: {
+ _save_resource(true);
+ } break;
+
case RESOURCE_MAKE_BUILT_IN: {
_unref_resource();
} break;
@@ -52,13 +60,6 @@ void InspectorDock::_menu_option(int p_option) {
_paste_resource();
} break;
- case RESOURCE_SAVE: {
- _save_resource(false);
- } break;
- case RESOURCE_SAVE_AS: {
- _save_resource(true);
- } break;
-
case OBJECT_REQUEST_HELP: {
if (current) {
editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
@@ -335,9 +336,16 @@ void InspectorDock::_notification(int p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
set_theme(editor->get_gui_base()->get_theme());
+
resource_new_button->set_icon(get_theme_icon("New", "EditorIcons"));
resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons"));
resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons"));
+ resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+
+ PopupMenu *resource_extra_popup = resource_extra_button->get_popup();
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), get_theme_icon("ActionPaste", "EditorIcons"));
+ resource_extra_popup->set_item_icon(resource_extra_popup->get_item_index(RESOURCE_COPY), get_theme_icon("ActionCopy", "EditorIcons"));
+
if (is_layout_rtl()) {
backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
@@ -345,6 +353,7 @@ void InspectorDock::_notification(int p_what) {
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
}
+
history_menu->set_icon(get_theme_icon("History", "EditorIcons"));
object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
@@ -403,12 +412,7 @@ void InspectorDock::update(Object *p_object) {
object_menu->set_disabled(true);
warning->hide();
search->set_editable(false);
-
- editor_path->set_disabled(true);
- editor_path->set_text("");
- editor_path->set_tooltip("");
- editor_path->set_icon(nullptr);
-
+ editor_path->clear_path();
return;
}
@@ -417,35 +421,28 @@ void InspectorDock::update(Object *p_object) {
object_menu->set_disabled(false);
search->set_editable(true);
- editor_path->set_disabled(false);
+ editor_path->enable_path();
+
resource_save_button->set_disabled(!is_resource);
+ open_docs_button->set_visible(is_resource || is_node);
+
+ PopupMenu *resource_extra_popup = resource_extra_button->get_popup();
+ resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_COPY), !is_resource);
+ resource_extra_popup->set_item_disabled(resource_extra_popup->get_item_index(RESOURCE_MAKE_BUILT_IN), !is_resource);
PopupMenu *p = object_menu->get_popup();
p->clear();
- p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand All Properties")), EXPAND_ALL);
- p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All Properties")), COLLAPSE_ALL);
- p->add_separator();
- if (is_resource) {
- p->add_item(TTR("Save"), RESOURCE_SAVE);
- p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
- p->add_separator();
- }
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
+ p->add_icon_shortcut(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL);
+ p->add_icon_shortcut(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource Clipboard")), RESOURCE_EDIT_CLIPBOARD);
- if (is_resource) {
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
- p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_MAKE_BUILT_IN);
- }
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Properties")), OBJECT_COPY_PARAMS);
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Properties")), OBJECT_PASTE_PARAMS);
if (is_resource || is_node) {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
- p->add_separator();
- p->add_icon_shortcut(get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
}
List<MethodInfo> methods;
@@ -525,6 +522,17 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_save_button->set_focus_mode(Control::FOCUS_NONE);
resource_save_button->set_disabled(true);
+ resource_extra_button = memnew(MenuButton);
+ resource_extra_button->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+ general_options_hb->add_child(resource_extra_button);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionPaste", "EditorIcons"), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
+ resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon("ActionCopy", "EditorIcons"), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+ resource_extra_button->get_popup()->set_item_disabled(1, true);
+ resource_extra_button->get_popup()->add_separator();
+ resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Resource Built-In")), RESOURCE_MAKE_BUILT_IN);
+ resource_extra_button->get_popup()->set_item_disabled(3, true);
+ resource_extra_button->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
+
general_options_hb->add_spacer();
backward_button = memnew(Button);
@@ -558,31 +566,42 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history));
history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history));
- HBoxContainer *node_info_hb = memnew(HBoxContainer);
- add_child(node_info_hb);
-
+ HBoxContainer *subresource_hb = memnew(HBoxContainer);
+ add_child(subresource_hb);
editor_path = memnew(EditorPath(editor->get_editor_history()));
editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- node_info_hb->add_child(editor_path);
+ subresource_hb->add_child(editor_path);
- object_menu = memnew(MenuButton);
- object_menu->set_shortcut_context(this);
- object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
- node_info_hb->add_child(object_menu);
- object_menu->set_tooltip(TTR("Object properties."));
- object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
+ open_docs_button = memnew(Button);
+ open_docs_button->set_flat(true);
+ open_docs_button->set_visible(false);
+ open_docs_button->set_tooltip(TTR("Open documentation for this object."));
+ open_docs_button->set_icon(get_theme_icon("HelpSearch", "EditorIcons"));
+ open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation")));
+ subresource_hb->add_child(open_docs_button);
+ open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option), varray(OBJECT_REQUEST_HELP));
new_resource_dialog = memnew(CreateDialog);
editor->get_gui_base()->add_child(new_resource_dialog);
new_resource_dialog->set_base_type("Resource");
new_resource_dialog->connect("create", callable_mp(this, &InspectorDock::_resource_created));
+ HBoxContainer *property_tools_hb = memnew(HBoxContainer);
+ add_child(property_tools_hb);
+
search = memnew(LineEdit);
search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search->set_placeholder(TTR("Filter properties"));
search->set_right_icon(get_theme_icon("Search", "EditorIcons"));
search->set_clear_button_enabled(true);
- add_child(search);
+ property_tools_hb->add_child(search);
+
+ object_menu = memnew(MenuButton);
+ object_menu->set_shortcut_context(this);
+ object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
+ property_tools_hb->add_child(object_menu);
+ object_menu->set_tooltip(TTR("Manage object properties."));
+ object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option));
warning = memnew(Button);
add_child(warning);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index bc16a3b628..d50785d95c 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -81,9 +81,11 @@ class InspectorDock : public VBoxContainer {
Button *resource_new_button;
Button *resource_load_button;
MenuButton *resource_save_button;
+ MenuButton *resource_extra_button;
MenuButton *history_menu;
LineEdit *search;
+ Button *open_docs_button;
MenuButton *object_menu;
EditorPath *editor_path;
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp
index 8d3242db2b..9323c31fae 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/node_3d_editor_gizmos.cpp
@@ -1541,19 +1541,46 @@ Position3DGizmoPlugin::Position3DGizmoPlugin() {
cursor_points = Vector<Vector3>();
Vector<Color> cursor_colors;
- float cs = 0.25;
+ const float cs = 0.25;
+ // Add more points to create a "hard stop" in the color gradient.
cursor_points.push_back(Vector3(+cs, 0, 0));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(-cs, 0, 0));
+
cursor_points.push_back(Vector3(0, +cs, 0));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(0, -cs, 0));
+
cursor_points.push_back(Vector3(0, 0, +cs));
+ cursor_points.push_back(Vector3());
+ cursor_points.push_back(Vector3());
cursor_points.push_back(Vector3(0, 0, -cs));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor"));
- cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor"));
+
+ // Use the axis color which is brighter for the positive axis.
+ // Use a darkened axis color for the negative axis.
+ // This makes it possible to see in which direction the Position3D node is rotated
+ // (which can be important depending on how it's used).
+ const Color color_x = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor");
+ cursor_colors.push_back(color_x);
+ cursor_colors.push_back(color_x);
+ // FIXME: Use less strong darkening factor once GH-48573 is fixed.
+ // The current darkening factor compensates for lines being too bright in the 3D editor.
+ cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_x.lerp(Color(0, 0, 0), 0.75));
+
+ const Color color_y = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor");
+ cursor_colors.push_back(color_y);
+ cursor_colors.push_back(color_y);
+ cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_y.lerp(Color(0, 0, 0), 0.75));
+
+ const Color color_z = EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor");
+ cursor_colors.push_back(color_z);
+ cursor_colors.push_back(color_z);
+ cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75));
+ cursor_colors.push_back(color_z.lerp(Color(0, 0, 0), 0.75));
Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index cf237f5a4a..235ccb18cb 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -832,7 +832,7 @@ struct FSample {
};
static FSample _samples[] = {
- { "hani", U"漢語" },
+ { "hani", U"漢字" },
{ "armn", U"Աբ" },
{ "copt", U"Αα" },
{ "cyrl", U"Аб" },
diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp
index fa58eb5480..8de7dc2447 100644
--- a/editor/plugins/font_editor_plugin.cpp
+++ b/editor/plugins/font_editor_plugin.cpp
@@ -56,7 +56,7 @@ struct FSample {
};
static FSample _samples[] = {
- { "hani", U"漢語" },
+ { "hani", U"漢字" },
{ "armn", U"Աբ" },
{ "copt", U"Αα" },
{ "cyrl", U"Аб" },
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 1edcbd2cc9..e1c6e61a0b 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -538,7 +538,7 @@ TextEditor::TextEditor() {
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option));
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("un_redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_cut"), EDIT_CUT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_copy"), EDIT_COPY);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 9ed9bdcb96..1b596ce599 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -2621,7 +2621,7 @@ ProjectManager::ProjectManager() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
- hash = "." + hash.left(9);
+ hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text("v" VERSION_FULL_BUILD + hash);
// Fade the version label to be less prominent, but still readable.
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 4cdf820877..c05a3c2f89 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -261,10 +261,6 @@ void EditorSettingsDialog::_update_shortcuts() {
for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) {
String action_name = E.key();
- if (!shortcut_filter.is_subsequence_ofi(action_name)) {
- continue;
- }
-
InputMap::Action action = E.get();
Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
@@ -298,6 +294,10 @@ void EditorSettingsDialog::_update_shortcuts() {
// Join the text of the events with a delimiter so they can all be displayed in one cell.
String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings);
+ if (!shortcut_filter.is_subsequence_ofi(action_name) && (events_display_string == "None" || !shortcut_filter.is_subsequence_ofi(events_display_string))) {
+ continue;
+ }
+
TreeItem *item = shortcuts->create_item(common_section);
item->set_text(0, action_name);
item->set_text(1, events_display_string);
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 2dac8e9a55..81bc412944 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -76,7 +76,8 @@ fi
# To get consistent formatting, we recommend contributors to use the same
# clang-format version as CI.
-RECOMMENDED_CLANG_FORMAT_MAJOR="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="12"
if [ ! -x "$CLANG_FORMAT" ] ; then
message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x."
@@ -106,8 +107,8 @@ fi
CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/\1/")"
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d. -f1)"
-if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then
- echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)."
+if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then
+ echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN.x.x and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX.x.x)."
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
fi
diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index b2abf8b8ae..b10a747568 100644
--- a/modules/gdnative/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -70,8 +70,7 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char
const NativeScriptDesc *b = desc.base_data;
while (b) {
- desc.rpc_count += b->rpc_count;
- desc.rset_count += b->rset_count;
+ desc.rpc_methods.append_array(b->rpc_methods);
b = b->base_data;
}
@@ -94,8 +93,6 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const
desc.destroy_func = p_destroy_func;
desc.is_tool = true;
desc.base = p_base;
- desc.rpc_count = 0;
- desc.rset_count = 0;
if (classes->has(p_base)) {
desc.base_data = &(*classes)[p_base];
@@ -103,8 +100,7 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const
const NativeScriptDesc *b = desc.base_data;
while (b) {
- desc.rpc_count += b->rpc_count;
- desc.rset_count += b->rset_count;
+ desc.rpc_methods.append_array(b->rpc_methods);
b = b->base_data;
}
@@ -126,13 +122,16 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha
method.method = p_method;
method.rpc_mode = p_attr.rpc_type;
method.rpc_method_id = UINT16_MAX;
- if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) {
- method.rpc_method_id = E->get().rpc_count;
- E->get().rpc_count += 1;
- }
method.info = MethodInfo(p_function_name);
E->get().methods.insert(p_function_name, method);
+
+ if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) {
+ MultiplayerAPI::RPCConfig nd;
+ nd.name = String(p_name);
+ nd.rpc_mode = MultiplayerAPI::RPCMode(p_attr.rpc_type);
+ E->get().rpc_methods.push_back(nd);
+ }
}
void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_nativescript_property_attributes *p_attr, godot_nativescript_property_set_func p_set_func, godot_nativescript_property_get_func p_get_func) {
@@ -144,11 +143,6 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c
NativeScriptDesc::Property property;
property.default_value = *(Variant *)&p_attr->default_value;
property.getter = p_get_func;
- property.rset_mode = p_attr->rset_type;
- if (p_attr->rset_type != GODOT_METHOD_RPC_MODE_DISABLED) {
- property.rset_property_id = E->get().rset_count;
- E->get().rset_count += 1;
- }
property.setter = p_set_func;
property.info = PropertyInfo((Variant::Type)p_attr->type,
p_path,
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 46af70f73c..03e25f49e6 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -415,245 +415,11 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
}
}
-Vector<ScriptNetData> NativeScript::get_rpc_methods() const {
- Vector<ScriptNetData> v;
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E->key();
- nd.mode = MultiplayerAPI::RPCMode(E->get().rpc_mode);
- v.push_back(nd);
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return v;
-}
-
-uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
- if (E) {
- return E->get().rpc_method_id;
- }
-
- script_data = script_data->base_data;
- }
-
- return UINT16_MAX;
-}
-
-StringName NativeScript::get_rpc_method(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
-
+const Vector<MultiplayerAPI::RPCConfig> NativeScript::get_rpc_methods() const {
NativeScriptDesc *script_data = get_script_desc();
+ ERR_FAIL_COND_V(!script_data, Vector<MultiplayerAPI::RPCConfig>());
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_method_id == p_id) {
- return E->key();
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return StringName();
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
- if (E->get().rpc_method_id == p_id) {
- switch (E->get().rpc_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
- if (E) {
- switch (E->get().rpc_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-Vector<ScriptNetData> NativeScript::get_rset_properties() const {
- Vector<ScriptNetData> v;
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E.key();
- nd.mode = MultiplayerAPI::RPCMode(E.get().rset_mode);
- v.push_back(nd);
- }
- }
- script_data = script_data->base_data;
- }
-
- return v;
-}
-
-uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
- if (E) {
- return E.get().rset_property_id;
- }
-
- script_data = script_data->base_data;
- }
-
- return UINT16_MAX;
-}
-
-StringName NativeScript::get_rset_property(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_property_id == p_id) {
- return E.key();
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return StringName();
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const {
- ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
-
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
- if (E.get().rset_property_id == p_id) {
- switch (E.get().rset_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const {
- NativeScriptDesc *script_data = get_script_desc();
-
- while (script_data) {
- OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
- if (E) {
- switch (E.get().rset_mode) {
- case GODOT_METHOD_RPC_MODE_DISABLED:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- case GODOT_METHOD_RPC_MODE_REMOTE:
- return MultiplayerAPI::RPC_MODE_REMOTE;
- case GODOT_METHOD_RPC_MODE_MASTER:
- return MultiplayerAPI::RPC_MODE_MASTER;
- case GODOT_METHOD_RPC_MODE_PUPPET:
- return MultiplayerAPI::RPC_MODE_PUPPET;
- case GODOT_METHOD_RPC_MODE_REMOTESYNC:
- return MultiplayerAPI::RPC_MODE_REMOTESYNC;
- case GODOT_METHOD_RPC_MODE_MASTERSYNC:
- return MultiplayerAPI::RPC_MODE_MASTERSYNC;
- case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
- return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
- default:
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- }
-
- script_data = script_data->base_data;
- }
-
- return MultiplayerAPI::RPC_MODE_DISABLED;
+ return script_data->rpc_methods;
}
String NativeScript::get_class_documentation() const {
@@ -1046,46 +812,10 @@ Ref<Script> NativeScriptInstance::get_script() const {
return script;
}
-Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> NativeScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const {
- return script->get_rpc_method(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
- return script->get_rpc_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> NativeScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t NativeScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const {
- return script->get_rset_property(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
- return script->get_rset_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
ScriptLanguage *NativeScriptInstance::get_language() {
return NativeScriptLanguage::get_singleton();
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index ca5e76e43e..1756321281 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -62,8 +62,6 @@ struct NativeScriptDesc {
godot_nativescript_property_get_func getter;
PropertyInfo info;
Variant default_value;
- int rset_mode = 0;
- uint16_t rset_property_id;
String documentation;
};
@@ -72,9 +70,8 @@ struct NativeScriptDesc {
String documentation;
};
- uint16_t rpc_count = 0;
Map<StringName, Method> methods;
- uint16_t rset_count = 0;
+ Vector<MultiplayerAPI::RPCConfig> rpc_methods;
OrderedHashMap<StringName, Property> properties;
Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals
StringName base;
@@ -178,17 +175,7 @@ public:
virtual void get_script_method_list(List<MethodInfo> *p_list) const override;
virtual void get_script_property_list(List<PropertyInfo> *p_list) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const override;
- virtual StringName get_rset_property(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
String get_class_documentation() const;
String get_method_documentation(const StringName &p_method) const;
@@ -226,17 +213,7 @@ public:
String to_string(bool *r_valid);
virtual Ref<Script> get_script() const;
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
virtual ScriptLanguage *get_language();
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp
index 7f8dba0906..ed1c0af3ed 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp
@@ -100,46 +100,10 @@ String PluginScriptInstance::to_string(bool *r_valid) {
return str_ret;
}
-Vector<ScriptNetData> PluginScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> PluginScriptInstance::get_rpc_methods() const {
return _script->get_rpc_methods();
}
-uint16_t PluginScriptInstance::get_rpc_method_id(const StringName &p_variable) const {
- return _script->get_rpc_method_id(p_variable);
-}
-
-StringName PluginScriptInstance::get_rpc_method(uint16_t p_id) const {
- return _script->get_rpc_method(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
- return _script->get_rpc_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return _script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> PluginScriptInstance::get_rset_properties() const {
- return _script->get_rset_properties();
-}
-
-uint16_t PluginScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return _script->get_rset_property_id(p_variable);
-}
-
-StringName PluginScriptInstance::get_rset_property(uint16_t p_id) const {
- return _script->get_rset_property(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
- return _script->get_rset_mode_by_id(p_id);
-}
-
-MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return _script->get_rset_mode(p_variable);
-}
-
void PluginScriptInstance::refcount_incremented() {
if (_desc->refcount_decremented) {
_desc->refcount_incremented(_data);
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
index b263c0e62c..25b62ae8ab 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.h
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -71,17 +71,7 @@ public:
void set_path(const String &p_path);
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
virtual void refcount_incremented();
virtual bool refcount_decremented();
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index a48245814f..6bb11d3e8f 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -312,10 +312,9 @@ Error PluginScript::reload(bool p_keep_state) {
}
Array *methods = (Array *)&manifest.methods;
_rpc_methods.clear();
- _rpc_variables.clear();
if (_ref_base_parent.is_valid()) {
+ /// XXX TODO Should this be _rpc_methods.append_array(...)
_rpc_methods = _ref_base_parent->get_rpc_methods();
- _rpc_variables = _ref_base_parent->get_rset_properties();
}
for (int i = 0; i < methods->size(); ++i) {
Dictionary v = (*methods)[i];
@@ -324,9 +323,10 @@ Error PluginScript::reload(bool p_keep_state) {
// rpc_mode is passed as an optional field and is not part of MethodInfo
Variant var = v["rpc_mode"];
if (var != Variant()) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = mi.name;
- nd.mode = MultiplayerAPI::RPCMode(int(var));
+ nd.rpc_mode = MultiplayerAPI::RPCMode(int(var));
+ // TODO Transfer Channel
if (_rpc_methods.find(nd) == -1) {
_rpc_methods.push_back(nd);
}
@@ -334,7 +334,7 @@ Error PluginScript::reload(bool p_keep_state) {
}
// Sort so we are 100% that they are always the same.
- _rpc_methods.sort_custom<SortNetData>();
+ _rpc_methods.sort_custom<MultiplayerAPI::SortRPCConfig>();
Array *signals = (Array *)&manifest.signals;
for (int i = 0; i < signals->size(); ++i) {
@@ -348,21 +348,8 @@ Error PluginScript::reload(bool p_keep_state) {
PropertyInfo pi = PropertyInfo::from_dict(v);
_properties_info[pi.name] = pi;
_properties_default_values[pi.name] = v["default_value"];
- // rset_mode is passed as an optional field and is not part of PropertyInfo
- Variant var = v["rset_mode"];
- if (var != Variant()) {
- ScriptNetData nd;
- nd.name = pi.name;
- nd.mode = MultiplayerAPI::RPCMode(int(var));
- if (_rpc_variables.find(nd) == -1) {
- _rpc_variables.push_back(nd);
- }
- }
}
- // Sort so we are 100% that they are always the same.
- _rpc_variables.sort_custom<SortNetData>();
-
#ifdef TOOLS_ENABLED
/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
@@ -486,76 +473,10 @@ int PluginScript::get_member_line(const StringName &p_member) const {
return -1;
}
-Vector<ScriptNetData> PluginScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> PluginScript::get_rpc_methods() const {
return _rpc_methods;
}
-uint16_t PluginScript::get_rpc_method_id(const StringName &p_method) const {
- ASSERT_SCRIPT_VALID_V(UINT16_MAX);
- for (int i = 0; i < _rpc_methods.size(); i++) {
- if (_rpc_methods[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName PluginScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ASSERT_SCRIPT_VALID_V(StringName());
- if (p_rpc_method_id >= _rpc_methods.size()) {
- return StringName();
- }
- return _rpc_methods[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- if (p_rpc_method_id >= _rpc_methods.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return _rpc_methods[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> PluginScript::get_rset_properties() const {
- return _rpc_variables;
-}
-
-uint16_t PluginScript::get_rset_property_id(const StringName &p_property) const {
- ASSERT_SCRIPT_VALID_V(UINT16_MAX);
- for (int i = 0; i < _rpc_variables.size(); i++) {
- if (_rpc_variables[i].name == p_property) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName PluginScript::get_rset_property(const uint16_t p_rset_property_id) const {
- ASSERT_SCRIPT_VALID_V(StringName());
- if (p_rset_property_id >= _rpc_variables.size()) {
- return StringName();
- }
- return _rpc_variables[p_rset_property_id].name;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rset_mode_by_id(const uint16_t p_rset_property_id) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- if (p_rset_property_id >= _rpc_variables.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return _rpc_variables[p_rset_property_id].mode;
-}
-
-MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
- ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
PluginScript::PluginScript() :
_script_list(this) {
}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h
index 1c86f2056d..97989a19d8 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.h
+++ b/modules/gdnative/pluginscript/pluginscript_script.h
@@ -61,8 +61,7 @@ private:
Map<StringName, PropertyInfo> _properties_info;
Map<StringName, MethodInfo> _signals_info;
Map<StringName, MethodInfo> _methods_info;
- Vector<ScriptNetData> _rpc_methods;
- Vector<ScriptNetData> _rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> _rpc_methods;
Set<Object *> _instances;
//exported members
@@ -137,17 +136,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const override;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
PluginScript();
void init(PluginScriptLanguage *language);
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index d34cccb3af..b867b03903 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -64,6 +64,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
bool in_function_args = false;
bool in_member_variable = false;
bool in_node_path = false;
+ bool in_annotation = false;
bool is_hex_notation = false;
bool is_bin_notation = false;
bool expect_type = false;
@@ -357,9 +358,18 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
in_node_path = false;
}
+ if (!in_annotation && in_region == -1 && str[j] == '@') {
+ in_annotation = true;
+ } else if (in_region != -1 || is_a_symbol) {
+ in_annotation = false;
+ }
+
if (in_node_path) {
next_type = NODE_PATH;
color = node_path_color;
+ } else if (in_annotation) {
+ next_type = ANNOTATION;
+ color = annotation_color;
} else if (in_keyword) {
next_type = KEYWORD;
color = keyword_color;
@@ -546,19 +556,22 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
- const bool default_theme = text_edit_color_theme == "Godot 2";
+ const bool godot_2_theme = text_edit_color_theme == "Godot 2";
- if (default_theme || EditorSettings::get_singleton()->is_dark_theme()) {
+ if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) {
function_definition_color = Color(0.4, 0.9, 1.0);
node_path_color = Color(0.39, 0.76, 0.35);
+ annotation_color = Color(1.0, 0.7, 0.45);
} else {
function_definition_color = Color(0.0, 0.65, 0.73);
node_path_color = Color(0.32, 0.55, 0.29);
+ annotation_color = Color(0.8, 0.5, 0.25);
}
EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
- if (text_edit_color_theme == "Default" || default_theme) {
+ EDITOR_DEF("text_editor/highlighting/gdscript/annotation_color", annotation_color);
+ if (text_edit_color_theme == "Default" || godot_2_theme) {
EditorSettings::get_singleton()->set_initial_value(
"text_editor/highlighting/gdscript/function_definition_color",
function_definition_color,
@@ -567,10 +580,15 @@ void GDScriptSyntaxHighlighter::_update_cache() {
"text_editor/highlighting/gdscript/node_path_color",
node_path_color,
true);
+ EditorSettings::get_singleton()->set_initial_value(
+ "text_editor/highlighting/gdscript/annotation_color",
+ annotation_color,
+ true);
}
function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
+ annotation_color = EDITOR_GET("text_editor/highlighting/gdscript/annotation_color");
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index 1b57cb1923..d07c182aa6 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -54,6 +54,7 @@ private:
NONE,
REGION,
NODE_PATH,
+ ANNOTATION,
SYMBOL,
NUMBER,
FUNCTION,
@@ -72,6 +73,7 @@ private:
Color number_color;
Color member_color;
Color node_path_color;
+ Color annotation_color;
Color type_color;
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index d7814e85b0..e99c3d6cca 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -897,68 +897,10 @@ void GDScript::get_members(Set<StringName> *p_members) {
}
}
-Vector<ScriptNetData> GDScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> GDScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- if (p_rpc_method_id >= rpc_functions.size()) {
- return StringName();
- }
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- if (p_rpc_method_id >= rpc_functions.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> GDScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const {
- if (p_rset_member_id >= rpc_variables.size()) {
- return StringName();
- }
- return rpc_variables[p_rset_member_id].name;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- if (p_rset_member_id >= rpc_variables.size()) {
- return MultiplayerAPI::RPC_MODE_DISABLED;
- }
- return rpc_variables[p_rset_member_id].mode;
-}
-
-MultiplayerAPI::RPCMode GDScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *top = this;
while (top) {
@@ -1210,10 +1152,8 @@ void GDScript::_save_orphaned_subclasses() {
void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
rpc_functions.clear();
- rpc_variables.clear();
if (base.is_valid()) {
rpc_functions = base->rpc_functions;
- rpc_variables = base->rpc_variables;
}
GDScript *cscript = this;
@@ -1222,25 +1162,17 @@ void GDScript::_init_rpc_methods_properties() {
// RPC Methods
for (Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.front(); E; E = E->next()) {
if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = E->key();
- nd.mode = E->get()->get_rpc_mode();
+ nd.rpc_mode = E->get()->get_rpc_mode();
+ // TODO
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ nd.channel = 0;
if (-1 == rpc_functions.find(nd)) {
rpc_functions.push_back(nd);
}
}
}
- // RSet
- for (Map<StringName, MemberInfo>::Element *E = cscript->member_indices.front(); E; E = E->next()) {
- if (E->get().rpc_mode != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
- nd.name = E->key();
- nd.mode = E->get().rpc_mode;
- if (-1 == rpc_variables.find(nd)) {
- rpc_variables.push_back(nd);
- }
- }
- }
if (cscript != this) {
sub_E = sub_E->next();
@@ -1254,8 +1186,7 @@ void GDScript::_init_rpc_methods_properties() {
}
// Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<SortNetData>();
- rpc_variables.sort_custom<SortNetData>();
+ rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
}
GDScript::~GDScript() {
@@ -1611,46 +1542,10 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-Vector<ScriptNetData> GDScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> GDScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t GDScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName GDScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> GDScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t GDScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName GDScriptInstance::get_rset_property(const uint16_t p_rset_member_id) const {
- return script->get_rset_property(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- return script->get_rset_mode_by_id(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void GDScriptInstance::reload_members() {
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 6df66e876d..8b1b859ca2 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -86,8 +86,7 @@ class GDScript : public Script {
Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script.
Map<StringName, Ref<GDScript>> subclasses;
Map<StringName, Vector<StringName>> _signals;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
@@ -247,17 +246,7 @@ public:
virtual void get_constants(Map<StringName, Variant> *p_constants) override;
virtual void get_members(Set<StringName> *p_members) override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const override;
- virtual StringName get_rset_property(const uint16_t p_variable_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
virtual bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -310,17 +299,7 @@ public:
void reload_members();
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_variable) const;
- virtual StringName get_rset_property(const uint16_t p_variable_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
GDScriptInstance();
~GDScriptInstance();
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 5406e17054..ac248bcff8 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2105,46 +2105,10 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-Vector<ScriptNetData> CSharpInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> CSharpInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t CSharpInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName CSharpInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> CSharpInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t CSharpInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName CSharpInstance::get_rset_property(const uint16_t p_rset_member_id) const {
- return script->get_rset_property(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- return script->get_rset_mode_by_id(p_rset_member_id);
-}
-
-MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void CSharpInstance::notification(int p_notification) {
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -3046,7 +3010,6 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
p_script->rpc_functions.clear();
- p_script->rpc_variables.clear();
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
@@ -3060,9 +3023,12 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
if (!methods[i]->is_static()) {
MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = methods[i]->get_name();
- nd.mode = mode;
+ nd.rpc_mode = mode;
+ // TODO Transfer mode, channel
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE;
+ nd.channel = 0;
if (-1 == p_script->rpc_functions.find(nd)) {
p_script->rpc_functions.push_back(nd);
}
@@ -3071,46 +3037,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
}
}
- {
- Vector<GDMonoField *> fields = top->get_all_fields();
- for (int i = 0; i < fields.size(); i++) {
- if (!fields[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(fields[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = fields[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
- {
- Vector<GDMonoProperty *> properties = top->get_all_properties();
- for (int i = 0; i < properties.size(); i++) {
- if (!properties[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(properties[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = properties[i]->get_name();
- nd.mode = mode;
- if (-1 == p_script->rpc_variables.find(nd)) {
- p_script->rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
top = top->get_parent_class();
}
// Sort so we are 100% that they are always the same.
- p_script->rpc_functions.sort_custom<SortNetData>();
- p_script->rpc_variables.sort_custom<SortNetData>();
+ p_script->rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
p_script->load_script_signals(p_script->script_class, p_script->native);
}
@@ -3543,60 +3474,10 @@ MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_m
return MultiplayerAPI::RPC_MODE_DISABLED;
}
-Vector<ScriptNetData> CSharpScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> CSharpScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t CSharpScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> CSharpScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t CSharpScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName CSharpScript::get_rset_property(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName());
- return rpc_variables[p_rset_member_id].name;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rset_member_id].mode;
-}
-
-MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
Error CSharpScript::load_source_code(const String &p_path) {
Error ferr = read_all_file_utf8(p_path, source);
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 145bf8cf85..b389e900f4 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -136,8 +136,7 @@ private:
Map<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
@@ -235,17 +234,7 @@ public:
int get_member_line(const StringName &p_member) const override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
bool is_placeholder_fallback_enabled() const override { return placeholder_fallback_enabled; }
@@ -322,17 +311,7 @@ public:
void refcount_incremented() override;
bool refcount_decremented() override;
- Vector<ScriptNetData> get_rpc_methods() const override;
- uint16_t get_rpc_method_id(const StringName &p_method) const override;
- StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- Vector<ScriptNetData> get_rset_properties() const override;
- uint16_t get_rset_property_id(const StringName &p_variable) const override;
- StringName get_rset_property(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_variable_id) const override;
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
void notification(int p_notification) override;
void _call_notification(int p_notification);
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index b863f622bd..c9ed912ac1 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -954,60 +954,10 @@ bool VisualScript::are_subnodes_edited() const {
}
#endif
-Vector<ScriptNetData> VisualScript::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> VisualScript::get_rpc_methods() const {
return rpc_functions;
}
-uint16_t VisualScript::get_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < rpc_functions.size(); i++) {
- if (rpc_functions[i].name == p_method) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName VisualScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
- return rpc_functions[p_rpc_method_id].name;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_functions[p_rpc_method_id].mode;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rpc_mode(const StringName &p_method) const {
- return get_rpc_mode_by_id(get_rpc_method_id(p_method));
-}
-
-Vector<ScriptNetData> VisualScript::get_rset_properties() const {
- return rpc_variables;
-}
-
-uint16_t VisualScript::get_rset_property_id(const StringName &p_variable) const {
- for (int i = 0; i < rpc_variables.size(); i++) {
- if (rpc_variables[i].name == p_variable) {
- return i;
- }
- }
- return UINT16_MAX;
-}
-
-StringName VisualScript::get_rset_property(const uint16_t p_rset_property_id) const {
- ERR_FAIL_COND_V(p_rset_property_id >= rpc_variables.size(), StringName());
- return rpc_variables[p_rset_property_id].name;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const {
- ERR_FAIL_COND_V(p_rset_variable_id >= rpc_variables.size(), MultiplayerAPI::RPC_MODE_DISABLED);
- return rpc_variables[p_rset_variable_id].mode;
-}
-
-MultiplayerAPI::RPCMode VisualScript::get_rset_mode(const StringName &p_variable) const {
- return get_rset_mode_by_id(get_rset_property_id(p_variable));
-}
-
void VisualScript::_set_data(const Dictionary &p_data) {
Dictionary d = p_data;
if (d.has("base_type")) {
@@ -1065,7 +1015,6 @@ void VisualScript::_set_data(const Dictionary &p_data) {
// Takes all the rpc methods.
rpc_functions.clear();
- rpc_variables.clear();
List<StringName> fns;
functions.get_key_list(&fns);
for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) {
@@ -1073,9 +1022,10 @@ void VisualScript::_set_data(const Dictionary &p_data) {
Ref<VisualScriptFunction> vsf = nodes[functions[E->get()].func_id].node;
if (vsf.is_valid()) {
if (vsf->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
- ScriptNetData nd;
+ MultiplayerAPI::RPCConfig nd;
nd.name = E->get();
- nd.mode = vsf->get_rpc_mode();
+ nd.rpc_mode = vsf->get_rpc_mode();
+ nd.transfer_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
if (rpc_functions.find(nd) == -1) {
rpc_functions.push_back(nd);
}
@@ -1085,7 +1035,7 @@ void VisualScript::_set_data(const Dictionary &p_data) {
}
// Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<SortNetData>();
+ rpc_functions.sort_custom<MultiplayerAPI::SortRPCConfig>();
}
Dictionary VisualScript::_get_data() const {
@@ -1882,46 +1832,10 @@ Ref<Script> VisualScriptInstance::get_script() const {
return script;
}
-Vector<ScriptNetData> VisualScriptInstance::get_rpc_methods() const {
+const Vector<MultiplayerAPI::RPCConfig> VisualScriptInstance::get_rpc_methods() const {
return script->get_rpc_methods();
}
-uint16_t VisualScriptInstance::get_rpc_method_id(const StringName &p_method) const {
- return script->get_rpc_method_id(p_method);
-}
-
-StringName VisualScriptInstance::get_rpc_method(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_method(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- return script->get_rpc_mode_by_id(p_rpc_method_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
- return script->get_rpc_mode(p_method);
-}
-
-Vector<ScriptNetData> VisualScriptInstance::get_rset_properties() const {
- return script->get_rset_properties();
-}
-
-uint16_t VisualScriptInstance::get_rset_property_id(const StringName &p_variable) const {
- return script->get_rset_property_id(p_variable);
-}
-
-StringName VisualScriptInstance::get_rset_property(const uint16_t p_rset_property_id) const {
- return script->get_rset_property(p_rset_property_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode_by_id(const uint16_t p_rset_variable_id) const {
- return script->get_rset_mode_by_id(p_rset_variable_id);
-}
-
-MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return script->get_rset_mode(p_variable);
-}
-
void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
script = p_script;
owner = p_owner;
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index cc78b3242d..3c4a26a2a3 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -234,8 +234,7 @@ private:
HashMap<StringName, Function> functions;
HashMap<StringName, Variable> variables;
Map<StringName, Vector<Argument>> custom_signals;
- Vector<ScriptNetData> rpc_functions;
- Vector<ScriptNetData> rpc_variables;
+ Vector<MultiplayerAPI::RPCConfig> rpc_functions;
Map<Object *, VisualScriptInstance *> instances;
@@ -363,17 +362,7 @@ public:
virtual int get_member_line(const StringName &p_member) const override;
- virtual Vector<ScriptNetData> get_rpc_methods() const override;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const override;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override;
-
- virtual Vector<ScriptNetData> get_rset_properties() const override;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const override;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const override;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override;
#ifdef TOOLS_ENABLED
virtual bool are_subnodes_edited() const;
@@ -454,17 +443,7 @@ public:
virtual ScriptLanguage *get_language();
- virtual Vector<ScriptNetData> get_rpc_methods() const;
- virtual uint16_t get_rpc_method_id(const StringName &p_method) const;
- virtual StringName get_rpc_method(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
-
- virtual Vector<ScriptNetData> get_rset_properties() const;
- virtual uint16_t get_rset_property_id(const StringName &p_property) const;
- virtual StringName get_rset_property(const uint16_t p_rset_property_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(const uint16_t p_rpc_method_id) const;
- virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const;
VisualScriptInstance();
~VisualScriptInstance();
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 98325bcdf1..6ce7c301c4 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -1853,7 +1853,7 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) {
}
member_name = ti->get_text(0);
}
- if (ED_IS_SHORTCUT("visual_script_editor/delete_selected", p_event)) {
+ if (ED_IS_SHORTCUT("ui_graph_delete", p_event)) {
_member_option(MEMBER_REMOVE);
}
if (ED_IS_SHORTCUT("visual_script_editor/edit_member", p_event)) {
@@ -4121,7 +4121,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
@@ -4131,7 +4131,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
@@ -4141,7 +4141,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
member_name = ti->get_text(0);
member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT);
member_popup->add_separator();
- member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("visual_script_editor/delete_selected"), MEMBER_REMOVE);
+ member_popup->add_icon_shortcut(del_icon, ED_GET_SHORTCUT("ui_graph_delete"), MEMBER_REMOVE);
member_popup->popup();
return;
}
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 9310b86627..a0ba7b1962 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -737,20 +737,22 @@ public:
}
int to_id = 0;
- bool reliable = true;
+ //bool reliable = true;
if (rpc_mode >= VisualScriptFunctionCall::RPC_RELIABLE_TO_ID) {
to_id = *p_args[0];
p_args += 1;
p_argcount -= 1;
- if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) {
- reliable = false;
- }
- } else if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE) {
- reliable = false;
+ //if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE_TO_ID) {
+ //reliable = false;
+ //}
}
+ //else if (rpc_mode == VisualScriptFunctionCall::RPC_UNRELIABLE) {
+ //reliable = false;
+ //}
- node->rpcp(to_id, !reliable, function, p_args, p_argcount);
+ // TODO reliable?
+ node->rpcp(to_id, function, p_args, p_argcount);
return true;
}
diff --git a/platform/javascript/js/libs/library_godot_fetch.js b/platform/javascript/js/libs/library_godot_fetch.js
index de5ae2b1ae..04b90aea9c 100644
--- a/platform/javascript/js/libs/library_godot_fetch.js
+++ b/platform/javascript/js/libs/library_godot_fetch.js
@@ -29,7 +29,7 @@
/*************************************************************************/
const GodotFetch = {
- $GodotFetch__deps: ['$GodotRuntime'],
+ $GodotFetch__deps: ['$IDHandler', '$GodotRuntime'],
$GodotFetch: {
onread: function (id, result) {
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 8f6e1c4695..4b72043a46 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1203,8 +1203,16 @@ real_t CharacterBody2D::get_floor_max_angle() const {
return floor_max_angle;
}
-void CharacterBody2D::set_floor_max_angle(real_t p_floor_max_angle) {
- floor_max_angle = p_floor_max_angle;
+void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody2D::get_floor_max_angle_degrees() const {
+ return Math::rad2deg(floor_max_angle);
+}
+
+void CharacterBody2D::set_floor_max_angle_degrees(real_t p_degrees) {
+ floor_max_angle = Math::deg2rad(p_degrees);
}
const Vector2 &CharacterBody2D::get_snap() const {
@@ -1262,7 +1270,9 @@ void CharacterBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle", "floor_max_angle"), &CharacterBody2D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody2D::get_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody2D::set_floor_max_angle_degrees);
ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap);
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap);
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
@@ -1283,7 +1293,8 @@ void CharacterBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle"), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 5a44d31cc2..cd39a1996c 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -301,7 +301,10 @@ private:
void set_max_slides(int p_max_slides);
real_t get_floor_max_angle() const;
- void set_floor_max_angle(real_t p_floor_max_angle);
+ void set_floor_max_angle(real_t p_radians);
+
+ real_t get_floor_max_angle_degrees() const;
+ void set_floor_max_angle_degrees(real_t p_degrees);
const Vector2 &get_snap() const;
void set_snap(const Vector2 &p_snap);
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index 5c7d65e3e0..1019f85c8a 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -36,10 +36,41 @@
const real_t DEFAULT_GIZMO_EXTENTS = 10.0;
void Position2D::_draw_cross() {
- real_t extents = get_gizmo_extents();
- // Colors taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`)
- draw_line(Point2(-extents, 0), Point2(+extents, 0), Color(0.96, 0.20, 0.32));
- draw_line(Point2(0, -extents), Point2(0, +extents), Color(0.53, 0.84, 0.01));
+ const real_t extents = get_gizmo_extents();
+
+ // Add more points to create a "hard stop" in the color gradient.
+ PackedVector2Array points_x;
+ points_x.push_back(Point2(+extents, 0));
+ points_x.push_back(Point2());
+ points_x.push_back(Point2());
+ points_x.push_back(Point2(-extents, 0));
+
+ PackedVector2Array points_y;
+ points_y.push_back(Point2(0, +extents));
+ points_y.push_back(Point2());
+ points_y.push_back(Point2());
+ points_y.push_back(Point2(0, -extents));
+
+ // Use the axis color which is brighter for the positive axis.
+ // Use a darkened axis color for the negative axis.
+ // This makes it possible to see in which direction the Position3D node is rotated
+ // (which can be important depending on how it's used).
+ // Axis colors are taken from `axis_x_color` and `axis_y_color` (defined in `editor/editor_themes.cpp`).
+ PackedColorArray colors_x;
+ const Color color_x = Color(0.96, 0.20, 0.32);
+ colors_x.push_back(color_x);
+ colors_x.push_back(color_x);
+ colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5));
+ colors_x.push_back(color_x.lerp(Color(0, 0, 0), 0.5));
+ draw_multiline_colors(points_x, colors_x);
+
+ PackedColorArray colors_y;
+ const Color color_y = Color(0.53, 0.84, 0.01);
+ colors_y.push_back(color_y);
+ colors_y.push_back(color_y);
+ colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5));
+ colors_y.push_back(color_y.lerp(Color(0, 0, 0), 0.5));
+ draw_multiline_colors(points_y, colors_y);
}
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index c5ad3dde39..8f1f5fadbc 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -787,7 +787,7 @@ void Skeleton2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_modification_stack", "modification_stack"), &Skeleton2D::set_modification_stack);
ClassDB::bind_method(D_METHOD("get_modification_stack"), &Skeleton2D::get_modification_stack);
- ClassDB::bind_method(D_METHOD("execute_modifications", "execution_mode", "execution_mode"), &Skeleton2D::execute_modifications);
+ ClassDB::bind_method(D_METHOD("execute_modifications", "delta", "execution_mode"), &Skeleton2D::execute_modifications);
ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "override_pose", "strength", "persistent"), &Skeleton2D::set_bone_local_pose_override);
ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton2D::get_bone_local_pose_override);
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 3496ed1a56..25c7c3d798 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1204,8 +1204,16 @@ real_t CharacterBody3D::get_floor_max_angle() const {
return floor_max_angle;
}
-void CharacterBody3D::set_floor_max_angle(real_t p_floor_max_angle) {
- floor_max_angle = p_floor_max_angle;
+void CharacterBody3D::set_floor_max_angle(real_t p_radians) {
+ floor_max_angle = p_radians;
+}
+
+real_t CharacterBody3D::get_floor_max_angle_degrees() const {
+ return Math::rad2deg(floor_max_angle);
+}
+
+void CharacterBody3D::set_floor_max_angle_degrees(real_t p_degrees) {
+ floor_max_angle = Math::deg2rad(p_degrees);
}
const Vector3 &CharacterBody3D::get_snap() const {
@@ -1251,7 +1259,9 @@ void CharacterBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody3D::get_max_slides);
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody3D::set_max_slides);
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody3D::get_floor_max_angle);
- ClassDB::bind_method(D_METHOD("set_floor_max_angle", "floor_max_angle"), &CharacterBody3D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody3D::set_floor_max_angle);
+ ClassDB::bind_method(D_METHOD("get_floor_max_angle_degrees"), &CharacterBody3D::get_floor_max_angle_degrees);
+ ClassDB::bind_method(D_METHOD("set_floor_max_angle_degrees", "degrees"), &CharacterBody3D::set_floor_max_angle_degrees);
ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody3D::get_snap);
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody3D::set_snap);
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody3D::get_up_direction);
@@ -1270,7 +1280,8 @@ void CharacterBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle"), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle_degrees", PROPERTY_HINT_RANGE, "0,180,0.1", PROPERTY_USAGE_EDITOR), "set_floor_max_angle_degrees", "get_floor_max_angle_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "snap"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index d5e474c5d5..a25cb06bc3 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -305,7 +305,10 @@ private:
void set_max_slides(int p_max_slides);
real_t get_floor_max_angle() const;
- void set_floor_max_angle(real_t p_floor_max_angle);
+ void set_floor_max_angle(real_t p_radians);
+
+ real_t get_floor_max_angle_degrees() const;
+ void set_floor_max_angle_degrees(real_t p_degrees);
const Vector3 &get_snap() const;
void set_snap(const Vector3 &p_snap);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index ac067aa001..4e18a15b41 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -98,17 +98,14 @@ void BaseButton::_notification(int p_what) {
}
if (p_what == NOTIFICATION_FOCUS_ENTER) {
- status.hovering = true;
update();
}
if (p_what == NOTIFICATION_FOCUS_EXIT) {
if (status.press_attempt) {
status.press_attempt = false;
- status.hovering = false;
update();
} else if (status.hovering) {
- status.hovering = false;
update();
}
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index c7c782b992..c39b8005e4 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -491,36 +491,24 @@ bool Node::is_network_master() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode) {
- uint16_t mid = get_node_rpc_method_id(p_method);
- if (mid == UINT16_MAX) {
- // It's new
- NetData nd;
- nd.name = p_method;
- nd.mode = p_mode;
- data.rpc_methods.push_back(nd);
- return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
- } else {
- int c_mid = (~(1 << 15)) & mid;
- data.rpc_methods.write[c_mid].mode = p_mode;
- return mid;
- }
-}
-
-uint16_t Node::rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode) {
- uint16_t pid = get_node_rset_property_id(p_property);
- if (pid == UINT16_MAX) {
- // It's new
- NetData nd;
- nd.name = p_property;
- nd.mode = p_mode;
- data.rpc_properties.push_back(nd);
- return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15);
- } else {
- int c_pid = (~(1 << 15)) & pid;
- data.rpc_properties.write[c_pid].mode = p_mode;
- return pid;
+uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
+ for (int i = 0; i < data.rpc_methods.size(); i++) {
+ if (data.rpc_methods[i].name == p_method) {
+ MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i];
+ nd.rpc_mode = p_rpc_mode;
+ nd.transfer_mode = p_transfer_mode;
+ nd.channel = p_channel;
+ return i | (1 << 15);
+ }
}
+ // New method
+ MultiplayerAPI::RPCConfig nd;
+ nd.name = p_method;
+ nd.rpc_mode = p_rpc_mode;
+ nd.transfer_mode = p_transfer_mode;
+ nd.channel = p_channel;
+ data.rpc_methods.push_back(nd);
+ return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15);
}
/***** RPC FUNCTIONS ********/
@@ -536,7 +524,7 @@ void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) {
argc++;
}
- rpcp(0, false, p_method, argptr, argc);
+ rpcp(0, p_method, argptr, argc);
}
void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
@@ -550,35 +538,7 @@ void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE
argc++;
}
- rpcp(p_peer_id, false, p_method, argptr, argc);
-}
-
-void Node::rpc_unreliable(const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(0, true, p_method, argptr, argc);
-}
-
-void Node::rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(p_peer_id, true, p_method, argptr, argc);
+ rpcp(p_peer_id, p_method, argptr, argc);
}
Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -597,7 +557,7 @@ Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallEr
StringName method = *p_args[0];
- rpcp(0, false, method, &p_args[1], p_argcount - 1);
+ rpcp(0, method, &p_args[1], p_argcount - 1);
r_error.error = Callable::CallError::CALL_OK;
return Variant();
@@ -627,92 +587,17 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal
int peer_id = *p_args[0];
StringName method = *p_args[1];
- rpcp(peer_id, false, method, &p_args[2], p_argcount - 2);
-
- r_error.error = Callable::CallError::CALL_OK;
- return Variant();
-}
-
-Variant Node::_rpc_unreliable_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 1) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 1;
- return Variant();
- }
-
- if (p_args[0]->get_type() != Variant::STRING_NAME) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING_NAME;
- return Variant();
- }
-
- StringName method = *p_args[0];
-
- rpcp(0, true, method, &p_args[1], p_argcount - 1);
-
- r_error.error = Callable::CallError::CALL_OK;
- return Variant();
-}
-
-Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (p_argcount < 2) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = 2;
- return Variant();
- }
-
- if (p_args[0]->get_type() != Variant::INT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::INT;
- return Variant();
- }
-
- if (p_args[1]->get_type() != Variant::STRING_NAME) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 1;
- r_error.expected = Variant::STRING_NAME;
- return Variant();
- }
-
- int peer_id = *p_args[0];
- StringName method = *p_args[1];
-
- rpcp(peer_id, true, method, &p_args[2], p_argcount - 2);
+ rpcp(peer_id, method, &p_args[2], p_argcount - 2);
r_error.error = Callable::CallError::CALL_OK;
return Variant();
}
-void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) {
+void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rpcp(this, p_peer_id, p_unreliable, p_method, p_arg, p_argcount);
+ get_multiplayer()->rpcp(this, p_peer_id, true, p_method, p_arg, p_argcount);
}
-void Node::rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) {
- ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rsetp(this, p_peer_id, p_unreliable, p_property, p_value);
-}
-
-/******** RSET *********/
-void Node::rset(const StringName &p_property, const Variant &p_value) {
- rsetp(0, false, p_property, p_value);
-}
-
-void Node::rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value) {
- rsetp(p_peer_id, false, p_property, p_value);
-}
-
-void Node::rset_unreliable(const StringName &p_property, const Variant &p_value) {
- rsetp(0, true, p_property, p_value);
-}
-
-void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value) {
- rsetp(p_peer_id, true, p_property, p_value);
-}
-
-//////////// end of rpc
Ref<MultiplayerAPI> Node::get_multiplayer() const {
if (multiplayer.is_valid()) {
return multiplayer;
@@ -731,99 +616,11 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
multiplayer = p_multiplayer;
}
-uint16_t Node::get_node_rpc_method_id(const StringName &p_method) const {
- for (int i = 0; i < data.rpc_methods.size(); i++) {
- if (data.rpc_methods[i].name == p_method) {
- // Returns `i` with the high bit set to 1 so we know that this id comes
- // from the node and not the script.
- return i | (1 << 15);
- }
- }
- return UINT16_MAX;
-}
-
-StringName Node::get_node_rpc_method(const uint16_t p_rpc_method_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rpc_method_id) > 0) {
- int mid = (~(1 << 15)) & p_rpc_method_id;
- if (mid < data.rpc_methods.size()) {
- return data.rpc_methods[mid].name;
- }
- }
- return StringName();
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rpc_method_id) > 0) {
- int mid = (~(1 << 15)) & p_rpc_method_id;
- if (mid < data.rpc_methods.size()) {
- return data.rpc_methods[mid].mode;
- }
- }
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rpc_mode(const StringName &p_method) const {
- return get_node_rpc_mode_by_id(get_node_rpc_method_id(p_method));
+Vector<MultiplayerAPI::RPCConfig> Node::get_node_rpc_methods() const {
+ return data.rpc_methods;
}
-uint16_t Node::get_node_rset_property_id(const StringName &p_property) const {
- for (int i = 0; i < data.rpc_properties.size(); i++) {
- if (data.rpc_properties[i].name == p_property) {
- // Returns `i` with the high bit set to 1 so we know that this id comes
- // from the node and not the script.
- return i | (1 << 15);
- }
- }
- return UINT16_MAX;
-}
-
-StringName Node::get_node_rset_property(const uint16_t p_rset_property_id) const {
- // Make sure this is a node generated ID.
- if (((1 << 15) & p_rset_property_id) > 0) {
- int mid = (~(1 << 15)) & p_rset_property_id;
- if (mid < data.rpc_properties.size()) {
- return data.rpc_properties[mid].name;
- }
- }
- return StringName();
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rset_mode_by_id(const uint16_t p_rset_property_id) const {
- if (((1 << 15) & p_rset_property_id) > 0) {
- int mid = (~(1 << 15)) & p_rset_property_id;
- if (mid < data.rpc_properties.size()) {
- return data.rpc_properties[mid].mode;
- }
- }
- return MultiplayerAPI::RPC_MODE_DISABLED;
-}
-
-MultiplayerAPI::RPCMode Node::get_node_rset_mode(const StringName &p_property) const {
- return get_node_rset_mode_by_id(get_node_rset_property_id(p_property));
-}
-
-String Node::get_rpc_md5() const {
- String rpc_list;
- for (int i = 0; i < data.rpc_methods.size(); i += 1) {
- rpc_list += String(data.rpc_methods[i].name);
- }
- for (int i = 0; i < data.rpc_properties.size(); i += 1) {
- rpc_list += String(data.rpc_properties[i].name);
- }
- if (get_script_instance()) {
- Vector<ScriptNetData> rpc = get_script_instance()->get_rpc_methods();
- for (int i = 0; i < rpc.size(); i += 1) {
- rpc_list += String(rpc[i].name);
- }
- rpc = get_script_instance()->get_rset_properties();
- for (int i = 0; i < rpc.size(); i += 1) {
- rpc_list += String(rpc[i].name);
- }
- }
- return rpc_list.md5_text();
-}
+//////////// end of rpc
bool Node::can_process_notification(int p_what) const {
switch (p_what) {
@@ -2776,8 +2573,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
- ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
@@ -2794,22 +2590,13 @@ void Node::_bind_methods() {
mi.name = "rpc";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc", &Node::_rpc_bind, mi);
- mi.name = "rpc_unreliable";
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable", &Node::_rpc_unreliable_bind, mi);
mi.arguments.push_front(PropertyInfo(Variant::INT, "peer_id"));
mi.name = "rpc_id";
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_id", &Node::_rpc_id_bind, mi);
- mi.name = "rpc_unreliable_id";
- ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable_id", &Node::_rpc_unreliable_id_bind, mi);
}
- ClassDB::bind_method(D_METHOD("rset", "property", "value"), &Node::rset);
- ClassDB::bind_method(D_METHOD("rset_id", "peer_id", "property", "value"), &Node::rset_id);
- ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable);
- ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id);
-
ClassDB::bind_method(D_METHOD("update_configuration_warnings"), &Node::update_configuration_warnings);
BIND_CONSTANT(NOTIFICATION_ENTER_TREE);
diff --git a/scene/main/node.h b/scene/main/node.h
index 04897cf2e8..e7b36f351b 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -80,11 +80,6 @@ private:
SceneTree::Group *group = nullptr;
};
- struct NetData {
- StringName name;
- MultiplayerAPI::RPCMode mode = MultiplayerAPI::RPCMode::RPC_MODE_DISABLED;
- };
-
struct Data {
String filename;
Ref<SceneState> instance_state;
@@ -116,8 +111,7 @@ private:
Node *process_owner = nullptr;
int network_master = 1; // Server by default.
- Vector<NetData> rpc_methods;
- Vector<NetData> rpc_properties;
+ Vector<MultiplayerAPI::RPCConfig> rpc_methods;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
@@ -179,9 +173,7 @@ private:
Array _get_groups() const;
Variant _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant _rpc_unreliable_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant _rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
friend class SceneTree;
@@ -429,42 +421,17 @@ public:
int get_network_master() const;
bool is_network_master() const;
- uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode); // config a local method for RPC
- uint16_t rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode); // config a local property for RPC
+ uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
+ Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
- void rpc(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_unreliable(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
- void rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode
-
- void rset(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_unreliable(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
- void rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode
-
- void rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
- void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value);
+ void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
+ void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel
+ void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const;
Ref<MultiplayerAPI> get_custom_multiplayer() const;
void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
- /// Returns the rpc method ID, otherwise UINT32_MAX
- uint16_t get_node_rpc_method_id(const StringName &p_method) const;
- StringName get_node_rpc_method(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rpc_mode(const StringName &p_method) const;
-
- /// Returns the rpc property ID, otherwise UINT32_MAX
- uint16_t get_node_rset_property_id(const StringName &p_property) const;
- StringName get_node_rset_property(const uint16_t p_rset_property_id) const;
- MultiplayerAPI::RPCMode get_node_rset_mode_by_id(const uint16_t p_rpc_method_id) const;
- MultiplayerAPI::RPCMode get_node_rset_mode(const StringName &p_property) const;
-
- /// Can be used to check if the rpc methods and the rset properties are the
- /// same across the peers.
- String get_rpc_md5() const;
-
Node();
~Node();
};
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index c2f33accee..2c5634e6ef 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -505,9 +505,6 @@ void BaseMaterial3D::_update_shader() {
case DIFFUSE_LAMBERT_WRAP:
code += ",diffuse_lambert_wrap";
break;
- case DIFFUSE_OREN_NAYAR:
- code += ",diffuse_oren_nayar";
- break;
case DIFFUSE_TOON:
code += ",diffuse_toon";
break;
@@ -2400,7 +2397,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Shading", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Toon"), "set_diffuse_mode", "get_diffuse_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT);
@@ -2654,7 +2651,6 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP);
- BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR);
BIND_ENUM_CONSTANT(DIFFUSE_TOON);
BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index ad1b7b3e33..dc3ecdb5de 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -243,7 +243,6 @@ public:
DIFFUSE_BURLEY,
DIFFUSE_LAMBERT,
DIFFUSE_LAMBERT_WRAP,
- DIFFUSE_OREN_NAYAR,
DIFFUSE_TOON,
DIFFUSE_MAX
};
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index ff6d179f5b..35430e4a46 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -164,8 +164,8 @@ public:
Vector2 normal;
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
Variant metadata;
};
@@ -174,8 +174,8 @@ public:
struct ShapeResult {
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
Variant metadata;
};
@@ -193,7 +193,7 @@ public:
Vector2 normal;
RID rid;
ObjectID collider_id;
- int shape;
+ int shape = 0;
Vector2 linear_velocity; //velocity at contact point
Variant metadata;
};
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 4e76f7ce7e..ec4914641a 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -157,8 +157,8 @@ public:
struct ShapeResult {
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
};
virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
@@ -168,8 +168,8 @@ public:
Vector3 normal;
RID rid;
ObjectID collider_id;
- Object *collider;
- int shape;
+ Object *collider = nullptr;
+ int shape = 0;
};
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
@@ -181,7 +181,7 @@ public:
Vector3 normal;
RID rid;
ObjectID collider_id;
- int shape;
+ int shape = 0;
Vector3 linear_velocity; //velocity at contact point
};
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 6dbac0f7e1..dcfdf14784 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -721,7 +721,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 37508d70af..0d9dfbc51b 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -737,7 +737,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 7deedb80c3..b347197289 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -1504,7 +1504,6 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
}
- actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 32a86cb166..709ea45b88 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -144,12 +144,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
float metallic = unpackUnorm4x8(orms).z;
if (metallic < 1.0) {
float roughness = unpackUnorm4x8(orms).y;
-
-#if defined(DIFFUSE_OREN_NAYAR)
- vec3 diffuse_brdf_NL;
-#else
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
-#endif
#if defined(DIFFUSE_LAMBERT_WRAP)
// energy conserving lambert wrap shader
@@ -243,7 +238,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
+#ifdef USE_SOFT_SHADOWS
float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
+#else
+ float cRdotV = clamp(dot(R, V), 0.0, 1.0);
+#endif
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index a1e892498b..35f1b05796 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -204,7 +204,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
diff --git a/tests/test_object.h b/tests/test_object.h
index 142d76553d..a12fad51e2 100644
--- a/tests/test_object.h
+++ b/tests/test_object.h
@@ -93,35 +93,8 @@ public:
Ref<Script> get_script() const override {
return Ref<Script>();
}
- Vector<ScriptNetData> get_rpc_methods() const override {
- return Vector<ScriptNetData>();
- }
- uint16_t get_rpc_method_id(const StringName &p_method) const override {
- return 0;
- }
- StringName get_rpc_method(uint16_t p_id) const override {
- return StringName();
- }
- MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- Vector<ScriptNetData> get_rset_properties() const override {
- return Vector<ScriptNetData>();
- }
- uint16_t get_rset_property_id(const StringName &p_variable) const override {
- return 0;
- }
- StringName get_rset_property(uint16_t p_id) const override {
- return StringName();
- }
- MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
- }
- MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override {
- return MultiplayerAPI::RPC_MODE_PUPPET;
+ const Vector<MultiplayerAPI::RPCConfig> get_rpc_methods() const override {
+ return Vector<MultiplayerAPI::RPCConfig>();
}
ScriptLanguage *get_language() override {
return nullptr;