diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index e07983f0..8e09898c 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -22,7 +22,6 @@ - @@ -61,9 +60,9 @@ + - @@ -136,6 +135,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index daf84566..d470f726 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -285,9 +285,6 @@ render\DirectX - - platform\win32 - core @@ -297,12 +294,12 @@ render - - core - core + + platform + @@ -512,5 +509,8 @@ core + + platform + \ No newline at end of file diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index 3a7dbba2..396967e1 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,12 +29,14 @@ void ImGuiModule::SetupModule() // Setup Dear ImGui style ImGui::StyleColorsDark(); + window_ = Application::GetInstance().GetMainWindow(); + // Setup Platform/Renderer bindings io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) io.BackendPlatformName = "imgui_impl_win32"; - io.ImeWindowHandle = WindowImpl::GetInstance().GetHandle(); + io.ImeWindowHandle = window_->GetHandle(); // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during // the application lifetime. @@ -174,7 +176,7 @@ void ImGuiModule::UpdateMousePos() if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; - ::ClientToScreen(WindowImpl::GetInstance().GetHandle(), &pos); + ::ClientToScreen(window_->GetHandle(), &pos); ::SetCursorPos(pos.x, pos.y); } @@ -216,7 +218,7 @@ void ImGuiModule::UpdateMouseCursor() break; } - Window::GetInstance().SetCursor(cursor); + window_->SetCursor(cursor); } } // namespace imgui diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index 0a5c34aa..1b17c59e 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -21,6 +21,7 @@ #pragma once #include #include +#include namespace kiwano { @@ -58,6 +59,9 @@ private: void UpdateMousePos(); void UpdateMouseCursor(); + +private: + WindowPtr window_; }; } // namespace imgui diff --git a/src/kiwano-network/HttpModule.h b/src/kiwano-network/HttpModule.h index 8450fa0c..bb51b8f8 100644 --- a/src/kiwano-network/HttpModule.h +++ b/src/kiwano-network/HttpModule.h @@ -30,7 +30,7 @@ namespace network { /** * \~chinese - * \defgroup Network 网络通信 + * \defgroup Network 网络模块 */ /** diff --git a/src/kiwano-physics/World.h b/src/kiwano-physics/World.h index 6b5a4a49..1e635fc4 100644 --- a/src/kiwano-physics/World.h +++ b/src/kiwano-physics/World.h @@ -30,7 +30,7 @@ KGE_DECLARE_SMART_PTR(World); /** * \~chinese - * \defgroup Physics 物理引擎 + * \defgroup Physics 物理模块 */ /** diff --git a/src/kiwano/2d/Button.cpp b/src/kiwano/2d/Button.cpp index 519b88f4..d112f4a3 100644 --- a/src/kiwano/2d/Button.cpp +++ b/src/kiwano/2d/Button.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include namespace kiwano { @@ -73,14 +73,14 @@ void Button::SetStatus(Status status) if (status == Status::Normal) { - Window::GetInstance().SetCursor(CursorType::Arrow); + Application::GetInstance().GetMainWindow()->SetCursor(CursorType::Arrow); if (mouse_out_callback_) mouse_out_callback_(this); } else if (status == Status::Hover) { - Window::GetInstance().SetCursor(CursorType::Hand); + Application::GetInstance().GetMainWindow()->SetCursor(CursorType::Hand); if (old_status != Status::Pressed) { diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 38953e4f..af047772 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -105,10 +105,11 @@ // platform // +#include +#include #include #include #include -#include // // utils diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index c3a3498d..efd45494 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -39,8 +40,11 @@ Application::Application() Application::~Application() {} -void Application::Run(Runner& runner, bool debug) +void Application::Run(Runner* runner, bool debug) { + KGE_ASSERT(runner); + runner_ = runner; + // Setup all modules for (auto c : modules_) { @@ -54,38 +58,18 @@ void Application::Run(Runner& runner, bool debug) } // Everything is ready - runner.OnReady(); + runner->OnReady(); + runner->SetLastUpdateTime(Time::Now()); - // Initialize variables - quiting_ = false; - last_update_time_ = Time::Now(); - - Window& window = Window::GetInstance(); + quiting_ = false; while (!quiting_) { - if (window.ShouldClose()) - { - if (runner.OnClosing()) - break; - else - window.SetShouldClose(false); - } - - while (EventPtr evt = window.PollEvent()) - { - this->DispatchEvent(evt.get()); - } - - this->Update(); - this->Render(); + quiting_ = !runner->MainLoop(); } // Destroy all resources - runner.OnDestroy(); + runner->OnDestroy(); this->Destroy(); - - // Destroy window - window.Destroy(); } void Application::Quit() @@ -123,7 +107,7 @@ void Application::SetTimeScale(float scale_factor) time_scale_ = scale_factor; } -void Application::Update() +void Application::Update(Duration dt) { // Before update for (auto comp : modules_) @@ -155,18 +139,12 @@ void Application::Update() } // Updating + Duration scaled_dt = dt * time_scale_; + for (auto comp : modules_) { - const Time now = Time::Now(); - const Duration dt = (now - last_update_time_) * time_scale_; - - last_update_time_ = now; - - for (auto comp : modules_) + if (auto update_comp = comp->Cast()) { - if (auto update_comp = comp->Cast()) - { - update_comp->OnUpdate(dt); - } + update_comp->OnUpdate(scaled_dt); } } diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 090aff07..49e6cad5 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -23,11 +23,10 @@ #include #include #include -#include #include #include +#include #include -#include namespace kiwano { @@ -47,11 +46,20 @@ public: /** * \~chinese * @brief 启动应用程序 - * @param[in] runner 程序运行器 + * @param runner 程序运行器 * @param debug 是否启用调试模式 * @note 该函数是阻塞的,应用程序结束时函数返回 */ - void Run(Runner& runner, bool debug = false); + void Run(RunnerPtr runner, bool debug = false); + + /** + * \~chinese + * @brief 启动应用程序 + * @param runner 程序运行器 + * @param debug 是否启用调试模式 + * @note 该函数是阻塞的,应用程序结束时函数返回 + */ + void Run(Runner* runner, bool debug = false); /** * \~chinese @@ -65,6 +73,18 @@ public: */ void Destroy(); + /** + * \~chinese + * @brief 获取程序运行器 + */ + RunnerPtr GetRunner() const; + + /** + * \~chinese + * @brief 获取主窗口 + */ + WindowPtr GetMainWindow() const; + /** * \~chinese * @brief 添加模块 @@ -97,26 +117,42 @@ public: */ void PreformInMainThread(Function func); -private: /** * \~chinese * @brief 更新所有模块 + * @param dt 时间间隔 */ - void Update(); + void Update(Duration dt); /** * \~chinese - * @brief 渲染所有模块 + * @brief 渲染 */ void Render(); private: bool quiting_; float time_scale_; - Time last_update_time_; - List modules_; + RunnerPtr runner_; + List modules_; std::mutex perform_mutex_; Queue> functions_to_perform_; }; +inline void Application::Run(RunnerPtr runner, bool debug) +{ + this->Run(runner.get(), debug); +} + +inline RunnerPtr Application::GetRunner() const +{ + return runner_; +} + +inline WindowPtr Application::GetMainWindow() const +{ + KGE_ASSERT(runner_); + return runner_->GetMainWindow(); +} + } // namespace kiwano diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp new file mode 100644 index 00000000..d5f24c3f --- /dev/null +++ b/src/kiwano/platform/Runner.cpp @@ -0,0 +1,100 @@ +// 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. + +#include +#include + +namespace kiwano +{ + +RunnerPtr Runner::Create(WindowPtr main_window) +{ + RunnerPtr ptr = new (std::nothrow) Runner; + if (ptr) + { + ptr->SetMainWindow(main_window); + } + return ptr; +} + +RunnerPtr Runner::Create(WindowPtr main_window, Function on_ready, Function on_destroy) +{ + class CallbackRunner : public Runner + { + public: + void OnReady() override + { + if (on_ready) + on_ready(); + } + + void OnDestroy() override + { + if (on_destroy) + on_destroy(); + } + + Function on_ready; + Function on_destroy; + }; + + SmartPtr ptr = new (std::nothrow) CallbackRunner; + if (ptr) + { + ptr->on_ready = on_ready; + ptr->on_destroy = on_destroy; + ptr->SetMainWindow(main_window); + } + return ptr; +} + +Runner::Runner() {} + +Runner::~Runner() {} + +bool Runner::MainLoop() +{ + if (main_window_->ShouldClose()) + { + if (this->OnClosing()) + return false; + + main_window_->SetShouldClose(false); + } + + Application& app = Application::GetInstance(); + + // Poll events + while (EventPtr evt = main_window_->PollEvent()) + { + app.DispatchEvent(evt.get()); + } + + // Update & render + const Time now = Time::Now(); + const Duration dt = (now - last_update_time_); + last_update_time_ = now; + + app.Update(dt); + app.Render(); + return true; +} + +} // namespace kiwano diff --git a/src/kiwano/core/Runner.h b/src/kiwano/platform/Runner.h similarity index 52% rename from src/kiwano/core/Runner.h rename to src/kiwano/platform/Runner.h index 6752b5b9..7f4d5f51 100644 --- a/src/kiwano/core/Runner.h +++ b/src/kiwano/platform/Runner.h @@ -20,25 +20,36 @@ #pragma once #include +#include +#include namespace kiwano { + +KGE_DECLARE_SMART_PTR(Runner); + /** * \~chinese * @brief 程序运行器 */ -class KGE_API Runner +class KGE_API Runner : public virtual ObjectBase { public: - typedef Function Callback; + /// \~chinese + /// @brief 创建程序运行器 + /// @param main_window 主窗口 + static RunnerPtr Create(WindowPtr main_window); + + /// \~chinese + /// @brief 创建程序运行器 + /// @param main_window 主窗口 + /// @param on_ready 应用程序初始化完成后执行的回调函数 + /// @param on_destroy 应用程序销毁时执行的回调函数 + static RunnerPtr Create(WindowPtr main_window, Function on_ready, Function on_destroy = nullptr); Runner(); - /// \~chinese - /// @brief 构造程序运行器 - /// @param on_ready 应用程序初始化完成后执行的回调函数 - /// @param on_destroy 应用程序销毁时执行的回调函数 - Runner(const Callback& on_ready, const Callback& on_destroy = nullptr); + virtual ~Runner(); /// \~chinese /// @brief 初始化完成处理 @@ -51,44 +62,65 @@ public: virtual void OnDestroy(); /// \~chinese - /// @brief 窗口关闭处理 - /// @details 重载该函数以处理用户关闭窗口时的行为,如保存用户数据等 - /// @return 返回true允许用户关闭窗口,否则阻止窗口关闭 + /// @brief 应用程序关闭处理 + /// @details 重载该函数以处理用户关闭应用程序时的行为,如保存用户数据等 + /// @return 返回true允许用户关闭程序,否则阻止程序关闭 virtual bool OnClosing(); + /// \~chinese + /// @brief 应用程序主循环 + /// @details 重载该函数以 + /// @return 返回false退出主循环,否则继续运行主循环 + virtual bool MainLoop(); + + /// \~chinese + /// @brief 获取主窗口 + WindowPtr GetMainWindow() const; + + /// \~chinese + /// @brief 设置主窗口 + void SetMainWindow(WindowPtr window); + + /// \~chinese + /// @brief 获取上一次更新时间 + Time GetLastUpdateTime() const; + + /// \~chinese + /// @brief 设置上一次更新时间 + void SetLastUpdateTime(Time time); + private: - Callback on_ready_; - Callback on_destroy_; + WindowPtr main_window_; + Time last_update_time_; }; +inline void Runner::OnReady() {} -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 void Runner::OnDestroy() {} inline bool Runner::OnClosing() { return true; } +inline WindowPtr Runner::GetMainWindow() const +{ + return main_window_; +} + +inline void Runner::SetMainWindow(WindowPtr window) +{ + main_window_ = window; +} + +inline Time Runner::GetLastUpdateTime() const +{ + return last_update_time_; +} + +inline void Runner::SetLastUpdateTime(Time time) +{ + last_update_time_ = time; +} + } // namespace kiwano diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index 01dd6820..35ccc97e 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -24,13 +24,17 @@ namespace kiwano { Window::Window() - : should_close_(false) + : handle_(nullptr) + , should_close_(false) , width_(0) , height_(0) { } -Window::~Window() {} +Window::~Window() +{ + Destroy(); +} EventPtr Window::PollEvent() { @@ -65,6 +69,11 @@ uint32_t Window::GetHeight() const return height_; } +WindowHandle Window::GetHandle() const +{ + return handle_; +} + bool Window::ShouldClose() { return should_close_; diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index efcca5f6..526b63f3 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -20,12 +20,15 @@ #pragma once #include +#include #include #include namespace kiwano { +KGE_DECLARE_SMART_PTR(Window); + /** * \~chinese * @brief 鼠标指针类型 @@ -43,19 +46,18 @@ enum class CursorType }; +#if defined(KGE_WIN32) +typedef HWND WindowHandle; +#endif + + /** * \~chinese * @brief 窗口类,控制窗口标题、大小、图标等 */ -class KGE_API Window : protected Noncopyable +class KGE_API Window : public ObjectBase { public: - /** - * \~chinese - * @brief 获取窗口实例 - */ - static Window& GetInstance(); - /** * \~chinese * @brief 初始化窗口 @@ -67,8 +69,8 @@ public: * @param fullscreen 全屏模式 * @throw std::system_error 窗口创建失败时抛出 */ - virtual void Create(String const& title, uint32_t width, uint32_t height, uint32_t icon = 0, bool resizable = false, - bool fullscreen = false) = 0; + static WindowPtr Create(String const& title, uint32_t width, uint32_t height, uint32_t icon = 0, + bool resizable = false, bool fullscreen = false); /** * \~chinese @@ -98,6 +100,12 @@ public: */ uint32_t GetHeight() const; + /** + * \~chinese + * @brief 获取窗口句柄 + */ + WindowHandle GetHandle() const; + /** * \~chinese * @brief 设置标题 @@ -146,11 +154,17 @@ public: /** * \~chinese - * @brief 将窗口事件放入队列 - * @param evt 窗口事件 + * @brief 将事件放入队列 + * @param evt 事件 */ void PushEvent(EventPtr evt); + /** + * \~chinese + * @brief 抽取窗口事件 + */ + virtual void PumpEvents() = 0; + /** * \~chinese * @brief 窗口是否需要关闭 @@ -172,14 +186,13 @@ public: protected: Window(); - ~Window(); - - virtual void PumpEvents() = 0; + virtual ~Window(); protected: bool should_close_; uint32_t width_; uint32_t height_; + WindowHandle handle_; String title_; std::queue event_queue_; }; diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index 12c38bee..dab99056 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -18,37 +18,87 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #if defined(KGE_WIN32) -#include // GET_X_LPARAM, GET_Y_LPARAM -#include // ImmAssociateContext +#include #include #include #include #include #include #include +#include // GET_X_LPARAM, GET_Y_LPARAM +#include // ImmAssociateContext #pragma comment(lib, "imm32.lib") -#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX -#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX -#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP - namespace kiwano { -Window& Window::GetInstance() +KGE_DECLARE_SMART_PTR(WindowWin32Impl); + +class KGE_API WindowWin32Impl : public Window { - return WindowImpl::GetInstance(); +public: + WindowWin32Impl(); + + virtual ~WindowWin32Impl(); + + void Init(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen); + + void SetTitle(String const& title) override; + + void SetIcon(uint32_t icon_resource) override; + + void Resize(uint32_t width, uint32_t height) override; + + void SetFullscreen(bool fullscreen) override; + + void SetCursor(CursorType cursor) override; + + void Destroy() override; + + void PumpEvents() override; + + DWORD GetStyle() const; + + void UpdateCursor(); + + void SetActive(bool actived); + + LRESULT MessageProc(HWND, UINT32, WPARAM, LPARAM); + + static LRESULT CALLBACK StaticWndProc(HWND, UINT32, WPARAM, LPARAM); + +private: + bool resizable_; + bool is_fullscreen_; + wchar_t* device_name_; + CursorType mouse_cursor_; + + std::array key_map_; +}; + +WindowPtr Window::Create(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, + bool fullscreen) +{ + WindowWin32ImplPtr ptr = new (std::nothrow) WindowWin32Impl; + if (ptr) + { + ptr->Init(title, width, height, icon, resizable, fullscreen); + } + return ptr; } -WindowImpl& WindowImpl::GetInstance() +} // namespace kiwano + +namespace kiwano { - static WindowImpl instance; - return instance; -} + +#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX +#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX +#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP namespace { @@ -106,9 +156,8 @@ void RestoreResolution(WCHAR* device_name) } } // namespace -WindowImpl::WindowImpl() - : handle_(nullptr) - , device_name_(nullptr) +WindowWin32Impl::WindowWin32Impl() + : device_name_(nullptr) , is_fullscreen_(false) , resizable_(false) , mouse_cursor_(CursorType::Arrow) @@ -156,17 +205,17 @@ WindowImpl::WindowImpl() key_map_[VK_F1 + i] = KeyCode(size_t(KeyCode::F1) + i); } -WindowImpl::~WindowImpl() {} +WindowWin32Impl::~WindowWin32Impl() {} -void WindowImpl::Create(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, - bool fullscreen) +void WindowWin32Impl::Init(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, + bool fullscreen) { HINSTANCE hinst = GetModuleHandleW(nullptr); WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpszClassName = L"KiwanoAppWnd"; wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */; - wcex.lpfnWndProc = WindowImpl::StaticWndProc; + wcex.lpfnWndProc = WindowWin32Impl::StaticWndProc; wcex.hIcon = nullptr; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); @@ -257,12 +306,7 @@ void WindowImpl::Create(String const& title, uint32_t width, uint32_t height, ui } } -HWND WindowImpl::GetHandle() const -{ - return handle_; -} - -void WindowImpl::PumpEvents() +void WindowWin32Impl::PumpEvents() { MSG msg; while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) @@ -272,7 +316,7 @@ void WindowImpl::PumpEvents() } } -void WindowImpl::SetTitle(String const& title) +void WindowWin32Impl::SetTitle(String const& title) { if (handle_) { @@ -281,7 +325,7 @@ void WindowImpl::SetTitle(String const& title) } } -void WindowImpl::SetIcon(uint32_t icon_resource) +void WindowWin32Impl::SetIcon(uint32_t icon_resource) { if (handle_) { @@ -294,7 +338,7 @@ void WindowImpl::SetIcon(uint32_t icon_resource) } } -void WindowImpl::Resize(uint32_t width, uint32_t height) +void WindowWin32Impl::Resize(uint32_t width, uint32_t height) { if (handle_ && !is_fullscreen_) { @@ -307,7 +351,7 @@ void WindowImpl::Resize(uint32_t width, uint32_t height) } } -void WindowImpl::SetFullscreen(bool fullscreen) +void WindowWin32Impl::SetFullscreen(bool fullscreen) { if (is_fullscreen_ != fullscreen) { @@ -349,12 +393,12 @@ void WindowImpl::SetFullscreen(bool fullscreen) } } -void WindowImpl::SetCursor(CursorType cursor) +void WindowWin32Impl::SetCursor(CursorType cursor) { mouse_cursor_ = cursor; } -void WindowImpl::Destroy() +void WindowWin32Impl::Destroy() { if (is_fullscreen_) RestoreResolution(device_name_); @@ -374,12 +418,12 @@ void WindowImpl::Destroy() Window::Destroy(); } -DWORD WindowImpl::GetStyle() const +DWORD WindowWin32Impl::GetStyle() const { return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE)); } -void WindowImpl::UpdateCursor() +void WindowWin32Impl::UpdateCursor() { LPTSTR win32_cursor = IDC_ARROW; switch (mouse_cursor_) @@ -412,7 +456,7 @@ void WindowImpl::UpdateCursor() ::SetCursor(::LoadCursorW(nullptr, win32_cursor)); } -void WindowImpl::SetActive(bool actived) +void WindowWin32Impl::SetActive(bool actived) { if (!handle_) return; @@ -437,7 +481,7 @@ void WindowImpl::SetActive(bool actived) } } -LRESULT WindowImpl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) +LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) { switch (msg) { @@ -553,7 +597,7 @@ LRESULT WindowImpl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lpa { // KGE_SYS_LOG("Window resized"); - this->width_ = ((uint32_t)(short)LOWORD(lparam)); + this->width_ = ((uint32_t)(short)LOWORD(lparam)); this->height_ = ((uint32_t)(short)HIWORD(lparam)); WindowResizedEventPtr evt = new WindowResizedEvent; @@ -641,12 +685,12 @@ LRESULT WindowImpl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lpa return ::DefWindowProcW(hwnd, msg, wparam, lparam); } -LRESULT CALLBACK WindowImpl::StaticWndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) +LRESULT CALLBACK WindowWin32Impl::StaticWndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) { LONG_PTR ptr = static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)); if (ptr) { - WindowImpl* window = reinterpret_cast(ptr); + WindowWin32Impl* window = reinterpret_cast(ptr); return window->MessageProc(hwnd, msg, wparam, lparam); } return ::DefWindowProcW(hwnd, msg, wparam, lparam); diff --git a/src/kiwano/platform/win32/WindowImpl.h b/src/kiwano/platform/win32/WindowImpl.h deleted file mode 100644 index 65fff529..00000000 --- a/src/kiwano/platform/win32/WindowImpl.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2016-2020 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 -#include - -#if defined(KGE_WIN32) - -namespace kiwano -{ - -class KGE_API WindowImpl : public Window -{ -public: - static WindowImpl& GetInstance(); - - HWND GetHandle() const; - - void Create(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, - bool fullscreen) override; - - void SetTitle(String const& title) override; - - void SetIcon(uint32_t icon_resource) override; - - void Resize(uint32_t width, uint32_t height) override; - - void SetFullscreen(bool fullscreen) override; - - void SetCursor(CursorType cursor) override; - - void Destroy() override; - -private: - WindowImpl(); - - ~WindowImpl(); - - void PumpEvents() override; - - DWORD GetStyle() const; - - void UpdateCursor(); - - void SetActive(bool actived); - - LRESULT MessageProc(HWND, UINT32, WPARAM, LPARAM); - - static LRESULT CALLBACK StaticWndProc(HWND, UINT32, WPARAM, LPARAM); - -private: - bool resizable_; - bool is_fullscreen_; - wchar_t* device_name_; - HWND handle_; - CursorType mouse_cursor_; - - std::array key_map_; -}; - -} // namespace kiwano - -#endif diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index 494bdc91..6a7e5a78 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,14 +46,14 @@ RendererImpl::RendererImpl() render_ctx_ = new RenderContextImpl; } -void RendererImpl::SetupModule() +void RendererImpl::MakeContextForWindow(WindowPtr window) { KGE_SYS_LOG("Creating device resources"); ThrowIfFailed(::CoInitialize(nullptr), "CoInitialize failed"); - HWND target_window = WindowImpl::GetInstance().GetHandle(); - output_size_ = Window::GetInstance().GetSize(); + HWND target_window = window->GetHandle(); + output_size_ = window->GetSize(); d2d_res_ = nullptr; d3d_res_ = nullptr; @@ -115,7 +115,7 @@ void RendererImpl::SetupModule() ThrowIfFailed(hr, "Create render resources failed"); } -void RendererImpl::DestroyModule() +void RendererImpl::Destroy() { KGE_SYS_LOG("Destroying device resources"); @@ -168,15 +168,6 @@ void RendererImpl::Present() ThrowIfFailed(hr, "Unexpected DXGI exception"); } -void RendererImpl::HandleEvent(Event* evt) -{ - if (evt->IsType()) - { - auto window_evt = dynamic_cast(evt); - Resize(window_evt->width, window_evt->height); - } -} - HRESULT RendererImpl::HandleDeviceLost() { KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_); diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index 2c010a2d..a9e1712d 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -44,55 +44,55 @@ class KGE_API RendererImpl public: static RendererImpl& GetInstance(); - void CreateTexture(Texture& texture, String const& file_path); + void CreateTexture(Texture& texture, String const& file_path) override; - void CreateTexture(Texture& texture, Resource const& resource); + void CreateTexture(Texture& texture, Resource const& resource) override; - void CreateGifImage(GifImage& gif, String const& file_path); + void CreateGifImage(GifImage& gif, String const& file_path) override; - void CreateGifImage(GifImage& gif, Resource const& resource); + void CreateGifImage(GifImage& gif, Resource const& resource) override; - void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index); + void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index) override; - void CreateFontCollection(Font& font, String const& file_path); + void CreateFontCollection(Font& font, String const& file_path) override; - void CreateFontCollection(Font& font, Resource const& res); + void CreateFontCollection(Font& font, Resource const& res) override; - void CreateTextFormat(TextLayout& layout); + void CreateTextFormat(TextLayout& layout) override; - void CreateTextLayout(TextLayout& layout); + void CreateTextLayout(TextLayout& layout) override; - void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos); + void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos) override; - void CreateRectShape(Shape& shape, Rect const& rect); + void CreateRectShape(Shape& shape, Rect const& rect) override; - void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius); + void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius) override; - void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius); + void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) override; - void CreateShapeSink(ShapeSink& sink); + void CreateShapeSink(ShapeSink& sink) override; - void CreateBrush(Brush& brush, Color const& color); + void CreateBrush(Brush& brush, Color const& color) override; - void CreateBrush(Brush& brush, LinearGradientStyle const& style); + void CreateBrush(Brush& brush, LinearGradientStyle const& style) override; - void CreateBrush(Brush& brush, RadialGradientStyle const& style); + void CreateBrush(Brush& brush, RadialGradientStyle const& style) override; void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, const float* dash_array, - size_t dash_size, float dash_offset); + size_t dash_size, float dash_offset) override; - TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr); + TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) override; public: - void BeginDraw(); + void BeginDraw() override; - void EndDraw(); + void EndDraw() override; - void Clear(); + void Clear() override; - void Present(); + void Present() override; - RenderContext& GetContext(); + RenderContext& GetContext() override; /// \~chinese /// @brief 获取Direct2D设备资源 @@ -102,19 +102,18 @@ public: /// @brief 获取Direct3D设备资源 ID3DDeviceResources* GetD3DDeviceResources(); -public: - void SetupModule() override; + /// \~chinese + /// @brief 重设渲染输出大小 + void Resize(uint32_t width, uint32_t height) override; - void DestroyModule() override; - - void HandleEvent(Event* evt) override; - -private: +protected: RendererImpl(); - HRESULT HandleDeviceLost(); + void MakeContextForWindow(WindowPtr window) override; - void Resize(uint32_t width, uint32_t height); + void Destroy() override; + + HRESULT HandleDeviceLost(); private: RenderContextImplPtr render_ctx_; diff --git a/src/kiwano/render/Renderer.cpp b/src/kiwano/render/Renderer.cpp index 53904c2c..c9e3ed55 100644 --- a/src/kiwano/render/Renderer.cpp +++ b/src/kiwano/render/Renderer.cpp @@ -19,6 +19,8 @@ // THE SOFTWARE. #include +#include +#include namespace kiwano { @@ -29,4 +31,24 @@ Renderer::Renderer() { } +void Renderer::SetupModule() +{ + WindowPtr window = Application::GetInstance().GetMainWindow(); + MakeContextForWindow(window); +} + +void Renderer::DestroyModule() +{ + Destroy(); +} + +void Renderer::HandleEvent(Event* evt) +{ + if (evt->IsType()) + { + auto window_evt = dynamic_cast(evt); + Resize(window_evt->width, window_evt->height); + } +} + } // namespace kiwano diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index 85c1f906..cfe67cc1 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -25,13 +25,14 @@ #include #include #include +#include namespace kiwano { /** * \~chinese - * \defgroup Render 渲染引擎 + * \defgroup Render 渲染模块 */ /** @@ -202,6 +203,14 @@ public: virtual TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) = 0; public: + /// \~chinese + /// @brief 获取渲染上下文 + virtual RenderContext& GetContext() = 0; + + /// \~chinese + /// @brief 获取渲染输出大小 + virtual Size GetOutputSize() const; + /// \~chinese /// @brief 开始渲染 virtual void BeginDraw() = 0; @@ -220,20 +229,27 @@ public: virtual void Present() = 0; /// \~chinese - /// @brief 获取渲染上下文 - virtual RenderContext& GetContext() = 0; + /// @brief 重设渲染输出大小 + virtual void Resize(uint32_t width, uint32_t height) = 0; - /// \~chinese - /// @brief 获取渲染输出大小 - virtual Size GetOutputSize() const; +public: + void SetupModule() override; + + void DestroyModule() override; + + void HandleEvent(Event* evt) override; protected: Renderer(); + virtual void MakeContextForWindow(WindowPtr window) = 0; + + virtual void Destroy() = 0; + protected: - bool vsync_; - Color clear_color_; - Size output_size_; + bool vsync_; + Color clear_color_; + Size output_size_; }; /** @} */