diff --git a/project/Box2DSample/main.cpp b/project/Box2DSample/main.cpp index d51a78e1..39837069 100644 --- a/project/Box2DSample/main.cpp +++ b/project/Box2DSample/main.cpp @@ -132,10 +132,7 @@ class MainScene public: MainScene() { - // 修改场景大小, 并设置可响应状态, 使场景可以 - // 接收到鼠标 Click 消息 - auto size = Window::Instance().GetSize(); - SetSize(size); + // 设置可响应状态, 使场景可以接收到鼠标 Click 消息 SetResponsible(true); // 添加消息监听 @@ -144,7 +141,7 @@ public: // 创建物理世界 world_ = new b2World(b2Vec2(0, 10)); - BoardPtr board = new Board(world_, Size(GetWidth() - 100, 20), Point(size.x / 2, size.y - 50)); + BoardPtr board = new Board(world_, Size(GetWidth() - 100, 20), Point(GetWidth() / 2, GetHeight() - 50)); AddChild(board); CirclePtr circle = new Circle(world_, Point(320, 240)); @@ -208,7 +205,9 @@ int main() try { Application app; - app.Init(); + + Options options(L"Box2D Demo"); + app.Init(options); ScenePtr scene = new MainScene; app.EnterScene(scene); diff --git a/project/Easy2D/Easy2D.vcxproj b/project/Easy2D/Easy2D.vcxproj index 48fc5fed..ef302934 100644 --- a/project/Easy2D/Easy2D.vcxproj +++ b/project/Easy2D/Easy2D.vcxproj @@ -7,19 +7,23 @@ + + + + + + + + - - - - @@ -29,24 +33,20 @@ - + - - + - - - @@ -63,6 +63,7 @@ + @@ -101,6 +102,7 @@ + @@ -119,7 +121,6 @@ - diff --git a/project/Easy2D/Easy2D.vcxproj.filters b/project/Easy2D/Easy2D.vcxproj.filters index 1e8ff355..9e431f3b 100644 --- a/project/Easy2D/Easy2D.vcxproj.filters +++ b/project/Easy2D/Easy2D.vcxproj.filters @@ -19,6 +19,9 @@ {836608a6-7443-48f9-8acd-18d3ba664348} + + {86e2d0f2-a9d0-4456-b6a5-d480228bbf82} + @@ -40,9 +43,6 @@ core - - core - core @@ -100,9 +100,6 @@ ui - - core - core @@ -121,9 +118,6 @@ core - - core - utils @@ -154,9 +148,6 @@ core - - core - core @@ -178,27 +169,12 @@ core - - core - - - core - - - core - core core - - core - - - core - core @@ -244,7 +220,33 @@ audio - + + core + + + + + common + + + common + + + common + + + common + + + common + + + common + + + common + + core @@ -297,9 +299,6 @@ core - - math - utils @@ -393,5 +392,8 @@ audio + + core + \ No newline at end of file diff --git a/project/ImGuiSample/ImGuiSample.vcxproj b/project/ImGuiSample/ImGuiSample.vcxproj index 6e9bad0c..144cccaa 100644 --- a/project/ImGuiSample/ImGuiSample.vcxproj +++ b/project/ImGuiSample/ImGuiSample.vcxproj @@ -136,8 +136,9 @@ - - + + + @@ -147,8 +148,10 @@ - - + + + + diff --git a/project/ImGuiSample/ImGuiSample.vcxproj.filters b/project/ImGuiSample/ImGuiSample.vcxproj.filters index aa603c21..a89be911 100644 --- a/project/ImGuiSample/ImGuiSample.vcxproj.filters +++ b/project/ImGuiSample/ImGuiSample.vcxproj.filters @@ -2,8 +2,6 @@ - - imgui @@ -16,10 +14,17 @@ imgui + + easy2d-imgui + + + easy2d-imgui + + + easy2d-imgui + - - imgui @@ -38,10 +43,25 @@ imgui + + easy2d-imgui + + + easy2d-imgui + + + easy2d-imgui + + + easy2d-imgui + {24ae99cd-ee12-481f-bb03-d8be40d99342} + + {37f1585a-e992-454a-8cac-e9a6142b08b6} + \ No newline at end of file diff --git a/project/ImGuiSample/easy2d-imgui/ImGuiLayer.cpp b/project/ImGuiSample/easy2d-imgui/ImGuiLayer.cpp new file mode 100644 index 00000000..166a8617 --- /dev/null +++ b/project/ImGuiSample/easy2d-imgui/ImGuiLayer.cpp @@ -0,0 +1,165 @@ +// Copyright (C) 2019 Nomango + +#include "easy2d-imgui.h" + +namespace easy2d +{ + namespace + { + Map mouse_buttons = + { + { MouseButton::Left, 0 }, + { MouseButton::Right, 1 }, + { MouseButton::Middle, 2 } + }; + } + + ImGuiLayer::ImGuiLayer() + { + target_window_ = Renderer::Instance().GetTargetWindow(); + } + + ImGuiLayer::~ImGuiLayer() + { + } + + void ImGuiLayer::OnMouseButtonDown(int btn, Point const & p) + { + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == nullptr) + ::SetCapture(target_window_); + + E2D_ASSERT(mouse_buttons.find(btn) != mouse_buttons.end()); + ImGui::GetIO().MouseDown[mouse_buttons[btn]] = true; + } + + void ImGuiLayer::OnMouseButtonUp(int btn, Point const & p) + { + E2D_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) + { + E2D_ASSERT(key < 256); + ImGui::GetIO().KeysDown[key] = 1; + } + + void ImGuiLayer::OnKeyUp(int key) + { + E2D_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) + { + pipelines_.insert(std::make_pair(name, item)); + } + + void ImGuiLayer::RemoveItem(String const & name) + { + auto iter = pipelines_.find(name); + if (iter != pipelines_.end()) + { + pipelines_.erase(iter); + } + } + + void ImGuiLayer::RemoveAllItems() + { + pipelines_.clear(); + } + +} \ No newline at end of file diff --git a/project/ImGuiSample/easy2d-imgui/ImGuiLayer.h b/project/ImGuiSample/easy2d-imgui/ImGuiLayer.h new file mode 100644 index 00000000..7731708d --- /dev/null +++ b/project/ImGuiSample/easy2d-imgui/ImGuiLayer.h @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Nomango + +#pragma once + +namespace easy2d +{ + E2D_DECLARE_SMART_PTR(ImGuiLayer); + + using ImGuiPipeline = std::function; + + class ImGuiLayer + : public Layer + { + public: + ImGuiLayer(); + + virtual ~ImGuiLayer(); + + // 添加 ImGui 元素 + void AddItem( + ImGuiPipeline const& item, + String const& name + ); + + // 移除 ImGui 元素 + void RemoveItem( + String const& name + ); + + // 移除所有元素 + 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: + HWND target_window_; + Map pipelines_; + }; +} diff --git a/project/ImGuiSample/easy2d-imgui/ImGuiView.cpp b/project/ImGuiSample/easy2d-imgui/ImGuiView.cpp new file mode 100644 index 00000000..0467a44f --- /dev/null +++ b/project/ImGuiSample/easy2d-imgui/ImGuiView.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2019 Nomango + +#include "easy2d-imgui.h" +#include "imgui_impl_dx11.h" + +namespace easy2d +{ + void ImGuiView::Setup(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::Destroy() + { + ImGui_ImplDX11_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_ImplDX11_Init( + Renderer::Instance().GetDeviceResources()->GetD3DDevice(), + Renderer::Instance().GetDeviceResources()->GetD3DDeviceContext() + ); + } + + void ImGuiView::NewFrame() + { + ImGui_ImplDX11_NewFrame(); + + ImGuiIO& io = ImGui::GetIO(); + E2D_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_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + } + +} \ No newline at end of file diff --git a/project/ImGuiSample/easy2d-imgui/ImGuiView.h b/project/ImGuiSample/easy2d-imgui/ImGuiView.h new file mode 100644 index 00000000..c9cfce9b --- /dev/null +++ b/project/ImGuiSample/easy2d-imgui/ImGuiView.h @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Nomango + +#pragma once + +namespace easy2d +{ + class ImGuiView + : public Singleton + , public Component + { + E2D_DECLARE_SINGLETON(ImGuiView); + + public: + void Setup(Application* app) override; + + void Destroy() override; + + public: + void Init(HWND hwnd); + + void NewFrame(); + + void Render(); + }; + +} diff --git a/project/ImGuiSample/easy2d-imgui/easy2d-imgui.h b/project/ImGuiSample/easy2d-imgui/easy2d-imgui.h new file mode 100644 index 00000000..f169b80b --- /dev/null +++ b/project/ImGuiSample/easy2d-imgui/easy2d-imgui.h @@ -0,0 +1,9 @@ +// Copyright (C) 2019 Nomango + +#pragma once +#include "easy2d.h" +#include "ImGuiView.h" +#include "ImGuiLayer.h" + +// ImGui +#include "imgui.h" diff --git a/project/ImGuiSample/imgui_impl_dx11.cpp b/project/ImGuiSample/easy2d-imgui/imgui_impl_dx11.cpp similarity index 100% rename from project/ImGuiSample/imgui_impl_dx11.cpp rename to project/ImGuiSample/easy2d-imgui/imgui_impl_dx11.cpp diff --git a/project/ImGuiSample/imgui_impl_dx11.h b/project/ImGuiSample/easy2d-imgui/imgui_impl_dx11.h similarity index 100% rename from project/ImGuiSample/imgui_impl_dx11.h rename to project/ImGuiSample/easy2d-imgui/imgui_impl_dx11.h diff --git a/project/ImGuiSample/imgui_impl_win32.cpp b/project/ImGuiSample/imgui_impl_win32.cpp deleted file mode 100644 index 6d033f66..00000000 --- a/project/ImGuiSample/imgui_impl_win32.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// dear imgui: Platform Binding for Windows (standard windows API for 32 and 64 bits applications) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) - -#include "imgui.h" -#include "imgui_impl_win32.h" -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include - -// Win32 Data -static HWND g_hWnd = 0; -static INT64 g_Time = 0; -static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; - -// Functions -bool ImGui_ImplWin32_Init(void* hwnd) -{ - if (!::QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) - return false; - if (!::QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) - return false; - - // Setup back-end capabilities flags - g_hWnd = (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] = VK_TAB; - io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = VK_UP; - io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; - io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; - io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; - io.KeyMap[ImGuiKey_Home] = VK_HOME; - io.KeyMap[ImGuiKey_End] = VK_END; - io.KeyMap[ImGuiKey_Insert] = VK_INSERT; - io.KeyMap[ImGuiKey_Delete] = VK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = VK_BACK; - io.KeyMap[ImGuiKey_Space] = VK_SPACE; - io.KeyMap[ImGuiKey_Enter] = VK_RETURN; - io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; - - return true; -} - -void ImGui_ImplWin32_Shutdown() -{ - g_hWnd = (HWND)0; -} - -static bool ImGui_ImplWin32_UpdateMouseCursor() -{ - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) - return false; - - ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) - { - // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - ::SetCursor(NULL); - } - else - { - // Show OS mouse cursor - LPTSTR win32_cursor = IDC_ARROW; - switch (imgui_cursor) - { - case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; - case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; - case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; - case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; - case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; - case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; - case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; - case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; - } - ::SetCursor(::LoadCursor(NULL, win32_cursor)); - } - return true; -} - -static void ImGui_ImplWin32_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(g_hWnd, &pos); - ::SetCursorPos(pos.x, pos.y); - } - - // Set mouse position - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - POINT pos; - if (HWND active_window = ::GetForegroundWindow()) - if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) - if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) - io.MousePos = ImVec2((float)pos.x, (float)pos.y); -} - -void ImGui_ImplWin32_NewFrame() -{ - ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); - - // Setup display size (every frame to accommodate for window resizing) - RECT rect; - ::GetClientRect(g_hWnd, &rect); - io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); - - // Setup time step - INT64 current_time; - ::QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); - io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; - g_Time = current_time; - - // Read keyboard modifiers inputs - io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; - io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; - io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; - io.KeySuper = false; - // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. - - // Update OS mouse position - ImGui_ImplWin32_UpdateMousePos(); - - // Update OS mouse cursor with the cursor requested by imgui - ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); - if (g_LastMouseCursor != mouse_cursor) - { - g_LastMouseCursor = mouse_cursor; - ImGui_ImplWin32_UpdateMouseCursor(); - } -} - -// 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 - -// Process Win32 mouse/keyboard inputs. -// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. -// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. -// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. -// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. -IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ImGui::GetCurrentContext() == NULL) - return 0; - - 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; - return 0; - } - 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(); - return 0; - } - case WM_MOUSEWHEEL: - io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; - return 0; - case WM_MOUSEHWHEEL: - io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; - return 0; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (wParam < 256) - io.KeysDown[wParam] = 1; - return 0; - case WM_KEYUP: - case WM_SYSKEYUP: - if (wParam < 256) - io.KeysDown[wParam] = 0; - return 0; - case WM_CHAR: - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - if (wParam > 0 && wParam < 0x10000) - io.AddInputCharacter((unsigned short)wParam); - return 0; - case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) - return 1; - return 0; - } - return 0; -} - diff --git a/project/ImGuiSample/imgui_impl_win32.h b/project/ImGuiSample/imgui_impl_win32.h deleted file mode 100644 index debd00d6..00000000 --- a/project/ImGuiSample/imgui_impl_win32.h +++ /dev/null @@ -1,15 +0,0 @@ -// dear imgui: Platform Binding for Windows (standard windows API for 32 and 64 bits applications) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) - -#pragma once - -IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); -IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); - -// Handler for Win32 messages, update mouse/keyboard data. -// You may or not need this for your implementation, but it can serve as reference for handling inputs. -// Intentionally commented out to avoid dragging dependencies on types. You can COPY this line into your .cpp code instead. -/* -IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -*/ diff --git a/project/ImGuiSample/main.cpp b/project/ImGuiSample/main.cpp index ffcdb62d..a3f81827 100644 --- a/project/ImGuiSample/main.cpp +++ b/project/ImGuiSample/main.cpp @@ -1,11 +1,8 @@ -// ImGui -#include "imgui.h" -#include "imgui_impl_win32.h" -#include "imgui_impl_dx11.h" -#include +// Copyright (C) 2019 Nomango -// easy2d #include "easy2d.h" +#include "easy2d-imgui/easy2d-imgui.h" + using namespace easy2d; const int WINDOW_WIDTH = 1280; @@ -17,108 +14,36 @@ class ImGuiScene : public Scene { bool show_demo_window = true; - bool show_another_window = false; - Color clear_color = Color(0.45f, 0.55f, 0.6f, 1.f); public: - void OnEnter() override + ImGuiScene() { - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // 创建 ImGui 图层 + ImGuiLayerPtr layer = new ImGuiLayer; + AddChild(layer); - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); - - // Setup Platform/Renderer bindings - ImGui_ImplWin32_Init(Window::Instance().GetHandle()); - ImGui_ImplDX11_Init( - Renderer::Instance().GetDeviceResources()->GetD3DDevice(), - Renderer::Instance().GetDeviceResources()->GetD3DDeviceContext() - ); - } - - void OnRender() override - { - // Start the Dear ImGui frame - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - ImGui::Render(); - - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - - Renderer::Instance().SetClearColor(clear_color); - } - - void OnExit() override - { - ImGui_ImplDX11_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); + // 添加 ImGui 提供的 Demo 窗口 + layer->AddItem([=]() { + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + }, L"DemoWindow"); } }; - -extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM); - class ImGuiApp : public Application { public: ImGuiApp() { - Options options; - options.title = L"ImGui Demo"; - options.width = WINDOW_WIDTH; - options.height = WINDOW_HEIGHT; + // 添加 ImGui 组件 + Use(&ImGuiView::Instance()); + + // 初始化 + Options options(L"ImGui Demo", WINDOW_WIDTH, WINDOW_HEIGHT); options.clear_color = Color(0.45f, 0.55f, 0.6f, 1.f); Init(options); - - SetPreMessageProc(ImGui_ImplWin32_WndProcHandler); } void OnStart() override diff --git a/project/Samples/main.cpp b/project/Samples/main.cpp index fa0bb2b8..45c7fa66 100644 --- a/project/Samples/main.cpp +++ b/project/Samples/main.cpp @@ -39,7 +39,7 @@ public: void ChangeDemoScene() { - Window::Instance().SetTitle(s_Demos[s_DemoIndex].title); + GetWindow()->SetTitle(s_Demos[s_DemoIndex].title); ScenePtr scene = s_Demos[s_DemoIndex].Create(); EnterScene(scene); diff --git a/src/audio/Transcoder.cpp b/src/audio/Transcoder.cpp index d332b019..ce9a66a2 100644 --- a/src/audio/Transcoder.cpp +++ b/src/audio/Transcoder.cpp @@ -24,7 +24,7 @@ #include "Transcoder.h" #include "audio-modules.h" -#include "../core/ComPtr.hpp" +#include "../common/ComPtr.hpp" #include "../core/logs.h" #include "../core/modules.h" diff --git a/src/audio/Voice.h b/src/audio/Voice.h index 583179f9..7993e8f3 100644 --- a/src/audio/Voice.h +++ b/src/audio/Voice.h @@ -19,8 +19,8 @@ // THE SOFTWARE. #pragma once -#include "../core/macros.h" -#include "../core/noncopyable.hpp" +#include "../macros.h" +#include "../common/noncopyable.hpp" #include namespace easy2d diff --git a/src/audio/audio-modules.h b/src/audio/audio-modules.h index 36744487..d7b3e184 100644 --- a/src/audio/audio-modules.h +++ b/src/audio/audio-modules.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/macros.h" +#include "../macros.h" #include #include #include diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 11354479..4619dc42 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -34,7 +34,7 @@ namespace easy2d { } - void Audio::Setup() + void Audio::Setup(Application*) { E2D_LOG(L"Creating audio resources"); @@ -65,7 +65,11 @@ namespace easy2d mastering_voice_ = nullptr; } - DX::SafeRelease(x_audio2_); + if (x_audio2_) + { + x_audio2_->Release(); + x_audio2_ = nullptr; + } modules::MediaFoundation::Get().MFShutdown(); } diff --git a/src/audio/audio.h b/src/audio/audio.h index b6697c23..22deb128 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -20,8 +20,8 @@ #pragma once #include "../core/include-forwards.h" -#include "../core/Singleton.hpp" #include "../core/Component.h" +#include "../common/Singleton.hpp" #include "Voice.h" namespace easy2d @@ -35,7 +35,7 @@ namespace easy2d using VoiceMap = UnorderedSet; public: - void Setup() override; + void Setup(Application*) override; void Destroy() override; diff --git a/src/core/Array.h b/src/common/Array.h similarity index 99% rename from src/core/Array.h rename to src/common/Array.h index 284eaf4a..92e38cb9 100644 --- a/src/core/Array.h +++ b/src/common/Array.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" namespace easy2d { diff --git a/src/core/ComPtr.hpp b/src/common/ComPtr.hpp similarity index 97% rename from src/core/ComPtr.hpp rename to src/common/ComPtr.hpp index 6f6a6124..4f7b0beb 100644 --- a/src/core/ComPtr.hpp +++ b/src/common/ComPtr.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/IntrusivePtr.hpp" +#include "IntrusivePtr.hpp" #include namespace easy2d diff --git a/src/core/IntrusiveList.hpp b/src/common/IntrusiveList.hpp similarity index 99% rename from src/core/IntrusiveList.hpp rename to src/common/IntrusiveList.hpp index 729f9193..44004b70 100644 --- a/src/core/IntrusiveList.hpp +++ b/src/common/IntrusiveList.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" #include #ifdef E2D_DEBUG diff --git a/src/core/IntrusivePtr.hpp b/src/common/IntrusivePtr.hpp similarity index 99% rename from src/core/IntrusivePtr.hpp rename to src/common/IntrusivePtr.hpp index 004c5ec6..edc19c7d 100644 --- a/src/core/IntrusivePtr.hpp +++ b/src/common/IntrusivePtr.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" #include namespace easy2d diff --git a/src/core/Singleton.hpp b/src/common/Singleton.hpp similarity index 92% rename from src/core/Singleton.hpp rename to src/common/Singleton.hpp index d5d630ff..31f1739c 100644 --- a/src/core/Singleton.hpp +++ b/src/common/Singleton.hpp @@ -20,6 +20,14 @@ #pragma once +// Class that will implement the singleton mode, +// must use the macro in its delare file + +#ifndef E2D_DECLARE_SINGLETON +#define E2D_DECLARE_SINGLETON( CLASS ) \ + friend class ::easy2d::Singleton< CLASS > +#endif + namespace easy2d { template @@ -28,7 +36,7 @@ namespace easy2d public: static inline _Ty& Instance() { - static _Ty instance; // Thread safe + static _Ty instance; // Thread-safe return instance; } @@ -41,11 +49,3 @@ namespace easy2d Singleton& operator=(const Singleton&) = delete; }; } - -// Class that will implement the singleton mode, -// must use the macro in its delare file - -#ifndef E2D_DECLARE_SINGLETON -#define E2D_DECLARE_SINGLETON( type ) \ - friend class ::easy2d::Singleton< type > -#endif diff --git a/src/core/closure.hpp b/src/common/closure.hpp similarity index 93% rename from src/core/closure.hpp rename to src/common/closure.hpp index 4c877230..793ab423 100644 --- a/src/core/closure.hpp +++ b/src/common/closure.hpp @@ -23,6 +23,17 @@ namespace easy2d { + // + // Closure is a simple function for binding member functions + // + + template + std::function<_Ret(_Args...)> Closure(_Ty* _Ptr, _Ret(_Ty::*_Func)(_Args...)); + + + // + // Details of Closure + // namespace __closure__detail { // sequence & generater @@ -62,10 +73,6 @@ namespace easy2d }; } - // - // Closure is a simple function for binding member functions - // - template inline std::function<_Ret(_Args...)> Closure(_Ty* _Ptr, _Ret(_Ty::*_Func)(_Args...)) { diff --git a/src/core/noncopyable.hpp b/src/common/noncopyable.hpp similarity index 96% rename from src/core/noncopyable.hpp rename to src/common/noncopyable.hpp index 3ec85eeb..2c1dbc80 100644 --- a/src/core/noncopyable.hpp +++ b/src/common/noncopyable.hpp @@ -19,11 +19,10 @@ // THE SOFTWARE. #pragma once -#include "macros.h" namespace easy2d { - class E2D_API Noncopyable + class Noncopyable { protected: Noncopyable() = default; diff --git a/src/core/config.h b/src/config.h similarity index 100% rename from src/core/config.h rename to src/config.h diff --git a/src/core/Action.h b/src/core/Action.h index 98e999f2..97de29bb 100644 --- a/src/core/Action.h +++ b/src/core/Action.h @@ -21,7 +21,7 @@ #pragma once #include "include-forwards.h" #include "time.h" -#include "IntrusiveList.hpp" +#include "../common/IntrusiveList.hpp" namespace easy2d { diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 9c55849a..820e15c3 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -22,7 +22,6 @@ #include "logs.h" #include "modules.h" #include "render.h" -#include "window.h" #include "input.h" #include "Event.hpp" #include "Scene.h" @@ -36,22 +35,17 @@ namespace easy2d { - namespace - { - LRESULT(*pre_proc)(HWND, UINT, WPARAM, LPARAM) = nullptr; // Custom message proc for user - } - Application::Application(String const& app_name) : end_(true) , inited_(false) - , curr_scene_(nullptr) - , next_scene_(nullptr) - , transition_(nullptr) + , main_window_(nullptr) , time_scale_(1.f) , app_name_(app_name) { ::CoInitialize(nullptr); + main_window_ = new Window; + Use(&Renderer::Instance()); Use(&Input::Instance()); } @@ -66,7 +60,7 @@ namespace easy2d void Application::Init(const Options& options) { ThrowIfFailed( - Window::Instance().Create( + main_window_->Create( options.title, options.width, options.height, @@ -76,16 +70,15 @@ namespace easy2d ) ); - HWND hwnd = Window::Instance().GetHandle(); + HWND hwnd = main_window_->GetHandle(); - Renderer::Instance().SetTargetWindow(hwnd); Renderer::Instance().SetClearColor(options.clear_color); Renderer::Instance().SetVSyncEnabled(options.vsync); // Setup all components for (Component* c : components_) { - c->Setup(); + c->Setup(this); } OnStart(); @@ -101,13 +94,15 @@ namespace easy2d void Application::Run() { - HWND hwnd = Window::Instance().GetHandle(); + HWND hwnd = main_window_->GetHandle(); + + if (!hwnd) + throw std::exception("Calling Application::Run before Application::Init"); if (hwnd) { end_ = false; - - Window::Instance().Prepare(); + main_window_->Prepare(); MSG msg = {}; while (::GetMessageW(&msg, nullptr, 0, 0) && !end_) @@ -125,24 +120,25 @@ namespace easy2d void Application::Destroy() { + transition_.Reset(); + next_scene_.Reset(); + curr_scene_.Reset(); + debug_node_.Reset(); + if (inited_) { inited_ = false; - if (curr_scene_) - curr_scene_->OnExit(); - - transition_.Reset(); - next_scene_.Reset(); - curr_scene_.Reset(); - debug_node_.Reset(); - for (auto iter = components_.rbegin(); iter != components_.rend(); ++iter) { (*iter)->Destroy(); } - Window::Instance().Destroy(); + if (main_window_) + { + delete main_window_; + main_window_ = nullptr; + } } } @@ -166,7 +162,7 @@ namespace easy2d { if (component) { - for (auto iter = components_.begin(); iter != components_.end(); iter++) + for (auto iter = components_.begin(); iter != components_.end(); ++iter) { if ((*iter) == component) { @@ -213,11 +209,6 @@ namespace easy2d time_scale_ = scale_factor; } - void Application::SetPreMessageProc(LRESULT(*proc)(HWND, UINT, WPARAM, LPARAM)) - { - pre_proc = proc; - } - void Application::ShowDebugInfo(bool show) { if (show) @@ -290,11 +281,11 @@ namespace easy2d curr_scene_->Render(); } + OnRender(); + if (debug_node_) debug_node_->Render(); - OnRender(); - ThrowIfFailed( Renderer::Instance().EndDraw() ); @@ -336,9 +327,6 @@ namespace easy2d LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - if (pre_proc && pre_proc(hwnd, msg, wparam, lparam)) - return 1; - Application * app = reinterpret_cast( static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)) ); @@ -359,13 +347,16 @@ namespace easy2d break; case WM_KEYDOWN: + case WM_SYSKEYDOWN: case WM_KEYUP: + case WM_SYSKEYUP: { - Input::Instance().UpdateKey((int)wparam, (msg == WM_KEYDOWN) ? true : false); + bool down = msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN; + Input::Instance().UpdateKey((int)wparam, down); if (!app->transition_ && app->curr_scene_) { - Event evt((msg == WM_KEYDOWN) ? Event::KeyDown : Event::KeyUp); + Event evt(down ? Event::KeyDown : Event::KeyUp); evt.key.code = static_cast(wparam); evt.key.count = static_cast(lparam & 0xFF); @@ -374,6 +365,19 @@ namespace easy2d } break; + case WM_CHAR: + { + if (!app->transition_ && app->curr_scene_) + { + Event evt(Event::Char); + evt.key.c = static_cast(wparam); + evt.key.count = static_cast(lparam & 0xFF); + + app->curr_scene_->Dispatch(evt); + } + } + break; + case WM_LBUTTONUP: case WM_LBUTTONDOWN: //case WM_LBUTTONDBLCLK: @@ -426,7 +430,7 @@ namespace easy2d UINT width = LOWORD(lparam); UINT height = HIWORD(lparam); - Renderer::Instance().GetDeviceResources()->SetLogicalSize(Size{ (float)width, (float)height }); + Renderer::Instance().Resize(width, height); if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) { @@ -444,7 +448,7 @@ namespace easy2d app->curr_scene_->Dispatch(evt); } - Window::Instance().UpdateWindowRect(); + app->GetWindow()->UpdateWindowRect(); } } break; @@ -470,7 +474,7 @@ namespace easy2d E2D_LOG(active ? L"Window activated" : L"Window deactivated"); - Window::Instance().SetActive(active); + app->GetWindow()->SetActive(active); if (app->curr_scene_) { @@ -512,11 +516,10 @@ namespace easy2d { E2D_LOG(L"Window is closing"); - if (app->OnClosing()) + if (!app->OnClosing()) { - Window::Instance().Destroy(); + return 0; } - return 0; } break; diff --git a/src/core/Application.h b/src/core/Application.h index c764e5eb..28c3cad5 100644 --- a/src/core/Application.h +++ b/src/core/Application.h @@ -21,6 +21,7 @@ #pragma once #include "include-forwards.h" #include "time.h" +#include "window.h" #include "Component.h" namespace easy2d @@ -35,20 +36,10 @@ namespace easy2d bool vsync; // 垂直同步 bool fullscreen; // 全屏模式 - Options() - : title(L"Easy2D Game") - , width(640) - , height(480) - , icon(nullptr) - , clear_color(Color::Black) - , vsync(true) - , fullscreen(false) - {} - Options( - String const& title, - int width, - int height, + String const& title = L"Easy2D Game", + int width = 640, + int height = 480, LPCWSTR icon = nullptr, Color clear_color = Color::Black, bool vsync = true, @@ -128,16 +119,14 @@ namespace easy2d // 获取当前场景 ScenePtr const& GetCurrentScene(); + // 获取主窗口 + inline Window* GetWindow() const { return main_window_; } + // 设置时间缩放因子 void SetTimeScale( float scale_factor ); - // 设置消息预处理函数 - void SetPreMessageProc( - LRESULT (*proc)(HWND, UINT, WPARAM, LPARAM) - ); - // 显示调试信息 void ShowDebugInfo( bool show = true @@ -158,11 +147,13 @@ namespace easy2d bool inited_; float time_scale_; String app_name_; + ScenePtr curr_scene_; ScenePtr next_scene_; NodePtr debug_node_; TransitionPtr transition_; - Array components_; + Window* main_window_; + Array components_; }; } diff --git a/src/core/Color.h b/src/core/Color.h index 8185f1fa..812581a2 100644 --- a/src/core/Color.h +++ b/src/core/Color.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" namespace easy2d { diff --git a/src/core/Component.h b/src/core/Component.h index 60e3524c..3a89f380 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -22,10 +22,12 @@ namespace easy2d { + class Application; + class Component { public: - virtual void Setup() = 0; + virtual void Setup(Application*) = 0; virtual void Destroy() = 0; }; diff --git a/src/core/DebugNode.cpp b/src/core/DebugNode.cpp index cff72718..b2e20083 100644 --- a/src/core/DebugNode.cpp +++ b/src/core/DebugNode.cpp @@ -19,6 +19,7 @@ // THE SOFTWARE. #include "DebugNode.h" +#include "Text.h" #include "render.h" #include "../utils/string.h" #include diff --git a/src/core/DebugNode.h b/src/core/DebugNode.h index a8149a23..aee5a022 100644 --- a/src/core/DebugNode.h +++ b/src/core/DebugNode.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "Text.h" +#include "Node.h" #include "time.h" namespace easy2d diff --git a/src/core/Event.hpp b/src/core/Event.hpp index 75ed5910..18241b37 100644 --- a/src/core/Event.hpp +++ b/src/core/Event.hpp @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include "macros.h" #include "keys.hpp" namespace easy2d @@ -33,14 +32,17 @@ namespace easy2d bool left_btn_down; // 左键是否按下 bool right_btn_down; // 右键是否按下 - struct // Events::MouseDown | Events::MouseUp | Events::MouseClick + union { - int button; - }; + struct // Events::MouseDown | Events::MouseUp | Events::MouseClick + { + int button; + }; - struct // Events::MouseWheel - { - float wheel; + struct // Events::MouseWheel + { + float wheel; + }; }; static bool Check(UINT type); @@ -49,8 +51,19 @@ namespace easy2d // 键盘事件 struct KeyboardEvent { - int code; // enum KeyCode int count; + union + { + struct // Events::KeyDown | Events::KeyUp + { + int code; // enum KeyCode + }; + + struct // Events::Char + { + char c; + }; + }; static bool Check(UINT type); }; @@ -114,6 +127,7 @@ namespace easy2d KeyFirst, KeyDown, // 按键按下 KeyUp, // 按键抬起 + Char, // 输出字符 KeyLast, // 窗口消息 diff --git a/src/core/EventListener.h b/src/core/EventListener.h index 62ddb0bb..1630c0de 100644 --- a/src/core/EventListener.h +++ b/src/core/EventListener.h @@ -20,7 +20,7 @@ #pragma once #include "include-forwards.h" -#include "IntrusiveList.hpp" +#include "../common/IntrusiveList.hpp" #include "Event.hpp" namespace easy2d diff --git a/src/core/Geometry.h b/src/core/Geometry.h index aed3637f..7d070250 100644 --- a/src/core/Geometry.h +++ b/src/core/Geometry.h @@ -20,6 +20,7 @@ #pragma once #include "include-forwards.h" +#include namespace easy2d { diff --git a/src/core/Image.h b/src/core/Image.h index a335a77a..f544da0b 100644 --- a/src/core/Image.h +++ b/src/core/Image.h @@ -21,6 +21,7 @@ #pragma once #include "include-forwards.h" #include "Resource.h" +#include namespace easy2d { diff --git a/src/core/Input.h b/src/core/Input.h index c3066bcb..2a73cbcf 100644 --- a/src/core/Input.h +++ b/src/core/Input.h @@ -21,8 +21,8 @@ #pragma once #include "include-forwards.h" #include "keys.hpp" -#include "Singleton.hpp" #include "Component.h" +#include "../common/Singleton.hpp" namespace easy2d { @@ -58,7 +58,7 @@ namespace easy2d Point GetMousePos(); public: - void Setup() override {} + void Setup(Application*) override {} void Destroy() override {} diff --git a/src/core/Layer.cpp b/src/core/Layer.cpp new file mode 100644 index 00000000..4c552240 --- /dev/null +++ b/src/core/Layer.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2016-2018 Easy2D - 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 "Layer.h" +#include "render.h" + +namespace easy2d +{ + Layer::Layer() + { + SetSize(Renderer::Instance().GetOutputSize()); + + AddListener(Event::MouseBtnDown, Closure(this, &Layer::HandleMessages)); + AddListener(Event::MouseBtnUp, Closure(this, &Layer::HandleMessages)); + AddListener(Event::MouseMove, Closure(this, &Layer::HandleMessages)); + AddListener(Event::MouseWheel, Closure(this, &Layer::HandleMessages)); + + AddListener(Event::KeyDown, Closure(this, &Layer::HandleMessages)); + AddListener(Event::KeyUp, Closure(this, &Layer::HandleMessages)); + AddListener(Event::Char, Closure(this, &Layer::HandleMessages)); + } + + Layer::~Layer() + { + } + + void Layer::Dispatch(Event& evt) + { + if (!IsVisible()) + return; + + NodePtr prev; + for (auto child = children_.Last(); child; child = prev) + { + prev = child->PrevItem(); + child->Dispatch(evt); + } + + EventDispatcher::Dispatch(evt); + } + + void Layer::HandleMessages(Event const & evt) + { + switch (evt.type) + { + case Event::MouseBtnDown: + OnMouseButtonDown(evt.mouse.button, Point{ evt.mouse.x, evt.mouse.y }); + break; + case Event::MouseBtnUp: + OnMouseButtonUp(evt.mouse.button, Point{ evt.mouse.x, evt.mouse.y }); + break; + case Event::MouseMove: + OnMouseMoved(Point{ evt.mouse.x, evt.mouse.y }); + break; + case Event::MouseWheel: + OnMouseWheel(evt.mouse.wheel); + break; + case Event::KeyDown: + OnKeyDown(evt.key.code); + break; + case Event::KeyUp: + OnKeyUp(evt.key.code); + break; + case Event::Char: + OnChar(evt.key.c); + break; + } + } + +} diff --git a/src/math/rand.cpp b/src/core/Layer.h similarity index 68% rename from src/math/rand.cpp rename to src/core/Layer.h index 5f86ea55..8fdd6bcc 100644 --- a/src/math/rand.cpp +++ b/src/core/Layer.h @@ -18,21 +18,32 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "rand.h" +#pragma once +#include "Node.h" namespace easy2d { - namespace math + class E2D_API Layer + : public Node { - namespace - { - std::random_device device; - std::default_random_engine engine(device()); - } + public: + Layer(); - std::default_random_engine& GetRandomEngine() - { - return engine; - } - } + virtual ~Layer(); + + virtual void OnMouseButtonDown(int btn, Point const& p) {} + virtual void OnMouseButtonUp(int btn, Point const& p) {} + virtual void OnMouseMoved(Point const& p) {} + virtual void OnMouseWheel(float wheel) {} + + virtual void OnKeyDown(int key) {} + virtual void OnKeyUp(int key) {} + virtual void OnChar(char c) {} + + public: + void Dispatch(Event& evt) override; + + protected: + void HandleMessages(Event const& evt); + }; } diff --git a/src/core/Node.cpp b/src/core/Node.cpp index 1799e613..09a3bde8 100644 --- a/src/core/Node.cpp +++ b/src/core/Node.cpp @@ -48,6 +48,7 @@ namespace easy2d , dirty_transform_(false) , dirty_transform_inverse_(false) , parent_(nullptr) + , scene_(nullptr) , hash_name_(0) , z_order_(0) , opacity_(1.f) @@ -194,16 +195,6 @@ namespace easy2d return transform_matrix_inverse_; } - Node* Node::GetParent() const - { - return parent_; - } - - Scene* Node::GetScene() const - { - return scene_; - } - void Node::UpdateTransform() const { if (!dirty_transform_) @@ -237,12 +228,15 @@ namespace easy2d } } - void Node::SetScene(Scene * scene) + void Node::SetScene(Scene* scene) { - scene_ = scene; - for (Node* child = children_.First().Get(); child; child = child->NextItem().Get()) + if (scene && scene_ != scene) { - child->scene_ = scene; + scene_ = scene; + for (Node* child = children_.First().Get(); child; child = child->NextItem().Get()) + { + child->scene_ = scene; + } } } diff --git a/src/core/Node.h b/src/core/Node.h index 6c6f6dce..bbc59fd6 100644 --- a/src/core/Node.h +++ b/src/core/Node.h @@ -25,7 +25,6 @@ #include "TaskManager.h" #include "ActionManager.h" #include "EventDispatcher.h" -#include "IntrusiveList.hpp" namespace easy2d { @@ -37,10 +36,9 @@ namespace easy2d , public TaskManager , public ActionManager , public EventDispatcher - , protected IntrusiveListItem + , public IntrusiveListItem { friend class Application; - friend class Scene; friend class Transition; friend class IntrusiveList; @@ -56,9 +54,6 @@ namespace easy2d // 渲染节点 virtual void OnRender() {} - // 事件分发 - void Dispatch(Event& evt) override; - // 获取显示状态 bool IsVisible() const { return visible_; } @@ -135,10 +130,10 @@ namespace easy2d Matrix const& GetTransformInverseMatrix() const; // 获取父节点 - Node* GetParent() const; + inline Node* GetParent() const { return parent_; } // 获取所在场景 - Scene* GetScene() const; + inline Scene* GetScene() const { return scene_; } // 设置是否显示 void SetVisible( @@ -364,6 +359,10 @@ namespace easy2d float anchor_y ); + public: + // 事件分发 + void Dispatch(Event& evt) override; + protected: virtual void PrepareRender() {} @@ -402,6 +401,7 @@ namespace easy2d }; + // 可视化节点 class E2D_API VisualNode : public Node { diff --git a/src/core/Object.h b/src/core/Object.h index 53d6e0c6..4ec57cff 100644 --- a/src/core/Object.h +++ b/src/core/Object.h @@ -19,8 +19,7 @@ // THE SOFTWARE. #pragma once -#include "RefCounter.hpp" -#include "helper.hpp" +#include "helper.h" namespace easy2d { diff --git a/src/core/RefCounter.hpp b/src/core/RefCounter.hpp index df6992de..02482f2a 100644 --- a/src/core/RefCounter.hpp +++ b/src/core/RefCounter.hpp @@ -19,8 +19,8 @@ // THE SOFTWARE. #pragma once -#include "macros.h" -#include "noncopyable.hpp" +#include "../macros.h" +#include "../common/noncopyable.hpp" namespace easy2d { diff --git a/src/core/Resource.h b/src/core/Resource.h index ecf39447..61912ded 100644 --- a/src/core/Resource.h +++ b/src/core/Resource.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "helper.hpp" +#include "helper.h" namespace easy2d { diff --git a/src/core/Scene.cpp b/src/core/Scene.cpp index 42d95675..e43b53e3 100644 --- a/src/core/Scene.cpp +++ b/src/core/Scene.cpp @@ -19,14 +19,18 @@ // THE SOFTWARE. #include "Scene.h" -#include "Node.h" #include "logs.h" +#include "render.h" namespace easy2d { Scene::Scene() + : mouse_cursor_(MouseCursor::Arrow) + , last_mouse_cursor(MouseCursor(-1)) { scene_ = this; + + SetSize(Renderer::Instance().GetOutputSize()); } Scene::~Scene() @@ -43,4 +47,33 @@ namespace easy2d E2D_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/src/core/Scene.h b/src/core/Scene.h index 11e24dc1..89b8510d 100644 --- a/src/core/Scene.h +++ b/src/core/Scene.h @@ -37,5 +37,16 @@ namespace easy2d // 退出场景 virtual void OnExit(); + + public: + void Update(Duration dt); + + void SetMouseCursor( + MouseCursor cursor + ); + + protected: + MouseCursor mouse_cursor_; + MouseCursor last_mouse_cursor; }; } diff --git a/src/core/Task.h b/src/core/Task.h index 0ca3036f..2c439783 100644 --- a/src/core/Task.h +++ b/src/core/Task.h @@ -21,7 +21,7 @@ #pragma once #include "include-forwards.h" #include "time.h" -#include "IntrusiveList.hpp" +#include "../common/IntrusiveList.hpp" #include namespace easy2d diff --git a/src/core/Text.h b/src/core/Text.h index 1459d174..abb94a30 100644 --- a/src/core/Text.h +++ b/src/core/Text.h @@ -22,6 +22,7 @@ #include "Node.h" #include "Font.hpp" #include "TextStyle.hpp" +#include namespace easy2d { diff --git a/src/core/Transition.cpp b/src/core/Transition.cpp index e33b7acf..7f8eb3a7 100644 --- a/src/core/Transition.cpp +++ b/src/core/Transition.cpp @@ -77,7 +77,7 @@ namespace easy2d ); } - window_size_ = Window::Instance().GetSize(); + window_size_ = Renderer::Instance().GetOutputSize(); out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f }; } diff --git a/src/core/Transition.h b/src/core/Transition.h index e21f34a8..12d6a284 100644 --- a/src/core/Transition.h +++ b/src/core/Transition.h @@ -21,6 +21,7 @@ #pragma once #include "include-forwards.h" #include "time.h" +#include namespace easy2d { @@ -56,17 +57,17 @@ namespace easy2d virtual void Reset() { }; protected: - bool done_; - float process_; - Duration duration_; - Duration delta_; - Size window_size_; + bool done_; + float process_; + Duration duration_; + Duration delta_; + Size window_size_; ScenePtr out_scene_; ScenePtr in_scene_; - ComPtr out_layer_; - ComPtr in_layer_; - LayerProperties out_layer_prop_; - LayerProperties in_layer_prop_; + ComPtr out_layer_; + ComPtr in_layer_; + LayerProperties out_layer_prop_; + LayerProperties in_layer_prop_; }; diff --git a/src/core/helper.hpp b/src/core/helper.h similarity index 93% rename from src/core/helper.hpp rename to src/core/helper.h index fe5b5bb4..99bcbbc2 100644 --- a/src/core/helper.hpp +++ b/src/core/helper.h @@ -20,13 +20,8 @@ #pragma once #include "RefCounter.hpp" -#include "IntrusivePtr.hpp" -#include "ComPtr.hpp" -#include "Array.h" -#include "closure.hpp" -#include "../math/vector.hpp" -#include "../math/Rect.hpp" -#include "../math/Matrix.hpp" +#include "../common/Array.h" +#include "../common/IntrusivePtr.hpp" #include #include #include @@ -89,6 +84,7 @@ namespace easy2d E2D_DECLARE_SMART_PTR(Node); E2D_DECLARE_SMART_PTR(Scene); + E2D_DECLARE_SMART_PTR(Layer); E2D_DECLARE_SMART_PTR(Sprite); E2D_DECLARE_SMART_PTR(Text); E2D_DECLARE_SMART_PTR(Canvas); @@ -120,11 +116,8 @@ namespace easy2d E2D_DECLARE_SMART_PTR(MoveTransition); E2D_DECLARE_SMART_PTR(RotationTransition); - E2D_DECLARE_NS_SMART_PTR(ui, Button); - E2D_DECLARE_NS_SMART_PTR(ui, Menu); - - using namespace math; - using namespace ui; + E2D_DECLARE_SMART_PTR(Button); + E2D_DECLARE_SMART_PTR(Menu); } namespace easy2d diff --git a/src/core/include-forwards.h b/src/core/include-forwards.h index b790d13b..3f3ee450 100644 --- a/src/core/include-forwards.h +++ b/src/core/include-forwards.h @@ -19,14 +19,19 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "helper.h" #include "Color.h" #include "Object.h" -#include "helper.hpp" -#include "../DX/helper.hpp" +#include "../common/ComPtr.hpp" +#include "../common/Closure.hpp" +#include "../math/vector.hpp" +#include "../math/Rect.hpp" +#include "../math/Matrix.hpp" namespace easy2d { + using namespace math; + // 画笔样式 enum class StrokeStyle : int { @@ -44,6 +49,19 @@ namespace easy2d Right /* 右 */ }; + // 鼠标指针 + enum class MouseCursor : int + { + Arrow, /* 指针 */ + TextInput, /* 输入文本 */ + Hand, /* 手指 */ + SizeAll, + SizeNESW, + SizeNS, + SizeNWSE, + SizeWE, + }; + // 文字抗锯齿属性 enum class TextAntialias { diff --git a/src/core/keys.hpp b/src/core/keys.hpp index 2dd31a1b..9b611116 100644 --- a/src/core/keys.hpp +++ b/src/core/keys.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" namespace easy2d { @@ -54,6 +54,10 @@ namespace easy2d Esc = VK_ESCAPE, Ctrl = VK_CONTROL, Shift = VK_SHIFT, + Alt = VK_MENU, + Tab = VK_TAB, + Delete = VK_DELETE, + Back = VK_BACK, A = 0x41, B, diff --git a/src/core/logs.h b/src/core/logs.h index 744c8bb9..9b11ec0e 100644 --- a/src/core/logs.h +++ b/src/core/logs.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" #ifdef E2D_DISABLE_LOG_FUNCTIONS diff --git a/src/core/modules.h b/src/core/modules.h index c4da4995..9b677d33 100644 --- a/src/core/modules.h +++ b/src/core/modules.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" #include #include #include diff --git a/src/core/render.cpp b/src/core/render.cpp index 93b1beab..5bd1a278 100644 --- a/src/core/render.cpp +++ b/src/core/render.cpp @@ -21,6 +21,7 @@ #include "render.h" #include "logs.h" #include "Image.h" +#include "Application.h" namespace easy2d { @@ -29,7 +30,7 @@ namespace easy2d , antialias_(true) , vsync_(true) , text_antialias_(TextAntialias::ClearType) - , clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) + , clear_color_(Color::Black) , opacity_(1.f) , collecting_data_(false) { @@ -40,11 +41,14 @@ namespace easy2d { } - void Renderer::Setup() + void Renderer::Setup(Application* app) { E2D_LOG(L"Creating device resources"); - HRESULT hr = hwnd_ ? S_OK : E_FAIL; + HRESULT hr; + + hwnd_ = app->GetWindow()->GetHandle(); + hr = hwnd_ ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { @@ -74,6 +78,11 @@ namespace easy2d hr = CreateDeviceResources(); } + if (SUCCEEDED(hr)) + { + output_size_ = app->GetWindow()->GetSize(); + } + ThrowIfFailed(hr); } @@ -89,11 +98,6 @@ namespace easy2d device_resources_.Reset(); } - void Renderer::SetTargetWindow(HWND hwnd) - { - hwnd_ = hwnd; - } - HRESULT Renderer::CreateDeviceResources() { HRESULT hr = S_OK; @@ -344,6 +348,17 @@ namespace easy2d return S_OK; } + HRESULT Renderer::Resize(UINT width, UINT height) + { + output_size_.x = static_cast(width); + output_size_.y = static_cast(height); + if (device_resources_) + { + return device_resources_->SetLogicalSize(output_size_); + } + return S_OK; + } + void Renderer::StartCollectData() { collecting_data_ = true; @@ -356,7 +371,7 @@ namespace easy2d void Renderer::SetClearColor(const Color & color) { - clear_color_ = DX::ConvertToColorF(color); + clear_color_ = color; } HRESULT Renderer::SetTransform(const Matrix & matrix) diff --git a/src/core/render.h b/src/core/render.h index 7548c869..15f8a2dd 100644 --- a/src/core/render.h +++ b/src/core/render.h @@ -24,7 +24,7 @@ #include "Resource.h" #include "TextStyle.hpp" #include "Component.h" -#include "Singleton.hpp" +#include "../common/Singleton.hpp" #include "../DX/helper.hpp" #include "../DX/DeviceResources.h" #include "../DX/TextRenderer.h" @@ -130,13 +130,16 @@ namespace easy2d HRESULT PopLayer(); + HRESULT Resize( + UINT width, + UINT height + ); + public: - void Setup() override; + void Setup(Application*) override; void Destroy() override; - void SetTargetWindow(HWND); - void StartCollectData(); void StopCollectData(); @@ -145,6 +148,8 @@ namespace easy2d inline RenderStatus const& GetStatus() const { return status_; } + inline Size const& GetOutputSize() const { return output_size_; } + inline DeviceResources* GetDeviceResources() const { return device_resources_.Get(); } inline ITextRenderer* GetTextRenderer() const { return text_renderer_.Get(); } @@ -169,8 +174,9 @@ namespace easy2d bool vsync_; bool collecting_data_; + Size output_size_; + Color clear_color_; TextAntialias text_antialias_; - D2D1_COLOR_F clear_color_; RenderStatus status_; ComPtr device_resources_; diff --git a/src/core/time.h b/src/core/time.h index f3b41097..adb135d6 100644 --- a/src/core/time.h +++ b/src/core/time.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "macros.h" +#include "../macros.h" namespace easy2d { diff --git a/src/core/window.cpp b/src/core/window.cpp index 156ca4e8..691a4c65 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -49,6 +49,20 @@ namespace easy2d Window::~Window() { + if (is_fullscreen_) + RestoreResolution(device_name_); + + if (device_name_) + { + delete[] device_name_; + device_name_ = nullptr; + } + + if (handle_) + { + ::DestroyWindow(handle_); + handle_ = nullptr; + } } HRESULT Window::Create(String title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc) @@ -65,7 +79,7 @@ namespace easy2d wcex.hInstance = hinst; wcex.hbrBackground = nullptr; wcex.lpszMenuName = nullptr; - wcex.hCursor = ::LoadCursorW(nullptr, IDC_ARROW); + wcex.hCursor = nullptr; if (icon) { @@ -152,24 +166,6 @@ namespace easy2d return S_OK; } - void Window::Destroy() - { - if (is_fullscreen_) - RestoreResolution(device_name_); - - if (device_name_) - { - delete[] device_name_; - device_name_ = nullptr; - } - - if (handle_) - { - ::DestroyWindow(handle_); - handle_ = nullptr; - } - } - void Window::Prepare() { ::ShowWindow(handle_, SW_SHOWNORMAL); diff --git a/src/core/window.h b/src/core/window.h index 910042da..c5564537 100644 --- a/src/core/window.h +++ b/src/core/window.h @@ -20,15 +20,11 @@ #pragma once #include "include-forwards.h" -#include "Singleton.hpp" namespace easy2d { class E2D_API Window - : public Singleton { - E2D_DECLARE_SINGLETON(Window); - public: // 获取标题 String GetTitle() const; @@ -64,8 +60,6 @@ namespace easy2d WNDPROC proc ); - void Destroy(); - void Prepare(); HWND GetHandle() const; @@ -76,7 +70,7 @@ namespace easy2d void SetActive(bool actived); - protected: + public: Window(); ~Window(); diff --git a/src/dx/D3D11DeviceResources.cpp b/src/dx/D3D11DeviceResources.cpp index bfd7d8a2..6cf9a816 100644 --- a/src/dx/D3D11DeviceResources.cpp +++ b/src/dx/D3D11DeviceResources.cpp @@ -401,19 +401,18 @@ namespace easy2d return hr; } - void D3D11DeviceResources::SetLogicalSize(Size logical_size) + HRESULT D3D11DeviceResources::SetLogicalSize(Size logical_size) { if (logical_size_ != logical_size) { logical_size_ = logical_size; - ThrowIfFailed( - CreateWindowSizeDependentResources() - ); + return CreateWindowSizeDependentResources(); } + return S_OK; } - void D3D11DeviceResources::SetDpi(float dpi) + HRESULT D3D11DeviceResources::SetDpi(float dpi) { if (dpi != dpi_) { @@ -427,10 +426,9 @@ namespace easy2d GetD2DDeviceContext()->SetDpi(dpi_, dpi_); - ThrowIfFailed( - CreateWindowSizeDependentResources() - ); + return CreateWindowSizeDependentResources(); } + return S_OK; } } diff --git a/src/dx/D3D11DeviceResources.h b/src/dx/D3D11DeviceResources.h index fcfc03dc..60b3f6a7 100644 --- a/src/dx/D3D11DeviceResources.h +++ b/src/dx/D3D11DeviceResources.h @@ -39,11 +39,11 @@ namespace easy2d HRESULT HandleDeviceLost(); - void SetLogicalSize( + HRESULT SetLogicalSize( Size logical_size ); - void SetDpi( + HRESULT SetDpi( float dpi ); diff --git a/src/dx/DeviceResources.h b/src/dx/DeviceResources.h index 32717345..1a8598d7 100644 --- a/src/dx/DeviceResources.h +++ b/src/dx/DeviceResources.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/macros.h" +#include "../macros.h" #if defined(E2D_USE_DIRECTX10) # include "D3D10DeviceResources.h" diff --git a/src/dx/helper.hpp b/src/dx/helper.hpp index b99d4197..a5b1b614 100644 --- a/src/dx/helper.hpp +++ b/src/dx/helper.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/ComPtr.hpp" +#include "../common/ComPtr.hpp" #include "../core/Color.h" #include "../math/vector.hpp" #include "../math/Rect.hpp" diff --git a/src/easy2d.h b/src/easy2d.h index 071981cf..882dcc64 100644 --- a/src/easy2d.h +++ b/src/easy2d.h @@ -25,12 +25,13 @@ #pragma once +#include "macros.h" + // // core // -#include "core/macros.h" #include "core/modules.h" #include "core/render.h" #include "core/window.h" @@ -64,6 +65,7 @@ #include "core/Node.h" #include "core/Scene.h" +#include "core/Layer.h" #include "core/Sprite.h" #include "core/Text.h" #include "core/Canvas.h" diff --git a/src/core/macros.h b/src/macros.h similarity index 100% rename from src/core/macros.h rename to src/macros.h diff --git a/src/math/constants.hpp b/src/math/constants.hpp index b7570545..7f4f2478 100644 --- a/src/math/constants.hpp +++ b/src/math/constants.hpp @@ -20,25 +20,19 @@ #pragma once -#if _MSC_VER >= 1900 -# define E2D_CONSTEXPR constexpr -#else -# define E2D_CONSTEXPR const -#endif - namespace easy2d { namespace math { namespace constants { - E2D_CONSTEXPR auto PI_F = 3.141592653589793f; - E2D_CONSTEXPR auto PI_F_2 = 1.570796326794896f; - E2D_CONSTEXPR auto PI_F_X_2 = 6.283185307179586f; + const auto PI_F = 3.141592653589793f; + const auto PI_F_2 = 1.570796326794896f; + const auto PI_F_X_2 = 6.283185307179586f; - E2D_CONSTEXPR auto PI_D = 3.14159265358979323846; - E2D_CONSTEXPR auto PI_D_2 = 1.57079632679489661923; - E2D_CONSTEXPR auto PI_D_X_2 = 6.28318530717958647692; + const auto PI_D = 3.14159265358979323846; + const auto PI_D_2 = 1.57079632679489661923; + const auto PI_D_X_2 = 6.28318530717958647692; } } } diff --git a/src/math/rand.h b/src/math/rand.h index f989b8f3..0f1c229c 100644 --- a/src/math/rand.h +++ b/src/math/rand.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include "../core/macros.h" #include namespace easy2d @@ -34,65 +33,94 @@ namespace easy2d // 产生的随机数类型取决于参数的类型, 如获取随机浮点数: // double d = math::Rand(1.2, 1.5); // - - E2D_API std::default_random_engine& GetRandomEngine(); - template - static T RandomInt(T min, T max) - { - std::uniform_int_distribution dist(min, max); - return dist(GetRandomEngine()); - } + int Rand(int min, int max); - template - static T RandomReal(T min, T max) + unsigned int Rand(unsigned int min, unsigned int max); + + long Rand(long min, long max); + + unsigned long Rand(unsigned long min, unsigned long max); + + char Rand(char min, char max); + + unsigned char Rand(unsigned char min, unsigned char max); + + float Rand(float min, float max); + + double Rand(double min, double max); + + + // + // Details of math::Rand + // + + namespace __rand_detail { - std::uniform_real_distribution dist(min, max); - return dist(GetRandomEngine()); + inline std::default_random_engine& GetRandomEngine() + { + static std::random_device device; + static std::default_random_engine engine(device()); + return engine; + } + + template + inline T RandomInt(T min, T max) + { + std::uniform_int_distribution dist(min, max); + return dist(GetRandomEngine()); + } + + template + inline T RandomReal(T min, T max) + { + std::uniform_real_distribution dist(min, max); + return dist(GetRandomEngine()); + } } inline int Rand(int min, int max) { - return RandomInt(min, max); + return __rand_detail::RandomInt(min, max); } inline unsigned int Rand(unsigned int min, unsigned int max) { - return RandomInt(min, max); + return __rand_detail::RandomInt(min, max); } inline long Rand(long min, long max) { - return RandomInt(min, max); + return __rand_detail::RandomInt(min, max); } inline unsigned long Rand(unsigned long min, unsigned long max) { - return RandomInt(min, max); + return __rand_detail::RandomInt(min, max); } inline char Rand(char min, char max) { return static_cast( - RandomInt(static_cast(min), static_cast(max)) + __rand_detail::RandomInt(static_cast(min), static_cast(max)) ); } inline unsigned char Rand(unsigned char min, unsigned char max) { return static_cast( - RandomInt(static_cast(min), static_cast(max)) + __rand_detail::RandomInt(static_cast(min), static_cast(max)) ); } inline float Rand(float min, float max) { - return RandomReal(min, max); + return __rand_detail::RandomReal(min, max); } inline double Rand(double min, double max) { - return RandomReal(min, max); + return __rand_detail::RandomReal(min, max); } } } \ No newline at end of file diff --git a/src/ui/Button.cpp b/src/ui/Button.cpp index cfa92ab5..00aee1aa 100644 --- a/src/ui/Button.cpp +++ b/src/ui/Button.cpp @@ -19,121 +19,121 @@ // THE SOFTWARE. #include "Button.h" +#include "../core/Scene.h" namespace easy2d { - namespace ui + Button::Button() + : enabled_(true) + , is_selected_(false) + , click_callback_(nullptr) + , status_(Status::Normal) { - Button::Button() - : enabled_(true) - , is_selected_(false) - , click_callback_(nullptr) - , status_(Status::Normal) - { - SetResponsible(true); - - AddListener(Event::MouseHover, Closure(this, &Button::UpdateStatus)); - AddListener(Event::MouseOut, Closure(this, &Button::UpdateStatus)); - AddListener(Event::MouseBtnDown, Closure(this, &Button::UpdateStatus)); - AddListener(Event::MouseBtnUp, Closure(this, &Button::UpdateStatus)); - } - - Button::Button(const Callback& click) - : Button() - { - this->SetClickCallback(click); - } - - Button::Button(Callback const & click, Callback const & pressed, Callback const & mouse_over, Callback const & mouse_out) - : Button() - { - this->SetClickCallback(click); - this->SetPressedCallback(pressed); - this->SetMouseOverCallback(mouse_over); - this->SetMouseOutCallback(mouse_out); - } - - Button::~Button() - { - } - - bool Button::IsEnable() const - { - return enabled_; - } - - void Button::SetEnabled(bool enabled) - { - if (enabled_ != enabled) - { - enabled_ = enabled; - } - } - - void Button::SetClickCallback(const Callback& func) - { - click_callback_ = func; - } - - void Button::SetPressedCallback(const Callback & func) - { - pressed_callback_ = func; - } - - void Button::SetMouseOverCallback(const Callback & func) - { - mouse_over_callback_ = func; - } - - void Button::SetMouseOutCallback(const Callback & func) - { - mouse_out_callback_ = func; - } - - void Button::SetStatus(Status status) - { - if (status_ != status) - { - status_ = status; - } - } - - void Button::UpdateStatus(Event const& evt) - { - E2D_ASSERT(MouseEvent::Check(evt.type)); - - if (enabled_ && (evt.target == this)) - { - if (evt.type == Event::MouseHover) - { - SetStatus(Status::Hover); - - if (mouse_over_callback_) - mouse_over_callback_(); - } - else if (evt.type == Event::MouseOut) - { - SetStatus(Status::Normal); - - if (mouse_out_callback_) - mouse_out_callback_(); - } - else if (evt.type == Event::MouseBtnDown && status_ == Status::Hover) - { - SetStatus(Status::Pressed); - - if (pressed_callback_) - pressed_callback_(); - } - else if (evt.type == Event::MouseBtnUp && status_ == Status::Pressed) - { - SetStatus(Status::Hover); - - if (click_callback_) - click_callback_(); - } - } - } + SetResponsible(true); + AddListener(Event::MouseHover, Closure(this, &Button::UpdateStatus)); + AddListener(Event::MouseOut, Closure(this, &Button::UpdateStatus)); + AddListener(Event::MouseBtnDown, Closure(this, &Button::UpdateStatus)); + AddListener(Event::MouseBtnUp, Closure(this, &Button::UpdateStatus)); } + + Button::Button(const Callback& click) + : Button() + { + this->SetClickCallback(click); + } + + Button::Button(Callback const & click, Callback const & pressed, Callback const & mouse_over, Callback const & mouse_out) + : Button() + { + this->SetClickCallback(click); + this->SetPressedCallback(pressed); + this->SetMouseOverCallback(mouse_over); + this->SetMouseOutCallback(mouse_out); + } + + Button::~Button() + { + } + + bool Button::IsEnable() const + { + return enabled_; + } + + void Button::SetEnabled(bool enabled) + { + if (enabled_ != enabled) + { + enabled_ = enabled; + } + } + + void Button::SetClickCallback(const Callback& func) + { + click_callback_ = func; + } + + void Button::SetPressedCallback(const Callback & func) + { + pressed_callback_ = func; + } + + void Button::SetMouseOverCallback(const Callback & func) + { + mouse_over_callback_ = func; + } + + void Button::SetMouseOutCallback(const Callback & func) + { + mouse_out_callback_ = func; + } + + void Button::SetStatus(Status status) + { + if (status_ != status) + { + status_ = status; + } + } + + void Button::UpdateStatus(Event const& evt) + { + E2D_ASSERT(MouseEvent::Check(evt.type)); + + if (enabled_ && (evt.target == this)) + { + if (evt.type == Event::MouseHover) + { + SetStatus(Status::Hover); + GetScene()->SetMouseCursor(MouseCursor::Hand); + + if (mouse_over_callback_) + mouse_over_callback_(); + } + else if (evt.type == Event::MouseOut) + { + SetStatus(Status::Normal); + GetScene()->SetMouseCursor(MouseCursor::Arrow); + + if (mouse_out_callback_) + mouse_out_callback_(); + } + else if (evt.type == Event::MouseBtnDown && status_ == Status::Hover) + { + SetStatus(Status::Pressed); + + if (pressed_callback_) + pressed_callback_(); + } + else if (evt.type == Event::MouseBtnUp && status_ == Status::Pressed) + { + SetStatus(Status::Hover); + + if (click_callback_) + click_callback_(); + } + } + } + } \ No newline at end of file diff --git a/src/ui/Button.h b/src/ui/Button.h index f0969793..e94c879c 100644 --- a/src/ui/Button.h +++ b/src/ui/Button.h @@ -24,74 +24,71 @@ namespace easy2d { - namespace ui + class E2D_API Button + : public Sprite { - class E2D_API Button - : public Sprite - { - using Callback = std::function; + using Callback = std::function; - public: - Button(); + public: + Button(); - explicit Button( - Callback const& click /* 按钮点击回调函数 */ - ); + explicit Button( + Callback const& click /* 按钮点击回调函数 */ + ); - explicit Button( - Callback const& click, /* 按钮点击回调函数 */ - Callback const& pressed, /* 按钮按下回调函数 */ - Callback const& mouse_over, /* 按钮移入回调函数 */ - Callback const& mouse_out /* 按钮移出回调函数 */ - ); + explicit Button( + Callback const& click, /* 按钮点击回调函数 */ + Callback const& pressed, /* 按钮按下回调函数 */ + Callback const& mouse_over, /* 按钮移入回调函数 */ + Callback const& mouse_out /* 按钮移出回调函数 */ + ); - virtual ~Button(); + virtual ~Button(); - // 获取按钮状态是启用还是禁用 - bool IsEnable() const; + // 获取按钮状态是启用还是禁用 + bool IsEnable() const; - // 设置按钮启用或禁用 - void SetEnabled( - bool enabled - ); + // 设置按钮启用或禁用 + void SetEnabled( + bool enabled + ); - // 设置按钮点击后的回调函数 - void SetClickCallback( - const Callback& func - ); + // 设置按钮点击后的回调函数 + void SetClickCallback( + const Callback& func + ); - // 设置按钮被按下时的回调函数 - void SetPressedCallback( - const Callback& func - ); + // 设置按钮被按下时的回调函数 + void SetPressedCallback( + const Callback& func + ); - // 设置鼠标移入按钮时的回调函数 - void SetMouseOverCallback( - const Callback& func - ); + // 设置鼠标移入按钮时的回调函数 + void SetMouseOverCallback( + const Callback& func + ); - // 设置鼠标移出按钮时的回调函数 - void SetMouseOutCallback( - const Callback& func - ); + // 设置鼠标移出按钮时的回调函数 + void SetMouseOutCallback( + const Callback& func + ); - private: - enum class Status { Normal, Hover, Pressed }; + private: + enum class Status { Normal, Hover, Pressed }; - void SetStatus( - Status status - ); + void SetStatus( + Status status + ); - void UpdateStatus(Event const& evt); + void UpdateStatus(Event const& evt); - private: - bool enabled_; - bool is_selected_; - Status status_; - Callback click_callback_; - Callback pressed_callback_; - Callback mouse_over_callback_; - Callback mouse_out_callback_; - }; - } + private: + bool enabled_; + bool is_selected_; + Status status_; + Callback click_callback_; + Callback pressed_callback_; + Callback mouse_over_callback_; + Callback mouse_out_callback_; + }; } \ No newline at end of file diff --git a/src/ui/Menu.cpp b/src/ui/Menu.cpp index 181de680..b4ab69f5 100644 --- a/src/ui/Menu.cpp +++ b/src/ui/Menu.cpp @@ -22,81 +22,79 @@ namespace easy2d { - namespace ui + Menu::Menu() + : enabled_(true) { - Menu::Menu() - : enabled_(true) - { - } + } - Menu::Menu(Array const& buttons) - : enabled_(true) + Menu::Menu(Array const& buttons) + : enabled_(true) + { + for (const auto& button : buttons) { - for (const auto& button : buttons) + this->AddButton(button); + } + } + + bool Menu::IsEnable() const + { + return enabled_; + } + + int Menu::GetButtonCount() const + { + return buttons_.size(); + } + + void Menu::SetEnabled(bool enabled) + { + if (enabled_ != enabled) + { + enabled_ = enabled; + + for (const auto& button : buttons_) { - this->AddButton(button); + button->SetEnabled(enabled); } } + } - bool Menu::IsEnable() const + void Menu::AddButton(ButtonPtr const& button) + { + if (button) { - return enabled_; + this->AddChild(button); + buttons_.push_back(button); + button->SetEnabled(enabled_); } + } - int Menu::GetButtonCount() const + bool Menu::RemoveButton(ButtonPtr const& button) + { + if (buttons_.empty()) { - return buttons_.size(); - } - - void Menu::SetEnabled(bool enabled) - { - if (enabled_ != enabled) - { - enabled_ = enabled; - - for (const auto& button : buttons_) - { - button->SetEnabled(enabled); - } - } - } - - void Menu::AddButton(ButtonPtr const& button) - { - if (button) - { - this->AddChild(button); - buttons_.push_back(button); - button->SetEnabled(enabled_); - } - } - - bool Menu::RemoveButton(ButtonPtr const& button) - { - if (buttons_.empty()) - { - return false; - } - - this->RemoveChild(button); - - if (button) - { - auto iter = std::find(buttons_.begin(), buttons_.end(), button); - if (iter != buttons_.end()) - { - // 移除按钮前,将它启用 - button->SetEnabled(true); - buttons_.erase(iter); - return true; - } - } return false; } - Array const& Menu::GetAllButtons() const + this->RemoveChild(button); + + if (button) { - return buttons_; + auto iter = std::find(buttons_.begin(), buttons_.end(), button); + if (iter != buttons_.end()) + { + // 移除按钮前,将它启用 + button->SetEnabled(true); + buttons_.erase(iter); + return true; + } } + return false; } + + Array const& Menu::GetAllButtons() const + { + return buttons_; + } + } \ No newline at end of file diff --git a/src/ui/Menu.h b/src/ui/Menu.h index 172ac8b2..b3d8ecee 100644 --- a/src/ui/Menu.h +++ b/src/ui/Menu.h @@ -23,46 +23,44 @@ namespace easy2d { - namespace ui + // 菜单 + class E2D_API Menu + : public Node { - // 菜单 - class E2D_API Menu - : public Node - { - public: - Menu(); + public: + Menu(); - explicit Menu( - Array const& buttons /* 按钮数组 */ - ); + explicit Menu( + Array const& buttons /* 按钮数组 */ + ); - // 获取菜单是否禁用 - bool IsEnable() const; + // 获取菜单是否禁用 + bool IsEnable() const; - // 获取菜单中的按钮数量 - int GetButtonCount() const; + // 获取菜单中的按钮数量 + int GetButtonCount() const; - // 设置菜单启用或禁用 - void SetEnabled( - bool enabled - ); + // 设置菜单启用或禁用 + void SetEnabled( + bool enabled + ); - // 添加按钮 - void AddButton( - ButtonPtr const& button - ); + // 添加按钮 + void AddButton( + ButtonPtr const& button + ); - // 移除按钮 - bool RemoveButton( - ButtonPtr const& button - ); + // 移除按钮 + bool RemoveButton( + ButtonPtr const& button + ); - // 获取所有按钮 - Array const& GetAllButtons() const; + // 获取所有按钮 + Array const& GetAllButtons() const; + + private: + bool enabled_; + Array buttons_; + }; - private: - bool enabled_; - Array buttons_; - }; - } } \ No newline at end of file diff --git a/src/utils/Data.h b/src/utils/Data.h index 3130ef56..c4a63142 100644 --- a/src/utils/Data.h +++ b/src/utils/Data.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/helper.hpp" +#include "../core/helper.h" namespace easy2d { diff --git a/src/utils/File.h b/src/utils/File.h index 55b5d80a..6ea9c288 100644 --- a/src/utils/File.h +++ b/src/utils/File.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/helper.hpp" +#include "../core/helper.h" #include "../core/Resource.h" namespace easy2d diff --git a/src/utils/Path.cpp b/src/utils/Path.cpp index 643ff51f..7164cd38 100644 --- a/src/utils/Path.cpp +++ b/src/utils/Path.cpp @@ -62,15 +62,10 @@ namespace easy2d { // 设置数据的保存路径 String local_app_data_path = Path::GetLocalAppDataPath(); - String title = Window::Instance().GetTitle(); - String folder_name = std::to_wstring(std::hash{}(title)); if (!local_app_data_path.empty()) { - data_path.append(local_app_data_path) - .append(L"\\Easy2DGameData\\") - .append(folder_name) - .append(L"\\"); + data_path.append(local_app_data_path).append(L"\\Easy2DGameData\\"); File file(data_path); if (!file.Exists() && !CreateFolder(data_path)) @@ -90,15 +85,10 @@ namespace easy2d { // 设置临时文件保存路径 wchar_t path[_MAX_PATH]; - String title = Window::Instance().GetTitle(); - String folder_name = std::to_wstring(std::hash{}(title)); if (0 != ::GetTempPath(_MAX_PATH, path)) { - temp_path.append(path) - .append(L"\\Easy2DGameTemp\\") - .append(folder_name) - .append(L"\\"); + temp_path.append(path).append(L"\\Easy2DGameTemp\\"); File file(temp_path); if (!file.Exists() && !CreateFolder(temp_path)) diff --git a/src/utils/Path.h b/src/utils/Path.h index 1f13a4fa..98e45d8b 100644 --- a/src/utils/Path.h +++ b/src/utils/Path.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/helper.hpp" +#include "../core/helper.h" namespace easy2d { diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 87529b6d..abf0d382 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -19,7 +19,6 @@ // THE SOFTWARE. #include "string.h" -#include "../core/macros.h" #include "../core/logs.h" namespace easy2d diff --git a/src/utils/string.h b/src/utils/string.h index 48155cb6..28b951bd 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/macros.h" +#include "../macros.h" #include namespace easy2d