From 9039dff8d3105c15287a86281793763bbe3bd579 Mon Sep 17 00:00:00 2001 From: Haibo Date: Sun, 30 Sep 2018 14:54:43 +0800 Subject: [PATCH] update:modules --- core/e2dmodule.h | 238 +++++----- core/e2dobject.h | 14 - core/impl/TextRenderer.cpp | 6 +- core/managers/CollisionManager.cpp | 4 +- core/modules/Audio.cpp | 24 +- core/modules/GC.cpp | 2 +- core/modules/Game.cpp | 459 +++++++++++++++++--- core/modules/{Renderer.cpp => Graphics.cpp} | 186 ++++---- core/modules/Window.cpp | 433 +----------------- core/objects/Canvas.cpp | 8 +- core/objects/Collider.cpp | 8 +- core/objects/Image.cpp | 8 +- core/objects/Node.cpp | 25 +- core/objects/Scene.cpp | 27 -- core/objects/Sprite.cpp | 11 +- core/objects/Text.cpp | 10 +- core/transitions/Transition.cpp | 10 +- project/vs2017/Easy2D.vcxproj | 2 +- project/vs2017/Easy2D.vcxproj.filters | 6 +- 19 files changed, 649 insertions(+), 832 deletions(-) rename core/modules/{Renderer.cpp => Graphics.cpp} (61%) diff --git a/core/e2dmodule.h b/core/e2dmodule.h index a6e2e7a9..0ba93728 100644 --- a/core/e2dmodule.h +++ b/core/e2dmodule.h @@ -8,7 +8,7 @@ namespace e2d { - // 窗体 + // 窗口 class Window { public: @@ -31,123 +31,36 @@ namespace e2d }; public: - // 获取窗体实例 - static Window * GetInstance(); - - // 销毁窗体实例 - static void DestroyInstance(); - - // 获取屏幕大小 - static Size GetScreenSize(); - - // 获取窗体标题 - const String& GetTitle() const; - - // 获取窗体宽度 - int GetWidth() const; - - // 获取窗体高度 - int GetHeight() const; - - // 获取窗体大小 - Size GetSize() const; - - // 获取窗口 DPI - float GetDpi() const; - - // 获取窗口句柄 - HWND GetHWnd(); - - // 修改窗体大小 - void SetSize( - int width, /* 窗体宽度 */ - int height /* 窗体高度 */ - ); - - // 设置窗体标题 - void SetTitle( - const String& title /* 窗体标题 */ - ); - - // 设置窗体图标 - void SetIcon( - int resource_id /* 图标资源 ID */ - ); - // 设置鼠标指针样式 - void SetCursor( + static void SetCursor( Cursor cursor ); // 打开或隐藏控制台 - void SetConsoleEnabled( + static void ShowConsole( bool enabled ); - // 是否允许响应输入法 - void SetTypewritingEnabled( - bool enabled - ); - - // 检测窗口是否唯一 - // 返回值:返回 false 说明游戏已经正在进行,可以防止用户同时打开多个游戏窗口 - bool CheckUnique(); - // 弹出窗口 // 返回值:当窗口包含取消按钮时,返回值表示用户是否点击确认按钮 - bool Popup( + static bool Popup( const String& text, /* 窗口内容 */ const String& title, /* 窗口标题 */ PopupStyle style = PopupStyle::Info,/* 弹窗样式 */ bool has_cancel = false /* 包含取消按钮 */ ); - // 处理窗体消息 - void Poll(); - - private: - Window(); - - ~Window(); - - E2D_DISABLE_COPY(Window); - - // 根据客户区大小定位窗口 - Rect Locate( - int width, - int height - ); - - // Win32 窗口消息回调程序 - static LRESULT CALLBACK WndProc( - HWND hwnd, - UINT msg, - WPARAM w_param, - LPARAM l_param - ); - - private: - HWND hwnd_; - MSG msg_; - int width_; - int height_; - int icon_id_; - float dpi_; - String title_; - - static Window * instance_; + // 获取屏幕大小 + static Size GetScreenSize(); }; // 渲染器 - class Renderer + class Graphics { public: // 获取渲染器实例 - static Renderer * GetInstance(); - - // 销毁实例 - static void DestroyInstance(); + static Graphics * Get(); // 获取 ID2D1Factory 对象 static ID2D1Factory * GetFactory(); @@ -176,14 +89,6 @@ namespace e2d // 获取 ID2D1SolidColorBrush 对象 ID2D1SolidColorBrush * GetSolidBrush(); - // 获取背景色 - Color GetBackgroundColor(); - - // 修改背景色 - void SetBackgroundColor( - const Color& color - ); - // 显示或隐藏 FPS // 默认:隐藏 void ShowFps( @@ -196,12 +101,15 @@ namespace e2d // 结束渲染 void EndDraw(); + // 渲染调试信息 + void DrawDebugInfo(); + protected: - Renderer(); + Graphics(); - ~Renderer(); + ~Graphics(); - E2D_DISABLE_COPY(Renderer); + E2D_DISABLE_COPY(Graphics); protected: bool show_fps_; @@ -220,7 +128,7 @@ namespace e2d static ID2D1StrokeStyle* miter_stroke_style_; static ID2D1StrokeStyle* bevel_stroke_style_; static ID2D1StrokeStyle* round_stroke_style_; - static Renderer * instance_; + static Graphics * instance_; }; @@ -288,16 +196,13 @@ namespace e2d { public: // 获取音频设备实例 - static Audio * GetInstance(); - - // 销毁实例 - static void DestroyInstance(); + static Audio * Get(); // 获取 XAudio2 实例对象 - IXAudio2 * GetXAudio2(); + IXAudio2 * GetXAudio2() const; // 获取 MasteringVoice 实例对象 - IXAudio2MasteringVoice* GetMasteringVoice(); + IXAudio2MasteringVoice* GetMasteringVoice() const; protected: Audio(); @@ -309,35 +214,78 @@ namespace e2d protected: IXAudio2 * x_audio2_; IXAudio2MasteringVoice* mastering_voice_; - - static Audio * instance_; }; - // 游戏 + // 选项 + struct Option + { + String title; // 窗口标题 + int width; // 窗口宽度 + int height; // 窗口高度 + int icon; // 窗口图标 + Color background_color; // 背景色 + bool debug_mode; // Debug 模式 + + Option() + : title(L"Easy2D Game") + , width(640) + , height(480) + , icon(0) + , background_color(Color::Black) + , debug_mode(false) + { + } + }; + + + // 游戏控制器 class Game { public: - // 获取 Game 实例 - static Game * GetInstance(); + static Game * New( + const Option& option + ); - // 销毁实例 - static void DestroyInstance(); + // 获取控制器 + static Game * Get(); // 启动游戏 - void Start(); - - // 暂停游戏 - void Pause(); - - // 继续游戏 - void Resume(); + void Run(); // 结束游戏 void Quit(); - // 游戏是否暂停 - bool IsPaused(); + // 获取窗体标题 + const String& GetTitle() const; + + // 获取窗体宽度 + int GetWidth() const; + + // 获取窗体高度 + int GetHeight() const; + + // 获取窗体大小 + Size GetSize() const; + + // 获取窗口句柄 + HWND GetHWnd() const; + + // 修改窗体大小 + void SetSize( + int width, /* 窗体宽度 */ + int height /* 窗体高度 */ + ); + + // 设置窗体标题 + void SetTitle( + const String& title /* 窗体标题 */ + ); + + // 设置窗体图标 + void SetIcon( + int resource_id /* 图标资源 ID */ + ); // 切换场景 void EnterScene( @@ -364,12 +312,34 @@ namespace e2d E2D_DISABLE_COPY(Game); + // 初始化 + void Init(); + + // 根据客户区大小定位窗口 + Rect Locate( + int width, + int height + ); + + // Win32 窗口消息回调程序 + static LRESULT CALLBACK WndProc( + HWND hwnd, + UINT msg, + WPARAM w_param, + LPARAM l_param + ); + private: - bool quit_; - bool paused_; - Scene* curr_scene_; - Scene* next_scene_; - Transition* transition_; + HWND hwnd_; + String title_; + int width_; + int height_; + int icon_; + bool debug_mode_; + bool quit_; + Scene* curr_scene_; + Scene* next_scene_; + Transition* transition_; static Game * instance_; }; diff --git a/core/e2dobject.h b/core/e2dobject.h index 055f9874..0c3baeaf 100644 --- a/core/e2dobject.h +++ b/core/e2dobject.h @@ -144,18 +144,6 @@ namespace e2d // 获取根节点 Node* GetRoot() const; - // 显示或隐藏节点边缘 - // 默认:隐藏 - void ShowBorder( - bool visible - ); - - // 显示或隐藏碰撞体 - // 默认:隐藏 - void ShowCollider( - bool visible - ); - // 渲染场景 void Draw(); @@ -182,8 +170,6 @@ namespace e2d protected: Node* root_; - bool border_visible_; - bool collider_visible_; D2D1::Matrix3x2F transform_; }; diff --git a/core/impl/TextRenderer.cpp b/core/impl/TextRenderer.cpp index 3a323678..09f43cf9 100644 --- a/core/impl/TextRenderer.cpp +++ b/core/impl/TextRenderer.cpp @@ -62,13 +62,13 @@ STDMETHODIMP_(void) E2DTextRenderer::SetTextStyle( switch (outlineJoin) { case D2D1_LINE_JOIN_MITER: - pCurrStrokeStyle_ = Renderer::GetMiterStrokeStyle(); + pCurrStrokeStyle_ = Graphics::GetMiterStrokeStyle(); break; case D2D1_LINE_JOIN_BEVEL: - pCurrStrokeStyle_ = Renderer::GetBevelStrokeStyle(); + pCurrStrokeStyle_ = Graphics::GetBevelStrokeStyle(); break; case D2D1_LINE_JOIN_ROUND: - pCurrStrokeStyle_ = Renderer::GetRoundStrokeStyle(); + pCurrStrokeStyle_ = Graphics::GetRoundStrokeStyle(); break; default: pCurrStrokeStyle_ = nullptr; diff --git a/core/managers/CollisionManager.cpp b/core/managers/CollisionManager.cpp index 3ad3ea20..0fb01209 100644 --- a/core/managers/CollisionManager.cpp +++ b/core/managers/CollisionManager.cpp @@ -36,10 +36,10 @@ void e2d::CollisionManager::RemoveCollider(Collider * collider) void e2d::CollisionManager::UpdateCollider(Collider* active) { if (!collision_enabled_ || - Game::GetInstance()->IsTransitioning()) + Game::Get()->IsTransitioning()) return; - auto currScene = Game::GetInstance()->GetCurrentScene(); + auto currScene = Game::Get()->GetCurrentScene(); if (active->GetNode()->GetParentScene() != currScene) return; diff --git a/core/modules/Audio.cpp b/core/modules/Audio.cpp index 6dad95b9..af9271a4 100644 --- a/core/modules/Audio.cpp +++ b/core/modules/Audio.cpp @@ -1,24 +1,10 @@ #include "..\e2dmodule.h" -e2d::Audio * e2d::Audio::instance_ = nullptr; - -e2d::Audio * e2d::Audio::GetInstance() +e2d::Audio * e2d::Audio::Get() { - if (!instance_) - { - instance_ = new (std::nothrow) Audio; - } - return instance_; -} - -void e2d::Audio::DestroyInstance() -{ - if (instance_) - { - delete instance_; - instance_ = nullptr; - } + static Audio audio; + return &audio; } e2d::Audio::Audio() @@ -49,12 +35,12 @@ e2d::Audio::~Audio() ::CoUninitialize(); } -IXAudio2 * e2d::Audio::GetXAudio2() +IXAudio2 * e2d::Audio::GetXAudio2() const { return x_audio2_; } -IXAudio2MasteringVoice * e2d::Audio::GetMasteringVoice() +IXAudio2MasteringVoice * e2d::Audio::GetMasteringVoice() const { return mastering_voice_; } diff --git a/core/modules/GC.cpp b/core/modules/GC.cpp index 7038a286..e0071658 100644 --- a/core/modules/GC.cpp +++ b/core/modules/GC.cpp @@ -14,7 +14,7 @@ e2d::GC::~GC() Player::DestroyInstance(); Audio::DestroyInstance(); - Renderer::DestroyInstance(); + Graphics::DestroyInstance(); Input::DestroyInstance(); Window::DestroyInstance(); Game::DestroyInstance(); diff --git a/core/modules/Game.cpp b/core/modules/Game.cpp index 0e5f0105..2b4ae3f1 100644 --- a/core/modules/Game.cpp +++ b/core/modules/Game.cpp @@ -3,29 +3,18 @@ #include "..\e2dtransition.h" #include "..\e2dmanager.h" #include +#include +#pragma comment (lib ,"imm32.lib") + +#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME +#define REGISTER_CLASS L"Easy2DApp" e2d::Game * e2d::Game::instance_ = nullptr; -e2d::Game * e2d::Game::GetInstance() -{ - if (!instance_) - instance_ = new (std::nothrow) Game; - return instance_; -} - -void e2d::Game::DestroyInstance() -{ - if (instance_) - { - delete instance_; - instance_ = nullptr; - } -} - e2d::Game::Game() - : quit_(true) - , paused_(false) + : hwnd_(nullptr) + , quit_(true) , curr_scene_(nullptr) , next_scene_(nullptr) , transition_(nullptr) @@ -39,24 +28,47 @@ e2d::Game::~Game() SafeRelease(curr_scene_); SafeRelease(next_scene_); + if (hwnd_) + { + ::DestroyWindow(hwnd_); + } + ::CoUninitialize(); } -void e2d::Game::Start() +e2d::Game * e2d::Game::New(const Option & option) +{ + static Game game; + game.title_ = option.title; + game.width_ = option.width; + game.height_ = option.height; + game.icon_ = option.icon; + game.debug_mode_ = option.debug_mode; + + game.Init(); + + instance_ = &game; + return instance_; +} + +e2d::Game * e2d::Game::Get() +{ + return instance_; +} + +void e2d::Game::Run() { quit_ = false; - auto window = Window::GetInstance(); auto input = Input::GetInstance(); - auto renderer = Renderer::GetInstance(); + auto graphics = Graphics::Get(); - const int minInterval = 5; + const int min_interval = 5; Time last = Time::Now(); - HWND hwnd = window->GetHWnd(); + MSG msg = { 0 }; - ::ShowWindow(hwnd, SW_SHOWNORMAL); - ::UpdateWindow(hwnd); - window->Poll(); + ::ShowWindow(hwnd_, SW_SHOWNORMAL); + ::UpdateWindow(hwnd_); UpdateScene(); while (!quit_) @@ -64,7 +76,7 @@ void e2d::Game::Start() auto now = Time::Now(); auto dur = now - last; - if (dur.Milliseconds() > minInterval) + if (dur.Milliseconds() > min_interval) { last = now; input->Update(); @@ -72,14 +84,18 @@ void e2d::Game::Start() UpdateScene(); DrawScene(); - window->Poll(); + while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } } else { // ID2D1HwndRenderTarget 开启了垂直同步,在渲染时会等待显示器刷新, // 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。 // 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。 - int wait = minInterval - dur.Milliseconds(); + int wait = min_interval - dur.Milliseconds(); if (wait > 1) { std::this_thread::sleep_for(std::chrono::milliseconds(wait)); @@ -88,28 +104,6 @@ void e2d::Game::Start() } } -void e2d::Game::Pause() -{ - paused_ = true; -} - -void e2d::Game::Resume() -{ - if (paused_ && !quit_) - { - if (curr_scene_) - { - curr_scene_->GetRoot()->UpdateTime(); - } - } - paused_ = false; -} - -bool e2d::Game::IsPaused() -{ - return paused_; -} - void e2d::Game::Quit() { quit_ = true; @@ -162,9 +156,6 @@ bool e2d::Game::IsTransitioning() const void e2d::Game::UpdateScene() { - if (paused_) - return; - if (transition_) { transition_->Update(); @@ -197,16 +188,360 @@ void e2d::Game::UpdateScene() void e2d::Game::DrawScene() { - Renderer::GetInstance()->BeginDraw(); + auto graphics = Graphics::Get(); + graphics->BeginDraw(); + + if (transition_) { - if (transition_) + transition_->Draw(); + } + else if (curr_scene_) + { + curr_scene_->Draw(); + } + + // TODO @Nomango if debug_mode_ + /* + { + graphics->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); + graphics->GetSolidBrush()->SetOpacity(1.f); + root_->DrawBorder(); + } + + { + graphics->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); + root_->DrawCollider(); + } + */ + + if (debug_mode_) + { + graphics->DrawDebugInfo(); + } + graphics->EndDraw(); +} + +void e2d::Game::Init() +{ + WNDCLASSEX wcex = { 0 }; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpszClassName = REGISTER_CLASS; + wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + wcex.lpfnWndProc = Game::WndProc; + wcex.hIcon = nullptr; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(LONG_PTR); + wcex.hInstance = HINST_THISCOMPONENT; + wcex.hbrBackground = nullptr; + wcex.lpszMenuName = nullptr; + wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW); + + if (icon_ != 0) + { + wcex.hIcon = (HICON)::LoadImage( + HINST_THISCOMPONENT, + MAKEINTRESOURCE(icon_), + IMAGE_ICON, + 0, + 0, + LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE + ); + } + + // 注册窗口类 + RegisterClassEx(&wcex); + + // 计算窗口大小 + Rect client_rect = Locate(width_, height_); + + // 创建窗口 + hwnd_ = ::CreateWindowEx( + NULL, + REGISTER_CLASS, + (LPCTSTR)title_, + WINDOW_STYLE, + int(client_rect.origin.x), + int(client_rect.origin.y), + int(client_rect.size.width), + int(client_rect.size.height), + nullptr, + nullptr, + HINST_THISCOMPONENT, + this + ); + + if (hwnd_) + { + // 禁用输入法 + ::ImmAssociateContext(hwnd_, nullptr); + // 禁用控制台关闭按钮 + HWND console_hwnd = ::GetConsoleWindow(); + if (console_hwnd) { - transition_->Draw(); - } - else if (curr_scene_) - { - curr_scene_->Draw(); + HMENU hmenu = ::GetSystemMenu(console_hwnd, FALSE); + ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); } } - Renderer::GetInstance()->EndDraw(); + else + { + ::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT); + throw RuntimeException("Create window failed"); + } +} + +e2d::Rect e2d::Game::Locate(int width, int height) +{ + int max_width = ::GetSystemMetrics(SM_CXSCREEN); + int max_height = ::GetSystemMetrics(SM_CYSCREEN); + + float dpi_x, dpi_y; + Graphics::GetFactory()->GetDesktopDpi(&dpi_x, &dpi_y); + RECT rect = { 0, 0, LONG(ceil(width * dpi_x / 96.f)), LONG(ceil(height * dpi_y / 96.f)) }; + + // 计算合适的窗口大小 + ::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); + width = static_cast(rect.right - rect.left); + height = static_cast(rect.bottom - rect.top); + + // 当输入的窗口大小比分辨率大时,给出警告 + WARN_IF(max_width < width || max_height < height, "The window Is larger than screen!"); + width = std::min(width, max_width); + height = std::min(height, max_height); + + Rect client_rect( + static_cast((max_width - width) / 2), + static_cast((max_height - height) / 2), + static_cast(width), + static_cast(height) + ); + return std::move(client_rect); +} + +int e2d::Game::GetWidth() const +{ + return width_; +} + +int e2d::Game::GetHeight() const +{ + return height_; +} + +e2d::Size e2d::Game::GetSize() const +{ + e2d::Size size( + static_cast(width_), + static_cast(height_) + ); + return std::move(size); +} + +HWND e2d::Game::GetHWnd() const +{ + return hwnd_; +} + +const e2d::String& e2d::Game::GetTitle() const +{ + return title_; +} + +void e2d::Game::SetSize(int width, int height) +{ + if (width_ == width && height_ == height) + return; + + width_ = width; + height_ = height; + + Rect rect = Locate(width, height); + ::MoveWindow( + hwnd_, + int(rect.origin.x), + int(rect.origin.y), + int(rect.size.width), + int(rect.size.height), + TRUE + ); +} + +void e2d::Game::SetTitle(const String& title) +{ + title_ = title; + + ::SetWindowText(hwnd_, (LPCWSTR)title); +} + +void e2d::Game::SetIcon(int resource_id) +{ + icon_ = resource_id; + + HICON icon = (HICON)::LoadImage( + HINST_THISCOMPONENT, + MAKEINTRESOURCE(resource_id), + IMAGE_ICON, + 0, + 0, + LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE + ); + + ::SendMessage(hwnd_, WM_SETICON, ICON_BIG, (LPARAM)icon); + ::SendMessage(hwnd_, WM_SETICON, ICON_SMALL, (LPARAM)icon); +} + + +LRESULT e2d::Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) +{ + LRESULT result = 0; + + if (msg == WM_CREATE) + { + LPCREATESTRUCT pcs = (LPCREATESTRUCT)l_param; + Game * game = (Game *)pcs->lpCreateParams; + + ::SetWindowLongPtrW( + hwnd, + GWLP_USERDATA, + PtrToUlong(game) + ); + + result = 1; + } + else + { + bool has_handled = false; + Game * game = reinterpret_cast( + static_cast( + ::GetWindowLongPtrW(hwnd, GWLP_USERDATA) + ) + ); + + switch (msg) + { + + // 处理鼠标消息 + case WM_LBUTTONUP: + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: + { + if (game->IsTransitioning()) + break; + + auto curr_scene = game->GetCurrentScene(); + if (curr_scene) + { + curr_scene->Dispatch(MouseEvent(msg, w_param, l_param)); + } + } + result = 0; + has_handled = true; + break; + + // 处理按键消息 + case WM_KEYDOWN: + case WM_KEYUP: + { + if (game->IsTransitioning()) + break; + + auto curr_scene = game->GetCurrentScene(); + if (curr_scene) + { + curr_scene->Dispatch(KeyEvent(msg, w_param, l_param)); + } + } + result = 0; + has_handled = true; + break; + + // 处理窗口大小变化消息 + case WM_SIZE: + { + UINT width = LOWORD(l_param); + UINT height = HIWORD(l_param); + + if (w_param == SIZE_RESTORED) + { + float dpi_x, dpi_y; + Graphics::GetFactory()->GetDesktopDpi(&dpi_x, &dpi_y); + game->width_ = static_cast(width * 96.f / dpi_x); + game->height_ = static_cast(height * 96.f / dpi_y); + } + + // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 + // 目标的大小。它可能会调用失败,但是这里可以忽略有可能的 + // 错误,因为这个错误将在下一次调用 EndDraw 时产生 + auto render_target = Graphics::Get()->GetRenderTarget(); + if (render_target) + { + render_target->Resize(D2D1::SizeU(width, height)); + } + } + break; + + // 处理窗口标题变化消息 + case WM_SETTEXT: + { + game->title_ = (const wchar_t*)l_param; + } + break; + + // 处理分辨率变化消息 + case WM_DISPLAYCHANGE: + { + // 重绘客户区 + ::InvalidateRect(hwnd, nullptr, FALSE); + } + result = 0; + has_handled = true; + break; + + // 重绘窗口 + case WM_PAINT: + { + game->DrawScene(); + ::ValidateRect(hwnd, nullptr); + } + result = 0; + has_handled = true; + break; + + // 窗口关闭消息 + case WM_CLOSE: + { + auto currScene = game->GetCurrentScene(); + if (!currScene || currScene->OnCloseWindow()) + { + game->Quit(); + } + } + result = 0; + has_handled = true; + break; + + // 窗口销毁消息 + case WM_DESTROY: + { + ::PostQuitMessage(0); + } + result = 1; + has_handled = true; + break; + + } + + if (!has_handled) + { + result = ::DefWindowProc(hwnd, msg, w_param, l_param); + } + } + return result; } diff --git a/core/modules/Renderer.cpp b/core/modules/Graphics.cpp similarity index 61% rename from core/modules/Renderer.cpp rename to core/modules/Graphics.cpp index d8475d96..153a1488 100644 --- a/core/modules/Renderer.cpp +++ b/core/modules/Graphics.cpp @@ -3,24 +3,24 @@ #include "..\e2dobject.h" -e2d::Renderer* e2d::Renderer::instance_ = nullptr; -ID2D1Factory* e2d::Renderer::factory_ = nullptr; -IWICImagingFactory* e2d::Renderer::imaging_factory_ = nullptr; -IDWriteFactory* e2d::Renderer::write_factory_ = nullptr; -ID2D1StrokeStyle* e2d::Renderer::miter_stroke_style_ = nullptr; -ID2D1StrokeStyle* e2d::Renderer::bevel_stroke_style_ = nullptr; -ID2D1StrokeStyle* e2d::Renderer::round_stroke_style_ = nullptr; +e2d::Graphics* e2d::Graphics::instance_ = nullptr; +ID2D1Factory* e2d::Graphics::factory_ = nullptr; +IWICImagingFactory* e2d::Graphics::imaging_factory_ = nullptr; +IDWriteFactory* e2d::Graphics::write_factory_ = nullptr; +ID2D1StrokeStyle* e2d::Graphics::miter_stroke_style_ = nullptr; +ID2D1StrokeStyle* e2d::Graphics::bevel_stroke_style_ = nullptr; +ID2D1StrokeStyle* e2d::Graphics::round_stroke_style_ = nullptr; -e2d::Renderer * e2d::Renderer::GetInstance() +e2d::Graphics * e2d::Graphics::GetInstance() { if (!instance_) { - instance_ = new (std::nothrow) Renderer; + instance_ = new (std::nothrow) Graphics; } return instance_; } -void e2d::Renderer::DestroyInstance() +void e2d::Graphics::DestroyInstance() { if (instance_) { @@ -36,7 +36,7 @@ void e2d::Renderer::DestroyInstance() } } -e2d::Renderer::Renderer() +e2d::Graphics::Graphics() : show_fps_(false) , last_render_time_(Time::Now()) , render_times_(0) @@ -50,7 +50,7 @@ e2d::Renderer::Renderer() ::CoInitialize(nullptr); } -e2d::Renderer::~Renderer() +e2d::Graphics::~Graphics() { SafeRelease(fps_text_format_); SafeRelease(fps_text_layout_); @@ -61,7 +61,7 @@ e2d::Renderer::~Renderer() ::CoUninitialize(); } -void e2d::Renderer::BeginDraw() +void e2d::Graphics::BeginDraw() { auto render_target = GetRenderTarget(); render_target->BeginDraw(); @@ -69,71 +69,8 @@ void e2d::Renderer::BeginDraw() render_target->Clear(clear_color_); } -void e2d::Renderer::EndDraw() +void e2d::Graphics::EndDraw() { - if (show_fps_) - { - int duration = (Time::Now() - last_render_time_).Milliseconds(); - - ++render_times_; - if (duration >= 100) - { - String fpsText = String::Format(L"FPS: %.1f", (1000.f / duration * render_times_)); - last_render_time_ = Time::Now(); - render_times_ = 0; - - if (!fps_text_format_) - { - ThrowIfFailed( - GetWriteFactory()->CreateTextFormat( - L"", - nullptr, - DWRITE_FONT_WEIGHT_NORMAL, - DWRITE_FONT_STYLE_NORMAL, - DWRITE_FONT_STRETCH_NORMAL, - 20, - L"", - &fps_text_format_ - ) - ); - - ThrowIfFailed( - fps_text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP) - ); - } - - SafeRelease(fps_text_layout_); - - ThrowIfFailed( - GetWriteFactory()->CreateTextLayout( - (const wchar_t *)fpsText, - (UINT32)fpsText.GetLength(), - fps_text_format_, - 0, - 0, - &fps_text_layout_ - ) - ); - } - - if (fps_text_layout_) - { - GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); - GetSolidBrush()->SetOpacity(1.0f); - GetTextRenderer()->SetTextStyle( - D2D1::ColorF(D2D1::ColorF::White), - TRUE, - D2D1::ColorF(D2D1::ColorF::Black, 0.4f), - 1.5f, - D2D1_LINE_JOIN_ROUND - ); - - ThrowIfFailed( - fps_text_layout_->Draw(nullptr, text_renderer_, 10, 0) - ); - } - } - HRESULT hr = render_target_->EndDraw(); if (hr == D2DERR_RECREATE_TARGET) @@ -152,7 +89,70 @@ void e2d::Renderer::EndDraw() ThrowIfFailed(hr); } -e2d::E2DTextRenderer * e2d::Renderer::GetTextRenderer() +void e2d::Graphics::DrawDebugInfo() +{ + int duration = (Time::Now() - last_render_time_).Milliseconds(); + + ++render_times_; + if (duration >= 100) + { + String fpsText = String::Format(L"FPS: %.1f", (1000.f / duration * render_times_)); + last_render_time_ = Time::Now(); + render_times_ = 0; + + if (!fps_text_format_) + { + ThrowIfFailed( + GetWriteFactory()->CreateTextFormat( + L"", + nullptr, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 20, + L"", + &fps_text_format_ + ) + ); + + ThrowIfFailed( + fps_text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP) + ); + } + + SafeRelease(fps_text_layout_); + + ThrowIfFailed( + GetWriteFactory()->CreateTextLayout( + (const wchar_t *)fpsText, + (UINT32)fpsText.GetLength(), + fps_text_format_, + 0, + 0, + &fps_text_layout_ + ) + ); + } + + if (fps_text_layout_) + { + GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); + GetSolidBrush()->SetOpacity(1.0f); + GetTextRenderer()->SetTextStyle( + D2D1::ColorF(D2D1::ColorF::White), + TRUE, + D2D1::ColorF(D2D1::ColorF::Black, 0.4f), + 1.5f, + D2D1_LINE_JOIN_ROUND + ); + + ThrowIfFailed( + fps_text_layout_->Draw(nullptr, text_renderer_, 10, 0) + ); + } +} + +e2d::E2DTextRenderer * e2d::Graphics::GetTextRenderer() { if (!text_renderer_) { @@ -169,11 +169,11 @@ e2d::E2DTextRenderer * e2d::Renderer::GetTextRenderer() return text_renderer_; } -ID2D1HwndRenderTarget * e2d::Renderer::GetRenderTarget() +ID2D1HwndRenderTarget * e2d::Graphics::GetRenderTarget() { if (!render_target_) { - HWND hwnd = Window::GetInstance()->GetHWnd(); + HWND hwnd = Game::Get()->GetHWnd(); RECT rc; GetClientRect(hwnd, &rc); @@ -199,7 +199,7 @@ ID2D1HwndRenderTarget * e2d::Renderer::GetRenderTarget() return render_target_; } -ID2D1SolidColorBrush * e2d::Renderer::GetSolidBrush() +ID2D1SolidColorBrush * e2d::Graphics::GetSolidBrush() { if (!solid_brush_) { @@ -213,22 +213,12 @@ ID2D1SolidColorBrush * e2d::Renderer::GetSolidBrush() return solid_brush_; } -e2d::Color e2d::Renderer::GetBackgroundColor() -{ - return clear_color_; -} - -void e2d::Renderer::SetBackgroundColor(const Color& color) -{ - clear_color_ = (D2D1_COLOR_F)color; -} - -void e2d::Renderer::ShowFps(bool show) +void e2d::Graphics::ShowFps(bool show) { show_fps_ = show; } -ID2D1Factory * e2d::Renderer::GetFactory() +ID2D1Factory * e2d::Graphics::GetFactory() { if (!factory_) { @@ -246,7 +236,7 @@ ID2D1Factory * e2d::Renderer::GetFactory() return factory_; } -IWICImagingFactory * e2d::Renderer::GetImagingFactory() +IWICImagingFactory * e2d::Graphics::GetImagingFactory() { if (!imaging_factory_) { @@ -267,7 +257,7 @@ IWICImagingFactory * e2d::Renderer::GetImagingFactory() return imaging_factory_; } -IDWriteFactory * e2d::Renderer::GetWriteFactory() +IDWriteFactory * e2d::Graphics::GetWriteFactory() { if (!write_factory_) { @@ -286,7 +276,7 @@ IDWriteFactory * e2d::Renderer::GetWriteFactory() return write_factory_; } -ID2D1StrokeStyle * e2d::Renderer::GetMiterStrokeStyle() +ID2D1StrokeStyle * e2d::Graphics::GetMiterStrokeStyle() { if (!miter_stroke_style_) { @@ -309,7 +299,7 @@ ID2D1StrokeStyle * e2d::Renderer::GetMiterStrokeStyle() return miter_stroke_style_; } -ID2D1StrokeStyle * e2d::Renderer::GetBevelStrokeStyle() +ID2D1StrokeStyle * e2d::Graphics::GetBevelStrokeStyle() { if (!bevel_stroke_style_) { @@ -332,7 +322,7 @@ ID2D1StrokeStyle * e2d::Renderer::GetBevelStrokeStyle() return bevel_stroke_style_; } -ID2D1StrokeStyle * e2d::Renderer::GetRoundStrokeStyle() +ID2D1StrokeStyle * e2d::Graphics::GetRoundStrokeStyle() { if (!round_stroke_style_) { diff --git a/core/modules/Window.cpp b/core/modules/Window.cpp index c4a15db2..9ea320c5 100644 --- a/core/modules/Window.cpp +++ b/core/modules/Window.cpp @@ -1,30 +1,5 @@ #include "..\e2dmodule.h" -#include "..\e2dmanager.h" -#include "..\e2dobject.h" -#include -#pragma comment (lib ,"imm32.lib") -#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME -#define REGISTER_CLASS L"Easy2DApp" - - -e2d::Window * e2d::Window::instance_ = nullptr; - -e2d::Window * e2d::Window::GetInstance() -{ - if (!instance_) - instance_ = new (std::nothrow) Window; - return instance_; -} - -void e2d::Window::DestroyInstance() -{ - if (instance_) - { - delete instance_; - instance_ = nullptr; - } -} e2d::Size e2d::Window::GetScreenSize() { @@ -37,229 +12,6 @@ e2d::Size e2d::Window::GetScreenSize() return std::move(screen_size); } -e2d::Window::Window() - : hwnd_(nullptr) - , width_(640) - , height_(480) - , title_(L"Easy2D Game") - , icon_id_(0) - , dpi_(0.f) -{ - ::CoInitialize(nullptr); - - // 获取系统 DPI - Renderer::GetFactory()->GetDesktopDpi(&dpi_, &dpi_); -} - -e2d::Window::~Window() -{ - if (::GetConsoleWindow()) - ::FreeConsole(); - - if (hwnd_) - ::DestroyWindow(hwnd_); - - ::CoUninitialize(); -} - -bool e2d::Window::CheckUnique() -{ - HANDLE mutex = ::CreateMutex(nullptr, TRUE, LPCWSTR(L"Easy2DApp-" + title_)); - - if (mutex == nullptr) - { - WARN("CreateMutex Failed!"); - return false; - } - else if (::GetLastError() == ERROR_ALREADY_EXISTS) - { - ::CloseHandle(mutex); - return false; - } - return true; -} - -e2d::Rect e2d::Window::Locate(int width, int height) -{ - Rect result; - RECT rect = { 0, 0, LONG(ceil(width * dpi_ / 96.f)), LONG(ceil(height * dpi_ / 96.f)) }; - int max_width = ::GetSystemMetrics(SM_CXSCREEN); - int max_height = ::GetSystemMetrics(SM_CYSCREEN); - - // 计算合适的窗口大小 - ::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); - width = static_cast(rect.right - rect.left); - height = static_cast(rect.bottom - rect.top); - - // 当输入的窗口大小比分辨率大时,给出警告 - WARN_IF(max_width < width || max_height < height, "The window Is larger than screen!"); - width = std::min(width, max_width); - height = std::min(height, max_height); - - float x = float((max_width - width) / 2), y = float((max_height - height) / 2); - return std::move(Rect(x, y, float(width), float(height))); -} - -void e2d::Window::Poll() -{ - while (::PeekMessage(&msg_, nullptr, 0, 0, PM_REMOVE)) - { - ::TranslateMessage(&msg_); - ::DispatchMessage(&msg_); - } -} - -int e2d::Window::GetWidth() const -{ - return width_; -} - -int e2d::Window::GetHeight() const -{ - return height_; -} - -e2d::Size e2d::Window::GetSize() const -{ - e2d::Size size( - static_cast(width_), - static_cast(height_) - ); - return std::move(size); -} - -float e2d::Window::GetDpi() const -{ - return dpi_; -} - -const e2d::String& e2d::Window::GetTitle() const -{ - return title_; -} - -HWND e2d::Window::GetHWnd() -{ - if (!hwnd_) - { - WNDCLASSEX wcex = { 0 }; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.lpszClassName = REGISTER_CLASS; - wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - wcex.lpfnWndProc = Window::WndProc; - wcex.hIcon = nullptr; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = sizeof(LONG_PTR); - wcex.hInstance = HINST_THISCOMPONENT; - wcex.hbrBackground = nullptr; - wcex.lpszMenuName = nullptr; - wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW); - - if (icon_id_ != 0) - { - wcex.hIcon = (HICON)::LoadImage( - HINST_THISCOMPONENT, - MAKEINTRESOURCE(icon_id_), - IMAGE_ICON, - 0, - 0, - LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE - ); - } - - // 注册窗口类 - RegisterClassEx(&wcex); - - // 计算窗口大小 - Rect clientRect = Locate(width_, height_); - - // 创建窗口 - hwnd_ = ::CreateWindowEx( - NULL, - REGISTER_CLASS, - (LPCTSTR)title_, - WINDOW_STYLE, - int(clientRect.origin.x), - int(clientRect.origin.y), - int(clientRect.size.width), - int(clientRect.size.height), - nullptr, - nullptr, - HINST_THISCOMPONENT, - this - ); - - if (hwnd_) - { - // 禁用输入法 - SetTypewritingEnabled(false); - // 禁用控制台关闭按钮 - HWND console_hwnd = ::GetConsoleWindow(); - if (console_hwnd) - { - HMENU hmenu = ::GetSystemMenu(console_hwnd, FALSE); - ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); - } - } - else - { - ::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT); - throw RuntimeException("Create window failed"); - } - } - return hwnd_; -} - -void e2d::Window::SetSize(int width, int height) -{ - if (width_ == width && height_ == height) - return; - - width_ = width; - height_ = height; - - if (hwnd_) - { - Rect rect = Locate(width, height); - ::MoveWindow( - hwnd_, - int(rect.origin.x), - int(rect.origin.y), - int(rect.size.width), - int(rect.size.height), - TRUE - ); - } -} - -void e2d::Window::SetTitle(const String& title) -{ - title_ = title; - if (hwnd_) - { - ::SetWindowText(hwnd_, (LPCWSTR)title); - } -} - -void e2d::Window::SetIcon(int resource_id) -{ - this->icon_id_ = resource_id; - if (hwnd_) - { - HICON icon = (HICON)::LoadImage( - HINST_THISCOMPONENT, - MAKEINTRESOURCE(resource_id), - IMAGE_ICON, - 0, - 0, - LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE - ); - // 设置窗口的图标 - ::SendMessage(hwnd_, WM_SETICON, ICON_BIG, (LPARAM)icon); - ::SendMessage(hwnd_, WM_SETICON, ICON_SMALL, (LPARAM)icon); - } -} - void e2d::Window::SetCursor(Cursor cursor) { LPCWSTR cursor_name = nullptr; @@ -296,7 +48,7 @@ void e2d::Window::SetCursor(Cursor cursor) } } -void e2d::Window::SetConsoleEnabled(bool enabled) +void e2d::Window::ShowConsole(bool enabled) { // 查找已存在的控制台句柄 HWND hwnd = ::GetConsoleWindow(); @@ -333,27 +85,6 @@ void e2d::Window::SetConsoleEnabled(bool enabled) } } -void e2d::Window::SetTypewritingEnabled(bool enabled) -{ - static HIMC himc = nullptr; - - if (enabled) - { - if (himc != nullptr) - { - ::ImmAssociateContext(GetHWnd(), himc); - himc = nullptr; - } - } - else - { - if (himc == nullptr) - { - himc = ::ImmAssociateContext(GetHWnd(), nullptr); - } - } -} - bool e2d::Window::Popup(const String & text, const String & title, PopupStyle style, bool has_cancel) { UINT type = 0; @@ -377,166 +108,6 @@ bool e2d::Window::Popup(const String & text, const String & title, PopupStyle st type |= MB_OKCANCEL; } - Game::GetInstance()->Pause(); - int ret = ::MessageBox(hwnd_, (LPCWSTR)text, (LPCWSTR)title, type); - Game::GetInstance()->Resume(); + int ret = ::MessageBoxW(nullptr, (LPCWSTR)text, (LPCWSTR)title, type); return ret == IDOK; } - - -LRESULT e2d::Window::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) -{ - LRESULT result = 0; - - if (msg == WM_CREATE) - { - LPCREATESTRUCT pcs = (LPCREATESTRUCT)l_param; - Window *window = (Window *)pcs->lpCreateParams; - - ::SetWindowLongPtrW( - hwnd, - GWLP_USERDATA, - PtrToUlong(window) - ); - - result = 1; - } - else - { - bool has_handled = false; - Window *window = reinterpret_cast( - static_cast( - ::GetWindowLongPtrW(hwnd, GWLP_USERDATA) - ) - ); - - switch (msg) - { - - // 处理鼠标消息 - case WM_LBUTTONUP: - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MOUSEMOVE: - case WM_MOUSEWHEEL: - { - auto game = Game::GetInstance(); - if (game->IsTransitioning()) - break; - - auto curr_scene = game->GetCurrentScene(); - if (curr_scene) - { - curr_scene->Dispatch(MouseEvent(msg, w_param, l_param)); - } - } - result = 0; - has_handled = true; - break; - - // 处理按键消息 - case WM_KEYDOWN: - case WM_KEYUP: - { - auto game = Game::GetInstance(); - if (game->IsTransitioning()) - break; - - auto curr_scene = game->GetCurrentScene(); - if (curr_scene) - { - curr_scene->Dispatch(KeyEvent(msg, w_param, l_param)); - } - } - result = 0; - has_handled = true; - break; - - // 处理窗口大小变化消息 - case WM_SIZE: - { - UINT width = LOWORD(l_param); - UINT height = HIWORD(l_param); - - if (w_param == SIZE_RESTORED) - { - window->width_ = static_cast(width * 96.f / window->dpi_); - window->height_ = static_cast(height * 96.f / window->dpi_); - } - - // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 - // 目标的大小。它可能会调用失败,但是这里可以忽略有可能的 - // 错误,因为这个错误将在下一次调用 EndDraw 时产生 - auto render_target = Renderer::GetInstance()->GetRenderTarget(); - if (render_target) - { - render_target->Resize(D2D1::SizeU(width, height)); - } - } - break; - - // 处理窗口标题变化消息 - case WM_SETTEXT: - { - window->title_ = (const wchar_t*)l_param; - } - break; - - // 处理分辨率变化消息 - case WM_DISPLAYCHANGE: - { - // 重绘客户区 - ::InvalidateRect(hwnd, nullptr, FALSE); - } - result = 0; - has_handled = true; - break; - - // 重绘窗口 - case WM_PAINT: - { - Game::GetInstance()->DrawScene(); - ::ValidateRect(hwnd, nullptr); - } - result = 0; - has_handled = true; - break; - - // 窗口关闭消息 - case WM_CLOSE: - { - auto game = Game::GetInstance(); - auto currScene = game->GetCurrentScene(); - if (!currScene || currScene->OnCloseWindow()) - { - game->Quit(); - } - } - result = 0; - has_handled = true; - break; - - // 窗口销毁消息 - case WM_DESTROY: - { - ::PostQuitMessage(0); - } - result = 1; - has_handled = true; - break; - - } - - if (!has_handled) - { - result = ::DefWindowProc(hwnd, msg, w_param, l_param); - } - } - return result; -} \ No newline at end of file diff --git a/core/objects/Canvas.cpp b/core/objects/Canvas.cpp index adbfa13d..1b997da5 100644 --- a/core/objects/Canvas.cpp +++ b/core/objects/Canvas.cpp @@ -9,7 +9,7 @@ e2d::Canvas::Canvas(float width, float height) , stroke_width_(1.0f) , stroke_(Stroke::Miter) { - render_target_ = Renderer::GetInstance()->GetRenderTarget(); + render_target_ = Graphics::Get()->GetRenderTarget(); render_target_->AddRef(); ThrowIfFailed( @@ -59,13 +59,13 @@ void e2d::Canvas::SetStrokeStyle(Stroke strokeStyle) switch (strokeStyle) { case e2d::Stroke::Miter: - stroke_style_ = Renderer::GetMiterStrokeStyle(); + stroke_style_ = Graphics::GetMiterStrokeStyle(); break; case e2d::Stroke::Bevel: - stroke_style_ = Renderer::GetBevelStrokeStyle(); + stroke_style_ = Graphics::GetBevelStrokeStyle(); break; case e2d::Stroke::Round: - stroke_style_ = Renderer::GetRoundStrokeStyle(); + stroke_style_ = Graphics::GetRoundStrokeStyle(); break; } } diff --git a/core/objects/Collider.cpp b/core/objects/Collider.cpp index 3d5951f9..d543a6f5 100644 --- a/core/objects/Collider.cpp +++ b/core/objects/Collider.cpp @@ -84,14 +84,14 @@ void e2d::Collider::Draw() { if (geometry_ && enabled_ && visible_) { - auto renderer = Renderer::GetInstance(); + auto graphics = Graphics::GetInstance(); // 获取纯色画刷 - ID2D1SolidColorBrush * brush = renderer->GetSolidBrush(); + ID2D1SolidColorBrush * brush = graphics->GetSolidBrush(); // 设置画刷颜色和透明度 brush->SetColor((D2D1_COLOR_F)border_color_); brush->SetOpacity(1.f); // 绘制几何碰撞体 - renderer->GetRenderTarget()->DrawGeometry(geometry_, brush, 1.5f); + graphics->GetRenderTarget()->DrawGeometry(geometry_, brush, 1.5f); } } @@ -135,7 +135,7 @@ void e2d::Collider::Recreate() return; SafeRelease(geometry_); - auto factory = Renderer::GetFactory(); + auto factory = Graphics::GetFactory(); switch (shape_) { diff --git a/core/objects/Image.cpp b/core/objects/Image.cpp index 941151d7..e746ed95 100644 --- a/core/objects/Image.cpp +++ b/core/objects/Image.cpp @@ -164,8 +164,8 @@ bool e2d::Image::Preload(const Resource& res) return true; } - IWICImagingFactory *imaging_factory = Renderer::GetImagingFactory(); - ID2D1HwndRenderTarget* render_target = Renderer::GetInstance()->GetRenderTarget(); + IWICImagingFactory *imaging_factory = Graphics::GetImagingFactory(); + ID2D1HwndRenderTarget* render_target = Graphics::GetInstance()->GetRenderTarget(); IWICBitmapDecoder *decoder = nullptr; IWICBitmapFrameDecode *source = nullptr; IWICStream *stream = nullptr; @@ -297,8 +297,8 @@ bool e2d::Image::Preload(const String & file_name) // 默认搜索路径,所以需要通过 File::GetPath 获取完整路径 String image_file_path = image_file.GetPath(); - IWICImagingFactory *imaging_factory = Renderer::GetImagingFactory(); - ID2D1HwndRenderTarget* render_target = Renderer::GetInstance()->GetRenderTarget(); + IWICImagingFactory *imaging_factory = Graphics::GetImagingFactory(); + ID2D1HwndRenderTarget* render_target = Graphics::GetInstance()->GetRenderTarget(); IWICBitmapDecoder *decoder = nullptr; IWICBitmapFrameDecode *source = nullptr; IWICStream *stream = nullptr; diff --git a/core/objects/Node.cpp b/core/objects/Node.cpp index 8f8e22b0..eba54fa3 100644 --- a/core/objects/Node.cpp +++ b/core/objects/Node.cpp @@ -52,21 +52,18 @@ void e2d::Node::Visit() if (!visible_) return; - if (!Game::GetInstance()->IsPaused()) - { - UpdateActions(); - UpdateTasks(); + UpdateActions(); + UpdateTasks(); - auto updatable_node = dynamic_cast(this); - if (updatable_node) - { - updatable_node->Update(); - } + auto updatable_node = dynamic_cast(this); + if (updatable_node) + { + updatable_node->Update(); } UpdateTransform(); - auto render_target = Renderer::GetInstance()->GetRenderTarget(); + auto render_target = Graphics::Get()->GetRenderTarget(); if (clip_enabled_) { render_target->SetTransform(final_matrix_); @@ -138,10 +135,10 @@ void e2d::Node::DrawBorder() { if (border_) { - auto renderer = Renderer::GetInstance(); - auto brush = renderer->GetSolidBrush(); + auto graphics = Graphics::Get(); + auto brush = graphics->GetSolidBrush(); brush->SetColor(D2D1_COLOR_F(border_color_)); - renderer->GetRenderTarget()->DrawGeometry( + graphics->GetRenderTarget()->DrawGeometry( border_, brush, 1.5f @@ -198,7 +195,7 @@ void e2d::Node::UpdateTransform() // 重新构造轮廓 SafeRelease(border_); - ID2D1Factory * factory = Renderer::GetFactory(); + ID2D1Factory * factory = Graphics::GetFactory(); ID2D1RectangleGeometry * rectangle = nullptr; ID2D1TransformedGeometry * transformed = nullptr; ThrowIfFailed( diff --git a/core/objects/Scene.cpp b/core/objects/Scene.cpp index 0b64a647..bdefcb15 100644 --- a/core/objects/Scene.cpp +++ b/core/objects/Scene.cpp @@ -3,16 +3,12 @@ e2d::Scene::Scene() : root_(nullptr) - , border_visible_(false) - , collider_visible_(false) , transform_(D2D1::Matrix3x2F::Identity()) { } e2d::Scene::Scene(Node * root) : root_(nullptr) - , border_visible_(false) - , collider_visible_(false) , transform_(D2D1::Matrix3x2F::Identity()) { this->SetRoot(root); @@ -52,34 +48,11 @@ e2d::Node * e2d::Scene::GetRoot() const return root_; } -void e2d::Scene::ShowBorder(bool visible) -{ - border_visible_ = visible; -} - -void e2d::Scene::ShowCollider(bool visible) -{ - collider_visible_ = visible; -} - void e2d::Scene::Draw() { if (root_) { root_->Visit(); - - if (border_visible_) - { - Renderer::GetInstance()->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); - Renderer::GetInstance()->GetSolidBrush()->SetOpacity(1.f); - root_->DrawBorder(); - } - - if (collider_visible_) - { - Renderer::GetInstance()->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); - root_->DrawCollider(); - } } } diff --git a/core/objects/Sprite.cpp b/core/objects/Sprite.cpp index 12a39f55..90cfc66b 100644 --- a/core/objects/Sprite.cpp +++ b/core/objects/Sprite.cpp @@ -93,6 +93,15 @@ bool e2d::Sprite::Open(const String & file_name) return false; } +void e2d::Sprite::Crop(const Rect& crop_rect) +{ + image_->Crop(crop_rect); + Node::SetSize( + std::min(std::max(crop_rect.size.width, 0.f), image_->GetSourceWidth() - image_->GetCropX()), + std::min(std::max(crop_rect.size.height, 0.f), image_->GetSourceHeight() - image_->GetCropY()) + ); +} + e2d::Image * e2d::Sprite::GetImage() const { return image_; @@ -105,7 +114,7 @@ void e2d::Sprite::Draw() const // 获取图片裁剪位置 auto crop_pos = image_->GetCropPos(); // 渲染图片 - Renderer::GetInstance()->GetRenderTarget()->DrawBitmap( + Graphics::Get()->GetRenderTarget()->DrawBitmap( image_->GetBitmap(), D2D1::RectF(0, 0, transform_.size.width, transform_.size.height), display_opacity_, diff --git a/core/objects/Text.cpp b/core/objects/Text.cpp index cac7ba48..dfc09bea 100644 --- a/core/objects/Text.cpp +++ b/core/objects/Text.cpp @@ -292,13 +292,13 @@ void e2d::Text::Draw() const { if (text_layout_) { - auto renderer = Renderer::GetInstance(); + auto graphics = Graphics::GetInstance(); // 创建文本区域 D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, transform_.size.width, transform_.size.height); // 设置画刷颜色和透明度 - renderer->GetSolidBrush()->SetOpacity(display_opacity_); + graphics->GetSolidBrush()->SetOpacity(display_opacity_); // 获取文本渲染器 - auto textRenderer = renderer->GetTextRenderer(); + auto textRenderer = graphics->GetTextRenderer(); textRenderer->SetTextStyle( (D2D1_COLOR_F)style_.color, style_.outline, @@ -323,7 +323,7 @@ void e2d::Text::CreateFormat() SafeRelease(text_format_); ThrowIfFailed( - Renderer::GetWriteFactory()->CreateTextFormat( + Graphics::GetWriteFactory()->CreateTextFormat( (const wchar_t *)font_.family, nullptr, DWRITE_FONT_WEIGHT(font_.weight), @@ -381,7 +381,7 @@ void e2d::Text::CreateLayout() } UINT32 length = (UINT32)text_.GetLength(); - auto writeFactory = Renderer::GetWriteFactory(); + auto writeFactory = Graphics::GetWriteFactory(); // 对文本自动换行情况下进行处理 if (style_.wrap) diff --git a/core/transitions/Transition.cpp b/core/transitions/Transition.cpp index fd04c6e0..a449fa6d 100644 --- a/core/transitions/Transition.cpp +++ b/core/transitions/Transition.cpp @@ -42,18 +42,18 @@ void e2d::Transition::Init(Scene * prev, Scene * next) if (in_scene_) in_scene_->Retain(); - auto renderer = Renderer::GetInstance(); + auto graphics = Graphics::GetInstance(); if (in_scene_) { ThrowIfFailed( - renderer->GetRenderTarget()->CreateLayer(&in_layer_) + graphics->GetRenderTarget()->CreateLayer(&in_layer_) ); } if (out_scene_) { ThrowIfFailed( - renderer->GetRenderTarget()->CreateLayer(&out_layer_) + graphics->GetRenderTarget()->CreateLayer(&out_layer_) ); } @@ -69,7 +69,7 @@ void e2d::Transition::Init(Scene * prev, Scene * next) D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, D2D1::Matrix3x2F::Identity(), 1.f, - renderer->GetSolidBrush(), + graphics->GetSolidBrush(), D2D1_LAYER_OPTIONS_NONE ); } @@ -94,7 +94,7 @@ void e2d::Transition::Update() void e2d::Transition::Draw() { - auto render_target = Renderer::GetInstance()->GetRenderTarget(); + auto render_target = Graphics::GetInstance()->GetRenderTarget(); if (out_scene_) { diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index ee60ed9b..1e4a0ed4 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -229,7 +229,7 @@ - + diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index b6ff1f86..00c7e0cc 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -108,9 +108,6 @@ modules - - modules - modules @@ -234,6 +231,9 @@ utils + + modules +