diff --git a/Source/Engine/Core/Config/TimeSettings.h b/Source/Engine/Core/Config/TimeSettings.h
index 991f505ab..4e308a32e 100644
--- a/Source/Engine/Core/Config/TimeSettings.h
+++ b/Source/Engine/Core/Config/TimeSettings.h
@@ -43,6 +43,18 @@ public:
API_FIELD(Attributes="EditorOrder(20), Limit(0.1f, 1000.0f, 0.01f), EditorDisplay(\"General\")")
float MaxUpdateDeltaTime = 0.1f;
+ ///
+ /// Limits maximum game framerate when application window loses focus. Use 0 to disable this feature.
+ ///
+ API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Unfocused\")")
+ float UnfocusedMaxFPS = 30;
+
+ ///
+ /// Enables pausing game when application window loses focus.
+ ///
+ API_FIELD(Attributes="EditorOrder(110), EditorDisplay(\"Unfocused\")")
+ bool UnfocusedPause = false;
+
public:
///
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp
index 5e8224b4e..c0f1e06aa 100644
--- a/Source/Engine/Engine/Engine.cpp
+++ b/Source/Engine/Engine/Engine.cpp
@@ -40,15 +40,11 @@
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MMethod.h"
#include "Engine/Scripting/ManagedCLR/MException.h"
-#include "Engine/Core/Config/PlatformSettings.h"
#endif
namespace EngineImpl
{
bool IsReady = false;
-#if !USE_EDITOR
- bool RunInBackground = false;
-#endif
String CommandLine = nullptr;
int32 Fps = 0, FpsAccumulatedFrames = 0;
double FpsAccumulated = 0.0;
@@ -168,9 +164,6 @@ int32 Engine::Main(const Char* cmdLine)
Platform::BeforeRun();
EngineImpl::InitMainWindow();
Application::BeforeRun();
-#if !USE_EDITOR && (PLATFORM_WINDOWS || PLATFORM_LINUX || PLATFORM_MAC)
- EngineImpl::RunInBackground = PlatformSettings::Get()->RunInBackground;
-#endif
LOG_FLOOR();
LOG_FLUSH();
Time::Synchronize();
@@ -353,20 +346,8 @@ void Engine::OnUpdate()
UpdateCount++;
- const auto mainWindow = MainWindow;
-
-#if !USE_EDITOR
- // Pause game if window lost focus and cannot run in a background
- bool isGameRunning = true;
- if (mainWindow && !mainWindow->IsFocused())
- {
- isGameRunning = EngineImpl::RunInBackground;
- }
- Time::SetGamePaused(!isGameRunning);
-#endif
-
// Determine if application has focus (flag used by the other parts of the engine)
- HasFocus = (mainWindow && mainWindow->IsFocused()) || Platform::GetHasFocus();
+ HasFocus = (MainWindow && MainWindow->IsFocused()) || Platform::GetHasFocus();
// Simulate lags
//Platform::Sleep(100);
diff --git a/Source/Engine/Engine/Time.cpp b/Source/Engine/Engine/Time.cpp
index e55e76971..7d268cf73 100644
--- a/Source/Engine/Engine/Time.cpp
+++ b/Source/Engine/Engine/Time.cpp
@@ -6,12 +6,29 @@
#include "Engine/Platform/Platform.h"
#include "Engine/Core/Config/TimeSettings.h"
#include "Engine/Serialization/Serialization.h"
+#if !USE_EDITOR
+#include "Engine/Engine/Engine.h"
+#endif
namespace
{
bool FixedDeltaTimeEnable;
float FixedDeltaTimeValue;
float MaxUpdateDeltaTime = 0.1f;
+#if USE_EDITOR
+ constexpr bool _gamePausedUnfocsed = false;
+ #define GetFps(fps) fps
+#else
+ bool _gamePausedUnfocsed = false;
+ float UnfocusedMaxFPS = 0.0f;
+ bool UnfocusedPause = false;
+ float GetFps(float fps)
+ {
+ if (UnfocusedMaxFPS > 0 && !Engine::HasFocus && fps > UnfocusedMaxFPS)
+ fps = UnfocusedMaxFPS;
+ return fps;
+ }
+#endif
}
bool Time::_gamePaused = false;
@@ -52,15 +69,16 @@ void TimeSettings::Apply()
Time::DrawFPS = DrawFPS;
Time::TimeScale = TimeScale;
::MaxUpdateDeltaTime = MaxUpdateDeltaTime;
+#if !USE_EDITOR
+ ::UnfocusedMaxFPS = UnfocusedMaxFPS;
+ ::UnfocusedPause = UnfocusedPause;
+#endif
}
void Time::TickData::Synchronize(float targetFps, double currentTime)
{
+ OnReset(targetFps, currentTime);
Time = UnscaledTime = TimeSpan::Zero();
- DeltaTime = UnscaledDeltaTime = targetFps > ZeroTolerance ? TimeSpan::FromSeconds(1.0f / targetFps) : TimeSpan::Zero();
- LastLength = static_cast(DeltaTime.Ticks) / TimeSpan::TicksPerSecond;
- LastBegin = currentTime - LastLength;
- LastEnd = currentTime;
NextBegin = targetFps > ZeroTolerance ? LastBegin + (1.0f / targetFps) : 0.0;
}
@@ -115,7 +133,7 @@ void Time::TickData::OnTickEnd()
void Time::TickData::Advance(double time, double deltaTime)
{
float timeScale = TimeScale;
- if (_gamePaused)
+ if (_gamePaused || _gamePausedUnfocsed)
timeScale = 0.0f;
LastBegin = time;
UnscaledDeltaTime = TimeSpan::FromSeconds(deltaTime);
@@ -194,9 +212,11 @@ void Time::SetGamePaused(bool value)
{
if (_gamePaused == value)
return;
-
_gamePaused = value;
+ if (_gamePausedUnfocsed)
+ return;
+ // Reset ticking
const double time = Platform::GetTimeSeconds();
Update.OnReset(UpdateFPS, time);
Physics.OnReset(PhysicsFPS, time);
@@ -249,7 +269,24 @@ void Time::Synchronize()
bool Time::OnBeginUpdate(double time)
{
- if (Update.OnTickBegin(time, UpdateFPS, MaxUpdateDeltaTime))
+#if !USE_EDITOR
+ // Pause game if window lost focus (based on game settings)
+ bool gamePausedUnfocsed = !Engine::HasFocus && UnfocusedPause;
+ if (gamePausedUnfocsed != _gamePausedUnfocsed)
+ {
+ _gamePausedUnfocsed = gamePausedUnfocsed;
+ if (!gamePausedUnfocsed)
+ {
+ // Reset ticking
+ const double time = Platform::GetTimeSeconds();
+ Update.OnReset(UpdateFPS, time);
+ Physics.OnReset(PhysicsFPS, time);
+ Draw.OnReset(DrawFPS, time);
+ }
+ }
+#endif
+
+ if (Update.OnTickBegin(time, GetFps(UpdateFPS), MaxUpdateDeltaTime))
{
Current = &Update;
return true;
@@ -259,7 +296,7 @@ bool Time::OnBeginUpdate(double time)
bool Time::OnBeginPhysics(double time)
{
- if (Physics.OnTickBegin(time, PhysicsFPS, _physicsMaxDeltaTime))
+ if (Physics.OnTickBegin(time, GetFps(PhysicsFPS), _physicsMaxDeltaTime))
{
Current = &Physics;
return true;
@@ -269,7 +306,7 @@ bool Time::OnBeginPhysics(double time)
bool Time::OnBeginDraw(double time)
{
- if (Draw.OnTickBegin(time, DrawFPS, 1.0f))
+ if (Draw.OnTickBegin(time, GetFps(DrawFPS), 1.0f))
{
Current = &Draw;
return true;
diff --git a/Source/Engine/Platform/Linux/LinuxPlatformSettings.h b/Source/Engine/Platform/Linux/LinuxPlatformSettings.h
index 6e9200cc6..dd63c0d78 100644
--- a/Source/Engine/Platform/Linux/LinuxPlatformSettings.h
+++ b/Source/Engine/Platform/Linux/LinuxPlatformSettings.h
@@ -43,8 +43,10 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
///
/// Enables game running when application window loses focus.
+ /// [Deprecated in v1.12]
///
API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")")
+ DEPRECATED("Use UnfocusedPause from TimeSettings.")
bool RunInBackground = false;
///
diff --git a/Source/Engine/Platform/Mac/MacPlatformSettings.h b/Source/Engine/Platform/Mac/MacPlatformSettings.h
index f78b12167..9f6807fba 100644
--- a/Source/Engine/Platform/Mac/MacPlatformSettings.h
+++ b/Source/Engine/Platform/Mac/MacPlatformSettings.h
@@ -40,8 +40,10 @@ API_CLASS(Sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
///
/// Enables game running when application window loses focus.
+ /// [Deprecated in v1.12]
///
API_FIELD(Attributes="EditorOrder(1010), EditorDisplay(\"Other\", \"Run In Background\")")
+ DEPRECATED("Use UnfocusedPause from TimeSettings.")
bool RunInBackground = false;
///
diff --git a/Source/Engine/Platform/Windows/WindowsPlatformSettings.h b/Source/Engine/Platform/Windows/WindowsPlatformSettings.h
index 9745b61c1..40e6bef9e 100644
--- a/Source/Engine/Platform/Windows/WindowsPlatformSettings.h
+++ b/Source/Engine/Platform/Windows/WindowsPlatformSettings.h
@@ -43,8 +43,10 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
///
/// Enables game running when application window loses focus.
+ /// [Deprecated in v1.12]
///
API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")")
+ DEPRECATED("Use UnfocusedPause from TimeSettings.")
bool RunInBackground = false;
///