diff --git a/platform/macos/godot_main_macos.mm b/platform/macos/godot_main_macos.mm index 6d8a6fcecd7..e2f3d6955af 100644 --- a/platform/macos/godot_main_macos.mm +++ b/platform/macos/godot_main_macos.mm @@ -56,6 +56,7 @@ int main(int argc, char **argv) { int wait_for_debugger = 0; // wait 5 second by default bool is_embedded = false; + bool is_headless = false; for (int i = 0; i < argc; i++) { if (strcmp("-NSDocumentRevisionsDebugMode", argv[i]) == 0) { @@ -75,6 +76,12 @@ int main(int argc, char **argv) { if (strcmp("--embedded", argv[i]) == 0) { is_embedded = true; } + if (strcmp("--headless", argv[i]) == 0 || strcmp("--doctool", argv[i]) == 0) { + is_headless = true; + } + if (i < argc - 1 && strcmp("--display-driver", argv[i]) == 0 && strcmp("headless", argv[i + 1]) == 0) { + is_headless = true; + } args.ptr()[argsc] = argv[i]; argsc++; @@ -90,6 +97,8 @@ int main(int argc, char **argv) { WARN_PRINT("Embedded mode is not supported in release builds."); return EXIT_FAILURE; #endif + } else if (is_headless) { + os = memnew(OS_MacOS_Headless(args[0], remaining_args, remaining_args > 0 ? &args[1] : nullptr)); } else { os = memnew(OS_MacOS_NSApp(args[0], remaining_args, remaining_args > 0 ? &args[1] : nullptr)); } diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h index 73294c0fec7..8cf47902b1d 100644 --- a/platform/macos/os_macos.h +++ b/platform/macos/os_macos.h @@ -171,6 +171,13 @@ public: OS_MacOS_NSApp(const char *p_execpath, int p_argc, char **p_argv); }; +class OS_MacOS_Headless : public OS_MacOS { +public: + virtual void run() override; + + OS_MacOS_Headless(const char *p_execpath, int p_argc, char **p_argv); +}; + #ifdef DEBUG_ENABLED class OS_MacOS_Embedded : public OS_MacOS { diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index f70a24a3c53..087c2f0a376 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -1171,6 +1171,59 @@ OS_MacOS_NSApp::OS_MacOS_NSApp(const char *p_execpath, int p_argc, char **p_argv sigaction(SIGINT, &action, nullptr); } +// MARK: - OS_MacOS_Headless + +void OS_MacOS_Headless::run() { + CFRunLoopGetCurrent(); + + @autoreleasepool { + Error err = Main::setup(execpath, argc, argv); + if (err != OK) { + if (err == ERR_HELP) { + return set_exit_code(EXIT_SUCCESS); + } + return set_exit_code(EXIT_FAILURE); + } + } + + int ret; + @autoreleasepool { + ret = Main::start(); + } + + if (ret == EXIT_SUCCESS && main_loop) { + @autoreleasepool { + main_loop->initialize(); + } + + while (true) { + @autoreleasepool { + @try { + if (Input::get_singleton()) { + Input::get_singleton()->flush_buffered_events(); + } + + if (Main::iteration()) { + break; + } + + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); + } @catch (NSException *exception) { + ERR_PRINT("NSException: " + String::utf8([exception reason].UTF8String)); + } + } + } + + main_loop->finalize(); + } + + Main::cleanup(); +} + +OS_MacOS_Headless::OS_MacOS_Headless(const char *p_execpath, int p_argc, char **p_argv) : + OS_MacOS(p_execpath, p_argc, p_argv) { +} + // MARK: - OS_MacOS_Embedded #ifdef DEBUG_ENABLED