123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- // Description : CryENGINE system core-handle all subsystems
- #include "CrySystem_precompiled.h"
- #include "System.h"
- #include <time.h>
- #include <AzCore/Console/Console.h>
- #include <AzCore/IO/IStreamer.h>
- #include <AzCore/IO/SystemFile.h>
- #include <AzCore/Debug/Budget.h>
- #include <CryPath.h>
- #include <CrySystemBus.h>
- #include <CryCommon/IFont.h>
- #include <CryCommon/MiniQueue.h>
- #include <AzFramework/API/ApplicationAPI.h>
- #include <AzFramework/API/ApplicationAPI_Platform.h>
- #include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
- #include <AzFramework/Spawnable/RootSpawnableInterface.h>
- #include <AzCore/Debug/Profiler.h>
- #include <AzCore/Debug/Trace.h>
- #include <AzCore/Interface/Interface.h>
- #include <AzCore/std/algorithm.h>
- #include <AzCore/Time/ITime.h>
- #include <AzFramework/Logging/MissingAssetLogger.h>
- #include <AzFramework/Entity/EntityDebugDisplayBus.h>
- #include <AzCore/Interface/Interface.h>
- AZ_DEFINE_BUDGET(CrySystem);
- #if defined(AZ_RESTRICTED_PLATFORM)
- #undef AZ_RESTRICTED_SECTION
- #define SYSTEM_CPP_SECTION_1 1
- #define SYSTEM_CPP_SECTION_2 2
- #define SYSTEM_CPP_SECTION_3 3
- #define SYSTEM_CPP_SECTION_4 4
- #define SYSTEM_CPP_SECTION_5 5
- #define SYSTEM_CPP_SECTION_6 6
- #define SYSTEM_CPP_SECTION_7 7
- #define SYSTEM_CPP_SECTION_8 8
- #define SYSTEM_CPP_SECTION_9 9
- #endif
- #if defined(_RELEASE) && AZ_LEGACY_CRYSYSTEM_TRAIT_USE_EXCLUDEUPDATE_ON_CONSOLE
- //exclude some not needed functionality for release console builds
- #define EXCLUDE_UPDATE_ON_CONSOLE
- #endif
- #ifdef WIN32
- #include <AzCore/PlatformIncl.h>
- LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- CSystem* pSystem = 0;
- if (gEnv)
- {
- pSystem = static_cast<CSystem*>(gEnv->pSystem);
- }
- if (pSystem && !pSystem->IsQuitting())
- {
- LRESULT result = 0;
- bool bAny = false;
- for (std::vector<IWindowMessageHandler*>::const_iterator it = pSystem->m_windowMessageHandlers.begin(); it != pSystem->m_windowMessageHandlers.end(); ++it)
- {
- IWindowMessageHandler* pHandler = *it;
- LRESULT maybeResult = 0xDEADDEAD;
- if (pHandler->HandleMessage(hWnd, uMsg, wParam, lParam, &maybeResult))
- {
- assert(maybeResult != 0xDEADDEAD && "Message handler indicated a resulting value, but no value was written");
- if (bAny)
- {
- assert(result == maybeResult && "Two window message handlers tried to return different result values");
- }
- else
- {
- bAny = true;
- result = maybeResult;
- }
- }
- }
- if (bAny)
- {
- // One of the registered handlers returned something
- return result;
- }
- }
- // Handle with the default procedure
- assert(IsWindowUnicode(hWnd) && "Window should be Unicode when compiling with UNICODE");
- return DefWindowProcW(hWnd, uMsg, wParam, lParam);
- }
- #endif
- #if defined(LINUX) && !defined(ANDROID)
- #include <execinfo.h> // for backtrace
- #endif
- #if defined(ANDROID)
- #include <unwind.h> // for _Unwind_Backtrace and _Unwind_GetIP
- #endif
- #if defined(AZ_RESTRICTED_PLATFORM)
- #define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_1
- #include AZ_RESTRICTED_FILE(System_cpp)
- #endif
- #include <IRenderer.h>
- #include <IMovieSystem.h>
- #include <ILog.h>
- #include <IAudioSystem.h>
- #include <LoadScreenBus.h>
- #include <AzFramework/Archive/Archive.h>
- #include "XConsole.h"
- #include "Log.h"
- #include "XML/xml.h"
- #include "LocalizedStringManager.h"
- #include "XML/XmlUtils.h"
- #include "SystemEventDispatcher.h"
- #include "RemoteConsole/RemoteConsole.h"
- #include <AzFramework/Asset/AssetSystemBus.h>
- #include <AzFramework/Input/Buses/Requests/InputSystemRequestBus.h>
- #ifdef WIN32
- #include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
- #include <process.h>
- #include <malloc.h>
- #endif
- #include <ILevelSystem.h>
- #include <AzFramework/IO/LocalFileIO.h>
- // Define global cvars.
- SSystemCVars g_cvars;
- #include <AzCore/Module/Environment.h>
- #include <AzCore/Component/ComponentApplication.h>
- #include "AZCoreLogSink.h"
- namespace
- {
- float GetMovieFrameDeltaTime()
- {
- // Use GetRealTickDeltaTimeUs for CryMovie, because it should not be affected by pausing game time
- const AZ::TimeUs delta = AZ::GetRealTickDeltaTimeUs();
- return AZ::TimeUsToSeconds(delta);
- }
- }
- /////////////////////////////////////////////////////////////////////////////////
- // System Implementation.
- //////////////////////////////////////////////////////////////////////////
- CSystem::CSystem()
- {
- CrySystemRequestBus::Handler::BusConnect();
- m_systemGlobalState = ESYSTEM_GLOBAL_STATE_UNKNOWN;
- m_iHeight = 0;
- m_iWidth = 0;
- m_iColorBits = 0;
- // CRT ALLOCATION threshold
- m_bIsAsserting = false;
- m_pSystemEventDispatcher = new CSystemEventDispatcher(); // Must be first.
- if (m_pSystemEventDispatcher)
- {
- m_pSystemEventDispatcher->RegisterListener(this);
- }
- //////////////////////////////////////////////////////////////////////////
- // Clear environment.
- //////////////////////////////////////////////////////////////////////////
- memset(&m_env, 0, sizeof(m_env));
- //////////////////////////////////////////////////////////////////////////
- // Initialize global environment interface pointers.
- m_env.pSystem = this;
- m_env.bIgnoreAllAsserts = false;
- m_env.bNoAssertDialog = false;
- //////////////////////////////////////////////////////////////////////////
- m_sysNoUpdate = NULL;
- m_pCmdLine = NULL;
- m_pLevelSystem = NULL;
- m_pLocalizationManager = NULL;
- #if defined(AZ_RESTRICTED_PLATFORM)
- #define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_2
- #include AZ_RESTRICTED_FILE(System_cpp)
- #endif
- m_pUserCallback = NULL;
- m_sys_firstlaunch = NULL;
- m_gpu_particle_physics = NULL;
- m_bInitializedSuccessfully = false;
- m_bRelaunch = false;
- m_iLoadingMode = 0;
- m_bTestMode = false;
- m_bEditor = false;
- m_bPreviewMode = false;
- m_bIgnoreUpdates = false;
- m_bNoCrashDialog = false;
- m_bNoErrorReportWindow = false;
- m_bInDevMode = false;
- m_bGameFolderWritable = false;
- m_bPaused = false;
- m_bNoUpdate = false;
- m_iApplicationInstance = -1;
- m_pXMLUtils = new CXmlUtils(this);
- m_eRuntimeState = ESYSTEM_EVENT_LEVEL_UNLOAD;
- m_bHasRenderedErrorMessage = false;
- #if AZ_LEGACY_CRYSYSTEM_TRAIT_USE_MESSAGE_HANDLER
- RegisterWindowMessageHandler(this);
- #endif
- m_ConfigPlatform = CONFIG_INVALID_PLATFORM;
- m_movieSystem = AZ::Interface<IMovieSystem>::Get();
- }
- /////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////
- CSystem::~CSystem()
- {
- ShutDown();
- #if AZ_LEGACY_CRYSYSTEM_TRAIT_USE_MESSAGE_HANDLER
- UnregisterWindowMessageHandler(this);
- #endif
- CRY_ASSERT(m_windowMessageHandlers.empty() && "There exists a dangling window message handler somewhere");
- SAFE_DELETE(m_pXMLUtils);
- SAFE_DELETE(m_pSystemEventDispatcher);
- AZCoreLogSink::Disconnect();
- m_env.pSystem = 0;
- gEnv = 0;
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::Release()
- {
- delete this;
- }
- //////////////////////////////////////////////////////////////////////////
- IRemoteConsole* CSystem::GetIRemoteConsole()
- {
- return CRemoteConsole::GetInst();
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::SetDevMode(bool bEnable)
- {
- m_bInDevMode = bEnable;
- }
- ///////////////////////////////////////////////////
- void CSystem::ShutDown()
- {
- CryLogAlways("System Shutdown");
- // Disconnect any networking connections at the beginning of shutting down.
- // This needs to happen before unloading the level because the network connection might queue
- // references to entities and assets that could prevent cleanup from happening during the level unload.
- if (const auto console = AZ::Interface<AZ::IConsole>::Get())
- {
- console->PerformCommand("disconnect");
- }
- // On shutdown, we need to start by unloading the level spawnable and processing the spawnable queue
- // to clean up any remaining references. Otherwise, we'll get lots of errors on shutdown due to assets still
- // being in use as various subsystems get shut down. By the time the spawnable system shuts down, it will try
- // to clean up the assets, but the asset handlers for those assets will also be deregistered and destroyed by then,
- // causing even more errors.
- // By unloading the level before shutting down any subsystems, we can avoid the cascade of errors.
- ILevelSystem* levelSystem = GetILevelSystem();
- if (levelSystem)
- {
- levelSystem->UnloadLevel();
- if (auto spawnableInterface = AzFramework::RootSpawnableInterface::Get(); spawnableInterface)
- {
- spawnableInterface->ProcessSpawnableQueueUntilEmpty();
- }
- }
- // don't broadcast OnCrySystemShutdown unless
- // we'd previously broadcast OnCrySystemInitialized
- if (m_bInitializedSuccessfully)
- {
- EBUS_EVENT(CrySystemEventBus, OnCrySystemShutdown, *this);
- }
- if (m_pUserCallback)
- {
- m_pUserCallback->OnShutdown();
- }
- if (GetIRemoteConsole()->IsStarted())
- {
- GetIRemoteConsole()->Stop();
- }
- if (m_sys_firstlaunch)
- {
- m_sys_firstlaunch->Set("0");
- }
- if ((m_bEditor) && (m_env.pConsole))
- {
- // restore the old saved cvars
- if (m_env.pConsole->GetCVar("r_Width"))
- {
- m_env.pConsole->GetCVar("r_Width")->Set(m_iWidth);
- }
- if (m_env.pConsole->GetCVar("r_Height"))
- {
- m_env.pConsole->GetCVar("r_Height")->Set(m_iHeight);
- }
- if (m_env.pConsole->GetCVar("r_ColorBits"))
- {
- m_env.pConsole->GetCVar("r_ColorBits")->Set(m_iColorBits);
- }
- }
- if (m_bEditor && !m_bRelaunch)
- {
- SaveConfiguration();
- }
- // Dispatch the full-shutdown event in case this is not a fast-shutdown.
- if (m_pSystemEventDispatcher != NULL)
- {
- m_pSystemEventDispatcher->OnSystemEvent(ESYSTEM_EVENT_FULL_SHUTDOWN, 0, 0);
- }
- SAFE_RELEASE(m_env.pCryFont);
- if (m_env.pConsole)
- {
- ((CXConsole*)m_env.pConsole)->FreeRenderResources();
- }
- SAFE_RELEASE(m_pLevelSystem);
- if (m_env.pLog)
- {
- m_env.pLog->UnregisterConsoleVariables();
- }
- GetIRemoteConsole()->UnregisterConsoleVariables();
- // Release console variables.
- SAFE_RELEASE(m_sys_firstlaunch);
- #if defined(AZ_RESTRICTED_PLATFORM)
- #define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_3
- #include AZ_RESTRICTED_FILE(System_cpp)
- #endif
- SAFE_DELETE(m_pLocalizationManager);
- delete m_pCmdLine;
- m_pCmdLine = 0;
- // Audio System Shutdown!
- // Shut down audio as late as possible but before the streaming system and console get released!
- Audio::Gem::SystemRequestBus::Broadcast(&Audio::Gem::SystemRequestBus::Events::Release);
- // Shut down console as late as possible and after audio!
- SAFE_RELEASE(m_env.pConsole);
- // Log must be last thing released.
- if (m_env.pLog)
- {
- m_env.pLog->Flush();
- }
- SAFE_RELEASE(m_env.pLog); // creates log backup
- ShutdownFileSystem();
- EBUS_EVENT(CrySystemEventBus, OnCrySystemPostShutdown);
- }
- /////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////
- void CSystem::Quit()
- {
- CryLogAlways("CSystem::Quit invoked from thread %" PRI_THREADID " (main is %" PRI_THREADID ")", GetCurrentThreadId(), gEnv->mMainThreadId);
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
- // If this was set from anywhere but the main thread, bail and let the main thread handle shutdown
- if (GetCurrentThreadId() != gEnv->mMainThreadId)
- {
- return;
- }
- if (m_pUserCallback)
- {
- m_pUserCallback->OnQuit();
- }
- gEnv->pLog->Flush();
- #ifdef WIN32
- //Post a WM_QUIT message to the Win32 api which causes the message loop to END
- //This is not the same as handling a WM_DESTROY event which destroys a window
- //but keeps the message loop alive.
- PostQuitMessage(0);
- #endif
- }
- /////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////
- bool CSystem::IsQuitting() const
- {
- bool wasExitMainLoopRequested = false;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(wasExitMainLoopRequested, &AzFramework::ApplicationRequests::WasExitMainLoopRequested);
- return wasExitMainLoopRequested;
- }
- //////////////////////////////////////////////////////////////////////////
- ISystem* CSystem::GetCrySystem()
- {
- return this;
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::SleepIfNeeded()
- {
- static bool firstCall = true;
- typedef MiniQueue<CTimeValue, 32> PrevNow;
- static PrevNow prevNow;
- if (firstCall)
- {
- const AZ::TimeMs timeMs = AZ::GetRealElapsedTimeMs();
- const double timeSec = AZ::TimeMsToSecondsDouble(timeMs);
- m_lastTickTime = CTimeValue(timeSec);
- prevNow.Push(m_lastTickTime);
- firstCall = false;
- return;
- }
- const float maxRate = m_svDedicatedMaxRate->GetFVal();
- const float minTime = 1.0f / maxRate;
- const AZ::TimeMs nowTimeMs = AZ::GetRealElapsedTimeMs();
- const double nowTimeSec = AZ::TimeMsToSecondsDouble(nowTimeMs);
- const CTimeValue now = CTimeValue(nowTimeSec);
- const float elapsed = (now - m_lastTickTime).GetSeconds();
- if (prevNow.Full())
- {
- prevNow.Pop();
- }
- prevNow.Push(now);
- static bool allowStallCatchup = true;
- if (elapsed > minTime && allowStallCatchup)
- {
- allowStallCatchup = false;
- const AZ::TimeMs lastTimeMs = AZ::GetRealElapsedTimeMs();
- const double lastTimeSec = AZ::TimeMsToSecondsDouble(lastTimeMs);
- m_lastTickTime = CTimeValue(lastTimeSec);
- return;
- }
- allowStallCatchup = true;
- float totalElapsed = (now - prevNow.Front()).GetSeconds();
- float wantSleepTime = AZStd::clamp(minTime * (prevNow.Size() - 1) - totalElapsed, 0.0f, (minTime - elapsed) * 0.9f);
- static float sleepTime = 0;
- sleepTime = (15 * sleepTime + wantSleepTime) / 16;
- int sleepMS = (int)(1000.0f * sleepTime + 0.5f);
- if (sleepMS > 0)
- {
- AZ_PROFILE_FUNCTION(CrySystem);
- Sleep(sleepMS);
- }
- const AZ::TimeMs lastTimeMs = AZ::GetRealElapsedTimeMs();
- const double lastTimeSec = AZ::TimeMsToSecondsDouble(lastTimeMs);
- m_lastTickTime = CTimeValue(lastTimeSec);
- }
- extern DWORD g_idDebugThreads[];
- extern int g_nDebugThreads;
- int prev_sys_float_exceptions = -1;
- //////////////////////////////////////////////////////////////////////
- bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
- {
- // If we detect the quit flag at the start of Update, that means it was set
- // from another thread, and we should quit immediately. Otherwise, it will
- // be set by game logic or the console during Update and we will quit later
- if (IsQuitting())
- {
- Quit();
- return false;
- }
- #ifndef EXCLUDE_UPDATE_ON_CONSOLE
- // do the dedicated sleep earlier than the frame profiler to avoid having it counted
- if (gEnv->IsDedicated())
- {
- SleepIfNeeded();
- }
- #endif //EXCLUDE_UPDATE_ON_CONSOLE
- #ifdef WIN32
- // enable/disable SSE fp exceptions (#nan and /0)
- // need to do it each frame since sometimes they are being reset
- _mm_setcsr(_mm_getcsr() & ~0x280 | (g_cvars.sys_float_exceptions > 0 ? 0 : 0x280));
- #endif //WIN32
- AZ_PROFILE_FUNCTION(CrySystem);
- #ifndef EXCLUDE_UPDATE_ON_CONSOLE
- if (m_pUserCallback)
- {
- m_pUserCallback->OnUpdate();
- }
- //////////////////////////////////////////////////////////////////////////
- // Enable/Disable floating exceptions.
- //////////////////////////////////////////////////////////////////////////
- prev_sys_float_exceptions += 1 + g_cvars.sys_float_exceptions & prev_sys_float_exceptions >> 31;
- if (prev_sys_float_exceptions != g_cvars.sys_float_exceptions)
- {
- prev_sys_float_exceptions = g_cvars.sys_float_exceptions;
- EnableFloatExceptions(g_cvars.sys_float_exceptions);
- }
- #endif //EXCLUDE_UPDATE_ON_CONSOLE
- //////////////////////////////////////////////////////////////////////////
- if (m_env.pLog)
- {
- m_env.pLog->Update();
- }
- #ifdef USE_REMOTE_CONSOLE
- GetIRemoteConsole()->Update();
- #endif
- if (nPauseMode != 0)
- {
- m_bPaused = true;
- }
- else
- {
- m_bPaused = false;
- }
- #ifndef EXCLUDE_UPDATE_ON_CONSOLE
- if (m_bIgnoreUpdates)
- {
- return true;
- }
- #endif //EXCLUDE_UPDATE_ON_CONSOLE
- //static bool sbPause = false;
- //bool bPause = false;
- bool bNoUpdate = false;
- #ifndef EXCLUDE_UPDATE_ON_CONSOLE
- if (m_sysNoUpdate && m_sysNoUpdate->GetIVal())
- {
- bNoUpdate = true;
- }
- m_bNoUpdate = bNoUpdate;
- #endif //EXCLUDE_UPDATE_ON_CONSOLE
- //check if we are quitting from the game
- if (IsQuitting())
- {
- Quit();
- return (false);
- }
- //limit frame rate if vsync is turned off
- //for consoles this is done inside renderthread to be vsync dependent
- {
- static ICVar* pSysMaxFPS = NULL;
- static ICVar* pVSync = NULL;
- if (pSysMaxFPS == NULL && gEnv && gEnv->pConsole)
- {
- pSysMaxFPS = gEnv->pConsole->GetCVar("sys_MaxFPS");
- }
- if (pVSync == NULL && gEnv && gEnv->pConsole)
- {
- pVSync = gEnv->pConsole->GetCVar("vsync_interval");
- }
- if (pSysMaxFPS && pVSync)
- {
- int32 maxFPS = pSysMaxFPS->GetIVal();
- uint32 vSync = pVSync->GetIVal();
- if (maxFPS == 0 && vSync == 0)
- {
- ILevelSystem* pLvlSys = GetILevelSystem();
- const bool inLevel = pLvlSys && pLvlSys->IsLevelLoaded();
- maxFPS = !inLevel || IsPaused() ? 60 : 0;
- }
- if (maxFPS > 0 && vSync == 0)
- {
- const float safeMarginFPS = 0.5f;//save margin to not drop below 30 fps
- static AZ::TimeMs sTimeLast = AZ::GetRealElapsedTimeMs();
- const AZ::TimeMs timeFrameMax(static_cast<AZ::TimeMs>(
- (int64)(1000.f / ((float)maxFPS + safeMarginFPS))
- ));
- const AZ::TimeMs timeLast = timeFrameMax + sTimeLast;
- while (timeLast > AZ::GetRealElapsedTimeMs())
- {
- CrySleep(0);
- }
- sTimeLast = AZ::GetRealElapsedTimeMs();
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- //update console system
- if (m_env.pConsole)
- {
- m_env.pConsole->Update();
- }
- if (IsQuitting())
- {
- Quit();
- return false;
- }
- // Run movie system pre-update
- if (!bNoUpdate)
- {
- UpdateMovieSystem(updateFlags, GetMovieFrameDeltaTime(), true);
- }
- return !IsQuitting();
- }
- //////////////////////////////////////////////////////////////////////
- bool CSystem::UpdatePostTickBus(int updateFlags, int /*nPauseMode*/)
- {
- const AZ::TimeMs updateStartTimeMs = AZ::GetRealElapsedTimeMs();
- const double updateStartTimeSec = AZ::TimeMsToSecondsDouble(updateStartTimeMs);
- const CTimeValue updateStart(updateStartTimeSec);
- // Run movie system post-update
- if (!m_bNoUpdate)
- {
- UpdateMovieSystem(updateFlags, GetMovieFrameDeltaTime(), false);
- }
- //////////////////////////////////////////////////////////////////////
- // Update sound system
- if (!m_bNoUpdate)
- {
- UpdateAudioSystems();
- }
- //Now update frame statistics
- const AZ::TimeMs curTimeMs = AZ::GetRealElapsedTimeMs();
- const double curTimeSec = AZ::TimeMsToSecondsDouble(curTimeMs);
- const CTimeValue cur_time(curTimeSec);
- CTimeValue a_second(g_cvars.sys_update_profile_time);
- std::vector< std::pair<CTimeValue, float> >::iterator it = m_updateTimes.begin();
- for (std::vector< std::pair<CTimeValue, float> >::iterator eit = m_updateTimes.end(); it != eit; ++it)
- {
- if ((cur_time - it->first) < a_second)
- {
- break;
- }
- }
- {
- if (it != m_updateTimes.begin())
- {
- m_updateTimes.erase(m_updateTimes.begin(), it);
- }
- float updateTime = (cur_time - updateStart).GetMilliSeconds();
- m_updateTimes.push_back(std::make_pair(cur_time, updateTime));
- }
- m_pSystemEventDispatcher->Update();
- if (!gEnv->IsEditing() && m_eRuntimeState == ESYSTEM_EVENT_LEVEL_GAMEPLAY_START)
- {
- gEnv->pCryPak->DisableRuntimeFileAccess(true);
- }
- // Also broadcast for anyone else that needs to draw global debug to do so now
- AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
- return !IsQuitting();
- }
- bool CSystem::UpdateLoadtime()
- {
- return !IsQuitting();
- }
- void CSystem::UpdateAudioSystems()
- {
- if (auto audioSystem = AZ::Interface<Audio::IAudioSystem>::Get(); audioSystem != nullptr)
- {
- audioSystem->ExternalUpdate();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::GetUpdateStats(SSystemUpdateStats& stats)
- {
- if (m_updateTimes.empty())
- {
- stats = SSystemUpdateStats();
- }
- else
- {
- stats.avgUpdateTime = 0;
- stats.maxUpdateTime = -FLT_MAX;
- stats.minUpdateTime = +FLT_MAX;
- for (std::vector< std::pair<CTimeValue, float> >::const_iterator it = m_updateTimes.begin(), eit = m_updateTimes.end(); it != eit; ++it)
- {
- const float t = it->second;
- stats.avgUpdateTime += t;
- stats.maxUpdateTime = max(stats.maxUpdateTime, t);
- stats.minUpdateTime = min(stats.minUpdateTime, t);
- }
- stats.avgUpdateTime /= m_updateTimes.size();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::UpdateMovieSystem(const int updateFlags, const float fFrameTime, const bool bPreUpdate)
- {
- if (!m_movieSystem)
- {
- m_movieSystem = AZ::Interface<IMovieSystem>::Get();
- }
- if (m_movieSystem && !(updateFlags & ESYSUPDATE_EDITOR) && g_cvars.sys_trackview)
- {
- float fMovieFrameTime = fFrameTime;
- if (fMovieFrameTime > g_cvars.sys_maxTimeStepForMovieSystem)
- {
- fMovieFrameTime = g_cvars.sys_maxTimeStepForMovieSystem;
- }
- if (bPreUpdate)
- {
- m_movieSystem->PreUpdate(fMovieFrameTime);
- }
- else
- {
- m_movieSystem->PostUpdate(fMovieFrameTime);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // XML stuff
- //////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef CSystem::CreateXmlNode(const char* sNodeName, bool bReuseStrings, bool bIsProcessingInstruction)
- {
- return new CXmlNode(sNodeName, bReuseStrings, bIsProcessingInstruction);
- }
- //////////////////////////////////////////////////////////////////////////
- IXmlUtils* CSystem::GetXmlUtils()
- {
- return m_pXMLUtils;
- }
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef CSystem::LoadXmlFromFile(const char* sFilename, bool bReuseStrings)
- {
- return m_pXMLUtils->LoadXmlFromFile(sFilename, bReuseStrings);
- }
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef CSystem::LoadXmlFromBuffer(const char* buffer, size_t size, bool bReuseStrings, bool bSuppressWarnings)
- {
- return m_pXMLUtils->LoadXmlFromBuffer(buffer, size, bReuseStrings, bSuppressWarnings);
- }
- //////////////////////////////////////////////////////////////////////////
- bool CSystem::CheckLogVerbosity(int verbosity)
- {
- if (verbosity <= m_env.pLog->GetVerbosityLevel())
- {
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::Warning(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, ...)
- {
- va_list args;
- va_start(args, format);
- WarningV(module, severity, flags, file, format, args);
- va_end(args);
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::ShowMessage(const char* text, const char* caption, unsigned int uType)
- {
- if (m_pUserCallback)
- {
- m_pUserCallback->ShowMessage(text, caption, uType);
- }
- else
- {
- CryMessageBox(text, caption, uType);
- }
- }
- inline const char* ValidatorModuleToString(EValidatorModule module)
- {
- switch (module)
- {
- case VALIDATOR_MODULE_RENDERER:
- return "Renderer";
- case VALIDATOR_MODULE_3DENGINE:
- return "3DEngine";
- case VALIDATOR_MODULE_ASSETS:
- return "Assets";
- case VALIDATOR_MODULE_SYSTEM:
- return "System";
- case VALIDATOR_MODULE_AUDIO:
- return "Audio";
- case VALIDATOR_MODULE_MOVIE:
- return "Movie";
- case VALIDATOR_MODULE_EDITOR:
- return "Editor";
- case VALIDATOR_MODULE_NETWORK:
- return "Network";
- case VALIDATOR_MODULE_PHYSICS:
- return "Physics";
- case VALIDATOR_MODULE_ONLINE:
- return "Online";
- case VALIDATOR_MODULE_FEATURETESTS:
- return "FeatureTests";
- case VALIDATOR_MODULE_SHINE:
- return "UI";
- }
- return "";
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::WarningV(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, va_list args)
- {
- // Fran: No logging in a testing environment
- if (m_env.pLog == 0)
- {
- return;
- }
- const char* sModuleFilter = m_env.pLog->GetModuleFilter();
- if (sModuleFilter && *sModuleFilter != 0)
- {
- const char* sModule = ValidatorModuleToString(module);
- if (strlen(sModule) > 1 || AZ::StringFunc::Find(sModule, sModuleFilter) == AZStd::string::npos)
- {
- // Filter out warnings from other modules.
- return;
- }
- }
- bool bDbgBreak = false;
- if (severity == VALIDATOR_ERROR_DBGBRK)
- {
- bDbgBreak = true;
- severity = VALIDATOR_ERROR; // change it to a standard VALIDATOR_ERROR for simplicity in the rest of the system
- }
- IMiniLog::ELogType ltype = ILog::eComment;
- switch (severity)
- {
- case VALIDATOR_ERROR:
- ltype = ILog::eError;
- break;
- case VALIDATOR_WARNING:
- ltype = ILog::eWarning;
- break;
- case VALIDATOR_COMMENT:
- ltype = ILog::eComment;
- break;
- default:
- break;
- }
- AZStd::fixed_string<MAX_WARNING_LENGTH> fmt;
- vsnprintf_s(fmt.data(), MAX_WARNING_LENGTH, MAX_WARNING_LENGTH - 1, format, args);
- if (file && *file)
- {
- fmt += " [File=";
- fmt += file;
- fmt += "]";
- }
- m_env.pLog->LogWithType(ltype, flags | VALIDATOR_FLAG_SKIP_VALIDATOR, "%s", fmt.c_str());
- if (bDbgBreak && g_cvars.sys_error_debugbreak)
- {
- AZ::Debug::Trace::Instance().Break();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::GetLocalizedPath(const char* sLanguage, AZStd::string& sLocalizedPath)
- {
- // Omit the trailing slash!
- AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
- sLocalizationFolder.pop_back();
- int locFormat = 0;
- LocalizationManagerRequestBus::BroadcastResult(locFormat, &LocalizationManagerRequestBus::Events::GetLocalizationFormat);
- if(locFormat == 1)
- {
- sLocalizedPath = sLocalizationFolder + "/" + sLanguage + ".loc.agsxml";
- }
- else
- {
- if (AZ::StringFunc::Equal(sLocalizationFolder, "Languages", false))
- {
- sLocalizedPath = sLocalizationFolder + "/" + sLanguage + "_xml.pak";
- }
- else
- {
- sLocalizedPath = AZStd::string("Localized/") + sLanguage + "_xml.pak";
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::GetLocalizedAudioPath(const char* sLanguage, AZStd::string& sLocalizedPath)
- {
- // Omit the trailing slash!
- AZStd::string sLocalizationFolder(PathUtil::GetLocalizationFolder());
- sLocalizationFolder.pop_back();
- if (AZ::StringFunc::Equal(sLocalizationFolder, "Languages", false))
- {
- sLocalizedPath = sLocalizationFolder + "/" + sLanguage + ".pak";
- }
- else
- {
- sLocalizedPath = AZStd::string("Localized/") + sLanguage + ".pak";
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::CloseLanguagePak(const char* sLanguage)
- {
- AZStd::string sLocalizedPath;
- GetLocalizedPath(sLanguage, sLocalizedPath);
- m_env.pCryPak->ClosePacks({ sLocalizedPath.c_str(), sLocalizedPath.size() });
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::CloseLanguageAudioPak(const char* sLanguage)
- {
- AZStd::string sLocalizedPath;
- GetLocalizedAudioPath(sLanguage, sLocalizedPath);
- m_env.pCryPak->ClosePacks({ sLocalizedPath.c_str(), sLocalizedPath.size() });
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::Relaunch(bool bRelaunch)
- {
- if (m_sys_firstlaunch)
- {
- m_sys_firstlaunch->Set("0");
- }
- m_bRelaunch = bRelaunch;
- SaveConfiguration();
- }
- //////////////////////////////////////////////////////////////////////////
- ILocalizationManager* CSystem::GetLocalizationManager()
- {
- return m_pLocalizationManager;
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::ExecuteCommandLine(bool deferred)
- {
- if (m_executedCommandLine)
- {
- return;
- }
- m_executedCommandLine = true;
- // execute command line arguments e.g. +g_gametype ASSAULT +LoadLevel "testy"
- ICmdLine* pCmdLine = GetICmdLine();
- assert(pCmdLine);
- const int iCnt = pCmdLine->GetArgCount();
- for (int i = 0; i < iCnt; ++i)
- {
- const ICmdLineArg* pCmd = pCmdLine->GetArg(i);
- if (pCmd->GetType() == eCLAT_Post)
- {
- AZStd::string sLine = pCmd->GetName();
- {
- if (pCmd->GetValue())
- {
- sLine += AZStd::string(" ") + pCmd->GetValue();
- }
- GetILog()->Log("Executing command from command line: \n%s\n", sLine.c_str()); // - the actual command might be executed much later (e.g. level load pause)
- GetIConsole()->ExecuteString(sLine.c_str(), false, deferred);
- }
- }
- }
- //gEnv->pConsole->ExecuteString("sys_RestoreSpec test*"); // to get useful debugging information about current spec settings to the log file
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::SetConfigPlatform(const ESystemConfigPlatform platform)
- {
- m_ConfigPlatform = platform;
- }
- //////////////////////////////////////////////////////////////////////////
- ESystemConfigPlatform CSystem::GetConfigPlatform() const
- {
- return m_ConfigPlatform;
- }
- //////////////////////////////////////////////////////////////////////
- void CSystem::OnLanguageCVarChanged(ICVar* language)
- {
- if (language && language->GetType() == CVAR_STRING)
- {
- CSystem* pSys = static_cast<CSystem*>(gEnv->pSystem);
- if (pSys && pSys->GetLocalizationManager())
- {
- const char* lang = language->GetString();
- // Hook up Localization initialization
- int locFormat = 0;
- LocalizationManagerRequestBus::BroadcastResult(locFormat, &LocalizationManagerRequestBus::Events::GetLocalizationFormat);
- if (locFormat == 0)
- {
- const char* locLanguage = nullptr;
- LocalizationManagerRequestBus::BroadcastResult(locLanguage, &LocalizationManagerRequestBus::Events::GetLanguage);
- pSys->OpenLanguagePak(lang);
- }
- LocalizationManagerRequestBus::Broadcast(&LocalizationManagerRequestBus::Events::SetLanguage, lang);
- LocalizationManagerRequestBus::Broadcast(&LocalizationManagerRequestBus::Events::ReloadData);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::OnLocalizationFolderCVarChanged(ICVar* const pLocalizationFolder)
- {
- if (pLocalizationFolder && pLocalizationFolder->GetType() == CVAR_STRING)
- {
- CSystem* const pSystem = static_cast<CSystem* const>(gEnv->pSystem);
- if (pSystem != NULL && gEnv->pCryPak != NULL)
- {
- CLocalizedStringsManager* const pLocalizationManager = static_cast<CLocalizedStringsManager* const>(pSystem->GetLocalizationManager());
- if (pLocalizationManager)
- {
- // Get what is currently loaded
- CLocalizedStringsManager::TLocalizationTagVec tagVec;
- pLocalizationManager->GetLoadedTags(tagVec);
- // Release the old localization data.
- CLocalizedStringsManager::TLocalizationTagVec::const_iterator end = tagVec.end();
- for (CLocalizedStringsManager::TLocalizationTagVec::const_iterator it = tagVec.begin(); it != end; ++it)
- {
- pLocalizationManager->ReleaseLocalizationDataByTag(it->c_str());
- }
- // Close the paks situated in the previous localization folder.
- pSystem->CloseLanguagePak(pLocalizationManager->GetLanguage());
- pSystem->CloseLanguageAudioPak(pSystem->m_currentLanguageAudio.c_str());
- // Set the new localization folder.
- gEnv->pCryPak->SetLocalizationFolder(pLocalizationFolder->GetString());
- // Now open the paks situated in the new localization folder.
- pSystem->OpenLanguagePak(pLocalizationManager->GetLanguage());
- pSystem->OpenLanguageAudioPak(pSystem->m_currentLanguageAudio.c_str());
- // And load the new data.
- for (CLocalizedStringsManager::TLocalizationTagVec::const_iterator it = tagVec.begin(); it != end; ++it)
- {
- pLocalizationManager->LoadLocalizationDataByTag(it->c_str());
- }
- }
- }
- }
- }
- // Catch changes to assert verbosity and update the global used to track it
- void CSystem::SetAssertLevel(int _assertlevel)
- {
- AZ::EnvironmentVariable<int> assertVerbosityLevel = AZ::Environment::FindVariable<int>("assertVerbosityLevel");
- if (assertVerbosityLevel)
- {
- assertVerbosityLevel.Set(_assertlevel);
- }
- }
- void CSystem::OnAssertLevelCvarChanged(ICVar* pArgs)
- {
- SetAssertLevel(pArgs->GetIVal());
- }
- void CSystem::SetLogLevel(int _loglevel)
- {
- AZ::EnvironmentVariable<int> logVerbosityLevel = AZ::Environment::FindVariable<int>("sys_LogLevel");
- if (logVerbosityLevel.IsConstructed())
- {
- logVerbosityLevel.Set(_loglevel);
- }
- }
- void CSystem::OnLogLevelCvarChanged(ICVar* pArgs)
- {
- if (pArgs)
- {
- SetLogLevel(pArgs->GetIVal());
- }
- }
- void CSystem::OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
- {
- switch (event)
- {
- case ESYSTEM_EVENT_LEVEL_LOAD_START_LOADINGSCREEN:
- case ESYSTEM_EVENT_LEVEL_UNLOAD:
- gEnv->pCryPak->DisableRuntimeFileAccess(false);
- case ESYSTEM_EVENT_LEVEL_GAMEPLAY_START:
- m_eRuntimeState = event;
- break;
- }
- }
- ESystemGlobalState CSystem::GetSystemGlobalState(void)
- {
- return m_systemGlobalState;
- }
- const char* CSystem::GetSystemGlobalStateName(const ESystemGlobalState systemGlobalState)
- {
- static const char* const s_systemGlobalStateNames[] = {
- "UNKNOWN", // ESYSTEM_GLOBAL_STATE_UNKNOWN,
- "INIT", // ESYSTEM_GLOBAL_STATE_INIT,
- "RUNNING", // ESYSTEM_GLOBAL_STATE_RUNNING,
- "LEVEL_LOAD_PREPARE", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PREPARE,
- "LEVEL_LOAD_START", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START,
- "LEVEL_LOAD_MATERIALS", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_MATERIALS,
- "LEVEL_LOAD_OBJECTS", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_OBJECTS,
- "LEVEL_LOAD_STATIC_WORLD", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_STATIC_WORLD,
- "LEVEL_LOAD_PRECACHE", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PRECACHE,
- "LEVEL_LOAD_TEXTURES", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_TEXTURES,
- "LEVEL_LOAD_END", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_END,
- "LEVEL_LOAD_COMPLETE" // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_COMPLETE
- };
- const size_t numElements = sizeof(s_systemGlobalStateNames) / sizeof(s_systemGlobalStateNames[0]);
- const size_t index = (size_t)systemGlobalState;
- if (index >= numElements)
- {
- return "INVALID INDEX";
- }
- return s_systemGlobalStateNames[index];
- }
- void CSystem::SetSystemGlobalState(const ESystemGlobalState systemGlobalState)
- {
- static AZ::TimeMs s_startTime = AZ::Time::ZeroTimeMs;
- if (systemGlobalState != m_systemGlobalState)
- {
- const AZ::TimeMs endTime = AZ::GetRealElapsedTimeMs();
- [[maybe_unused]] const double numSeconds = AZ::TimeMsToSecondsDouble(endTime - s_startTime);
- CryLog("SetGlobalState %d->%d '%s'->'%s' %3.1f seconds",
- m_systemGlobalState, systemGlobalState,
- CSystem::GetSystemGlobalStateName(m_systemGlobalState), CSystem::GetSystemGlobalStateName(systemGlobalState),
- numSeconds);
- s_startTime = AZ::GetRealElapsedTimeMs();
- }
- m_systemGlobalState = systemGlobalState;
- #if AZ_LOADSCREENCOMPONENT_ENABLED
- if (m_systemGlobalState == ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_COMPLETE)
- {
- EBUS_EVENT(LoadScreenBus, Stop);
- }
- #endif // if AZ_LOADSCREENCOMPONENT_ENABLED
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::RegisterWindowMessageHandler(IWindowMessageHandler* pHandler)
- {
- #if AZ_LEGACY_CRYSYSTEM_TRAIT_USE_MESSAGE_HANDLER
- assert(pHandler && !stl::find(m_windowMessageHandlers, pHandler) && "This IWindowMessageHandler is already registered");
- m_windowMessageHandlers.push_back(pHandler);
- #else
- CRY_ASSERT(false && "This platform does not support window message handlers");
- #endif
- }
- //////////////////////////////////////////////////////////////////////////
- void CSystem::UnregisterWindowMessageHandler(IWindowMessageHandler* pHandler)
- {
- #if AZ_LEGACY_CRYSYSTEM_TRAIT_USE_MESSAGE_HANDLER
- [[maybe_unused]] bool bRemoved = stl::find_and_erase(m_windowMessageHandlers, pHandler);
- assert(pHandler && bRemoved && "This IWindowMessageHandler was not registered");
- #else
- CRY_ASSERT(false && "This platform does not support window message handlers");
- #endif
- }
- //////////////////////////////////////////////////////////////////////////
- #if defined(WIN32)
- bool CSystem::HandleMessage([[maybe_unused]] HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- static bool sbInSizingModalLoop;
- int x = LOWORD(lParam);
- int y = HIWORD(lParam);
- *pResult = 0;
- switch (uMsg)
- {
- // System event translation
- case WM_CLOSE:
- /*
- Trigger CSystem to call Quit() the next time
- it calls Update(). HandleMessages can get messages
- pumped to it from SyncMainWithRender which would
- be called recurively by Quit(). Doing so would
- cause the render thread to deadlock and the main
- thread to spin in SRenderThread::WaitFlushFinishedCond.
- */
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
- return false;
- case WM_MOVE:
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_MOVE, x, y);
- return false;
- case WM_SIZE:
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_RESIZE, x, y);
- switch (wParam)
- {
- case SIZE_MINIMIZED:
- EBUS_EVENT(AzFramework::WindowsLifecycleEvents::Bus, OnMinimized);
- break;
- case SIZE_MAXIMIZED:
- EBUS_EVENT(AzFramework::WindowsLifecycleEvents::Bus, OnMaximized);
- break;
- case SIZE_RESTORED:
- EBUS_EVENT(AzFramework::WindowsLifecycleEvents::Bus, OnRestored);
- break;
- }
- return false;
- case WM_WINDOWPOSCHANGED:
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_POS_CHANGED, 1, 0);
- return false;
- case WM_STYLECHANGED:
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_STYLE_CHANGED, 1, 0);
- return false;
- case WM_ACTIVATE:
- // Pass HIWORD(wParam) as well to indicate whether this window is minimized or not
- // HIWORD(wParam) != 0 is minimized, HIWORD(wParam) == 0 is not minimized
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_ACTIVATE, LOWORD(wParam) != WA_INACTIVE, HIWORD(wParam));
- return true;
- case WM_SETFOCUS:
- EBUS_EVENT(AzFramework::WindowsLifecycleEvents::Bus, OnSetFocus);
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_CHANGE_FOCUS, 1, 0);
- return false;
- case WM_KILLFOCUS:
- EBUS_EVENT(AzFramework::WindowsLifecycleEvents::Bus, OnKillFocus);
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_CHANGE_FOCUS, 0, 0);
- return false;
- case WM_INPUTLANGCHANGE:
- GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LANGUAGE_CHANGE, wParam, lParam);
- return false;
- case WM_SYSCOMMAND:
- if ((wParam & 0xFFF0) == SC_SCREENSAVE)
- {
- // Check if screen saver is allowed
- IConsole* const pConsole = gEnv->pConsole;
- const ICVar* const pVar = pConsole ? pConsole->GetCVar("sys_screensaver_allowed") : 0;
- return pVar && pVar->GetIVal() == 0;
- }
- return false;
- // Mouse activation
- case WM_MOUSEACTIVATE:
- *pResult = MA_ACTIVATEANDEAT;
- return true;
- // Hardware mouse counters
- case WM_ENTERSIZEMOVE:
- sbInSizingModalLoop = true;
- // Fall through intended
- case WM_ENTERMENULOOP:
- {
- return true;
- }
- case WM_CAPTURECHANGED:
- // If WM_CAPTURECHANGED is received after WM_ENTERSIZEMOVE (ie, moving/resizing begins).
- // but no matching WM_EXITSIZEMOVE is received (this can happen if the window is not actually moved).
- // we still need to decrement the hardware mouse counter that was incremented when WM_ENTERSIZEMOVE was seen.
- // So in this case, we effectively treat WM_CAPTURECHANGED as if it was the WM_EXITSIZEMOVE message.
- // This behavior has only been reproduced the window is deactivated during the modal loop (ie, breakpoint triggered and focus moves to VS).
- case WM_EXITSIZEMOVE:
- if (!sbInSizingModalLoop)
- {
- return false;
- }
- sbInSizingModalLoop = false;
- // Fall through intended
- case WM_EXITMENULOOP:
- {
- return (uMsg != WM_CAPTURECHANGED);
- }
- case WM_SYSKEYUP:
- case WM_SYSKEYDOWN:
- {
- const bool bAlt = (lParam & (1 << 29)) != 0;
- if (bAlt && wParam == VK_F4)
- {
- return false; // Pass though ALT+F4
- }
- // Prevent game from entering menu loop! Editor does allow menu loop.
- return !m_bEditor;
- }
- case WM_INPUT:
- {
- UINT rawInputSize;
- const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize);
- AZStd::array<BYTE, sizeof(RAWINPUT)> rawInputBytesArray;
- LPBYTE rawInputBytes = rawInputBytesArray.data();
- [[maybe_unused]] const UINT bytesCopied = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize);
- CRY_ASSERT(bytesCopied == rawInputSize);
- [[maybe_unused]] RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes;
- CRY_ASSERT(rawInput);
- AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput);
- return false;
- }
- case WM_DEVICECHANGE:
- {
- if (wParam == 0x0007) // DBT_DEVNODES_CHANGED
- {
- AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent);
- }
- return true;
- }
- case WM_CHAR:
- {
- const unsigned short codeUnitUTF16 = static_cast<unsigned short>(wParam);
- AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputCodeUnitUTF16Event, codeUnitUTF16);
- return true;
- }
- // Any other event doesn't interest us
- default:
- return false;
- }
- }
- #endif
- ILevelSystem* CSystem::GetILevelSystem()
- {
- return m_pLevelSystem;
- }
- #undef EXCLUDE_UPDATE_ON_CONSOLE
|