add ImGui Component

minor

minor

refactoring
This commit is contained in:
Nomango 2019-03-12 00:27:54 +08:00 committed by Nomango
parent b1b1f0c22c
commit 8eb3f9887c
82 changed files with 1163 additions and 935 deletions

View File

@ -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);

View File

@ -7,19 +7,23 @@
<ClInclude Include="..\..\src\audio\Player.h" />
<ClInclude Include="..\..\src\audio\Transcoder.h" />
<ClInclude Include="..\..\src\audio\Voice.h" />
<ClInclude Include="..\..\src\common\Array.h" />
<ClInclude Include="..\..\src\common\closure.hpp" />
<ClInclude Include="..\..\src\common\ComPtr.hpp" />
<ClInclude Include="..\..\src\common\IntrusiveList.hpp" />
<ClInclude Include="..\..\src\common\IntrusivePtr.hpp" />
<ClInclude Include="..\..\src\common\noncopyable.hpp" />
<ClInclude Include="..\..\src\common\Singleton.hpp" />
<ClInclude Include="..\..\src\config.h" />
<ClInclude Include="..\..\src\core\Action.h" />
<ClInclude Include="..\..\src\core\ActionGroup.h" />
<ClInclude Include="..\..\src\core\ActionHelper.h" />
<ClInclude Include="..\..\src\core\ActionTween.h" />
<ClInclude Include="..\..\src\core\ActionManager.h" />
<ClInclude Include="..\..\src\core\Animation.h" />
<ClInclude Include="..\..\src\core\Array.h" />
<ClInclude Include="..\..\src\core\Canvas.h" />
<ClInclude Include="..\..\src\core\closure.hpp" />
<ClInclude Include="..\..\src\core\Color.h" />
<ClInclude Include="..\..\src\core\Component.h" />
<ClInclude Include="..\..\src\core\ComPtr.hpp" />
<ClInclude Include="..\..\src\core\config.h" />
<ClInclude Include="..\..\src\core\DebugNode.h" />
<ClInclude Include="..\..\src\core\Event.hpp" />
<ClInclude Include="..\..\src\core\EventDispatcher.h" />
@ -29,24 +33,20 @@
<ClInclude Include="..\..\src\core\Application.h" />
<ClInclude Include="..\..\src\core\Geometry.h" />
<ClInclude Include="..\..\src\core\GeometryNode.h" />
<ClInclude Include="..\..\src\core\helper.hpp" />
<ClInclude Include="..\..\src\core\helper.h" />
<ClInclude Include="..\..\src\core\Image.h" />
<ClInclude Include="..\..\src\core\include-forwards.h" />
<ClInclude Include="..\..\src\core\Input.h" />
<ClInclude Include="..\..\src\core\IntrusiveList.hpp" />
<ClInclude Include="..\..\src\core\IntrusivePtr.hpp" />
<ClInclude Include="..\..\src\core\keys.hpp" />
<ClInclude Include="..\..\src\core\Layer.h" />
<ClInclude Include="..\..\src\core\logs.h" />
<ClInclude Include="..\..\src\core\macros.h" />
<ClInclude Include="..\..\src\core\modules.h" />
<ClInclude Include="..\..\src\core\Node.h" />
<ClInclude Include="..\..\src\core\noncopyable.hpp" />
<ClInclude Include="..\..\src\core\Object.h" />
<ClInclude Include="..\..\src\core\RefCounter.hpp" />
<ClInclude Include="..\..\src\core\render.h" />
<ClInclude Include="..\..\src\core\Resource.h" />
<ClInclude Include="..\..\src\core\Scene.h" />
<ClInclude Include="..\..\src\core\Singleton.hpp" />
<ClInclude Include="..\..\src\core\Sprite.h" />
<ClInclude Include="..\..\src\core\Task.h" />
<ClInclude Include="..\..\src\core\TaskManager.h" />
@ -63,6 +63,7 @@
<ClInclude Include="..\..\src\dx\helper.hpp" />
<ClInclude Include="..\..\src\dx\TextRenderer.h" />
<ClInclude Include="..\..\src\easy2d.h" />
<ClInclude Include="..\..\src\macros.h" />
<ClInclude Include="..\..\src\math\constants.hpp" />
<ClInclude Include="..\..\src\math\ease.hpp" />
<ClInclude Include="..\..\src\math\Matrix.hpp" />
@ -101,6 +102,7 @@
<ClCompile Include="..\..\src\core\GeometryNode.cpp" />
<ClCompile Include="..\..\src\core\Image.cpp" />
<ClCompile Include="..\..\src\core\Input.cpp" />
<ClCompile Include="..\..\src\core\Layer.cpp" />
<ClCompile Include="..\..\src\core\logs.cpp" />
<ClCompile Include="..\..\src\core\modules.cpp" />
<ClCompile Include="..\..\src\core\Node.cpp" />
@ -119,7 +121,6 @@
<ClCompile Include="..\..\src\dx\D3D10DeviceResources.cpp" />
<ClCompile Include="..\..\src\dx\D3D11DeviceResources.cpp" />
<ClCompile Include="..\..\src\dx\TextRenderer.cpp" />
<ClCompile Include="..\..\src\math\rand.cpp" />
<ClCompile Include="..\..\src\ui\Button.cpp" />
<ClCompile Include="..\..\src\ui\Menu.cpp" />
<ClCompile Include="..\..\src\utils\Data.cpp" />

View File

@ -19,6 +19,9 @@
<Filter Include="audio">
<UniqueIdentifier>{836608a6-7443-48f9-8acd-18d3ba664348}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{86e2d0f2-a9d0-4456-b6a5-d480228bbf82}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\easy2d.h" />
@ -40,9 +43,6 @@
<ClInclude Include="..\..\src\core\logs.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\macros.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\modules.h">
<Filter>core</Filter>
</ClInclude>
@ -100,9 +100,6 @@
<ClInclude Include="..\..\src\ui\Menu.h">
<Filter>ui</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\Singleton.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\RefCounter.hpp">
<Filter>core</Filter>
</ClInclude>
@ -121,9 +118,6 @@
<ClInclude Include="..\..\src\core\Transform.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\noncopyable.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\utils\string.h">
<Filter>utils</Filter>
</ClInclude>
@ -154,9 +148,6 @@
<ClInclude Include="..\..\src\core\Object.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\helper.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\keys.hpp">
<Filter>core</Filter>
</ClInclude>
@ -178,27 +169,12 @@
<ClInclude Include="..\..\src\core\Event.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\IntrusiveList.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\IntrusivePtr.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\closure.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\ActionGroup.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\ActionHelper.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\Array.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\config.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\Action.h">
<Filter>core</Filter>
</ClInclude>
@ -244,7 +220,33 @@
<ClInclude Include="..\..\src\audio\audio-modules.h">
<Filter>audio</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\ComPtr.hpp">
<ClInclude Include="..\..\src\core\Layer.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\config.h" />
<ClInclude Include="..\..\src\macros.h" />
<ClInclude Include="..\..\src\common\Array.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\closure.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\ComPtr.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\IntrusiveList.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\IntrusivePtr.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\noncopyable.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\Singleton.hpp">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\helper.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup>
@ -297,9 +299,6 @@
<ClCompile Include="..\..\src\core\window.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\math\rand.cpp">
<Filter>math</Filter>
</ClCompile>
<ClCompile Include="..\..\src\utils\Data.cpp">
<Filter>utils</Filter>
</ClCompile>
@ -393,5 +392,8 @@
<ClCompile Include="..\..\src\audio\audio-modules.cpp">
<Filter>audio</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\Layer.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -136,8 +136,9 @@
<ClCompile Include="..\..\3rd-party\ImGui\imgui_demo.cpp" />
<ClCompile Include="..\..\3rd-party\ImGui\imgui_draw.cpp" />
<ClCompile Include="..\..\3rd-party\ImGui\imgui_widgets.cpp" />
<ClCompile Include="imgui_impl_dx11.cpp" />
<ClCompile Include="imgui_impl_win32.cpp" />
<ClCompile Include="easy2d-imgui\ImGuiLayer.cpp" />
<ClCompile Include="easy2d-imgui\ImGuiView.cpp" />
<ClCompile Include="easy2d-imgui\imgui_impl_dx11.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
@ -147,8 +148,10 @@
<ClInclude Include="..\..\3rd-party\ImGui\imstb_rectpack.h" />
<ClInclude Include="..\..\3rd-party\ImGui\imstb_textedit.h" />
<ClInclude Include="..\..\3rd-party\ImGui\imstb_truetype.h" />
<ClInclude Include="imgui_impl_dx11.h" />
<ClInclude Include="imgui_impl_win32.h" />
<ClInclude Include="easy2d-imgui\easy2d-imgui.h" />
<ClInclude Include="easy2d-imgui\ImGuiLayer.h" />
<ClInclude Include="easy2d-imgui\ImGuiView.h" />
<ClInclude Include="easy2d-imgui\imgui_impl_dx11.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Easy2D\Easy2D.vcxproj">

View File

@ -2,8 +2,6 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="imgui_impl_win32.cpp" />
<ClCompile Include="imgui_impl_dx11.cpp" />
<ClCompile Include="..\..\3rd-party\ImGui\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
@ -16,10 +14,17 @@
<ClCompile Include="..\..\3rd-party\ImGui\imgui_widgets.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="easy2d-imgui\imgui_impl_dx11.cpp">
<Filter>easy2d-imgui</Filter>
</ClCompile>
<ClCompile Include="easy2d-imgui\ImGuiLayer.cpp">
<Filter>easy2d-imgui</Filter>
</ClCompile>
<ClCompile Include="easy2d-imgui\ImGuiView.cpp">
<Filter>easy2d-imgui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="imgui_impl_win32.h" />
<ClInclude Include="imgui_impl_dx11.h" />
<ClInclude Include="..\..\3rd-party\ImGui\imconfig.h">
<Filter>imgui</Filter>
</ClInclude>
@ -38,10 +43,25 @@
<ClInclude Include="..\..\3rd-party\ImGui\imstb_truetype.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="easy2d-imgui\imgui_impl_dx11.h">
<Filter>easy2d-imgui</Filter>
</ClInclude>
<ClInclude Include="easy2d-imgui\ImGuiLayer.h">
<Filter>easy2d-imgui</Filter>
</ClInclude>
<ClInclude Include="easy2d-imgui\ImGuiView.h">
<Filter>easy2d-imgui</Filter>
</ClInclude>
<ClInclude Include="easy2d-imgui\easy2d-imgui.h">
<Filter>easy2d-imgui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{24ae99cd-ee12-481f-bb03-d8be40d99342}</UniqueIdentifier>
</Filter>
<Filter Include="easy2d-imgui">
<UniqueIdentifier>{37f1585a-e992-454a-8cac-e9a6142b08b6}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,165 @@
// Copyright (C) 2019 Nomango
#include "easy2d-imgui.h"
namespace easy2d
{
namespace
{
Map<int, int> 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();
}
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2019 Nomango
#pragma once
namespace easy2d
{
E2D_DECLARE_SMART_PTR(ImGuiLayer);
using ImGuiPipeline = std::function<void()>;
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<String, ImGuiPipeline> pipelines_;
};
}

View File

@ -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());
}
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2019 Nomango
#pragma once
namespace easy2d
{
class ImGuiView
: public Singleton<ImGuiView>
, public Component
{
E2D_DECLARE_SINGLETON(ImGuiView);
public:
void Setup(Application* app) override;
void Destroy() override;
public:
void Init(HWND hwnd);
void NewFrame();
void Render();
};
}

View File

@ -0,0 +1,9 @@
// Copyright (C) 2019 Nomango
#pragma once
#include "easy2d.h"
#include "ImGuiView.h"
#include "ImGuiLayer.h"
// ImGui
#include "imgui.h"

View File

@ -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 <windows.h>
#include <tchar.h>
// 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 *)&current_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;
}

View File

@ -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 <windows.h> 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);
*/

View File

@ -1,11 +1,8 @@
// ImGui
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_dx11.h"
#include <tchar.h>
// 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

View File

@ -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);

View File

@ -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"

View File

@ -19,8 +19,8 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include "../core/noncopyable.hpp"
#include "../macros.h"
#include "../common/noncopyable.hpp"
#include <xaudio2.h>
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include "../macros.h"
#include <xaudio2.h>
#include <mfapi.h>
#include <mfidl.h>

View File

@ -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();
}

View File

@ -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<Voice*>;
public:
void Setup() override;
void Setup(Application*) override;
void Destroy() override;

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/IntrusivePtr.hpp"
#include "IntrusivePtr.hpp"
#include <Unknwnbase.h>
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
#include <functional>
#ifdef E2D_DEBUG

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
#include <utility>
namespace easy2d

View File

@ -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 <typename _Ty>
@ -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

View File

@ -23,6 +23,17 @@
namespace easy2d
{
//
// Closure is a simple function for binding member functions
//
template<typename _Ty, typename _Ret, typename... _Args>
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<typename _Ty, typename _Ret, typename... _Args>
inline std::function<_Ret(_Args...)> Closure(_Ty* _Ptr, _Ret(_Ty::*_Func)(_Args...))
{

View File

@ -19,11 +19,10 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
namespace easy2d
{
class E2D_API Noncopyable
class Noncopyable
{
protected:
Noncopyable() = default;

View File

@ -21,7 +21,7 @@
#pragma once
#include "include-forwards.h"
#include "time.h"
#include "IntrusiveList.hpp"
#include "../common/IntrusiveList.hpp"
namespace easy2d
{

View File

@ -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<Application*>(
static_cast<LONG_PTR>(::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<int>(wparam);
evt.key.count = static_cast<int>(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<char>(wparam);
evt.key.count = static_cast<int>(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;

View File

@ -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<Component*> components_;
Window* main_window_;
Array<Component*> components_;
};
}

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
namespace easy2d
{

View File

@ -22,10 +22,12 @@
namespace easy2d
{
class Application;
class Component
{
public:
virtual void Setup() = 0;
virtual void Setup(Application*) = 0;
virtual void Destroy() = 0;
};

View File

@ -19,6 +19,7 @@
// THE SOFTWARE.
#include "DebugNode.h"
#include "Text.h"
#include "render.h"
#include "../utils/string.h"
#include <sstream>

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "Text.h"
#include "Node.h"
#include "time.h"
namespace easy2d

View File

@ -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,
// 窗口消息

View File

@ -20,7 +20,7 @@
#pragma once
#include "include-forwards.h"
#include "IntrusiveList.hpp"
#include "../common/IntrusiveList.hpp"
#include "Event.hpp"
namespace easy2d

View File

@ -20,6 +20,7 @@
#pragma once
#include "include-forwards.h"
#include <d2d1.h>
namespace easy2d
{

View File

@ -21,6 +21,7 @@
#pragma once
#include "include-forwards.h"
#include "Resource.h"
#include <d2d1.h>
namespace easy2d
{

View File

@ -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 {}

88
src/core/Layer.cpp Normal file
View File

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

View File

@ -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);
};
}

View File

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

View File

@ -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<NodePtr>
, public IntrusiveListItem<NodePtr>
{
friend class Application;
friend class Scene;
friend class Transition;
friend class IntrusiveList<NodePtr>;
@ -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
{

View File

@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "RefCounter.hpp"
#include "helper.hpp"
#include "helper.h"
namespace easy2d
{

View File

@ -19,8 +19,8 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "noncopyable.hpp"
#include "../macros.h"
#include "../common/noncopyable.hpp"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "helper.hpp"
#include "helper.h"
namespace easy2d
{

View File

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

View File

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

View File

@ -21,7 +21,7 @@
#pragma once
#include "include-forwards.h"
#include "time.h"
#include "IntrusiveList.hpp"
#include "../common/IntrusiveList.hpp"
#include <functional>
namespace easy2d

View File

@ -22,6 +22,7 @@
#include "Node.h"
#include "Font.hpp"
#include "TextStyle.hpp"
#include <dwrite.h>
namespace easy2d
{

View File

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

View File

@ -21,6 +21,7 @@
#pragma once
#include "include-forwards.h"
#include "time.h"
#include <d2d1.h>
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<ID2D1Layer> out_layer_;
ComPtr<ID2D1Layer> in_layer_;
LayerProperties out_layer_prop_;
LayerProperties in_layer_prop_;
ComPtr<ID2D1Layer> out_layer_;
ComPtr<ID2D1Layer> in_layer_;
LayerProperties out_layer_prop_;
LayerProperties in_layer_prop_;
};

View File

@ -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 <set>
#include <map>
#include <list>
@ -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

View File

@ -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
{

View File

@ -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,

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
#ifdef E2D_DISABLE_LOG_FUNCTIONS

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
#include <xaudio2.h>
#include <mfapi.h>
#include <mfidl.h>

View File

@ -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<float>(width);
output_size_.y = static_cast<float>(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)

View File

@ -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<DeviceResources> device_resources_;

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "../macros.h"
namespace easy2d
{

View File

@ -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);

View File

@ -20,15 +20,11 @@
#pragma once
#include "include-forwards.h"
#include "Singleton.hpp"
namespace easy2d
{
class E2D_API Window
: public Singleton<Window>
{
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();

View File

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

View File

@ -39,11 +39,11 @@ namespace easy2d
HRESULT HandleDeviceLost();
void SetLogicalSize(
HRESULT SetLogicalSize(
Size logical_size
);
void SetDpi(
HRESULT SetDpi(
float dpi
);

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include "../macros.h"
#if defined(E2D_USE_DIRECTX10)
# include "D3D10DeviceResources.h"

View File

@ -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"

View File

@ -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"

View File

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

View File

@ -19,7 +19,6 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include <random>
namespace easy2d
@ -35,64 +34,93 @@ namespace easy2d
// double d = math::Rand(1.2, 1.5);
//
E2D_API std::default_random_engine& GetRandomEngine();
int Rand(int min, int max);
template<typename T>
static T RandomInt(T min, T max)
{
std::uniform_int_distribution<T> dist(min, max);
return dist(GetRandomEngine());
}
unsigned int Rand(unsigned int min, unsigned int max);
template<typename T>
static T RandomReal(T min, T 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<T> 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<typename T>
inline T RandomInt(T min, T max)
{
std::uniform_int_distribution<T> dist(min, max);
return dist(GetRandomEngine());
}
template<typename T>
inline T RandomReal(T min, T max)
{
std::uniform_real_distribution<T> 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<char>(
RandomInt(static_cast<int>(min), static_cast<int>(max))
__rand_detail::RandomInt(static_cast<int>(min), static_cast<int>(max))
);
}
inline unsigned char Rand(unsigned char min, unsigned char max)
{
return static_cast<unsigned char>(
RandomInt(static_cast<unsigned int>(min), static_cast<unsigned int>(max))
__rand_detail::RandomInt(static_cast<unsigned int>(min), static_cast<unsigned int>(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);
}
}
}

View File

@ -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_();
}
}
}
}

View File

@ -24,74 +24,71 @@
namespace easy2d
{
namespace ui
class E2D_API Button
: public Sprite
{
class E2D_API Button
: public Sprite
{
using Callback = std::function<void()>;
using Callback = std::function<void()>;
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_;
};
}

View File

@ -22,81 +22,79 @@
namespace easy2d
{
namespace ui
Menu::Menu()
: enabled_(true)
{
Menu::Menu()
: enabled_(true)
{
}
}
Menu::Menu(Array<ButtonPtr> const& buttons)
: enabled_(true)
Menu::Menu(Array<ButtonPtr> 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<ButtonPtr> 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<ButtonPtr> const& Menu::GetAllButtons() const
{
return buttons_;
}
}

View File

@ -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<ButtonPtr> const& buttons /* 按钮数组 */
);
explicit Menu(
Array<ButtonPtr> 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<ButtonPtr> const& GetAllButtons() const;
// 获取所有按钮
Array<ButtonPtr> const& GetAllButtons() const;
private:
bool enabled_;
Array<ButtonPtr> buttons_;
};
private:
bool enabled_;
Array<ButtonPtr> buttons_;
};
}
}

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/helper.hpp"
#include "../core/helper.h"
namespace easy2d
{

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/helper.hpp"
#include "../core/helper.h"
#include "../core/Resource.h"
namespace easy2d

View File

@ -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<String>{}(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<String>{}(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))

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/helper.hpp"
#include "../core/helper.h"
namespace easy2d
{

View File

@ -19,7 +19,6 @@
// THE SOFTWARE.
#include "string.h"
#include "../core/macros.h"
#include "../core/logs.h"
namespace easy2d

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include "../macros.h"
#include <string>
namespace easy2d