diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 6b2f3a5d..1a09e2d1 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -13,6 +13,7 @@ + @@ -55,7 +56,6 @@ - @@ -111,6 +111,7 @@ + @@ -126,7 +127,6 @@ - diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index 80189179..134c91ce 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -231,9 +231,6 @@ platform - - platform - 2d @@ -282,6 +279,9 @@ renderer + + core + @@ -440,9 +440,6 @@ platform - - platform - 2d @@ -479,5 +476,8 @@ renderer + + core + \ No newline at end of file diff --git a/src/kiwano-imgui/ImGuiLayer.cpp b/src/kiwano-imgui/ImGuiLayer.cpp index 754bad47..ae5ea8e7 100644 --- a/src/kiwano-imgui/ImGuiLayer.cpp +++ b/src/kiwano-imgui/ImGuiLayer.cpp @@ -35,14 +35,18 @@ namespace kiwano void ImGuiLayer::OnRender(RenderContext& ctx) { - PrepareToRender(ctx); for (const auto& pipeline : pipelines_) { pipeline.second(); } } - void ImGuiLayer::AddItem(ImGuiPipeline const& item, String const& name) + bool ImGuiLayer::CheckVisibility(RenderContext& ctx) const + { + return true; + } + + void ImGuiLayer::AddItem(String const& name, ImGuiPipeline const& item) { pipelines_.insert(std::make_pair(name, item)); } diff --git a/src/kiwano-imgui/ImGuiLayer.h b/src/kiwano-imgui/ImGuiLayer.h index 1d243f95..d62e5b0c 100644 --- a/src/kiwano-imgui/ImGuiLayer.h +++ b/src/kiwano-imgui/ImGuiLayer.h @@ -45,9 +45,9 @@ namespace kiwano /// \~chinese /// @brief 添加 ImGui 元素 - /// @param item 管道 /// @param name 元素名称 - void AddItem(ImGuiPipeline const& item, String const& name); + /// @param item 管道 + void AddItem(String const& name, ImGuiPipeline const& item); /// \~chinese /// @brief 移除 ImGui 元素 @@ -62,6 +62,8 @@ namespace kiwano public: void OnRender(RenderContext& ctx) override; + bool CheckVisibility(RenderContext& ctx) const override; + private: Map pipelines_; }; diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index d0fa9a0f..ac7ed61c 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -1,32 +1,20 @@ // Copyright (C) 2019 Nomango #include +#include +#include #include #include #include #include #include -#include -#pragma comment(lib, "xinput") - -// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. -#ifndef WM_MOUSEHWHEEL -# define WM_MOUSEHWHEEL 0x020E -#endif - -#ifndef DBT_DEVNODES_CHANGED -# define DBT_DEVNODES_CHANGED 0x0007 -#endif - namespace kiwano { namespace imgui { ImGuiModule::ImGuiModule() - : has_gamepad_(false) - , want_update_has_gamepad_(false) - , target_window_(nullptr) + : target_window_(nullptr) { } @@ -36,55 +24,17 @@ namespace kiwano IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls // Setup Dear ImGui style ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); // Setup Platform/Renderer bindings - Init(Window::instance().GetHandle()); - target_window_ = Renderer::instance().GetTargetWindow(); - } - void ImGuiModule::DestroyComponent() - { - ImGui_Impl_Shutdown(); - ImGui::DestroyContext(); - } - - void ImGuiModule::OnUpdate(Duration dt) - { - ImGuiIO& io = ImGui::GetIO(); - - // Setup time step - io.DeltaTime = dt.Seconds(); - - // Read keyboard modifiers inputs - io.KeyCtrl = Input::instance().IsDown(KeyCode::Ctrl); - io.KeyShift = Input::instance().IsDown(KeyCode::Shift); - io.KeyAlt = Input::instance().IsDown(KeyCode::Alt); - io.KeySuper = false; - // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. - - // Update OS mouse position - UpdateMousePos(); - - // Update OS mouse cursor with the cursor requested by imgui - UpdateMouseCursor(); - - // Update game controllers (if enabled and available) - UpdateGamepads(); - } - - void ImGuiModule::Init(HWND hwnd) - { - ImGuiIO& io = ImGui::GetIO(); 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 = hwnd; + io.ImeWindowHandle = target_window_; // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. io.KeyMap[ImGuiKey_Tab] = KeyCode::Tab; @@ -104,7 +54,34 @@ namespace kiwano io.KeyMap[ImGuiKey_Y] = KeyCode::Y; io.KeyMap[ImGuiKey_Z] = KeyCode::Z; - ImGui_Impl_Init(&Renderer::instance()); + ImGui_Impl_Init(Renderer::instance()); + } + + void ImGuiModule::DestroyComponent() + { + ImGui_Impl_Shutdown(); + ImGui::DestroyContext(); + } + + void ImGuiModule::OnUpdate(Duration dt) + { + ImGuiIO& io = ImGui::GetIO(); + + // Setup time step + io.DeltaTime = dt.Seconds(); + + // Read keyboard modifiers inputs + io.KeyCtrl = Input::instance().IsDown(KeyCode::Ctrl); + io.KeyShift = Input::instance().IsDown(KeyCode::Shift); + io.KeyAlt = Input::instance().IsDown(KeyCode::Alt); + io.KeySuper = Input::instance().IsDown(KeyCode::Super); + // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below. + + // Update OS mouse position + UpdateMousePos(); + + // Update OS mouse cursor with the cursor requested by imgui + UpdateMouseCursor(); } void ImGuiModule::BeforeRender() @@ -117,89 +94,56 @@ namespace kiwano Render(); } - void ImGuiModule::HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) + void ImGuiModule::HandleEvent(Event* evt) { if (ImGui::GetCurrentContext() == NULL) return; ImGuiIO& io = ImGui::GetIO(); - switch (msg) + if (evt->IsType()) { - case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: - case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: - { - int button = 0; - if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } - if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } - if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } - if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wparam) == XBUTTON1) ? 3 : 4; } - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) - ::SetCapture(hwnd); - - io.MouseDown[button] = true; - break; - } - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: - { - int button = 0; - if (msg == WM_LBUTTONUP) { button = 0; } - if (msg == WM_RBUTTONUP) { button = 1; } - if (msg == WM_MBUTTONUP) { button = 2; } - if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wparam) == XBUTTON1) ? 3 : 4; } - io.MouseDown[button] = false; - if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) - ::ReleaseCapture(); - break; - } - case WM_MOUSEWHEEL: - { - io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; - break; - } - case WM_MOUSEHWHEEL: - { - io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; - break; - } - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - { - if (wparam < 256) - io.KeysDown[wparam] = 1; - break; - } - case WM_KEYUP: - case WM_SYSKEYUP: - { - if (wparam < 256) - io.KeysDown[wparam] = 0; - break; - } - case WM_CHAR: - { - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - io.AddInputCharacter((uint32_t)wparam); - break; - } - case WM_SETCURSOR: - { - if (LOWORD(lparam) == HTCLIENT) + if (evt->IsType()) { - UpdateMouseCursor(); + int button = dynamic_cast(evt)->button; + int index = 0; + if (button == MouseButton::Left) index = 0; + else if (button == MouseButton::Right) index = 1; + else if (button == MouseButton::Middle) index = 2; + io.MouseDown[index] = true; + } + else if (evt->IsType()) + { + int button = dynamic_cast(evt)->button; + int index = 0; + if (button == MouseButton::Left) index = 0; + else if (button == MouseButton::Right) index = 1; + else if (button == MouseButton::Middle) index = 2; + io.MouseDown[index] = false; + } + else if (evt->IsType()) + { + float wheel = dynamic_cast(evt)->wheel; + io.MouseWheel += wheel; } - break; } - case WM_DEVICECHANGE: + else if (evt->IsType()) { - if ((uint32_t)wparam == DBT_DEVNODES_CHANGED) - want_update_has_gamepad_ = true; - break; - } + if (evt->IsType()) + { + int key = dynamic_cast(evt)->code; + io.KeysDown[key] = true; + } + else if (evt->IsType()) + { + int key = dynamic_cast(evt)->code; + io.KeysDown[key] = false; + } + else if (evt->IsType()) + { + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + char ch = dynamic_cast(evt)->value; + io.AddInputCharacter(static_cast(ch)); + } } } @@ -260,50 +204,6 @@ namespace kiwano Window::instance().SetCursor(cursor); } - void ImGuiModule::UpdateGamepads() - { - ImGuiIO& io = ImGui::GetIO(); - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) - return; - // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. - // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. - if (want_update_has_gamepad_) - { - XINPUT_CAPABILITIES caps; - has_gamepad_ = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS); - want_update_has_gamepad_ = false; - } - - XINPUT_STATE xinput_state; - io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; - if (has_gamepad_ && XInputGetState(0, &xinput_state) == ERROR_SUCCESS) - { - const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; - io.BackendFlags |= ImGuiBackendFlags_HasGamepad; - -#define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; } -#define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } - MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A - MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B - MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X - MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y - MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left - MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right - MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up - MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB - MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB - MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB - MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB - MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); - MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); - MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); - MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767); -#undef MAP_BUTTON -#undef MAP_ANALOG - } - } } } diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index 50e50115..b4087c12 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -49,13 +49,11 @@ namespace kiwano void AfterRender() override; - void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; + void HandleEvent(Event* evt) override; void OnUpdate(Duration dt) override; private: - void Init(HWND hwnd); - void NewFrame(); void Render(); @@ -64,12 +62,8 @@ namespace kiwano void UpdateMouseCursor(); - void UpdateGamepads(); - private: - bool has_gamepad_; - bool want_update_has_gamepad_; - HWND target_window_; + WindowHandle target_window_; }; } } diff --git a/src/kiwano-imgui/imgui_impl.h b/src/kiwano-imgui/imgui_impl.h index 372f26fe..72fb88cf 100644 --- a/src/kiwano-imgui/imgui_impl.h +++ b/src/kiwano-imgui/imgui_impl.h @@ -8,7 +8,7 @@ #include -inline bool ImGui_Impl_Init(::kiwano::Renderer* renderer) { return ImGui_ImplDX11_Init(renderer->GetD3DDeviceResources()->GetDevice(), renderer->GetD3DDeviceResources()->GetDeviceContext()); } +inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(), renderer.GetD3DDeviceResources()->GetDeviceContext()); } inline void ImGui_Impl_Shutdown() { ImGui_ImplDX11_Shutdown(); } inline void ImGui_Impl_NewFrame() { ImGui_ImplDX11_NewFrame(); } inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX11_RenderDrawData(draw_data); } @@ -20,7 +20,7 @@ inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX11_Cre #include -inline bool ImGui_Impl_Init(::kiwano::Renderer* renderer) { return ImGui_ImplDX10_Init(renderer->GetD3DDeviceResources()->GetDevice()); } +inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice()); } inline void ImGui_Impl_Shutdown() { ImGui_ImplDX10_Shutdown(); } inline void ImGui_Impl_NewFrame() { ImGui_ImplDX10_NewFrame(); } inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX10_RenderDrawData(draw_data); } diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h index 79a11962..65679692 100644 --- a/src/kiwano-physics/ContactEvent.h +++ b/src/kiwano-physics/ContactEvent.h @@ -26,6 +26,9 @@ namespace kiwano { namespace physics { + KGE_DECLARE_SMART_PTR(ContactBeginEvent); + KGE_DECLARE_SMART_PTR(ContactEndEvent); + /** * \addtogroup Events * @{ diff --git a/src/kiwano-physics/World.cpp b/src/kiwano-physics/World.cpp index 9814557c..99cf93bf 100644 --- a/src/kiwano-physics/World.cpp +++ b/src/kiwano-physics/World.cpp @@ -67,14 +67,14 @@ namespace kiwano void BeginContact(b2Contact* contact) override { - ContactBeginEvent evt(contact); - world_->DispatchEvent(evt); + ContactBeginEventPtr evt = new ContactBeginEvent(contact); + world_->DispatchEvent(evt.get()); } void EndContact(b2Contact* contact) override { - ContactEndEvent evt(contact); - world_->DispatchEvent(evt); + ContactEndEventPtr evt = new ContactEndEvent(contact); + world_->DispatchEvent(evt.get()); } void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override { KGE_NOT_USED(contact); KGE_NOT_USED(oldManifold); } diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index eb01716d..5ebc692b 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -97,7 +97,7 @@ namespace kiwano if (children_.empty()) { - if (CheckVisibilty(ctx)) + if (CheckVisibility(ctx)) { PrepareToRender(ctx); OnRender(ctx); @@ -116,7 +116,7 @@ namespace kiwano child = child->next_item().get(); } - if (CheckVisibilty(ctx)) + if (CheckVisibility(ctx)) { PrepareToRender(ctx); OnRender(ctx); @@ -157,7 +157,7 @@ namespace kiwano } } - bool Actor::CheckVisibilty(RenderContext& ctx) const + bool Actor::CheckVisibility(RenderContext& ctx) const { if (dirty_visibility_) { @@ -175,7 +175,7 @@ namespace kiwano return visible_in_rt_; } - bool Actor::DispatchEvent(Event& evt) + bool Actor::DispatchEvent(Event* evt) { if (!visible_) return true; @@ -208,54 +208,48 @@ namespace kiwano return true; } - void Actor::HandleEvent(Event& evt) + void Actor::HandleEvent(Event* evt) { if (responsible_) { - if (evt.IsType()) + if (evt->IsType()) { - auto& mouse_evt = evt.SafeCast(); - bool contains = ContainsPoint(mouse_evt.pos); + auto mouse_evt = dynamic_cast(evt); + bool contains = ContainsPoint(mouse_evt->pos); if (!hover_ && contains) { hover_ = true; - MouseHoverEvent hover; - hover.pos = mouse_evt.pos; - hover.left_btn_down = mouse_evt.left_btn_down; - hover.right_btn_down = mouse_evt.right_btn_down; - EventDispatcher::DispatchEvent(hover); + MouseHoverEventPtr hover = new MouseHoverEvent; + hover->pos = mouse_evt->pos; + EventDispatcher::DispatchEvent(hover.get()); } else if (hover_ && !contains) { hover_ = false; pressed_ = false; - MouseOutEvent out; - out.pos = mouse_evt.pos; - out.left_btn_down = mouse_evt.left_btn_down; - out.right_btn_down = mouse_evt.right_btn_down; - EventDispatcher::DispatchEvent(out); + MouseOutEventPtr out = new MouseOutEvent; + out->pos = mouse_evt->pos; + EventDispatcher::DispatchEvent(out.get()); } } - if (evt.IsType() && hover_) + if (evt->IsType() && hover_) { pressed_ = true; } - if (evt.IsType() && pressed_) + if (evt->IsType() && pressed_) { pressed_ = false; - auto& mouse_up_evt = evt.SafeCast(); + auto mouse_up_evt = dynamic_cast(evt); - MouseClickEvent click; - click.pos = mouse_up_evt.pos; - click.left_btn_down = mouse_up_evt.left_btn_down; - click.right_btn_down = mouse_up_evt.right_btn_down; - click.button = mouse_up_evt.button; - EventDispatcher::DispatchEvent(click); + MouseClickEventPtr click = new MouseClickEvent; + click->pos = mouse_up_evt->pos; + click->button = mouse_up_evt->button; + EventDispatcher::DispatchEvent(click.get()); } } } diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index e32057da..96334877 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -395,7 +395,7 @@ namespace kiwano /// @brief 分发事件 /// @param evt 事件 /// @return 是否继续分发该事件 - virtual bool DispatchEvent(Event& evt); + virtual bool DispatchEvent(Event* evt); /// \~chinese /// @brief 设置默认锚点 @@ -416,10 +416,10 @@ namespace kiwano /// \~chinese /// @brief 检查是否在渲染上下文的视区内 - virtual bool CheckVisibilty(RenderContext& ctx) const; + virtual bool CheckVisibility(RenderContext& ctx) const; /// \~chinese - /// @brief 渲染前初始化渲染上下文状态,仅当 CheckVisibilty 返回真时调用该函数 + /// @brief 渲染前初始化渲染上下文状态,仅当 CheckVisibility 返回真时调用该函数 virtual void PrepareToRender(RenderContext& ctx); /// \~chinese @@ -440,7 +440,7 @@ namespace kiwano /// \~chinese /// @brief 处理事件 - void HandleEvent(Event& evt); + void HandleEvent(Event* evt); private: bool visible_; diff --git a/src/kiwano/2d/Button.cpp b/src/kiwano/2d/Button.cpp index 424ec53f..a7b3a263 100644 --- a/src/kiwano/2d/Button.cpp +++ b/src/kiwano/2d/Button.cpp @@ -130,28 +130,28 @@ namespace kiwano return status_; } - void Button::UpdateStatus(Event& evt) + void Button::UpdateStatus(Event* evt) { if (!enabled_) return; - if (evt.IsType()) + if (evt->IsType()) { SetStatus(Status::Hover); } - else if (evt.IsType()) + else if (evt->IsType()) { SetStatus(Status::Normal); } - else if (evt.IsType() && status_ == Status::Hover) + else if (evt->IsType() && status_ == Status::Hover) { SetStatus(Status::Pressed); } - else if (evt.IsType() && status_ == Status::Pressed) + else if (evt->IsType() && status_ == Status::Pressed) { SetStatus(Status::Hover); } - else if (evt.IsType()) + else if (evt->IsType()) { if (click_callback_) click_callback_(this); diff --git a/src/kiwano/2d/Button.h b/src/kiwano/2d/Button.h index 73247ea9..e8fc1af2 100644 --- a/src/kiwano/2d/Button.h +++ b/src/kiwano/2d/Button.h @@ -105,7 +105,7 @@ namespace kiwano protected: /// \~chinese /// @brief 更新按钮状态 - void UpdateStatus(Event& evt); + void UpdateStatus(Event* evt); private: bool enabled_; diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index d235f788..b4e7dbd6 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -67,8 +67,8 @@ namespace kiwano style.fill_brush = fill_brush; debug_text_.SetStyle(style); - AddListener([=](Event&) { SetOpacity(0.4f); }); - AddListener([=](Event&) { SetOpacity(1.f); }); + AddListener([=](Event*) { SetOpacity(0.4f); }); + AddListener([=](Event*) { SetOpacity(1.f); }); } DebugActor::~DebugActor() @@ -139,7 +139,7 @@ namespace kiwano } } - bool DebugActor::CheckVisibilty(RenderContext& ctx) const + bool DebugActor::CheckVisibility(RenderContext& ctx) const { return true; } diff --git a/src/kiwano/2d/DebugActor.h b/src/kiwano/2d/DebugActor.h index b2eb60eb..01a7317d 100644 --- a/src/kiwano/2d/DebugActor.h +++ b/src/kiwano/2d/DebugActor.h @@ -46,7 +46,7 @@ namespace kiwano void OnUpdate(Duration dt) override; protected: - bool CheckVisibilty(RenderContext& ctx) const override; + bool CheckVisibility(RenderContext& ctx) const override; private: std::locale comma_locale_; diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index ec052938..e0cd31cd 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -72,7 +72,7 @@ namespace kiwano void GifSprite::OnRender(RenderContext& ctx) { - if (frame_to_render_ && CheckVisibilty(ctx)) + if (frame_to_render_ && CheckVisibility(ctx)) { PrepareToRender(ctx); diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp index 52f5f163..8b652d6c 100644 --- a/src/kiwano/2d/Layer.cpp +++ b/src/kiwano/2d/Layer.cpp @@ -54,7 +54,7 @@ namespace kiwano area_.SetMaskTransform(transform); } - bool Layer::DispatchEvent(Event& evt) + bool Layer::DispatchEvent(Event* evt) { if (!IsVisible()) return true; @@ -75,7 +75,7 @@ namespace kiwano ctx.PopLayer(); } - bool Layer::CheckVisibilty(RenderContext& ctx) const + bool Layer::CheckVisibility(RenderContext& ctx) const { // Do not need to render Layer return false; diff --git a/src/kiwano/2d/Layer.h b/src/kiwano/2d/Layer.h index 0026a358..b28aa085 100644 --- a/src/kiwano/2d/Layer.h +++ b/src/kiwano/2d/Layer.h @@ -82,12 +82,12 @@ namespace kiwano /// @brief 获取图层区域 LayerArea const& GetArea() const; - bool DispatchEvent(Event& evt) override; + bool DispatchEvent(Event* evt) override; protected: void Render(RenderContext& ctx) override; - bool CheckVisibilty(RenderContext& ctx) const override; + bool CheckVisibility(RenderContext& ctx) const override; private: bool swallow_; diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp index 4d7c7ea1..9bc1c0a7 100644 --- a/src/kiwano/2d/ShapeActor.cpp +++ b/src/kiwano/2d/ShapeActor.cpp @@ -99,9 +99,9 @@ namespace kiwano ctx.FillGeometry(geo_); } - bool ShapeActor::CheckVisibilty(RenderContext& ctx) const + bool ShapeActor::CheckVisibility(RenderContext& ctx) const { - return geo_.IsValid() && Actor::CheckVisibilty(ctx); + return geo_.IsValid() && Actor::CheckVisibility(ctx); } //------------------------------------------------------- diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h index fc335706..052c633a 100644 --- a/src/kiwano/2d/ShapeActor.h +++ b/src/kiwano/2d/ShapeActor.h @@ -122,7 +122,7 @@ namespace kiwano void OnRender(RenderContext& ctx) override; protected: - bool CheckVisibilty(RenderContext& ctx) const override; + bool CheckVisibility(RenderContext& ctx) const override; private: BrushPtr fill_brush_; diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp index 9dee1773..f6c22809 100644 --- a/src/kiwano/2d/Sprite.cpp +++ b/src/kiwano/2d/Sprite.cpp @@ -79,8 +79,8 @@ namespace kiwano ctx.DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds()); } - bool Sprite::CheckVisibilty(RenderContext& ctx) const + bool Sprite::CheckVisibility(RenderContext& ctx) const { - return frame_ && frame_->IsValid() && Actor::CheckVisibilty(ctx); + return frame_ && frame_->IsValid() && Actor::CheckVisibility(ctx); } } diff --git a/src/kiwano/2d/Sprite.h b/src/kiwano/2d/Sprite.h index 33b2ea0e..b30bda5a 100644 --- a/src/kiwano/2d/Sprite.h +++ b/src/kiwano/2d/Sprite.h @@ -70,7 +70,7 @@ namespace kiwano void OnRender(RenderContext& ctx) override; protected: - bool CheckVisibilty(RenderContext& ctx) const override; + bool CheckVisibility(RenderContext& ctx) const override; private: FramePtr frame_; diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp index 9f3b3424..b7180231 100644 --- a/src/kiwano/2d/TextActor.cpp +++ b/src/kiwano/2d/TextActor.cpp @@ -106,9 +106,9 @@ namespace kiwano } } - bool TextActor::CheckVisibilty(RenderContext& ctx) const + bool TextActor::CheckVisibility(RenderContext& ctx) const { - return text_layout_.IsValid() && Actor::CheckVisibilty(ctx); + return text_layout_.IsValid() && Actor::CheckVisibility(ctx); } void TextActor::SetFillColor(Color const& color) diff --git a/src/kiwano/2d/TextActor.h b/src/kiwano/2d/TextActor.h index 283ffe58..a7576d91 100644 --- a/src/kiwano/2d/TextActor.h +++ b/src/kiwano/2d/TextActor.h @@ -175,7 +175,7 @@ namespace kiwano void OnUpdate(Duration dt) override; protected: - bool CheckVisibilty(RenderContext& ctx) const override; + bool CheckVisibility(RenderContext& ctx) const override; private: bool show_underline_; diff --git a/src/kiwano/core/Component.h b/src/kiwano/core/Component.h index e9b703d0..514809aa 100644 --- a/src/kiwano/core/Component.h +++ b/src/kiwano/core/Component.h @@ -119,11 +119,7 @@ namespace kiwano /// \~chinese /// @brief 事件处理 /// @param evt 事件 - virtual void HandleEvent(Event& evt) {} - - /// \~chinese - /// @brief 处理 Windows 消息 - virtual void HandleMessage(HWND, UINT32, WPARAM, LPARAM) {} + virtual void HandleEvent(Event* evt) {} public: static const int flag; diff --git a/src/kiwano/platform/Director.cpp b/src/kiwano/core/Director.cpp similarity index 98% rename from src/kiwano/platform/Director.cpp rename to src/kiwano/core/Director.cpp index 463ada46..aaf44e2c 100644 --- a/src/kiwano/platform/Director.cpp +++ b/src/kiwano/core/Director.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include #include @@ -179,7 +179,7 @@ namespace kiwano } } - void Director::HandleEvent(Event& evt) + void Director::HandleEvent(Event* evt) { if (current_stage_) current_stage_->DispatchEvent(evt); diff --git a/src/kiwano/platform/Director.h b/src/kiwano/core/Director.h similarity index 98% rename from src/kiwano/platform/Director.h rename to src/kiwano/core/Director.h index 3ab0831e..e8445793 100644 --- a/src/kiwano/platform/Director.h +++ b/src/kiwano/core/Director.h @@ -108,7 +108,7 @@ namespace kiwano void OnRender(RenderContext& ctx) override; - void HandleEvent(Event& evt) override; + void HandleEvent(Event* evt) override; private: Director(); diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/core/EventDispatcher.cpp index 74cec5ae..999a1e5e 100644 --- a/src/kiwano/core/EventDispatcher.cpp +++ b/src/kiwano/core/EventDispatcher.cpp @@ -23,7 +23,7 @@ namespace kiwano { - bool EventDispatcher::DispatchEvent(Event& evt) + bool EventDispatcher::DispatchEvent(Event* evt) { if (listeners_.empty()) return true; diff --git a/src/kiwano/core/EventDispatcher.h b/src/kiwano/core/EventDispatcher.h index 8e0edb5d..2859d460 100644 --- a/src/kiwano/core/EventDispatcher.h +++ b/src/kiwano/core/EventDispatcher.h @@ -132,7 +132,7 @@ namespace kiwano /// @brief 分发事件 /// @param evt 事件 /// @return 是否继续分发该事件 - bool DispatchEvent(Event& evt); + bool DispatchEvent(Event* evt); private: Listeners listeners_; diff --git a/src/kiwano/core/EventListener.h b/src/kiwano/core/EventListener.h index a28425fe..d3be9f56 100644 --- a/src/kiwano/core/EventListener.h +++ b/src/kiwano/core/EventListener.h @@ -47,7 +47,7 @@ namespace kiwano public: /// \~chinese /// @brief 监听器回调函数 - using Callback = Function; + using Callback = Function; /// \~chinese /// @brief 构造空监听器 @@ -154,7 +154,7 @@ namespace kiwano /// \~chinese /// @brief 接收消息 - void Receive(Event& evt); + void Receive(Event* evt); private: bool running_; @@ -220,9 +220,11 @@ namespace kiwano type_ = type; } - inline void EventListener::Receive(Event& evt) + inline void EventListener::Receive(Event* evt) { - if (type_ == evt.GetType() && callback_) + KGE_ASSERT(evt != nullptr); + + if (type_ == evt->GetType() && callback_) { callback_(evt); } diff --git a/src/kiwano/core/event/Event.h b/src/kiwano/core/event/Event.h index eafc0a28..751d8201 100644 --- a/src/kiwano/core/event/Event.h +++ b/src/kiwano/core/event/Event.h @@ -19,12 +19,15 @@ // THE SOFTWARE. #pragma once -#include #include +#include #include +#include namespace kiwano { + KGE_DECLARE_SMART_PTR(Event); + /** * \~chinese * \defgroup Events 事件 @@ -38,6 +41,7 @@ namespace kiwano /// \~chinese /// @brief 事件 class KGE_API Event + : public RefCounter { public: /// \~chinese @@ -66,7 +70,7 @@ namespace kiwano typename _Ty, typename = typename std::enable_if::value, int>::type > - const _Ty& SafeCast() const; + const _Ty* SafeCast() const; /// \~chinese /// @brief 安全转换为其他类型事件 @@ -75,7 +79,7 @@ namespace kiwano typename _Ty, typename = typename std::enable_if::value, int>::type > - _Ty& SafeCast(); + _Ty* SafeCast(); private: const EventType type_; @@ -93,9 +97,9 @@ namespace kiwano template ::value, int>::type> struct IsEventType { - inline bool operator()(const Event& evt) const + inline bool operator()(const Event* evt) const { - return evt.GetType() == KGE_EVENT(_Ty); + return evt->GetType() == KGE_EVENT(_Ty); } }; @@ -109,21 +113,21 @@ namespace kiwano template inline bool Event::IsType() const { - return kiwano::IsEventType<_Ty>()(*this); + return kiwano::IsEventType<_Ty>()(this); } template - inline const _Ty& Event::SafeCast() const + inline const _Ty* Event::SafeCast() const + { + return const_cast(this)->SafeCast<_Ty>(); + } + + template + inline _Ty* Event::SafeCast() { if (!IsType<_Ty>()) throw std::bad_cast(); - return dynamic_cast(*this); - } - - template - inline _Ty& Event::SafeCast() - { - return const_cast<_Ty&>(const_cast(this)->SafeCast<_Ty>()); + return dynamic_cast<_Ty*>(this); } } diff --git a/src/kiwano/core/event/KeyEvent.cpp b/src/kiwano/core/event/KeyEvent.cpp index 4ae1e86e..f66e69c4 100644 --- a/src/kiwano/core/event/KeyEvent.cpp +++ b/src/kiwano/core/event/KeyEvent.cpp @@ -2,20 +2,26 @@ namespace kiwano { + + KeyEvent::KeyEvent(const EventType& type) + : Event(type) + { + } + KeyDownEvent::KeyDownEvent() - : Event(KGE_EVENT(KeyDownEvent)) + : KeyEvent(KGE_EVENT(KeyDownEvent)) , code(0) { } KeyUpEvent::KeyUpEvent() - : Event(KGE_EVENT(KeyUpEvent)) + : KeyEvent(KGE_EVENT(KeyUpEvent)) , code(0) { } KeyCharEvent::KeyCharEvent() - : Event(KGE_EVENT(KeyCharEvent)) + : KeyEvent(KGE_EVENT(KeyCharEvent)) , value() { } diff --git a/src/kiwano/core/event/KeyEvent.h b/src/kiwano/core/event/KeyEvent.h index bcc78322..5ac0604d 100644 --- a/src/kiwano/core/event/KeyEvent.h +++ b/src/kiwano/core/event/KeyEvent.h @@ -24,6 +24,11 @@ namespace kiwano { + KGE_DECLARE_SMART_PTR(KeyEvent); + KGE_DECLARE_SMART_PTR(KeyDownEvent); + KGE_DECLARE_SMART_PTR(KeyUpEvent); + KGE_DECLARE_SMART_PTR(KeyCharEvent); + /** * \addtogroup Events * @{ @@ -34,12 +39,14 @@ namespace kiwano class KGE_API KeyEvent : public Event { + public: + KeyEvent(const EventType& type); }; /// \~chinese /// @brief 键盘按下事件 class KGE_API KeyDownEvent - : public Event + : public KeyEvent { public: KeyCode::Value code; ///< 键值 @@ -50,7 +57,7 @@ namespace kiwano /// \~chinese /// @brief 键盘抬起事件 class KGE_API KeyUpEvent - : public Event + : public KeyEvent { public: KeyCode::Value code; ///< 键值 @@ -61,7 +68,7 @@ namespace kiwano /// \~chinese /// @brief 键盘字符事件 class KGE_API KeyCharEvent - : public Event + : public KeyEvent { public: char value; ///< 字符 @@ -74,11 +81,11 @@ namespace kiwano template <> struct IsEventType { - inline bool operator()(const Event& evt) const + inline bool operator()(const Event* evt) const { - return evt.GetType() == KGE_EVENT(KeyDownEvent) - || evt.GetType() == KGE_EVENT(KeyUpEvent) - || evt.GetType() == KGE_EVENT(KeyCharEvent); + return evt->GetType() == KGE_EVENT(KeyDownEvent) + || evt->GetType() == KGE_EVENT(KeyUpEvent) + || evt->GetType() == KGE_EVENT(KeyCharEvent); } }; diff --git a/src/kiwano/core/event/MouseEvent.cpp b/src/kiwano/core/event/MouseEvent.cpp index 349357d2..b661567e 100644 --- a/src/kiwano/core/event/MouseEvent.cpp +++ b/src/kiwano/core/event/MouseEvent.cpp @@ -5,8 +5,6 @@ namespace kiwano MouseEvent::MouseEvent(EventType const& type) : Event(type) , pos() - , left_btn_down(false) - , right_btn_down(false) { } diff --git a/src/kiwano/core/event/MouseEvent.h b/src/kiwano/core/event/MouseEvent.h index 89edab09..bbfdca02 100644 --- a/src/kiwano/core/event/MouseEvent.h +++ b/src/kiwano/core/event/MouseEvent.h @@ -25,6 +25,15 @@ namespace kiwano { + KGE_DECLARE_SMART_PTR(MouseEvent); + KGE_DECLARE_SMART_PTR(MouseMoveEvent); + KGE_DECLARE_SMART_PTR(MouseDownEvent); + KGE_DECLARE_SMART_PTR(MouseUpEvent); + KGE_DECLARE_SMART_PTR(MouseClickEvent); + KGE_DECLARE_SMART_PTR(MouseHoverEvent); + KGE_DECLARE_SMART_PTR(MouseOutEvent); + KGE_DECLARE_SMART_PTR(MouseWheelEvent); + /** * \addtogroup Events * @{ @@ -37,8 +46,6 @@ namespace kiwano { public: Point pos; ///< 鼠标位置 - bool left_btn_down; ///< 鼠标左键是否按下 - bool right_btn_down; ///< 鼠标右键是否按下 MouseEvent(EventType const& type); }; @@ -119,15 +126,15 @@ namespace kiwano template <> struct IsEventType { - inline bool operator()(const Event& evt) const + inline bool operator()(const Event* evt) const { - return evt.GetType() == KGE_EVENT(MouseMoveEvent) - || evt.GetType() == KGE_EVENT(MouseDownEvent) - || evt.GetType() == KGE_EVENT(MouseUpEvent) - || evt.GetType() == KGE_EVENT(MouseClickEvent) - || evt.GetType() == KGE_EVENT(MouseHoverEvent) - || evt.GetType() == KGE_EVENT(MouseOutEvent) - || evt.GetType() == KGE_EVENT(MouseWheelEvent); + return evt->GetType() == KGE_EVENT(MouseMoveEvent) + || evt->GetType() == KGE_EVENT(MouseDownEvent) + || evt->GetType() == KGE_EVENT(MouseUpEvent) + || evt->GetType() == KGE_EVENT(MouseClickEvent) + || evt->GetType() == KGE_EVENT(MouseHoverEvent) + || evt->GetType() == KGE_EVENT(MouseOutEvent) + || evt->GetType() == KGE_EVENT(MouseWheelEvent); } }; diff --git a/src/kiwano/core/event/WindowEvent.cpp b/src/kiwano/core/event/WindowEvent.cpp index 608b72e4..4d266063 100644 --- a/src/kiwano/core/event/WindowEvent.cpp +++ b/src/kiwano/core/event/WindowEvent.cpp @@ -2,34 +2,40 @@ namespace kiwano { + + WindowEvent::WindowEvent(const EventType& type) + : Event(type) + { + } + WindowMovedEvent::WindowMovedEvent() - : Event(KGE_EVENT(WindowMovedEvent)) + : WindowEvent(KGE_EVENT(WindowMovedEvent)) , x(0) , y(0) { } WindowResizedEvent::WindowResizedEvent() - : Event(KGE_EVENT(WindowResizedEvent)) + : WindowEvent(KGE_EVENT(WindowResizedEvent)) , width(0) , height(0) { } WindowFocusChangedEvent::WindowFocusChangedEvent() - : Event(KGE_EVENT(WindowFocusChangedEvent)) + : WindowEvent(KGE_EVENT(WindowFocusChangedEvent)) , focus(false) { } WindowTitleChangedEvent::WindowTitleChangedEvent() - : Event(KGE_EVENT(WindowTitleChangedEvent)) + : WindowEvent(KGE_EVENT(WindowTitleChangedEvent)) , title() { } WindowClosedEvent::WindowClosedEvent() - : Event(KGE_EVENT(WindowClosedEvent)) + : WindowEvent(KGE_EVENT(WindowClosedEvent)) { } diff --git a/src/kiwano/core/event/WindowEvent.h b/src/kiwano/core/event/WindowEvent.h index 5514853a..b837b46a 100644 --- a/src/kiwano/core/event/WindowEvent.h +++ b/src/kiwano/core/event/WindowEvent.h @@ -23,6 +23,13 @@ namespace kiwano { + KGE_DECLARE_SMART_PTR(WindowEvent); + KGE_DECLARE_SMART_PTR(WindowMovedEvent); + KGE_DECLARE_SMART_PTR(WindowResizedEvent); + KGE_DECLARE_SMART_PTR(WindowFocusChangedEvent); + KGE_DECLARE_SMART_PTR(WindowTitleChangedEvent); + KGE_DECLARE_SMART_PTR(WindowClosedEvent); + /** * \addtogroup Events * @{ @@ -33,12 +40,14 @@ namespace kiwano class KGE_API WindowEvent : public Event { + public: + WindowEvent(const EventType& type); }; /// \~chinese /// @brief 窗口移动事件 class KGE_API WindowMovedEvent - : public Event + : public WindowEvent { public: int x; ///< 窗口左上角 x 坐标 @@ -50,11 +59,11 @@ namespace kiwano /// \~chinese /// @brief 窗口大小变化事件 class KGE_API WindowResizedEvent - : public Event + : public WindowEvent { public: - int width; ///< 窗口宽度 - int height; ///< 窗口高度 + uint32_t width; ///< 窗口宽度 + uint32_t height; ///< 窗口高度 WindowResizedEvent(); }; @@ -62,7 +71,7 @@ namespace kiwano /// \~chinese /// @brief 窗口焦点变化事件 class KGE_API WindowFocusChangedEvent - : public Event + : public WindowEvent { public: bool focus; ///< 是否获取到焦点 @@ -73,7 +82,7 @@ namespace kiwano /// \~chinese /// @brief 窗口标题更改事件 class KGE_API WindowTitleChangedEvent - : public Event + : public WindowEvent { public: String title; ///< 标题 @@ -84,7 +93,7 @@ namespace kiwano /// \~chinese /// @brief 窗口关闭事件 class KGE_API WindowClosedEvent - : public Event + : public WindowEvent { public: WindowClosedEvent(); @@ -95,13 +104,13 @@ namespace kiwano template <> struct IsEventType { - inline bool operator()(const Event& evt) const + inline bool operator()(const Event* evt) const { - return evt.GetType() == KGE_EVENT(WindowMovedEvent) - || evt.GetType() == KGE_EVENT(WindowResizedEvent) - || evt.GetType() == KGE_EVENT(WindowFocusChangedEvent) - || evt.GetType() == KGE_EVENT(WindowTitleChangedEvent) - || evt.GetType() == KGE_EVENT(WindowClosedEvent); + return evt->GetType() == KGE_EVENT(WindowMovedEvent) + || evt->GetType() == KGE_EVENT(WindowResizedEvent) + || evt->GetType() == KGE_EVENT(WindowFocusChangedEvent) + || evt->GetType() == KGE_EVENT(WindowTitleChangedEvent) + || evt->GetType() == KGE_EVENT(WindowClosedEvent); } }; diff --git a/src/kiwano/core/keys.h b/src/kiwano/core/keys.h index f259a0da..06a91537 100644 --- a/src/kiwano/core/keys.h +++ b/src/kiwano/core/keys.h @@ -60,6 +60,7 @@ namespace kiwano Tab = VK_TAB, ///< TAB键 Delete = VK_DELETE, ///< 删除键 Back = VK_BACK, ///< 退格键 + Super = VK_LWIN, ///< Cmd/Super/Windows键 A = 0x41, ///< A键 B, ///< B键 diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 1f375096..6992eeb4 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -59,6 +59,7 @@ #include #include #include +#include // @@ -112,7 +113,6 @@ #include #include #include -#include #include diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 3793fe06..28b6a485 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -19,19 +19,13 @@ // THE SOFTWARE. #include - -#include #include #include -#include +#include +#include #include #include -#include // GET_X_LPARAM, GET_Y_LPARAM -#include // ImmAssociateContext - -#pragma comment(lib, "imm32.lib") - namespace kiwano { namespace @@ -62,12 +56,8 @@ namespace kiwano namespace kiwano { Application::Application() - : end_(true) - , inited_(false) - , time_scale_(1.f) + : time_scale_(1.f) { - ::CoInitialize(nullptr); - Use(&Renderer::instance()); Use(&Input::instance()); Use(&Director::instance()); @@ -76,13 +66,11 @@ namespace kiwano Application::~Application() { Destroy(); - - ::CoUninitialize(); } - void Application::Init(const Config& config) + void Application::Run(const Config& config) { - Window::instance().Init(config.window, Application::WndProc); + Window::instance().Init(config.window); Renderer::instance().Init(config.render); // Setup all components @@ -100,33 +88,24 @@ namespace kiwano // Everything is ready OnReady(); - HWND hwnd = Window::instance().GetHandle(); + last_update_time_ = Time::Now(); - // disable imm - ::ImmAssociateContext(hwnd, nullptr); - - // use Application instance in message loop - ::SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(this)); - - inited_ = true; - } - - void Application::Run() - { - KGE_ASSERT(inited_ && "Calling Application::Run before Application::Init"); - - end_ = false; - - Window::instance().Prepare(); - while (!end_) + Window& window = Window::instance(); + while (!window.ShouldClose()) { - Window::instance().PollEvents(); + while (EventPtr evt = window.PollEvent()) + { + DispatchEvent(evt.get()); + } + + Update(); + Render(); } } void Application::Quit() { - end_ = true; + Window::instance().Destroy(); } void Application::Destroy() @@ -136,18 +115,11 @@ namespace kiwano ResourceCache::instance().Clear(); TextureCache::instance().Clear(); - if (inited_) + for (auto iter = comps_.rbegin(); iter != comps_.rend(); ++iter) { - inited_ = false; - - for (auto iter = comps_.rbegin(); iter != comps_.rend(); ++iter) - { - (*iter)->DestroyComponent(); - } - comps_.clear(); + (*iter)->DestroyComponent(); } - - Window::instance().Destroy(); + comps_.clear(); } void Application::Use(ComponentBase* component) @@ -210,11 +182,10 @@ namespace kiwano // Updating { - static auto last = Time::Now(); + const Time now = Time::Now(); + const Duration dt = (now - last_update_time_) * time_scale_; - const auto now = Time::Now(); - const auto dt = (now - last) * time_scale_; - last = now; + last_update_time_ = now; for (auto c : update_comps_) { @@ -251,7 +222,7 @@ namespace kiwano } } - void Application::DispatchEvent(Event& evt) + void Application::DispatchEvent(Event* evt) { for (auto c : event_comps_) { @@ -264,215 +235,4 @@ namespace kiwano std::lock_guard lock(perform_mutex_); functions_to_perform_.push(func); } - - LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) - { - Application* app = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))); - if (app == nullptr) - { - return ::DefWindowProcW(hwnd, msg, wparam, lparam); - } - - // Handle Message - for (auto c : app->event_comps_) - { - c->HandleMessage(hwnd, msg, wparam, lparam); - } - - switch (msg) - { - case WM_PAINT: - { - app->Update(); - app->Render(); - - ::InvalidateRect(hwnd, NULL, FALSE); - return 0; - } - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - { - bool down = msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN; - if (down) - { - KeyDownEvent evt; - evt.code = static_cast(wparam); - app->DispatchEvent(evt); - } - else - { - KeyUpEvent evt; - evt.code = static_cast(wparam); - app->DispatchEvent(evt); - } - } - break; - - case WM_CHAR: - { - KeyCharEvent evt; - evt.value = static_cast(wparam); - app->DispatchEvent(evt); - } - break; - - case WM_LBUTTONUP: - case WM_LBUTTONDOWN: - //case WM_LBUTTONDBLCLK: - case WM_MBUTTONUP: - case WM_MBUTTONDOWN: - //case WM_MBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - //case WM_RBUTTONDBLCLK: - case WM_MOUSEMOVE: - case WM_MOUSEWHEEL: - { - auto UpdateMouseData = [&](MouseEvent& evt) - { - evt.pos = Point(static_cast(GET_X_LPARAM(lparam)), static_cast(GET_Y_LPARAM(lparam))); - evt.left_btn_down = !!(wparam & MK_LBUTTON); - evt.left_btn_down = !!(wparam & MK_RBUTTON); - }; - - if (msg == WM_MOUSEMOVE) - { - MouseMoveEvent evt; - UpdateMouseData(evt); - app->DispatchEvent(evt); - } - else if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) - { - MouseDownEvent evt; - UpdateMouseData(evt); - if (msg == WM_LBUTTONDOWN) { evt.button = MouseButton::Left; } - else if (msg == WM_RBUTTONDOWN) { evt.button = MouseButton::Right; } - else if (msg == WM_MBUTTONDOWN) { evt.button = MouseButton::Middle; } - app->DispatchEvent(evt); - } - else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) - { - MouseUpEvent evt; - UpdateMouseData(evt); - if (msg == WM_LBUTTONUP) { evt.button = MouseButton::Left; } - else if (msg == WM_RBUTTONUP) { evt.button = MouseButton::Right; } - else if (msg == WM_MBUTTONUP) { evt.button = MouseButton::Middle; } - app->DispatchEvent(evt); - } - else if (msg == WM_MOUSEWHEEL) - { - MouseWheelEvent evt; - UpdateMouseData(evt); - evt.wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; - app->DispatchEvent(evt); - } - } - break; - - case WM_SIZE: - { - if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) - { - KGE_SYS_LOG(L"Window minimized"); - } - else - { - // KGE_SYS_LOG(L"Window resized"); - - Window::instance().UpdateWindowRect(); - - WindowResizedEvent evt; - evt.width = LOWORD(lparam); - evt.height = HIWORD(lparam); - app->DispatchEvent(evt); - } - } - break; - - case WM_MOVE: - { - int x = (int)(short)LOWORD(lparam); - int y = (int)(short)HIWORD(lparam); - - WindowMovedEvent evt; - evt.x = x; - evt.y = y; - app->DispatchEvent(evt); - } - break; - - case WM_ACTIVATE: - { - bool active = (LOWORD(wparam) != WA_INACTIVE); - - Window::instance().SetActive(active); - - WindowFocusChangedEvent evt; - evt.focus = active; - app->DispatchEvent(evt); - } - break; - - case WM_SETTEXT: - { - KGE_SYS_LOG(L"Window title changed"); - - WindowTitleChangedEvent evt; - evt.title = reinterpret_cast(lparam); - app->DispatchEvent(evt); - } - break; - - case WM_SETICON: - { - KGE_SYS_LOG(L"Window icon changed"); - } - break; - - case WM_DISPLAYCHANGE: - { - KGE_SYS_LOG(L"The display resolution has changed"); - - ::InvalidateRect(hwnd, nullptr, FALSE); - } - break; - - case WM_SETCURSOR: - { - Window::instance().UpdateCursor(); - } - break; - - case WM_CLOSE: - { - KGE_SYS_LOG(L"Window is closing"); - - if (!app->OnClosing()) - { - WindowClosedEvent evt; - app->DispatchEvent(evt); - return 0; - } - } - break; - - case WM_DESTROY: - { - KGE_SYS_LOG(L"Window was destroyed"); - - app->Quit(); - app->OnDestroy(); - - ::PostQuitMessage(0); - return 0; - } - break; - } - - return ::DefWindowProcW(hwnd, msg, wparam, lparam); - } } diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index e48e384c..065c3fbd 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -80,15 +80,6 @@ namespace kiwano virtual ~Application(); - /** - * \~chinese - * @brief 初始化应用程序 - * @details 初始化所有功能组件后执行 OnReady 函数 - * @param config 初始化配置 - * @attention 应在使用其他功能前执行初始化,否则可能引发异常 - */ - void Init(Config const& config = Config()); - /** * \~chinese * @brief 初始化完成处理 @@ -96,14 +87,6 @@ namespace kiwano */ virtual void OnReady() {} - /** - * \~chinese - * @brief 窗口关闭处理 - * @details 重载该函数以处理用户关闭应用程序窗口时的行为 - * @return 返回 true 则正常关闭窗口,否则阻止窗口关闭 - */ - virtual bool OnClosing() { return true; } - /** * \~chinese * @brief 应用程序销毁处理 @@ -114,9 +97,11 @@ namespace kiwano /** * \~chinese * @brief 启动应用程序 + * @details 初始化所有功能组件后执行 OnReady 函数 + * @param config 初始化配置 * @note 该函数是阻塞的,应用程序结束时函数返回 */ - void Run(); + void Run(Config const& config = Config()); /** * \~chinese @@ -152,7 +137,7 @@ namespace kiwano * @details 将事件分发给所有事件功能组件 * @param evt 事件 */ - void DispatchEvent(Event& evt); + void DispatchEvent(Event* evt); /** * \~chinese @@ -167,13 +152,9 @@ namespace kiwano void Update(); - static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM); - private: - bool end_; - bool inited_; - float time_scale_; - + float time_scale_; + Time last_update_time_; Vector comps_; Vector render_comps_; Vector update_comps_; diff --git a/src/kiwano/platform/Input.cpp b/src/kiwano/platform/Input.cpp index 9803760c..1fb900d7 100644 --- a/src/kiwano/platform/Input.cpp +++ b/src/kiwano/platform/Input.cpp @@ -20,24 +20,73 @@ #include #include -#include // GET_X_LPARAM, GET_Y_LPARAM +#include +#include namespace kiwano { Input::Input() : want_update_(false) - , mouse_pos_x_(0.f) - , mouse_pos_y_(0.f) + , keys_{} + , keys_pressed_{} + , keys_released_{} { - ZeroMemory(keys_, sizeof(keys_)); - ZeroMemory(keys_pressed_, sizeof(keys_pressed_)); - ZeroMemory(keys_released_, sizeof(keys_released_)); } Input::~Input() { } + void Input::AfterUpdate() + { + if (want_update_) + { + want_update_ = false; + + keys_pressed_.fill(false); + keys_released_.fill(false); + } + } + + bool Input::IsDown(int key_or_btn) const + { + KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); + if (key_or_btn >= 0 && key_or_btn < KEY_NUM) + return keys_[key_or_btn]; + return false; + } + + bool Input::WasPressed(int key_or_btn) const + { + KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); + if (key_or_btn >= 0 && key_or_btn < KEY_NUM) + return keys_pressed_[key_or_btn]; + return false; + } + + bool Input::WasReleased(int key_or_btn) const + { + KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); + if (key_or_btn >= 0 && key_or_btn < KEY_NUM) + return keys_released_[key_or_btn]; + return false; + } + + float Input::GetMouseX() const + { + return mouse_pos_.x; + } + + float Input::GetMouseY() const + { + return mouse_pos_.y; + } + + Point Input::GetMousePos() const + { + return mouse_pos_; + } + void Input::UpdateKey(int key, bool down) { if (down && !keys_[key]) @@ -50,94 +99,38 @@ namespace kiwano want_update_ = true; } - void Input::UpdateMousePos(float x, float y) + void Input::UpdateMousePos(const Point& pos) { - mouse_pos_x_ = x; - mouse_pos_y_ = y; + mouse_pos_ = pos; } - void Input::AfterUpdate() + void Input::HandleEvent(Event* evt) { - if (want_update_) + if (evt->IsType()) { - want_update_ = false; - - ZeroMemory(keys_pressed_, sizeof(keys_pressed_)); - ZeroMemory(keys_released_, sizeof(keys_released_)); + if (evt->IsType()) + { + UpdateMousePos(dynamic_cast(evt)->pos); + } + else if (evt->IsType()) + { + UpdateKey(dynamic_cast(evt)->button, true); + } + else if (evt->IsType()) + { + UpdateKey(dynamic_cast(evt)->button, false); + } } - } - - void Input::HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) - { - switch (msg) + else if (evt->IsType()) { - case WM_LBUTTONUP: - case WM_LBUTTONDOWN: - //case WM_LBUTTONDBLCLK: - case WM_MBUTTONUP: - case WM_MBUTTONDOWN: - //case WM_MBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - //case WM_RBUTTONDBLCLK: - case WM_MOUSEMOVE: - case WM_MOUSEWHEEL: - { - if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) { UpdateKey(VK_LBUTTON, (msg == WM_LBUTTONDOWN) ? true : false); } - else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) { UpdateKey(VK_RBUTTON, (msg == WM_RBUTTONDOWN) ? true : false); } - else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) { UpdateKey(VK_MBUTTON, (msg == WM_MBUTTONDOWN) ? true : false); } - else if (msg == WM_MOUSEMOVE) { UpdateMousePos(static_cast(GET_X_LPARAM(lparam)), static_cast(GET_Y_LPARAM(lparam))); } - - break; + if (evt->IsType()) + { + UpdateKey(dynamic_cast(evt)->code, true); + } + else if (evt->IsType()) + { + UpdateKey(dynamic_cast(evt)->code, false); + } } - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - { - bool down = msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN; - UpdateKey((int)wparam, down); - } - } - } - - bool Input::IsDown(int key_or_btn) - { - KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); - if (key_or_btn >= 0 && key_or_btn < KEY_NUM) - return keys_[key_or_btn]; - return false; - } - - bool Input::WasPressed(int key_or_btn) - { - KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); - if (key_or_btn >= 0 && key_or_btn < KEY_NUM) - return keys_pressed_[key_or_btn]; - return false; - } - - bool Input::WasReleased(int key_or_btn) - { - KGE_ASSERT(key_or_btn >= 0 && key_or_btn < KEY_NUM); - if (key_or_btn >= 0 && key_or_btn < KEY_NUM) - return keys_released_[key_or_btn]; - return false; - } - - float Input::GetMouseX() - { - return mouse_pos_x_; - } - - float Input::GetMouseY() - { - return mouse_pos_y_; - } - - Point Input::GetMousePos() - { - return Point{ mouse_pos_x_, mouse_pos_y_ }; } } diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 0daebfab..9e59e8d5 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -20,9 +20,9 @@ #pragma once #include -#include #include -#include +#include +#include #include namespace kiwano @@ -46,7 +46,7 @@ namespace kiwano * @return 是否正被按下 * @see kiwano::KeyCode kiwano::MouseButton */ - bool IsDown(int key_or_btn); + bool IsDown(int key_or_btn) const; /** * \~chinese @@ -55,7 +55,7 @@ namespace kiwano * @return 是否刚被点击 * @see kiwano::KeyCode kiwano::MouseButton */ - bool WasPressed(int key_or_btn); + bool WasPressed(int key_or_btn) const; /** * \~chinese @@ -64,28 +64,28 @@ namespace kiwano * @return 是否刚抬起 * @see kiwano::KeyCode kiwano::MouseButton */ - bool WasReleased(int key_or_btn); + bool WasReleased(int key_or_btn) const; /** * \~chinese * @brief 获得鼠标 x 坐标 * @return 鼠标 x 坐标 */ - float GetMouseX(); + float GetMouseX() const; /** * \~chinese * @brief 获得鼠标 y 坐标 * @return 鼠标 y 坐标 */ - float GetMouseY(); + float GetMouseY() const; /** * \~chinese * @brief 获得鼠标坐标 * @return 鼠标坐标 */ - Point GetMousePos(); + Point GetMousePos() const; public: void SetupComponent() override {} @@ -94,25 +94,24 @@ namespace kiwano void AfterUpdate() override; - void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; - - void UpdateKey(int, bool); - - void UpdateMousePos(float, float); + void HandleEvent(Event* evt) override; private: Input(); ~Input(); + void UpdateKey(int, bool); + + void UpdateMousePos(const Point& pos); + private: static const int KEY_NUM = 256; bool want_update_; - bool keys_[KEY_NUM]; - bool keys_pressed_[KEY_NUM]; - bool keys_released_[KEY_NUM]; - float mouse_pos_x_; - float mouse_pos_y_; + Point mouse_pos_; + std::array keys_; + std::array keys_pressed_; + std::array keys_released_; }; } diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index 009ccced..a5271f99 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -19,8 +19,14 @@ // THE SOFTWARE. #include -#include #include +#include +#include +#include +#include + +#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 @@ -65,19 +71,19 @@ namespace kiwano { } - void Window::Init(WindowConfig const& config, WNDPROC proc) + void Window::Init(WindowConfig const& config) { HINSTANCE hinst = GetModuleHandleW(nullptr); WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpszClassName = KGE_WND_CLASS_NAME; wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */; - wcex.lpfnWndProc = proc; + wcex.lpfnWndProc = Window::WndProc; wcex.hIcon = nullptr; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = hinst; - wcex.hbrBackground = nullptr; + wcex.hbrBackground = (HBRUSH)(::GetStockObject(BLACK_BRUSH)); wcex.lpszMenuName = nullptr; wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW); @@ -155,18 +161,18 @@ namespace kiwano { ::UnregisterClass(KGE_WND_CLASS_NAME, hinst); win32::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); + return; } - else - { - RECT rc; - GetClientRect(handle_, &rc); - width_ = rc.right - rc.left; - height_ = rc.bottom - rc.top; - } - } - void Window::Prepare() - { + width_ = width; + height_ = height; + + // disable imm + ::ImmAssociateContext(handle_, nullptr); + + // use Application instance in message loop + ::SetWindowLongPtr(handle_, GWLP_USERDATA, LONG_PTR(this)); + ::ShowWindow(handle_, SW_SHOWNORMAL); ::UpdateWindow(handle_); @@ -176,15 +182,22 @@ namespace kiwano } } - void Window::PollEvents() + EventPtr Window::PollEvent() { - static MSG msg = {}; - - if (::GetMessageW(&msg, nullptr, 0, 0)) + MSG msg; + while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessageW(&msg); } + + EventPtr evt; + if (!event_queue_.empty()) + { + evt = event_queue_.front(); + event_queue_.pop(); + } + return evt; } String Window::GetTitle() const @@ -293,7 +306,12 @@ namespace kiwano ::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle()); ::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, win_width, win_height, SWP_DRAWFRAME | SWP_FRAMECHANGED); - UpdateWindowRect(); + // Update window rect + RECT rc; + ::GetClientRect(handle_, &rc); + + width_ = static_cast(rc.right - rc.left); + height_ = static_cast(rc.bottom - rc.top); } ::ShowWindow(handle_, SW_SHOWNORMAL); @@ -305,28 +323,46 @@ namespace kiwano mouse_cursor_ = cursor; } - HWND Window::GetHandle() const + WindowHandle Window::GetHandle() const { return handle_; } + bool Window::ShouldClose() + { + return handle_ == nullptr; + } + + void Window::PushEvent(EventPtr evt) + { + event_queue_.push(evt); + } + + void Window::Destroy() + { + if (is_fullscreen_) + RestoreResolution(device_name_); + + if (device_name_) + { + delete[] device_name_; + device_name_ = nullptr; + } + + if (handle_) + { + ::DestroyWindow(handle_); + handle_ = nullptr; + } + } + +#if defined(KGE_WIN32) + DWORD Window::GetWindowStyle() const { return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE)); } - void Window::UpdateWindowRect() - { - if (!handle_) - return; - - RECT rc; - ::GetClientRect(handle_, &rc); - - width_ = rc.right - rc.left; - height_ = rc.bottom - rc.top; - } - void Window::UpdateCursor() { LPTSTR win32_cursor = IDC_ARROW; @@ -368,22 +404,185 @@ namespace kiwano } } - void Window::Destroy() + LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) { - if (is_fullscreen_) - RestoreResolution(device_name_); - - if (device_name_) + Window* window = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))); + if (window == nullptr) { - delete[] device_name_; - device_name_ = nullptr; + return ::DefWindowProcW(hwnd, msg, wparam, lparam); } - if (handle_) + switch (msg) { - ::DestroyWindow(handle_); - handle_ = nullptr; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + KeyDownEventPtr evt = new KeyDownEvent; + evt->code = static_cast(wparam); + window->PushEvent(evt); } + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + { + KeyUpEventPtr evt = new KeyUpEvent; + evt->code = static_cast(wparam); + window->PushEvent(evt); + } + break; + + case WM_CHAR: + { + KeyCharEventPtr evt = new KeyCharEvent; + evt->value = static_cast(wparam); + window->PushEvent(evt); + } + break; + + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: + { + MouseDownEventPtr evt = new MouseDownEvent; + evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam))); + + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { evt->button = MouseButton::Left; } + else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { evt->button = MouseButton::Right; } + else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { evt->button = MouseButton::Middle; } + + window->PushEvent(evt); + } + break; + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + MouseUpEventPtr evt = new MouseUpEvent; + evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam))); + + if (msg == WM_LBUTTONUP) { evt->button = MouseButton::Left; } + else if (msg == WM_RBUTTONUP) { evt->button = MouseButton::Right; } + else if (msg == WM_MBUTTONUP) { evt->button = MouseButton::Middle; } + + window->PushEvent(evt); + } + break; + + case WM_MOUSEMOVE: + { + MouseMoveEventPtr evt = new MouseMoveEvent; + evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam))); + window->PushEvent(evt); + } + break; + + case WM_MOUSEWHEEL: + { + MouseWheelEventPtr evt = new MouseWheelEvent; + evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam))); + evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; + window->PushEvent(evt); + } + break; + + case WM_SIZE: + { + if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) + { + KGE_SYS_LOG(L"Window minimized"); + } + else + { + // KGE_SYS_LOG(L"Window resized"); + + window->width_ = ((uint32_t)(short)LOWORD(lparam)); + window->height_ = ((uint32_t)(short)HIWORD(lparam)); + + WindowResizedEventPtr evt = new WindowResizedEvent; + evt->width = window->width_; + evt->height = window->height_; + window->PushEvent(evt); + } + } + break; + + case WM_MOVE: + { + int x = ((int)(short)LOWORD(lparam)); + int y = ((int)(short)HIWORD(lparam)); + + WindowMovedEventPtr evt = new WindowMovedEvent; + evt->x = x; + evt->y = y; + window->PushEvent(evt); + } + break; + + case WM_ACTIVATE: + { + bool active = (LOWORD(wparam) != WA_INACTIVE); + + window->SetActive(active); + + WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent; + evt->focus = active; + window->PushEvent(evt); + } + break; + + case WM_SETTEXT: + { + KGE_SYS_LOG(L"Window title changed"); + + WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent; + evt->title.assign(reinterpret_cast(lparam)); + window->PushEvent(evt); + } + break; + + case WM_SETICON: + { + KGE_SYS_LOG(L"Window icon changed"); + } + break; + + case WM_DISPLAYCHANGE: + { + KGE_SYS_LOG(L"The display resolution has changed"); + + ::InvalidateRect(hwnd, nullptr, FALSE); + } + break; + + case WM_SETCURSOR: + { + window->UpdateCursor(); + } + break; + + case WM_CLOSE: + { + KGE_SYS_LOG(L"Window is closing"); + + WindowClosedEventPtr evt = new WindowClosedEvent; + window->PushEvent(evt); + window->Destroy(); + } + break; + + case WM_DESTROY: + { + KGE_SYS_LOG(L"Window was destroyed"); + + ::PostQuitMessage(0); + return 0; + } + break; + } + + return ::DefWindowProcW(hwnd, msg, wparam, lparam); } namespace @@ -441,4 +640,6 @@ namespace kiwano } } +#endif + } diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index 75455bbe..020054b6 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -20,8 +20,9 @@ #pragma once #include -#include #include +#include +#include namespace kiwano { @@ -74,6 +75,10 @@ namespace kiwano ); }; +#if defined(KGE_WIN32) + typedef HWND WindowHandle; +#endif + /** * \~chinese @@ -85,6 +90,13 @@ namespace kiwano friend Singleton; public: + /** + * \~chinese + * @brief 初始化窗口 + * @param config 窗口设置 + */ + void Init(WindowConfig const& config); + /** * \~chinese * @brief 获取窗口标题 @@ -151,39 +163,56 @@ namespace kiwano */ void SetCursor(CursorType cursor); -#ifdef KGE_WIN32 - public: - void Init(WindowConfig const& config, WNDPROC proc); + /** + * \~chinese + * @brief 轮询窗口事件 + * @return 返回事件队列中的第一个事件并将其从队列中移除,若事件队列为空则返回空指针 + */ + EventPtr PollEvent(); - void Prepare(); + /** + * \~chinese + * @brief 获取窗口句柄 + */ + WindowHandle GetHandle() const; - void PollEvents(); - - HWND GetHandle() const; - - DWORD GetWindowStyle() const; - - void UpdateWindowRect(); - - void UpdateCursor(); - - void SetActive(bool actived); + /** + * \~chinese + * @brief 是否需要关闭 + */ + bool ShouldClose(); + /** + * \~chinese + * @brief 销毁窗口 + */ void Destroy(); -#endif private: Window(); ~Window(); + void PushEvent(EventPtr evt); + +#if defined(KGE_WIN32) + DWORD GetWindowStyle() const; + + void UpdateCursor(); + + void SetActive(bool actived); + + static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM); +#endif + private: - bool resizable_; - bool is_fullscreen_; - HWND handle_; - int width_; - int height_; - wchar_t* device_name_; - CursorType mouse_cursor_; + bool resizable_; + bool is_fullscreen_; + WindowHandle handle_; + uint32_t width_; + uint32_t height_; + wchar_t* device_name_; + CursorType mouse_cursor_; + std::queue event_queue_; }; } diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index d1782b71..ab11ddfb 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -20,8 +20,8 @@ #include #include +#include #include -#include #include namespace kiwano @@ -33,7 +33,7 @@ namespace kiwano } Renderer::Renderer() - : hwnd_(nullptr) + : target_window_(nullptr) , vsync_(true) , clear_color_(Color::Black) { @@ -53,19 +53,21 @@ namespace kiwano { KGE_SYS_LOG(L"Creating device resources"); - hwnd_ = Window::instance().GetHandle(); + win32::ThrowIfFailed(::CoInitialize(nullptr)); + + target_window_ = Window::instance().GetHandle(); output_size_ = Window::instance().GetSize(); d2d_res_ = nullptr; d3d_res_ = nullptr; drawing_state_block_ = nullptr; - HRESULT hr = hwnd_ ? S_OK : E_FAIL; + HRESULT hr = target_window_ ? S_OK : E_FAIL; // Direct3D device resources if (SUCCEEDED(hr)) { - hr = ID3DDeviceResources::Create(&d3d_res_, hwnd_); + hr = ID3DDeviceResources::Create(&d3d_res_, target_window_); // Direct2D device resources if (SUCCEEDED(hr)) @@ -136,6 +138,8 @@ namespace kiwano drawing_state_block_.reset(); d2d_res_.reset(); d3d_res_.reset(); + + ::CoUninitialize(); } void Renderer::BeforeRender() @@ -171,18 +175,12 @@ namespace kiwano win32::ThrowIfFailed(hr); } - void Renderer::HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) + void Renderer::HandleEvent(Event* evt) { - switch (msg) + if (evt->IsType()) { - case WM_SIZE: - { - uint32_t width = LOWORD(lparam); - uint32_t height = HIWORD(lparam); - - ResizeTarget(width, height); - break; - } + auto window_evt = dynamic_cast(evt); + ResizeTarget(window_evt->width, window_evt->height); } } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index ec9c76ab..00343d8e 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -25,6 +25,7 @@ #include #include #include +#include #if defined(KGE_USE_DIRECTX10) # include "win32/D3D10DeviceResources.h" @@ -278,7 +279,7 @@ namespace kiwano public: /// \~chinese /// @brief 获取目标窗口 - HWND GetTargetWindow() const; + WindowHandle GetTargetWindow() const; /// \~chinese /// @brief 获取渲染输出大小 @@ -303,7 +304,7 @@ namespace kiwano void AfterRender() override; - void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; + void HandleEvent(Event* evt) override; private: Renderer(); @@ -315,10 +316,10 @@ namespace kiwano void ResizeTarget(uint32_t width, uint32_t height); private: - bool vsync_; - HWND hwnd_; - Color clear_color_; - Size output_size_; + bool vsync_; + WindowHandle target_window_; + Color clear_color_; + Size output_size_; ComPtr d2d_res_; ComPtr d3d_res_; @@ -330,7 +331,7 @@ namespace kiwano /** @} */ - inline HWND Renderer::GetTargetWindow() const { return hwnd_; } + inline WindowHandle Renderer::GetTargetWindow() const { return target_window_; } inline Size const& Renderer::GetOutputSize() const { return output_size_; }