fix: the problem of window message loop blocking main loop
This commit is contained in:
parent
523262866a
commit
91508fd7cf
|
|
@ -19,17 +19,17 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Scene.h"
|
|
||||||
#include "Transition.h"
|
|
||||||
#include "Image.h"
|
|
||||||
#include "../utils/Player.h"
|
|
||||||
#include "../math/Matrix.hpp"
|
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
#include "Scene.h"
|
||||||
|
#include "Transition.h"
|
||||||
|
#include "../math/Matrix.hpp"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <imm.h>
|
||||||
|
#pragma comment (lib ,"imm32.lib")
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
|
|
@ -40,6 +40,8 @@ namespace easy2d
|
||||||
, transition_(nullptr)
|
, transition_(nullptr)
|
||||||
, debug_enabled_(false)
|
, debug_enabled_(false)
|
||||||
, initialized_(false)
|
, initialized_(false)
|
||||||
|
, hwnd_(nullptr)
|
||||||
|
, window_inactived_(false)
|
||||||
{
|
{
|
||||||
::CoInitialize(nullptr);
|
::CoInitialize(nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -62,26 +64,41 @@ namespace easy2d
|
||||||
|
|
||||||
debug_enabled_ = options.debug;
|
debug_enabled_ = options.debug;
|
||||||
|
|
||||||
Window::Instance()->Init(options.title, options.width, options.height, options.icon, debug_enabled_);
|
Window::Instance()->Init(
|
||||||
devices::Graphics::Instance()->Init(Window::Instance()->GetHandle(), debug_enabled_);
|
options.title,
|
||||||
devices::Input::Instance()->Init(debug_enabled_);
|
options.width,
|
||||||
|
options.height,
|
||||||
|
options.icon,
|
||||||
|
Game::WndProc,
|
||||||
|
debug_enabled_
|
||||||
|
);
|
||||||
|
|
||||||
|
const auto window = Window::Instance();
|
||||||
|
hwnd_ = window->GetHandle();
|
||||||
|
|
||||||
|
::SetWindowLongW(hwnd_, GWLP_USERDATA, PtrToUlong(this));
|
||||||
|
|
||||||
|
devices::Graphics::Instance()->Init(hwnd_, debug_enabled_);
|
||||||
|
devices::Input::Instance()->Init(hwnd_, window->GetContentScaleX(), window->GetContentScaleY(), debug_enabled_);
|
||||||
devices::Audio::Instance()->Init(debug_enabled_);
|
devices::Audio::Instance()->Init(debug_enabled_);
|
||||||
|
|
||||||
|
// disable imm
|
||||||
|
::ImmAssociateContext(hwnd_, nullptr);
|
||||||
|
|
||||||
HWND console = ::GetConsoleWindow();
|
HWND console = ::GetConsoleWindow();
|
||||||
if (debug_enabled_)
|
if (debug_enabled_)
|
||||||
{
|
{
|
||||||
if (console == nullptr)
|
if (console == nullptr)
|
||||||
{
|
{
|
||||||
// 显示一个新控制台
|
|
||||||
if (::AllocConsole())
|
if (::AllocConsole())
|
||||||
{
|
{
|
||||||
console = ::GetConsoleWindow();
|
console = ::GetConsoleWindow();
|
||||||
// 重定向输入输出
|
|
||||||
FILE * stdoutStream, *stdinStream, *stderrStream;
|
FILE * stdoutStream, *stdinStream, *stderrStream;
|
||||||
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
||||||
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
||||||
freopen_s(&stderrStream, "conout$", "w+t", stderr);
|
freopen_s(&stderrStream, "conout$", "w+t", stderr);
|
||||||
// 禁用控制台关闭按钮
|
|
||||||
|
// disable the close button of console
|
||||||
HMENU hmenu = ::GetSystemMenu(console, FALSE);
|
HMENU hmenu = ::GetSystemMenu(console, FALSE);
|
||||||
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
||||||
}
|
}
|
||||||
|
|
@ -95,12 +112,6 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::SetWindowLongPtrW(
|
|
||||||
Window::Instance()->GetHandle(),
|
|
||||||
GWLP_USERDATA,
|
|
||||||
PtrToUlong(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,46 +126,14 @@ namespace easy2d
|
||||||
next_scene_ = nullptr;
|
next_scene_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto window = Window::Instance();
|
::ShowWindow(hwnd_, SW_SHOWNORMAL);
|
||||||
::ShowWindow(window->GetHandle(), SW_SHOWNORMAL);
|
::UpdateWindow(hwnd_);
|
||||||
::UpdateWindow(window->GetHandle());
|
|
||||||
window->Poll();
|
|
||||||
|
|
||||||
const int64_t min_interval = 5;
|
MSG msg = {};
|
||||||
auto last = time::Now();
|
while (::GetMessageW(&msg, nullptr, 0, 0) && !quit_)
|
||||||
|
|
||||||
while (!quit_)
|
|
||||||
{
|
{
|
||||||
auto now = time::Now();
|
::TranslateMessage(&msg);
|
||||||
auto dur = now - last;
|
::DispatchMessageW(&msg);
|
||||||
|
|
||||||
if (dur.Milliseconds() > min_interval)
|
|
||||||
{
|
|
||||||
const auto dt = now - last;
|
|
||||||
last = now;
|
|
||||||
|
|
||||||
devices::Input::Instance()->Update(
|
|
||||||
window->GetHandle(),
|
|
||||||
window->GetContentScaleX(),
|
|
||||||
window->GetContentScaleY()
|
|
||||||
);
|
|
||||||
|
|
||||||
UpdateScene(dt);
|
|
||||||
DrawScene();
|
|
||||||
|
|
||||||
window->Poll();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ID2D1HwndRenderTarget 开启了垂直同步,在渲染时会等待显示器刷新,
|
|
||||||
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
|
|
||||||
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
|
|
||||||
int64_t wait = min_interval - dur.Milliseconds();
|
|
||||||
if (wait > 1LL)
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,31 +180,31 @@ namespace easy2d
|
||||||
return curr_scene_;
|
return curr_scene_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::UpdateScene(Duration const& dt)
|
void Game::Update()
|
||||||
{
|
{
|
||||||
|
static auto last = time::Now();
|
||||||
|
|
||||||
|
const auto now = time::Now();
|
||||||
|
const auto dt = now - last;
|
||||||
|
last = now;
|
||||||
|
|
||||||
|
devices::Input::Instance()->Update();
|
||||||
|
|
||||||
if (curr_scene_)
|
if (curr_scene_)
|
||||||
{
|
|
||||||
curr_scene_->Update(dt);
|
curr_scene_->Update(dt);
|
||||||
}
|
|
||||||
|
|
||||||
if (next_scene_)
|
if (next_scene_)
|
||||||
{
|
|
||||||
next_scene_->Update(dt);
|
next_scene_->Update(dt);
|
||||||
}
|
|
||||||
|
|
||||||
if (transition_)
|
if (transition_)
|
||||||
{
|
{
|
||||||
transition_->Update(dt);
|
transition_->Update(dt);
|
||||||
|
|
||||||
if (transition_->IsDone())
|
if (transition_->IsDone())
|
||||||
{
|
|
||||||
transition_ = nullptr;
|
transition_ = nullptr;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (next_scene_)
|
if (next_scene_)
|
||||||
{
|
{
|
||||||
|
|
@ -241,32 +220,14 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::Dispatch(MouseEvent const & e)
|
void Game::Render()
|
||||||
{
|
|
||||||
if (transition_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (curr_scene_)
|
|
||||||
curr_scene_->Dispatch(e, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::Dispatch(KeyEvent const & e)
|
|
||||||
{
|
|
||||||
if (transition_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (curr_scene_)
|
|
||||||
curr_scene_->Dispatch(e, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::DrawScene()
|
|
||||||
{
|
{
|
||||||
auto graphics = devices::Graphics::Instance();
|
auto graphics = devices::Graphics::Instance();
|
||||||
graphics->BeginDraw(Window::Instance()->GetHandle());
|
graphics->BeginDraw(hwnd_);
|
||||||
|
|
||||||
if (transition_)
|
if (transition_)
|
||||||
{
|
{
|
||||||
transition_->Draw();
|
transition_->Render();
|
||||||
}
|
}
|
||||||
else if (curr_scene_)
|
else if (curr_scene_)
|
||||||
{
|
{
|
||||||
|
|
@ -292,5 +253,134 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics->EndDraw();
|
graphics->EndDraw();
|
||||||
|
|
||||||
|
if (!window_inactived_)
|
||||||
|
::InvalidateRect(hwnd_, NULL, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::Dispatch(MouseEvent const & e)
|
||||||
|
{
|
||||||
|
if (transition_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curr_scene_)
|
||||||
|
curr_scene_->Dispatch(e, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::Dispatch(KeyEvent const & e)
|
||||||
|
{
|
||||||
|
if (transition_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curr_scene_)
|
||||||
|
curr_scene_->Dispatch(e, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||||
|
{
|
||||||
|
LRESULT result = 0;
|
||||||
|
bool was_handled = false;
|
||||||
|
|
||||||
|
Game * game = reinterpret_cast<Game*>(
|
||||||
|
static_cast<LONG_PTR>(::GetWindowLongW(hwnd, GWLP_USERDATA))
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
::BeginPaint(hwnd, &ps);
|
||||||
|
|
||||||
|
game->Update();
|
||||||
|
game->Render();
|
||||||
|
|
||||||
|
::EndPaint(hwnd, &ps);
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
game->Dispatch(MouseEvent(msg, w_param, l_param));
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
{
|
||||||
|
game->Dispatch(KeyEvent(msg, w_param, l_param));
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
if (SIZE_MAXHIDE == w_param || SIZE_MINIMIZED == w_param)
|
||||||
|
game->window_inactived_ = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game->window_inactived_ = false;
|
||||||
|
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT width = LOWORD(l_param);
|
||||||
|
UINT height = HIWORD(l_param);
|
||||||
|
|
||||||
|
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
|
||||||
|
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
|
||||||
|
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
|
||||||
|
devices::Graphics::Instance()->Resize(width, height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
{
|
||||||
|
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
if (game->OnClose())
|
||||||
|
{
|
||||||
|
game->Quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
{
|
||||||
|
::PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
result = 1;
|
||||||
|
was_handled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!was_handled)
|
||||||
|
{
|
||||||
|
result = ::DefWindowProcW(hwnd, msg, w_param, l_param);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,11 +89,10 @@ namespace easy2d
|
||||||
// »ñÈ¡µ±Ç°³¡¾°
|
// »ñÈ¡µ±Ç°³¡¾°
|
||||||
spScene const& GetCurrentScene();
|
spScene const& GetCurrentScene();
|
||||||
|
|
||||||
void DrawScene();
|
private:
|
||||||
|
void Render();
|
||||||
|
|
||||||
void UpdateScene(
|
void Update();
|
||||||
Duration const& dt
|
|
||||||
);
|
|
||||||
|
|
||||||
void Dispatch(
|
void Dispatch(
|
||||||
MouseEvent const& e
|
MouseEvent const& e
|
||||||
|
|
@ -103,10 +102,14 @@ namespace easy2d
|
||||||
KeyEvent const& e
|
KeyEvent const& e
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
bool debug_enabled_;
|
bool debug_enabled_;
|
||||||
bool quit_;
|
bool quit_;
|
||||||
|
bool window_inactived_;
|
||||||
|
HWND hwnd_;
|
||||||
spScene curr_scene_;
|
spScene curr_scene_;
|
||||||
spScene next_scene_;
|
spScene next_scene_;
|
||||||
spTransition transition_;
|
spTransition transition_;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
InputDevice::InputDevice()
|
InputDevice::InputDevice()
|
||||||
: initialized(false)
|
: initialized(false)
|
||||||
|
, hwnd_(nullptr)
|
||||||
|
, scale_x_(1.f)
|
||||||
|
, scale_y_(1.f)
|
||||||
{
|
{
|
||||||
ZeroMemory(keys_, sizeof(keys_));
|
ZeroMemory(keys_, sizeof(keys_));
|
||||||
ZeroMemory(keys_cache_, sizeof(keys_cache_));
|
ZeroMemory(keys_cache_, sizeof(keys_cache_));
|
||||||
|
|
@ -38,26 +41,30 @@ namespace easy2d
|
||||||
E2D_LOG("Destroying input device");
|
E2D_LOG("Destroying input device");
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDevice::Init(bool debug)
|
void InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
|
||||||
{
|
{
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
E2D_LOG("Initing input device");
|
E2D_LOG("Initing input device");
|
||||||
|
|
||||||
|
hwnd_ = hwnd;
|
||||||
|
scale_x_ = scale_x;
|
||||||
|
scale_y_ = scale_y;
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDevice::Update(HWND hwnd, float scale_x, float scale_y)
|
void InputDevice::Update()
|
||||||
{
|
{
|
||||||
memcpy(keys_cache_, keys_, sizeof(keys_cache_));
|
memcpy(keys_cache_, keys_, sizeof(keys_cache_));
|
||||||
GetKeyboardState(keys_);
|
GetKeyboardState(keys_);
|
||||||
|
|
||||||
POINT client_cursor_pos;
|
POINT client_cursor_pos;
|
||||||
GetCursorPos(&client_cursor_pos);
|
GetCursorPos(&client_cursor_pos);
|
||||||
ScreenToClient(hwnd, &client_cursor_pos);
|
ScreenToClient(hwnd_, &client_cursor_pos);
|
||||||
|
|
||||||
mouse_pos_ = Point(client_cursor_pos.x * scale_x, client_cursor_pos.y * scale_y);
|
mouse_pos_ = Point(client_cursor_pos.x * scale_x_, client_cursor_pos.y * scale_y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputDevice::IsDown(KeyCode code)
|
bool InputDevice::IsDown(KeyCode code)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace easy2d
|
||||||
E2D_DECLARE_SINGLETON(InputDevice);
|
E2D_DECLARE_SINGLETON(InputDevice);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(bool debug);
|
void Init(HWND hwnd, float scale_x, float scale_y, bool debug);
|
||||||
|
|
||||||
// 检测键盘某按键是否正被按下
|
// 检测键盘某按键是否正被按下
|
||||||
bool IsDown(
|
bool IsDown(
|
||||||
|
|
@ -63,12 +63,7 @@ namespace easy2d
|
||||||
// 获得鼠标坐标值
|
// 获得鼠标坐标值
|
||||||
Point GetMousePos();
|
Point GetMousePos();
|
||||||
|
|
||||||
// 刷新设备状态
|
void Update();
|
||||||
void Update(
|
|
||||||
HWND hwnd,
|
|
||||||
float scale_x,
|
|
||||||
float scale_y
|
|
||||||
);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
InputDevice();
|
InputDevice();
|
||||||
|
|
@ -77,6 +72,9 @@ namespace easy2d
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
HWND hwnd_;
|
||||||
|
float scale_x_;
|
||||||
|
float scale_y_;
|
||||||
BYTE keys_[256];
|
BYTE keys_[256];
|
||||||
BYTE keys_cache_[256];
|
BYTE keys_cache_[256];
|
||||||
Point mouse_pos_;
|
Point mouse_pos_;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transition::Draw()
|
void Transition::Render()
|
||||||
{
|
{
|
||||||
auto graphics = devices::Graphics::Instance();
|
auto graphics = devices::Graphics::Instance();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace easy2d
|
||||||
|
|
||||||
virtual void Update(Duration const& dt);
|
virtual void Update(Duration const& dt);
|
||||||
|
|
||||||
virtual void Draw();
|
virtual void Render();
|
||||||
|
|
||||||
virtual void Stop();
|
virtual void Stop();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ namespace easy2d
|
||||||
, fps_text_layout_(nullptr)
|
, fps_text_layout_(nullptr)
|
||||||
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
||||||
, opacity_(1.f)
|
, opacity_(1.f)
|
||||||
|
, window_occluded(false)
|
||||||
, initialized(false)
|
, initialized(false)
|
||||||
{
|
{
|
||||||
ZeroMemory(&d2d, sizeof(D2DResources));
|
ZeroMemory(&d2d, sizeof(D2DResources));
|
||||||
|
|
@ -130,11 +131,18 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
CreateDeviceResources(hwnd);
|
CreateDeviceResources(hwnd);
|
||||||
|
|
||||||
|
window_occluded = !!(d2d.render_target->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
|
||||||
|
|
||||||
|
if (!window_occluded)
|
||||||
|
{
|
||||||
d2d.render_target->BeginDraw();
|
d2d.render_target->BeginDraw();
|
||||||
d2d.render_target->Clear(clear_color_);
|
d2d.render_target->Clear(clear_color_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsDevice::EndDraw()
|
void GraphicsDevice::EndDraw()
|
||||||
|
{
|
||||||
|
if (!window_occluded)
|
||||||
{
|
{
|
||||||
HRESULT hr = d2d.render_target->EndDraw();
|
HRESULT hr = d2d.render_target->EndDraw();
|
||||||
|
|
||||||
|
|
@ -153,6 +161,7 @@ namespace easy2d
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsDevice::ClearImageCache()
|
void GraphicsDevice::ClearImageCache()
|
||||||
{
|
{
|
||||||
|
|
@ -375,6 +384,9 @@ namespace easy2d
|
||||||
!d2d.render_target)
|
!d2d.render_target)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.solid_brush->SetColor(border_color);
|
d2d.solid_brush->SetColor(border_color);
|
||||||
d2d.render_target->DrawGeometry(
|
d2d.render_target->DrawGeometry(
|
||||||
geometry.Get(),
|
geometry.Get(),
|
||||||
|
|
@ -393,6 +405,9 @@ namespace easy2d
|
||||||
if (!image->GetBitmap())
|
if (!image->GetBitmap())
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.render_target->DrawBitmap(
|
d2d.render_target->DrawBitmap(
|
||||||
image->GetBitmap().Get(),
|
image->GetBitmap().Get(),
|
||||||
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
|
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
|
||||||
|
|
@ -427,6 +442,9 @@ namespace easy2d
|
||||||
if (!d2d.render_target)
|
if (!d2d.render_target)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
// Do not crop bitmap
|
// Do not crop bitmap
|
||||||
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
|
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
|
||||||
d2d.render_target->DrawBitmap(
|
d2d.render_target->DrawBitmap(
|
||||||
|
|
@ -444,6 +462,9 @@ namespace easy2d
|
||||||
if (!d2d.text_renderer)
|
if (!d2d.text_renderer)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
return text_layout->Draw(nullptr, d2d.text_renderer.Get(), 0, 0);
|
return text_layout->Draw(nullptr, d2d.text_renderer.Get(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,6 +473,9 @@ namespace easy2d
|
||||||
if (!d2d.render_target)
|
if (!d2d.render_target)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.render_target->SetTransform(ConvertToD2DMatrix(clip_matrix));
|
d2d.render_target->SetTransform(ConvertToD2DMatrix(clip_matrix));
|
||||||
d2d.render_target->PushAxisAlignedClip(
|
d2d.render_target->PushAxisAlignedClip(
|
||||||
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
|
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
|
||||||
|
|
@ -465,6 +489,9 @@ namespace easy2d
|
||||||
if (!d2d.render_target)
|
if (!d2d.render_target)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.render_target->PopAxisAlignedClip();
|
d2d.render_target->PopAxisAlignedClip();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -475,6 +502,9 @@ namespace easy2d
|
||||||
!d2d.solid_brush)
|
!d2d.solid_brush)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.render_target->PushLayer(
|
d2d.render_target->PushLayer(
|
||||||
D2D1::LayerParameters(
|
D2D1::LayerParameters(
|
||||||
properties.area,
|
properties.area,
|
||||||
|
|
@ -495,6 +525,9 @@ namespace easy2d
|
||||||
if (!d2d.render_target)
|
if (!d2d.render_target)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
if (window_occluded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
d2d.render_target->PopLayer();
|
d2d.render_target->PopLayer();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ namespace easy2d
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
bool window_occluded;
|
||||||
float opacity_;
|
float opacity_;
|
||||||
D2DResources d2d;
|
D2DResources d2d;
|
||||||
D2D1_COLOR_F clear_color_;
|
D2D1_COLOR_F clear_color_;
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,7 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
#include "Game.h"
|
|
||||||
#include "KeyEvent.h"
|
|
||||||
#include "MouseEvent.h"
|
|
||||||
#include "../math/scalar.hpp"
|
#include "../math/scalar.hpp"
|
||||||
#include <imm.h>
|
|
||||||
#pragma comment (lib ,"imm32.lib")
|
|
||||||
|
|
||||||
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
|
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
|
||||||
#define REGISTER_CLASS L"Easy2DApp"
|
#define REGISTER_CLASS L"Easy2DApp"
|
||||||
|
|
@ -38,8 +33,6 @@ namespace easy2d
|
||||||
void GetContentScale(float* scale_x, float* scale_y);
|
void GetContentScale(float* scale_x, float* scale_y);
|
||||||
|
|
||||||
Rect LocateWindow(int width, int height, float scale_x, float scale_y);
|
Rect LocateWindow(int width, int height, float scale_x, float scale_y);
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowImpl::WindowImpl()
|
WindowImpl::WindowImpl()
|
||||||
|
|
@ -58,7 +51,7 @@ namespace easy2d
|
||||||
::DestroyWindow(handle);
|
::DestroyWindow(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowImpl::Init(String title, int width, int height, LPCWSTR icon, bool debug)
|
void WindowImpl::Init(String title, int width, int height, LPCWSTR icon, WNDPROC proc, bool debug)
|
||||||
{
|
{
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return;
|
return;
|
||||||
|
|
@ -70,7 +63,7 @@ namespace easy2d
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
wcex.lpszClassName = REGISTER_CLASS;
|
wcex.lpszClassName = REGISTER_CLASS;
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||||
wcex.lpfnWndProc = WndProc;
|
wcex.lpfnWndProc = proc;
|
||||||
wcex.hIcon = nullptr;
|
wcex.hIcon = nullptr;
|
||||||
wcex.cbClsExtra = 0;
|
wcex.cbClsExtra = 0;
|
||||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
wcex.cbWndExtra = sizeof(LONG_PTR);
|
||||||
|
|
@ -123,9 +116,6 @@ namespace easy2d
|
||||||
throw std::runtime_error(err);
|
throw std::runtime_error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁用输入法
|
|
||||||
::ImmAssociateContext(handle, nullptr);
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,17 +210,6 @@ namespace easy2d
|
||||||
return scale_y;
|
return scale_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowImpl::Poll()
|
|
||||||
{
|
|
||||||
static MSG msg = {};
|
|
||||||
|
|
||||||
while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
::TranslateMessage(&msg);
|
|
||||||
::DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void GetContentScale(float* scale_x, float* scale_y)
|
void GetContentScale(float* scale_x, float* scale_y)
|
||||||
|
|
@ -276,109 +255,5 @@ namespace easy2d
|
||||||
static_cast<float>(height)
|
static_cast<float>(height)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
|
||||||
{
|
|
||||||
LRESULT result = 0;
|
|
||||||
bool was_handled = false;
|
|
||||||
|
|
||||||
Game * game = reinterpret_cast<Game*>(
|
|
||||||
static_cast<LONG_PTR>(::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:
|
|
||||||
{
|
|
||||||
game->Dispatch(MouseEvent(msg, w_param, l_param));
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 处理按键消息
|
|
||||||
case WM_KEYDOWN:
|
|
||||||
case WM_KEYUP:
|
|
||||||
{
|
|
||||||
game->Dispatch(KeyEvent(msg, w_param, l_param));
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 处理窗口大小变化消息
|
|
||||||
case WM_SIZE:
|
|
||||||
{
|
|
||||||
UINT width = LOWORD(l_param);
|
|
||||||
UINT height = HIWORD(l_param);
|
|
||||||
|
|
||||||
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
|
|
||||||
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
|
|
||||||
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
|
|
||||||
devices::Graphics::Instance()->Resize(width, height);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 处理分辨率变化消息
|
|
||||||
case WM_DISPLAYCHANGE:
|
|
||||||
{
|
|
||||||
// 重绘客户区
|
|
||||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 重绘窗口
|
|
||||||
case WM_PAINT:
|
|
||||||
{
|
|
||||||
game->DrawScene();
|
|
||||||
::ValidateRect(hwnd, nullptr);
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 窗口关闭消息
|
|
||||||
case WM_CLOSE:
|
|
||||||
{
|
|
||||||
if (game->OnClose())
|
|
||||||
{
|
|
||||||
game->Quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = 0;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// 窗口销毁消息
|
|
||||||
case WM_DESTROY:
|
|
||||||
{
|
|
||||||
::PostQuitMessage(0);
|
|
||||||
}
|
|
||||||
result = 1;
|
|
||||||
was_handled = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!was_handled)
|
|
||||||
{
|
|
||||||
result = ::DefWindowProc(hwnd, msg, w_param, l_param);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ namespace easy2d
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
LPCWSTR icon,
|
LPCWSTR icon,
|
||||||
|
WNDPROC proc,
|
||||||
bool debug
|
bool debug
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -65,8 +66,6 @@ namespace easy2d
|
||||||
|
|
||||||
float GetContentScaleY() const;
|
float GetContentScaleY() const;
|
||||||
|
|
||||||
void Poll();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WindowImpl();
|
WindowImpl();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue