// 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(); };