update frame ticker & fix window frozen when minimized

This commit is contained in:
Nomango 2020-06-03 22:07:07 +08:00
parent 7f902e3343
commit 091a05e8fd
4 changed files with 97 additions and 77 deletions

View File

@ -48,9 +48,10 @@ Application::~Application()
void Application::Run(RunnerPtr runner) void Application::Run(RunnerPtr runner)
{ {
KGE_ASSERT(runner); KGE_ASSERT(runner);
runner_ = runner; running_ = true;
running_ = true;
is_paused_ = false; is_paused_ = false;
runner_ = runner;
timer_ = Timer::Create();
// Initialize runner // Initialize runner
runner->InitSettings(); runner->InitSettings();
@ -64,29 +65,17 @@ void Application::Run(RunnerPtr runner)
// Everything is ready // Everything is ready
runner->OnReady(); runner->OnReady();
// Update everything
this->Update(0);
// Start the loop
while (running_) while (running_)
{ {
if (!frame_ticker_) timer_->Tick();
{
frame_ticker_ = Ticker::Create(0);
}
if (frame_ticker_->Tick()) // Execute main loop
{ if (!runner->MainLoop(timer_->GetDeltaTime()))
// Execute main loop running_ = false;
if (!runner->MainLoop(frame_ticker_->GetDeltaTime()))
running_ = false;
}
else
{
// Releases CPU
Duration total_dt = frame_ticker_->GetDeltaTime() + frame_ticker_->GetErrorTime();
Duration sleep_dt = frame_ticker_->GetInterval() - total_dt;
if (sleep_dt.Milliseconds() > 1LL)
{
sleep_dt.Sleep();
}
}
} }
this->Destroy(); this->Destroy();
@ -96,16 +85,16 @@ void Application::Pause()
{ {
is_paused_ = true; is_paused_ = true;
if (frame_ticker_) if (timer_)
frame_ticker_->Pause(); timer_->Pause();
} }
void Application::Resume() void Application::Resume()
{ {
is_paused_ = false; is_paused_ = false;
if (frame_ticker_) if (timer_)
frame_ticker_->Resume(); timer_->Resume();
} }
void Application::Quit() void Application::Quit()
@ -113,6 +102,12 @@ void Application::Quit()
running_ = false; running_ = false;
} }
void Application::UpdateFrame(Duration dt)
{
this->Render();
this->Update(dt);
}
void Application::Destroy() void Application::Destroy()
{ {
if (runner_) if (runner_)

View File

@ -27,7 +27,7 @@
#include <kiwano/event/Event.h> #include <kiwano/event/Event.h>
#include <kiwano/platform/Runner.h> #include <kiwano/platform/Runner.h>
#include <kiwano/platform/Window.h> #include <kiwano/platform/Window.h>
#include <kiwano/utils/Ticker.h> #include <kiwano/utils/Timer.h>
namespace kiwano namespace kiwano
{ {
@ -103,18 +103,6 @@ public:
*/ */
WindowPtr GetWindow() const; WindowPtr GetWindow() const;
/**
* \~chinese
* @brief
*/
TickerPtr GetFrameTicker() const;
/**
* \~chinese
* @brief
*/
void SetFrameTicker(TickerPtr ticker);
/** /**
* \~chinese * \~chinese
* @brief * @brief
@ -150,16 +138,10 @@ public:
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @param dt * @param dt
*/ */
void Update(Duration dt); void UpdateFrame(Duration dt);
/**
* \~chinese
* @brief
*/
void Render();
/** /**
* \~chinese * \~chinese
@ -167,12 +149,26 @@ public:
*/ */
void Destroy(); void Destroy();
private:
/**
* \~chinese
* @brief
* @param dt
*/
void Update(Duration dt);
/**
* \~chinese
* @brief
*/
void Render();
private: private:
bool running_; bool running_;
bool is_paused_; bool is_paused_;
float time_scale_; float time_scale_;
RunnerPtr runner_; RunnerPtr runner_;
TickerPtr frame_ticker_; TimerPtr timer_;
List<Module*> modules_; List<Module*> modules_;
std::mutex perform_mutex_; std::mutex perform_mutex_;
Queue<Function<void()>> functions_to_perform_; Queue<Function<void()>> functions_to_perform_;
@ -185,18 +181,9 @@ inline RunnerPtr Application::GetRunner() const
inline WindowPtr Application::GetWindow() const inline WindowPtr Application::GetWindow() const
{ {
KGE_ASSERT(runner_); if (runner_)
return runner_->GetWindow(); return runner_->GetWindow();
} return nullptr;
inline TickerPtr Application::GetFrameTicker() const
{
return frame_ticker_;
}
inline void Application::SetFrameTicker(TickerPtr ticker)
{
frame_ticker_ = ticker;
} }
inline bool Application::IsPaused() const inline bool Application::IsPaused() const

View File

@ -101,6 +101,9 @@ void Runner::InitSettings()
Director::GetInstance().ShowDebugInfo(true); Director::GetInstance().ShowDebugInfo(true);
Renderer::GetInstance().GetContext().SetCollectingStatus(true); Renderer::GetInstance().GetContext().SetCollectingStatus(true);
} }
// Create frame ticker
frame_ticker_ = Ticker::Create(settings_.frame_interval, -1);
} }
bool Runner::MainLoop(Duration dt) bool Runner::MainLoop(Duration dt)
@ -118,9 +121,6 @@ bool Runner::MainLoop(Duration dt)
Application& app = Application::GetInstance(); Application& app = Application::GetInstance();
// Update modules before poll events
app.Update(dt);
// Poll events // Poll events
main_window_->PumpEvents(); main_window_->PumpEvents();
while (EventPtr evt = main_window_->PollEvent()) while (EventPtr evt = main_window_->PollEvent())
@ -128,12 +128,27 @@ bool Runner::MainLoop(Duration dt)
app.DispatchEvent(evt.Get()); app.DispatchEvent(evt.Get());
} }
app.Render(); // Update frame ticker
if (frame_ticker_)
if (app.IsPaused())
{ {
// Slow down when the application is paused if (frame_ticker_->Tick(dt))
Duration(5).Sleep(); {
app.UpdateFrame(frame_ticker_->GetDeltaTime());
}
else
{
// Releases CPU
Duration total_dt = frame_ticker_->GetDeltaTime() + frame_ticker_->GetErrorTime();
Duration sleep_dt = frame_ticker_->GetInterval() - total_dt;
if (sleep_dt.Milliseconds() > 1LL)
{
sleep_dt.Sleep();
}
}
}
else
{
app.UpdateFrame(dt);
} }
return true; return true;
} }

View File

@ -24,6 +24,8 @@
#include <kiwano/platform/Window.h> #include <kiwano/platform/Window.h>
#include <kiwano/render/Color.h> #include <kiwano/render/Color.h>
#include <kiwano/render/Texture.h> #include <kiwano/render/Texture.h>
#include <kiwano/utils/Ticker.h>
namespace kiwano namespace kiwano
{ {
@ -38,14 +40,15 @@ KGE_DECLARE_SMART_PTR(Runner);
*/ */
struct Settings struct Settings
{ {
uint32_t width; ///< 窗口宽度 uint32_t width; ///< 窗口宽度
uint32_t height; ///< 窗口高度 uint32_t height; ///< 窗口高度
String title; ///< 窗口标题 String title; ///< 窗口标题
uint32_t icon; ///< 窗口图标 uint32_t icon; ///< 窗口图标
bool resizable; ///< 窗口大小可调整 bool resizable; ///< 窗口大小可调整
Color bg_color; ///< 窗口背景色 Color bg_color; ///< 窗口背景色
bool vsync_enabled; ///< 垂直同步 Duration frame_interval; ///< 帧间隔
bool debug_mode; ///< 调试模式 bool vsync_enabled; ///< 垂直同步
bool debug_mode; ///< 调试模式
Settings() Settings()
: width(800) : width(800)
@ -54,7 +57,8 @@ struct Settings
, icon() , icon()
, resizable(false) , resizable(false)
, bg_color(Color::Black) , bg_color(Color::Black)
, vsync_enabled(true) , frame_interval(16)
, vsync_enabled(false)
, debug_mode(false) , debug_mode(false)
{ {
} }
@ -118,6 +122,14 @@ public:
/// @brief »ñÈ¡ÉèÖà /// @brief »ñÈ¡ÉèÖÃ
Settings GetSettings() const; Settings GetSettings() const;
/// \~chinese
/// @brief 获取帧报时器
TickerPtr GetFrameTicker() const;
/// \~chinese
/// @brief 设置帧报时器
void SetFrameTicker(TickerPtr ticker);
protected: protected:
/// \~chinese /// \~chinese
/// @brief ÐÞ¸ÄÉèÖà /// @brief ÐÞ¸ÄÉèÖÃ
@ -131,6 +143,7 @@ private:
private: private:
Settings settings_; Settings settings_;
WindowPtr main_window_; WindowPtr main_window_;
TickerPtr frame_ticker_;
}; };
inline void Runner::OnReady() {} inline void Runner::OnReady() {}
@ -162,4 +175,14 @@ inline void Runner::SetSettings(Settings settings)
settings_ = settings; settings_ = settings;
} }
inline TickerPtr Runner::GetFrameTicker() const
{
return frame_ticker_;
}
inline void Runner::SetFrameTicker(TickerPtr ticker)
{
frame_ticker_ = ticker;
}
} // namespace kiwano } // namespace kiwano