summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub1
-rw-r--r--core/config/engine.cpp5
-rw-r--r--core/core_bind.cpp65
-rw-r--r--core/core_bind.h25
-rw-r--r--core/debugger/debugger_marshalls.cpp183
-rw-r--r--core/debugger/debugger_marshalls.h87
-rw-r--r--core/debugger/engine_profiler.cpp82
-rw-r--r--core/debugger/engine_profiler.h65
-rw-r--r--core/debugger/remote_debugger.cpp354
-rw-r--r--core/debugger/remote_debugger.h14
-rw-r--r--core/io/marshalls.cpp2
-rw-r--r--core/math/vector2.h4
-rw-r--r--core/math/vector2i.h22
-rw-r--r--core/multiplayer/multiplayer_api.cpp1
-rw-r--r--core/object/class_db.cpp18
-rw-r--r--core/object/class_db.h4
-rw-r--r--core/object/object.h2
-rw-r--r--core/register_core_types.cpp3
-rw-r--r--core/string/string_name.h2
-rw-r--r--core/version.h3
20 files changed, 232 insertions, 710 deletions
diff --git a/core/SCsub b/core/SCsub
index c12dd4e60e..1379e9df9b 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -147,6 +147,7 @@ env.core_sources += thirdparty_obj
env.add_source_files(env.core_sources, "*.cpp")
env.add_source_files(env.core_sources, "script_encryption_key.gen.cpp")
+env.add_source_files(env.core_sources, "version_hash.gen.cpp")
# Certificates
env.Depends(
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index d9abf5e5e9..ff8a8d283f 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -35,7 +35,6 @@
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/version.h"
-#include "core/version_hash.gen.h"
void Engine::set_physics_ticks_per_second(int p_ips) {
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
@@ -95,8 +94,8 @@ Dictionary Engine::get_version_info() const {
dict["build"] = VERSION_BUILD;
dict["year"] = VERSION_YEAR;
- String hash = VERSION_HASH;
- dict["hash"] = hash.length() == 0 ? String("unknown") : hash;
+ String hash = String(VERSION_HASH);
+ dict["hash"] = hash.is_empty() ? String("unknown") : hash;
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
if ((int)dict["patch"] != 0) {
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 8d03f35617..195292f7e6 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -2376,21 +2376,18 @@ bool EngineDebugger::is_active() {
return ::EngineDebugger::is_active();
}
-void EngineDebugger::register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
- ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler already registered: " + p_name);
- profilers.insert(p_name, ProfilerCallable(p_toggle, p_add, p_tick));
- ProfilerCallable &p = profilers[p_name];
- ::EngineDebugger::Profiler profiler(
- &p,
- &EngineDebugger::call_toggle,
- &EngineDebugger::call_add,
- &EngineDebugger::call_tick);
- ::EngineDebugger::register_profiler(p_name, profiler);
+void EngineDebugger::register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler) {
+ ERR_FAIL_COND(p_profiler.is_null());
+ ERR_FAIL_COND_MSG(p_profiler->is_bound(), "Profiler already registered.");
+ ERR_FAIL_COND_MSG(profilers.has(p_name) || has_profiler(p_name), "Profiler name already in use: " + p_name);
+ Error err = p_profiler->bind(p_name);
+ ERR_FAIL_COND_MSG(err != OK, "Profiler failed to register with error: " + itos(err));
+ profilers.insert(p_name, p_profiler);
}
void EngineDebugger::unregister_profiler(const StringName &p_name) {
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
- ::EngineDebugger::unregister_profiler(p_name);
+ profilers[p_name]->unbind();
profilers.erase(p_name);
}
@@ -2435,45 +2432,6 @@ void EngineDebugger::send_message(const String &p_msg, const Array &p_data) {
::EngineDebugger::get_singleton()->send_message(p_msg, p_data);
}
-void EngineDebugger::call_toggle(void *p_user, bool p_enable, const Array &p_opts) {
- Callable &toggle = ((ProfilerCallable *)p_user)->callable_toggle;
- if (toggle.is_null()) {
- return;
- }
- Variant enable = p_enable, opts = p_opts;
- const Variant *args[2] = { &enable, &opts };
- Variant retval;
- Callable::CallError err;
- toggle.call(args, 2, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'toggle' to callable: " + Variant::get_callable_error_text(toggle, args, 2, err));
-}
-
-void EngineDebugger::call_add(void *p_user, const Array &p_data) {
- Callable &add = ((ProfilerCallable *)p_user)->callable_add;
- if (add.is_null()) {
- return;
- }
- Variant data = p_data;
- const Variant *args[1] = { &data };
- Variant retval;
- Callable::CallError err;
- add.call(args, 1, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'add' to callable: " + Variant::get_callable_error_text(add, args, 1, err));
-}
-
-void EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- Callable &tick = ((ProfilerCallable *)p_user)->callable_tick;
- if (tick.is_null()) {
- return;
- }
- Variant frame_time = p_frame_time, idle_time = p_idle_time, physics_time = p_physics_time, physics_frame_time = p_physics_frame_time;
- const Variant *args[4] = { &frame_time, &idle_time, &physics_time, &physics_frame_time };
- Variant retval;
- Callable::CallError err;
- tick.call(args, 4, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'tick' to callable: " + Variant::get_callable_error_text(tick, args, 4, err));
-}
-
Error EngineDebugger::call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
Callable &capture = *(Callable *)p_user;
if (capture.is_null()) {
@@ -2495,10 +2453,6 @@ EngineDebugger::~EngineDebugger() {
::EngineDebugger::unregister_message_capture(E.key);
}
captures.clear();
- for (const KeyValue<StringName, ProfilerCallable> &E : profilers) {
- ::EngineDebugger::unregister_profiler(E.key);
- }
- profilers.clear();
}
EngineDebugger *EngineDebugger::singleton = nullptr;
@@ -2506,8 +2460,9 @@ EngineDebugger *EngineDebugger::singleton = nullptr;
void EngineDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_active"), &EngineDebugger::is_active);
- ClassDB::bind_method(D_METHOD("register_profiler", "name", "toggle", "add", "tick"), &EngineDebugger::register_profiler);
+ ClassDB::bind_method(D_METHOD("register_profiler", "name", "profiler"), &EngineDebugger::register_profiler);
ClassDB::bind_method(D_METHOD("unregister_profiler", "name"), &EngineDebugger::unregister_profiler);
+
ClassDB::bind_method(D_METHOD("is_profiling", "name"), &EngineDebugger::is_profiling);
ClassDB::bind_method(D_METHOD("has_profiler", "name"), &EngineDebugger::has_profiler);
diff --git a/core/core_bind.h b/core/core_bind.h
index ac0e92a87a..21a1fc2077 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -31,6 +31,7 @@
#ifndef CORE_BIND_H
#define CORE_BIND_H
+#include "core/debugger/engine_profiler.h"
#include "core/io/compression.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@@ -673,25 +674,8 @@ public:
class EngineDebugger : public Object {
GDCLASS(EngineDebugger, Object);
- class ProfilerCallable {
- friend class EngineDebugger;
-
- Callable callable_toggle;
- Callable callable_add;
- Callable callable_tick;
-
- public:
- ProfilerCallable() {}
-
- ProfilerCallable(const Callable &p_toggle, const Callable &p_add, const Callable &p_tick) {
- callable_toggle = p_toggle;
- callable_add = p_add;
- callable_tick = p_tick;
- }
- };
-
Map<StringName, Callable> captures;
- Map<StringName, ProfilerCallable> profilers;
+ Map<StringName, Ref<EngineProfiler>> profilers;
protected:
static void _bind_methods();
@@ -702,7 +686,7 @@ public:
bool is_active();
- void register_profiler(const StringName &p_name, const Callable &p_toggle, const Callable &p_add, const Callable &p_tick);
+ void register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler);
void unregister_profiler(const StringName &p_name);
bool is_profiling(const StringName &p_name);
bool has_profiler(const StringName &p_name);
@@ -715,9 +699,6 @@ public:
void send_message(const String &p_msg, const Array &p_data);
- static void call_toggle(void *p_user, bool p_enable, const Array &p_opts);
- static void call_add(void *p_user, const Array &p_data);
- static void call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
static Error call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured);
EngineDebugger() { singleton = this; }
diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp
index 1a746d59a3..4c69290c2e 100644
--- a/core/debugger/debugger_marshalls.cpp
+++ b/core/debugger/debugger_marshalls.cpp
@@ -35,159 +35,6 @@
#define CHECK_SIZE(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() < (uint32_t)(expected), false, String("Malformed ") + what + " message from script debugger, message too short. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() > (uint32_t)expected, false, String("Malformed ") + what + " message from script debugger, message too long. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
-Array DebuggerMarshalls::ResourceUsage::serialize() {
- infos.sort();
-
- Array arr;
- arr.push_back(infos.size() * 4);
- for (const ResourceInfo &E : infos) {
- arr.push_back(E.path);
- arr.push_back(E.format);
- arr.push_back(E.type);
- arr.push_back(E.vram);
- }
- return arr;
-}
-
-bool DebuggerMarshalls::ResourceUsage::deserialize(const Array &p_arr) {
- CHECK_SIZE(p_arr, 1, "ResourceUsage");
- uint32_t size = p_arr[0];
- CHECK_SIZE(p_arr, size, "ResourceUsage");
- int idx = 1;
- for (uint32_t i = 0; i < size / 4; i++) {
- ResourceInfo info;
- info.path = p_arr[idx];
- info.format = p_arr[idx + 1];
- info.type = p_arr[idx + 2];
- info.vram = p_arr[idx + 3];
- infos.push_back(info);
- }
- CHECK_END(p_arr, idx, "ResourceUsage");
- return true;
-}
-
-Array DebuggerMarshalls::ScriptFunctionSignature::serialize() {
- Array arr;
- arr.push_back(name);
- arr.push_back(id);
- return arr;
-}
-
-bool DebuggerMarshalls::ScriptFunctionSignature::deserialize(const Array &p_arr) {
- CHECK_SIZE(p_arr, 2, "ScriptFunctionSignature");
- name = p_arr[0];
- id = p_arr[1];
- CHECK_END(p_arr, 2, "ScriptFunctionSignature");
- return true;
-}
-
-Array DebuggerMarshalls::NetworkProfilerFrame::serialize() {
- Array arr;
- arr.push_back(infos.size() * 6);
- for (int i = 0; i < infos.size(); ++i) {
- arr.push_back(uint64_t(infos[i].node));
- arr.push_back(infos[i].node_path);
- arr.push_back(infos[i].incoming_rpc);
- arr.push_back(infos[i].incoming_rset);
- arr.push_back(infos[i].outgoing_rpc);
- arr.push_back(infos[i].outgoing_rset);
- }
- return arr;
-}
-
-bool DebuggerMarshalls::NetworkProfilerFrame::deserialize(const Array &p_arr) {
- CHECK_SIZE(p_arr, 1, "NetworkProfilerFrame");
- uint32_t size = p_arr[0];
- CHECK_SIZE(p_arr, size, "NetworkProfilerFrame");
- infos.resize(size);
- int idx = 1;
- for (uint32_t i = 0; i < size / 6; ++i) {
- infos.write[i].node = uint64_t(p_arr[idx]);
- infos.write[i].node_path = p_arr[idx + 1];
- infos.write[i].incoming_rpc = p_arr[idx + 2];
- infos.write[i].incoming_rset = p_arr[idx + 3];
- infos.write[i].outgoing_rpc = p_arr[idx + 4];
- infos.write[i].outgoing_rset = p_arr[idx + 5];
- }
- CHECK_END(p_arr, idx, "NetworkProfilerFrame");
- return true;
-}
-
-Array DebuggerMarshalls::ServersProfilerFrame::serialize() {
- Array arr;
- arr.push_back(frame_number);
- arr.push_back(frame_time);
- arr.push_back(idle_time);
- arr.push_back(physics_time);
- arr.push_back(physics_frame_time);
- arr.push_back(script_time);
-
- arr.push_back(servers.size());
- for (int i = 0; i < servers.size(); i++) {
- ServerInfo &s = servers[i];
- arr.push_back(s.name);
- arr.push_back(s.functions.size() * 2);
- for (int j = 0; j < s.functions.size(); j++) {
- ServerFunctionInfo &f = s.functions[j];
- arr.push_back(f.name);
- arr.push_back(f.time);
- }
- }
-
- arr.push_back(script_functions.size() * 4);
- for (int i = 0; i < script_functions.size(); i++) {
- arr.push_back(script_functions[i].sig_id);
- arr.push_back(script_functions[i].call_count);
- arr.push_back(script_functions[i].self_time);
- arr.push_back(script_functions[i].total_time);
- }
- return arr;
-}
-
-bool DebuggerMarshalls::ServersProfilerFrame::deserialize(const Array &p_arr) {
- CHECK_SIZE(p_arr, 7, "ServersProfilerFrame");
- frame_number = p_arr[0];
- frame_time = p_arr[1];
- idle_time = p_arr[2];
- physics_time = p_arr[3];
- physics_frame_time = p_arr[4];
- script_time = p_arr[5];
- int servers_size = p_arr[6];
- int idx = 7;
- while (servers_size) {
- CHECK_SIZE(p_arr, idx + 2, "ServersProfilerFrame");
- servers_size--;
- ServerInfo si;
- si.name = p_arr[idx];
- int sub_data_size = p_arr[idx + 1];
- idx += 2;
- CHECK_SIZE(p_arr, idx + sub_data_size, "ServersProfilerFrame");
- for (int j = 0; j < sub_data_size / 2; j++) {
- ServerFunctionInfo sf;
- sf.name = p_arr[idx];
- sf.time = p_arr[idx + 1];
- idx += 2;
- si.functions.push_back(sf);
- }
- servers.push_back(si);
- }
- CHECK_SIZE(p_arr, idx + 1, "ServersProfilerFrame");
- int func_size = p_arr[idx];
- idx += 1;
- CHECK_SIZE(p_arr, idx + func_size, "ServersProfilerFrame");
- for (int i = 0; i < func_size / 4; i++) {
- ScriptFunctionInfo fi;
- fi.sig_id = p_arr[idx];
- fi.call_count = p_arr[idx + 1];
- fi.self_time = p_arr[idx + 2];
- fi.total_time = p_arr[idx + 3];
- script_functions.push_back(fi);
- idx += 4;
- }
- CHECK_END(p_arr, idx, "ServersProfilerFrame");
- return true;
-}
-
Array DebuggerMarshalls::ScriptStackDump::serialize() {
Array arr;
arr.push_back(frames.size() * 3);
@@ -298,33 +145,3 @@ bool DebuggerMarshalls::OutputError::deserialize(const Array &p_arr) {
CHECK_END(p_arr, idx, "OutputError");
return true;
}
-
-Array DebuggerMarshalls::VisualProfilerFrame::serialize() {
- Array arr;
- arr.push_back(frame_number);
- arr.push_back(areas.size() * 3);
- for (int i = 0; i < areas.size(); i++) {
- arr.push_back(areas[i].name);
- arr.push_back(areas[i].cpu_msec);
- arr.push_back(areas[i].gpu_msec);
- }
- return arr;
-}
-
-bool DebuggerMarshalls::VisualProfilerFrame::deserialize(const Array &p_arr) {
- CHECK_SIZE(p_arr, 2, "VisualProfilerFrame");
- frame_number = p_arr[0];
- int size = p_arr[1];
- CHECK_SIZE(p_arr, size, "VisualProfilerFrame");
- int idx = 2;
- areas.resize(size / 3);
- RS::FrameProfileArea *w = areas.ptrw();
- for (int i = 0; i < size / 3; i++) {
- w[i].name = p_arr[idx];
- w[i].cpu_msec = p_arr[idx + 1];
- w[i].gpu_msec = p_arr[idx + 2];
- idx += 3;
- }
- CHECK_END(p_arr, idx, "VisualProfilerFrame");
- return true;
-}
diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h
index fae766812a..378c3af8aa 100644
--- a/core/debugger/debugger_marshalls.h
+++ b/core/debugger/debugger_marshalls.h
@@ -32,86 +32,8 @@
#define DEBUGGER_MARSHARLLS_H
#include "core/object/script_language.h"
-#include "servers/rendering_server.h"
struct DebuggerMarshalls {
- // Memory usage
- struct ResourceInfo {
- String path;
- String format;
- String type;
- RID id;
- int vram = 0;
- bool operator<(const ResourceInfo &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; }
- };
-
- struct ResourceUsage {
- List<ResourceInfo> infos;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
- // Network profiler
- struct MultiplayerNodeInfo {
- ObjectID node;
- String node_path;
- int incoming_rpc = 0;
- int incoming_rset = 0;
- int outgoing_rpc = 0;
- int outgoing_rset = 0;
- };
-
- struct NetworkProfilerFrame {
- Vector<MultiplayerNodeInfo> infos;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
- // Script Profiler
- class ScriptFunctionSignature {
- public:
- StringName name;
- int id = -1;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
- struct ScriptFunctionInfo {
- StringName name;
- int sig_id = -1;
- int call_count = 0;
- double self_time = 0;
- double total_time = 0;
- };
-
- // Servers profiler
- struct ServerFunctionInfo {
- StringName name;
- double time = 0;
- };
-
- struct ServerInfo {
- StringName name;
- List<ServerFunctionInfo> functions;
- };
-
- struct ServersProfilerFrame {
- int frame_number = 0;
- double frame_time = 0;
- double idle_time = 0;
- double physics_time = 0;
- double physics_frame_time = 0;
- double script_time = 0;
- List<ServerInfo> servers;
- Vector<ScriptFunctionInfo> script_functions;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
struct ScriptStackVariable {
String name;
Variant value;
@@ -145,15 +67,6 @@ struct DebuggerMarshalls {
Array serialize();
bool deserialize(const Array &p_arr);
};
-
- // Visual Profiler
- struct VisualProfilerFrame {
- uint64_t frame_number = 0;
- Vector<RS::FrameProfileArea> areas;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
};
#endif // DEBUGGER_MARSHARLLS_H
diff --git a/core/debugger/engine_profiler.cpp b/core/debugger/engine_profiler.cpp
new file mode 100644
index 0000000000..c858b1febd
--- /dev/null
+++ b/core/debugger/engine_profiler.cpp
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* engine_profiler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "engine_profiler.h"
+
+#include "core/debugger/engine_debugger.h"
+
+void EngineProfiler::_bind_methods() {
+ GDVIRTUAL_BIND(_toggle, "enable", "options");
+ GDVIRTUAL_BIND(_add_frame, "data");
+ GDVIRTUAL_BIND(_tick, "frame_time", "idle_time", "physics_time", "physics_frame_time");
+}
+
+void EngineProfiler::toggle(bool p_enable, const Array &p_array) {
+ GDVIRTUAL_CALL(_toggle, p_enable, p_array);
+}
+
+void EngineProfiler::add(const Array &p_data) {
+ GDVIRTUAL_CALL(_add_frame, p_data);
+}
+
+void EngineProfiler::tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ GDVIRTUAL_CALL(_tick, p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+}
+
+Error EngineProfiler::bind(const String &p_name) {
+ ERR_FAIL_COND_V(is_bound(), ERR_ALREADY_IN_USE);
+ EngineDebugger::Profiler prof(
+ this,
+ [](void *p_user, bool p_enable, const Array &p_opts) {
+ ((EngineProfiler *)p_user)->toggle(p_enable, p_opts);
+ },
+ [](void *p_user, const Array &p_data) {
+ ((EngineProfiler *)p_user)->add(p_data);
+ },
+ [](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
+ ((EngineProfiler *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
+ });
+ registration = p_name;
+ EngineDebugger::register_profiler(p_name, prof);
+ return OK;
+}
+
+Error EngineProfiler::unbind() {
+ ERR_FAIL_COND_V(!is_bound(), ERR_UNCONFIGURED);
+ EngineDebugger::unregister_profiler(registration);
+ registration.clear();
+ return OK;
+}
+
+EngineProfiler::~EngineProfiler() {
+ if (is_bound()) {
+ unbind();
+ }
+}
diff --git a/core/debugger/engine_profiler.h b/core/debugger/engine_profiler.h
new file mode 100644
index 0000000000..ade280a7bb
--- /dev/null
+++ b/core/debugger/engine_profiler.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* engine_profiler.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef ENGINE_PROFILER_H
+#define ENGINE_PROFILER_H
+
+#include "core/object/ref_counted.h"
+
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+
+class EngineProfiler : public RefCounted {
+ GDCLASS(EngineProfiler, RefCounted);
+
+private:
+ String registration;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual void toggle(bool p_enable, const Array &p_opts);
+ virtual void add(const Array &p_data);
+ virtual void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
+
+ Error bind(const String &p_name);
+ Error unbind();
+ bool is_bound() const { return registration.length() > 0; }
+
+ GDVIRTUAL2(_toggle, bool, Array);
+ GDVIRTUAL1(_add_frame, Array);
+ GDVIRTUAL4(_tick, double, double, double, double);
+
+ EngineProfiler() {}
+ virtual ~EngineProfiler();
+};
+
+#endif // ENGINE_PROFILER_H
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 339aa9b61f..2fce23d003 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -33,32 +33,13 @@
#include "core/config/project_settings.h"
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
+#include "core/debugger/engine_profiler.h"
#include "core/debugger/script_debugger.h"
#include "core/input/input.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
-#include "scene/main/node.h"
-#include "servers/display_server.h"
-
-template <typename T>
-void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) {
- EngineDebugger::Profiler prof(
- p_prof,
- [](void *p_user, bool p_enable, const Array &p_opts) {
- ((T *)p_user)->toggle(p_enable, p_opts);
- },
- [](void *p_user, const Array &p_data) {
- ((T *)p_user)->add(p_data);
- },
- [](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- ((T *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
- });
- EngineDebugger::register_profiler(p_name, prof);
-}
-struct RemoteDebugger::NetworkProfiler {
-public:
- typedef DebuggerMarshalls::MultiplayerNodeInfo NodeInfo;
+class RemoteDebugger::MultiplayerProfiler : public EngineProfiler {
struct BandwidthFrame {
uint32_t timestamp;
int packet_size;
@@ -70,11 +51,6 @@ public:
Vector<BandwidthFrame> bandwidth_out;
uint64_t last_bandwidth_time = 0;
- Map<ObjectID, NodeInfo> multiplayer_node_data;
- uint64_t last_profile_time = 0;
-
- NetworkProfiler() {}
-
int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
int total_bandwidth = 0;
@@ -96,22 +72,8 @@ public:
return total_bandwidth;
}
- void init_node(const ObjectID p_node) {
- if (multiplayer_node_data.has(p_node)) {
- return;
- }
- multiplayer_node_data.insert(p_node, DebuggerMarshalls::MultiplayerNodeInfo());
- multiplayer_node_data[p_node].node = p_node;
- multiplayer_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
- multiplayer_node_data[p_node].incoming_rpc = 0;
- multiplayer_node_data[p_node].incoming_rset = 0;
- multiplayer_node_data[p_node].outgoing_rpc = 0;
- multiplayer_node_data[p_node].outgoing_rset = 0;
- }
-
+public:
void toggle(bool p_enable, const Array &p_opts) {
- multiplayer_node_data.clear();
-
if (!p_enable) {
bandwidth_in.clear();
bandwidth_out.clear();
@@ -130,37 +92,18 @@ public:
}
void add(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() < 1);
- const String type = p_data[0];
- if (type == "node") {
- ERR_FAIL_COND(p_data.size() < 3);
- const ObjectID id = p_data[1];
- const String what = p_data[2];
- init_node(id);
- NodeInfo &info = multiplayer_node_data[id];
- if (what == "rpc_in") {
- info.incoming_rpc++;
- } else if (what == "rpc_out") {
- info.outgoing_rpc++;
- } else if (what == "rset_in") {
- info.incoming_rset = 0;
- } else if (what == "rset_out") {
- info.outgoing_rset++;
- }
- } else if (type == "bandwidth") {
- ERR_FAIL_COND(p_data.size() < 4);
- const String inout = p_data[1];
- int time = p_data[2];
- int size = p_data[3];
- if (inout == "in") {
- bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
- bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
- bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
- } else if (inout == "out") {
- bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
- bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
- bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
- }
+ ERR_FAIL_COND(p_data.size() < 3);
+ const String inout = p_data[0];
+ int time = p_data[1];
+ int size = p_data[2];
+ if (inout == "in") {
+ bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
+ bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
+ bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
+ } else if (inout == "out") {
+ bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
+ bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
+ bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
}
}
@@ -174,208 +117,17 @@ public:
Array arr;
arr.push_back(incoming_bandwidth);
arr.push_back(outgoing_bandwidth);
- EngineDebugger::get_singleton()->send_message("network:bandwidth", arr);
- }
- if (pt - last_profile_time > 100) {
- last_profile_time = pt;
- DebuggerMarshalls::NetworkProfilerFrame frame;
- for (const KeyValue<ObjectID, NodeInfo> &E : multiplayer_node_data) {
- frame.infos.push_back(E.value);
- }
- multiplayer_node_data.clear();
- EngineDebugger::get_singleton()->send_message("network:profile_frame", frame.serialize());
- }
- }
-};
-
-struct RemoteDebugger::ScriptsProfiler {
- typedef DebuggerMarshalls::ScriptFunctionSignature FunctionSignature;
- typedef DebuggerMarshalls::ScriptFunctionInfo FunctionInfo;
- struct ProfileInfoSort {
- bool operator()(ScriptLanguage::ProfilingInfo *A, ScriptLanguage::ProfilingInfo *B) const {
- return A->total_time < B->total_time;
- }
- };
- Vector<ScriptLanguage::ProfilingInfo> info;
- Vector<ScriptLanguage::ProfilingInfo *> ptrs;
- Map<StringName, int> sig_map;
- int max_frame_functions = 16;
-
- void toggle(bool p_enable, const Array &p_opts) {
- if (p_enable) {
- sig_map.clear();
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->profiling_start();
- }
- if (p_opts.size() == 1 && p_opts[0].get_type() == Variant::INT) {
- max_frame_functions = MAX(0, int(p_opts[0]));
- }
- } else {
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->profiling_stop();
- }
+ EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
}
}
-
- void write_frame_data(Vector<FunctionInfo> &r_funcs, uint64_t &r_total, bool p_accumulated) {
- int ofs = 0;
- for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- if (p_accumulated) {
- ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&info.write[ofs], info.size() - ofs);
- } else {
- ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&info.write[ofs], info.size() - ofs);
- }
- }
-
- for (int i = 0; i < ofs; i++) {
- ptrs.write[i] = &info.write[i];
- }
-
- SortArray<ScriptLanguage::ProfilingInfo *, ProfileInfoSort> sa;
- sa.sort(ptrs.ptrw(), ofs);
-
- int to_send = MIN(ofs, max_frame_functions);
-
- // Check signatures first, and compute total time.
- r_total = 0;
- for (int i = 0; i < to_send; i++) {
- if (!sig_map.has(ptrs[i]->signature)) {
- int idx = sig_map.size();
- FunctionSignature sig;
- sig.name = ptrs[i]->signature;
- sig.id = idx;
- EngineDebugger::get_singleton()->send_message("servers:function_signature", sig.serialize());
- sig_map[ptrs[i]->signature] = idx;
- }
- r_total += ptrs[i]->self_time;
- }
-
- // Send frame, script time, functions information then
- r_funcs.resize(to_send);
-
- FunctionInfo *w = r_funcs.ptrw();
- for (int i = 0; i < to_send; i++) {
- if (sig_map.has(ptrs[i]->signature)) {
- w[i].sig_id = sig_map[ptrs[i]->signature];
- }
- w[i].call_count = ptrs[i]->call_count;
- w[i].total_time = ptrs[i]->total_time / 1000000.0;
- w[i].self_time = ptrs[i]->self_time / 1000000.0;
- }
- }
-
- ScriptsProfiler() {
- info.resize(GLOBAL_GET("debug/settings/profiler/max_functions"));
- ptrs.resize(info.size());
- }
};
-struct RemoteDebugger::ServersProfiler {
- bool skip_profile_frame = false;
- typedef DebuggerMarshalls::ServerInfo ServerInfo;
- typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo;
-
- Map<StringName, ServerInfo> server_data;
- ScriptsProfiler scripts_profiler;
-
- double frame_time = 0;
- double idle_time = 0;
- double physics_time = 0;
- double physics_frame_time = 0;
-
- void toggle(bool p_enable, const Array &p_opts) {
- skip_profile_frame = false;
- if (p_enable) {
- server_data.clear(); // Clear old profiling data.
- } else {
- _send_frame_data(true); // Send final frame.
- }
- scripts_profiler.toggle(p_enable, p_opts);
- }
-
- void add(const Array &p_data) {
- String name = p_data[0];
- if (!server_data.has(name)) {
- ServerInfo info;
- info.name = name;
- server_data[name] = info;
- }
- ServerInfo &srv = server_data[name];
-
- ServerFunctionInfo fi;
- fi.name = p_data[1];
- fi.time = p_data[2];
- srv.functions.push_back(fi);
- }
-
- void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- frame_time = p_frame_time;
- idle_time = p_idle_time;
- physics_time = p_physics_time;
- physics_frame_time = p_physics_frame_time;
- _send_frame_data(false);
- }
-
- void _send_frame_data(bool p_final) {
- DebuggerMarshalls::ServersProfilerFrame frame;
- frame.frame_number = Engine::get_singleton()->get_process_frames();
- frame.frame_time = frame_time;
- frame.idle_time = idle_time;
- frame.physics_time = physics_time;
- frame.physics_frame_time = physics_frame_time;
- Map<StringName, ServerInfo>::Element *E = server_data.front();
- while (E) {
- if (!p_final) {
- frame.servers.push_back(E->get());
- }
- E->get().functions.clear();
- E = E->next();
- }
- uint64_t time = 0;
- scripts_profiler.write_frame_data(frame.script_functions, time, p_final);
- frame.script_time = USEC_TO_SEC(time);
- if (skip_profile_frame) {
- skip_profile_frame = false;
- return;
- }
- if (p_final) {
- EngineDebugger::get_singleton()->send_message("servers:profile_total", frame.serialize());
- } else {
- EngineDebugger::get_singleton()->send_message("servers:profile_frame", frame.serialize());
- }
- }
-};
-
-struct RemoteDebugger::VisualProfiler {
- typedef DebuggerMarshalls::ServerInfo ServerInfo;
- typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo;
-
- Map<StringName, ServerInfo> server_data;
-
- void toggle(bool p_enable, const Array &p_opts) {
- RS::get_singleton()->set_frame_profiling_enabled(p_enable);
- }
-
- void add(const Array &p_data) {}
-
- void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
- Vector<RS::FrameProfileArea> profile_areas = RS::get_singleton()->get_frame_profile();
- DebuggerMarshalls::VisualProfilerFrame frame;
- if (!profile_areas.size()) {
- return;
- }
-
- frame.frame_number = RS::get_singleton()->get_frame_profile_frame();
- frame.areas.append_array(profile_areas);
- EngineDebugger::get_singleton()->send_message("visual:profile_frame", frame.serialize());
- }
-};
-
-struct RemoteDebugger::PerformanceProfiler {
+class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
Object *performance = nullptr;
int last_perf_time = 0;
uint64_t last_monitor_modification_time = 0;
+public:
void toggle(bool p_enable, const Array &p_opts) {}
void add(const Array &p_data) {}
void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
@@ -421,29 +173,6 @@ struct RemoteDebugger::PerformanceProfiler {
}
};
-void RemoteDebugger::_send_resource_usage() {
- DebuggerMarshalls::ResourceUsage usage;
-
- List<RS::TextureInfo> tinfo;
- RS::get_singleton()->texture_debug_usage(&tinfo);
-
- for (const RS::TextureInfo &E : tinfo) {
- DebuggerMarshalls::ResourceInfo info;
- info.path = E.path;
- info.vram = E.bytes;
- info.id = E.texture;
- info.type = "Texture";
- if (E.depth == 0) {
- info.format = itos(E.width) + "x" + itos(E.height) + " " + Image::get_format_name(E.format);
- } else {
- info.format = itos(E.width) + "x" + itos(E.height) + "x" + itos(E.depth) + " " + Image::get_format_name(E.format);
- }
- usage.infos.push_back(info);
- }
-
- EngineDebugger::get_singleton()->send_message("memory:usage", usage.serialize());
-}
-
Error RemoteDebugger::_put_msg(String p_message, Array p_data) {
Array msg;
msg.push_back(p_message);
@@ -710,18 +439,12 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
msg.push_back(script_lang->debug_get_stack_level_count() > 0);
send_message("debug_enter", msg);
- servers_profiler->skip_profile_frame = true; // Avoid frame time spike in debug.
-
Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode();
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
}
- uint64_t loop_begin_usec = 0;
- uint64_t loop_time_sec = 0;
while (is_peer_connected()) {
- loop_begin_usec = OS::get_singleton()->get_ticks_usec();
-
flush_output();
peer->poll();
@@ -748,7 +471,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (command == "continue") {
script_debugger->set_depth(-1);
script_debugger->set_lines_left(-1);
- DisplayServer::get_singleton()->window_move_to_foreground();
break;
} else if (command == "break") {
@@ -824,13 +546,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
OS::get_singleton()->delay_usec(10000);
OS::get_singleton()->process_and_drop_events();
}
-
- // This is for the camera override to stay live even when the game is paused from the editor
- loop_time_sec = (OS::get_singleton()->get_ticks_usec() - loop_begin_usec) / 1000000.0f;
- RenderingServer::get_singleton()->sync();
- if (RenderingServer::get_singleton()->has_changed()) {
- RenderingServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale());
- }
}
send_message("debug_exit", Array());
@@ -897,8 +612,6 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo
} else if (p_cmd == "set_skip_breakpoints") {
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
script_debugger->set_skip_breakpoints(p_data[0]);
- } else if (p_cmd == "memory") {
- _send_resource_usage();
} else if (p_cmd == "break") {
script_debugger->debug(script_debugger->get_break_language());
} else {
@@ -928,23 +641,15 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
max_errors_per_second = GLOBAL_GET("network/limits/debugger/max_errors_per_second");
max_warnings_per_second = GLOBAL_GET("network/limits/debugger/max_warnings_per_second");
- // Network Profiler
- network_profiler = memnew(NetworkProfiler);
- _bind_profiler("network", network_profiler);
-
- // Servers Profiler (audio/physics/...)
- servers_profiler = memnew(ServersProfiler);
- _bind_profiler("servers", servers_profiler);
-
- // Visual Profiler (cpu/gpu times)
- visual_profiler = memnew(VisualProfiler);
- _bind_profiler("visual", visual_profiler);
+ // Multiplayer Profiler
+ multiplayer_profiler.instantiate();
+ multiplayer_profiler->bind("multiplayer");
// Performance Profiler
Object *perf = Engine::get_singleton()->get_singleton_object("Performance");
if (perf) {
- performance_profiler = memnew(PerformanceProfiler(perf));
- _bind_profiler("performance", performance_profiler);
+ performance_profiler = Ref<PerformanceProfiler>(memnew(PerformanceProfiler(perf)));
+ performance_profiler->bind("performance");
profiler_enable("performance", true);
}
@@ -973,17 +678,4 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
RemoteDebugger::~RemoteDebugger() {
remove_print_handler(&phl);
remove_error_handler(&eh);
-
- EngineDebugger::get_singleton()->unregister_profiler("servers");
- EngineDebugger::get_singleton()->unregister_profiler("network");
- EngineDebugger::get_singleton()->unregister_profiler("visual");
- if (EngineDebugger::has_profiler("performance")) {
- EngineDebugger::get_singleton()->unregister_profiler("performance");
- }
- memdelete(servers_profiler);
- memdelete(network_profiler);
- memdelete(visual_profiler);
- if (performance_profiler) {
- memdelete(performance_profiler);
- }
}
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index bd64955c89..aada92da60 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -49,16 +49,11 @@ public:
private:
typedef DebuggerMarshalls::OutputError ErrorMessage;
- struct NetworkProfiler;
- struct ServersProfiler;
- struct ScriptsProfiler;
- struct VisualProfiler;
- struct PerformanceProfiler;
+ class MultiplayerProfiler;
+ class PerformanceProfiler;
- NetworkProfiler *network_profiler = nullptr;
- ServersProfiler *servers_profiler = nullptr;
- VisualProfiler *visual_profiler = nullptr;
- PerformanceProfiler *performance_profiler = nullptr;
+ Ref<MultiplayerProfiler> multiplayer_profiler;
+ Ref<PerformanceProfiler> performance_profiler;
Ref<RemoteDebuggerPeer> peer;
@@ -97,7 +92,6 @@ private:
bool is_peer_connected() { return peer->is_peer_connected(); }
void flush_output();
- void _send_resource_usage();
void _send_stack_vars(List<String> &p_names, List<Variant> &p_vals, int p_type);
Error _profiler_capture(const String &p_cmd, const Array &p_data, bool &r_captured);
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 555d4f6df4..a363cc3694 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -1030,7 +1030,7 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
}
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects, int p_depth) {
- ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Potential inifite recursion detected. Bailing.");
+ ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ERR_OUT_OF_MEMORY, "Potential infinite recursion detected. Bailing.");
uint8_t *buf = r_buffer;
r_len = 0;
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 123e3dc7b6..92ac5257b0 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -60,10 +60,10 @@ struct _NO_DISCARD_ Vector2 {
};
_FORCE_INLINE_ real_t &operator[](int p_idx) {
- return p_idx ? y : x;
+ return coord[p_idx];
}
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
- return p_idx ? y : x;
+ return coord[p_idx];
}
_FORCE_INLINE_ void set_all(const real_t p_value) {
diff --git a/core/math/vector2i.h b/core/math/vector2i.h
index 707c8c9490..3f5f12d4dd 100644
--- a/core/math/vector2i.h
+++ b/core/math/vector2i.h
@@ -43,19 +43,25 @@ struct _NO_DISCARD_ Vector2i {
};
union {
- int32_t x = 0;
- int32_t width;
- };
- union {
- int32_t y = 0;
- int32_t height;
+ struct {
+ union {
+ int32_t x;
+ int32_t width;
+ };
+ union {
+ int32_t y;
+ int32_t height;
+ };
+ };
+
+ int32_t coord[2] = { 0 };
};
_FORCE_INLINE_ int32_t &operator[](int p_idx) {
- return p_idx ? y : x;
+ return coord[p_idx];
}
_FORCE_INLINE_ const int32_t &operator[](int p_idx) const {
- return p_idx ? y : x;
+ return coord[p_idx];
}
_FORCE_INLINE_ Vector2i::Axis min_axis_index() const {
diff --git a/core/multiplayer/multiplayer_api.cpp b/core/multiplayer/multiplayer_api.cpp
index c8cb333e2c..3533acd103 100644
--- a/core/multiplayer/multiplayer_api.cpp
+++ b/core/multiplayer/multiplayer_api.cpp
@@ -47,7 +47,6 @@ MultiplayerCacheInterface *(*MultiplayerAPI::create_default_cache_interface)(Mul
void MultiplayerAPI::profile_bandwidth(const String &p_inout, int p_size) {
if (EngineDebugger::is_profiling("multiplayer")) {
Array values;
- values.push_back("bandwidth");
values.push_back(p_inout);
values.push_back(OS::get_singleton()->get_ticks_msec());
values.push_back(p_size);
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 3df4db9c5e..c29316c089 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1007,20 +1007,30 @@ bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal,
return false;
}
-void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix) {
+void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_COND(!type);
- type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_GROUP));
+ String prefix = p_prefix;
+ if (p_indent_depth > 0) {
+ prefix = vformat("%s,%d", p_prefix, p_indent_depth);
+ }
+
+ type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP));
}
-void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix) {
+void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
ERR_FAIL_COND(!type);
- type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_SUBGROUP));
+ String prefix = p_prefix;
+ if (p_indent_depth > 0) {
+ prefix = vformat("%s,%d", p_prefix, p_indent_depth);
+ }
+
+ type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_SUBGROUP));
}
void ClassDB::add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage) {
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 5adf1a59a4..5d258a29bf 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -328,8 +328,8 @@ public:
static bool get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal);
static void get_signal_list(const StringName &p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
- static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix = "");
- static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "");
+ static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix = "", int p_indent_depth = 0);
+ static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = "", int p_indent_depth = 0);
static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_DEFAULT);
static void add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix);
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
diff --git a/core/object/object.h b/core/object/object.h
index 1a0a81581d..be360703bc 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -142,7 +142,9 @@ enum PropertyUsageFlags {
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
#define ADD_PROPERTY_DEFAULT(m_property, m_default) ::ClassDB::set_property_default_value(get_class_static(), m_property, m_default)
#define ADD_GROUP(m_name, m_prefix) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
+#define ADD_GROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix, m_depth)
#define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
+#define ADD_SUBGROUP_INDENT(m_name, m_prefix, m_depth) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix, m_depth)
#define ADD_LINKED_PROPERTY(m_property, m_linked_property) ::ClassDB::add_linked_property(get_class_static(), m_property, m_linked_property)
#define ADD_ARRAY_COUNT(m_label, m_count_property, m_count_property_setter, m_count_property_getter, m_prefix) ClassDB::add_property_array_count(get_class_static(), m_label, m_count_property, _scs_create(m_count_property_setter), _scs_create(m_count_property_getter), m_prefix)
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 388368d181..a4b6a589f3 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -37,6 +37,7 @@
#include "core/crypto/aes_context.h"
#include "core/crypto/crypto.h"
#include "core/crypto/hashing_context.h"
+#include "core/debugger/engine_profiler.h"
#include "core/extension/native_extension.h"
#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
@@ -237,6 +238,8 @@ void register_core_types() {
GDREGISTER_VIRTUAL_CLASS(ResourceUID);
+ GDREGISTER_CLASS(EngineProfiler);
+
resource_uid = memnew(ResourceUID);
native_extension_manager = memnew(NativeExtensionManager);
diff --git a/core/string/string_name.h b/core/string/string_name.h
index f767f3e1ec..6f08d32981 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -188,7 +188,7 @@ StringName _scs_create(const char *p_chr, bool p_static = false);
* - Control::get_theme_*(<name> and Window::get_theme_*(<name> functions.
* - emit_signal(<name>,..) function
* - call_deferred(<name>,..) function
- * - Comparisons to a StringName in overriden _set and _get methods.
+ * - Comparisons to a StringName in overridden _set and _get methods.
*
* Use in places that can be called hundreds of times per frame (or more) is recommended, but this situation is very rare. If in doubt, do not use.
*/
diff --git a/core/version.h b/core/version.h
index c718d0f4d7..e22922fa66 100644
--- a/core/version.h
+++ b/core/version.h
@@ -68,4 +68,7 @@
// Example: "Godot v3.1.4.stable.official.mono"
#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_FULL_BUILD
+// Git commit hash, generated at build time in `core/version_hash.gen.cpp`.
+extern const char *const VERSION_HASH;
+
#endif // VERSION_H