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_; }