Add Runner

This commit is contained in:
Nomango 2020-02-14 17:12:13 +08:00
parent a34184dd18
commit 93e97c60c2
11 changed files with 193 additions and 88 deletions

View File

@ -22,6 +22,7 @@
<ClInclude Include="..\..\src\kiwano\core\Exception.h" /> <ClInclude Include="..\..\src\kiwano\core\Exception.h" />
<ClInclude Include="..\..\src\kiwano\core\Keys.h" /> <ClInclude Include="..\..\src\kiwano\core\Keys.h" />
<ClInclude Include="..\..\src\kiwano\core\Library.h" /> <ClInclude Include="..\..\src\kiwano\core\Library.h" />
<ClInclude Include="..\..\src\kiwano\core\Runner.h" />
<ClInclude Include="..\..\src\kiwano\core\Singleton.h" /> <ClInclude Include="..\..\src\kiwano\core\Singleton.h" />
<ClInclude Include="..\..\src\kiwano\core\Time.h" /> <ClInclude Include="..\..\src\kiwano\core\Time.h" />
<ClInclude Include="..\..\src\kiwano\kiwano.h" /> <ClInclude Include="..\..\src\kiwano\kiwano.h" />

View File

@ -300,6 +300,9 @@
<ClInclude Include="..\..\src\kiwano\render\Layer.h"> <ClInclude Include="..\..\src\kiwano\render\Layer.h">
<Filter>render</Filter> <Filter>render</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Runner.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">

View File

@ -235,7 +235,7 @@ void HttpClient::NetworkThread()
response_queue_.push(response); response_queue_.push(response);
response_mutex_.unlock(); response_mutex_.unlock();
Application::PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback)); Application::GetInstance().PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback));
} }
} }

View File

@ -77,7 +77,7 @@ void AsyncTask::TaskThread()
func_mutex_.unlock(); func_mutex_.unlock();
} }
Application::PreformInMainThread(Closure(this, &AsyncTask::Complete)); Application::GetInstance().PreformInMainThread(Closure(this, &AsyncTask::Complete));
} }
void AsyncTask::Complete() void AsyncTask::Complete()

94
src/kiwano/core/Runner.h Normal file
View File

@ -0,0 +1,94 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <kiwano/core/Common.h>
namespace kiwano
{
/**
* \~chinese
* @brief
*/
class KGE_API Runner
{
public:
typedef Function<void()> Callback;
Runner();
/// \~chinese
/// @brief 构造程序运行器
/// @param on_ready 应用程序初始化完成后执行的回调函数
/// @param on_destroy 应用程序销毁时执行的回调函数
Runner(const Callback& on_ready, const Callback& on_destroy = nullptr);
/// \~chinese
/// @brief 初始化完成处理
/// @details 重载该函数以在应用程序初始化完成后自动执行
virtual void OnReady();
/// \~chinese
/// @brief 应用程序销毁处理
/// @details 重载该函数以处理应用程序销毁时的行为,如完成资源回收等
virtual void OnDestroy();
/// \~chinese
/// @brief 窗口关闭处理
/// @details 重载该函数以处理用户关闭窗口时的行为,如保存用户数据等
/// @return 返回true允许用户关闭窗口否则阻止窗口关闭
virtual bool OnClosing();
private:
Callback on_ready_;
Callback on_destroy_;
};
inline Runner::Runner() {}
inline Runner::Runner(const Callback& on_ready, const Callback& on_destroy)
: on_ready_(on_ready)
, on_destroy_(on_destroy)
{
}
inline void Runner::OnReady()
{
if (on_ready_)
{
on_ready_();
}
}
inline void Runner::OnDestroy()
{
if (on_destroy_)
{
on_destroy_();
}
}
inline bool Runner::OnClosing()
{
return true;
}
} // namespace kiwano

View File

@ -18,40 +18,28 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/core/Director.h>
#include <kiwano/core/Logger.h>
#include <kiwano/platform/Application.h> #include <kiwano/platform/Application.h>
#include <kiwano/platform/Input.h> #include <kiwano/platform/Input.h>
#include <kiwano/core/Director.h>
#include <kiwano/core/Logger.h>
#include <kiwano/render/TextureCache.h> #include <kiwano/render/TextureCache.h>
#include <kiwano/utils/ResourceCache.h> #include <kiwano/utils/ResourceCache.h>
#include <mutex>
namespace kiwano namespace kiwano
{ {
namespace
{
using FunctionToPerform = Function<void()>;
std::mutex perform_mutex_;
Queue<FunctionToPerform> functions_to_perform_;
} // namespace
Application::Application() Application::Application()
: time_scale_(1.f) : quiting_(false)
, time_scale_(1.f)
{ {
Use(&Renderer::GetInstance()); Use(&Renderer::GetInstance());
Use(&Input::GetInstance()); Use(&Input::GetInstance());
Use(&Director::GetInstance()); Use(&Director::GetInstance());
} }
Application::~Application() Application::~Application() {}
{
Destroy();
}
void Application::Run(bool debug) void Application::Run(Runner& runner, bool debug)
{ {
// Setup all components // Setup all components
for (auto c : comps_) for (auto c : comps_)
@ -66,26 +54,43 @@ void Application::Run(bool debug)
} }
// Everything is ready // Everything is ready
OnReady(); runner.OnReady();
// Initialize variables
quiting_ = false;
last_update_time_ = Time::Now(); last_update_time_ = Time::Now();
Window& window = Window::GetInstance(); Window& window = Window::GetInstance();
while (!window.ShouldClose()) while (!quiting_)
{ {
while (EventPtr evt = window.PollEvent()) if (window.ShouldClose())
{ {
DispatchEvent(evt.get()); if (runner.OnClosing())
break;
else
window.SetShouldClose(false);
} }
Update(); while (EventPtr evt = window.PollEvent())
Render(); {
this->DispatchEvent(evt.get());
}
this->Update();
this->Render();
} }
// Destroy all resources
runner.OnDestroy();
this->Destroy();
// Destroy window
window.Destroy();
} }
void Application::Quit() void Application::Quit()
{ {
Window::GetInstance().Destroy(); quiting_ = true;
} }
void Application::Destroy() void Application::Destroy()
@ -99,10 +104,6 @@ void Application::Destroy()
{ {
(*iter)->DestroyComponent(); (*iter)->DestroyComponent();
} }
render_comps_.clear();
update_comps_.clear();
event_comps_.clear();
comps_.clear();
} }
void Application::Use(ComponentBase* component) void Application::Use(ComponentBase* component)

View File

@ -19,13 +19,13 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <mutex>
#include <kiwano/core/Common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/Component.h> #include <kiwano/core/Component.h>
#include <kiwano/core/Time.h> #include <kiwano/core/Time.h>
#include <kiwano/core/Runner.h>
#include <kiwano/core/Singleton.h>
#include <kiwano/core/event/Event.h> #include <kiwano/core/event/Event.h>
#include <kiwano/core/event/KeyEvent.h>
#include <kiwano/core/event/MouseEvent.h>
#include <kiwano/core/event/WindowEvent.h>
#include <kiwano/platform/Window.h> #include <kiwano/platform/Window.h>
#include <kiwano/render/Renderer.h> #include <kiwano/render/Renderer.h>
@ -35,35 +35,23 @@ namespace kiwano
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Application : protected Noncopyable class KGE_API Application : public Singleton<Application>
{ {
friend Singleton<Application>;
public: public:
Application(); Application();
virtual ~Application(); virtual ~Application();
/**
* \~chinese
* @brief
* @details
*/
virtual void OnReady();
/**
* \~chinese
* @brief
* @details
*/
virtual void OnDestroy();
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @details OnReady * @param[in] runner
* @param debug * @param debug
* @note * @note
*/ */
void Run(bool debug = false); void Run(Runner& runner, bool debug = false);
/** /**
* \~chinese * \~chinese
@ -107,7 +95,7 @@ public:
* @details 线 Kiwano * @details 线 Kiwano
* @param func * @param func
*/ */
static void PreformInMainThread(Function<void()> func); void PreformInMainThread(Function<void()> func);
private: private:
/** /**
@ -123,15 +111,15 @@ private:
void Render(); void Render();
private: private:
bool quiting_;
float time_scale_; float time_scale_;
Time last_update_time_; Time last_update_time_;
Vector<ComponentBase*> comps_; Vector<ComponentBase*> comps_;
Vector<RenderComponent*> render_comps_; Vector<RenderComponent*> render_comps_;
Vector<UpdateComponent*> update_comps_; Vector<UpdateComponent*> update_comps_;
Vector<EventComponent*> event_comps_; Vector<EventComponent*> event_comps_;
std::mutex perform_mutex_;
Queue<Function<void()>> functions_to_perform_;
}; };
inline void Application::OnReady() {}
inline void Application::OnDestroy() {}
} // namespace kiwano } // namespace kiwano

View File

@ -70,6 +70,11 @@ bool Window::ShouldClose()
return should_close_; return should_close_;
} }
void Window::SetShouldClose(bool should)
{
should_close_ = should;
}
void Window::PushEvent(EventPtr evt) void Window::PushEvent(EventPtr evt)
{ {
event_queue_.push(evt); event_queue_.push(evt);

View File

@ -21,7 +21,6 @@
#pragma once #pragma once
#include <kiwano/core/Common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/event/Event.h> #include <kiwano/core/event/Event.h>
#include <kiwano/macros.h>
#include <kiwano/math/Math.h> #include <kiwano/math/Math.h>
namespace kiwano namespace kiwano
@ -158,6 +157,12 @@ public:
*/ */
bool ShouldClose(); bool ShouldClose();
/**
* \~chinese
* @brief
*/
void SetShouldClose(bool should);
/** /**
* \~chinese * \~chinese
* @brief * @brief

View File

@ -166,7 +166,7 @@ void WindowImpl::Create(String const& title, uint32_t width, uint32_t height, ui
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = L"KiwanoAppWnd"; wcex.lpszClassName = L"KiwanoAppWnd";
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */; wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
wcex.lpfnWndProc = WindowImpl::WndProc; wcex.lpfnWndProc = WindowImpl::StaticWndProc;
wcex.hIcon = nullptr; wcex.hIcon = nullptr;
wcex.cbClsExtra = 0; wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR); wcex.cbWndExtra = sizeof(LONG_PTR);
@ -437,25 +437,19 @@ void WindowImpl::SetActive(bool actived)
} }
} }
LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) LRESULT WindowImpl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
{ {
WindowImpl* window = reinterpret_cast<WindowImpl*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
if (window == nullptr)
{
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
}
switch (msg) switch (msg)
{ {
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
{ {
KeyCode key = window->key_map_[size_t(wparam)]; KeyCode key = this->key_map_[size_t(wparam)];
if (key != KeyCode::Unknown) if (key != KeyCode::Unknown)
{ {
KeyDownEventPtr evt = new KeyDownEvent; KeyDownEventPtr evt = new KeyDownEvent;
evt->code = key; evt->code = key;
window->PushEvent(evt); this->PushEvent(evt);
} }
} }
break; break;
@ -463,12 +457,12 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP: case WM_SYSKEYUP:
{ {
KeyCode key = window->key_map_[size_t(wparam)]; KeyCode key = this->key_map_[size_t(wparam)];
if (key != KeyCode::Unknown) if (key != KeyCode::Unknown)
{ {
KeyUpEventPtr evt = new KeyUpEvent; KeyUpEventPtr evt = new KeyUpEvent;
evt->code = key; evt->code = key;
window->PushEvent(evt); this->PushEvent(evt);
} }
} }
break; break;
@ -477,7 +471,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
KeyCharEventPtr evt = new KeyCharEvent; KeyCharEventPtr evt = new KeyCharEvent;
evt->value = char(wparam); evt->value = char(wparam);
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -504,7 +498,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
evt->button = MouseButton::Middle; evt->button = MouseButton::Middle;
} }
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -528,7 +522,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
evt->button = MouseButton::Middle; evt->button = MouseButton::Middle;
} }
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -536,7 +530,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
MouseMoveEventPtr evt = new MouseMoveEvent; MouseMoveEventPtr evt = new MouseMoveEvent;
evt->pos = Point((float)GET_X_LPARAM(lparam), (float)GET_Y_LPARAM(lparam)); evt->pos = Point((float)GET_X_LPARAM(lparam), (float)GET_Y_LPARAM(lparam));
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -545,7 +539,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
MouseWheelEventPtr evt = new MouseWheelEvent; MouseWheelEventPtr evt = new MouseWheelEvent;
evt->pos = Point((float)GET_X_LPARAM(lparam), (float)GET_Y_LPARAM(lparam)); evt->pos = Point((float)GET_X_LPARAM(lparam), (float)GET_Y_LPARAM(lparam));
evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -559,13 +553,13 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
// KGE_SYS_LOG("Window resized"); // KGE_SYS_LOG("Window resized");
window->width_ = ((uint32_t)(short)LOWORD(lparam)); this->width_ = ((uint32_t)(short)LOWORD(lparam));
window->height_ = ((uint32_t)(short)HIWORD(lparam)); this->height_ = ((uint32_t)(short)HIWORD(lparam));
WindowResizedEventPtr evt = new WindowResizedEvent; WindowResizedEventPtr evt = new WindowResizedEvent;
evt->width = window->GetWidth(); evt->width = this->GetWidth();
evt->height = window->GetHeight(); evt->height = this->GetHeight();
window->PushEvent(evt); this->PushEvent(evt);
} }
} }
break; break;
@ -575,7 +569,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
WindowMovedEventPtr evt = new WindowMovedEvent; WindowMovedEventPtr evt = new WindowMovedEvent;
evt->x = GET_X_LPARAM(lparam); evt->x = GET_X_LPARAM(lparam);
evt->y = GET_Y_LPARAM(lparam); evt->y = GET_Y_LPARAM(lparam);
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -583,11 +577,11 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
bool active = (LOWORD(wparam) != WA_INACTIVE); bool active = (LOWORD(wparam) != WA_INACTIVE);
window->SetActive(active); this->SetActive(active);
WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent; WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent;
evt->focus = active; evt->focus = active;
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -595,11 +589,11 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
KGE_SYS_LOG("Window title changed"); KGE_SYS_LOG("Window title changed");
window->title_ = WideToMultiByte(reinterpret_cast<LPCWSTR>(lparam)); this->title_ = WideToMultiByte(reinterpret_cast<LPCWSTR>(lparam));
WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent; WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent;
evt->title = window->title_; evt->title = this->title_;
window->PushEvent(evt); this->PushEvent(evt);
} }
break; break;
@ -619,7 +613,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_SETCURSOR: case WM_SETCURSOR:
{ {
window->UpdateCursor(); this->UpdateCursor();
} }
break; break;
@ -628,8 +622,9 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
KGE_SYS_LOG("Window is closing"); KGE_SYS_LOG("Window is closing");
WindowClosedEventPtr evt = new WindowClosedEvent; WindowClosedEventPtr evt = new WindowClosedEvent;
window->PushEvent(evt); this->PushEvent(evt);
window->Destroy(); this->SetShouldClose(true);
return 0;
} }
break; break;
@ -646,6 +641,17 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
return ::DefWindowProcW(hwnd, msg, wparam, lparam); return ::DefWindowProcW(hwnd, msg, wparam, lparam);
} }
LRESULT CALLBACK WindowImpl::StaticWndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
{
LONG_PTR ptr = static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA));
if (ptr)
{
WindowImpl* window = reinterpret_cast<WindowImpl*>(ptr);
return window->MessageProc(hwnd, msg, wparam, lparam);
}
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
}
} // namespace kiwano } // namespace kiwano
#endif #endif

View File

@ -62,7 +62,9 @@ private:
void SetActive(bool actived); void SetActive(bool actived);
static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM); LRESULT MessageProc(HWND, UINT32, WPARAM, LPARAM);
static LRESULT CALLBACK StaticWndProc(HWND, UINT32, WPARAM, LPARAM);
private: private:
bool resizable_; bool resizable_;