summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/main.cpp95
-rw-r--r--main/main.h1
-rw-r--r--main/performance.cpp76
-rw-r--r--main/performance.h22
-rw-r--r--main/tests/test_basis.cpp2
-rw-r--r--main/tests/test_basis.h2
-rw-r--r--main/tests/test_string.cpp7
7 files changed, 135 insertions, 70 deletions
diff --git a/main/main.cpp b/main/main.cpp
index 747b12677d..7492d3d6c9 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -780,7 +780,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get().ends_with("project.godot")) {
String path;
String file = I->get();
- int sep = MAX(file.find_last("/"), file.find_last("\\"));
+ int sep = MAX(file.rfind("/"), file.rfind("\\"));
if (sep == -1) {
path = ".";
} else {
@@ -836,6 +836,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "-d" || I->get() == "--debug") {
debug_uri = "local://";
+ OS::get_singleton()->_debug_stdout = true;
#if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED)
} else if (I->get() == "--debug-collisions") {
debug_collisions = true;
@@ -856,7 +857,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
} else if (I->get() == "--allow_focus_steal_pid") { // not exposed to user
if (I->next()) {
- allow_focus_steal_pid = I->next()->get().to_int64();
+ allow_focus_steal_pid = I->next()->get().to_int();
N = I->next()->next();
} else {
OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
@@ -1620,7 +1621,7 @@ bool Main::start() {
{
DirAccessRef da = DirAccess::open(doc_tool);
- ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a base Godot build directory.");
+ ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
}
#ifndef MODULE_MONO_ENABLED
@@ -1792,46 +1793,26 @@ bool Main::start() {
if (!project_manager && !editor) { // game
if (game_path != "" || script != "") {
//autoload
- List<PropertyInfo> props;
- ProjectSettings::get_singleton()->get_property_list(&props);
+ Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
//first pass, add the constants so they exist before any script is loaded
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String s = E->get().name;
- if (!s.begins_with("autoload/")) {
- continue;
- }
- String name = s.get_slicec('/', 1);
- String path = ProjectSettings::get_singleton()->get(s);
- bool global_var = false;
- if (path.begins_with("*")) {
- global_var = true;
- }
+ for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+ const ProjectSettings::AutoloadInfo &info = E->get();
- if (global_var) {
+ if (info.is_singleton) {
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->add_global_constant(name, Variant());
+ ScriptServer::get_language(i)->add_global_constant(info.name, Variant());
}
}
}
//second pass, load into global constants
List<Node *> to_add;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String s = E->get().name;
- if (!s.begins_with("autoload/")) {
- continue;
- }
- String name = s.get_slicec('/', 1);
- String path = ProjectSettings::get_singleton()->get(s);
- bool global_var = false;
- if (path.begins_with("*")) {
- global_var = true;
- path = path.substr(1, path.length() - 1);
- }
+ for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+ const ProjectSettings::AutoloadInfo &info = E->get();
- RES res = ResourceLoader::load(path);
- ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + path);
+ RES res = ResourceLoader::load(info.path);
+ ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
Node *n = nullptr;
if (res->is_class("PackedScene")) {
Ref<PackedScene> ps = res;
@@ -1840,7 +1821,7 @@ bool Main::start() {
Ref<Script> script_res = res;
StringName ibt = script_res->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + path);
+ ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path);
Object *obj = ClassDB::instance(ibt);
@@ -1850,15 +1831,15 @@ bool Main::start() {
n->set_script(script_res);
}
- ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + path);
- n->set_name(name);
+ ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path);
+ n->set_name(info.name);
//defer so references are all valid on _ready()
to_add.push_back(n);
- if (global_var) {
+ if (info.is_singleton) {
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
- ScriptServer::get_language(i)->add_global_constant(name, n);
+ ScriptServer::get_language(i)->add_global_constant(info.name, n);
}
}
}
@@ -1895,10 +1876,10 @@ bool Main::start() {
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0));
Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED;
- if (stretch_mode == "objects") {
- cs_sm = Window::CONTENT_SCALE_MODE_OBJECTS;
- } else if (stretch_mode == "pixels") {
- cs_sm = Window::CONTENT_SCALE_MODE_PIXELS;
+ if (stretch_mode == "canvas_items") {
+ cs_sm = Window::CONTENT_SCALE_MODE_CANVAS_ITEMS;
+ } else if (stretch_mode == "viewport") {
+ cs_sm = Window::CONTENT_SCALE_MODE_VIEWPORT;
}
Window::ContentScaleAspect cs_aspect = Window::CONTENT_SCALE_ASPECT_IGNORE;
@@ -1954,7 +1935,7 @@ bool Main::start() {
} else {
GLOBAL_DEF("display/window/stretch/mode", "disabled");
- ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,2d,viewport"));
+ ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,canvas_items,viewport"));
GLOBAL_DEF("display/window/stretch/aspect", "ignore");
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect", PropertyInfo(Variant::STRING, "display/window/stretch/aspect", PROPERTY_HINT_ENUM, "ignore,keep,keep_width,keep_height,expand"));
GLOBAL_DEF("display/window/stretch/shrink", 1.0);
@@ -1992,7 +1973,7 @@ bool Main::start() {
local_game_path = "res://" + local_game_path;
} else {
- int sep = local_game_path.find_last("/");
+ int sep = local_game_path.rfind("/");
if (sep == -1) {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@@ -2115,7 +2096,6 @@ bool Main::start() {
*/
uint64_t Main::last_ticks = 0;
-uint64_t Main::target_ticks = 0;
uint32_t Main::frames = 0;
uint32_t Main::frame = 0;
bool Main::force_redraw_requested = false;
@@ -2266,26 +2246,7 @@ bool Main::iteration() {
return exit;
}
- if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->can_any_window_draw()) {
- OS::get_singleton()->delay_usec(OS::get_singleton()->get_low_processor_usage_mode_sleep_usec()); //apply some delay to force idle time
- } else {
- uint32_t frame_delay = Engine::get_singleton()->get_frame_delay();
- if (frame_delay) {
- OS::get_singleton()->delay_usec(Engine::get_singleton()->get_frame_delay() * 1000);
- }
- }
-
- int target_fps = Engine::get_singleton()->get_target_fps();
- if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) {
- uint64_t time_step = 1000000L / target_fps;
- target_ticks += time_step;
- uint64_t current_ticks = OS::get_singleton()->get_ticks_usec();
- if (current_ticks < target_ticks) {
- OS::get_singleton()->delay_usec(target_ticks - current_ticks);
- }
- current_ticks = OS::get_singleton()->get_ticks_usec();
- target_ticks = MIN(MAX(target_ticks, current_ticks - time_step), current_ticks + time_step);
- }
+ OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw());
#ifdef TOOLS_ENABLED
if (auto_build_solutions) {
@@ -2321,8 +2282,8 @@ void Main::cleanup() {
ResourceLoader::remove_custom_loaders();
ResourceSaver::remove_custom_savers();
+ // Flush before uninitializing the scene, but delete the MessageQueue as late as possible.
message_queue->flush();
- memdelete(message_queue);
OS::get_singleton()->delete_main_loop();
@@ -2408,6 +2369,10 @@ void Main::cleanup() {
OS::get_singleton()->set_restart_on_exit(false, List<String>()); //clear list (uses memory)
}
+ // Now should be safe to delete MessageQueue (famous last words).
+ message_queue->flush();
+ memdelete(message_queue);
+
unregister_core_driver_types();
unregister_core_types();
diff --git a/main/main.h b/main/main.h
index ab6917a65c..308128735c 100644
--- a/main/main.h
+++ b/main/main.h
@@ -38,7 +38,6 @@
class Main {
static void print_help(const char *p_binary);
static uint64_t last_ticks;
- static uint64_t target_ticks;
static uint32_t frames;
static uint32_t frame;
static bool force_redraw_requested;
diff --git a/main/performance.cpp b/main/performance.cpp
index 7e6b9fca64..7234511aeb 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -43,6 +43,12 @@ Performance *Performance::singleton = nullptr;
void Performance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_monitor", "monitor"), &Performance::get_monitor);
+ ClassDB::bind_method(D_METHOD("add_custom_monitor", "id", "callable", "arguments"), &Performance::add_custom_monitor, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("remove_custom_monitor", "id"), &Performance::remove_custom_monitor);
+ ClassDB::bind_method(D_METHOD("has_custom_monitor", "id"), &Performance::has_custom_monitor);
+ ClassDB::bind_method(D_METHOD("get_custom_monitor", "id"), &Performance::get_custom_monitor);
+ ClassDB::bind_method(D_METHOD("get_monitor_modification_time"), &Performance::get_monitor_modification_time);
+ ClassDB::bind_method(D_METHOD("get_custom_monitor_names"), &Performance::get_custom_monitor_names);
BIND_ENUM_CONSTANT(TIME_FPS);
BIND_ENUM_CONSTANT(TIME_PROCESS);
@@ -231,8 +237,78 @@ void Performance::set_physics_process_time(float p_pt) {
_physics_process_time = p_pt;
}
+void Performance::add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args) {
+ ERR_FAIL_COND_MSG(has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' already exists.");
+ _monitor_map.insert(p_id, MonitorCall(p_callable, p_args));
+ _monitor_modification_time = OS::get_singleton()->get_ticks_usec();
+}
+
+void Performance::remove_custom_monitor(const StringName &p_id) {
+ ERR_FAIL_COND_MSG(!has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' doesn't exists.");
+ _monitor_map.erase(p_id);
+ _monitor_modification_time = OS::get_singleton()->get_ticks_usec();
+}
+
+bool Performance::has_custom_monitor(const StringName &p_id) {
+ return _monitor_map.has(p_id);
+}
+
+Variant Performance::get_custom_monitor(const StringName &p_id) {
+ ERR_FAIL_COND_V_MSG(!has_custom_monitor(p_id), Variant(), "Custom monitor with id '" + String(p_id) + "' doesn't exists.");
+ bool error;
+ String error_message;
+ Variant return_value = _monitor_map[p_id].call(error, error_message);
+ ERR_FAIL_COND_V_MSG(error, return_value, "Error calling from custom monitor '" + String(p_id) + "' to callable: " + error_message);
+ return return_value;
+}
+
+Array Performance::get_custom_monitor_names() {
+ if (!_monitor_map.size()) {
+ return Array();
+ }
+ Array return_array;
+ return_array.resize(_monitor_map.size());
+ int index = 0;
+ for (OrderedHashMap<StringName, MonitorCall>::Element i = _monitor_map.front(); i; i = i.next()) {
+ return_array.set(index, i.key());
+ index++;
+ }
+ return return_array;
+}
+
+uint64_t Performance::get_monitor_modification_time() {
+ return _monitor_modification_time;
+}
+
Performance::Performance() {
_process_time = 0;
_physics_process_time = 0;
+ _monitor_modification_time = 0;
singleton = this;
}
+
+Performance::MonitorCall::MonitorCall(Callable p_callable, Vector<Variant> p_arguments) {
+ _callable = p_callable;
+ _arguments = p_arguments;
+}
+
+Performance::MonitorCall::MonitorCall() {
+}
+
+Variant Performance::MonitorCall::call(bool &r_error, String &r_error_message) {
+ Vector<const Variant *> arguments_mem;
+ arguments_mem.resize(_arguments.size());
+ for (int i = 0; i < _arguments.size(); i++) {
+ arguments_mem.write[i] = &_arguments[i];
+ }
+ const Variant **args = (const Variant **)arguments_mem.ptr();
+ int argc = _arguments.size();
+ Variant return_value;
+ Callable::CallError error;
+ _callable.call(args, argc, return_value, error);
+ r_error = (error.error != Callable::CallError::CALL_OK);
+ if (r_error) {
+ r_error_message = Variant::get_callable_error_text(_callable, args, argc, error);
+ }
+ return return_value;
+}
diff --git a/main/performance.h b/main/performance.h
index ddbe45fa00..5f88a24c0f 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -32,6 +32,7 @@
#define PERFORMANCE_H
#include "core/object.h"
+#include "core/ordered_hash_map.h"
#define PERF_WARN_OFFLINE_FUNCTION
#define PERF_WARN_PROCESS_SYNC
@@ -47,6 +48,19 @@ class Performance : public Object {
float _process_time;
float _physics_process_time;
+ class MonitorCall {
+ Callable _callable;
+ Vector<Variant> _arguments;
+
+ public:
+ MonitorCall(Callable p_callable, Vector<Variant> p_arguments);
+ MonitorCall();
+ Variant call(bool &r_error, String &r_error_message);
+ };
+
+ OrderedHashMap<StringName, MonitorCall> _monitor_map;
+ uint64_t _monitor_modification_time;
+
public:
enum Monitor {
@@ -95,6 +109,14 @@ public:
void set_process_time(float p_pt);
void set_physics_process_time(float p_pt);
+ void add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args);
+ void remove_custom_monitor(const StringName &p_id);
+ bool has_custom_monitor(const StringName &p_id);
+ Variant get_custom_monitor(const StringName &p_id);
+ Array get_custom_monitor_names();
+
+ uint64_t get_monitor_modification_time();
+
static Performance *get_singleton() { return singleton; }
Performance();
diff --git a/main/tests/test_basis.cpp b/main/tests/test_basis.cpp
index ac25151fd8..5904fc386a 100644
--- a/main/tests/test_basis.cpp
+++ b/main/tests/test_basis.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* test_fbx.cpp */
+/* test_basis.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/main/tests/test_basis.h b/main/tests/test_basis.h
index 67c9db8877..63297bd3b8 100644
--- a/main/tests/test_basis.h
+++ b/main/tests/test_basis.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* test_fbx.h */
+/* test_basis.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp
index 775c039282..73d59b0088 100644
--- a/main/tests/test_string.cpp
+++ b/main/tests/test_string.cpp
@@ -370,8 +370,11 @@ bool test_22() {
static const int num[4] = { 1237461283, -22, 0, -1123412 };
for (int i = 0; i < 4; i++) {
- OS::get_singleton()->print("\tString: \"%s\" as Int is %i\n", nums[i], String(nums[i]).to_int());
-
+#ifdef __MINGW32__ // MinGW can't handle normal format specifiers for some reason. So we need special code just for MinGW.
+ OS::get_singleton()->print("\tString: \"%s\" as Int is %I64i\n", nums[i], (long long)(String(nums[i]).to_int()));
+#else
+ OS::get_singleton()->print("\tString: \"%s\" as Int is %lli\n", nums[i], (long long)(String(nums[i]).to_int()));
+#endif
if (String(nums[i]).to_int() != num[i]) {
return false;
}