diff --git a/source/main.cpp b/source/main.cpp index b7f2e6db53..7e9db44fec 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -89,13 +89,30 @@ that of Atlas depending on commandline parameters. #define getpid _getpid // Use the non-deprecated function name #endif +extern CmdLineArgs g_args; extern CStrW g_UniqueLogPostfix; -void kill_mainloop(); - // Marks terrain as modified so the minimap can repaint (is there a cleaner way of handling this?) bool g_GameRestarted = false; +// Determines the lifetime of the mainloop +enum ShutdownType +{ + // The application shall continue the main loop. + None, + + // The process shall terminate as soon as possible. + Quit, + + // The engine should be restarted in the same process, for instance to activate different mods. + Restart, + + // Atlas should be started in the same process. + RestartAsAtlas +}; + +static ShutdownType g_Shutdown = ShutdownType::None; + // to avoid redundant and/or recursive resizing, we save the new // size after VIDEORESIZE messages and only update the video mode // once per frame. @@ -106,6 +123,21 @@ static int g_ResizedH; static std::chrono::high_resolution_clock::time_point lastFrameTime; +void QuitEngine() +{ + g_Shutdown = ShutdownType::Quit; +} + +void RestartEngine() +{ + g_Shutdown = ShutdownType::Restart; +} + +void StartAtlas() +{ + g_Shutdown = ShutdownType::RestartAsAtlas; +} + // main app message handler static InReaction MainInputHandler(const SDL_Event_* ev) { @@ -130,14 +162,14 @@ static InReaction MainInputHandler(const SDL_Event_* ev) break; case SDL_QUIT: - kill_mainloop(); + QuitEngine(); break; case SDL_HOTKEYDOWN: std::string hotkey = static_cast(ev->ev.user.data1); if (hotkey == "exit") { - kill_mainloop(); + QuitEngine(); return IN_HANDLED; } else if (hotkey == "screenshot") @@ -278,9 +310,6 @@ static void RendererIncrementalLoad() while (more && timer_Time() - startTime < maxTime); } - -static bool quit = false; // break out of main loop - static void Frame() { g_Profiler2.RecordFrameStart(); @@ -334,7 +363,7 @@ static void Frame() // if the user quit by closing the window, the GL context will be broken and // may crash when we call Render() on some drivers, so leave this loop // before rendering - if (quit) + if (g_Shutdown != ShutdownType::None) return; // respond to pumped resize events @@ -406,10 +435,9 @@ static void NonVisualFrame() g_Profiler.Frame(); if (g_Game->IsGameFinished()) - kill_mainloop(); + QuitEngine(); } - static void MainControllerInit() { // add additional input handlers only needed by this controller: @@ -418,41 +446,11 @@ static void MainControllerInit() in_add_handler(MainInputHandler); } - - static void MainControllerShutdown() { in_reset_handlers(); } - -// stop the main loop and trigger orderly shutdown. called from several -// places: the event handler (SDL_QUIT and hotkey) and JS exitProgram. -void kill_mainloop() -{ - quit = true; -} - - -static bool restart_in_atlas = false; -// called by game code to indicate main() should restart in Atlas mode -// instead of terminating -void restart_mainloop_in_atlas() -{ - quit = true; - restart_in_atlas = true; -} - -static bool restart = false; -// trigger an orderly shutdown and restart the game. -void restart_engine() -{ - quit = true; - restart = true; -} - -extern CmdLineArgs g_args; - // moved into a helper function to ensure args is destroyed before // exit(), which may result in a memory leak. static void RunGameOrAtlas(int argc, const char* argv[]) @@ -593,8 +591,8 @@ static void RunGameOrAtlas(int argc, const char* argv[]) int flags = INIT_MODS; do { - restart = false; - quit = false; + g_Shutdown = ShutdownType::None; + if (!Init(args, flags)) { flags &= ~INIT_MODS; @@ -618,14 +616,14 @@ static void RunGameOrAtlas(int argc, const char* argv[]) if (isNonVisual) { InitNonVisual(args); - while (!quit) + while (g_Shutdown == ShutdownType::None) NonVisualFrame(); } else { InitGraphics(args, 0, installedMods); MainControllerInit(); - while (!quit) + while (g_Shutdown == ShutdownType::None) Frame(); } @@ -635,9 +633,10 @@ static void RunGameOrAtlas(int argc, const char* argv[]) Shutdown(0); MainControllerShutdown(); flags &= ~INIT_MODS; - } while (restart); - if (restart_in_atlas) + } while (g_Shutdown == ShutdownType::Restart); + + if (g_Shutdown == ShutdownType::RestartAsAtlas) ATLAS_RunIfOnCmdLine(args, true); CXeromyces::Terminate(); diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index ba9a108bbb..3712e98a59 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -94,7 +94,7 @@ #define MUST_INIT_X11 0 #endif -extern void restart_engine(); +extern void RestartEngine(); #include @@ -958,7 +958,7 @@ bool Init(const CmdLineArgs& args, int flags) std::swap(g_modsLoaded, mods); // Abort init and restart - restart_engine(); + RestartEngine(); return false; } } diff --git a/source/ps/scripting/JSInterface_Main.cpp b/source/ps/scripting/JSInterface_Main.cpp index 13076d5a3b..6a6767c6ba 100644 --- a/source/ps/scripting/JSInterface_Main.cpp +++ b/source/ps/scripting/JSInterface_Main.cpp @@ -31,17 +31,17 @@ #include "scriptinterface/ScriptInterface.h" #include "tools/atlas/GameInterface/GameLoop.h" -extern void restart_mainloop_in_atlas(); -extern void kill_mainloop(); +extern void QuitEngine(); +extern void StartAtlas(); -void JSI_Main::ExitProgram(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +void JSI_Main::QuitEngine(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - kill_mainloop(); + ::QuitEngine(); } -void JSI_Main::RestartInAtlas(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +void JSI_Main::StartAtlas(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - restart_mainloop_in_atlas(); + ::StartAtlas(); } bool JSI_Main::AtlasIsAvailable(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) @@ -111,8 +111,8 @@ int JSI_Main::GetTextWidth(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const void JSI_Main::RegisterScriptFunctions(const ScriptInterface& scriptInterface) { - scriptInterface.RegisterFunction("Exit"); - scriptInterface.RegisterFunction("RestartInAtlas"); + scriptInterface.RegisterFunction("Exit"); + scriptInterface.RegisterFunction("RestartInAtlas"); scriptInterface.RegisterFunction("AtlasIsAvailable"); scriptInterface.RegisterFunction("IsAtlasRunning"); scriptInterface.RegisterFunction("OpenURL"); diff --git a/source/ps/scripting/JSInterface_Main.h b/source/ps/scripting/JSInterface_Main.h index 12153f3a4e..01260bb080 100644 --- a/source/ps/scripting/JSInterface_Main.h +++ b/source/ps/scripting/JSInterface_Main.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ namespace JSI_Main { - void ExitProgram(ScriptInterface::CxPrivate* pCxPrivate); - void RestartInAtlas(ScriptInterface::CxPrivate* pCxPrivate); + void QuitEngine(ScriptInterface::CxPrivate* pCxPrivate); + void StartAtlas(ScriptInterface::CxPrivate* pCxPrivate); bool AtlasIsAvailable(ScriptInterface::CxPrivate* pCxPrivate); bool IsAtlasRunning(ScriptInterface::CxPrivate* pCxPrivate); void OpenURL(ScriptInterface::CxPrivate* pCxPrivate, const std::string& url); diff --git a/source/ps/scripting/JSInterface_Mod.cpp b/source/ps/scripting/JSInterface_Mod.cpp index 420ab9211b..a195f2bcf0 100644 --- a/source/ps/scripting/JSInterface_Mod.cpp +++ b/source/ps/scripting/JSInterface_Mod.cpp @@ -22,7 +22,7 @@ #include "ps/Mod.h" #include "scriptinterface/ScriptInterface.h" -extern void restart_engine(); +extern void RestartEngine(); JS::Value JSI_Mod::GetEngineInfo(ScriptInterface::CxPrivate* pCxPrivate) { @@ -46,7 +46,7 @@ JS::Value JSI_Mod::GetAvailableMods(ScriptInterface::CxPrivate* pCxPrivate) void JSI_Mod::RestartEngine(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - restart_engine(); + ::RestartEngine(); } void JSI_Mod::SetMods(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::vector& mods) diff --git a/source/ps/tests/stub_impl_hack.h b/source/ps/tests/stub_impl_hack.h index fc34795a74..40e02bc8de 100644 --- a/source/ps/tests/stub_impl_hack.h +++ b/source/ps/tests/stub_impl_hack.h @@ -22,15 +22,15 @@ bool g_GameRestarted; -void kill_mainloop() +void QuitEngine() { } -void restart_mainloop_in_atlas() +void StartAtlas() { } -void restart_engine() +void RestartEngine() { } diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index a52472df0d..23be80b7a8 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -44,7 +44,7 @@ #include "simulation2/serialization/StdSerializer.h" #include "simulation2/serialization/SerializeTemplates.h" -extern void kill_mainloop(); +extern void QuitEngine(); /** * @file @@ -354,7 +354,7 @@ public: static void ExitProgram(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - kill_mainloop(); + QuitEngine(); } /**