// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/TimeSpan.h"
#include "Engine/Core/Types/DateTime.h"
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Core/Collections/SamplesBuffer.h"
///
/// Game ticking and timing system.
///
API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API Time
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Time);
friend class Engine;
friend class TimeService;
friend class PhysicsSettings;
public:
///
/// Engine subsystem updating data.
/// Used to invoke game logic updates, physics updates and rendering with possibly different frequencies.
///
class FLAXENGINE_API TickData
{
public:
virtual ~TickData() = default;
///
/// The total amount of tick since start.
///
uint64 TicksCount = 0;
///
/// The last tick start time (gathered from PlatformTime::Seconds)
///
double LastBegin;
///
/// The last tick end time (gathered from PlatformTime::Seconds)
///
double LastEnd;
///
/// The last tick length in seconds. Note: LastEnd-LastBegin may be invalid inside a tick but LastLength is always valid.
///
double LastLength;
///
/// The next tick start time.
///
double NextBegin;
///
/// The delta time.
/// Always returns the delta time for the current event, meaning it can be used in Update, FixedUpdate, Draw, etc.
///
TimeSpan DeltaTime;
///
/// The total time.
///
TimeSpan Time;
///
/// The unscaled delta time.
///
TimeSpan UnscaledDeltaTime;
///
/// The unscaled total time.
///
TimeSpan UnscaledTime;
public:
virtual void Synchronize(float targetFps, double currentTime);
virtual void OnReset(float targetFps, double currentTime);
virtual bool OnTickBegin(double time, float targetFps, float maxDeltaTime);
virtual void OnTickEnd();
protected:
void Advance(double time, double deltaTime);
};
///
/// Ticking method that tries to use fixed steps policy as much as possible (if not running slowly).
///
class FixedStepTickData : public TickData
{
public:
///
/// The last few ticks delta times. Used to check if can use fixed steps or whenever is running slowly so should use normal stepping.
///
SamplesBuffer Samples;
public:
// [TickData]
bool OnTickBegin(double time, float targetFps, float maxDeltaTime) override;
};
private:
static bool _gamePaused;
static float _physicsMaxDeltaTime;
public:
///
/// The time at which the game started (UTC local).
///
API_FIELD(ReadOnly) static DateTime StartupTime;
///
/// The target amount of the game logic updates per second (script updates frequency).
///
API_FIELD() static float UpdateFPS;
///
/// The target amount of the physics simulation updates per second (also fixed updates frequency).
///
API_FIELD() static float PhysicsFPS;
///
/// The target amount of the frames rendered per second (target game FPS).
///
///
/// To get the actual game FPS use
///
API_FIELD() static float DrawFPS;
///
/// The game time scale factor. Default is 1.
///
API_FIELD() static float TimeScale;
public:
///
/// The game logic updating data.
///
static TickData Update;
///
/// The physics simulation updating data.
///
static FixedStepTickData Physics;
///
/// The rendering data.
///
static TickData Draw;
///
/// The current tick data (update, physics or draw).
///
static TickData* Current;
public:
///
/// Gets the current tick data (safety so returns Update tick data if no active).
///
/// The tick data.
FORCE_INLINE static TickData* GetCurrentSafe()
{
return Current ? Current : &Update;
}
///
/// Gets the time of next upcoming tick data of ticking group with defined update frequency.
///
/// The time of next tick.
static double GetNextTick();
///
/// Gets the value indicating whenever game logic is paused (physics, script updates, etc.).
///
/// True if game is being paused, otherwise false.
API_PROPERTY() FORCE_INLINE static bool GetGamePaused()
{
return _gamePaused;
}
///
/// Sets the value indicating whenever game logic is paused (physics, script updates, etc.).
///
/// True if pause game logic, otherwise false.
API_PROPERTY() static void SetGamePaused(bool value);
///
/// Gets time in seconds it took to complete the last frame, dependent.
///
API_PROPERTY() static float GetDeltaTime();
///
/// Gets time at the beginning of this frame. This is the time in seconds since the start of the game.
///
API_PROPERTY() static float GetGameTime();
///
/// Gets timeScale-independent time in seconds it took to complete the last frame.
///
API_PROPERTY() static float GetUnscaledDeltaTime();
///
/// Gets timeScale-independent time at the beginning of this frame. This is the time in seconds since the start of the game.
///
API_PROPERTY() static float GetUnscaledGameTime();
///
/// Gets the time since startup in seconds (unscaled).
///
API_PROPERTY() static float GetTimeSinceStartup();
///
/// Sets the fixed FPS for game logic updates (draw and update).
///
/// True if enable this feature, otherwise false.
/// The fixed draw/update rate for the time.
API_FUNCTION() static void SetFixedDeltaTime(bool enable, float value);
///
/// Synchronizes update, fixed update and draw. Resets any pending deltas for fresh ticking in sync.
///
API_FUNCTION() static void Synchronize();
private:
// Methods used by the Engine class
static bool OnBeginUpdate(double time);
static bool OnBeginPhysics(double time);
static bool OnBeginDraw(double time);
static void OnEndUpdate();
static void OnEndPhysics();
static void OnEndDraw();
};