diff --git a/kiwano-imgui/kiwano-imgui.h b/kiwano-imgui/kiwano-imgui.h
index 1c947d2a..75111546 100644
--- a/kiwano-imgui/kiwano-imgui.h
+++ b/kiwano-imgui/kiwano-imgui.h
@@ -22,7 +22,7 @@
#include "kiwano/kiwano.h"
#include "src/ImGuiLayer.h"
-#include "src/ImGuiView.h"
+#include "src/ImGuiModule.h"
// ImGui
#include "third-party/ImGui/imgui.h"
diff --git a/kiwano-imgui/kiwano-imgui.vcxproj b/kiwano-imgui/kiwano-imgui.vcxproj
index 3ce24ae7..38d06357 100644
--- a/kiwano-imgui/kiwano-imgui.vcxproj
+++ b/kiwano-imgui/kiwano-imgui.vcxproj
@@ -3,8 +3,8 @@
-
-
+
+
@@ -16,7 +16,7 @@
-
+
diff --git a/kiwano-imgui/kiwano-imgui.vcxproj.filters b/kiwano-imgui/kiwano-imgui.vcxproj.filters
index 3ed53b00..4a6acaaf 100644
--- a/kiwano-imgui/kiwano-imgui.vcxproj.filters
+++ b/kiwano-imgui/kiwano-imgui.vcxproj.filters
@@ -12,9 +12,6 @@
-
- src
-
src
@@ -24,9 +21,6 @@
src
-
- src
-
third-party\ImGui
@@ -46,6 +40,12 @@
third-party\ImGui
+
+ src
+
+
+ src
+
@@ -57,9 +57,6 @@
src
-
- src
-
third-party\ImGui
@@ -72,5 +69,8 @@
third-party\ImGui
+
+ src
+
\ No newline at end of file
diff --git a/kiwano-imgui/src/ImGuiLayer.cpp b/kiwano-imgui/src/ImGuiLayer.cpp
index 7d67af02..8c5744fc 100644
--- a/kiwano-imgui/src/ImGuiLayer.cpp
+++ b/kiwano-imgui/src/ImGuiLayer.cpp
@@ -24,146 +24,21 @@ namespace kiwano
{
namespace imgui
{
-
- namespace
- {
- Map mouse_buttons =
- {
- { MouseButton::Left, 0 },
- { MouseButton::Right, 1 },
- { MouseButton::Middle, 2 }
- };
- }
-
ImGuiLayer::ImGuiLayer()
{
- target_window_ = Renderer::Instance().GetTargetWindow();
SetSwallowEvents(true);
}
ImGuiLayer::~ImGuiLayer()
{
- ImGuiView::Instance().RemoveLayer(this);
- }
-
- void ImGuiLayer::OnMouseButtonDown(int btn, Point const& p)
- {
- if (!ImGui::IsAnyMouseDown() && ::GetCapture() == nullptr)
- ::SetCapture(target_window_);
-
- KGE_ASSERT(mouse_buttons.find(btn) != mouse_buttons.end());
- ImGui::GetIO().MouseDown[mouse_buttons[btn]] = true;
- }
-
- void ImGuiLayer::OnMouseButtonUp(int btn, Point const& p)
- {
- KGE_ASSERT(mouse_buttons.find(btn) != mouse_buttons.end());
- ImGui::GetIO().MouseDown[mouse_buttons[btn]] = false;
-
- if (!ImGui::IsAnyMouseDown() && ::GetCapture() == target_window_)
- ::ReleaseCapture();
- }
-
- void ImGuiLayer::OnMouseWheel(float wheel)
- {
- ImGui::GetIO().MouseWheel += wheel;
- }
-
- void ImGuiLayer::OnKeyDown(int key)
- {
- KGE_ASSERT(key < 256);
- ImGui::GetIO().KeysDown[key] = 1;
- }
-
- void ImGuiLayer::OnKeyUp(int key)
- {
- KGE_ASSERT(key < 256);
- ImGui::GetIO().KeysDown[key] = 0;
- }
-
- void ImGuiLayer::OnChar(char c)
- {
- ImGui::GetIO().AddInputCharacter(c);
- }
-
- void ImGuiLayer::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();
}
void ImGuiLayer::OnRender()
{
- ImGuiView::Instance().NewFrame();
-
for (const auto& pipeline : pipelines_)
{
pipeline.second();
}
-
- ImGuiView::Instance().Render();
- }
-
- void ImGuiLayer::UpdateMousePos()
- {
- ImGuiIO& io = ImGui::GetIO();
-
- // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
- if (io.WantSetMousePos)
- {
- POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
- HWND hwnd = target_window_;
- ::ClientToScreen(hwnd, &pos);
- ::SetCursorPos(pos.x, pos.y);
- }
-
- Point pos = Input::Instance().GetMousePos();
- io.MousePos = ImVec2(pos.x, pos.y);
- }
-
- void ImGuiLayer::UpdateMouseCursor()
- {
- static ImGuiMouseCursor last_mouse_cursor = ImGuiMouseCursor_COUNT;
-
- ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
-
- if (last_mouse_cursor != imgui_cursor)
- {
- last_mouse_cursor = imgui_cursor;
-
- if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
- return;
-
- MouseCursor cursor = MouseCursor::Arrow;
- switch (imgui_cursor)
- {
- case ImGuiMouseCursor_Arrow: cursor = MouseCursor::Arrow; break;
- case ImGuiMouseCursor_TextInput: cursor = MouseCursor::TextInput; break;
- case ImGuiMouseCursor_ResizeAll: cursor = MouseCursor::SizeAll; break;
- case ImGuiMouseCursor_ResizeEW: cursor = MouseCursor::SizeWE; break;
- case ImGuiMouseCursor_ResizeNS: cursor = MouseCursor::SizeNS; break;
- case ImGuiMouseCursor_ResizeNESW: cursor = MouseCursor::SizeNESW; break;
- case ImGuiMouseCursor_ResizeNWSE: cursor = MouseCursor::SizeNWSE; break;
- case ImGuiMouseCursor_Hand: cursor = MouseCursor::Hand; break;
- }
-
- GetScene()->SetMouseCursor(cursor);
- }
}
void ImGuiLayer::AddItem(ImGuiPipeline const& item, String const& name)
diff --git a/kiwano-imgui/src/ImGuiLayer.h b/kiwano-imgui/src/ImGuiLayer.h
index 7188f82a..761f666b 100644
--- a/kiwano-imgui/src/ImGuiLayer.h
+++ b/kiwano-imgui/src/ImGuiLayer.h
@@ -28,14 +28,12 @@ namespace kiwano
using ImGuiPipeline = Closure;
- class ImGuiView;
-
class ImGuiLayer
: public Layer
{
- friend class ImGuiView;
-
public:
+ ImGuiLayer();
+
virtual ~ImGuiLayer();
// 添加 ImGui 元素
@@ -53,26 +51,9 @@ namespace kiwano
void RemoveAllItems();
public:
- void OnMouseButtonDown(int btn, Point const& p) override;
- void OnMouseButtonUp(int btn, Point const& p) override;
- void OnMouseWheel(float wheel) override;
-
- void OnKeyDown(int key) override;
- void OnKeyUp(int key) override;
- void OnChar(char c) override;
-
- public:
- void OnUpdate(Duration dt) override;
void OnRender() override;
- void UpdateMousePos();
- void UpdateMouseCursor();
-
protected:
- ImGuiLayer();
-
- protected:
- HWND target_window_;
Map pipelines_;
};
}
diff --git a/kiwano-imgui/src/ImGuiModule.cpp b/kiwano-imgui/src/ImGuiModule.cpp
new file mode 100644
index 00000000..0d820192
--- /dev/null
+++ b/kiwano-imgui/src/ImGuiModule.cpp
@@ -0,0 +1,305 @@
+// Copyright (C) 2019 Nomango
+
+#include "../kiwano-imgui.h"
+#include "imgui_impl.h"
+
+#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)
+ {
+ }
+
+ void ImGuiModule::SetupComponent(Application* app)
+ {
+ // Setup Dear ImGui context
+ 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(app->GetWindow()->GetHandle());
+
+ target_window_ = Renderer::Instance().GetTargetWindow();
+ }
+
+ void ImGuiModule::DestroyComponent()
+ {
+ ImGui_Impl_Shutdown();
+ ImGui::DestroyContext();
+ }
+
+ void ImGuiModule::BeforeUpdate(float dt)
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup time step
+ io.DeltaTime = dt;
+
+ // 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;
+
+ // 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;
+ io.KeyMap[ImGuiKey_LeftArrow] = KeyCode::Left;
+ io.KeyMap[ImGuiKey_RightArrow] = KeyCode::Right;
+ io.KeyMap[ImGuiKey_UpArrow] = KeyCode::Up;
+ io.KeyMap[ImGuiKey_DownArrow] = KeyCode::Down;
+ io.KeyMap[ImGuiKey_Delete] = KeyCode::Delete;
+ io.KeyMap[ImGuiKey_Backspace] = KeyCode::Back;
+ io.KeyMap[ImGuiKey_Space] = KeyCode::Space;
+ io.KeyMap[ImGuiKey_Enter] = KeyCode::Enter;
+ io.KeyMap[ImGuiKey_Escape] = KeyCode::Esc;
+ io.KeyMap[ImGuiKey_A] = KeyCode::A;
+ io.KeyMap[ImGuiKey_C] = KeyCode::C;
+ io.KeyMap[ImGuiKey_V] = KeyCode::V;
+ io.KeyMap[ImGuiKey_X] = KeyCode::X;
+ io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
+ io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
+
+ ImGui_Impl_Init(Renderer::Instance());
+ }
+
+ void ImGuiModule::BeforeRender()
+ {
+ NewFrame();
+ }
+
+ void ImGuiModule::AfterRender()
+ {
+ Render();
+ }
+
+ void ImGuiModule::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+ {
+ if (ImGui::GetCurrentContext() == NULL)
+ return;
+
+ ImGuiIO& io = ImGui::GetIO();
+ switch (msg)
+ {
+ 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((unsigned int)wparam);
+ break;
+ }
+ case WM_SETCURSOR:
+ {
+ if (LOWORD(lparam) == HTCLIENT)
+ {
+ UpdateMouseCursor();
+ }
+ break;
+ }
+ case WM_DEVICECHANGE:
+ {
+ if ((UINT)wparam == DBT_DEVNODES_CHANGED)
+ want_update_has_gamepad_ = true;
+ break;
+ }
+ }
+ }
+
+ void ImGuiModule::NewFrame()
+ {
+ ImGui_Impl_NewFrame();
+
+ ImGuiIO& io = ImGui::GetIO();
+ KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
+
+ // Setup display size (every frame to accommodate for window resizing)
+ Size display_size = Renderer::Instance().GetOutputSize();
+ io.DisplaySize = ImVec2(display_size.x, display_size.y);
+
+ ImGui::NewFrame();
+ }
+
+ void ImGuiModule::Render()
+ {
+ ImGui::Render();
+
+ ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
+ }
+
+ void ImGuiModule::UpdateMousePos()
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+ if (io.WantSetMousePos)
+ {
+ POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
+ ::ClientToScreen(target_window_, &pos);
+ ::SetCursorPos(pos.x, pos.y);
+ }
+
+ Point pos = Input::Instance().GetMousePos();
+ io.MousePos = ImVec2(pos.x, pos.y);
+ }
+
+ void ImGuiModule::UpdateMouseCursor()
+ {
+ if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return;
+
+ MouseCursor cursor = MouseCursor::Arrow;
+ switch (ImGui::GetMouseCursor())
+ {
+ case ImGuiMouseCursor_Arrow: cursor = MouseCursor::Arrow; break;
+ case ImGuiMouseCursor_TextInput: cursor = MouseCursor::TextInput; break;
+ case ImGuiMouseCursor_ResizeAll: cursor = MouseCursor::SizeAll; break;
+ case ImGuiMouseCursor_ResizeEW: cursor = MouseCursor::SizeWE; break;
+ case ImGuiMouseCursor_ResizeNS: cursor = MouseCursor::SizeNS; break;
+ case ImGuiMouseCursor_ResizeNESW: cursor = MouseCursor::SizeNESW; break;
+ case ImGuiMouseCursor_ResizeNWSE: cursor = MouseCursor::SizeNWSE; break;
+ case ImGuiMouseCursor_Hand: cursor = MouseCursor::Hand; break;
+ }
+
+ Window::Instance().SetMouseCursor(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
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/kiwano-imgui/src/ImGuiView.h b/kiwano-imgui/src/ImGuiModule.h
similarity index 75%
rename from kiwano-imgui/src/ImGuiView.h
rename to kiwano-imgui/src/ImGuiModule.h
index af5bbbb8..977ba357 100644
--- a/kiwano-imgui/src/ImGuiView.h
+++ b/kiwano-imgui/src/ImGuiModule.h
@@ -24,21 +24,11 @@ namespace kiwano
{
namespace imgui
{
- class ImGuiLayer;
-
- class ImGuiView
- : public Singleton
+ class ImGuiModule
+ : public Singleton
, public Component
{
- KGE_DECLARE_SINGLETON(ImGuiView);
-
- friend class ImGuiLayer;
-
- public:
- // 创建 ImGui 图层
- ImGuiLayerPtr CreateLayer(
- Scene* scene /* 指定场景 */
- );
+ KGE_DECLARE_SINGLETON(ImGuiModule);
private:
void Init(HWND hwnd);
@@ -47,15 +37,31 @@ namespace kiwano
void Render();
- void RemoveLayer(ImGuiLayer* layer);
-
public:
+ ImGuiModule();
+
void SetupComponent(Application* app) override;
void DestroyComponent() override;
+ void BeforeUpdate(float dt) override;
+
+ void BeforeRender() override;
+
+ void AfterRender() override;
+
+ void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
+
+ void UpdateMousePos();
+
+ void UpdateMouseCursor();
+
+ void UpdateGamepads();
+
private:
- Map layers_;
+ bool has_gamepad_;
+ bool want_update_has_gamepad_;
+ HWND target_window_;
};
}
}
diff --git a/kiwano-imgui/src/ImGuiView.cpp b/kiwano-imgui/src/ImGuiView.cpp
deleted file mode 100644
index 27298556..00000000
--- a/kiwano-imgui/src/ImGuiView.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2019 Nomango
-
-#include "../kiwano-imgui.h"
-#include "imgui_impl.hpp"
-
-namespace kiwano
-{
- namespace imgui
- {
-
- void ImGuiView::SetupComponent(Application* app)
- {
- // Setup Dear ImGui context
- 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(app->GetWindow()->GetHandle());
- }
-
- void ImGuiView::DestroyComponent()
- {
- ImGui_Impl_Shutdown();
- ImGui::DestroyContext();
- }
-
- void ImGuiView::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;
-
- // 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;
- io.KeyMap[ImGuiKey_LeftArrow] = KeyCode::Left;
- io.KeyMap[ImGuiKey_RightArrow] = KeyCode::Right;
- io.KeyMap[ImGuiKey_UpArrow] = KeyCode::Up;
- io.KeyMap[ImGuiKey_DownArrow] = KeyCode::Down;
- io.KeyMap[ImGuiKey_Delete] = KeyCode::Delete;
- io.KeyMap[ImGuiKey_Backspace] = KeyCode::Back;
- io.KeyMap[ImGuiKey_Space] = KeyCode::Space;
- io.KeyMap[ImGuiKey_Enter] = KeyCode::Enter;
- io.KeyMap[ImGuiKey_Escape] = KeyCode::Esc;
- io.KeyMap[ImGuiKey_A] = KeyCode::A;
- io.KeyMap[ImGuiKey_C] = KeyCode::C;
- io.KeyMap[ImGuiKey_V] = KeyCode::V;
- io.KeyMap[ImGuiKey_X] = KeyCode::X;
- io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
- io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
-
- ImGui_Impl_Init(
- Renderer::Instance()
- );
- }
-
- void ImGuiView::NewFrame()
- {
- ImGui_Impl_NewFrame();
-
- ImGuiIO& io = ImGui::GetIO();
- KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
-
- // Setup display size (every frame to accommodate for window resizing)
- Size display_size = Renderer::Instance().GetOutputSize();
- io.DisplaySize = ImVec2(display_size.x, display_size.y);
-
- ImGui::NewFrame();
- }
-
- void ImGuiView::Render()
- {
- ImGui::Render();
-
- ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
- }
-
- ImGuiLayerPtr ImGuiView::CreateLayer(Scene* scene)
- {
- auto iter = layers_.find(scene);
- if (iter == layers_.end())
- {
- ImGuiLayerPtr layer = new (std::nothrow) ImGuiLayer;
- if (layer)
- {
- layers_.insert(std::make_pair(scene, layer.Get()));
- }
- return layer;
- }
- else
- {
- return iter->second;
- }
- }
-
- void ImGuiView::RemoveLayer(ImGuiLayer* layer)
- {
- using value_type = Map::value_type;
-
- auto iter = std::find_if(layers_.begin(), layers_.end(), [=](value_type const& value)
- {
- return value.second == layer;
- });
- if (iter != layers_.end())
- {
- layers_.erase(iter);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/kiwano-imgui/src/imgui_impl.hpp b/kiwano-imgui/src/imgui_impl.h
similarity index 100%
rename from kiwano-imgui/src/imgui_impl.hpp
rename to kiwano-imgui/src/imgui_impl.h
diff --git a/kiwano/2d/Scene.cpp b/kiwano/2d/Scene.cpp
index c01e16cf..1cfe6b47 100644
--- a/kiwano/2d/Scene.cpp
+++ b/kiwano/2d/Scene.cpp
@@ -25,8 +25,6 @@
namespace kiwano
{
Scene::Scene()
- : mouse_cursor_(MouseCursor::Arrow)
- , last_mouse_cursor(MouseCursor(-1))
{
scene_ = this;
@@ -48,33 +46,4 @@ namespace kiwano
KGE_LOG(L"Scene exited");
}
- void Scene::Update(Duration dt)
- {
- Node::Update(dt);
-
- if (last_mouse_cursor != mouse_cursor_)
- {
- last_mouse_cursor = mouse_cursor_;
-
- LPTSTR win32_cursor = IDC_ARROW;
- switch (mouse_cursor_)
- {
- case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
- case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
- case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
- case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
- case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
- case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
- case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
- case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
- }
- ::SetCursor(::LoadCursorW(nullptr, win32_cursor));
- }
- }
-
- void Scene::SetMouseCursor(MouseCursor cursor)
- {
- mouse_cursor_ = cursor;
- }
-
}
diff --git a/kiwano/2d/Scene.h b/kiwano/2d/Scene.h
index f3f2997d..3dbddae5 100644
--- a/kiwano/2d/Scene.h
+++ b/kiwano/2d/Scene.h
@@ -37,16 +37,5 @@ namespace kiwano
// 退出场景
virtual void OnExit();
-
- public:
- void Update(Duration dt);
-
- void SetMouseCursor(
- MouseCursor cursor
- );
-
- protected:
- MouseCursor mouse_cursor_;
- MouseCursor last_mouse_cursor;
};
}
diff --git a/kiwano/2d/include-forwards.h b/kiwano/2d/include-forwards.h
index 9fdb85b0..fe502288 100644
--- a/kiwano/2d/include-forwards.h
+++ b/kiwano/2d/include-forwards.h
@@ -30,6 +30,7 @@
#include "../base/SmartPtr.hpp"
#include "../base/Object.h"
#include "../math/helper.h"
+#include "../base/types.h"
namespace kiwano
{
@@ -80,52 +81,3 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(Button);
KGE_DECLARE_SMART_PTR(Menu);
}
-
-namespace kiwano
-{
- // 画笔样式
- enum class StrokeStyle : int
- {
- Miter = 0, /* 斜切 */
- Bevel = 1, /* 斜角 */
- Round = 2 /* 圆角 */
- };
-
- // 方向
- enum class Direction : int
- {
- Up, /* 上 */
- Down, /* 下 */
- Left, /* 左 */
- Right /* 右 */
- };
-
- // 鼠标指针
- enum class MouseCursor : int
- {
- Arrow, /* 指针 */
- TextInput, /* 输入文本 */
- Hand, /* 手指 */
- SizeAll,
- SizeNESW,
- SizeNS,
- SizeNWSE,
- SizeWE,
- };
-
- // 文字抗锯齿属性
- enum class TextAntialias
- {
- Default, // 系统默认
- ClearType, // ClearType 抗锯齿
- GrayScale, // 灰度抗锯齿
- None // 不启用抗锯齿
- };
-
- // 图层属性
- struct LayerProperties
- {
- Rect area;
- float opacity;
- };
-}
diff --git a/kiwano/Kiwano.vcxproj b/kiwano/Kiwano.vcxproj
index e516a13e..15c1e667 100644
--- a/kiwano/Kiwano.vcxproj
+++ b/kiwano/Kiwano.vcxproj
@@ -1,6 +1,7 @@
+
diff --git a/kiwano/Kiwano.vcxproj.filters b/kiwano/Kiwano.vcxproj.filters
index b5373957..925203e2 100644
--- a/kiwano/Kiwano.vcxproj.filters
+++ b/kiwano/Kiwano.vcxproj.filters
@@ -258,6 +258,9 @@
renderer
+
+ base
+
diff --git a/kiwano/base/Component.h b/kiwano/base/Component.h
index b76efe7c..7759351f 100644
--- a/kiwano/base/Component.h
+++ b/kiwano/base/Component.h
@@ -30,12 +30,10 @@ namespace kiwano
virtual void SetupComponent(Application*) = 0;
virtual void DestroyComponent() = 0;
- virtual void BeforeUpdate() {}
- virtual void OnUpdate(float dt) {}
+ virtual void BeforeUpdate(float dt) {}
virtual void AfterUpdate() {}
virtual void BeforeRender() {}
- virtual void OnRender() {}
virtual void AfterRender() {}
virtual void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {}
diff --git a/kiwano/base/Input.cpp b/kiwano/base/Input.cpp
index d9caf178..ba52a7f5 100644
--- a/kiwano/base/Input.cpp
+++ b/kiwano/base/Input.cpp
@@ -38,17 +38,6 @@ namespace kiwano
{
}
- void Input::Update()
- {
- if (want_update_)
- {
- want_update_ = false;
-
- ZeroMemory(keys_pressed_, sizeof(keys_pressed_));
- ZeroMemory(keys_released_, sizeof(keys_released_));
- }
- }
-
void Input::UpdateKey(int key, bool down)
{
if (down && !keys_[key])
@@ -67,6 +56,17 @@ namespace kiwano
mouse_pos_y_ = y;
}
+ void Input::AfterUpdate()
+ {
+ if (want_update_)
+ {
+ want_update_ = false;
+
+ ZeroMemory(keys_pressed_, sizeof(keys_pressed_));
+ ZeroMemory(keys_released_, sizeof(keys_released_));
+ }
+ }
+
void Input::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
diff --git a/kiwano/base/Input.h b/kiwano/base/Input.h
index 23b42ef7..c9d37658 100644
--- a/kiwano/base/Input.h
+++ b/kiwano/base/Input.h
@@ -63,14 +63,14 @@ namespace kiwano
void DestroyComponent() override {}
- void Update();
+ void AfterUpdate() override;
+
+ void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
void UpdateKey(int, bool);
void UpdateMousePos(float, float);
- void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
-
protected:
Input();
diff --git a/kiwano/base/types.h b/kiwano/base/types.h
new file mode 100644
index 00000000..28e139e0
--- /dev/null
+++ b/kiwano/base/types.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2016-2019 Kiwano - Nomango
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#pragma once
+#include "../math/Rect.hpp"
+
+namespace kiwano
+{
+ // 画笔样式
+ enum class StrokeStyle : int
+ {
+ Miter = 0, /* 斜切 */
+ Bevel = 1, /* 斜角 */
+ Round = 2 /* 圆角 */
+ };
+
+ // 方向
+ enum class Direction : int
+ {
+ Up, /* 上 */
+ Down, /* 下 */
+ Left, /* 左 */
+ Right /* 右 */
+ };
+
+ // 鼠标指针
+ enum class MouseCursor : int
+ {
+ Arrow, /* 指针 */
+ TextInput, /* 输入文本 */
+ Hand, /* 手指 */
+ SizeAll,
+ SizeNESW,
+ SizeNS,
+ SizeNWSE,
+ SizeWE,
+ };
+
+ // 文字抗锯齿属性
+ enum class TextAntialias
+ {
+ Default, // 系统默认
+ ClearType, // ClearType 抗锯齿
+ GrayScale, // 灰度抗锯齿
+ None // 不启用抗锯齿
+ };
+
+ // 图层属性
+ struct LayerProperties
+ {
+ Rect area;
+ float opacity;
+ };
+}
\ No newline at end of file
diff --git a/kiwano/base/window.cpp b/kiwano/base/window.cpp
index c02811ed..98ef3f6b 100644
--- a/kiwano/base/window.cpp
+++ b/kiwano/base/window.cpp
@@ -44,6 +44,7 @@ namespace kiwano
, height_(0)
, device_name_(nullptr)
, is_fullscreen_(false)
+ , mouse_cursor_(MouseCursor(-1))
{
}
@@ -163,6 +164,8 @@ namespace kiwano
GetClientRect(handle_, &rc);
width_ = rc.right - rc.left;
height_ = rc.bottom - rc.top;
+
+ SetMouseCursor(MouseCursor::Arrow);
return S_OK;
}
@@ -290,6 +293,28 @@ namespace kiwano
}
}
+ void Window::SetMouseCursor(MouseCursor cursor)
+ {
+ if (mouse_cursor_ != cursor)
+ {
+ mouse_cursor_ = cursor;
+
+ LPTSTR win32_cursor = IDC_ARROW;
+ switch (cursor)
+ {
+ case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
+ case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
+ case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
+ case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
+ case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
+ case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
+ case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
+ case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
+ }
+ ::SetCursor(::LoadCursorW(nullptr, win32_cursor));
+ }
+ }
+
HWND Window::GetHandle() const
{
return handle_;
diff --git a/kiwano/base/window.h b/kiwano/base/window.h
index 185d47ea..58dbdc32 100644
--- a/kiwano/base/window.h
+++ b/kiwano/base/window.h
@@ -22,11 +22,16 @@
#include "../macros.h"
#include "../common/helper.h"
#include "../math/helper.h"
+#include "../common/Singleton.hpp"
+#include "types.h"
namespace kiwano
{
class KGE_API Window
+ : public Singleton
{
+ KGE_DECLARE_SINGLETON(Window);
+
public:
// 获取标题
String GetTitle() const;
@@ -52,6 +57,9 @@ namespace kiwano
// 设置全屏模式
void SetFullscreen(bool fullscreen, int width, int height);
+ // 设置鼠标指针
+ void SetMouseCursor(MouseCursor cursor);
+
public:
HRESULT Create(
String const& title,
@@ -72,7 +80,7 @@ namespace kiwano
void SetActive(bool actived);
- public:
+ protected:
Window();
~Window();
@@ -83,5 +91,6 @@ namespace kiwano
int width_;
int height_;
WCHAR* device_name_;
+ MouseCursor mouse_cursor_;
};
}
diff --git a/kiwano/platform/Application.cpp b/kiwano/platform/Application.cpp
index 78e2c4bb..43297563 100644
--- a/kiwano/platform/Application.cpp
+++ b/kiwano/platform/Application.cpp
@@ -56,7 +56,7 @@ namespace kiwano
::CoInitialize(nullptr)
);
- main_window_ = new Window;
+ main_window_ = &Window::Instance();
Use(&Renderer::Instance());
Use(&Input::Instance());
@@ -146,12 +146,6 @@ namespace kiwano
{
(*iter)->DestroyComponent();
}
-
- if (main_window_)
- {
- delete main_window_;
- main_window_ = nullptr;
- }
}
}
@@ -247,7 +241,7 @@ namespace kiwano
// Before update
for (Component* c : components_)
{
- c->BeforeUpdate();
+ c->BeforeUpdate(dt.Seconds());
}
// Updating
diff --git a/kiwano/ui/Button.cpp b/kiwano/ui/Button.cpp
index 29923e48..7497bd30 100644
--- a/kiwano/ui/Button.cpp
+++ b/kiwano/ui/Button.cpp
@@ -20,6 +20,7 @@
#include "Button.h"
#include "../2d/Scene.h"
+#include "../base/window.h"
namespace kiwano
{
@@ -111,7 +112,7 @@ namespace kiwano
if (evt.type == Event::MouseHover)
{
SetStatus(Status::Hover);
- GetScene()->SetMouseCursor(MouseCursor::Hand);
+ Window::Instance().SetMouseCursor(MouseCursor::Hand);
if (mouse_over_callback_)
mouse_over_callback_();
@@ -119,7 +120,7 @@ namespace kiwano
else if (evt.type == Event::MouseOut)
{
SetStatus(Status::Normal);
- GetScene()->SetMouseCursor(MouseCursor::Arrow);
+ Window::Instance().SetMouseCursor(MouseCursor::Arrow);
if (mouse_out_callback_)
mouse_out_callback_();
diff --git a/samples/ImGuiSample/MainScene.h b/samples/ImGuiSample/MainScene.h
index 44bb494e..e9a2d0cd 100644
--- a/samples/ImGuiSample/MainScene.h
+++ b/samples/ImGuiSample/MainScene.h
@@ -20,7 +20,7 @@ public:
MainScene()
{
// 创建 ImGui 图层
- ImGuiLayerPtr layer = ImGuiView::Instance().CreateLayer(this);
+ ImGuiLayerPtr layer = new ImGuiLayer;
AddChild(layer);
// 添加 ImGui 提供的 Demo 窗口
diff --git a/samples/ImGuiSample/main.cpp b/samples/ImGuiSample/main.cpp
index 47e7c0d9..b821cc61 100644
--- a/samples/ImGuiSample/main.cpp
+++ b/samples/ImGuiSample/main.cpp
@@ -11,11 +11,10 @@ public:
ImGuiApp()
{
// 添加 ImGui 组件
- Use(&ImGuiView::Instance());
+ Use(&ImGuiModule::Instance());
// 初始化
Options options(L"ImGui Demo", 1280, 800);
-
Init(options);
}