summaryrefslogtreecommitdiff
path: root/main/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main/main.cpp')
-rw-r--r--main/main.cpp193
1 files changed, 149 insertions, 44 deletions
diff --git a/main/main.cpp b/main/main.cpp
index 532b5277b5..deffb3a632 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -45,6 +45,7 @@
#include "input_map.h"
#include "io/resource_loader.h"
#include "scene/main/scene_tree.h"
+#include "servers/arvr_server.h"
#include "servers/audio_server.h"
#include "io/resource_loader.h"
@@ -58,6 +59,7 @@
#ifdef TOOLS_ENABLED
#include "editor/doc/doc_data.h"
+#include "editor/doc/doc_data_class_path.gen.h"
#include "editor/editor_node.h"
#include "editor/project_manager.h"
#endif
@@ -73,6 +75,7 @@
#include "performance.h"
#include "translation.h"
#include "version.h"
+#include "version_hash.gen.h"
static ProjectSettings *globals = NULL;
static Engine *engine = NULL;
@@ -80,6 +83,7 @@ static InputMap *input_map = NULL;
static bool _start_success = false;
static ScriptDebugger *script_debugger = NULL;
AudioServer *audio_server = NULL;
+ARVRServer *arvr_server = NULL;
static MessageQueue *message_queue = NULL;
static Performance *performance = NULL;
@@ -111,6 +115,8 @@ static int init_screen = -1;
static bool use_vsync = true;
static bool editor = false;
static bool show_help = false;
+static bool disable_render_loop = false;
+static int fixed_fps = -1;
static OS::ProcessID allow_focus_steal_pid = 0;
@@ -119,6 +125,14 @@ static String unescape_cmdline(const String &p_str) {
return p_str.replace("%20", " ");
}
+static String get_full_version_string() {
+
+ String hash = String(VERSION_HASH);
+ if (hash.length() != 0)
+ hash = "." + hash.left(7);
+ return String(VERSION_MKSTRING) + hash;
+}
+
//#define DEBUG_INIT
#ifdef DEBUG_INIT
@@ -129,7 +143,7 @@ static String unescape_cmdline(const String &p_str) {
void Main::print_help(const char *p_binary) {
- OS::get_singleton()->print(VERSION_FULL_NAME " - https://godotengine.org\n");
+ print_line(String(_MKSTR(VERSION_NAME)) + " v" + get_full_version_string() + " - https://godotengine.org");
OS::get_singleton()->print("(c) 2007-2017 Juan Linietsky, Ariel Manzur.\n");
OS::get_singleton()->print("(c) 2014-2017 Godot Engine contributors.\n");
OS::get_singleton()->print("\n");
@@ -138,6 +152,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print("General options:\n");
OS::get_singleton()->print(" -h, --help Display this help message.\n");
+ OS::get_singleton()->print(" --version Display the version string.\n");
OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
OS::get_singleton()->print("\n");
@@ -149,6 +164,7 @@ void Main::print_help(const char *p_binary) {
#endif
OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
+ OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
@@ -175,7 +191,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
- OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS only).\n");
+ OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
OS::get_singleton()->print("\n");
@@ -190,6 +206,9 @@ void Main::print_help(const char *p_binary) {
#endif
OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
+ OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
+ OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
+ OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Standalone tools:\n");
@@ -197,7 +216,7 @@ void Main::print_help(const char *p_binary) {
#ifdef TOOLS_ENABLED
OS::get_singleton()->print(" --export <target> Export the project using the given export target.\n");
OS::get_singleton()->print(" --export-debug Use together with --export, enables debug mode for the template.\n");
- OS::get_singleton()->print(" --doctool <file> Dump the whole engine API to <file> in XML format. If <file> exists, it will be merged.\n");
+ OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
#ifdef DEBUG_METHODS_ENABLED
OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
@@ -215,7 +234,6 @@ void Main::print_help(const char *p_binary) {
}
Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
-
RID_OwnerBase::init_rid();
OS::get_singleton()->initialize_core();
@@ -238,10 +256,15 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
register_core_settings(); //here globals is present
+ OS::get_singleton()->initialize_logger();
+
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
+ ClassDB::register_class<Performance>();
globals->add_singleton(ProjectSettings::Singleton("Performance", performance));
+ GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
+
MAIN_PRINT("Main: Parse CMDLine");
/* argument parsing and main creation */
@@ -260,7 +283,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
while (I) {
I->get() = unescape_cmdline(I->get().strip_escapes());
- //print_line("CMD: "+I->get());
I = I->next();
}
@@ -271,6 +293,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String video_driver = "";
String audio_driver = "";
String game_path = ".";
+ bool upwards = false;
String debug_mode;
String debug_host;
String main_pack;
@@ -310,6 +333,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
show_help = true;
goto error;
+ } else if (I->get() == "--version") {
+
+ print_line(get_full_version_string());
+ goto error;
+
} else if (I->get() == "--resolution") { // force resolution
if (I->next()) {
@@ -474,6 +502,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing relative or absolute path, aborting.\n");
goto error;
}
+ } else if (I->get() == "-u" || I->get() == "--upwards") { // scan folders upwards
+ upwards = true;
} else if (I->get().ends_with("project.godot")) {
String path;
String file = I->get();
@@ -567,6 +597,18 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing editor PID argument, aborting.\n");
goto error;
}
+ } else if (I->get() == "--disable-render-loop") {
+ disable_render_loop = true;
+ } else if (I->get() == "--fixed-fps") {
+ if (I->next()) {
+ fixed_fps = I->next()->get().to_int();
+ N = I->next()->next();
+ } else {
+ OS::get_singleton()->print("Missing fixed-fps argument, aborting.\n");
+ goto error;
+ }
+ } else if (I->get() == "--disable-crash-handler") {
+ OS::get_singleton()->disable_crash_handler();
} else {
//test for game path
@@ -659,7 +701,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#endif
- if (globals->setup(game_path, main_pack) != OK) {
+ if (globals->setup(game_path, main_pack, upwards) != OK) {
#ifdef TOOLS_ENABLED
editor = false;
@@ -691,7 +733,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#ifdef TOOLS_ENABLED
- if (main_args.size() == 0 && (!ProjectSettings::get_singleton()->has("application/run/main_loop_type")) && (!ProjectSettings::get_singleton()->has("application/run/main_scene") || String(ProjectSettings::get_singleton()->get("application/run/main_scene")) == ""))
+ if (main_args.size() == 0 && (!ProjectSettings::get_singleton()->has_setting("application/run/main_loop_type")) && (!ProjectSettings::get_singleton()->has_setting("application/run/main_scene") || String(ProjectSettings::get_singleton()->get("application/run/main_scene")) == ""))
use_custom_res = false; //project manager (run without arguments)
#endif
@@ -704,21 +746,21 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
//if (video_driver == "") // useless for now, so removing
// video_driver = GLOBAL_DEF("display/driver/name", Variant((const char *)OS::get_singleton()->get_video_driver_name(0)));
- if (!force_res && use_custom_res && globals->has("display/window/size/width"))
+ if (!force_res && use_custom_res && globals->has_setting("display/window/size/width"))
video_mode.width = globals->get("display/window/size/width");
- if (!force_res && use_custom_res && globals->has("display/window/size/height"))
+ if (!force_res && use_custom_res && globals->has_setting("display/window/size/height"))
video_mode.height = globals->get("display/window/size/height");
- if (!editor && ((globals->has("display/window/dpi/allow_hidpi") && !globals->get("display/window/dpi/allow_hidpi")) || force_lowdpi)) {
+ if (!editor && ((globals->has_setting("display/window/dpi/allow_hidpi") && !globals->get("display/window/dpi/allow_hidpi")) || force_lowdpi)) {
OS::get_singleton()->_allow_hidpi = false;
}
- if (use_custom_res && globals->has("display/window/size/fullscreen"))
+ if (use_custom_res && globals->has_setting("display/window/size/fullscreen"))
video_mode.fullscreen = globals->get("display/window/size/fullscreen");
- if (use_custom_res && globals->has("display/window/size/resizable"))
+ if (use_custom_res && globals->has_setting("display/window/size/resizable"))
video_mode.resizable = globals->get("display/window/size/resizable");
- if (use_custom_res && globals->has("display/window/size/borderless"))
+ if (use_custom_res && globals->has_setting("display/window/size/borderless"))
video_mode.borderless_window = globals->get("display/window/size/borderless");
- if (!force_res && use_custom_res && globals->has("display/window/size/test_width") && globals->has("display/window/size/test_height")) {
+ if (!force_res && use_custom_res && globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) {
int tw = globals->get("display/window/size/test_width");
int th = globals->get("display/window/size/test_height");
if (tw > 0 && th > 0) {
@@ -739,6 +781,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
+ if (editor) {
+ OS::get_singleton()->_allow_hidpi = true; //editors always in hidpi
+ }
Engine::get_singleton()->_pixel_snap = GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false);
OS::get_singleton()->_keep_screen_on = GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
if (rtm == -1) {
@@ -896,11 +941,14 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
OS::get_singleton()->set_window_position(init_custom_pos);
}
- //right moment to create and initialize the audio server
+ // right moment to create and initialize the audio server
audio_server = memnew(AudioServer);
audio_server->init();
+ // also init our arvr_server from here
+ arvr_server = memnew(ARVRServer);
+
OS::get_singleton()->set_use_vsync(use_vsync);
register_core_singletons();
@@ -970,8 +1018,10 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#endif
}
+#ifdef TOOLS_ENABLED
Ref<Image> icon = memnew(Image(app_icon_png));
OS::get_singleton()->set_icon(icon);
+#endif
}
MAIN_PRINT("Main: DCC");
@@ -1062,6 +1112,7 @@ bool Main::start() {
ERR_FAIL_COND_V(!_start_success, false);
+ bool hasicon = false;
bool editor = false;
String doc_tool;
List<String> removal_docs;
@@ -1098,10 +1149,20 @@ bool Main::start() {
test = args[i + 1];
} else if (args[i] == "--export") {
editor = true; //needs editor
- _export_preset = args[i + 1];
+ if (i + 1 < args.size()) {
+ _export_preset = args[i + 1];
+ } else {
+ ERR_PRINT("Export preset name not specified");
+ return false;
+ }
} else if (args[i] == "--export-debug") {
editor = true; //needs editor
- _export_preset = args[i + 1];
+ if (i + 1 < args.size()) {
+ _export_preset = args[i + 1];
+ } else {
+ ERR_PRINT("Export preset name not specified");
+ return false;
+ }
export_debug = true;
} else {
// The parameter does not match anything known, don't skip the next argument
@@ -1119,26 +1180,46 @@ bool Main::start() {
#ifdef TOOLS_ENABLED
if (doc_tool != "") {
+ {
+ DirAccessRef da = DirAccess::open(doc_tool);
+ if (!da) {
+ ERR_EXPLAIN("Argument supplied to --doctool must be a base godot build directory");
+ ERR_FAIL_V(false);
+ }
+ }
DocData doc;
doc.generate(doc_base);
DocData docsrc;
- if (docsrc.load(doc_tool) == OK) {
- print_line("Doc exists. Merging..");
- doc.merge_from(docsrc);
- } else {
- print_line("No Doc exists. Generating empty.");
+ Map<String, String> doc_data_classes;
+ Set<String> checked_paths;
+ print_line("Loading docs..");
+
+ for (int i = 0; i < _doc_data_class_path_count; i++) {
+ String path = doc_tool.plus_file(_doc_data_class_paths[i].path);
+ String name = _doc_data_class_paths[i].name;
+ doc_data_classes[name] = path;
+ if (!checked_paths.has(path)) {
+ checked_paths.insert(path);
+ docsrc.load_classes(path);
+ print_line("Loading docs from: " + path);
+ }
}
- for (List<String>::Element *E = removal_docs.front(); E; E = E->next()) {
- DocData rmdoc;
- if (rmdoc.load(E->get()) == OK) {
- print_line(String("Removing classes in ") + E->get());
- doc.remove_from(rmdoc);
- }
+ String index_path = doc_tool.plus_file("doc/classes");
+ docsrc.load_classes(index_path);
+ checked_paths.insert(index_path);
+ print_line("Loading docs from: " + index_path);
+
+ print_line("Merging docs..");
+ doc.merge_from(docsrc);
+ for (Set<String>::Element *E = checked_paths.front(); E; E = E->next()) {
+ print_line("Erasing old docs at: " + E->get());
+ DocData::erase_classes(E->get());
}
- doc.save(doc_tool);
+ print_line("Generating new docs..");
+ doc.save_classes(index_path, doc_data_classes);
return false;
}
@@ -1269,7 +1350,7 @@ bool Main::start() {
String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled");
String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore");
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0));
- int stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1);
+ real_t stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1.0f);
SceneTree::StretchMode sml_sm = SceneTree::STRETCH_MODE_DISABLED;
if (stretch_mode == "2d")
@@ -1309,6 +1390,9 @@ bool Main::start() {
Viewport::Usage usage = Viewport::Usage(int(GLOBAL_GET("rendering/quality/intended_usage/framebuffer_allocation")));
sml->get_root()->set_usage(usage);
+ bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
+ sml->get_root()->set_snap_controls_to_pixels(snap_controls);
+
} 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"));
@@ -1318,6 +1402,7 @@ bool Main::start() {
ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/shrink", PropertyInfo(Variant::STRING, "display/window/stretch/shrink", PROPERTY_HINT_RANGE, "1,8,1"));
sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
+ GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
}
String local_game_path;
@@ -1359,6 +1444,8 @@ bool Main::start() {
if (editor) {
Error serr = editor_node->load_scene(local_game_path);
+ if (serr != OK)
+ ERR_PRINT("Failed to load scene");
OS::get_singleton()->set_context(OS::CONTEXT_EDITOR);
}
#endif
@@ -1463,8 +1550,10 @@ bool Main::start() {
if (iconpath != "") {
Ref<Image> icon;
icon.instance();
- if (icon->load(iconpath) == OK)
+ if (icon->load(iconpath) == OK) {
OS::get_singleton()->set_icon(icon);
+ hasicon = true;
+ }
}
}
}
@@ -1481,6 +1570,11 @@ bool Main::start() {
#endif
}
+ if (!hasicon) {
+ Ref<Image> icon = memnew(Image(app_icon_png));
+ OS::get_singleton()->set_icon(icon);
+ }
+
OS::get_singleton()->set_main_loop(main_loop);
return true;
@@ -1494,7 +1588,7 @@ uint32_t Main::frame = 0;
bool Main::force_redraw_requested = false;
//for performance metrics
-static uint64_t fixed_process_max = 0;
+static uint64_t physics_process_max = 0;
static uint64_t idle_process_max = 0;
bool Main::iteration() {
@@ -1505,6 +1599,9 @@ bool Main::iteration() {
uint64_t ticks_elapsed = ticks - last_ticks;
double step = (double)ticks_elapsed / 1000000.0;
+ if (fixed_fps != -1)
+ step = 1.0 / fixed_fps;
+
float frame_slice = 1.0 / Engine::get_singleton()->get_iterations_per_second();
Engine::get_singleton()->_frame_step = step;
@@ -1514,14 +1611,14 @@ bool Main::iteration() {
return false;
*/
- uint64_t fixed_process_ticks = 0;
+ uint64_t physics_process_ticks = 0;
uint64_t idle_process_ticks = 0;
frame += ticks_elapsed;
last_ticks = ticks;
- if (step > frame_slice * 8)
+ if (fixed_fps == -1 && step > frame_slice * 8)
step = frame_slice * 8;
time_accum += step;
@@ -1532,11 +1629,11 @@ bool Main::iteration() {
int iters = 0;
- Engine::get_singleton()->_in_fixed = true;
+ Engine::get_singleton()->_in_physics = true;
while (time_accum > frame_slice) {
- uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();
+ uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
PhysicsServer::get_singleton()->sync();
PhysicsServer::get_singleton()->flush_queries();
@@ -1559,13 +1656,13 @@ bool Main::iteration() {
time_accum -= frame_slice;
message_queue->flush();
- fixed_process_ticks = MAX(fixed_process_ticks, OS::get_singleton()->get_ticks_usec() - fixed_begin); // keep the largest one for reference
- fixed_process_max = MAX(OS::get_singleton()->get_ticks_usec() - fixed_begin, fixed_process_max);
+ physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference
+ physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max);
iters++;
- Engine::get_singleton()->_fixed_frames++;
+ Engine::get_singleton()->_physics_frames++;
}
- Engine::get_singleton()->_in_fixed = false;
+ Engine::get_singleton()->_in_physics = false;
uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();
@@ -1574,7 +1671,7 @@ bool Main::iteration() {
VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames.
- if (OS::get_singleton()->can_draw()) {
+ if (OS::get_singleton()->can_draw() && !disable_render_loop) {
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
if (VisualServer::get_singleton()->has_changed()) {
@@ -1601,7 +1698,7 @@ bool Main::iteration() {
if (script_debugger) {
if (script_debugger->is_profiling()) {
- script_debugger->profiling_set_frame_times(USEC_TO_SEC(frame_time), USEC_TO_SEC(idle_process_ticks), USEC_TO_SEC(fixed_process_ticks), frame_slice);
+ script_debugger->profiling_set_frame_times(USEC_TO_SEC(frame_time), USEC_TO_SEC(idle_process_ticks), USEC_TO_SEC(physics_process_ticks), frame_slice);
}
script_debugger->idle_poll();
}
@@ -1617,14 +1714,17 @@ bool Main::iteration() {
Engine::get_singleton()->_fps = frames;
performance->set_process_time(USEC_TO_SEC(idle_process_max));
- performance->set_fixed_process_time(USEC_TO_SEC(fixed_process_max));
+ performance->set_physics_process_time(USEC_TO_SEC(physics_process_max));
idle_process_max = 0;
- fixed_process_max = 0;
+ physics_process_max = 0;
frame %= 1000000;
frames = 0;
}
+ if (fixed_fps != -1)
+ return exit;
+
if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw())
OS::get_singleton()->delay_usec(16600); //apply some delay to force idle time (results in about 60 FPS max)
else {
@@ -1680,6 +1780,11 @@ void Main::cleanup() {
memdelete(audio_server);
}
+ if (arvr_server) {
+ // cleanup now before we pull the rug from underneath...
+ memdelete(arvr_server);
+ }
+
unregister_driver_types();
unregister_module_types();
unregister_scene_types();