diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index b364d231..7656da8a 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -36,21 +36,19 @@ - + - - - + + - @@ -102,7 +100,7 @@ - + diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index a14c5e46..2111540b 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -17,9 +17,6 @@ core - - core - core @@ -125,12 +122,6 @@ core - - core\intrusive - - - core\intrusive - core @@ -167,15 +158,6 @@ core - - core - - - core - - - core - core @@ -203,6 +185,18 @@ utils + + core + + + core + + + core + + + core + @@ -217,9 +211,6 @@ {07b6d541-4a1b-472a-aae0-daf9d082fe84} - - {0f508149-735a-43da-ab16-36cc1e9ab63a} - @@ -237,9 +228,6 @@ core - - core - core @@ -354,5 +342,8 @@ utils + + core + \ No newline at end of file diff --git a/project/vs2015/Easy2D.vcxproj b/project/vs2015/Easy2D.vcxproj index 413b0d2e..ab2c482c 100644 --- a/project/vs2015/Easy2D.vcxproj +++ b/project/vs2015/Easy2D.vcxproj @@ -36,21 +36,19 @@ - + - - - + + - @@ -102,7 +100,7 @@ - + diff --git a/project/vs2015/Easy2D.vcxproj.filters b/project/vs2015/Easy2D.vcxproj.filters index a14c5e46..2111540b 100644 --- a/project/vs2015/Easy2D.vcxproj.filters +++ b/project/vs2015/Easy2D.vcxproj.filters @@ -17,9 +17,6 @@ core - - core - core @@ -125,12 +122,6 @@ core - - core\intrusive - - - core\intrusive - core @@ -167,15 +158,6 @@ core - - core - - - core - - - core - core @@ -203,6 +185,18 @@ utils + + core + + + core + + + core + + + core + @@ -217,9 +211,6 @@ {07b6d541-4a1b-472a-aae0-daf9d082fe84} - - {0f508149-735a-43da-ab16-36cc1e9ab63a} - @@ -237,9 +228,6 @@ core - - core - core @@ -354,5 +342,8 @@ utils + + core + \ No newline at end of file diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 3a9bee02..fd983f57 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -36,21 +36,19 @@ - + - - - + + - @@ -102,7 +100,7 @@ - + diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index a14c5e46..2111540b 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -17,9 +17,6 @@ core - - core - core @@ -125,12 +122,6 @@ core - - core\intrusive - - - core\intrusive - core @@ -167,15 +158,6 @@ core - - core - - - core - - - core - core @@ -203,6 +185,18 @@ utils + + core + + + core + + + core + + + core + @@ -217,9 +211,6 @@ {07b6d541-4a1b-472a-aae0-daf9d082fe84} - - {0f508149-735a-43da-ab16-36cc1e9ab63a} - @@ -237,9 +228,6 @@ core - - core - core @@ -354,5 +342,8 @@ utils + + core + \ No newline at end of file diff --git a/src/core/Action.hpp b/src/core/Action.hpp index 81080623..e73d1e5b 100644 --- a/src/core/Action.hpp +++ b/src/core/Action.hpp @@ -22,21 +22,21 @@ #include "include-forwards.h" #include "time.h" #include "noncopyable.hpp" -#include "intrusive/List.hpp" +#include "IntrusiveList.hpp" namespace easy2d { class ActionManager; class Action - : public Object - , protected intrusive::ListItem + : public virtual Object + , protected IntrusiveListItem { friend class ActionManager; friend class Loop; friend class Sequence; friend class Spawn; - friend class intrusive::List; + friend class IntrusiveList; public: Action() : running_(false), done_(false), initialized_(false) {} diff --git a/src/core/ActionManager.h b/src/core/ActionManager.h index ea8ac98c..c46a2a86 100644 --- a/src/core/ActionManager.h +++ b/src/core/ActionManager.h @@ -25,7 +25,7 @@ namespace easy2d { class ActionManager { - using Actions = intrusive::List; + using Actions = IntrusiveList; public: // 执行动作 diff --git a/src/core/Game.cpp b/src/core/Application.cpp similarity index 68% rename from src/core/Game.cpp rename to src/core/Application.cpp index 51e4a0b9..f038b211 100644 --- a/src/core/Game.cpp +++ b/src/core/Application.cpp @@ -18,15 +18,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Game.h" +#include "Application.h" #include "logs.h" #include "modules.h" #include "Factory.h" +#include "Event.hpp" #include "Scene.h" #include "DebugNode.h" #include "Transition.h" -#include "KeyEvent.hpp" -#include "MouseEvent.hpp" #include #include @@ -34,29 +33,24 @@ namespace easy2d { - Game::Game() + Application::Application(String const& app_name) : active_(false) , debug_(false) , curr_scene_(nullptr) , next_scene_(nullptr) , transition_(nullptr) , time_scale_(1.f) + , app_name_(app_name) { ::CoInitialize(nullptr); } - Game::Game(Options const & options) - : Game() - { - Init(options); - } - - Game::~Game() + Application::~Application() { ::CoUninitialize(); } - void Game::Init(const Options& options) + void Application::Init(const Options& options) { debug_ = options.debug; @@ -70,7 +64,7 @@ namespace easy2d options.width, options.height, options.icon, - Game::WndProc, + Application::WndProc, debug_ ) ); @@ -78,7 +72,7 @@ namespace easy2d HWND hwnd = Window::Instance()->GetHandle(); ThrowIfFailed( - Graphics::Instance()->Init( + RenderSystem::Instance()->Init( hwnd, options.vsync, debug_ @@ -126,11 +120,13 @@ namespace easy2d ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); } - // use Game instance in message loop + // use Application instance in message loop ::SetWindowLongW(hwnd, GWLP_USERDATA, PtrToUlong(this)); + + Setup(); } - void Game::Run() + void Application::Run() { HWND hwnd = Window::Instance()->GetHandle(); @@ -148,14 +144,14 @@ namespace easy2d } } - void Game::Quit() + void Application::Quit() { Window::Instance()->Destroy(); } - void Game::EnterScene(ScenePtr const & scene) + void Application::EnterScene(ScenePtr const & scene) { - E2D_ASSERT(scene && "Game::EnterScene failed, NULL pointer exception"); + E2D_ASSERT(scene && "Application::EnterScene failed, NULL pointer exception"); if (curr_scene_ == scene || next_scene_ == scene) return; @@ -163,7 +159,7 @@ namespace easy2d next_scene_ = scene; } - void Game::EnterScene(ScenePtr const& scene, TransitionPtr const& transition) + void Application::EnterScene(ScenePtr const& scene, TransitionPtr const& transition) { EnterScene(scene); @@ -178,17 +174,17 @@ namespace easy2d } } - ScenePtr const& Game::GetCurrentScene() + ScenePtr const& Application::GetCurrentScene() { return curr_scene_; } - void Game::SetTimeScale(float scale) + void Application::SetTimeScale(float scale) { time_scale_ = scale; } - void Game::Update() + void Application::Update() { static auto last = time::Now(); @@ -229,12 +225,12 @@ namespace easy2d DebugNode::Instance()->Update(dt); } - void Game::Render(HWND hwnd) + void Application::Render(HWND hwnd) { - auto graphics = Graphics::Instance(); + auto rt = RenderSystem::Instance(); ThrowIfFailed( - graphics->BeginDraw(hwnd) + rt->BeginDraw(hwnd) ); if (transition_) @@ -250,27 +246,18 @@ namespace easy2d DebugNode::Instance()->Render(); ThrowIfFailed( - graphics->EndDraw() + rt->EndDraw() ); if (active_) ::InvalidateRect(hwnd, NULL, FALSE); } - void Game::Dispatch(Event * event) + LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - if (transition_) - return; + Application * app = reinterpret_cast(::GetWindowLongW(hwnd, GWLP_USERDATA)); - if (curr_scene_) - curr_scene_->DispatchEvent(event); - } - - LRESULT CALLBACK Game::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) - { - Game * game = reinterpret_cast(::GetWindowLongW(hwnd, GWLP_USERDATA)); - - if (!game) + if (!app) return ::DefWindowProcW(hwnd, msg, wparam, lparam); switch (msg) @@ -280,8 +267,8 @@ namespace easy2d PAINTSTRUCT ps; ::BeginPaint(hwnd, &ps); - game->Update(); - game->Render(hwnd); + app->Update(); + app->Render(hwnd); ::EndPaint(hwnd, &ps); @@ -289,11 +276,25 @@ namespace easy2d } break; + case WM_KEYDOWN: + case WM_KEYUP: + { + if (!app->transition_ && app->curr_scene_) + { + Event evt((msg == WM_KEYDOWN) ? KeyboardEvent::Down : KeyboardEvent::Up); + evt.key.code = KeyCode(wparam); + evt.key.count = static_cast(lparam & 0xFF); + + app->curr_scene_->Dispatch(evt); + } + } + break; + case WM_LBUTTONUP: case WM_LBUTTONDOWN: //case WM_LBUTTONDBLCLK: - //case WM_MBUTTONUP: - //case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDOWN: //case WM_MBUTTONDBLCLK: case WM_RBUTTONUP: case WM_RBUTTONDOWN: @@ -301,70 +302,36 @@ namespace easy2d case WM_MOUSEMOVE: case WM_MOUSEWHEEL: { - float x = GET_X_LPARAM(lparam) * Window::Instance()->GetContentScaleX(); - float y = GET_Y_LPARAM(lparam) * Window::Instance()->GetContentScaleY(); - float wheel_delta = 0.f; - - MouseEvent::Type type; - if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN) - type = MouseEvent::Down; - else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP) - type = MouseEvent::Up; - else if (msg == WM_MOUSEMOVE) - type = MouseEvent::Move; - else + if (!app->transition_ && app->curr_scene_) { - type = MouseEvent::Wheel; - wheel_delta = GET_WHEEL_DELTA_WPARAM(wparam) / 120.f; + Event evt; + + evt.mouse.x = GET_X_LPARAM(lparam) * Window::Instance()->GetContentScaleX(); + evt.mouse.y = GET_Y_LPARAM(lparam) * Window::Instance()->GetContentScaleY(); + evt.mouse.left_btn_down = !!(wparam & MK_LBUTTON); + evt.mouse.left_btn_down = !!(wparam & MK_RBUTTON); + + if (msg == WM_MOUSEMOVE) + evt.type = MouseEvent::Move; + else if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) + evt.type = MouseEvent::Down; + else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) + evt.type = MouseEvent::Up; + else + { + evt.type = MouseEvent::Wheel; + evt.mouse.wheel_delta = GET_WHEEL_DELTA_WPARAM(wparam) / 120.f; + } + + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) + evt.mouse.button = MouseButton::Left; + else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) + evt.mouse.button = MouseButton::Right; + else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) + evt.mouse.button = MouseButton::Middle; + + app->curr_scene_->Dispatch(evt); } - - MouseEvent event(type, x, y, wheel_delta); - - if (wparam & MK_LBUTTON || wparam & MK_RBUTTON) - event.button_down = true; - - game->Dispatch(&event); - } - break; - - case WM_KEYDOWN: - case WM_KEYUP: - { - KeyEvent event(msg, KeyCode(wparam)); - game->Dispatch(&event); - } - break; - - case WM_DISPLAYCHANGE: - { - E2D_LOG(L"The display resolution has changed"); - - ::InvalidateRect(hwnd, nullptr, FALSE); - } - break; - - case WM_CLOSE: - { - E2D_LOG(L"Received a message to close the window"); - - SysEvent event(SysEvent::WindowClose); - game->Dispatch(&event); - - if (game->OnClose()) - { - ::DestroyWindow(hwnd); - } - return 0; - } - break; - - case WM_DESTROY: - { - E2D_LOG(L"Window was destroyed"); - - game->OnExit(); - ::PostQuitMessage(0); - return 0; } break; @@ -372,13 +339,13 @@ namespace easy2d { if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) { - game->active_ = false; + app->active_ = false; E2D_LOG(L"Window minimized"); } else if (SIZE_RESTORED == wparam) { - game->active_ = true; + app->active_ = true; ::InvalidateRect(hwnd, nullptr, FALSE); E2D_LOG(L"Window restored"); @@ -390,7 +357,7 @@ namespace easy2d // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 // 目标的大小。它可能会调用失败,但是这里可以忽略有可能的 // 错误,因为这个错误将在下一次调用 EndDraw 时产生 - Graphics::Instance()->Resize(width, height); + RenderSystem::Instance()->Resize(width, height); } break; @@ -401,15 +368,21 @@ namespace easy2d { E2D_LOG(L"Window activated"); - SysEvent event(SysEvent::WindowActivate); - game->Dispatch(&event); + if (app->curr_scene_) + { + Event evt(WindowEvent::Activate); + app->curr_scene_->Dispatch(evt); + } } else { E2D_LOG(L"Window deactivated"); - SysEvent event(SysEvent::WindowDeavtivate); - game->Dispatch(&event); + if (app->curr_scene_) + { + Event evt(WindowEvent::Deavtivate); + app->curr_scene_->Dispatch(evt); + } } } break; @@ -425,6 +398,37 @@ namespace easy2d E2D_LOG(L"Window icon changed"); } break; + + case WM_DISPLAYCHANGE: + { + E2D_LOG(L"The display resolution has changed"); + + ::InvalidateRect(hwnd, nullptr, FALSE); + } + break; + + case WM_CLOSE: + { + E2D_LOG(L"Received a message to close the window"); + + if (app->curr_scene_) + { + Event evt(WindowEvent::Closing); + app->curr_scene_->Dispatch(evt); + } + ::DestroyWindow(hwnd); + return 0; + } + break; + + case WM_DESTROY: + { + E2D_LOG(L"Window was destroyed"); + + ::PostQuitMessage(0); + return 0; + } + break; } return ::DefWindowProcW(hwnd, msg, wparam, lparam); diff --git a/src/core/Game.h b/src/core/Application.h similarity index 88% rename from src/core/Game.h rename to src/core/Application.h index c84187d1..8481941b 100644 --- a/src/core/Game.h +++ b/src/core/Application.h @@ -25,7 +25,6 @@ #include "render.h" #include "input.h" #include "audio.h" -#include "Event.hpp" namespace easy2d { @@ -49,23 +48,18 @@ namespace easy2d }; - class Game + class Application : protected Noncopyable { public: - Game(); - - Game( - Options const& options + Application( + String const& app_name = L"Easy2dGame" ); - virtual ~Game(); + virtual ~Application(); - // 退出游戏 - virtual void OnExit() {} - - // 窗口关闭 - virtual bool OnClose() { return true; } + // 启动 + virtual void Setup() {} // 初始化 void Init( @@ -100,18 +94,15 @@ namespace easy2d void Update(); - void Dispatch( - Event* event - ); - static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); private: bool debug_; bool active_; float time_scale_; - ScenePtr curr_scene_; - ScenePtr next_scene_; + String app_name_; + ScenePtr curr_scene_; + ScenePtr next_scene_; TransitionPtr transition_; }; } diff --git a/src/core/Canvas.cpp b/src/core/Canvas.cpp index af192cd0..c8ca5bd1 100644 --- a/src/core/Canvas.cpp +++ b/src/core/Canvas.cpp @@ -32,7 +32,7 @@ namespace easy2d , stroke_width_(1.0f) { ThrowIfFailed( - Graphics::Instance()->CreateBitmapRenderTarget(render_target_) + RenderSystem::Instance()->CreateBitmapRenderTarget(render_target_) ); auto properties = D2D1::BrushProperties(); @@ -105,7 +105,7 @@ namespace easy2d if (bitmap_cached_) { - Graphics::Instance()->DrawBitmap(bitmap_cached_); + RenderSystem::Instance()->DrawBitmap(bitmap_cached_); } } diff --git a/src/core/Canvas.h b/src/core/Canvas.h index 68735c41..d8c7037d 100644 --- a/src/core/Canvas.h +++ b/src/core/Canvas.h @@ -224,11 +224,9 @@ namespace easy2d D2DBitmapPtr const& GetBitmap() const; protected: - mutable bool cache_expired_; - mutable D2DBitmapPtr bitmap_cached_; - float stroke_width_; - Font text_font_; - TextStyle text_style_; + float stroke_width_; + Font text_font_; + TextStyle text_style_; D2DPathGeometryPtr current_geometry_; D2DGeometrySinkPtr current_sink_; D2DStrokeStylePtr outline_join_style_; @@ -237,5 +235,8 @@ namespace easy2d D2DSolidColorBrushPtr text_brush_; D2DTextRendererPtr text_renderer_; D2DBitmapRenderTargetPtr render_target_; + + mutable bool cache_expired_; + mutable D2DBitmapPtr bitmap_cached_; }; } \ No newline at end of file diff --git a/src/core/DebugNode.cpp b/src/core/DebugNode.cpp index be484c09..d621c250 100644 --- a/src/core/DebugNode.cpp +++ b/src/core/DebugNode.cpp @@ -28,8 +28,7 @@ namespace easy2d { - - DebugNodeImpl::DebugNodeImpl() + DebugNode::DebugNode() { debug_text_ = new Text(); debug_text_->SetPosition(15, 15); @@ -46,11 +45,11 @@ namespace easy2d debug_text_->SetStyle(style); } - DebugNodeImpl::~DebugNodeImpl() + DebugNode::~DebugNode() { } - void DebugNodeImpl::AddDebugText(String const & text) + void DebugNode::AddDebugText(String const & text) { try { @@ -61,29 +60,29 @@ namespace easy2d } } - void DebugNodeImpl::ClearDebugText() + void DebugNode::ClearDebugText() { texts_.clear(); } - void DebugNodeImpl::OnRender() + void DebugNode::OnRender() { - auto graphics = Graphics::Instance(); + auto rt = RenderSystem::Instance(); - graphics->SetTransform(Matrix{}); + rt->SetTransform(Matrix{}); - graphics->GetSolidBrush()->SetColor(Color(0.0f, 0.0f, 0.0f, 0.5f)); + rt->GetSolidBrush()->SetColor(Color(0.0f, 0.0f, 0.0f, 0.5f)); - graphics->GetRenderTarget()->FillRoundedRectangle( + rt->GetRenderTarget()->FillRoundedRectangle( D2D1::RoundedRect( D2D1_RECT_F{ 10, 10, 200, 120 }, 6.f, 6.f), - graphics->GetSolidBrush().Get() + rt->GetSolidBrush().Get() ); } - void DebugNodeImpl::OnUpdate(Duration const & dt) + void DebugNode::OnUpdate(Duration const & dt) { try { @@ -106,9 +105,9 @@ namespace easy2d ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl; #endif - ss << "Render: " << Graphics::Instance()->GetStatus().duration.Milliseconds() << "ms" << std::endl; + ss << "Render: " << RenderSystem::Instance()->GetStatus().duration.Milliseconds() << "ms" << std::endl; - ss << "Primitives / sec: " << Graphics::Instance()->GetStatus().primitives * frame_time_.size() << std::endl; + ss << "Primitives / sec: " << RenderSystem::Instance()->GetStatus().primitives * frame_time_.size() << std::endl; PROCESS_MEMORY_COUNTERS_EX pmc; GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); diff --git a/src/core/DebugNode.h b/src/core/DebugNode.h index 7c419f65..a868aedb 100644 --- a/src/core/DebugNode.h +++ b/src/core/DebugNode.h @@ -25,15 +25,16 @@ namespace easy2d { - class DebugNodeImpl + class DebugNode : public Node + , public ISingleton { - E2D_DECLARE_SINGLETON(DebugNodeImpl); + E2D_DECLARE_SINGLETON(DebugNode); public: - DebugNodeImpl(); + DebugNode(); - virtual ~DebugNodeImpl(); + virtual ~DebugNode(); void AddDebugText(String const& text); @@ -48,6 +49,4 @@ namespace easy2d Array frame_time_; Array texts_; }; - - E2D_DECLARE_SINGLETON_TYPE(DebugNodeImpl, DebugNode); } diff --git a/src/core/Event.hpp b/src/core/Event.hpp index fda759c1..ff2b2638 100644 --- a/src/core/Event.hpp +++ b/src/core/Event.hpp @@ -20,39 +20,116 @@ #pragma once #include "macros.h" +#include "keys.hpp" namespace easy2d { typedef UINT EventType; - class Event + // 鼠标事件 + struct MouseEvent { - public: - Event(EventType type) : type(type), has_target(false) {} + enum Type : EventType + { + First = WM_MOUSEFIRST, - virtual ~Event() {} + Move, // 移动 + Down, // 按下 + Up, // 抬起 + Wheel, // 滚轮滚动 - EventType type; - bool has_target; + Hover, // 鼠标移入 + Out, // 鼠标移出 + Click, // 鼠标点击 + + Last // 结束标志 + }; + + float x; + float y; + bool left_btn_down; // 左键是否按下 + bool right_btn_down; // 右键是否按下 + + struct + { + MouseButton button; // 仅当消息类型为 Down | Up | Click 时有效 + }; + + struct + { + float wheel_delta; // 仅当消息类型为 Wheel 时有效 + }; + + static inline bool Check(EventType type) + { + return type > Type::First && type < Type::Last; + } }; - class SysEvent - : public Event + // 键盘事件 + struct KeyboardEvent { - public: - enum Type + enum Type : UINT { - First = WM_NULL, + First = WM_KEYFIRST, - WindowActivate, // 窗口获得焦点 - WindowDeavtivate, // 窗口失去焦点 - WindowClose, // 关闭窗口 + Down, // 键按下 + Up, // 键抬起 Last }; - SysEvent(EventType type) : Event(type) {} + KeyCode code; + int count; - static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; } + static inline bool Check(UINT type) + { + return type > Type::First && type < Type::Last; + } + }; + + // 窗口事件 + struct WindowEvent + { + public: + enum Type : EventType + { + First = WM_NULL, + + Activate, // 窗口获得焦点 + Deavtivate, // 窗口失去焦点 + Closing, // 关闭窗口 + + Last + }; + + static inline bool Check(EventType type) + { + return type > Type::First && type < Type::Last; + } + }; + + // 事件 + struct Event + { + EventType type; + bool has_target; + + union + { + MouseEvent mouse; + KeyboardEvent key; + WindowEvent win; + }; + + Event() + : type(0) + , has_target(false) + {} + + Event(EventType type) + : type(type) + , has_target(false) + {} }; } diff --git a/src/core/EventDispatcher.cpp b/src/core/EventDispatcher.cpp index a06e49e1..19150541 100644 --- a/src/core/EventDispatcher.cpp +++ b/src/core/EventDispatcher.cpp @@ -23,7 +23,7 @@ namespace easy2d { - void EventDispatcher::DispatchEvent(Event* e) + void EventDispatcher::Dispatch(Event& evt) { if (listeners_.IsEmpty()) return; @@ -33,9 +33,9 @@ namespace easy2d { next = listener->NextItem(); - if (listener->type_ == e->type) + if (listener->type_ == evt.type) { - listener->callback_(e); + listener->callback_(evt); } } } diff --git a/src/core/EventDispatcher.h b/src/core/EventDispatcher.h index ecf7615e..90bc7411 100644 --- a/src/core/EventDispatcher.h +++ b/src/core/EventDispatcher.h @@ -25,7 +25,7 @@ namespace easy2d { class EventDispatcher { - using Listeners = intrusive::List; + using Listeners = IntrusiveList; public: // 添加监听器 @@ -70,7 +70,7 @@ namespace easy2d EventType type ); - virtual void DispatchEvent(Event* e); + virtual void Dispatch(Event& evt); protected: Listeners listeners_; diff --git a/src/core/EventListener.h b/src/core/EventListener.h index c6bafcb6..222f2093 100644 --- a/src/core/EventListener.h +++ b/src/core/EventListener.h @@ -20,22 +20,21 @@ #pragma once #include "include-forwards.h" -#include "intrusive/List.hpp" +#include "IntrusiveList.hpp" #include "Event.hpp" namespace easy2d { - typedef std::function EventCallback; - + using EventCallback = std::function; class EventDispatcher; class EventListener - : public Object - , protected intrusive::ListItem + : public virtual Object + , protected IntrusiveListItem { friend class EventDispatcher; - friend class intrusive::List; + friend class IntrusiveList; public: EventListener( diff --git a/src/core/Factory.cpp b/src/core/Factory.cpp index 9953b011..12b0f899 100644 --- a/src/core/Factory.cpp +++ b/src/core/Factory.cpp @@ -25,18 +25,18 @@ namespace easy2d { - FactoryImpl::FactoryImpl() + Factory::Factory() { } - FactoryImpl::~FactoryImpl() + Factory::~Factory() { - E2D_LOG(L"Destroying device independent resources"); + E2D_LOG(L"Destroying device-independent resources"); } - HRESULT FactoryImpl::Init(bool debug) + HRESULT Factory::Init(bool debug) { - E2D_LOG(L"Creating device independent resources"); + E2D_LOG(L"Creating device-independent resources"); D2D1_FACTORY_OPTIONS fact_options; fact_options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE; @@ -111,7 +111,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateHwndRenderTarget(D2DHwndRenderTargetPtr & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const + HRESULT Factory::CreateHwndRenderTarget(D2DHwndRenderTargetPtr & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const { if (!factory_) return E_UNEXPECTED; @@ -128,7 +128,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateTextRenderer( + HRESULT Factory::CreateTextRenderer( D2DTextRendererPtr& text_renderer, D2DRenderTargetPtr const& render_target, D2DSolidColorBrushPtr const& brush @@ -150,20 +150,18 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateBitmapFromFile(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, String const & file_path) + HRESULT Factory::CreateBitmapFromFile(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, String const & file_path) { if (imaging_factory_ == nullptr) { return E_UNEXPECTED; } - using namespace intrusive; - - SmartPtr decoder; - SmartPtr source; - SmartPtr stream; - SmartPtr converter; - SmartPtr bitmap_tmp; + IntrusivePtr decoder; + IntrusivePtr source; + IntrusivePtr stream; + IntrusivePtr converter; + IntrusivePtr bitmap_tmp; HRESULT hr = imaging_factory_->CreateDecoderFromFilename( file_path.c_str(), @@ -211,20 +209,18 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateBitmapFromResource(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, Resource const & res) + HRESULT Factory::CreateBitmapFromResource(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, Resource const & res) { if (imaging_factory_ == nullptr) { return E_UNEXPECTED; } - using namespace intrusive; - - SmartPtr decoder; - SmartPtr source; - SmartPtr stream; - SmartPtr converter; - SmartPtr bitmap_tmp; + IntrusivePtr decoder; + IntrusivePtr source; + IntrusivePtr stream; + IntrusivePtr converter; + IntrusivePtr bitmap_tmp; // 加载资源 LPVOID buffer; @@ -294,7 +290,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateRectangleGeometry(D2DRectangleGeometryPtr & geo, Rect const& rect) const + HRESULT Factory::CreateRectangleGeometry(D2DRectangleGeometryPtr & geo, Rect const& rect) const { if (!factory_) return E_UNEXPECTED; @@ -310,7 +306,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateRoundedRectangleGeometry(D2DRoundedRectangleGeometryPtr & geo, Rect const & rect, float radius_x, float radius_y) const + HRESULT Factory::CreateRoundedRectangleGeometry(D2DRoundedRectangleGeometryPtr & geo, Rect const & rect, float radius_x, float radius_y) const { if (!factory_) return E_UNEXPECTED; @@ -330,7 +326,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateEllipseGeometry(D2DEllipseGeometryPtr & geo, Point const & center, float radius_x, float radius_y) const + HRESULT Factory::CreateEllipseGeometry(D2DEllipseGeometryPtr & geo, Point const & center, float radius_x, float radius_y) const { if (!factory_) return E_UNEXPECTED; @@ -350,7 +346,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateTransformedGeometry( + HRESULT Factory::CreateTransformedGeometry( D2DTransformedGeometryPtr& transformed, Matrix const& matrix, D2DGeometryPtr const& geo @@ -373,7 +369,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreatePathGeometry(D2DPathGeometryPtr & geometry) const + HRESULT Factory::CreatePathGeometry(D2DPathGeometryPtr & geometry) const { if (!factory_) return E_UNEXPECTED; @@ -381,7 +377,7 @@ namespace easy2d return factory_->CreatePathGeometry(&geometry); } - HRESULT FactoryImpl::CreateTextFormat(D2DTextFormatPtr & text_format, Font const & font, TextStyle const & text_style) const + HRESULT Factory::CreateTextFormat(D2DTextFormatPtr & text_format, Font const & font, TextStyle const & text_style) const { if (!write_factory_) return E_UNEXPECTED; @@ -419,7 +415,7 @@ namespace easy2d return hr; } - HRESULT FactoryImpl::CreateTextLayout(D2DTextLayoutPtr & text_layout, Size& layout_size, String const & text, D2DTextFormatPtr const& text_format, TextStyle const & text_style) const + HRESULT Factory::CreateTextLayout(D2DTextLayoutPtr & text_layout, Size& layout_size, String const & text, D2DTextFormatPtr const& text_format, TextStyle const & text_style) const { if (!write_factory_) return E_UNEXPECTED; @@ -497,7 +493,7 @@ namespace easy2d return hr; } - D2DStrokeStylePtr const& FactoryImpl::GetStrokeStyle(StrokeStyle stroke) const + D2DStrokeStylePtr const& Factory::GetStrokeStyle(StrokeStyle stroke) const { switch (stroke) { diff --git a/src/core/Factory.h b/src/core/Factory.h index 922c3d4b..e0c17eec 100644 --- a/src/core/Factory.h +++ b/src/core/Factory.h @@ -25,14 +25,13 @@ #include "Resource.h" #include "TextRenderer.h" #include "TextStyle.hpp" -#include "../math/Matrix.hpp" namespace easy2d { - class FactoryImpl - : protected Noncopyable + class Factory + : public ISingleton { - E2D_DECLARE_SINGLETON(FactoryImpl); + E2D_DECLARE_SINGLETON(Factory); public: HRESULT Init(bool debug); @@ -109,9 +108,9 @@ namespace easy2d ) const; protected: - FactoryImpl(); + Factory(); - ~FactoryImpl(); + ~Factory(); protected: D2DFactoryPtr factory_; @@ -121,6 +120,4 @@ namespace easy2d D2DStrokeStylePtr bevel_stroke_style_; D2DStrokeStylePtr round_stroke_style_; }; - - E2D_DECLARE_SINGLETON_TYPE(FactoryImpl, Factory); } diff --git a/src/core/Frames.h b/src/core/Frames.h index 128a4faa..7e27ec16 100644 --- a/src/core/Frames.h +++ b/src/core/Frames.h @@ -26,7 +26,7 @@ namespace easy2d { // 帧集合 class Frames - : public Object + : public virtual Object { public: Frames(); diff --git a/src/core/Geometry.h b/src/core/Geometry.h index a37e89c4..8da2be52 100644 --- a/src/core/Geometry.h +++ b/src/core/Geometry.h @@ -25,7 +25,7 @@ namespace easy2d { // 几何抽象 class Geometry - : public RefCounter + : public virtual Object { friend class Canvas; friend class GeometryNode; diff --git a/src/core/GeometryNode.cpp b/src/core/GeometryNode.cpp index 9d77fc35..5ba5cbc0 100644 --- a/src/core/GeometryNode.cpp +++ b/src/core/GeometryNode.cpp @@ -70,14 +70,14 @@ namespace easy2d { if (geometry_ && geometry_->geo_) { - auto graphics = Graphics::Instance(); + auto rt = RenderSystem::Instance(); - graphics->FillGeometry( + rt->FillGeometry( geometry_->geo_, fill_color_ ); - graphics->DrawGeometry( + rt->DrawGeometry( geometry_->geo_, stroke_color_, stroke_width_, diff --git a/src/core/Image.cpp b/src/core/Image.cpp index 42441a18..5e51c0f0 100644 --- a/src/core/Image.cpp +++ b/src/core/Image.cpp @@ -67,11 +67,11 @@ namespace easy2d logs::Warningln(L"Image file '%s' not found!", res.GetFileName()); return false; } - hr = Graphics::Instance()->CreateBitmapFromFile(bitmap, res.GetFileName()); + hr = RenderSystem::Instance()->CreateBitmapFromFile(bitmap, res.GetFileName()); } else { - hr = Graphics::Instance()->CreateBitmapFromResource(bitmap, res); + hr = RenderSystem::Instance()->CreateBitmapFromResource(bitmap, res); } if (FAILED(hr)) diff --git a/src/core/Image.h b/src/core/Image.h index cc97592c..eea23ae6 100644 --- a/src/core/Image.h +++ b/src/core/Image.h @@ -26,7 +26,7 @@ namespace easy2d { // 图片 class Image - : public Object + : public virtual Object { public: Image(); diff --git a/src/core/Input.cpp b/src/core/Input.cpp index 7d5de0a8..b2370427 100644 --- a/src/core/Input.cpp +++ b/src/core/Input.cpp @@ -24,7 +24,7 @@ namespace easy2d { - InputDevice::InputDevice() + Input::Input() : hwnd_(nullptr) , scale_x_(1.f) , scale_y_(1.f) @@ -33,12 +33,12 @@ namespace easy2d ZeroMemory(keys_cache_, sizeof(keys_cache_)); } - InputDevice::~InputDevice() + Input::~Input() { E2D_LOG(L"Destroying input device"); } - HRESULT InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug) + HRESULT Input::Init(HWND hwnd, float scale_x, float scale_y, bool debug) { E2D_LOG(L"Initing input device"); @@ -49,47 +49,47 @@ namespace easy2d return S_OK; } - void InputDevice::Update() + void Input::Update() { memcpy(keys_cache_, keys_, sizeof(keys_cache_)); GetKeyboardState(keys_); } - bool InputDevice::IsDown(KeyCode code) + bool Input::IsDown(KeyCode code) { return !!(keys_[static_cast(code)] & 0x80); } - bool InputDevice::IsDown(MouseButton btn) + bool Input::IsDown(MouseButton btn) { return !!(keys_[static_cast(btn)] & 0x80); } - bool InputDevice::WasPressed(KeyCode code) + bool Input::WasPressed(KeyCode code) { return !(keys_cache_[static_cast(code)] & 0x80) && (keys_[static_cast(code)] & 0x80); } - bool InputDevice::WasPressed(MouseButton btn) + bool Input::WasPressed(MouseButton btn) { return !(keys_cache_[static_cast(btn)] & 0x80) && (keys_[static_cast(btn)] & 0x80); } - bool InputDevice::WasReleased(KeyCode code) + bool Input::WasReleased(KeyCode code) { return (keys_cache_[static_cast(code)] & 0x80) && !(keys_[static_cast(code)] & 0x80); } - bool InputDevice::WasReleased(MouseButton btn) + bool Input::WasReleased(MouseButton btn) { return (keys_cache_[static_cast(btn)] & 0x80) && !(keys_[static_cast(btn)] & 0x80); } - float InputDevice::GetMouseX() + float Input::GetMouseX() { POINT pos; ::GetCursorPos(&pos); @@ -97,7 +97,7 @@ namespace easy2d return pos.x * scale_x_; } - float InputDevice::GetMouseY() + float Input::GetMouseY() { POINT pos; ::GetCursorPos(&pos); @@ -105,7 +105,7 @@ namespace easy2d return pos.y * scale_y_; } - Point InputDevice::GetMousePos() + Point Input::GetMousePos() { POINT pos; ::GetCursorPos(&pos); diff --git a/src/core/Input.h b/src/core/Input.h index cc21cc87..95a25db5 100644 --- a/src/core/Input.h +++ b/src/core/Input.h @@ -25,19 +25,10 @@ namespace easy2d { - // 鼠标键值 - enum class MouseButton : int + class Input + : public ISingleton { - Left = VK_LBUTTON, // 鼠标左键 - Right = VK_RBUTTON, // 鼠标右键 - Middle = VK_MBUTTON // 鼠标中键 - }; - - - class InputDevice - : protected Noncopyable - { - E2D_DECLARE_SINGLETON(InputDevice); + E2D_DECLARE_SINGLETON(Input); public: HRESULT Init(HWND hwnd, float scale_x, float scale_y, bool debug); @@ -84,9 +75,9 @@ namespace easy2d void Update(); protected: - InputDevice(); + Input(); - ~InputDevice(); + ~Input(); protected: HWND hwnd_; @@ -95,6 +86,4 @@ namespace easy2d BYTE keys_[256]; BYTE keys_cache_[256]; }; - - E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input); } diff --git a/src/core/IntrusiveList.hpp b/src/core/IntrusiveList.hpp new file mode 100644 index 00000000..9a9e0a1f --- /dev/null +++ b/src/core/IntrusiveList.hpp @@ -0,0 +1,254 @@ +// 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 "macros.h" +#include + +#undef DEBUG_CHECK_LIST +#ifdef E2D_DEBUG +# define DEBUG_CHECK_LIST(list_ptr) list_ptr->Check() +#else +# define DEBUG_CHECK_LIST __noop +#endif + +namespace easy2d +{ + template class IntrusiveList; + + template + class IntrusiveListItem + { + T prev_; + T next_; + + template + friend class IntrusiveList; + + public: + using ItemType = T; + + IntrusiveListItem() : prev_(), next_() {} + + T const& PrevItem() const { return prev_; } + + T& PrevItem() { return prev_; } + + T const& NextItem() const { return next_; } + + T& NextItem() { return next_; } + }; + + + template + class IntrusiveList + { + T first_; + T last_; + + public: + using ItemType = T; + + IntrusiveList() : first_(), last_() {} + + ~IntrusiveList() { Clear(); } + + T const& First() const { return first_; } + + T& First() { return first_; } + + T const& Last() const { return last_; } + + T& Last() { return last_; } + + bool IsEmpty() const { return !first_; } + + void PushBack(T const& child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = last_; + child->next_ = nullptr; + + if (first_) + { + last_->next_ = child; + } + else + { + first_ = child; + } + + last_ = child; + + DEBUG_CHECK_LIST(this); + } + + void PushFront(T const& child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = nullptr; + child->next_ = first_; + + if (first_) + { + first_->prev_ = child; + } + else + { + last_ = child; + } + + first_ = child; + + DEBUG_CHECK_LIST(this); + } + + void InsertBefore(T const& child, T const& before) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (before->prev_) + before->prev_->next_ = child; + else + first_ = child; + + child->prev_ = before->prev_; + child->next_ = before; + before->prev_ = child; + + DEBUG_CHECK_LIST(this); + } + + void InsertAfter(T const& child, T const& after) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (after->next_) + after->next_->prev_ = child; + else + last_ = child; + + child->next_ = after->next_; + child->prev_ = after; + after->next_ = child; + + DEBUG_CHECK_LIST(this); + } + + void Remove(T const& child) + { +#ifdef E2D_DEBUG + T tmp = first_; + while (tmp != child) + { + if (tmp == last_) + E2D_ASSERT(false && "The node to be removed is not in this list"); + tmp = tmp->next_; + } +#endif + + if (child->next_) + { + child->next_->prev_ = child->prev_; + } + else + { + last_ = child->prev_; + } + + if (child->prev_) + { + child->prev_->next_ = child->next_; + } + else + { + first_ = child->next_; + } + + child->prev_ = nullptr; + child->next_ = nullptr; + + DEBUG_CHECK_LIST(this); + } + + void Clear() + { + T p = first_; + while (p) + { + T tmp = p; + p = p->next_; + if (tmp) + { + tmp->next_ = nullptr; + tmp->prev_ = nullptr; + } + } + first_ = nullptr; + last_ = nullptr; + } + +#ifdef E2D_DEBUG + + private: + void Check() + { + if (!first_) + return; + + int pos = 0; + T p = first_; + T tmp = p; + do + { + tmp = p; + p = p->next_; + ++pos; + + if (p) + { + E2D_ASSERT(p->prev_ == tmp && "Check list failed"); + } + else + { + E2D_ASSERT(tmp == last_ && "Check list failed"); + } + } while (p); + } + +#endif + }; +} + +#undef DEBUG_CHECK_LIST diff --git a/src/core/IntrusivePtr.hpp b/src/core/IntrusivePtr.hpp new file mode 100644 index 00000000..11b78b1c --- /dev/null +++ b/src/core/IntrusivePtr.hpp @@ -0,0 +1,201 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining lhs 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 "macros.h" +#include + +namespace easy2d +{ + template + class IntrusivePtr + { + T* ptr_{ nullptr }; + + public: + using Type = T; + + IntrusivePtr() E2D_NOEXCEPT {} + + IntrusivePtr(nullptr_t) E2D_NOEXCEPT {} + + IntrusivePtr(Type* p) E2D_NOEXCEPT : ptr_(p) + { + IntrusivePtrAddRef(ptr_); + } + + IntrusivePtr(const IntrusivePtr& other) E2D_NOEXCEPT + : ptr_(other.ptr_) + { + IntrusivePtrAddRef(ptr_); + } + + template + IntrusivePtr(const IntrusivePtr& other) E2D_NOEXCEPT + : ptr_(other.Get()) + { + IntrusivePtrAddRef(ptr_); + } + + IntrusivePtr(IntrusivePtr&& other) E2D_NOEXCEPT + { + ptr_ = other.ptr_; + other.ptr_ = nullptr; + } + + ~IntrusivePtr() E2D_NOEXCEPT + { + IntrusivePtrRelease(ptr_); + } + + inline Type* Get() const E2D_NOEXCEPT { return ptr_; } + + inline void Swap(IntrusivePtr& other) E2D_NOEXCEPT + { + std::swap(ptr_, other.ptr_); + } + + inline Type* operator ->() const + { + E2D_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return ptr_; + } + + inline Type& operator *() const + { + E2D_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return *ptr_; + } + + inline Type** operator &() + { + E2D_ASSERT(ptr_ == nullptr && "Memory leak"); + return &ptr_; + } + + inline operator bool() const E2D_NOEXCEPT { return ptr_ != nullptr; } + + inline bool operator !() const E2D_NOEXCEPT { return ptr_ == 0; } + + inline IntrusivePtr& operator =(const IntrusivePtr& other) E2D_NOEXCEPT + { + if (other.ptr_ != ptr_) + IntrusivePtr(other).Swap(*this); + return *this; + } + + inline IntrusivePtr& operator =(IntrusivePtr&& other) E2D_NOEXCEPT + { + IntrusivePtrRelease(ptr_); + ptr_ = other.ptr_; + other.ptr_ = nullptr; + return *this; + } + + inline IntrusivePtr& operator =(Type* p) E2D_NOEXCEPT + { + if (p != ptr_) + IntrusivePtr(p).Swap(*this); + return *this; + } + + inline IntrusivePtr& operator =(nullptr_t) E2D_NOEXCEPT + { + if (nullptr != ptr_) + IntrusivePtr{}.Swap(*this); + return *this; + } + }; + + template + inline bool operator==(IntrusivePtr const& lhs, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return lhs.Get() == rhs.Get(); + } + + template + inline bool operator!=(IntrusivePtr const& lhs, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return lhs.Get() != rhs.Get(); + } + + template + inline bool operator<(IntrusivePtr const& lhs, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return lhs.Get() < rhs.Get(); + } + + template + inline bool operator==(IntrusivePtr const& lhs, T* rhs) E2D_NOEXCEPT + { + return lhs.Get() == rhs; + } + + template + inline bool operator!=(IntrusivePtr const& lhs, T* rhs) E2D_NOEXCEPT + { + return lhs.Get() != rhs; + } + + template + inline bool operator==(T* lhs, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return lhs == rhs.Get(); + } + + template + inline bool operator!=(T* lhs, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return lhs != rhs.Get(); + } + + template + inline bool operator==(IntrusivePtr const& lhs, nullptr_t) E2D_NOEXCEPT + { + return !static_cast(lhs); + } + + template + inline bool operator!=(IntrusivePtr const& lhs, nullptr_t) E2D_NOEXCEPT + { + return static_cast(lhs); + } + + template + inline bool operator==(nullptr_t, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return !static_cast(rhs); + } + + template + inline bool operator!=(nullptr_t, IntrusivePtr const& rhs) E2D_NOEXCEPT + { + return static_cast(rhs); + } + + // template class cannot specialize std::swap, + // so implement a swap function in easy2d namespace + template + inline void swap(IntrusivePtr& lhs, IntrusivePtr& rhs) E2D_NOEXCEPT + { + lhs.Swap(rhs); + } + +} diff --git a/src/core/KeyEvent.hpp b/src/core/KeyEvent.hpp deleted file mode 100644 index 4bc00188..00000000 --- a/src/core/KeyEvent.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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 "Event.hpp" -#include "keys.hpp" - -namespace easy2d -{ - class KeyEvent - : public Event - { - public: - enum Type - { - First = WM_KEYFIRST, - - Down, // 键按下 - Up, // 键抬起 - - Last // 结束标志 - }; - - KeyEvent(EventType type, KeyCode key) : Event(type), key(key) {} - - static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; } - - KeyCode key; - }; -} diff --git a/src/core/MouseEvent.hpp b/src/core/MouseEvent.hpp deleted file mode 100644 index 50aa7035..00000000 --- a/src/core/MouseEvent.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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 "Event.hpp" -#include "helper.hpp" - -namespace easy2d -{ - class MouseEvent - : public Event - { - public: - enum Type - { - First = WM_MOUSEFIRST, - - Move, // 移动 - Down, // 按下 - Up, // 抬起 - Wheel, // 滚轮滚动 - - Hover, // 鼠标移入 - Out, // 鼠标移出 - Click, // 鼠标点击 - - Last // 结束标志 - }; - - MouseEvent(EventType type, float x, float y, float wheel_delta) : Event(type), position(x, y), wheel_delta(wheel_delta), button_down(false) {} - - static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; } - - Point position; - float wheel_delta; - bool button_down; - }; -} diff --git a/src/core/Music.h b/src/core/Music.h index 73d34b22..1fcaedef 100644 --- a/src/core/Music.h +++ b/src/core/Music.h @@ -27,7 +27,7 @@ namespace easy2d { // 音乐 class Music - : public Object + : public virtual Object { public: Music(); diff --git a/src/core/Node.cpp b/src/core/Node.cpp index 3d2f5d18..435a1dcb 100644 --- a/src/core/Node.cpp +++ b/src/core/Node.cpp @@ -23,7 +23,6 @@ #include "Factory.h" #include "Scene.h" #include "Task.h" -#include "MouseEvent.hpp" #include "render.h" #include "logs.h" @@ -31,18 +30,19 @@ namespace easy2d { namespace { - float default_pivot_x = 0.f; - float default_pivot_y = 0.f; + float default_anchor_x = 0.f; + float default_anchor_y = 0.f; } - void Node::SetDefaultPivot(float pivot_x, float pivot_y) + void Node::SetDefaultAnchor(float anchor_x, float anchor_y) { - default_pivot_x = pivot_x; - default_pivot_y = pivot_y; + default_anchor_x = anchor_x; + default_anchor_y = anchor_y; } Node::Node() : visible_(true) + , pause_(false) , dirty_transform_(false) , dirty_transform_inverse_(false) , parent_(nullptr) @@ -50,12 +50,15 @@ namespace easy2d , z_order_(0) , opacity_(1.f) , display_opacity_(1.f) - , pivot_(default_pivot_x, default_pivot_y) + , anchor_(default_anchor_x, default_anchor_y) { } void Node::Update(Duration const & dt) { + if (pause_) + return; + OnUpdate(dt); UpdateActions(this, dt); UpdateTasks(dt); @@ -78,12 +81,12 @@ namespace easy2d UpdateTransform(); - auto graphics = Graphics::Instance(); + auto rt = RenderSystem::Instance(); if (children_.IsEmpty()) { - graphics->SetTransform(transform_matrix_); - graphics->SetOpacity(display_opacity_); + rt->SetTransform(transform_matrix_); + rt->SetOpacity(display_opacity_); OnRender(); } @@ -100,8 +103,8 @@ namespace easy2d child = child->NextItem().Get(); } - graphics->SetTransform(transform_matrix_); - graphics->SetOpacity(display_opacity_); + rt->SetTransform(transform_matrix_); + rt->SetOpacity(display_opacity_); OnRender(); @@ -113,7 +116,7 @@ namespace easy2d } } - void Node::DispatchEvent(Event * e) + void Node::Dispatch(Event& evt) { if (!visible_) return; @@ -122,26 +125,24 @@ namespace easy2d for (auto child = children_.Last(); child; child = prev) { prev = child->PrevItem(); - child->DispatchEvent(e); + child->Dispatch(evt); } - if (MouseEvent::Check(e)) + if (MouseEvent::Check(evt.type)) { - MouseEvent* me = static_cast(e); - - if (me->type == MouseEvent::Move) + if (evt.type == MouseEvent::Move) { - if (!me->has_target && ContainsPoint(me->position)) + if (!evt.has_target && ContainsPoint(Point{ evt.mouse.x, evt.mouse.y })) { - me->has_target = true; + evt.has_target = true; if (!hover_) { hover_ = true; - MouseEvent hover = *me; + Event hover = evt; hover.type = MouseEvent::Hover; - DispatchEvent(&hover); + Dispatch(hover); } } else if (hover_) @@ -149,28 +150,38 @@ namespace easy2d hover_ = false; pressed_ = false; - MouseEvent hover = *me; - hover.type = MouseEvent::Out; - DispatchEvent(&hover); + Event out = evt; + out.type = MouseEvent::Out; + Dispatch(out); } } - if (me->type == MouseEvent::Down && hover_) + if (evt.type == MouseEvent::Down && hover_) { pressed_ = true; } - if (me->type == MouseEvent::Up && pressed_) + if (evt.type == MouseEvent::Up && pressed_) { pressed_ = false; - MouseEvent click = *me; + Event click = evt; click.type = MouseEvent::Click; - DispatchEvent(&click); + Dispatch(click); } } - EventDispatcher::DispatchEvent(e); + EventDispatcher::Dispatch(evt); + } + + void Node::PauseUpdating() + { + pause_ = true; + } + + void Node::ResumeUpdating() + { + pause_ = false; } Matrix const & Node::GetTransformMatrix() const @@ -214,7 +225,7 @@ namespace easy2d * Matrix::Rotation(transform_.rotation) * Matrix::Translation(transform_.position); - Point offset{ -size_.x * pivot_.x, -size_.y * pivot_.y }; + Point offset{ -size_.x * anchor_.x, -size_.y * anchor_.y }; transform_matrix_.Translate(offset); if (parent_) @@ -290,23 +301,23 @@ namespace easy2d UpdateOpacity(); } - void Node::SetPivotX(float pivot_x) + void Node::SetAnchorX(float anchor_x) { - this->SetPivot(pivot_x, pivot_.y); + this->SetAnchor(anchor_x, anchor_.y); } - void Node::SetPivotY(float pivot_y) + void Node::SetAnchorY(float anchor_y) { - this->SetPivot(pivot_.x, pivot_y); + this->SetAnchor(anchor_.x, anchor_y); } - void Node::SetPivot(float pivot_x, float pivot_y) + void Node::SetAnchor(float anchor_x, float anchor_y) { - if (pivot_.x == pivot_x && pivot_.y == pivot_y) + if (anchor_.x == anchor_x && anchor_.y == anchor_y) return; - pivot_.x = pivot_x; - pivot_.y = pivot_y; + anchor_.x = anchor_x; + anchor_.y = anchor_y; dirty_transform_ = true; } diff --git a/src/core/Node.h b/src/core/Node.h index e29270f9..c38395f7 100644 --- a/src/core/Node.h +++ b/src/core/Node.h @@ -25,26 +25,26 @@ #include "TaskManager.h" #include "ActionManager.h" #include "EventDispatcher.h" -#include "intrusive/List.hpp" +#include "IntrusiveList.hpp" namespace easy2d { - class Game; + class Application; // 节点 class Node - : public Object + : public virtual Object , public TaskManager , public ActionManager , public EventDispatcher - , protected intrusive::ListItem + , protected IntrusiveListItem { - friend class Game; + friend class Application; friend class Scene; friend class Transition; - friend class intrusive::List; + friend class IntrusiveList; - using Children = intrusive::List; + using Children = IntrusiveList; public: Node(); @@ -55,11 +55,14 @@ namespace easy2d // 渲染节点 virtual void OnRender() {} + // 事件分发 + virtual void Dispatch(Event& evt) override; + // 获取显示状态 bool IsVisible() const { return visible_; } // 获取名称 - String const& GetName() const { return name_; } + String const& GetName() const { return name_; } // 获取名称的 Hash 值 size_t GetHashName() const { return hash_name_; } @@ -109,11 +112,11 @@ namespace easy2d // 获取缩放后的大小 Size GetScaledSize() const { return Size{ GetScaledWidth(), GetScaledHeight() }; } - // 获取 x 方向支点 - float GetPivotX() const { return pivot_.x; } + // 获取 x 方向锚点 + float GetAnchorX() const { return anchor_.x; } - // 获取 y 方向支点 - float GetPivotY() const { return pivot_.y; } + // 获取 y 方向锚点 + float GetAnchorY() const { return anchor_.y; } // 获取透明度 float GetOpacity() const { return opacity_; } @@ -228,23 +231,23 @@ namespace easy2d float rotation ); - // 设置支点的横向位置 + // 设置锚点的横向位置 // 默认为 0, 范围 [0, 1] - void SetPivotX( - float pivot_x + void SetAnchorX( + float anchor_x ); - // 设置支点的纵向位置 + // 设置锚点的纵向位置 // 默认为 0, 范围 [0, 1] - void SetPivotY( - float pivot_y + void SetAnchorY( + float anchor_y ); - // 设置支点位置 + // 设置锚点位置 // 默认为 (0, 0), 范围 [0, 1] - void SetPivot( - float pivot_x, - float pivot_y + void SetAnchor( + float anchor_x, + float anchor_y ); // 修改宽度 @@ -333,12 +336,16 @@ namespace easy2d // 从父节点移除 void RemoveFromParent(); - virtual void DispatchEvent(Event* e) override; + // 暂停节点更新 + void PauseUpdating(); - // 设置默认支点 - static void SetDefaultPivot( - float pivot_x, - float pivot_y + // 继续节点更新 + void ResumeUpdating(); + + // 设置默认锚点 + static void SetDefaultAnchor( + float anchor_x, + float anchor_y ); protected: @@ -356,13 +363,14 @@ namespace easy2d bool visible_; bool hover_; bool pressed_; + bool pause_; int z_order_; float opacity_; float display_opacity_; String name_; size_t hash_name_; Transform transform_; - Point pivot_; + Point anchor_; Size size_; Node* parent_; Scene* scene_; diff --git a/src/core/Scene.cpp b/src/core/Scene.cpp index b6e28d34..81c7153f 100644 --- a/src/core/Scene.cpp +++ b/src/core/Scene.cpp @@ -26,8 +26,8 @@ namespace easy2d { Scene::Scene() { - AddListener(SysEvent::WindowActivate, std::bind(&Scene::OnActivate, this)); - AddListener(SysEvent::WindowDeavtivate, std::bind(&Scene::OnDeactivate, this)); + AddListener(WindowEvent::Activate, std::bind(&Scene::OnActivate, this)); + AddListener(WindowEvent::Deavtivate, std::bind(&Scene::OnDeactivate, this)); scene_ = this; } diff --git a/src/core/Singleton.hpp b/src/core/Singleton.hpp index 18d03bcb..ba34f3c1 100644 --- a/src/core/Singleton.hpp +++ b/src/core/Singleton.hpp @@ -37,7 +37,7 @@ namespace easy2d return instance_.get(); } - private: + protected: ISingleton() = default; ~ISingleton() {} @@ -53,8 +53,3 @@ namespace easy2d friend struct ::std::default_delete< type >;\ friend class ::easy2d::ISingleton< type > #endif - -#ifndef E2D_DECLARE_SINGLETON_TYPE -#define E2D_DECLARE_SINGLETON_TYPE( type, singleton_type ) \ - using singleton_type = ::easy2d::ISingleton< type > -#endif diff --git a/src/core/Sprite.cpp b/src/core/Sprite.cpp index 7e942e8c..898b838f 100644 --- a/src/core/Sprite.cpp +++ b/src/core/Sprite.cpp @@ -99,7 +99,7 @@ namespace easy2d { if (image_) { - Graphics::Instance()->DrawImage(image_); + RenderSystem::Instance()->DrawImage(image_); } } } \ No newline at end of file diff --git a/src/core/Task.h b/src/core/Task.h index 3bc8319e..1640ec43 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 "intrusive/List.hpp" +#include "IntrusiveList.hpp" #include namespace easy2d @@ -30,11 +30,11 @@ namespace easy2d // 定时任务 class Task - : public Object - , protected intrusive::ListItem + : public virtual Object + , protected IntrusiveListItem { friend class TaskManager; - friend class intrusive::List; + friend class IntrusiveList; using Callback = std::function; diff --git a/src/core/TaskManager.h b/src/core/TaskManager.h index 5b36891b..0896dcc5 100644 --- a/src/core/TaskManager.h +++ b/src/core/TaskManager.h @@ -25,7 +25,7 @@ namespace easy2d { class TaskManager { - using Tasks = intrusive::List; + using Tasks = IntrusiveList; public: // 添加任务 diff --git a/src/core/Text.cpp b/src/core/Text.cpp index 7524d491..43671a01 100644 --- a/src/core/Text.cpp +++ b/src/core/Text.cpp @@ -295,15 +295,15 @@ namespace easy2d { if (text_layout_) { - auto graphics = Graphics::Instance(); - graphics->SetTextStyle( + auto rt = RenderSystem::Instance(); + rt->SetTextStyle( style_.color, style_.outline, style_.outline_color, style_.outline_width, style_.outline_stroke ); - graphics->DrawTextLayout(text_layout_); + rt->DrawTextLayout(text_layout_); } } diff --git a/src/core/Transition.cpp b/src/core/Transition.cpp index 72159694..e6ac5930 100644 --- a/src/core/Transition.cpp +++ b/src/core/Transition.cpp @@ -66,14 +66,14 @@ namespace easy2d if (in_scene_) { ThrowIfFailed( - Graphics::Instance()->CreateLayer(in_layer_) + RenderSystem::Instance()->CreateLayer(in_layer_) ); } if (out_scene_) { ThrowIfFailed( - Graphics::Instance()->CreateLayer(out_layer_) + RenderSystem::Instance()->CreateLayer(out_layer_) ); } @@ -101,34 +101,34 @@ namespace easy2d void Transition::Render() { - auto graphics = Graphics::Instance(); + auto rt = RenderSystem::Instance(); if (out_scene_) { - graphics->PushClip( + rt->PushClip( out_scene_->GetTransformMatrix(), window_size_ ); - graphics->PushLayer(out_layer_, out_layer_prop_); + rt->PushLayer(out_layer_, out_layer_prop_); out_scene_->Render(); - graphics->PopLayer(); - graphics->PopClip(); + rt->PopLayer(); + rt->PopClip(); } if (in_scene_) { - graphics->PushClip( + rt->PushClip( in_scene_->GetTransformMatrix(), window_size_ ); - graphics->PushLayer(in_layer_, in_layer_prop_); + rt->PushLayer(in_layer_, in_layer_prop_); in_scene_->Render(); - graphics->PopLayer(); - graphics->PopClip(); + rt->PopLayer(); + rt->PopClip(); } } @@ -337,13 +337,13 @@ namespace easy2d if (out_scene_) { out_scene_->SetTransform(transform); - out_scene_->SetPivot(0.5f, 0.5f); + out_scene_->SetAnchor(0.5f, 0.5f); } if (in_scene_) { in_scene_->SetTransform(transform); - in_scene_->SetPivot(0.5f, 0.5f); + in_scene_->SetAnchor(0.5f, 0.5f); } in_layer_prop_.opacity = 0; @@ -384,13 +384,13 @@ namespace easy2d if (out_scene_) { out_scene_->SetTransform(Transform{}); - out_scene_->SetPivot(0.f, 0.f); + out_scene_->SetAnchor(0.f, 0.f); } if (in_scene_) { in_scene_->SetTransform(Transform{}); - in_scene_->SetPivot(0.f, 0.f); + in_scene_->SetAnchor(0.f, 0.f); } } } diff --git a/src/core/Transition.h b/src/core/Transition.h index b6c57a38..5f04f3b5 100644 --- a/src/core/Transition.h +++ b/src/core/Transition.h @@ -28,9 +28,9 @@ namespace easy2d // 场景过渡 class Transition - : public Object + : public virtual Object { - friend class Game; + friend class Application; public: explicit Transition( diff --git a/src/core/audio.cpp b/src/core/audio.cpp index 8318de84..23357ad7 100644 --- a/src/core/audio.cpp +++ b/src/core/audio.cpp @@ -156,16 +156,16 @@ namespace easy2d //------------------------------------------------------- - // AudioDevice + // Audio //------------------------------------------------------- - AudioDevice::AudioDevice() + Audio::Audio() : x_audio2_(nullptr) , mastering_voice_(nullptr) { } - AudioDevice::~AudioDevice() + Audio::~Audio() { E2D_LOG(L"Destroying audio device"); @@ -182,7 +182,7 @@ namespace easy2d modules::MediaFoundation::Get().MFShutdown(); } - HRESULT AudioDevice::Init(bool debug) + HRESULT Audio::Init(bool debug) { E2D_LOG(L"Initing audio device"); @@ -201,7 +201,7 @@ namespace easy2d return hr; } - HRESULT AudioDevice::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx) + HRESULT Audio::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx) { HRESULT hr; IXAudio2SourceVoice* source_voice; @@ -215,12 +215,12 @@ namespace easy2d return hr; } - void AudioDevice::DeleteVoice(Voice* voice) + void Audio::DeleteVoice(Voice* voice) { voice_cache_.erase(voice); } - void AudioDevice::ClearVoiceCache() + void Audio::ClearVoiceCache() { for (auto voice : voice_cache_) { @@ -229,12 +229,12 @@ namespace easy2d voice_cache_.clear(); } - void AudioDevice::Open() + void Audio::Open() { x_audio2_->StartEngine(); } - void AudioDevice::Close() + void Audio::Close() { x_audio2_->StopEngine(); } diff --git a/src/core/audio.h b/src/core/audio.h index ee1ceb8a..6b6651f3 100644 --- a/src/core/audio.h +++ b/src/core/audio.h @@ -74,10 +74,10 @@ namespace easy2d }; - class AudioDevice - : protected Noncopyable + class Audio + : public ISingleton