1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
6 //#include "ini_vars.h"
7 #include <CryCore/Platform/CryLibrary.h>
9 #if defined(_RELEASE) && CRY_PLATFORM_DURANGO //note: check if orbis needs this
10 //exclude some not needed functionality for release console builds
11 #define EXCLUDE_UPDATE_ON_CONSOLE
14 #if CRY_PLATFORM_LINUX
15 #include <execinfo.h> // for backtrace
18 #if CRY_PLATFORM_ANDROID
19 #include <unwind.h> // for _Unwind_Backtrace and _Unwind_GetIP
22 #include <CryNetwork/INetwork.h>
23 #include <Cry3DEngine/I3DEngine.h>
24 #include <CryAISystem/IAISystem.h>
25 #include <CryRenderer/IRenderer.h>
26 #include <CrySystem/File/ICryPak.h>
27 #include <CryMovie/IMovieSystem.h>
28 #include <ServiceNetwork.h>
29 #include <CryEntitySystem/IEntitySystem.h>
30 #include <CryInput/IInput.h>
31 #include <CrySystem/ILog.h>
32 #include <CryAudio/IAudioSystem.h>
33 #include <CryAnimation/ICryAnimation.h>
34 #include <CryScriptSystem/IScriptSystem.h>
35 #include <CrySystem/IProcess.h>
36 #include <CrySystem/IBudgetingSystem.h>
37 #include <CryGame/IGameFramework.h>
38 #include <CryNetwork/INotificationNetwork.h>
39 #include <CrySystem/ICodeCheckpointMgr.h>
40 #include <CrySystem/Profilers/IStatoscope.h>
42 #include "TestSystem.h"
44 #include "VisRegTest.h"
45 #include <CryDynamicResponseSystem/IDynamicResponseSystem.h>
46 #include <Cry3DEngine/ITimeOfDay.h>
47 #include <CryMono/IMonoRuntime.h>
48 #include <CrySchematyc/ICore.h>
49 #include <CrySchematyc2/IFramework.h>
53 #include "CrySizerStats.h"
54 #include "CrySizerImpl.h"
55 #include "NotificationNetwork.h"
56 #include <CryString/CryPath.h>
59 #include "XML/ReadWriteXMLSink.h"
61 #include "StreamEngine/StreamEngine.h"
62 #include "PhysRenderer.h"
64 #include "LocalizedStringManager.h"
65 #include "XML/XmlUtils.h"
66 #include "Serialization/ArchiveHost.h"
67 #include <CrySystem/Profilers/IDiskProfiler.h>
68 #include "SystemEventDispatcher.h"
69 #include "HardwareMouse.h"
70 #include "ServerThrottle.h"
71 #include <CryMemory/ILocalMemoryUsage.h>
72 #include "ResourceManager.h"
73 #include "MemoryManager.h"
74 #include <CryLiveCreate/ILiveCreateHost.h>
75 #include <CryLiveCreate/ILiveCreateManager.h>
76 #include "OverloadSceneManager/OverloadSceneManager.h"
77 #include <CryThreading/IThreadManager.h>
78 #include <CryReflection/IModule.h>
79 #include <CryUDR/InterfaceIncludes.h>
81 #include <CrySystem/ZLib/IZLibCompressor.h>
82 #include <CrySystem/ZLib/IZlibDecompressor.h>
83 #include <CrySystem/ZLib/ILZ4Decompressor.h>
85 #include "RemoteConsole/RemoteConsole.h"
86 #include "ImeManager.h"
87 #include "BootProfiler.h"
89 # include <Cry_Brofiler.h>
90 # include "Profiling/CryBrofiler.h"
92 #include "Profiling/PlatformProfiler.h"
93 #include "Profiling/ProfilingRenderer.h"
94 #include "Profiling/CryProfilingSystem.h"
96 #include "NullImplementation/NULLAudioSystems.h"
97 #include "NullImplementation/NULLRenderAuxGeom.h"
99 #include <CryMath/PNoise3.h>
100 #include <CryString/StringUtils.h>
101 #include <CrySystem/Scaleform/IFlashUI.h>
102 #include "CryWaterMark.h"
104 #include "ExtensionSystem/CryPluginManager.h"
105 #include "ProjectManager/ProjectManager.h"
106 #include "UserAnalytics/UserAnalyticsSystem.h"
108 #include "DebugCallStack.h"
109 #include "ManualFrameStep.h"
113 #if defined(INCLUDE_SCALEFORM_SDK) || defined(CRY_FEATURE_SCALEFORM_HELPER)
114 #include <CrySystem/Scaleform/IScaleformHelper.h>
117 #include "HMDManager.h"
119 #include <../CryAction/ILevelSystem.h>
120 #include <../CryAction/IViewSystem.h>
122 #include <CryCore/CrtDebugStats.h>
123 #include "Interprocess/StatsAgent.h"
125 #if CRY_PLATFORM_WINDOWS
130 // Define global cvars.
131 SSystemCVars g_cvars
;
133 #include <CrySystem/ITextModeConsole.h>
135 extern int CryMemoryGetAllocatedSize();
137 // these heaps are used by underlying System structures
138 // to allocate, accordingly, small (like elements of std::set<..*>) and big (like memory for reading files) objects
139 // hopefully someday we'll have standard MT-safe heap
140 //CMTSafeHeap g_pakHeap;
141 CMTSafeHeap
* g_pPakHeap
= 0;// = &g_pakHeap;
143 //////////////////////////////////////////////////////////////////////////
144 #include "Validator.h"
145 #include "CPUDetect.h"
146 #include <CrySystem/CVarOverride.h>
148 #include <CryMath/Random.h>
150 #if CRY_PLATFORM_ANDROID
161 Callstack(void** addrs
, size_t ignore
, size_t count
)
164 this->ignore
= ignore
;
172 static _Unwind_Reason_Code
trace_func(struct _Unwind_Context
* context
, void* arg
)
174 Callstack
* cs
= static_cast<Callstack
*>(arg
);
177 void* ip
= (void*) _Unwind_GetIP(context
);
192 return _URC_NO_REASON
;
195 static int Backtrace(void** addrs
, size_t ignore
, size_t size
)
197 Callstack
cs(addrs
, ignore
, size
);
198 _Unwind_Backtrace(trace_func
, (void*) &cs
);
199 return size
- cs
.count
;
204 #if defined(CVARS_WHITELIST)
205 struct SCVarsWhitelistConfigSink
: public ILoadConfigurationEntrySink
207 virtual void OnLoadConfigurationEntry(const char* szKey
, const char* szValue
, const char* szGroup
)
209 if (gEnv
->pSystem
->IsCVarWhitelisted(szKey
, false))
211 gEnv
->pConsole
->LoadConfigVar(szKey
, szValue
);
214 } g_CVarsWhitelistConfigSink
;
215 #endif // defined(CVARS_WHITELIST)
217 /////////////////////////////////////////////////////////////////////////////////
218 // System Implementation.
219 //////////////////////////////////////////////////////////////////////////
220 CSystem::CSystem(const SSystemInitParams
& startupParams
)
221 #if defined(SYS_ENV_AS_STRUCT)
223 #elif !defined(CRY_IS_MONOLITHIC_BUILD)
224 : m_gameLibrary(nullptr)
227 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "CSystem Constructor");
229 m_pSystemEventDispatcher
= new CSystemEventDispatcher(); // Must be first.
230 m_pSystemEventDispatcher
->RegisterListener(this, "CSystem");
232 //////////////////////////////////////////////////////////////////////////
233 // Clear environment.
234 //////////////////////////////////////////////////////////////////////////
235 memset(&m_env
, 0, sizeof(m_env
));
237 //////////////////////////////////////////////////////////////////////////
239 memset(&m_dll
, 0, sizeof(m_dll
));
240 //////////////////////////////////////////////////////////////////////////
242 //////////////////////////////////////////////////////////////////////////
243 // Initialize global environment interface pointers.
244 m_env
.pSystem
= this;
245 m_env
.pTimer
= &m_Time
;
246 m_env
.pNameTable
= &m_nameTable
;
247 m_env
.bServer
= false;
248 m_env
.bMultiplayer
= false;
249 m_env
.bHostMigrating
= false;
250 m_env
.startProfilingSection
= CCryProfilingSystemImpl::StartSectionStaticDummy
;
251 m_env
.endProfilingSection
= CCryProfilingSystemImpl::EndSectionStaticDummy
;
252 m_env
.recordProfilingMarker
= CCryProfilingSystemImpl::RecordMarkerStaticDummy
;
254 m_env
.bUnattendedMode
= false;
255 m_env
.bTesting
= false;
257 #if CRY_PLATFORM_DURANGO
258 m_env
.ePLM_State
= EPLM_UNDEFINED
;
261 m_env
.SetFMVIsPlaying(false);
262 m_env
.SetCutsceneIsPlaying(false);
264 m_env
.szDebugStatus
[0] = '\0';
266 #if CRY_PLATFORM_DESKTOP
267 m_env
.SetIsClient(false);
269 #if !defined(SYS_ENV_AS_STRUCT)
272 //////////////////////////////////////////////////////////////////////////
274 m_randomGenerator
.SetState(m_Time
.GetAsyncTime().GetMicroSecondsAsInt64());
276 m_pStreamEngine
= nullptr;
277 m_PhysThread
= nullptr;
281 m_pTestSystem
= nullptr;
283 m_pVisRegTest
= nullptr;
284 m_rIntialWindowSizeRatio
= nullptr;
287 m_rColorBits
= nullptr;
288 m_rDepthBits
= nullptr;
289 m_cvSSInfo
= nullptr;
290 m_rStencilBits
= nullptr;
291 m_rFullscreen
= nullptr;
293 m_pPhysicsLibrary
= nullptr;
294 m_sysNoUpdate
= nullptr;
295 m_pMemoryManager
= nullptr;
296 m_pProcess
= nullptr;
297 m_pMtState
= nullptr;
299 m_pValidator
= nullptr;
300 m_pCmdLine
= nullptr;
301 m_pDefaultValidator
= nullptr;
302 m_pIBudgetingSystem
= nullptr;
303 m_pIZLibCompressor
= nullptr;
304 m_pIZLibDecompressor
= nullptr;
305 m_pILZ4Decompressor
= nullptr;
306 m_pNULLRenderAuxGeom
= nullptr;
307 m_pLocalizationManager
= nullptr;
308 m_sys_physics_enable_MT
= nullptr;
309 m_sys_min_step
= nullptr;
310 m_sys_max_step
= nullptr;
312 m_pNotificationNetwork
= nullptr;
314 m_cvAIUpdate
= nullptr;
316 m_pUserCallback
= nullptr;
317 #if defined(CVARS_WHITELIST)
318 m_pCVarsWhitelistConfigSink
= &g_CVarsWhitelistConfigSink
;
319 #endif // defined(CVARS_WHITELIST)
320 m_sys_memory_debug
= nullptr;
321 m_sysWarnings
= nullptr;
322 m_sysKeyboard
= nullptr;
323 m_sys_profile_watchdog_timeout
= nullptr;
324 m_sys_job_system_filter
= nullptr;
325 m_sys_job_system_enable
= nullptr;
326 m_sys_job_system_profiler
= nullptr;
327 m_sys_job_system_max_worker
= nullptr;
328 m_sys_job_system_worker_boost_enabled
= nullptr;
329 m_sys_spec
= nullptr;
330 m_sys_firstlaunch
= nullptr;
331 m_sys_enable_budgetmonitoring
= nullptr;
332 m_sys_use_Mono
= nullptr;
333 m_sys_dll_ai
= nullptr;
334 m_sys_dll_response_system
= nullptr;
335 m_sys_user_folder
= nullptr;
337 #if !defined(_RELEASE)
338 m_sys_resource_cache_folder
= nullptr;
341 m_sys_initpreloadpacks
= nullptr;
342 m_sys_menupreloadpacks
= nullptr;
344 // m_sys_filecache = nullptr;
345 m_gpu_particle_physics
= nullptr;
349 m_bShaderCacheGenMode
= false;
352 m_bPreviewMode
= false;
353 m_bIgnoreUpdates
= false;
354 m_bNoCrashDialog
= false;
357 m_checkpointLoadCount
= 0;
358 m_loadOrigin
= eLLO_Unknown
;
359 m_hasJustResumed
= false;
360 m_expectingMapCommand
= false;
363 m_nStrangeRatio
= 1000;
364 // no mem stats at the moment
365 m_pMemStats
= nullptr;
367 m_pCVarQuit
= nullptr;
369 m_pDownloadManager
= nullptr;
370 m_bForceNonDevMode
= false;
371 m_bWasInDevMode
= false;
372 m_bInDevMode
= false;
373 m_bGameFolderWritable
= false;
375 m_nServerConfigSpec
= CONFIG_VERYHIGH_SPEC
;
376 m_nMaxConfigSpec
= CONFIG_ORBIS
;
378 //m_hPhysicsThread = INVALID_HANDLE_VALUE;
379 //m_hPhysicsActive = INVALID_HANDLE_VALUE;
380 //m_bStopPhysics = 0;
381 //m_bPhysicsActive = 0;
383 m_pProgressListener
= nullptr;
387 m_nUpdateCounter
= 0;
388 m_iApplicationInstance
= -1;
390 m_pPhysRenderer
= nullptr;
392 m_root
= PathUtil::AddSlash(PathUtil::GetEnginePath());
394 m_pXMLUtils
= new CXmlUtils(this);
395 m_pArchiveHost
= Serialization::CreateArchiveHost();
397 m_pMemoryManager
= CryGetIMemoryManager();
398 m_pResourceManager
= new CResourceManager
;
399 m_pTextModeConsole
= nullptr;
400 m_pDiskProfiler
= nullptr;
403 m_pLegacyProfiler
= nullptr;
404 m_pProfilingSystem
= nullptr;
405 m_pProfileRenderer
= nullptr;
407 #ifdef ENABLE_PROFILING_CODE
408 const bool enableBootProfiler
= (strstr(startupParams
.szSystemCmdLine
, "-bootprofiler") != nullptr);
409 const bool enableBrofiler
= (strstr(startupParams
.szSystemCmdLine
, "-brofiler") != nullptr);
410 const bool enablePlatformProfiler
= (strstr(startupParams
.szSystemCmdLine
, "-platformprofiler") != nullptr);
412 const char* szVerbosity
= strstr(startupParams
.szSystemCmdLine
, "-profile_verbosity=");
413 if (szVerbosity
!= nullptr)
415 szVerbosity
+= sizeof("-profile_verbosity=") - 1;
416 int verbosity
= atoi(szVerbosity
);
418 CCryProfilingSystem::s_verbosity
= verbosity
;
422 if (enableBootProfiler
+ enableBrofiler
+ enablePlatformProfiler
> 1)
423 __debugbreak(); // may only choose one
429 m_pProfilingSystem
= new CBrofiler
;
430 m_env
.startProfilingSection
= CBrofiler::StartSectionStatic
;
431 m_env
.endProfilingSection
= CBrofiler::EndSectionStatic
;
432 // no markers on Brofiler
436 #if USE_PLATFORM_PROFILER
437 if (enablePlatformProfiler
)
439 m_pProfilingSystem
= new CPlatformProfiler
;
440 m_env
.startProfilingSection
= CPlatformProfiler::StartSectionStatic
;
441 m_env
.endProfilingSection
= CPlatformProfiler::EndSectionStatic
;
442 m_env
.recordProfilingMarker
= CPlatformProfiler::RecordMarkerStatic
;
447 m_pLegacyProfiler
= new CCryProfilingSystem
;
448 m_pProfilingSystem
= m_pLegacyProfiler
;
449 m_env
.startProfilingSection
= CCryProfilingSystem::StartSectionStatic
;
450 m_env
.endProfilingSection
= CCryProfilingSystem::EndSectionStatic
;
451 m_env
.recordProfilingMarker
= CCryProfilingSystem::RecordMarkerStatic
;
453 #if defined(ENABLE_LOADING_PROFILER)
454 if (!startupParams
.bShaderCacheGen
)
456 CBootProfiler::GetInstance().Init(this, startupParams
.szSystemCmdLine
);
458 m_pLegacyProfiler
->SetBootProfiler(&CBootProfiler::GetInstance());
460 m_pProfileRenderer
= new CProfilingRenderer
;
467 m_pTestSystem
= stl::make_unique
<CryTest::CTestSystem
>(this);
470 LOADING_TIME_PROFILE_SECTION_NAMED("CSystem Boot");
472 m_pMiniGUI
= nullptr;
473 m_pPerfHUD
= nullptr;
475 m_pHmdManager
= nullptr;
476 m_sys_vr_support
= nullptr;
478 g_pPakHeap
= new CMTSafeHeap
;
480 m_bUIFrameworkMode
= false;
482 m_PlatformOSCreateFlags
= 0;
484 // create job manager
485 m_env
.pJobManager
= GetJobManagerInterface();
487 m_UpdateTimesIdx
= 0U;
489 m_PlatformOSCreateFlags
= 0;
491 m_bHasRenderedErrorMessage
= false;
493 m_pImeManager
= nullptr;
494 RegisterWindowMessageHandler(this);
496 m_env
.pConsole
= new CXConsole(*this);
497 if (startupParams
.pPrintSync
)
498 m_env
.pConsole
->AddOutputPrintSink(startupParams
.pPrintSync
);
500 if(m_pProfilingSystem
)
501 m_pProfilingSystem
->RegisterCVars();
503 m_pPluginManager
= new CCryPluginManager(startupParams
);
505 m_pUserAnalyticsSystem
= new CUserAnalyticsSystem();
508 /////////////////////////////////////////////////////////////////////////////////
509 /////////////////////////////////////////////////////////////////////////////////
514 SAFE_DELETE(m_pImeManager
);
515 UnregisterWindowMessageHandler(this);
517 FreeLib(m_dll
.hNetwork
);
519 FreeLib(m_dll
.hInput
);
520 FreeLib(m_dll
.hScript
);
521 FreeLib(m_dll
.hPhysics
);
522 FreeLib(m_dll
.hEntitySystem
);
523 FreeLib(m_dll
.hRenderer
);
524 FreeLib(m_dll
.hFlash
);
525 FreeLib(m_dll
.hFont
);
526 FreeLib(m_dll
.hMovie
);
527 FreeLib(m_dll
.hIndoor
);
528 FreeLib(m_dll
.h3DEngine
);
529 FreeLib(m_dll
.hAnimation
);
530 FreeLib(m_dll
.hGame
);
531 FreeLib(m_dll
.hSound
);
532 SAFE_DELETE(m_pVisRegTest
);
533 #if defined(USE_DISK_PROFILER)
534 SAFE_DELETE(m_pDiskProfiler
);
536 SAFE_DELETE(m_pXMLUtils
);
537 SAFE_DELETE(m_pArchiveHost
);
538 SAFE_DELETE(m_pResourceManager
);
539 SAFE_DELETE(m_pSystemEventDispatcher
);
540 // SAFE_DELETE(m_pMemoryManager);
541 SAFE_DELETE(m_pNULLRenderAuxGeom
);
544 m_pTestSystem
.reset();
547 gEnv
->pThreadManager
->UnRegisterThirdPartyThread("Main");
548 ShutDownThreadSystem();
550 SAFE_DELETE(g_pPakHeap
);
552 m_env
.startProfilingSection
= CCryProfilingSystemImpl::StartSectionStaticDummy
;
553 m_env
.endProfilingSection
= CCryProfilingSystemImpl::EndSectionStaticDummy
;
554 m_env
.recordProfilingMarker
= CCryProfilingSystemImpl::RecordMarkerStaticDummy
;
555 SAFE_DELETE(m_pProfilingSystem
);
557 m_env
.pSystem
= nullptr;
558 #if !defined(SYS_ENV_AS_STRUCT)
562 #if CRY_PLATFORM_WINDOWS
563 ((DebugCallStack
*)IDebugCallStack::instance())->uninstallErrorHandler();
567 //////////////////////////////////////////////////////////////////////////
568 void CSystem::FreeLib(WIN_HMODULE hLibModule
)
572 CryFreeLibrary(hLibModule
);
576 //////////////////////////////////////////////////////////////////////////
577 IStreamEngine
* CSystem::GetStreamEngine()
579 return m_pStreamEngine
;
582 //////////////////////////////////////////////////////////////////////////
583 IRemoteConsole
* CSystem::GetIRemoteConsole()
585 return CRemoteConsole::GetInst();
588 //////////////////////////////////////////////////////////////////////////
589 void CSystem::SetForceNonDevMode(const bool bValue
)
591 m_bForceNonDevMode
= bValue
;
596 //////////////////////////////////////////////////////////////////////////
597 bool CSystem::GetForceNonDevMode() const
599 return m_bForceNonDevMode
;
602 //////////////////////////////////////////////////////////////////////////
603 void CSystem::SetDevMode(bool bEnable
)
606 m_bWasInDevMode
= true;
607 m_bInDevMode
= bEnable
;
610 void LvlRes_export(IConsoleCmdArgs
* pParams
);
612 ///////////////////////////////////////////////////
613 void CSystem::ShutDown()
615 CryLogAlways("System Shutdown");
617 SAFE_DELETE(m_pManualFrameStepController
);
619 if (m_pSystemEventDispatcher
)
621 m_pSystemEventDispatcher
->RemoveListener(this);
625 m_pUserCallback
->OnShutdown();
627 GetIRemoteConsole()->Stop();
629 SAFE_DELETE(m_pTextModeConsole
);
631 //////////////////////////////////////////////////////////////////////////
632 // Interprocess Communication
633 //////////////////////////////////////////////////////////////////////////
634 #if defined(ENABLE_STATS_AGENT)
635 CStatsAgent::ClosePipe();
640 if (m_sys_firstlaunch
)
641 m_sys_firstlaunch
->Set(0);
643 if (m_env
.IsEditor())
645 // restore the old saved cvars
646 if (m_env
.pConsole
->GetCVar("r_Width"))
647 m_env
.pConsole
->GetCVar("r_Width")->Set(m_iWidth
);
648 if (m_env
.pConsole
->GetCVar("r_Height"))
649 m_env
.pConsole
->GetCVar("r_Height")->Set(m_iHeight
);
650 if (m_env
.pConsole
->GetCVar("r_ColorBits"))
651 m_env
.pConsole
->GetCVar("r_ColorBits")->Set(m_iColorBits
);
654 if (m_env
.IsEditor() && !m_bRelaunch
)
659 //if (!m_bEditor && !bRelaunch)
660 #if !CRY_PLATFORM_DURANGO && !CRY_PLATFORM_ORBIS
661 if (!m_env
.IsEditor())
663 if (m_pCVarQuit
&& m_pCVarQuit
->GetIVal())
667 // Dispatch the fast-shutdown event so other systems can do any last minute processing.
668 if (m_pSystemEventDispatcher
!= NULL
)
670 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_FAST_SHUTDOWN
, 0, 0);
673 if (m_env
.pNetwork
!= NULL
)
675 m_env
.pNetwork
->FastShutdown();
678 SAFE_RELEASE(m_env
.pRenderer
);
679 FreeLib(m_dll
.hRenderer
);
681 // Shut down audio as late as possible but before the console gets released!
682 SAFE_RELEASE(m_env
.pAudioSystem
);
684 // Log must be last thing released.
685 m_env
.pLog
->FlushAndClose();
686 SAFE_RELEASE(m_env
.pLog
); // creates log backup
688 #if CRY_PLATFORM_WINDOWS
689 ((DebugCallStack
*)IDebugCallStack::instance())->uninstallErrorHandler();
692 #if CRY_PLATFORM_LINUX || CRY_PLATFORM_ANDROID
693 return; //safe clean return
695 // Commit files changes to the disk.
703 // Dispatch the full-shutdown event in case this is not a fast-shutdown.
704 if (m_pSystemEventDispatcher
!= NULL
)
706 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_FULL_SHUTDOWN
, 0, 0);
709 //////////////////////////////////////////////////////////////////////////
711 //////////////////////////////////////////////////////////////////////////
713 if (m_env
.pGameFramework
)
715 m_env
.pGameFramework
->ShutDown();
716 #if !defined(CRY_IS_MONOLITHIC_BUILD)
717 // This handle keeps gamedll loaded, it must be emptied on shutdown in order to properly clean up
718 m_gameLibrary
.Set(nullptr);
722 if (m_env
.pEntitySystem
)
723 m_env
.pEntitySystem
->Unload();
725 if (m_env
.pPhysicalWorld
)
727 m_env
.pPhysicalWorld
->SetPhysicsStreamer(0);
728 m_env
.pPhysicalWorld
->SetPhysicsEventClient(0);
731 UnloadSchematycModule();
733 UnloadEngineModule("CryAction");
734 UnloadEngineModule("CryFlowGraph");
735 SAFE_DELETE(m_pPluginManager
);
737 m_pPlatformOS
.reset();
739 if (gEnv
->pMonoRuntime
!= nullptr)
741 gEnv
->pMonoRuntime
->Shutdown();
744 SAFE_DELETE(m_pUserAnalyticsSystem
);
745 if (m_sys_dll_response_system
!= nullptr)
747 UnloadEngineModule(m_sys_dll_response_system
->GetString());
750 #if defined(INCLUDE_SCALEFORM_SDK) || defined(CRY_FEATURE_SCALEFORM_HELPER)
752 m_env
.pRenderer
->FlushRTCommands(true, true, true);
754 if (!gEnv
->IsDedicated() && gEnv
->pScaleformHelper
)
756 gEnv
->pScaleformHelper
->Destroy();
757 gEnv
->pScaleformHelper
= nullptr;
761 //////////////////////////////////////////////////////////////////////////
762 // Clear 3D Engine resources.
764 m_env
.p3DEngine
->ShutDown();
765 //////////////////////////////////////////////////////////////////////////
767 // Shutdown resource manager.
768 m_pResourceManager
->Shutdown();
770 // The LiveCreate module must be deleted here since at shutdown, it's using other modules, please keep this location
771 SAFE_DELETE(m_env
.pLiveCreateHost
);
772 SAFE_DELETE(m_env
.pLiveCreateManager
);
773 SAFE_RELEASE(m_env
.pHardwareMouse
);
774 UnloadEngineModule("CryMovie");
775 SAFE_DELETE(m_env
.pServiceNetwork
);
776 UnloadEngineModule("CryAISystem");
777 UnloadEngineModule("CryFont");
778 UnloadEngineModule("CryNetwork");
779 // SAFE_RELEASE(m_env.pCharacterManager);
780 UnloadEngineModule("CryAnimation");
781 UnloadEngineModule("Cry3DEngine"); // depends on EntitySystem
782 UnloadEngineModule("CryEntitySystem");
784 SAFE_DELETE(m_pPhysRenderer
); // Must be destroyed before unloading CryPhysics as it holds memory that was allocated by that module
785 UnloadEngineModule("CryPhysics");
787 UnloadEngineModule("CryMonoBridge");
790 ((CXConsole
*)m_env
.pConsole
)->FreeRenderResources();
791 SAFE_RELEASE(m_pIZLibCompressor
);
792 SAFE_RELEASE(m_pIZLibDecompressor
);
793 SAFE_RELEASE(m_pILZ4Decompressor
);
794 SAFE_RELEASE(m_pIBudgetingSystem
);
796 SAFE_RELEASE(m_env
.pRenderer
);
798 if (ICVar
* pDriverCVar
= m_env
.pConsole
->GetCVar("r_driver"))
800 const char* szRenderDriver
= pDriverCVar
->GetString();
801 CloseRenderLibrary(szRenderDriver
);
804 SAFE_RELEASE(m_env
.pCodeCheckpointMgr
);
807 m_env
.pLog
->UnregisterConsoleVariables();
809 GetIRemoteConsole()->UnregisterConsoleVariables();
811 // Release console variables.
813 SAFE_RELEASE(m_pCVarQuit
);
814 SAFE_RELEASE(m_rIntialWindowSizeRatio
);
815 SAFE_RELEASE(m_rWidth
);
816 SAFE_RELEASE(m_rHeight
);
817 SAFE_RELEASE(m_rColorBits
);
818 SAFE_RELEASE(m_rDepthBits
);
819 SAFE_RELEASE(m_cvSSInfo
);
820 SAFE_RELEASE(m_rStencilBits
);
821 SAFE_RELEASE(m_rFullscreen
);
822 SAFE_RELEASE(m_rDriver
);
823 SAFE_RELEASE(m_pPhysicsLibrary
);
825 SAFE_RELEASE(m_sysWarnings
);
826 SAFE_RELEASE(m_sysKeyboard
);
827 SAFE_RELEASE(m_sys_profile_watchdog_timeout
);
828 SAFE_RELEASE(m_sys_job_system_filter
);
829 SAFE_RELEASE(m_sys_job_system_enable
);
830 SAFE_RELEASE(m_sys_job_system_profiler
);
831 SAFE_RELEASE(m_sys_job_system_max_worker
);
832 SAFE_RELEASE(m_sys_job_system_worker_boost_enabled
);
833 SAFE_RELEASE(m_sys_spec
);
834 SAFE_RELEASE(m_sys_firstlaunch
);
835 SAFE_RELEASE(m_sys_enable_budgetmonitoring
);
836 SAFE_RELEASE(m_sys_physics_enable_MT
);
837 SAFE_RELEASE(m_sys_min_step
);
838 SAFE_RELEASE(m_sys_max_step
);
840 //Purposely leaking the object as we do not want to block the MainThread waiting for the Watchdog thread to join
841 if (m_pWatchdog
!= nullptr)
842 m_pWatchdog
->SignalStopWork();
846 m_env
.pInput
->ShutDown();
849 UnloadEngineModule("CryInput");
851 SAFE_RELEASE(m_pNotificationNetwork
);
852 UnloadEngineModule("CryScriptSystem");
854 SAFE_DELETE(m_pMemStats
);
855 SAFE_DELETE(m_pSizer
);
857 SAFE_DELETE(m_env
.pOverloadSceneManager
);
860 // CHmdManager shuts down the HDM devices on destruction.
861 // It must happen AFTER m_env.pRenderer: the renderer may consult info
862 // about the current HMD Device.
863 // It should happen AFTER m_env.pInput: as CryInput may use elements controlled
865 SAFE_DELETE(m_pHmdManager
);
867 #ifdef DOWNLOAD_MANAGER
868 SAFE_RELEASE(m_pDownloadManager
);
869 #endif //DOWNLOAD_MANAGER
871 SAFE_DELETE(m_pLocalizationManager
);
873 //DebugStats(false, false);//true);
875 //CryLogAlways("release mode memory manager stats:");
880 SAFE_DELETE(m_pCmdLine
);
882 // Shut down audio as late as possible but before the streaming system and console get released!
883 SAFE_RELEASE(m_env
.pAudioSystem
);
884 UnloadEngineModule("CryAudioSystem");
886 SAFE_DELETE(m_pProjectManager
);
888 // Shut down the CryPak system after audio!
889 SAFE_DELETE(m_env
.pCryPak
);
891 // Shut down the streaming system and console as late as possible and after audio!
892 SAFE_DELETE(m_pStreamEngine
);
894 // Shut down UDR before the console gets released as it accesses it during destruction!
895 UnloadEngineModule("CryUDR");
897 SAFE_RELEASE(m_env
.pConsole
);
899 // Log must be last thing released.
900 m_env
.pLog
->FlushAndClose();
901 SAFE_RELEASE(m_env
.pLog
); // creates log backup
903 // DefaultValidator is used by the logging system, make sure to delete this member after logging system!
904 SAFE_DELETE(m_pDefaultValidator
);
906 #if defined(MAP_LOADING_SLICING)
907 delete gEnv
->pSystemScheduler
;
908 #endif // defined(MAP_LOADING_SLICING)
910 UnloadEngineModule("CryReflection");
912 #if CAPTURE_REPLAY_LOG
913 CryGetIMemReplay()->Stop();
916 #if CRY_PLATFORM_LINUX
918 if (m_iApplicationInstance
!= -1)
920 // In case of a crash this will not get called
921 // but the OS clears the directory on reboot so
922 // "leaking" the file is not that bad
925 path
.Format("/tmp/CrytekApplication%d.lock", m_iApplicationInstance
);
926 remove(path
.c_str());
927 m_iApplicationInstance
= -1;
929 #endif // CRY_PLATFORM_LINUX
931 // Fix to improve wait() time within third party APIs using sleep()
932 #if CRY_PLATFORM_WINDOWS
934 if (timeGetDevCaps(&tc
, sizeof(TIMECAPS
)) != TIMERR_NOERROR
)
936 CryFatalError("Error while changing the system timer resolution!");
938 timeEndPeriod(tc
.wPeriodMin
);
939 #endif // CRY_PLATFORM_WINDOWS
942 /////////////////////////////////////////////////////////////////////////////////
943 /////////////////////////////////////////////////////////////////////////////////
946 CryLog("CSystem::Quit invoked from thread %" PRI_THREADID
" (main is %" PRI_THREADID
")", GetCurrentThreadId(), gEnv
->mMainThreadId
);
950 m_pUserCallback
->OnQuit();
951 if (gEnv
->pCryPak
&& gEnv
->pCryPak
->GetLvlResStatus())
952 LvlRes_export(0); // executable was started with -LvlRes so it should export lvlres file on quit
955 // clean up properly the console
956 if (m_pTextModeConsole
)
957 m_pTextModeConsole
->OnShutdown();
961 ICVar
* pCVarGamma
= m_env
.pConsole
->GetCVar("r_Gamma");
963 pCVarGamma
->Set(1.0f
); // prevent mysterious gamma snap back on quit (CE-15284)
964 m_env
.pRenderer
->RestoreGamma();
967 if (m_pCVarQuit
&& m_pCVarQuit
->GetIVal() != 0)
969 // Dispatch the fast-shutdown event so other systems can do any last minute processing.
970 if (m_pSystemEventDispatcher
!= NULL
)
972 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_FAST_SHUTDOWN
, 0, 0);
976 m_env
.pNetwork
->FastShutdown();
978 // HACK! to save cvars on quit.
982 gEnv
->pFlashUI
->Shutdown();
986 m_env
.pRenderer
->StopRenderIntroMovies(false);
987 m_env
.pRenderer
->StopLoadtimeFlashPlayback();
990 #if defined(INCLUDE_SCALEFORM_SDK) || defined(CRY_FEATURE_SCALEFORM_HELPER)
992 m_env
.pRenderer
->FlushRTCommands(true, true, true);
994 if (gEnv
->pScaleformHelper
)
996 gEnv
->pScaleformHelper
->Destroy();
997 gEnv
->pScaleformHelper
= nullptr;
1001 if (m_env
.pRenderer
)
1002 m_env
.pRenderer
->ShutDownFast();
1004 CryLogAlways("System:Quit");
1006 // Shut down audio as late as possible but before the streaming system and console get released!
1007 SAFE_RELEASE(m_env
.pAudioSystem
);
1009 // Shut down the streaming system as late as possible and after audio!
1010 if (m_pStreamEngine
)
1011 m_pStreamEngine
->Shutdown();
1013 // Commit files changes to the disk.
1014 #if CRY_PLATFORM_LINUX || CRY_PLATFORM_ANDROID
1019 //////////////////////////////////////////////////////////////////////////
1020 // Support relaunching for windows media center edition.
1021 //////////////////////////////////////////////////////////////////////////
1022 #if CRY_PLATFORM_WINDOWS
1023 if (m_pCmdLine
&& strstr(m_pCmdLine
->GetCommandLine(), "ReLaunchMediaCenter") != 0)
1025 ReLaunchMediaCenter();
1029 #if CAPTURE_REPLAY_LOG
1030 CryGetIMemReplay()->Stop();
1033 GetIRemoteConsole()->Stop();
1035 //////////////////////////////////////////////////////////////////////////
1036 // [marco] in test mode, kill the process and quit without performing full C libs cleanup
1037 // (for faster closing of application)
1038 CRY_ASSERT(m_pCVarQuit
->GetIVal());
1039 #if CRY_PLATFORM_ORBIS
1041 #elif CRY_PLATFORM_WINDOWS
1042 TerminateProcess(GetCurrentProcess(), 0);
1047 #if !CRY_PLATFORM_LINUX && !CRY_PLATFORM_ANDROID && !CRY_PLATFORM_APPLE && !CRY_PLATFORM_DURANGO && !CRY_PLATFORM_ORBIS
1051 /////////////////////////////////////////////////////////////////////////////////
1052 /////////////////////////////////////////////////////////////////////////////////
1053 bool CSystem::IsQuitting() const
1058 //////////////////////////////////////////////////////////////////////////
1059 void CSystem::SetIProcess(IProcess
* process
)
1061 m_pProcess
= process
;
1063 //m_pProcess->SetPMessage("");
1066 void CSystem::StartBootProfilerSession(const char* szName
)
1068 #ifdef ENABLE_LOADING_PROFILER
1069 CBootProfiler::GetInstance().StartSession(szName
);
1073 void CSystem::EndBootProfilerSession()
1075 #ifdef ENABLE_LOADING_PROFILER
1076 CBootProfiler::GetInstance().StopSession();
1080 //////////////////////////////////////////////////////////////////////////
1081 // Physics thread task
1082 //////////////////////////////////////////////////////////////////////////
1084 class IPhysicsThreadTask
: public IThread
1087 virtual ~IPhysicsThreadTask()
1090 // Start accepting work on thread
1091 virtual void ThreadEntry() = 0;
1093 // Signals the thread that it should not accept anymore work and exit
1094 virtual void SignalStopWork() = 0;
1097 class CPhysicsThreadTask
: public IPhysicsThreadTask
1101 CPhysicsThreadTask()
1103 m_bStopRequested
= 0;
1105 m_stepRequested
= 0;
1108 m_lastStepTimeTaken
= 0U;
1109 m_lastWaitTimeTaken
= 0U;
1112 virtual ~CPhysicsThreadTask()
1116 //////////////////////////////////////////////////////////////////////////
1117 // IThread implementation.
1118 //////////////////////////////////////////////////////////////////////////
1119 // Start accepting work on thread
1120 virtual void ThreadEntry()
1122 m_bStopRequested
= 0;
1125 float step
, timeTaken
, kSlowdown
= 1.0f
;
1126 int nSlowFrames
= 0;
1128 #ifdef ENABLE_LW_PROFILERS
1129 LARGE_INTEGER stepStart
, stepEnd
;
1131 LARGE_INTEGER waitStart
, waitEnd
;
1136 CRY_PROFILE_REGION_WAITING(PROFILE_PHYSICS
, "Wait - Physics Update");
1138 QueryPerformanceCounter(&waitStart
);
1139 m_FrameEvent
.Wait(); // Wait until new frame
1140 QueryPerformanceCounter(&waitEnd
);
1144 CRY_PROFILE_REGION(PROFILE_PHYSICS
, "Physics Update");
1146 m_lastWaitTimeTaken
= waitEnd
.QuadPart
- waitStart
.QuadPart
;
1148 if (m_bStopRequested
)
1152 bool stepped
= false;
1153 #ifdef ENABLE_LW_PROFILERS
1154 QueryPerformanceCounter(&stepStart
);
1156 IGameFramework
* pIGameFramework
= gEnv
->pGameFramework
;
1157 while ((step
= m_stepRequested
) > 0 || m_doZeroStep
)
1160 m_stepRequested
= 0;
1164 PhysicsVars
* pVars
= gEnv
->pPhysicalWorld
->GetPhysVars();
1165 pVars
->bMultithreaded
= 1;
1166 gEnv
->pPhysicalWorld
->TracePendingRays();
1167 if (kSlowdown
!= 1.0f
)
1169 step
= max(1, FtoI(step
* kSlowdown
* 50 - 0.5f
)) * 0.02f
;
1170 pVars
->timeScalePlayers
= 1.0f
/ max(kSlowdown
, 0.2f
);
1173 pVars
->timeScalePlayers
= 1.0f
;
1174 step
= min(step
, pVars
->maxWorldStep
);
1175 timeStart
= CryGetTicks();
1176 pIGameFramework
->PrePhysicsTimeStep(step
);
1177 gEnv
->pPhysicalWorld
->TimeStep(step
);
1178 timeTaken
= gEnv
->pTimer
->TicksToSeconds(CryGetTicks() - timeStart
);
1179 if (timeTaken
> step
* 0.9f
)
1181 if (++nSlowFrames
> 5)
1182 kSlowdown
= step
* 0.9f
/ timeTaken
;
1185 kSlowdown
= 1.0f
, nSlowFrames
= 0;
1186 gEnv
->pPhysicalWorld
->TracePendingRays(2);
1188 //int timeSleep = (int)((m_timeTarget-gEnv->pTimer->GetAsyncTime()).GetMilliSeconds()*0.9f);
1189 //Sleep(max(0,timeSleep));
1191 if (!stepped
) CrySleep(0);
1193 #ifdef ENABLE_LW_PROFILERS
1194 QueryPerformanceCounter(&stepEnd
);
1195 m_lastStepTimeTaken
= stepEnd
.QuadPart
- stepStart
.QuadPart
;
1201 // Signals the thread that it should not accept anymore work and exit
1202 virtual void SignalStopWork()
1205 m_bStopRequested
= 1;
1214 PhysicsVars
* vars
= gEnv
->pPhysicalWorld
->GetPhysVars();
1215 vars
->lastTimeStep
= 0;
1217 m_stepRequested
= 0;
1218 while (m_bProcessing
);
1221 gEnv
->pPhysicalWorld
->GetPhysVars()->lastTimeStep
= 0;
1233 int IsActive() { return m_bIsActive
; }
1234 int RequestStep(float dt
)
1236 if (m_bIsActive
&& dt
> FLT_EPSILON
)
1238 m_stepRequested
+= dt
;
1239 m_stepRequested
= min((float)m_stepRequested
, 10.f
* gEnv
->pPhysicalWorld
->GetPhysVars()->maxWorldStep
);
1245 return m_bProcessing
;
1247 float GetRequestedStep() { return m_stepRequested
; }
1249 uint64
LastStepTaken() const
1251 return m_lastStepTimeTaken
;
1254 uint64
LastWaitTime() const
1256 return m_lastWaitTimeTaken
;
1259 void EnsureStepDone()
1261 CRY_PROFILE_REGION_WAITING(PROFILE_SYSTEM
, "SysUpdate:PhysicsEnsureDone");
1265 while (m_stepRequested
> 0.0f
|| m_bProcessing
)
1274 volatile int m_bStopRequested
;
1275 volatile int m_bIsActive
;
1276 volatile float m_stepRequested
;
1277 volatile int m_bProcessing
;
1278 volatile int m_doZeroStep
;
1279 volatile uint64 m_lastStepTimeTaken
;
1280 volatile uint64 m_lastWaitTimeTaken
;
1282 CryEvent m_FrameEvent
;
1283 CryEvent m_FrameDone
;
1286 void CSystem::CreatePhysicsThread()
1290 m_PhysThread
= new CPhysicsThreadTask
;
1291 if (!gEnv
->pThreadManager
->SpawnThread(m_PhysThread
, "Physics"))
1293 CryFatalError("Error spawning \"Physics\" thread.");
1297 if (g_cvars
.sys_limit_phys_thread_count
)
1299 PhysicsVars
* pVars
= gEnv
->pPhysicalWorld
->GetPhysVars();
1300 pVars
->numThreads
= max(1, min(pVars
->numThreads
, (int)m_pCpu
->GetLogicalCPUCount() - 1));
1304 void CSystem::KillPhysicsThread()
1308 m_PhysThread
->SignalStopWork();
1309 gEnv
->pThreadManager
->JoinThread(m_PhysThread
, eJM_Join
);
1310 delete m_PhysThread
;
1315 //////////////////////////////////////////////////////////////////////////
1316 int CSystem::SetThreadState(ESubsystem subsys
, bool bActive
)
1320 case ESubsys_Physics
:
1324 return bActive
? ((CPhysicsThreadTask
*)m_PhysThread
)->Resume() : ((CPhysicsThreadTask
*)m_PhysThread
)->Pause();
1332 //////////////////////////////////////////////////////////////////////////
1333 void CSystem::SleepIfNeeded()
1335 CRY_PROFILE_FUNCTION(PROFILE_SYSTEM
)
1337 static ICVar
* pSysMaxFPS
= NULL
;
1338 static ICVar
* pVSync
= NULL
;
1340 if (pSysMaxFPS
== NULL
&& gEnv
&& gEnv
->pConsole
)
1341 pSysMaxFPS
= gEnv
->pConsole
->GetCVar("sys_MaxFPS");
1342 if (pVSync
== NULL
&& gEnv
&& gEnv
->pConsole
)
1343 pVSync
= gEnv
->pConsole
->GetCVar("r_Vsync");
1347 if (m_env
.IsDedicated())
1349 const float maxRate
= m_svDedicatedMaxRate
->GetFVal();
1350 maxFPS
= int32(maxRate
);
1354 if (pSysMaxFPS
&& pVSync
)
1356 uint32 vSync
= pVSync
->GetIVal();
1359 maxFPS
= pSysMaxFPS
->GetIVal();
1362 const bool bInLoading
= (ESYSTEM_GLOBAL_STATE_RUNNING
!= m_systemGlobalState
);
1363 if (bInLoading
|| IsPaused() || m_throttleFPS
)
1374 const int64 safeMarginMS
= 5; // microseconds
1375 const int64 thresholdMs
= (1000 * 1000) / (maxFPS
);
1377 ITimer
* pTimer
= gEnv
->pTimer
;
1378 static int64 sTimeLast
= pTimer
->GetAsyncTime().GetMicroSecondsAsInt64();
1379 int64 currentTime
= pTimer
->GetAsyncTime().GetMicroSecondsAsInt64();
1382 const int64 frameTime
= currentTime
- sTimeLast
;
1383 if (frameTime
>= thresholdMs
)
1385 if (thresholdMs
- frameTime
> 10 * 1000)
1390 currentTime
= pTimer
->GetAsyncTime().GetMicroSecondsAsInt64();
1393 m_lastTickTime
= pTimer
->GetAsyncTime();
1394 sTimeLast
= m_lastTickTime
.GetMicroSecondsAsInt64() + safeMarginMS
;
1398 //////////////////////////////////////////////////////////////////////
1399 #if CRY_PLATFORM_WINDOWS
1401 WNDPROC g_prevWndProc
;
1402 LRESULT CALLBACK
BreakWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1404 if (msg
== WM_HOTKEY
)
1406 return CallWindowProc(g_prevWndProc
, hWnd
, msg
, wParam
, lParam
);
1409 struct SBreakHotKeyThread
: public IThread
1411 SBreakHotKeyThread()
1416 // Start accepting work on thread
1417 virtual void ThreadEntry()
1419 g_hBreakWnd
= CreateWindowExW(0, L
"Message", L
"", 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, HWND_MESSAGE
, 0, GetModuleHandleW(0), 0);
1420 g_prevWndProc
= (WNDPROC
)SetWindowLongPtrW(g_hBreakWnd
, GWLP_WNDPROC
, (LONG_PTR
)BreakWndProc
);
1421 RegisterHotKey(g_hBreakWnd
, 0, 0, VK_PAUSE
);
1423 while (GetMessage(&msg
, g_hBreakWnd
, 0, 0) && m_bRun
)
1425 TranslateMessage(&msg
);
1426 DispatchMessageW(&msg
);
1428 UnregisterHotKey(g_hBreakWnd
, 0);
1431 // Signals the thread that it should not accept anymore work and exit
1432 void SignalStopWork()
1438 volatile bool m_bRun
;
1441 SBreakHotKeyThread
* g_pBreakHotkeyThread
;
1444 class BreakListener
: public IInputEventListener
1446 bool OnInputEvent(const SInputEvent
& ie
)
1448 if (ie
.deviceType
== eIDT_Keyboard
&& ie
.keyId
== eKI_Pause
&& ie
.state
& (eIS_Pressed
| eIS_Down
))
1454 volatile int g_lockInput
= 0;
1456 struct SBreakListenerTask
: public IThread
1458 SBreakListenerTask()
1463 // Start accepting work on thread
1464 virtual void ThreadEntry()
1469 if (++m_nBreakIdle
> 1)
1471 WriteLock
lock(g_lockInput
);
1472 gEnv
->pInput
->Update(true);
1478 // Signals the thread that it should not accept anymore work and exit
1479 void SignalStopWork()
1483 volatile int m_bStop
;
1486 SBreakListenerTask g_BreakListenerTask
;
1487 bool g_breakListenerOn
= false;
1489 extern DWORD g_idDebugThreads
[];
1490 extern int g_nDebugThreads
;
1491 int prev_sys_float_exceptions
= -1;
1493 //////////////////////////////////////////////////////////////////////
1494 void CSystem::PrePhysicsUpdate()
1496 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "System::PrePhysicsUpdate");
1498 if (m_env
.pGameFramework
)
1500 m_env
.pGameFramework
->PrePhysicsUpdate();
1503 if (m_pPluginManager
)
1505 m_pPluginManager
->UpdateBeforePhysics();
1508 //////////////////////////////////////////////////////////////////////
1509 //update entity system
1510 if (m_env
.pEntitySystem
&& g_cvars
.sys_entitysystem
)
1512 if (gEnv
->pSchematyc
!= nullptr)
1514 gEnv
->pSchematyc
->PrePhysicsUpdate();
1517 if (gEnv
->pSchematyc2
!= nullptr)
1519 gEnv
->pSchematyc2
->PrePhysicsUpdate();
1522 m_env
.pEntitySystem
->PrePhysicsUpdate();
1526 void CSystem::RunMainLoop()
1528 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "CSystem::MainLoop");
1530 if (m_bShaderCacheGenMode
)
1535 #if CRY_PLATFORM_WINDOWS
1536 if (!(gEnv
&& m_env
.pSystem
) || (!m_env
.IsEditor() && !m_env
.IsDedicated()))
1538 if (m_env
.pHardwareMouse
!= nullptr)
1540 m_env
.pHardwareMouse
->DecrementCounter();
1544 ::ShowCursor(FALSE
);
1548 if (gEnv
&& m_env
.pHardwareMouse
)
1549 m_env
.pHardwareMouse
->DecrementCounter();
1554 #if CRY_PLATFORM_DURANGO
1555 Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher
->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent
);
1564 //////////////////////////////////////////////////////////////////////
1565 bool CSystem::DoFrame(const SDisplayContextKey
& displayContextKey
, const SGraphicsPipelineKey
& graphicsPipelineKey
, CEnumFlags
<ESystemUpdateFlags
> updateFlags
)
1567 if(m_pProfilingSystem
&& !updateFlags
.Check(ESYSUPDATE_EDITOR
))
1568 m_pProfilingSystem
->StartFrame();
1570 BROFILER_FRAME("Main");
1573 if (m_pManualFrameStepController
!= nullptr && m_pManualFrameStepController
->Update() == EManualFrameStepResult::Block
)
1575 // Skip frame update
1579 CRY_PROFILE_REGION(PROFILE_SYSTEM
, __FUNC__
);
1580 #if defined(JOBMANAGER_SUPPORT_PROFILING)
1581 m_env
.GetJobManager()->SetFrameStartTime(m_env
.pTimer
->GetAsyncTime());
1584 if (m_env
.pGameFramework
!= nullptr)
1586 m_env
.pGameFramework
->PreSystemUpdate();
1589 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1591 m_pPluginManager
->UpdateBeforeSystem();
1594 if (ITextModeConsole
* pTextModeConsole
= GetITextModeConsole())
1596 pTextModeConsole
->BeginDraw();
1599 // Tell the network to go to sleep
1602 m_env
.pNetwork
->SyncWithGame(eNGS_SleepNetwork
);
1605 if (!m_env
.IsEditing()) // Editor calls its own rendering update
1606 RenderBegin(displayContextKey
, graphicsPipelineKey
);
1608 bool continueRunning
= true;
1610 // The Editor is responsible for updating the system manually, so we should skip in that case.
1611 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1615 if (m_env
.pRenderer
!= nullptr && m_env
.pRenderer
->IsPost3DRendererEnabled())
1618 updateFlags
|= ESYSUPDATE_IGNORE_AI
;
1620 else if (m_env
.pGameFramework
!= nullptr)
1622 pauseMode
= (m_env
.pGameFramework
->IsGamePaused() || !m_env
.pGameFramework
->IsGameStarted()) ? 1 : 0;
1629 if (!Update(updateFlags
, pauseMode
))
1631 continueRunning
= false;
1635 if (m_env
.pGameFramework
!= nullptr)
1637 if (!m_env
.pGameFramework
->PostSystemUpdate(m_hasWindowFocus
, updateFlags
))
1639 continueRunning
= false;
1643 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1645 m_pPluginManager
->UpdateAfterSystem();
1648 // Synchronize all animations to ensure that their computation has finished
1649 // Has to be done before view update, in case camera depends on a joint
1650 if (m_env
.pCharacterManager
&& !IsLoading())
1652 m_env
.pCharacterManager
->SyncAllAnimations();
1655 if (m_env
.pGameFramework
!= nullptr && !updateFlags
.Check(ESYSUPDATE_EDITOR_ONLY
) && !updateFlags
.Check(ESYSUPDATE_EDITOR_AI_PHYSICS
))
1657 m_env
.pGameFramework
->PreFinalizeCamera(updateFlags
);
1660 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1662 m_pPluginManager
->UpdateBeforeFinalizeCamera();
1665 ICVar
* pCameraFreeze
= gEnv
->pConsole
->GetCVar("e_CameraFreeze");
1666 const bool isCameraFrozen
= pCameraFreeze
&& pCameraFreeze
->GetIVal() != 0;
1668 const CCamera
& rCameraToSet
= isCameraFrozen
? m_env
.p3DEngine
->GetRenderingCamera() : m_ViewCamera
;
1669 m_env
.p3DEngine
->PrepareOcclusion(rCameraToSet
, SGraphicsPipelineKey::BaseGraphicsPipelineKey
);
1671 if (m_env
.pGameFramework
!= nullptr)
1673 m_env
.pGameFramework
->PreRender();
1676 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1678 m_pPluginManager
->UpdateBeforeRender();
1681 Render(graphicsPipelineKey
);
1683 if (m_env
.pGameFramework
!= nullptr)
1685 m_env
.pGameFramework
->PostRender(updateFlags
);
1688 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1690 m_pPluginManager
->UpdateAfterRender();
1693 if (updateFlags
& ESYSUPDATE_EDITOR_AI_PHYSICS
)
1695 return continueRunning
;
1698 #if !defined(_RELEASE) && !CRY_PLATFORM_DURANGO
1699 RenderPhysicsHelpers();
1704 if (m_env
.pGameFramework
!= nullptr)
1706 m_env
.pGameFramework
->PostRenderSubmit();
1709 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1711 m_pPluginManager
->UpdateAfterRenderSubmit();
1714 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
1716 if (m_env
.pStatoscope
)
1718 m_env
.pStatoscope
->Tick();
1721 if (ITextModeConsole
* pTextModeConsole
= GetITextModeConsole())
1723 pTextModeConsole
->EndDraw();
1726 m_env
.p3DEngine
->SyncProcessStreamingUpdate();
1728 if(m_pProfilingSystem
)
1729 m_pProfilingSystem
->EndFrame();
1733 return continueRunning
;
1736 //////////////////////////////////////////////////////////////////////
1737 bool CSystem::Update(CEnumFlags
<ESystemUpdateFlags
> updateFlags
, int nPauseMode
)
1739 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "System: Update");
1740 CRY_PROFILE_FUNCTION(PROFILE_SYSTEM
)
1741 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "CSystem::Update");
1743 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
1744 // do the dedicated sleep earlier than the frame profiler to avoid having it counted
1745 if (gEnv
->IsDedicated())
1747 #if defined(MAP_LOADING_SLICING)
1748 gEnv
->pSystemScheduler
->SchedulingSleepIfNeeded();
1749 #endif // defined(MAP_LOADING_SLICING)
1751 #endif //EXCLUDE_UPDATE_ON_CONSOLE
1752 #if CAPTURE_REPLAY_LOG
1753 if (CryGetIMemoryManager() && CryGetIMemReplay())
1755 CryGetIMemReplay()->AddFrameStart();
1756 if ((--m_ttMemStatSS
) <= 0)
1758 CryGetIMemReplay()->AddScreenshot();
1762 #endif //CAPTURE_REPLAY_LOG
1764 gEnv
->pOverloadSceneManager
->Update();
1766 m_pPlatformOS
->Tick(m_Time
.GetRealFrameTime());
1768 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
1769 if (g_cvars
.sys_keyboard_break
&& !g_breakListenerOn
)
1771 #if CRY_PLATFORM_WINDOWS
1772 if (m_env
.IsEditor() && !g_pBreakHotkeyThread
)
1774 g_pBreakHotkeyThread
= new SBreakHotKeyThread();
1775 if (!gEnv
->pThreadManager
->SpawnThread(g_pBreakHotkeyThread
, "WINAPI_BreakHotkeyListener"))
1777 CryFatalError("Error spawning \"WINAPI_BreakHotkeyListener\" thread.");
1781 if (!gEnv
->pThreadManager
->SpawnThread(&g_BreakListenerTask
, "BreakListener"))
1783 CryFatalError("Error spawning \"BreakListener\" thread.");
1785 gEnv
->pInput
->AddEventListener(&g_BreakListener
);
1786 g_breakListenerOn
= true;
1788 else if (!g_cvars
.sys_keyboard_break
&& g_breakListenerOn
)
1790 #if CRY_PLATFORM_WINDOWS
1791 if (g_pBreakHotkeyThread
)
1792 g_pBreakHotkeyThread
->SignalStopWork();
1794 gEnv
->pInput
->RemoveEventListener(&g_BreakListener
);
1795 g_BreakListenerTask
.SignalStopWork();
1796 g_breakListenerOn
= false;
1798 #endif //EXCLUDE_UPDATE_ON_CONSOLE
1801 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
1802 if (!m_sDelayedScreeenshot
.empty())
1804 gEnv
->pRenderer
->ScreenShot(m_sDelayedScreeenshot
.c_str());
1805 m_sDelayedScreeenshot
.clear();
1808 if (m_pUserCallback
)
1809 m_pUserCallback
->OnUpdate();
1811 //////////////////////////////////////////////////////////////////////////
1812 // Enable/Disable floating exceptions.
1813 //////////////////////////////////////////////////////////////////////////
1814 prev_sys_float_exceptions
+= 1 + g_cvars
.sys_float_exceptions
& prev_sys_float_exceptions
>> 31;
1815 if (prev_sys_float_exceptions
!= g_cvars
.sys_float_exceptions
)
1817 prev_sys_float_exceptions
= g_cvars
.sys_float_exceptions
;
1818 m_env
.pThreadManager
->EnableFloatExceptions((EFPE_Severity
) g_cvars
.sys_float_exceptions
); // Set FP Exceptions for this thread
1819 m_env
.pThreadManager
->EnableFloatExceptionsForEachOtherThread((EFPE_Severity
)g_cvars
.sys_float_exceptions
); // Set FP Exceptions for all other threads
1821 #endif //EXCLUDE_UPDATE_ON_CONSOLE
1822 //////////////////////////////////////////////////////////////////////////
1824 CTimeValue updateStart
= gEnv
->pTimer
->GetAsyncTime();
1828 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "Log::Update");
1829 m_env
.pLog
->Update();
1832 #if !defined(RELEASE) || defined(RELEASE_LOGGING)
1833 GetIRemoteConsole()->Update();
1836 if (gEnv
->pLocalMemoryUsage
!= NULL
)
1838 gEnv
->pLocalMemoryUsage
->OnUpdate();
1841 if (!gEnv
->IsEditor() && gEnv
->pRenderer
)
1843 CCamera rCamera
= GetViewCamera();
1845 // if aspect ratio changes or is different from default we need to update camera
1846 const float fNewAspectRatio
= gEnv
->pRenderer
->GetPixelAspectRatio();
1847 const int nNewWidth
= gEnv
->pRenderer
->GetOverlayWidth();
1848 const int nNewHeight
= gEnv
->pRenderer
->GetOverlayHeight();
1850 if ((fNewAspectRatio
!= rCamera
.GetPixelAspectRatio()) ||
1851 (nNewWidth
!= rCamera
.GetViewSurfaceX()) ||
1852 (nNewHeight
!= rCamera
.GetViewSurfaceZ()))
1858 rCamera
.GetNearPlane(),
1859 rCamera
.GetFarPlane(),
1862 SetViewCamera(rCamera
);
1866 #if defined (CRY_TESTING) && !defined(EXCLUDE_UPDATE_ON_CONSOLE)
1868 m_pTestSystem
->Update();
1870 if (nPauseMode
!= 0)
1875 if (m_pStreamEngine
)
1877 m_pStreamEngine
->Update();
1879 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
1880 if (m_bIgnoreUpdates
)
1882 #endif //EXCLUDE_UPDATE_ON_CONSOLE
1884 const bool bNotLoading
= !IsLoading();
1886 if (m_env
.pCharacterManager
)
1890 m_env
.pCharacterManager
->Update(nPauseMode
!= 0);
1894 m_env
.pCharacterManager
->DummyUpdate();
1898 bool bNoUpdate
= false;
1899 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
1900 //check what is the current process
1901 IProcess
* pProcess
= GetIProcess();
1903 return (true); //should never happen
1905 if (m_sysNoUpdate
&& m_sysNoUpdate
->GetIVal())
1908 updateFlags
= { ESYSUPDATE_IGNORE_AI
, ESYSUPDATE_IGNORE_PHYSICS
};
1911 m_bNoUpdate
= bNoUpdate
;
1912 #endif //EXCLUDE_UPDATE_ON_CONSOLE
1913 //check if we are quitting from the game
1917 #if CRY_PLATFORM_WINDOWS
1918 // process window messages
1920 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:PeekMessageW");
1922 if (m_hWnd
&& ::IsWindow((HWND
)m_hWnd
))
1924 PumpWindowMessage(true, m_hWnd
);
1929 //////////////////////////////////////////////////////////////////////
1930 //update time subsystem
1931 m_Time
.UpdateOnFrameStart();
1933 // Don't do a thing if we're not in a level
1934 if (m_env
.p3DEngine
&& bNotLoading
)
1935 m_env
.p3DEngine
->OnFrameStart();
1937 //////////////////////////////////////////////////////////////////////
1938 // update rate limiter for dedicated server
1939 if (m_pServerThrottle
.get())
1940 m_pServerThrottle
->Update();
1942 //////////////////////////////////////////////////////////////////////
1943 // initial network update
1946 m_env
.pNetwork
->SyncWithGame(eNGS_FrameStart
);
1949 //////////////////////////////////////////////////////////////////////////
1950 // Update script system.
1951 if (m_env
.pScriptSystem
&& bNotLoading
)
1953 m_env
.pScriptSystem
->Update();
1959 !(updateFlags
& ESYSUPDATE_EDITOR
) ||
1960 (updateFlags
& ESYSUPDATE_EDITOR_AI_PHYSICS
);
1963 //////////////////////////////////////////////////////////////////////
1964 //update input system
1965 #if !CRY_PLATFORM_WINDOWS
1966 m_env
.pInput
->Update(true);
1968 bool bFocus
= (::GetForegroundWindow() == m_hWnd
) || m_env
.IsEditor();
1970 WriteLock
lock(g_lockInput
);
1971 m_env
.pInput
->Update(bFocus
);
1972 g_BreakListenerTask
.m_nBreakIdle
= 0;
1978 if (m_pHmdManager
&& m_sys_vr_support
->GetIVal())
1980 m_pHmdManager
->UpdateTracking(eVRComponent_All
);
1983 if (m_env
.pPhysicalWorld
&& m_env
.pPhysicalWorld
->GetPhysVars()->bForceSyncPhysics
)
1986 static_cast<CPhysicsThreadTask
*>(m_PhysThread
)->EnsureStepDone();
1989 //////////////////////////////////////////////////////////////////////////
1990 //update the dynamic response system.
1991 if (m_env
.pDynamicResponseSystem
)
1993 m_env
.pDynamicResponseSystem
->Update();
1996 //////////////////////////////////////////////////////////////////////////
1997 //update the mono runtime
1998 if (m_env
.pMonoRuntime
)
2000 m_env
.pMonoRuntime
->Update(updateFlags
.UnderlyingValue(), nPauseMode
);
2003 //////////////////////////////////////////////////////////////////////
2004 //update console system
2007 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:Console");
2009 if (!(updateFlags
& ESYSUPDATE_EDITOR
))
2010 m_env
.pConsole
->Update();
2012 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
2013 //////////////////////////////////////////////////////////////////////
2014 //update notification network system
2015 if (m_pNotificationNetwork
)
2017 m_pNotificationNetwork
->Update();
2019 #endif //EXCLUDE_UPDATE_ON_CONSOLE
2021 // When in Editor and outside of Game Mode we will need to update the listeners here.
2022 // But when in Editor and in Game Mode the ViewSystem will update the listeners.
2023 if (!m_env
.IsEditorGameMode())
2025 if (updateFlags
.Check(ESYSUPDATE_EDITOR
) && !bNoUpdate
&& nPauseMode
!= 1)
2027 gEnv
->pGameFramework
->GetIViewSystem()->UpdateAudioListeners();
2031 //////////////////////////////////////////////////////////////////////////
2032 // Update Resource Manager.
2033 //////////////////////////////////////////////////////////////////////////
2034 m_pResourceManager
->Update();
2036 //////////////////////////////////////////////////////////////////////
2037 // update physic system
2038 //static float time_zero = 0;
2039 if (!m_bUIFrameworkMode
&& bNotLoading
)
2041 if (m_sys_physics_enable_MT
->GetIVal() > 0 && !gEnv
->IsDedicated())
2042 CreatePhysicsThread();
2044 KillPhysicsThread();
2046 static int g_iPausedPhys
= 0;
2047 PhysicsVars
* pVars
= m_env
.pPhysicalWorld
->GetPhysVars();
2048 pVars
->threadLag
= 0;
2050 CPhysicsThreadTask
* pPhysicsThreadTask
= ((CPhysicsThreadTask
*)m_PhysThread
);
2051 if (!pPhysicsThreadTask
)
2053 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SystemUpdate: AllAIAndPhysics");
2055 //////////////////////////////////////////////////////////////////////
2056 // update entity system (a little bit) before physics
2057 if (nPauseMode
!= 1 && !bNoUpdate
)
2062 // intermingle physics/AI updates so that if we get a big timestep (frame rate glitch etc) the
2063 // AI gets to steer entities before they travel over cliffs etc.
2064 float maxTimeStep
= 0.0f
;
2065 if (m_env
.pAISystem
)
2066 maxTimeStep
= m_env
.pAISystem
->GetUpdateInterval();
2068 maxTimeStep
= 0.25f
;
2070 float fCurTime
= m_Time
.GetCurrTime();
2071 //float fPrevTime = m_env.pPhysicalWorld->GetPhysicsTime();
2072 float timeToDo
= m_Time
.GetFrameTime();//fCurTime - fPrevTime;
2073 if (m_env
.bMultiplayer
)
2074 timeToDo
= m_Time
.GetRealFrameTime();
2075 m_env
.pPhysicalWorld
->TracePendingRays();
2077 while (timeToDo
> 0.0001f
&& maxSteps
-- > 0)
2079 float thisStep
= min(maxTimeStep
, timeToDo
);
2080 timeToDo
-= thisStep
;
2082 if ((nPauseMode
!= 1) && !(updateFlags
& ESYSUPDATE_IGNORE_PHYSICS
) && g_cvars
.sys_physics
&& !bNoUpdate
)
2084 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:Physics");
2086 //int iPrevTime = m_env.pPhysicalWorld->GetiPhysicsTime();
2087 //float fPrevTime=m_env.pPhysicalWorld->GetPhysicsTime();
2088 pVars
->bMultithreaded
= 0;
2089 pVars
->timeScalePlayers
= 1.0f
;
2090 if (!(updateFlags
& ESYSUPDATE_MULTIPLAYER
))
2091 m_env
.pPhysicalWorld
->TimeStep(thisStep
);
2094 //@TODO: fixed step in game.
2096 if (m_env.pGame->UseFixedStep())
2098 m_env.pPhysicalWorld->TimeStep(fCurTime-fPrevTime, 0);
2099 int iCurTime = m_env.pPhysicalWorld->GetiPhysicsTime();
2101 m_env.pPhysicalWorld->SetiPhysicsTime(m_env.pGame->SnapTime(iPrevTime));
2102 int i, iStep=m_env.pGame->GetiFixedStep();
2103 float fFixedStep = m_env.pGame->GetFixedStep();
2104 for(i=min(20*iStep,m_env.pGame->SnapTime(iCurTime)-m_pGame->SnapTime(iPrevTime)); i>0; i-=iStep)
2106 m_env.pGame->ExecuteScheduledEvents();
2107 m_env.pPhysicalWorld->TimeStep(fFixedStep, ent_rigid|ent_skip_flagged);
2110 m_env.pPhysicalWorld->SetiPhysicsTime(iPrevTime);
2111 m_env.pPhysicalWorld->TimeStep(fCurTime-fPrevTime, ent_rigid|ent_flagged_only);
2113 m_env.pPhysicalWorld->SetiPhysicsTime(iPrevTime);
2114 m_env.pPhysicalWorld->TimeStep(fCurTime-fPrevTime, ent_living|ent_independent|ent_deleted);
2118 m_env
.pPhysicalWorld
->TimeStep(thisStep
);
2123 else if (!(g_iPausedPhys
++ & 31))
2124 m_env
.pPhysicalWorld
->TimeStep(0); // make sure objects get all notifications; flush deleted ents
2125 gEnv
->pPhysicalWorld
->TracePendingRays(2);
2129 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:PumpLoggedEvents");
2130 m_env
.pPhysicalWorld
->PumpLoggedEvents();
2134 if ((nPauseMode
== 0) && !(updateFlags
& ESYSUPDATE_IGNORE_AI
) && g_cvars
.sys_ai
&& !bNoUpdate
)
2136 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:AI");
2137 //////////////////////////////////////////////////////////////////////
2138 //update AI system - match physics
2139 if (m_env
.pAISystem
&& !m_cvAIUpdate
->GetIVal() && g_cvars
.sys_ai
)
2140 m_env
.pAISystem
->Update(gEnv
->pTimer
->GetFrameStartTime(), gEnv
->pTimer
->GetFrameTime());
2144 // Make sure we don't lag too far behind
2145 if ((nPauseMode
!= 1) && !(updateFlags
& ESYSUPDATE_IGNORE_PHYSICS
))
2147 if (fabsf(m_env
.pPhysicalWorld
->GetPhysicsTime() - fCurTime
) > 0.01f
)
2149 //GetILog()->LogToConsole("Adjusting physical world clock by %.5f", fCurTime-m_env.pPhysicalWorld->GetPhysicsTime());
2150 m_env
.pPhysicalWorld
->SetPhysicsTime(fCurTime
);
2158 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:PumpLoggedEvents");
2159 m_env
.pPhysicalWorld
->PumpLoggedEvents();
2162 //////////////////////////////////////////////////////////////////////
2163 // update entity system (a little bit) before physics
2164 if (nPauseMode
!= 1 && !bNoUpdate
)
2169 if ((nPauseMode
!= 1) && !(updateFlags
& ESYSUPDATE_IGNORE_PHYSICS
))
2171 pPhysicsThreadTask
->Resume();
2172 float lag
= pPhysicsThreadTask
->GetRequestedStep();
2174 if (pPhysicsThreadTask
->RequestStep(m_Time
.GetFrameTime()))
2176 pVars
->threadLag
= lag
+ m_Time
.GetFrameTime();
2177 //GetILog()->Log("Physics thread lags behind; accum time %.3f", pVars->threadLag);
2182 pPhysicsThreadTask
->Pause();
2183 m_env
.pPhysicalWorld
->TracePendingRays();
2184 m_env
.pPhysicalWorld
->TracePendingRays(2);
2185 m_env
.pPhysicalWorld
->TimeStep(0);
2187 if ((nPauseMode
== 0) && !(updateFlags
& ESYSUPDATE_IGNORE_AI
) && g_cvars
.sys_ai
&& !bNoUpdate
)
2189 CRY_PROFILE_REGION(PROFILE_SYSTEM
, "SysUpdate:AI");
2190 //////////////////////////////////////////////////////////////////////
2192 if (m_env
.pAISystem
&& !m_cvAIUpdate
->GetIVal())
2193 m_env
.pAISystem
->Update(gEnv
->pTimer
->GetFrameStartTime(), gEnv
->pTimer
->GetFrameTime());
2196 pe_params_waterman pwm
;
2197 pwm
.posViewer
= GetViewCamera().GetPosition();
2198 m_env
.pPhysicalWorld
->SetWaterManagerParams(&pwm
);
2201 // Use UI timer for CryMovie, because it should not be affected by pausing game time
2202 const float fMovieFrameTime
= m_Time
.GetFrameTime(ITimer::ETIMER_UI
);
2204 // Run movie system pre-update
2207 UpdateMovieSystem(updateFlags
.UnderlyingValue(), fMovieFrameTime
, true);
2210 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
2211 if (nPauseMode
!= 1)
2212 #endif //EXCLUDE_UPDATE_ON_CONSOLE
2214 //////////////////////////////////////////////////////////////////////
2215 //update entity system
2216 if (m_env
.pEntitySystem
&& !bNoUpdate
&& g_cvars
.sys_entitysystem
)
2218 m_env
.pEntitySystem
->Update();
2222 // Run movie system post-update
2225 UpdateMovieSystem(updateFlags
.UnderlyingValue(), fMovieFrameTime
, false);
2228 //////////////////////////////////////////////////////////////////////
2229 //update process (3D engine)
2230 if (!(updateFlags
& ESYSUPDATE_EDITOR
) && !bNoUpdate
)
2232 if (ITimeOfDay
* pTOD
= m_env
.p3DEngine
->GetTimeOfDay())
2235 if (m_env
.p3DEngine
)
2236 m_env
.p3DEngine
->Tick(); // clear per frame temp data
2238 if (m_pProcess
&& (m_pProcess
->GetFlags() & PROC_3DENGINE
))
2240 if ((nPauseMode
!= 1))
2241 if (!IsEquivalent(m_ViewCamera
.GetPosition(), Vec3(0, 0, 0), VEC_EPSILON
))
2243 if (m_env
.p3DEngine
)
2245 // m_env.p3DEngine->SetCamera(m_ViewCamera);
2246 m_pProcess
->Update();
2247 #ifndef EXCLUDE_UPDATE_ON_CONSOLE
2248 //////////////////////////////////////////////////////////////////////////
2249 // Strange, !do not remove... ask Timur for the meaning of this.
2250 //////////////////////////////////////////////////////////////////////////
2251 if (m_nStrangeRatio
> 32767)
2253 gEnv
->pScriptSystem
->SetGCFrequency(-1); // lets get nasty.
2255 //////////////////////////////////////////////////////////////////////////
2256 // Strange, !do not remove... ask Timur for the meaning of this.
2257 //////////////////////////////////////////////////////////////////////////
2258 if (m_nStrangeRatio
> 1000)
2260 if (m_pProcess
&& (m_pProcess
->GetFlags() & PROC_3DENGINE
))
2261 m_nStrangeRatio
+= cry_random(1, 11);
2263 #endif //EXCLUDE_UPDATE_ON_CONSOLE
2264 //////////////////////////////////////////////////////////////////////////
2271 m_pProcess
->Update();
2275 //////////////////////////////////////////////////////////////////////
2276 //update sound system part 2
2279 UpdateAudioSystems();
2282 //////////////////////////////////////////////////////////////////////
2283 // final network update
2286 m_env
.pNetwork
->SyncWithGame(eNGS_FrameEnd
);
2287 m_env
.pNetwork
->SyncWithGame(eNGS_DisplayDebugInfo
);
2288 m_env
.pNetwork
->SyncWithGame(eNGS_WakeNetwork
); // This will wake the network thread up
2291 #ifdef DOWNLOAD_MANAGER
2292 if (m_pDownloadManager
&& !bNoUpdate
)
2294 m_pDownloadManager
->Update();
2296 #endif //DOWNLOAD_MANAGER
2297 #if !CRY_PLATFORM_LINUX && !CRY_PLATFORM_ANDROID && !CRY_PLATFORM_ORBIS
2298 if (m_sys_SimulateTask
->GetIVal() > 0)
2300 // have a chance to win longest Pi calculation content
2301 int64 delay
= m_sys_SimulateTask
->GetIVal();
2302 int64 start
= CryGetTicks();
2303 double a
= 1.0, b
= 1.0 / sqrt(2.0), t
= 1.0 / 4.0, p
= 1.0, an
, bn
, tn
, pn
, Pi
= 0.0;
2304 while (CryGetTicks() - start
< delay
)
2309 tn
= t
- p
* (a
- an
) * (a
- an
);
2317 Pi
= (a
+ b
) * (a
+ b
) / 4 / t
;
2319 //CryLog("Task calculate PI = %f ", Pi); // Thats funny , but it works :-)
2323 //////////////////////////////////////////////////////////////////////////
2324 //update stats agent
2325 #ifdef ENABLE_STATS_AGENT
2326 CStatsAgent::Update();
2327 #endif // #ifdef ENABLE_STATS_AGENT
2329 m_pSystemEventDispatcher
->Update();
2331 if (gEnv
->pSchematyc
!= nullptr)
2333 gEnv
->pSchematyc
->Update();
2336 if (gEnv
->pSchematyc2
!= nullptr)
2338 gEnv
->pSchematyc2
->Update();
2341 if (m_env
.pHardwareMouse
!= nullptr)
2343 m_env
.pHardwareMouse
->Update();
2346 //Now update frame statistics
2347 CTimeValue cur_time
= gEnv
->pTimer
->GetAsyncTime();
2349 CTimeValue
a_second(g_cvars
.sys_update_profile_time
);
2350 std::vector
<std::pair
<CTimeValue
, float>>::iterator it
= m_updateTimes
.begin();
2351 for (std::vector
<std::pair
<CTimeValue
, float>>::iterator eit
= m_updateTimes
.end(); it
!= eit
; ++it
)
2352 if ((cur_time
- it
->first
) < a_second
)
2355 if (it
!= m_updateTimes
.begin())
2356 m_updateTimes
.erase(m_updateTimes
.begin(), it
);
2358 float updateTime
= (cur_time
- updateStart
).GetMilliSeconds();
2359 m_updateTimes
.push_back(std::make_pair(cur_time
, updateTime
));
2361 UpdateUpdateTimes();
2366 IManualFrameStepController
* CSystem::GetManualFrameStepController() const
2368 return m_pManualFrameStepController
;
2371 bool CSystem::UpdateLoadtime()
2373 m_pPlatformOS
->Tick(m_Time
.GetRealFrameTime());
2376 // uncomment this code if input processing is required
2377 // during level loading
2380 //////////////////////////////////////////////////////////////////////
2381 //update input system
2382 #if !CRY_PLATFORM_WINDOWS
2383 m_env.pInput->Update(true);
2385 bool bFocus = (GetFocus()==m_hWnd) || m_bEditor;
2387 WriteLock lock(g_lockInput);
2388 m_env.pInput->Update(bFocus);
2389 g_BreakListenerTask.m_nBreakIdle = 0;
2398 void CSystem::UpdateAudioSystems()
2400 const bool isLoadInProgress
= m_systemGlobalState
> ESYSTEM_GLOBAL_STATE_INIT
&&
2401 m_systemGlobalState
<= ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_END
;
2403 if (m_env
.pAudioSystem
!= nullptr && !isLoadInProgress
) //do not update pAudioSystem during async level load
2405 CRY_PROFILE_SECTION(PROFILE_SYSTEM
, "UpdateAudioSystems");
2407 m_env
.pAudioSystem
->ExternalUpdate();
2411 //////////////////////////////////////////////////////////////////////////
2412 void CSystem::GetUpdateStats(SSystemUpdateStats
& stats
)
2414 if (m_updateTimes
.empty())
2416 stats
= SSystemUpdateStats();
2420 stats
.avgUpdateTime
= 0;
2421 stats
.maxUpdateTime
= -FLT_MAX
;
2422 stats
.minUpdateTime
= +FLT_MAX
;
2423 for (std::vector
<std::pair
<CTimeValue
, float>>::const_iterator it
= m_updateTimes
.begin(), eit
= m_updateTimes
.end(); it
!= eit
; ++it
)
2425 const float t
= it
->second
;
2426 stats
.avgUpdateTime
+= t
;
2427 stats
.maxUpdateTime
= max(stats
.maxUpdateTime
, t
);
2428 stats
.minUpdateTime
= min(stats
.minUpdateTime
, t
);
2430 stats
.avgUpdateTime
/= m_updateTimes
.size();
2432 size_t sz
= m_updateTimes
.size();
2435 const std::pair
<CTimeValue
, float> head
= m_updateTimes
.front();
2436 const std::pair
<CTimeValue
, float> tail
= m_updateTimes
.back();
2437 stats
.avgUpdateRate
= (sz
- 1) / (tail
.first
- head
.first
).GetSeconds();
2441 stats
.avgUpdateRate
= 0.0f
;
2446 //////////////////////////////////////////////////////////////////////////
2447 void CSystem::UpdateMovieSystem(const int updateFlags
, const float fFrameTime
, const bool bPreUpdate
)
2449 if (m_env
.pMovieSystem
&& !(updateFlags
& ESYSUPDATE_EDITOR
) && g_cvars
.sys_trackview
)
2451 float fMovieFrameTime
= fFrameTime
;
2453 if (fMovieFrameTime
> g_cvars
.sys_maxTimeStepForMovieSystem
)
2454 fMovieFrameTime
= g_cvars
.sys_maxTimeStepForMovieSystem
;
2458 m_env
.pMovieSystem
->PreUpdate(fMovieFrameTime
);
2462 m_env
.pMovieSystem
->PostUpdate(fMovieFrameTime
);
2467 //////////////////////////////////////////////////////////////////////////
2469 //////////////////////////////////////////////////////////////////////////
2471 //////////////////////////////////////////////////////////////////////////
2472 XmlNodeRef
CSystem::CreateXmlNode(const char* sNodeName
, bool bReuseStrings
)
2474 return new CXmlNode(sNodeName
, bReuseStrings
);
2477 //////////////////////////////////////////////////////////////////////////
2478 IXmlUtils
* CSystem::GetXmlUtils()
2483 //////////////////////////////////////////////////////////////////////////
2484 void CSystem::SetViewCamera(CCamera
& Camera
)
2486 m_ViewCamera
= Camera
;
2487 m_ViewCamera
.CalculateRenderMatrices();
2490 //////////////////////////////////////////////////////////////////////////
2491 XmlNodeRef
CSystem::LoadXmlFromFile(const char* sFilename
, bool bReuseStrings
)
2493 LOADING_TIME_PROFILE_SECTION_ARGS(sFilename
);
2495 return m_pXMLUtils
->LoadXmlFromFile(sFilename
, bReuseStrings
);
2498 //////////////////////////////////////////////////////////////////////////
2499 XmlNodeRef
CSystem::LoadXmlFromBuffer(const char* buffer
, size_t size
, bool bReuseStrings
)
2501 LOADING_TIME_PROFILE_SECTION
2502 return m_pXMLUtils
->LoadXmlFromBuffer(buffer
, size
, bReuseStrings
);
2505 //////////////////////////////////////////////////////////////////////////
2506 bool CSystem::CheckLogVerbosity(int verbosity
)
2508 if (verbosity
<= m_env
.pLog
->GetVerbosityLevel())
2513 //////////////////////////////////////////////////////////////////////////
2514 void CSystem::Warning(EValidatorModule module
, EValidatorSeverity severity
, int flags
, const char* file
, const char* format
, ...)
2517 va_start(args
, format
);
2518 WarningV(module
, severity
, flags
, file
, format
, args
);
2522 //////////////////////////////////////////////////////////////////////////
2523 void CSystem::WarningOnce(EValidatorModule module
, EValidatorSeverity severity
, int flags
, const char* file
, const char* format
, ...)
2525 char szBuffer
[MAX_WARNING_LENGTH
];
2527 va_start(args
, format
);
2528 cry_vsprintf(szBuffer
, format
, args
);
2531 CryAutoLock
<CryMutex
> lock(m_mapWarningOnceMutex
);
2532 uint32 crc
= CCrc32::ComputeLowercase(szBuffer
);
2533 if (m_mapWarningOnceAlreadyPrinted
.find(crc
) == m_mapWarningOnceAlreadyPrinted
.end())
2535 m_mapWarningOnceAlreadyPrinted
[crc
] = true;
2537 Warning(VALIDATOR_MODULE_ANIMATION
, VALIDATOR_WARNING
, VALIDATOR_FLAG_FILE
, 0, szBuffer
);
2541 inline const char* ValidatorModuleToString(EValidatorModule module
)
2545 case VALIDATOR_MODULE_RENDERER
:
2547 case VALIDATOR_MODULE_3DENGINE
:
2549 case VALIDATOR_MODULE_ASSETS
:
2551 case VALIDATOR_MODULE_AI
:
2553 case VALIDATOR_MODULE_ANIMATION
:
2555 case VALIDATOR_MODULE_ENTITYSYSTEM
:
2556 return "EntitySystem";
2557 case VALIDATOR_MODULE_SCRIPTSYSTEM
:
2559 case VALIDATOR_MODULE_SYSTEM
:
2561 case VALIDATOR_MODULE_AUDIO
:
2563 case VALIDATOR_MODULE_GAME
:
2565 case VALIDATOR_MODULE_MOVIE
:
2567 case VALIDATOR_MODULE_EDITOR
:
2569 case VALIDATOR_MODULE_NETWORK
:
2571 case VALIDATOR_MODULE_PHYSICS
:
2573 case VALIDATOR_MODULE_FLOWGRAPH
:
2575 case VALIDATOR_MODULE_ONLINE
:
2577 case VALIDATOR_MODULE_DRS
:
2578 return "DynamicResponseSystem";
2583 //////////////////////////////////////////////////////////////////////////
2584 void CSystem::WarningV(EValidatorModule module
, EValidatorSeverity severity
, int flags
, const char* file
, const char* format
, va_list args
)
2586 // Fran: No logging in a testing environment
2587 if (m_env
.pLog
== 0)
2592 const char* sModuleFilter
= m_env
.pLog
->GetModuleFilter();
2593 if (sModuleFilter
&& *sModuleFilter
!= 0)
2595 const char* sModule
= ValidatorModuleToString(module
);
2596 if (strlen(sModule
) > 1 || CryStringUtils::stristr(sModule
, sModuleFilter
) == 0)
2598 // Filter out warnings from other modules.
2603 bool bDbgBreak
= false;
2604 if (severity
== VALIDATOR_ERROR_DBGBRK
)
2607 severity
= VALIDATOR_ERROR
; // change it to a standard VALIDATOR_ERROR for simplicity in the rest of the system
2610 IMiniLog::ELogType ltype
= ILog::eComment
;
2613 case VALIDATOR_ERROR
:
2614 ltype
= ILog::eError
;
2616 case VALIDATOR_WARNING
:
2617 ltype
= ILog::eWarning
;
2619 case VALIDATOR_COMMENT
:
2620 ltype
= ILog::eComment
;
2622 case VALIDATOR_ASSERT
:
2623 ltype
= ILog::eAssert
;
2628 char szBuffer
[MAX_WARNING_LENGTH
];
2629 cry_vsprintf(szBuffer
, format
, args
);
2633 CryFixedStringT
<MAX_WARNING_LENGTH
> fmt
= szBuffer
;
2638 m_env
.pLog
->LogWithType(ltype
, flags
| VALIDATOR_FLAG_SKIP_VALIDATOR
, "%s", fmt
.c_str());
2642 m_env
.pLog
->LogWithType(ltype
, flags
| VALIDATOR_FLAG_SKIP_VALIDATOR
, "%s", szBuffer
);
2646 //m_env.pLog->LogWithType( ltype, " ... caused by file '%s'",file);
2648 if (m_pValidator
&& (flags
& VALIDATOR_FLAG_SKIP_VALIDATOR
) == 0)
2650 SValidatorRecord record
;
2652 record
.text
= szBuffer
;
2653 record
.module
= module
;
2654 record
.severity
= severity
;
2655 record
.flags
= flags
;
2656 record
.assetScope
= m_env
.pLog
->GetAssetScopeString();
2657 m_pValidator
->Report(record
);
2660 #if !defined(_RELEASE)
2661 if (bDbgBreak
&& g_cvars
.sys_error_debugbreak
)
2666 //////////////////////////////////////////////////////////////////////////
2667 void CSystem::Deltree(const char* szFolder
, bool bRecurse
)
2670 string filespec
= szFolder
;
2674 if ((hfil
= _findfirst64(filespec
.c_str(), &fd
)) == -1)
2681 if (fd
.attrib
& _A_SUBDIR
)
2683 string name
= fd
.name
;
2685 if ((name
!= ".") && (name
!= ".."))
2693 Deltree(name
.c_str(), bRecurse
);
2699 string name
= szFolder
;
2703 DeleteFile(name
.c_str());
2707 while (!_findnext64(hfil
, &fd
));
2711 RemoveDirectory(szFolder
);
2714 //////////////////////////////////////////////////////////////////////////
2715 void CSystem::GetLocalizedPath(char const* const szLanguage
, string
& szLocalizedPath
)
2717 string pakSuffix
= (g_cvars
.sys_localization_pak_suffix
) ? g_cvars
.sys_localization_pak_suffix
->GetString() : "";
2718 szLocalizedPath
= PathUtil::GetLocalizationFolder() + CRY_NATIVE_PATH_SEPSTR
+ szLanguage
+ pakSuffix
+ ".pak";
2721 //////////////////////////////////////////////////////////////////////////
2722 void CSystem::GetLocalizedAudioPath(char const* const szLanguage
, string
& szLocalizedPath
)
2724 szLocalizedPath
= PathUtil::GetLocalizationFolder() + CRY_NATIVE_PATH_SEPSTR
+ szLanguage
+ ".pak";
2727 //////////////////////////////////////////////////////////////////////////
2728 void CSystem::CloseLanguagePak(char const* const szLanguage
)
2730 string szLocalizedPath
;
2731 GetLocalizedPath(szLanguage
, szLocalizedPath
);
2732 m_env
.pCryPak
->ClosePacks(szLocalizedPath
);
2735 //////////////////////////////////////////////////////////////////////////
2736 void CSystem::CloseLanguageAudioPak(char const* const szLanguage
)
2738 string szLocalizedPath
;
2739 GetLocalizedAudioPath(szLanguage
, szLocalizedPath
);
2740 m_env
.pCryPak
->ClosePacks(szLocalizedPath
);
2743 #if CRY_PLATFORM_DURANGO
2744 //////////////////////////////////////////////////////////////////////////
2745 void CSystem::OnPLMEvent(EPLM_Event event
)
2750 case EPLMEV_ON_RESUMING
:
2752 CryLogAlways("CSystem::OnPLMEvent --- OnResuming");
2753 if (m_pSystemEventDispatcher
)
2754 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_PLM_ON_RESUMING
, 0, 0);
2755 if (gEnv
->pRenderer
)
2756 gEnv
->pRenderer
->ResumeDevice();
2757 gEnv
->ePLM_State
= EPLM_RUNNING
;
2761 case EPLMEV_ON_SUSPENDING
:
2763 CryLogAlways("CSystem::OnPLMEvent --- OnSuspending");
2764 if (m_pSystemEventDispatcher
)
2765 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_PLM_ON_SUSPENDING
, 0, 0);
2766 if (gEnv
->pRenderer
)
2767 gEnv
->pRenderer
->SuspendDevice();
2768 gEnv
->ePLM_State
= EPLM_SUSPENDED
;
2772 case EPLMEV_ON_CONSTRAINED
:
2774 CryLogAlways("CSystem::OnPLMEvent --- OnConstrained");
2775 if (m_pSystemEventDispatcher
)
2776 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_PLM_ON_CONSTRAINED
, 0, 0);
2777 gEnv
->ePLM_State
= EPLM_CONSTRAINED
;
2781 case EPLMEV_ON_FULL
:
2783 CryLogAlways("CSystem::OnPLMEvent --- OnFull");
2784 if (m_pSystemEventDispatcher
)
2785 m_pSystemEventDispatcher
->OnSystemEvent(ESYSTEM_EVENT_PLM_ON_FULL
, 0, 0);
2786 gEnv
->ePLM_State
= EPLM_RUNNING
;
2792 CryWarning(VALIDATOR_MODULE_SYSTEM
, VALIDATOR_ERROR
, "Unhandled PLM Event!");
2799 //////////////////////////////////////////////////////////////////////////
2800 void CSystem::UnloadSchematycModule()
2802 UnloadEngineModule("CrySchematyc");
2803 UnloadEngineModule("CrySchematyc2");
2805 gEnv
->pSchematyc2
= nullptr;
2808 //////////////////////////////////////////////////////////////////////////
2809 void CSystem::Strange()
2811 m_nStrangeRatio
+= cry_random(1, 101);
2814 //////////////////////////////////////////////////////////////////////////
2815 void CSystem::Relaunch(bool bRelaunch
)
2817 if (m_sys_firstlaunch
)
2818 m_sys_firstlaunch
->Set(0);
2820 m_bRelaunch
= bRelaunch
;
2821 SaveConfiguration();
2824 //////////////////////////////////////////////////////////////////////////
2825 ICrySizer
* CSystem::CreateSizer()
2827 return new CrySizerImpl
;
2830 //////////////////////////////////////////////////////////////////////////
2831 uint32
CSystem::GetUsedMemory()
2833 return CryMemoryGetAllocatedSize();
2836 //////////////////////////////////////////////////////////////////////////
2837 ILocalizationManager
* CSystem::GetLocalizationManager()
2839 return m_pLocalizationManager
;
2842 //////////////////////////////////////////////////////////////////////////
2843 IResourceManager
* CSystem::GetIResourceManager()
2845 return m_pResourceManager
;
2848 //////////////////////////////////////////////////////////////////////////
2849 void CSystem::debug_GetCallStackRaw(void** callstack
, uint32
& callstackLength
)
2851 #if CRY_PLATFORM_ORBIS || CRY_PLATFORM_WINAPI
2852 uint32 callstackCapacity
= callstackLength
;
2855 #if CRY_PLATFORM_WINAPI
2856 uint32 nNumStackFramesToSkip
= 1;
2859 memset(callstack
, 0, sizeof(void*) * callstackLength
);
2861 #if !CRY_PLATFORM_ANDROID
2862 callstackLength
= 0;
2865 #if CRY_PLATFORM_ORBIS
2867 void** stack
= NULL
;
2868 __asm__
__volatile__ ("mov %%rbp, %0" : "=r" (stack
)); // WARNING: This could be brittle
2869 while (csLength
< callstackCapacity
&& stack
)
2871 callstack
[csLength
] = stack
[1];
2872 stack
= (void**)stack
[0];
2875 callstackLength
= csLength
;
2876 #elif CRY_PLATFORM_WINAPI
2877 if (callstackCapacity
> 0x40)
2878 callstackCapacity
= 0x40;
2879 callstackLength
= RtlCaptureStackBackTrace(nNumStackFramesToSkip
, callstackCapacity
, callstack
, NULL
);
2885 if ((aaa & 0xF) == 0)
2887 CryLogAlways( "RtlCaptureStackBackTrace = (%d)",callstackLength );
2888 for (int i=0; i<callstackLength; i++)
2890 CryLogAlways( " [%d] = (%X)",i,callstack[i] );
2894 callstackLength = IDebugCallStack::instance()->CollectCallStackFrames( callstack,callstackCapacity );
2895 if ((aaa & 0xF) == 0)
2897 CryLogAlways( "StackWalk64 = (%d)",callstackLength );
2898 for (int i=0; i<callstackLength; i++)
2900 CryLogAlways( " [%d] = (%X)",i,callstack[i] );
2905 if (callstackLength
> 0)
2907 std::reverse(callstack
, callstack
+ callstackLength
);
2911 //////////////////////////////////////////////////////////////////////////
2912 void CSystem::ExecuteCommandLine()
2914 LOADING_TIME_PROFILE_SECTION
;
2915 // should only be called once
2917 static bool bCalledAlready
= false;
2918 assert(!bCalledAlready
);
2919 bCalledAlready
= true;
2922 // auto detect system spec (overrides profile settings)
2923 if (m_pCmdLine
->FindArg(eCLAT_Pre
, "autodetect"))
2924 AutoDetectSpec(false);
2926 // execute command line arguments e.g. +g_gametype ASSAULT +map "testy"
2928 ICmdLine
* pCmdLine
= GetICmdLine();
2931 const int iCnt
= pCmdLine
->GetArgCount();
2933 for (int i
= 0; i
< iCnt
; ++i
)
2935 const ICmdLineArg
* pCmd
= pCmdLine
->GetArg(i
);
2937 if (pCmd
->GetType() == eCLAT_Post
)
2939 string sLine
= pCmd
->GetName();
2941 if (gEnv
->pSystem
->IsCVarWhitelisted(sLine
.c_str(), false))
2943 if (pCmd
->GetValue())
2944 sLine
+= string(" ") + pCmd
->GetValue();
2946 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)
2947 GetIConsole()->ExecuteString(sLine
.c_str(), false, !m_bShaderCacheGenMode
);
2949 #if defined(DEDICATED_SERVER)
2952 GetILog()->LogError("Failed to execute command: '%s' as it is not whitelisted\n", sLine
.c_str());
2958 //gEnv->pConsole->ExecuteString("sys_RestoreSpec test*"); // to get useful debugging information about current spec settings to the log file
2961 ITextModeConsole
* CSystem::GetITextModeConsole()
2963 if (m_env
.IsDedicated())
2964 return m_pTextModeConsole
;
2969 //////////////////////////////////////////////////////////////////////////
2970 ESystemConfigSpec
CSystem::GetConfigSpec(bool bClient
)
2975 return (ESystemConfigSpec
)m_sys_spec
->GetIVal();
2976 return CONFIG_VERYHIGH_SPEC
; // highest spec.
2979 return m_nServerConfigSpec
;
2982 //////////////////////////////////////////////////////////////////////////
2983 void CSystem::SetConfigSpec(ESystemConfigSpec spec
, bool bClient
)
2988 m_sys_spec
->Set((int)spec
);
2992 m_nServerConfigSpec
= spec
;
2996 //////////////////////////////////////////////////////////////////////////
2997 ESystemConfigSpec
CSystem::GetMaxConfigSpec() const
2999 return m_nMaxConfigSpec
;
3002 //////////////////////////////////////////////////////////////////////////
3003 Cry::IProjectManager
* CSystem::GetIProjectManager()
3005 return m_pProjectManager
;
3008 //////////////////////////////////////////////////////////////////////////
3009 CPNoise3
* CSystem::GetNoiseGen()
3011 static CPNoise3 m_pNoiseGen
;
3012 return &m_pNoiseGen
;
3015 //////////////////////////////////////////////////////////////////////////
3016 sUpdateTimes
& CSystem::GetCurrentUpdateTimeStats()
3018 return m_UpdateTimes
[m_UpdateTimesIdx
];
3021 //////////////////////////////////////////////////////////////////////////
3022 const sUpdateTimes
* CSystem::GetUpdateTimeStats(uint32
& index
, uint32
& num
)
3024 index
= m_UpdateTimesIdx
;
3025 num
= NUM_UPDATE_TIMES
;
3026 return m_UpdateTimes
;
3029 void CSystem::FillRandomMT(uint32
* pOutWords
, uint32 numWords
)
3031 AUTO_LOCK(m_mtLock
);
3040 TicksTime tt
= { CryGetTicks(), time(nullptr) };
3041 m_pMtState
= new CMTRand_int32(reinterpret_cast<uint32
*>(&tt
), sizeof(tt
) / sizeof(uint32
));
3044 for (uint32 i
= 0; i
< numWords
; ++i
)
3045 pOutWords
[i
] = m_pMtState
->GenerateUint32();
3048 void CSystem::UpdateUpdateTimes()
3050 sUpdateTimes
& sample
= m_UpdateTimes
[m_UpdateTimesIdx
];
3053 static uint64 lastMainTime
= 0U;
3054 static uint64 lastPhysWait
= 0U;
3055 uint64 physTime
= 0, mainTime
= 0;
3057 physTime
= ((CPhysicsThreadTask
*)m_PhysThread
)->LastStepTaken();
3058 mainTime
= CryGetTicks() - lastMainTime
;
3059 lastMainTime
= mainTime
;
3060 lastPhysWait
= ((CPhysicsThreadTask
*)m_PhysThread
)->LastWaitTime();
3061 sample
.PhysStepTime
= physTime
;
3062 sample
.SysUpdateTime
= mainTime
;
3063 sample
.PhysYields
= yields
;
3064 sample
.physWaitTime
= lastPhysWait
;
3067 if (m_UpdateTimesIdx
>= NUM_UPDATE_TIMES
) m_UpdateTimesIdx
= 0;
3070 IPhysicsDebugRenderer
* CSystem::GetIPhysicsDebugRenderer()
3072 return m_pPhysRenderer
;
3075 IPhysRenderer
* CSystem::GetIPhysRenderer()
3077 return m_pPhysRenderer
;
3080 ICryProfilingSystem
* CSystem::GetProfilingSystem()
3082 return m_pProfilingSystem
;
3085 ILegacyProfiler
* CSystem::GetLegacyProfilerInterface()
3087 return m_pLegacyProfiler
;
3091 void CSystem::GetCheckpointData(ICheckpointData
& data
)
3093 data
.m_totalLoads
= m_checkpointLoadCount
;
3094 data
.m_loadOrigin
= m_loadOrigin
;
3097 void CSystem::IncreaseCheckpointLoadCount()
3099 if (!m_hasJustResumed
)
3100 ++m_checkpointLoadCount
;
3102 m_hasJustResumed
= false;
3105 void CSystem::SetLoadOrigin(LevelLoadOrigin origin
)
3109 case eLLO_NewLevel
: // Intentional fall through
3110 case eLLO_Level2Level
:
3111 m_expectingMapCommand
= true;
3115 m_hasJustResumed
= true;
3119 if (m_expectingMapCommand
)
3121 // We knew a map command was coming, so don't process this.
3122 m_expectingMapCommand
= false;
3128 m_loadOrigin
= origin
;
3129 m_checkpointLoadCount
= 0;
3133 //////////////////////////////////////////////////////////////////////
3134 void CSystem::OnLanguageCVarChanged(ICVar
* const pLanguage
)
3136 if (pLanguage
!= nullptr && pLanguage
->GetType() == ECVarType::String
)
3138 CSystem
* const pSystem
= static_cast<CSystem
*>(gEnv
->pSystem
);
3140 if (pSystem
!= nullptr)
3142 CLocalizedStringsManager
* const pLocalizationManager
= static_cast<CLocalizedStringsManager
* const>(pSystem
->GetLocalizationManager());
3144 if (pLocalizationManager
!= nullptr)
3146 char const* const szCurrentLanguage
= pLocalizationManager
->GetLanguage();
3148 if (szCurrentLanguage
!= nullptr && szCurrentLanguage
[0] != '\0')
3150 pSystem
->CloseLanguagePak(szCurrentLanguage
);
3153 CLocalizedStringsManager::TLocalizationTagVec tags
;
3154 pLocalizationManager
->GetLoadedTags(tags
);
3155 pLocalizationManager
->FreeLocalizationData();
3157 char const* const szNewLanguage
= pLanguage
->GetString();
3158 pSystem
->OpenLanguagePak(szNewLanguage
);
3159 pLocalizationManager
->SetLanguage(szNewLanguage
);
3161 for (auto& tag
: tags
)
3163 pLocalizationManager
->LoadLocalizationDataByTag(tag
.c_str());
3166 #if defined(INCLUDE_SCALEFORM_SDK) || defined(CRY_FEATURE_SCALEFORM_HELPER)
3167 if (gEnv
->pScaleformHelper
)
3169 gEnv
->pScaleformHelper
->SetTranslatorDirty(true);
3177 //////////////////////////////////////////////////////////////////////
3178 void CSystem::OnLanguageAudioCVarChanged(ICVar
* const pLanguageAudio
)
3180 if (pLanguageAudio
!= nullptr && pLanguageAudio
->GetType() == ECVarType::String
)
3182 CSystem
* const pSystem
= static_cast<CSystem
*>(gEnv
->pSystem
);
3184 if (pSystem
!= nullptr)
3186 char const* const szNewLanguage
= pLanguageAudio
->GetString();
3188 if (!pSystem
->m_currentLanguageAudio
.empty())
3190 pSystem
->CloseLanguageAudioPak(pSystem
->m_currentLanguageAudio
.c_str());
3193 pSystem
->OpenLanguageAudioPak(szNewLanguage
);
3194 pSystem
->m_currentLanguageAudio
= szNewLanguage
;
3196 pSystem
->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_AUDIO_LANGUAGE_CHANGED
, 0, 0);
3201 //////////////////////////////////////////////////////////////////////////
3202 void CSystem::OnLocalizationFolderCVarChanged(ICVar
* const pLocalizationFolder
)
3204 if (pLocalizationFolder
&& pLocalizationFolder
->GetType() == ECVarType::String
)
3206 CSystem
* const pSystem
= static_cast<CSystem
* const>(gEnv
->pSystem
);
3208 if (pSystem
!= NULL
&& gEnv
->pCryPak
!= NULL
)
3210 CLocalizedStringsManager
* const pLocalizationManager
= static_cast<CLocalizedStringsManager
* const>(pSystem
->GetLocalizationManager());
3212 if (pLocalizationManager
)
3214 // Get what is currently loaded
3215 CLocalizedStringsManager::TLocalizationTagVec tags
;
3216 pLocalizationManager
->GetLoadedTags(tags
);
3218 // Release the old localization data.
3219 for (auto& tag
: tags
)
3221 pLocalizationManager
->ReleaseLocalizationDataByTag(tag
.c_str());
3224 // Close the paks situated in the previous localization folder.
3225 pSystem
->CloseLanguagePak(pLocalizationManager
->GetLanguage());
3226 pSystem
->CloseLanguageAudioPak(pSystem
->m_currentLanguageAudio
.c_str());
3228 // Set the new localization folder.
3229 gEnv
->pCryPak
->SetLocalizationFolder(pLocalizationFolder
->GetString());
3231 // Now open the paks situated in the new localization folder.
3232 pSystem
->OpenLanguagePak(pLocalizationManager
->GetLanguage());
3233 pSystem
->OpenLanguageAudioPak(pSystem
->m_currentLanguageAudio
.c_str());
3235 // And load the new data.
3236 for (auto& tag
: tags
)
3238 pLocalizationManager
->LoadLocalizationDataByTag(tag
.c_str());
3245 void CSystem::OnSystemEvent(ESystemEvent event
, UINT_PTR wparam
, UINT_PTR lparam
)
3249 case ESYSTEM_EVENT_LEVEL_LOAD_END
:
3251 SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_END
);
3254 case ESYSTEM_EVENT_LEVEL_LOAD_START_LOADINGSCREEN
:
3255 case ESYSTEM_EVENT_LEVEL_UNLOAD
:
3257 gEnv
->pCryPak
->DisableRuntimeFileAccess(false);
3260 case ESYSTEM_EVENT_LEVEL_PRECACHE_END
:
3262 if (!gEnv
->IsEditing())
3264 gEnv
->pCryPak
->DisableRuntimeFileAccess(true);
3271 ESystemGlobalState
CSystem::GetSystemGlobalState(void)
3273 return m_systemGlobalState
;
3276 const char* CSystem::GetSystemGlobalStateName(const ESystemGlobalState systemGlobalState
)
3278 static const char* const s_systemGlobalStateNames
[] = {
3279 "INIT", // ESYSTEM_GLOBAL_STATE_INIT,
3280 "LEVEL_LOAD_PREPARE", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PREPARE,
3281 "LEVEL_LOAD_START", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START,
3282 "LEVEL_LOAD_MATERIALS", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_MATERIALS,
3283 "LEVEL_LOAD_OBJECTS", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_OBJECTS,
3284 "LEVEL_LOAD_CHARACTERS", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_CHARACTERS,
3285 "LEVEL_LOAD_STATIC_WORLD", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_STATIC_WORLD,
3286 "LEVEL_LOAD_ENTITIES", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_ENTITIES,
3287 "LEVEL_LOAD_PRECACHE", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PRECACHE,
3288 "LEVEL_LOAD_TEXTURES", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_TEXTURES,
3289 "LEVEL_LOAD_END", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_END,
3290 "LEVEL_LOAD_ENDING", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_ENDING,
3291 "LEVEL_LOAD_COMPLETE", // ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_COMPLETE
3292 "RUNNING", // ESYSTEM_GLOBAL_STATE_RUNNING,
3294 const size_t numElements
= CRY_ARRAY_COUNT(s_systemGlobalStateNames
);
3295 const size_t index
= (size_t)systemGlobalState
;
3296 if (index
>= numElements
)
3298 return "INVALID INDEX";
3300 return s_systemGlobalStateNames
[index
];
3303 void CSystem::SetSystemGlobalState(const ESystemGlobalState systemGlobalState
)
3305 static CTimeValue s_startTime
= CTimeValue();
3306 if (systemGlobalState
!= m_systemGlobalState
)
3308 if (gEnv
&& gEnv
->pTimer
)
3310 #if !defined(EXCLUDE_NORMAL_LOG)
3311 const CTimeValue endTime
= gEnv
->pTimer
->GetAsyncTime();
3312 const float numSeconds
= endTime
.GetDifferenceInSeconds(s_startTime
);
3314 CryLog("SetGlobalState %d->%d '%s'->'%s' %3.1f seconds",
3315 m_systemGlobalState
, systemGlobalState
,
3316 CSystem::GetSystemGlobalStateName(m_systemGlobalState
), CSystem::GetSystemGlobalStateName(systemGlobalState
),
3318 s_startTime
= gEnv
->pTimer
->GetAsyncTime();
3321 m_systemGlobalState
= systemGlobalState
;
3324 //////////////////////////////////////////////////////////////////////////
3325 void CSystem::RegisterWindowMessageHandler(IWindowMessageHandler
* pHandler
)
3327 assert(pHandler
&& !stl::find(m_windowMessageHandlers
, pHandler
) && "This IWindowMessageHandler is already registered");
3328 m_windowMessageHandlers
.push_back(pHandler
);
3331 //////////////////////////////////////////////////////////////////////////
3332 void CSystem::UnregisterWindowMessageHandler(IWindowMessageHandler
* pHandler
)
3334 #if defined(USE_CRY_ASSERT)
3335 bool bRemoved
= stl::find_and_erase(m_windowMessageHandlers
, pHandler
);
3336 assert(pHandler
&& bRemoved
&& "This IWindowMessageHandler was not registered");
3338 stl::find_and_erase(m_windowMessageHandlers
, pHandler
);
3342 //////////////////////////////////////////////////////////////////////////
3343 int CSystem::PumpWindowMessage(bool bAll
, CRY_HWND opaqueHWnd
)
3345 #if CRY_PLATFORM_WINDOWS
3347 const HWND hWnd
= (HWND
)opaqueHWnd
;
3348 const bool bUnicode
= hWnd
!= NULL
?
3349 IsWindowUnicode(hWnd
) != FALSE
:
3350 !(gEnv
&& gEnv
->IsEditor());
3351 #if defined(UNICODE) || defined(_UNICODE)
3352 // Once we compile as Unicode app on Windows, we should detect non-Unicode windows
3353 assert(bUnicode
&& "The window is not Unicode, this is most likely a bug");
3356 // Pick the correct function for handling messages
3357 typedef BOOL (WINAPI
* PeekMessageFunc
)(MSG
*, HWND
, UINT
, UINT
, UINT
);
3358 typedef LRESULT (WINAPI
* DispatchMessageFunc
)(const MSG
*);
3359 const PeekMessageFunc pfnPeekMessage
= bUnicode
? PeekMessageW
: PeekMessageA
;
3360 const DispatchMessageFunc pfnDispatchMessage
= bUnicode
? DispatchMessageW
: DispatchMessageA
;
3364 // Get a new message
3366 BOOL bHasMessage
= pfnPeekMessage(&msg
, hWnd
, 0, 0, PM_REMOVE
);
3367 if (bHasMessage
== FALSE
) break;
3370 // Special case for WM_QUIT
3371 if (msg
.message
== WM_QUIT
)
3376 if (msg
.message
== WM_ACTIVATE
)
3378 if (msg
.wParam
!= WA_INACTIVE
)
3379 m_hWndActive
= msg
.hwnd
;
3381 m_hWndActive
= (CRY_HWND
)msg
.lParam
;
3383 // During the time demo, do not sleep even in inactive window.
3384 if (!gEnv
->pGameFramework
|| !gEnv
->pGameFramework
->IsInTimeDemo())
3385 // use sys_maxFPS to throttle the engine
3386 m_throttleFPS
= msg
.wParam
!= WA_INACTIVE
;
3389 // Pre-process the message for IME
3390 if (msg
.hwnd
== m_hWnd
)
3392 for (std::vector
<IWindowMessageHandler
*>::const_iterator it
= m_windowMessageHandlers
.begin(); it
!= m_windowMessageHandlers
.end(); ++it
)
3394 IWindowMessageHandler
* pHandler
= *it
;
3395 pHandler
->PreprocessMessage(msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
3399 // Dispatch the message
3400 TranslateMessage(&msg
);
3401 pfnDispatchMessage(&msg
);
3407 // No window message support on this platform
3412 //////////////////////////////////////////////////////////////////////////
3413 bool CSystem::IsImeSupported() const
3415 assert(m_pImeManager
!= NULL
);
3416 return m_pImeManager
->IsImeSupported();
3419 //////////////////////////////////////////////////////////////////////////
3420 bool CSystem::IsCVarWhitelisted(const char* szName
, bool silent
) const
3422 CRY_ASSERT(szName
!= nullptr);
3424 if (szName
[0] == '?')
3429 if (szName
[0] == '+')
3434 const char* pNameEnd
= std::max(strchr(szName
, ' '), strchr(szName
, '='));
3435 if (pNameEnd
== nullptr)
3437 return ::IsCVarWhitelisted(szName
);
3441 const string
name(szName
, pNameEnd
);
3442 return ::IsCVarWhitelisted(name
.c_str());
3446 //////////////////////////////////////////////////////////////////////////
3447 #if CRY_PLATFORM_WINDOWS
3449 enum class EMouseWheelOrigin
3456 #ifndef GET_X_LPARAM
3457 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
3459 #ifndef GET_Y_LPARAM
3460 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
3463 bool CSystem::HandleMessage(CRY_HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
* pResult
)
3465 static bool sbInSizingModalLoop
;
3466 int x
= GET_X_LPARAM(lParam
);
3467 int y
= GET_Y_LPARAM(lParam
);
3468 EHARDWAREMOUSEEVENT event
= (EHARDWAREMOUSEEVENT
)-1;
3472 // System event translation
3477 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_MOVE
, x
, y
);
3480 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_RESIZE
, x
, y
);
3482 case WM_WINDOWPOSCHANGED
:
3483 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_POS_CHANGED
, 1, 0);
3485 case WM_STYLECHANGED
:
3486 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_STYLE_CHANGED
, 1, 0);
3489 // Pass HIWORD(wParam) as well to indicate whether this window is minimized or not
3490 // HIWORD(wParam) != 0 is minimized, HIWORD(wParam) == 0 is not minimized
3491 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_ACTIVATE
, LOWORD(wParam
) != WA_INACTIVE
, HIWORD(wParam
));
3495 m_hasWindowFocus
= uMsg
== WM_SETFOCUS
;
3496 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_CHANGE_FOCUS
, m_hasWindowFocus
, 0);
3498 case WM_INPUTLANGCHANGE
:
3499 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LANGUAGE_CHANGE
, wParam
, lParam
);
3501 case WM_DISPLAYCHANGE
:
3502 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_DISPLAY_CHANGED
, wParam
, lParam
);
3504 case WM_DEVICECHANGE
:
3505 GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_DEVICE_CHANGED
, wParam
, lParam
);
3509 if ((wParam
& 0xFFF0) == SC_SCREENSAVE
)
3511 // Check if screen saver is allowed
3512 IConsole
* const pConsole
= gEnv
->pConsole
;
3513 const ICVar
* const pVar
= pConsole
? pConsole
->GetCVar("sys_screensaver_allowed") : 0;
3514 return pVar
&& pVar
->GetIVal() == 0;
3519 case WM_MOUSEACTIVATE
:
3520 *pResult
= MA_ACTIVATEANDEAT
;
3523 // Hardware mouse counters
3524 case WM_ENTERSIZEMOVE
:
3525 sbInSizingModalLoop
= true;
3526 // Fall through intended
3527 case WM_ENTERMENULOOP
:
3529 IHardwareMouse
* const pMouse
= GetIHardwareMouse();
3532 pMouse
->IncrementCounter();
3536 case WM_CAPTURECHANGED
:
3537 // If WM_CAPTURECHANGED is received after WM_ENTERSIZEMOVE (ie, moving/resizing begins).
3538 // but no matching WM_EXITSIZEMOVE is received (this can happen if the window is not actually moved).
3539 // we still need to decrement the hardware mouse counter that was incremented when WM_ENTERSIZEMOVE was seen.
3540 // So in this case, we effectively treat WM_CAPTURECHANGED as if it was the WM_EXITSIZEMOVE message.
3541 // This behavior has only been reproduced the window is deactivated during the modal loop (ie, breakpoint triggered and focus moves to VS).
3542 case WM_EXITSIZEMOVE
:
3543 if (!sbInSizingModalLoop
)
3547 sbInSizingModalLoop
= false;
3548 // Fall through intended
3549 case WM_EXITMENULOOP
:
3551 IHardwareMouse
* const pMouse
= GetIHardwareMouse();
3554 pMouse
->DecrementCounter();
3557 return (uMsg
!= WM_CAPTURECHANGED
);
3559 // Events that should be forwarded to the hardware mouse
3561 event
= HARDWAREMOUSEEVENT_MOVE
;
3563 case WM_LBUTTONDOWN
:
3564 event
= HARDWAREMOUSEEVENT_LBUTTONDOWN
;
3567 event
= HARDWAREMOUSEEVENT_LBUTTONUP
;
3569 case WM_LBUTTONDBLCLK
:
3570 event
= HARDWAREMOUSEEVENT_LBUTTONDOUBLECLICK
;
3572 case WM_RBUTTONDOWN
:
3573 event
= HARDWAREMOUSEEVENT_RBUTTONDOWN
;
3576 event
= HARDWAREMOUSEEVENT_RBUTTONUP
;
3578 case WM_RBUTTONDBLCLK
:
3579 event
= HARDWAREMOUSEEVENT_RBUTTONDOUBLECLICK
;
3581 case WM_MBUTTONDOWN
:
3582 event
= HARDWAREMOUSEEVENT_MBUTTONDOWN
;
3585 event
= HARDWAREMOUSEEVENT_MBUTTONUP
;
3587 case WM_MBUTTONDBLCLK
:
3588 event
= HARDWAREMOUSEEVENT_MBUTTONDOUBLECLICK
;
3592 event
= HARDWAREMOUSEEVENT_WHEEL
;
3593 ICVar
* cv
= gEnv
->pConsole
->GetCVar("i_mouse_scroll_coordinate_origin");
3596 switch ((EMouseWheelOrigin
)cv
->GetIVal())
3598 case EMouseWheelOrigin::ScreenSpace
:
3599 // Windows default - do nothing
3601 case EMouseWheelOrigin::WindowSpace
:
3604 ScreenToClient((HWND
)hWnd
, &p
);
3609 case EMouseWheelOrigin::WindowSpaceClamped
:
3612 ScreenToClient((HWND
)hWnd
, &p
);
3614 GetClientRect((HWND
)hWnd
, &r
);
3615 x
= crymath::clamp
<int>(p
.x
, 0, r
.right
- r
.left
);
3616 y
= crymath::clamp
<int>(p
.y
, 0, r
.bottom
- r
.top
);
3620 CryWarning(VALIDATOR_MODULE_SYSTEM
, VALIDATOR_WARNING
, "i_mouse_scroll_coordinate_origin out of range");
3627 // Any other event doesn't interest us
3632 // This is an event that should be forwarded to the hardware mouse.
3633 // Note: This code has been moved from the GameDLL into here.
3634 // However, maybe it should be re-factored to be driven by CryInput mouse events (or implemented there).
3635 assert(event
!= -1 && "Logic problem in hardware mouse event handler");
3636 IHardwareMouse
* pMouse
= GetIHardwareMouse();
3639 int wheel
= uMsg
== WM_MOUSEWHEEL
? GET_WHEEL_DELTA_WPARAM(wParam
) : 0;
3640 pMouse
->Event(x
, y
, event
, wheel
);
3647 //////////////////////////////////////////////////////////////////////////
3648 #if CRY_PLATFORM_WINDOWS
3649 static LRESULT WINAPI
WndProc(CRY_HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3651 CSystem
* pSystem
= 0;
3654 pSystem
= static_cast<CSystem
*>(gEnv
->pSystem
);
3656 if (pSystem
&& !pSystem
->m_bQuit
)
3660 for (std::vector
<IWindowMessageHandler
*>::const_iterator it
= pSystem
->m_windowMessageHandlers
.begin(); it
!= pSystem
->m_windowMessageHandlers
.end(); ++it
)
3662 IWindowMessageHandler
* pHandler
= *it
;
3663 LRESULT maybeResult
= 0xDEADDEAD;
3664 if (pHandler
->HandleMessage(hWnd
, uMsg
, wParam
, lParam
, &maybeResult
))
3666 assert(maybeResult
!= 0xDEADDEAD && "Message handler indicated a resulting value, but no value was written");
3669 assert(result
== maybeResult
&& "Two window message handlers tried to return different result values");
3674 result
= maybeResult
;
3680 // One of the registered handlers returned something
3685 // Handle with the default procedure
3686 #if defined(UNICODE) || defined(_UNICODE)
3687 assert(IsWindowUnicode((HWND
)hWnd
) && "Window should be Unicode when compiling with UNICODE");
3689 if (!IsWindowUnicode((HWND
)hWnd
))
3691 return DefWindowProcA((HWND
)hWnd
, uMsg
, wParam
, lParam
);
3694 return DefWindowProcW((HWND
)hWnd
, uMsg
, wParam
, lParam
);
3698 //////////////////////////////////////////////////////////////////////////
3699 void* CSystem::GetRootWindowMessageHandler()
3701 #if CRY_PLATFORM_WINDOWS
3704 assert(false && "This platform does not support window message handlers");
3709 ICmdLine
* CSystem::GetICmdLine()
3714 IUserAnalyticsSystem
* CSystem::GetIUserAnalyticsSystem()
3716 return m_pUserAnalyticsSystem
;
3719 Cry::IPluginManager
* CSystem::GetIPluginManager()
3721 return m_pPluginManager
;
3724 uint32
CSystem::GetCPUFlags()
3726 return m_pCpu
? m_pCpu
->GetFeatures() : 0;
3729 int CSystem::GetLogicalCPUCount()
3731 return m_pCpu
? m_pCpu
->GetLogicalCPUCount() : 0;
3734 #undef EXCLUDE_UPDATE_ON_CONSOLE