update box2d-sample

minor

minor

minor

refactoring Events

minor
This commit is contained in:
Nomango 2019-02-12 16:12:15 +08:00 committed by Nomango
parent b4404db7b7
commit 1f8b0bb058
37 changed files with 324 additions and 336 deletions

View File

@ -15,18 +15,19 @@ namespace
{ {
const float GLOBAL_SCALE = 100.0f; const float GLOBAL_SCALE = 100.0f;
b2Vec2 convert(const Point& pos) b2Vec2 Vec2Convert(const Point& pos)
{ {
return b2Vec2(pos.x / GLOBAL_SCALE, pos.y / GLOBAL_SCALE); return b2Vec2(pos.x / GLOBAL_SCALE, pos.y / GLOBAL_SCALE);
} }
Point convert(const b2Vec2& pos) Point Vec2Convert(const b2Vec2& pos)
{ {
return Point(pos.x * GLOBAL_SCALE, pos.y * GLOBAL_SCALE); return Point(pos.x * GLOBAL_SCALE, pos.y * GLOBAL_SCALE);
} }
} }
// 小圆形 // 小圆形
E2D_DECLARE_SMART_PTR(Circle);
class Circle class Circle
: public Sprite : public Sprite
{ {
@ -39,7 +40,7 @@ public:
b2BodyDef bodyDef; b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody; bodyDef.type = b2_dynamicBody;
bodyDef.position = convert(pos); bodyDef.position = Vec2Convert(pos);
b2Body* body = world->CreateBody(&bodyDef); b2Body* body = world->CreateBody(&bodyDef);
@ -59,6 +60,7 @@ public:
}; };
// 小方块 // 小方块
E2D_DECLARE_SMART_PTR(Square);
class Square class Square
: public Sprite : public Sprite
{ {
@ -71,14 +73,14 @@ public:
b2BodyDef bodyDef; b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody; bodyDef.type = b2_dynamicBody;
bodyDef.position = convert(pos); bodyDef.position = Vec2Convert(pos);
b2Body* body = world->CreateBody(&bodyDef); b2Body* body = world->CreateBody(&bodyDef);
SetUserData(body); SetUserData(body);
b2PolygonShape shape; b2PolygonShape shape;
b2Vec2 sz = convert(GetSize() / 2 * 0.7f); b2Vec2 sz = Vec2Convert(GetSize() / 2 * 0.7f);
shape.SetAsBox(sz.x, sz.y); shape.SetAsBox(sz.x, sz.y);
b2FixtureDef fixtureDef; b2FixtureDef fixtureDef;
@ -92,13 +94,15 @@ public:
}; };
// 固定的木板 // 固定的木板
E2D_DECLARE_SMART_PTR(Board);
class Board class Board
: public GeometryNode : public GeometryNode
{ {
public: public:
Board(b2World* world, const Size& size, const Point& pos) Board(b2World* world, const Size& size, const Point& pos)
{ {
SetGeometry(new RectangleGeometry(Point(), size)); GeometryPtr geo = new RectangleGeometry(Point(), size);
SetGeometry(geo);
SetStrokeColor(Color::White); SetStrokeColor(Color::White);
SetFillColor(Color(0, 0, 0, 0)); SetFillColor(Color(0, 0, 0, 0));
@ -108,13 +112,13 @@ public:
SetPosition(pos); SetPosition(pos);
b2BodyDef groundBodyDef; b2BodyDef groundBodyDef;
groundBodyDef.position = convert(GetPosition()); groundBodyDef.position = Vec2Convert(GetPosition());
groundBodyDef.angle = 10 * math::constants::PI_F / 180.f; groundBodyDef.angle = 10 * math::constants::PI_F / 180.f;
b2Body* groundBody = world->CreateBody(&groundBodyDef); b2Body* groundBody = world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox; b2PolygonShape groundBox;
b2Vec2 sz = convert(Point{ size.x / 2, size.y / 2 }); b2Vec2 sz = Vec2Convert(Point{ size.x / 2, size.y / 2 });
groundBox.SetAsBox(sz.x, sz.y); groundBox.SetAsBox(sz.x, sz.y);
groundBody->CreateFixture(&groundBox, 0.0f); groundBody->CreateFixture(&groundBox, 0.0f);
} }
@ -130,20 +134,20 @@ public:
{ {
// 修改场景大小, 并设置可响应状态, 使场景可以 // 修改场景大小, 并设置可响应状态, 使场景可以
// 接收到鼠标 Click 消息 // 接收到鼠标 Click 消息
auto window = Window::Instance(); auto size = Window::Instance().GetSize();
SetSize(window->GetSize()); SetSize(size);
SetResponsible(true); SetResponsible(true);
// 添加消息监听 // 添加消息监听
AddListener(MouseEvent::Click, Closure(this, &MainScene::Click)); AddListener(Event::Click, Closure(this, &MainScene::Click));
// 创建物理世界 // 创建物理世界
world_ = new b2World(b2Vec2(0, 10)); world_ = new b2World(b2Vec2(0, 10));
auto board = new Board(world_, Size(GetWidth() - 100, 20), Point(window->GetSize().x / 2, window->GetSize().y - 50)); BoardPtr board = new Board(world_, Size(GetWidth() - 100, 20), Point(size.x / 2, size.y - 50));
AddChild(board); AddChild(board);
auto circle = new Circle(world_, Point(320, 240)); CirclePtr circle = new Circle(world_, Point(320, 240));
AddChild(circle); AddChild(circle);
} }
@ -167,7 +171,7 @@ public:
if (node) if (node)
{ {
const b2Vec2& pos = body->GetPosition(); const b2Vec2& pos = body->GetPosition();
node->SetPosition(convert(pos)); node->SetPosition(Vec2Convert(pos));
node->SetRotation(body->GetAngle() * 180.f / math::constants::PI_F); node->SetRotation(body->GetAngle() * 180.f / math::constants::PI_F);
// 移除掉落到场景外的物体 // 移除掉落到场景外的物体
@ -188,12 +192,12 @@ public:
{ {
if (evt.mouse.button == MouseButton::Left) if (evt.mouse.button == MouseButton::Left)
{ {
auto circle = E_NEW Circle(world_, Point{ evt.mouse.x, evt.mouse.y }); CirclePtr circle = new Circle(world_, Point{ evt.mouse.x, evt.mouse.y });
AddChild(circle); AddChild(circle);
} }
else if (evt.mouse.button == MouseButton::Right) else if (evt.mouse.button == MouseButton::Right)
{ {
auto rect = E_NEW Square(world_, Point{ evt.mouse.x, evt.mouse.y }); SquarePtr rect = new Square(world_, Point{ evt.mouse.x, evt.mouse.y });
AddChild(rect); AddChild(rect);
} }
} }

View File

@ -15,7 +15,7 @@ public:
Demo1() Demo1()
{ {
// 创建文本 // 创建文本
auto text = E_NEW Text(L"Hello Easy2D!"); TextPtr text = new Text(L"Hello Easy2D!");
// 让文本显示在屏幕中央 // 让文本显示在屏幕中央
text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2); text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
text->SetAnchor(0.5, 0.5); text->SetAnchor(0.5, 0.5);

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
E2D_DECLARE_SMART_PTR(Man);
class Man class Man
: public Sprite : public Sprite
{ {
@ -19,29 +20,29 @@ public:
void OnUpdate(Duration dt) override void OnUpdate(Duration dt) override
{ {
// 获取输入设备 // 获取输入设备
auto input = Input::Instance(); auto& input = Input::Instance();
// 按下左右键 // 按下左右键
if (input->IsDown(KeyCode::Left)) if (input.IsDown(KeyCode::Left))
{ {
this->Move(-2, 0); this->Move(-2, 0);
} }
else if (input->IsDown(KeyCode::Right)) else if (input.IsDown(KeyCode::Right))
{ {
this->Move(2, 0); this->Move(2, 0);
} }
// 按下上下键 // 按下上下键
if (input->IsDown(KeyCode::Up)) if (input.IsDown(KeyCode::Up))
{ {
this->Move(0, -2); this->Move(0, -2);
} }
else if (input->IsDown(KeyCode::Down)) else if (input.IsDown(KeyCode::Down))
{ {
this->Move(0, 2); this->Move(0, 2);
} }
// 按下鼠标左键,顺时针旋转小人 // 按下鼠标左键,顺时针旋转小人
if (input->IsDown(MouseButton::Left)) if (input.IsDown(MouseButton::Left))
{ {
// 获取当前旋转角度 // 获取当前旋转角度
float rotation = this->GetRotation(); float rotation = this->GetRotation();
@ -50,7 +51,7 @@ public:
} }
// 点击鼠标右键,隐藏或显示小人 // 点击鼠标右键,隐藏或显示小人
if (input->WasPressed(MouseButton::Right)) if (input.WasPressed(MouseButton::Right))
{ {
// 获取当前显示状态 // 获取当前显示状态
bool visible = this->IsVisible(); bool visible = this->IsVisible();
@ -72,13 +73,13 @@ public:
Demo2() Demo2()
{ {
// 创建人物 // 创建人物
auto man = E_NEW Man; ManPtr man = new Man;
// 在屏幕上居中显示 // 在屏幕上居中显示
man->SetAnchor(0.5f, 0.5f); man->SetAnchor(0.5f, 0.5f);
man->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2); man->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
// 创建说明文字 // 创建说明文字
auto text = E_NEW Text(L"按上下左右键移动\n按鼠标左键旋转\n点击鼠标右键隐藏"); TextPtr text = new Text(L"按上下左右键移动\n按鼠标左键旋转\n点击鼠标右键隐藏");
// 设置文字位置 // 设置文字位置
text->SetAnchor(0.5f, 0.5f); text->SetAnchor(0.5f, 0.5f);
text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT - 50); text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT - 50);

View File

@ -19,12 +19,12 @@ public:
Demo3() Demo3()
{ {
// 加载音乐 // 加载音乐
music = E_NEW Music; music = new Music;
if (!music->Load(L"res/music.wav")) if (!music->Load(L"res/music.wav"))
{ {
music = nullptr; music = nullptr;
auto err = E_NEW Text(L"音频文件加载失败"); TextPtr err = new Text(L"音频文件加载失败");
this->AddChild(err); this->AddChild(err);
} }
@ -32,17 +32,17 @@ public:
music->Play(-1); music->Play(-1);
// 创建说明文字 // 创建说明文字
auto intro_text = E_NEW Text(L"按上下键调整音量\n按空格键暂停或继续"); TextPtr intro_text = new Text(L"按上下键调整音量\n按空格键暂停或继续");
intro_text->SetAnchor(0.5f, 0.5f); intro_text->SetAnchor(0.5f, 0.5f);
intro_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 - 50); intro_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 - 50);
// 创建音量文字 // 创建音量文字
volume_text = E_NEW Text(L"当前音量:"); volume_text = new Text(L"当前音量:");
volume_text->SetAnchor(0.5f, 0.5f); volume_text->SetAnchor(0.5f, 0.5f);
volume_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 30); volume_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 30);
// 创建状态文字 // 创建状态文字
state_text = E_NEW Text(L"当前状态:"); state_text = new Text(L"当前状态:");
state_text->SetAnchor(0.5f, 0.5f); state_text->SetAnchor(0.5f, 0.5f);
state_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 60); state_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 60);
@ -66,20 +66,20 @@ public:
state_text->SetText(playing ? L"当前状态:正在播放" : L"当前状态:停止播放"); state_text->SetText(playing ? L"当前状态:正在播放" : L"当前状态:停止播放");
// 获取输入设备 // 获取输入设备
auto input = Input::Instance(); auto& input = Input::Instance();
// 按空格键暂停或继续 // 按空格键暂停或继续
if (input->WasPressed(KeyCode::Space)) if (input.WasPressed(KeyCode::Space))
{ {
music->IsPlaying() ? music->Pause() : music->Resume(); music->IsPlaying() ? music->Pause() : music->Resume();
} }
// 按上下键调整音量 // 按上下键调整音量
if (input->WasPressed(KeyCode::Up)) if (input.WasPressed(KeyCode::Up))
{ {
music->SetVolume(volume + 0.1f); music->SetVolume(volume + 0.1f);
} }
else if (input->WasPressed(KeyCode::Down)) else if (input.WasPressed(KeyCode::Down))
{ {
music->SetVolume(volume - 0.1f); music->SetVolume(volume - 0.1f);
} }

View File

@ -40,13 +40,13 @@ public:
void ChangeDemoScene() void ChangeDemoScene()
{ {
Window::Instance()->SetTitle(s_Demos[s_DemoIndex].title); Window::Instance().SetTitle(s_Demos[s_DemoIndex].title);
ScenePtr scene = s_Demos[s_DemoIndex].Create(); ScenePtr scene = s_Demos[s_DemoIndex].Create();
EnterScene(scene); EnterScene(scene);
// 添加按键监听 // 添加按键监听
scene->AddListener(KeyboardEvent::Up, Closure(this, &DemoApp::KeyPressed)); scene->AddListener(Event::KeyUp, Closure(this, &DemoApp::KeyPressed));
// 显示提示文字 // 显示提示文字
TextPtr intro = new Text(L"Key 1~3 to select demo"); TextPtr intro = new Text(L"Key 1~3 to select demo");
@ -56,7 +56,7 @@ public:
void KeyPressed(Event const& evt) void KeyPressed(Event const& evt)
{ {
E2D_ASSERT(evt.type == KeyboardEvent::Up); E2D_ASSERT(evt.type == Event::KeyUp);
if (evt.key.code > KeyCode::Num0 && if (evt.key.code > KeyCode::Num0 &&
evt.key.code <= (KeyCode::Num0 + s_DemoNum)) evt.key.code <= (KeyCode::Num0 + s_DemoNum))

View File

@ -42,6 +42,9 @@ namespace easy2d
// 动作结束时移除目标节点 // 动作结束时移除目标节点
inline ActionHelper& RemoveTargetWhenDone() { base->RemoveTargetWhenDone(); return (*this); } inline ActionHelper& RemoveTargetWhenDone() { base->RemoveTargetWhenDone(); return (*this); }
// ÉèÖÃÃû³Æ
inline ActionHelper& SetName(String const& name) { base->SetName(name); return (*this); }
// 获取指针 // 获取指针
inline ActionPtr const& Get() const { return base; } inline ActionPtr const& Get() const { return base; }
@ -76,6 +79,9 @@ namespace easy2d
// 动作结束时移除目标节点 // 动作结束时移除目标节点
inline TweenHelper& RemoveTargetWhenDone() { base->RemoveTargetWhenDone(); return (*this); } inline TweenHelper& RemoveTargetWhenDone() { base->RemoveTargetWhenDone(); return (*this); }
// ÉèÖÃÃû³Æ
inline TweenHelper& SetName(String const& name) { base->SetName(name); return (*this); }
// 获取指针 // 获取指针
inline ActionTweenPtr const& Get() const { return base; } inline ActionTweenPtr const& Get() const { return base; }

View File

@ -34,16 +34,6 @@
namespace easy2d namespace easy2d
{ {
Options::Options()
: title(L"Easy2D Game")
, width(640)
, height(480)
, icon(nullptr)
, vsync(true)
, fullscreen(false)
, debug(false)
{}
Application::Application(String const& app_name) Application::Application(String const& app_name)
: end_(true) : end_(true)
, inited_(false) , inited_(false)
@ -101,11 +91,11 @@ namespace easy2d
} }
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->Init(debug_) Factory::Instance().Init(debug_)
); );
ThrowIfFailed( ThrowIfFailed(
Window::Instance()->Init( Window::Instance().Init(
options.title, options.title,
options.width, options.width,
options.height, options.height,
@ -116,10 +106,10 @@ namespace easy2d
) )
); );
HWND hwnd = Window::Instance()->GetHandle(); HWND hwnd = Window::Instance().GetHandle();
ThrowIfFailed( ThrowIfFailed(
RenderSystem::Instance()->Init( RenderSystem::Instance().Init(
hwnd, hwnd,
options.vsync, options.vsync,
debug_ debug_
@ -127,14 +117,14 @@ namespace easy2d
); );
ThrowIfFailed( ThrowIfFailed(
Input::Instance()->Init( Input::Instance().Init(
hwnd, hwnd,
debug_ debug_
) )
); );
ThrowIfFailed( ThrowIfFailed(
Audio::Instance()->Init(debug_) Audio::Instance().Init(debug_)
); );
OnStart(); OnStart();
@ -150,13 +140,13 @@ namespace easy2d
void Application::Run() void Application::Run()
{ {
HWND hwnd = Window::Instance()->GetHandle(); HWND hwnd = Window::Instance().GetHandle();
if (hwnd) if (hwnd)
{ {
end_ = false; end_ = false;
Window::Instance()->Prepare(); Window::Instance().Prepare();
MSG msg = {}; MSG msg = {};
while (::GetMessageW(&msg, nullptr, 0, 0) && !end_) while (::GetMessageW(&msg, nullptr, 0, 0) && !end_)
@ -182,10 +172,10 @@ namespace easy2d
next_scene_.Reset(); next_scene_.Reset();
curr_scene_.Reset(); curr_scene_.Reset();
Audio::Instance()->Destroy(); Audio::Instance().Destroy();
RenderSystem::Instance()->Destroy(); RenderSystem::Instance().Destroy();
Window::Instance()->Destroy(); Window::Instance().Destroy();
Factory::Instance()->Destroy(); Factory::Instance().Destroy();
} }
} }
@ -219,9 +209,9 @@ namespace easy2d
return curr_scene_; return curr_scene_;
} }
void Application::SetTimeScale(float scale) void Application::SetTimeScale(float scale_factor)
{ {
time_scale_ = scale; time_scale_ = scale_factor;
} }
void Application::Update() void Application::Update()
@ -262,15 +252,15 @@ namespace easy2d
next_scene_->Update(dt); next_scene_->Update(dt);
if (debug_) if (debug_)
DebugNode::Instance()->Update(dt); DebugNode::Instance().Update(dt);
} }
void Application::Render(HWND hwnd) void Application::Render(HWND hwnd)
{ {
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
ThrowIfFailed( ThrowIfFailed(
rt->BeginDraw(hwnd) rt.BeginDraw(hwnd)
); );
if (transition_) if (transition_)
@ -283,10 +273,10 @@ namespace easy2d
} }
if (debug_) if (debug_)
DebugNode::Instance()->Render(); DebugNode::Instance().Render();
ThrowIfFailed( ThrowIfFailed(
rt->EndDraw() rt.EndDraw()
); );
::InvalidateRect(hwnd, NULL, FALSE); ::InvalidateRect(hwnd, NULL, FALSE);
@ -308,7 +298,7 @@ namespace easy2d
app->Update(); app->Update();
app->Render(hwnd); app->Render(hwnd);
Input::Instance()->Update(); Input::Instance().Update();
return 0; return 0;
} }
break; break;
@ -316,11 +306,11 @@ namespace easy2d
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:
{ {
Input::Instance()->UpdateKey((int)wparam, (msg == WM_KEYDOWN) ? true : false); Input::Instance().UpdateKey((int)wparam, (msg == WM_KEYDOWN) ? true : false);
if (!app->transition_ && app->curr_scene_) if (!app->transition_ && app->curr_scene_)
{ {
Event evt((msg == WM_KEYDOWN) ? KeyboardEvent::Down : KeyboardEvent::Up); Event evt((msg == WM_KEYDOWN) ? Event::KeyDown : Event::KeyUp);
evt.key.code = static_cast<int>(wparam); evt.key.code = static_cast<int>(wparam);
evt.key.count = static_cast<int>(lparam & 0xFF); evt.key.count = static_cast<int>(lparam & 0xFF);
@ -341,9 +331,9 @@ namespace easy2d
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) { Input::Instance()->UpdateKey(VK_LBUTTON, (msg == WM_LBUTTONDOWN) ? true : false); } if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) { Input::Instance().UpdateKey(VK_LBUTTON, (msg == WM_LBUTTONDOWN) ? true : false); }
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) { Input::Instance()->UpdateKey(VK_RBUTTON, (msg == WM_RBUTTONDOWN) ? true : false); } else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) { Input::Instance().UpdateKey(VK_RBUTTON, (msg == WM_RBUTTONDOWN) ? true : false); }
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) { Input::Instance()->UpdateKey(VK_MBUTTON, (msg == WM_MBUTTONDOWN) ? true : false); } else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONUP) { Input::Instance().UpdateKey(VK_MBUTTON, (msg == WM_MBUTTONDOWN) ? true : false); }
if (!app->transition_ && app->curr_scene_) if (!app->transition_ && app->curr_scene_)
{ {
@ -354,10 +344,10 @@ namespace easy2d
evt.mouse.left_btn_down = !!(wparam & MK_LBUTTON); evt.mouse.left_btn_down = !!(wparam & MK_LBUTTON);
evt.mouse.left_btn_down = !!(wparam & MK_RBUTTON); evt.mouse.left_btn_down = !!(wparam & MK_RBUTTON);
if (msg == WM_MOUSEMOVE) { evt.type = MouseEvent::Move; } if (msg == WM_MOUSEMOVE) { evt.type = Event::MouseMove; }
else if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) { evt.type = MouseEvent::Down; } else if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) { evt.type = Event::MouseBtnDown; }
else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) { evt.type = MouseEvent::Up; } else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) { evt.type = Event::MouseBtnUp; }
else if (msg == WM_MOUSEWHEEL) { evt.type = MouseEvent::Wheel; evt.mouse.wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; } else if (msg == WM_MOUSEWHEEL) { evt.type = Event::MouseWheel; evt.mouse.wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA; }
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) { evt.mouse.button = MouseButton::Left; } 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_RBUTTONDOWN || msg == WM_RBUTTONUP) { evt.mouse.button = MouseButton::Right; }
@ -376,7 +366,7 @@ namespace easy2d
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染 // 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的 // 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生 // 错误,因为这个错误将在下一次调用 EndDraw 时产生
RenderSystem::Instance()->Resize(width, height); RenderSystem::Instance().Resize(width, height);
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{ {
@ -388,13 +378,13 @@ namespace easy2d
if (app->curr_scene_) if (app->curr_scene_)
{ {
Event evt(WindowEvent::Resized); Event evt(Event::WindowResized);
evt.win.width = static_cast<int>(width); evt.win.width = static_cast<int>(width);
evt.win.height = static_cast<int>(height); evt.win.height = static_cast<int>(height);
app->curr_scene_->Dispatch(evt); app->curr_scene_->Dispatch(evt);
} }
Window::Instance()->UpdateWindowRect(); Window::Instance().UpdateWindowRect();
} }
} }
break; break;
@ -406,7 +396,7 @@ namespace easy2d
int x = (int)(short)LOWORD(lparam); int x = (int)(short)LOWORD(lparam);
int y = (int)(short)HIWORD(lparam); int y = (int)(short)HIWORD(lparam);
Event evt(WindowEvent::Moved); Event evt(Event::WindowMoved);
evt.win.x = x; evt.win.x = x;
evt.win.y = y; evt.win.y = y;
app->curr_scene_->Dispatch(evt); app->curr_scene_->Dispatch(evt);
@ -420,11 +410,11 @@ namespace easy2d
E2D_LOG(active ? L"Window activated" : L"Window deactivated"); E2D_LOG(active ? L"Window activated" : L"Window deactivated");
Window::Instance()->SetActive(active); Window::Instance().SetActive(active);
if (app->curr_scene_) if (app->curr_scene_)
{ {
Event evt(WindowEvent::FocusChanged); Event evt(Event::WindowFocusChanged);
evt.win.focus = active; evt.win.focus = active;
app->curr_scene_->Dispatch(evt); app->curr_scene_->Dispatch(evt);
} }
@ -437,7 +427,7 @@ namespace easy2d
if (app->curr_scene_) if (app->curr_scene_)
{ {
Event evt(WindowEvent::TitleChanged); Event evt(Event::WindowTitleChanged);
evt.win.title = reinterpret_cast<const wchar_t*>(lparam); evt.win.title = reinterpret_cast<const wchar_t*>(lparam);
app->curr_scene_->Dispatch(evt); app->curr_scene_->Dispatch(evt);
} }
@ -464,7 +454,7 @@ namespace easy2d
if (app->OnClosing()) if (app->OnClosing())
{ {
Window::Instance()->Destroy(); Window::Instance().Destroy();
} }
return 0; return 0;
} }
@ -476,7 +466,7 @@ namespace easy2d
if (app->curr_scene_) if (app->curr_scene_)
{ {
Event evt(WindowEvent::Closed); Event evt(Event::WindowClosed);
app->curr_scene_->Dispatch(evt); app->curr_scene_->Dispatch(evt);
} }

View File

@ -38,7 +38,15 @@ namespace easy2d
bool fullscreen; // 全屏模式 bool fullscreen; // 全屏模式
bool debug; // 调试模式 bool debug; // 调试模式
E2D_API Options(); Options()
: title(L"Easy2D Game")
, width(640)
, height(480)
, icon(nullptr)
, vsync(true)
, fullscreen(false)
, debug(false)
{}
}; };
@ -92,8 +100,10 @@ namespace easy2d
// 获取当前场景 // 获取当前场景
ScenePtr const& GetCurrentScene(); ScenePtr const& GetCurrentScene();
// ÉèÖñäËÙ // 设置时间缩放因子
void SetTimeScale(float scale); void SetTimeScale(
float scale_factor
);
private: private:
void Render(HWND); void Render(HWND);

View File

@ -32,7 +32,7 @@ namespace easy2d
, stroke_width_(1.0f) , stroke_width_(1.0f)
{ {
ThrowIfFailed( ThrowIfFailed(
RenderSystem::Instance()->CreateBitmapRenderTarget(render_target_) RenderSystem::Instance().CreateBitmapRenderTarget(render_target_)
); );
auto properties = D2D1::BrushProperties(); auto properties = D2D1::BrushProperties();
@ -58,7 +58,7 @@ namespace easy2d
); );
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreateTextRenderer( Factory::Instance().CreateTextRenderer(
text_renderer_, text_renderer_,
render_target_, render_target_,
text_brush_ text_brush_
@ -105,7 +105,7 @@ namespace easy2d
if (bitmap_cached_) if (bitmap_cached_)
{ {
RenderSystem::Instance()->DrawBitmap(bitmap_cached_); RenderSystem::Instance().DrawBitmap(bitmap_cached_);
} }
} }
@ -126,7 +126,7 @@ namespace easy2d
void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join) void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
{ {
outline_join_style_ = Factory::Instance()->GetStrokeStyle(outline_join); outline_join_style_ = Factory::Instance().GetStrokeStyle(outline_join);
} }
void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style) void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
@ -139,7 +139,7 @@ namespace easy2d
text_style_.outline, text_style_.outline,
ToD2dColorF(text_style_.outline_color), ToD2dColorF(text_style_.outline_color),
text_style_.outline_width, text_style_.outline_width,
Factory::Instance()->GetStrokeStyle(text_style_.outline_stroke).Get() Factory::Instance().GetStrokeStyle(text_style_.outline_stroke).Get()
); );
} }
@ -271,7 +271,7 @@ namespace easy2d
D2DTextFormatPtr text_format; D2DTextFormatPtr text_format;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreateTextFormat( Factory::Instance().CreateTextFormat(
text_format, text_format,
text_font_, text_font_,
text_style_ text_style_
@ -281,7 +281,7 @@ namespace easy2d
D2DTextLayoutPtr text_layout; D2DTextLayoutPtr text_layout;
Size layout_size; Size layout_size;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreateTextLayout( Factory::Instance().CreateTextLayout(
text_layout, text_layout,
layout_size, layout_size,
text, text,
@ -390,7 +390,7 @@ namespace easy2d
current_geometry_ = nullptr; current_geometry_ = nullptr;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreatePathGeometry(current_geometry_) Factory::Instance().CreatePathGeometry(current_geometry_)
); );
ThrowIfFailed( ThrowIfFailed(

View File

@ -67,16 +67,16 @@ namespace easy2d
void DebugNode::OnRender() void DebugNode::OnRender()
{ {
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
rt->GetSolidBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f)); rt.GetSolidBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f));
rt->GetRenderTarget()->FillRoundedRectangle( rt.GetRenderTarget()->FillRoundedRectangle(
D2D1::RoundedRect( D2D1::RoundedRect(
D2D1_RECT_F{ 10, 10, 200, 120 }, D2D1_RECT_F{ 10, 10, 200, 120 },
6.f, 6.f,
6.f), 6.f),
rt->GetSolidBrush().Get() rt.GetSolidBrush().Get()
); );
} }
@ -105,9 +105,9 @@ namespace easy2d
ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl; ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl;
#endif #endif
ss << "Render: " << RenderSystem::Instance()->GetStatus().duration.Milliseconds() << "ms" << std::endl; ss << "Render: " << RenderSystem::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Primitives / sec: " << RenderSystem::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; PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));

View File

@ -27,7 +27,7 @@ namespace easy2d
{ {
class E2D_API DebugNode class E2D_API DebugNode
: public Node : public Node
, public ISingleton<DebugNode> , public Singleton<DebugNode>
{ {
E2D_DECLARE_SINGLETON(DebugNode); E2D_DECLARE_SINGLETON(DebugNode);

View File

@ -24,122 +24,111 @@
namespace easy2d namespace easy2d
{ {
typedef UINT EventType;
// 鼠标事件 // 鼠标事件
struct MouseEvent struct MouseEvent
{ {
enum Type : EventType
{
First = WM_MOUSEFIRST,
Move, // 移动
Down, // 按下
Up, // 抬起
Wheel, // 滚轮滚动
Hover, // 鼠标移入
Out, // 鼠标移出
Click, // 鼠标点击
Last // 结束标志
};
float x; float x;
float y; float y;
bool left_btn_down; // 左键是否按下 bool left_btn_down; // 左键是否按下
bool right_btn_down; // 右键是否按下 bool right_btn_down; // 右键是否按下
struct struct // Events::MouseDown | Events::MouseUp | Events::MouseClick
{ {
int button; // 仅当消息类型为 Down | Up | Click 时有效 int button;
}; };
struct struct // Events::MouseWheel
{ {
float wheel; // 仅当消息类型为 Wheel 时有效 float wheel;
}; };
static inline bool Check(EventType type) static bool Check(UINT type);
{
return type > Type::First && type < Type::Last;
}
}; };
// 键盘事件 // 键盘事件
struct KeyboardEvent struct KeyboardEvent
{ {
enum Type : UINT int code; // enum KeyCode
{
First = WM_KEYFIRST,
Down, // 键按下
Up, // 键抬起
Last
};
int code; // enum KeyCode
int count; int count;
static inline bool Check(UINT type) static bool Check(UINT type);
{
return type > Type::First && type < Type::Last;
}
}; };
// 窗口事件 // 窗口事件
struct WindowEvent struct WindowEvent
{ {
public:
enum Type : EventType
{
First = WM_NULL,
Moved, // 窗口移动
Resized, // 窗口大小变化
FocusChanged, // 获得或失去焦点
TitleChanged, // 标题变化
Closed, // 窗口被关闭
Last
};
union union
{ {
struct // WindowEvent::Moved struct // Events::WindowMoved
{ {
int x; int x;
int y; int y;
}; };
struct // WindowEvent::Resized struct // Events::WindowResized
{ {
int width; int width;
int height; int height;
}; };
struct // WindowEvent::FocusChanged struct // Events::WindowFocusChanged
{ {
bool focus; bool focus;
}; };
struct // WindowEvent::TitleChanged struct // Events::WindowTitleChanged
{ {
const wchar_t* title; const wchar_t* title;
}; };
}; };
static inline bool Check(EventType type) static bool Check(UINT type);
{ };
return type > Type::First && type < Type::Last;
} // 自定义事件
struct CustomEvent
{
void* data;
}; };
// 事件 // 事件
struct E2D_API Event struct E2D_API Event
{ {
EventType type; enum Type : UINT
{
First,
// 鼠标事件
MouseFirst,
MouseMove, // 移动
MouseBtnDown, // 鼠标按下
MouseBtnUp, // 鼠标抬起
MouseWheel, // 滚轮滚动
MouseHover, // 鼠标移入
MouseOut, // 鼠标移出
Click, // 鼠标点击
MouseLast,
// 按键事件
KeyFirst,
KeyDown, // 按键按下
KeyUp, // 按键抬起
KeyLast,
// 窗口消息
WindowFirst,
WindowMoved, // 窗口移动
WindowResized, // 窗口大小变化
WindowFocusChanged, // 获得或失去焦点
WindowTitleChanged, // 标题变化
WindowClosed, // 窗口被关闭
WindowLast,
Last
};
UINT type;
Node* target; Node* target;
union union
@ -147,8 +136,28 @@ namespace easy2d
MouseEvent mouse; MouseEvent mouse;
KeyboardEvent key; KeyboardEvent key;
WindowEvent win; WindowEvent win;
CustomEvent custom;
}; };
Event(EventType type = 0) : type(type), target(nullptr) {} Event(UINT type = Type::First) : type(type), target(nullptr) {}
}; };
// Check-functions
inline bool MouseEvent::Check(UINT type)
{
return type > Event::MouseFirst && type < Event::MouseLast;
}
inline bool KeyboardEvent::Check(UINT type)
{
return type > Event::KeyFirst && type < Event::KeyLast;
}
inline bool WindowEvent::Check(UINT type)
{
return type > Event::WindowFirst && type < Event::WindowLast;
}
} }

View File

@ -50,7 +50,7 @@ namespace easy2d
} }
} }
void EventDispatcher::AddListener(EventType type, EventCallback callback, String const& name) void EventDispatcher::AddListener(UINT type, EventCallback callback, String const& name)
{ {
EventListenerPtr listener = new EventListener(type, callback, name); EventListenerPtr listener = new EventListener(type, callback, name);
if (listener) if (listener)
@ -95,7 +95,7 @@ namespace easy2d
} }
} }
void EventDispatcher::StartListeners(EventType type) void EventDispatcher::StartListeners(UINT type)
{ {
for (auto listener = listeners_.First(); listener; listener = listener->NextItem()) for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{ {
@ -106,7 +106,7 @@ namespace easy2d
} }
} }
void EventDispatcher::StopListeners(EventType type) void EventDispatcher::StopListeners(UINT type)
{ {
for (auto listener = listeners_.First(); listener; listener = listener->NextItem()) for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{ {
@ -117,7 +117,7 @@ namespace easy2d
} }
} }
void EventDispatcher::RemoveListeners(EventType type) void EventDispatcher::RemoveListeners(UINT type)
{ {
EventListenerPtr next; EventListenerPtr next;
for (auto listener = listeners_.First(); listener; listener = next) for (auto listener = listeners_.First(); listener; listener = next)

View File

@ -35,7 +35,7 @@ namespace easy2d
// 添加监听器 // 添加监听器
void AddListener( void AddListener(
EventType type, UINT type,
EventCallback callback, EventCallback callback,
String const& name = L"" String const& name = L""
); );
@ -57,17 +57,17 @@ namespace easy2d
// 启动监听器 // 启动监听器
void StartListeners( void StartListeners(
EventType type UINT type
); );
// 停止监听器 // 停止监听器
void StopListeners( void StopListeners(
EventType type UINT type
); );
// 移除监听器 // 移除监听器
void RemoveListeners( void RemoveListeners(
EventType type UINT type
); );
virtual void Dispatch(Event& evt); virtual void Dispatch(Event& evt);

View File

@ -23,7 +23,7 @@
namespace easy2d namespace easy2d
{ {
EventListener::EventListener(EventType type, EventCallback const & callback, String const & name) EventListener::EventListener(UINT type, EventCallback const & callback, String const & name)
: type_(type) : type_(type)
, callback_(callback) , callback_(callback)
, running_(true) , running_(true)
@ -35,19 +35,4 @@ namespace easy2d
{ {
} }
void EventListener::Start()
{
running_ = true;
}
void EventListener::Stop()
{
running_ = false;
}
bool EventListener::IsRunning() const
{
return running_;
}
} }

View File

@ -38,22 +38,22 @@ namespace easy2d
public: public:
EventListener( EventListener(
EventType type, UINT type,
EventCallback const& callback, EventCallback const& callback,
String const& name = L"" String const& name = L""
); );
virtual ~EventListener(); virtual ~EventListener();
void Start(); inline void Start() { running_ = true; }
void Stop(); inline void Stop() { running_ = true; }
bool IsRunning() const; inline bool IsRunning() const { return running_; }
protected: protected:
bool running_; bool running_;
EventType type_; UINT type_;
EventCallback callback_; EventCallback callback_;
}; };
} }

View File

@ -29,7 +29,7 @@
namespace easy2d namespace easy2d
{ {
class E2D_API Factory class E2D_API Factory
: public ISingleton<Factory> : public Singleton<Factory>
{ {
E2D_DECLARE_SINGLETON(Factory); E2D_DECLARE_SINGLETON(Factory);

View File

@ -129,7 +129,7 @@ namespace easy2d
D2DPathGeometryPtr path_geo; D2DPathGeometryPtr path_geo;
D2DGeometrySinkPtr path_sink; D2DGeometrySinkPtr path_sink;
HRESULT hr = Factory::Instance()->CreatePathGeometry(path_geo); HRESULT hr = Factory::Instance().CreatePathGeometry(path_geo);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -186,7 +186,7 @@ namespace easy2d
void RectangleGeometry::SetRect(Rect const & rect) void RectangleGeometry::SetRect(Rect const & rect)
{ {
D2DRectangleGeometryPtr geo; D2DRectangleGeometryPtr geo;
if (SUCCEEDED(Factory::Instance()->CreateRectangleGeometry(geo, rect))) if (SUCCEEDED(Factory::Instance().CreateRectangleGeometry(geo, rect)))
{ {
geo_ = geo; geo_ = geo;
rect_ = rect; rect_ = rect;
@ -225,7 +225,7 @@ namespace easy2d
void CircleGeometry::SetCircle(Point const & center, float radius) void CircleGeometry::SetCircle(Point const & center, float radius)
{ {
D2DEllipseGeometryPtr geo; D2DEllipseGeometryPtr geo;
if (SUCCEEDED(Factory::Instance()->CreateEllipseGeometry(geo, center, radius, radius))) if (SUCCEEDED(Factory::Instance().CreateEllipseGeometry(geo, center, radius, radius)))
{ {
geo_ = geo; geo_ = geo;
center_ = center; center_ = center;
@ -266,7 +266,7 @@ namespace easy2d
void EllipseGeometry::SetEllipse(Point const & center, float radius_x, float radius_y) void EllipseGeometry::SetEllipse(Point const & center, float radius_x, float radius_y)
{ {
D2DEllipseGeometryPtr geo; D2DEllipseGeometryPtr geo;
if (SUCCEEDED(Factory::Instance()->CreateEllipseGeometry(geo, center, radius_x, radius_y))) if (SUCCEEDED(Factory::Instance().CreateEllipseGeometry(geo, center, radius_x, radius_y)))
{ {
geo_ = geo; geo_ = geo;
radius_x_ = radius_x; radius_x_ = radius_x;
@ -292,7 +292,7 @@ namespace easy2d
current_geometry_ = nullptr; current_geometry_ = nullptr;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreatePathGeometry(current_geometry_) Factory::Instance().CreatePathGeometry(current_geometry_)
); );
ThrowIfFailed( ThrowIfFailed(
@ -405,7 +405,7 @@ namespace easy2d
void RoundedRectGeometry::SetRoundedRect(Rect const & rect, float radius_x, float radius_y) void RoundedRectGeometry::SetRoundedRect(Rect const & rect, float radius_x, float radius_y)
{ {
D2DRoundedRectangleGeometryPtr geo; D2DRoundedRectangleGeometryPtr geo;
if (SUCCEEDED(Factory::Instance()->CreateRoundedRectangleGeometry(geo, rect, radius_x, radius_y))) if (SUCCEEDED(Factory::Instance().CreateRoundedRectangleGeometry(geo, rect, radius_x, radius_y)))
{ {
geo_ = geo; geo_ = geo;
rect_ = rect; rect_ = rect;

View File

@ -70,14 +70,14 @@ namespace easy2d
{ {
if (geometry_ && geometry_->geo_) if (geometry_ && geometry_->geo_)
{ {
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
rt->FillGeometry( rt.FillGeometry(
geometry_->geo_, geometry_->geo_,
fill_color_ fill_color_
); );
rt->DrawGeometry( rt.DrawGeometry(
geometry_->geo_, geometry_->geo_,
stroke_color_, stroke_color_,
stroke_width_, stroke_width_,

View File

@ -67,11 +67,11 @@ namespace easy2d
E2D_WARNING_LOG(L"Image file '%s' not found!", res.GetFileName().c_str()); E2D_WARNING_LOG(L"Image file '%s' not found!", res.GetFileName().c_str());
return false; return false;
} }
hr = RenderSystem::Instance()->CreateBitmapFromFile(bitmap, res.GetFileName()); hr = RenderSystem::Instance().CreateBitmapFromFile(bitmap, res.GetFileName());
} }
else else
{ {
hr = RenderSystem::Instance()->CreateBitmapFromResource(bitmap, res); hr = RenderSystem::Instance().CreateBitmapFromResource(bitmap, res);
} }
if (FAILED(hr)) if (FAILED(hr))

View File

@ -26,7 +26,7 @@
namespace easy2d namespace easy2d
{ {
class E2D_API Input class E2D_API Input
: public ISingleton<Input> : public Singleton<Input>
{ {
E2D_DECLARE_SINGLETON(Input); E2D_DECLARE_SINGLETON(Input);

View File

@ -78,7 +78,7 @@ namespace easy2d
return false; return false;
} }
hr = Audio::Instance()->CreateVoice(voice_, transcoder.GetWaveFormatEx()); hr = Audio::Instance().CreateVoice(voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr)) if (FAILED(hr))
{ {
if (wave_data_) if (wave_data_)

View File

@ -88,12 +88,12 @@ namespace easy2d
UpdateTransform(); UpdateTransform();
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
if (children_.IsEmpty()) if (children_.IsEmpty())
{ {
rt->SetTransform(transform_matrix_); rt.SetTransform(transform_matrix_);
rt->SetOpacity(display_opacity_); rt.SetOpacity(display_opacity_);
OnRender(); OnRender();
} }
@ -110,8 +110,8 @@ namespace easy2d
child = child->NextItem().Get(); child = child->NextItem().Get();
} }
rt->SetTransform(transform_matrix_); rt.SetTransform(transform_matrix_);
rt->SetOpacity(display_opacity_); rt.SetOpacity(display_opacity_);
OnRender(); OnRender();
@ -137,7 +137,7 @@ namespace easy2d
if (responsible_ && MouseEvent::Check(evt.type)) if (responsible_ && MouseEvent::Check(evt.type))
{ {
if (evt.type == MouseEvent::Move) if (evt.type == Event::MouseMove)
{ {
if (!evt.target && ContainsPoint(Point{ evt.mouse.x, evt.mouse.y })) if (!evt.target && ContainsPoint(Point{ evt.mouse.x, evt.mouse.y }))
{ {
@ -148,7 +148,7 @@ namespace easy2d
hover_ = true; hover_ = true;
Event hover = evt; Event hover = evt;
hover.type = MouseEvent::Hover; hover.type = Event::MouseHover;
EventDispatcher::Dispatch(hover); EventDispatcher::Dispatch(hover);
} }
} }
@ -159,24 +159,24 @@ namespace easy2d
Event out = evt; Event out = evt;
out.target = this; out.target = this;
out.type = MouseEvent::Out; out.type = Event::MouseOut;
EventDispatcher::Dispatch(out); EventDispatcher::Dispatch(out);
} }
} }
if (evt.type == MouseEvent::Down && hover_) if (evt.type == Event::MouseBtnDown && hover_)
{ {
pressed_ = true; pressed_ = true;
evt.target = this; evt.target = this;
} }
if (evt.type == MouseEvent::Up && pressed_) if (evt.type == Event::MouseBtnUp && pressed_)
{ {
pressed_ = false; pressed_ = false;
evt.target = this; evt.target = this;
Event click = evt; Event click = evt;
click.type = MouseEvent::Click; click.type = Event::Click;
EventDispatcher::Dispatch(click); EventDispatcher::Dispatch(click);
} }
} }

View File

@ -44,7 +44,7 @@ namespace easy2d
protected: protected:
RefCounter() : ref_count_(0) {} RefCounter() : ref_count_(0) {}
~RefCounter() {} virtual ~RefCounter() {}
protected: protected:
long ref_count_; long ref_count_;

View File

@ -19,28 +19,26 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include "noncopyable.hpp"
#include <memory>
namespace easy2d namespace easy2d
{ {
template <typename T> template <typename _Ty>
class ISingleton class Singleton
: protected Noncopyable
{ {
public: public:
static inline T* Instance() static inline _Ty& Instance()
{ {
static std::unique_ptr<T> instance_; static _Ty instance; // Thread safe
if (!instance_) return instance;
instance_.reset(new (std::nothrow) T);
return instance_.get();
} }
protected: protected:
ISingleton() = default; Singleton() = default;
~ISingleton() {} private:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
}; };
} }
@ -49,7 +47,5 @@ namespace easy2d
#ifndef E2D_DECLARE_SINGLETON #ifndef E2D_DECLARE_SINGLETON
#define E2D_DECLARE_SINGLETON( type ) \ #define E2D_DECLARE_SINGLETON( type ) \
friend class ::std::unique_ptr< type >; \ friend class ::easy2d::Singleton< type >
friend struct ::std::default_delete< type >;\
friend class ::easy2d::ISingleton< type >
#endif #endif

View File

@ -99,7 +99,7 @@ namespace easy2d
{ {
if (image_) if (image_)
{ {
RenderSystem::Instance()->DrawImage(image_, GetBounds()); RenderSystem::Instance().DrawImage(image_, GetBounds());
} }
} }
} }

View File

@ -295,15 +295,15 @@ namespace easy2d
{ {
if (text_layout_) if (text_layout_)
{ {
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
rt->SetTextStyle( rt.SetTextStyle(
style_.color, style_.color,
style_.outline, style_.outline,
style_.outline_color, style_.outline_color,
style_.outline_width, style_.outline_width,
style_.outline_stroke style_.outline_stroke
); );
rt->DrawTextLayout(text_layout_); rt.DrawTextLayout(text_layout_);
} }
} }
@ -316,7 +316,7 @@ namespace easy2d
return; return;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreateTextFormat( Factory::Instance().CreateTextFormat(
text_format_, text_format_,
font_, font_,
style_ style_
@ -325,7 +325,7 @@ namespace easy2d
Size layout_size; Size layout_size;
ThrowIfFailed( ThrowIfFailed(
Factory::Instance()->CreateTextLayout( Factory::Instance().CreateTextLayout(
text_layout_, text_layout_,
layout_size, layout_size,
text_, text_,

View File

@ -66,18 +66,18 @@ namespace easy2d
if (in_scene_) if (in_scene_)
{ {
ThrowIfFailed( ThrowIfFailed(
RenderSystem::Instance()->CreateLayer(in_layer_) RenderSystem::Instance().CreateLayer(in_layer_)
); );
} }
if (out_scene_) if (out_scene_)
{ {
ThrowIfFailed( ThrowIfFailed(
RenderSystem::Instance()->CreateLayer(out_layer_) RenderSystem::Instance().CreateLayer(out_layer_)
); );
} }
window_size_ = Window::Instance()->GetSize(); window_size_ = Window::Instance().GetSize();
out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f }; out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f };
} }
@ -101,34 +101,34 @@ namespace easy2d
void Transition::Render() void Transition::Render()
{ {
auto rt = RenderSystem::Instance(); auto& rt = RenderSystem::Instance();
if (out_scene_) if (out_scene_)
{ {
rt->PushClip( rt.PushClip(
out_scene_->GetTransformMatrix(), out_scene_->GetTransformMatrix(),
window_size_ window_size_
); );
rt->PushLayer(out_layer_, out_layer_prop_); rt.PushLayer(out_layer_, out_layer_prop_);
out_scene_->Render(); out_scene_->Render();
rt->PopLayer(); rt.PopLayer();
rt->PopClip(); rt.PopClip();
} }
if (in_scene_) if (in_scene_)
{ {
rt->PushClip( rt.PushClip(
in_scene_->GetTransformMatrix(), in_scene_->GetTransformMatrix(),
window_size_ window_size_
); );
rt->PushLayer(in_layer_, in_layer_prop_); rt.PushLayer(in_layer_, in_layer_prop_);
in_scene_->Render(); in_scene_->Render();
rt->PopLayer(); rt.PopLayer();
rt->PopClip(); rt.PopClip();
} }
} }

View File

@ -46,7 +46,7 @@ namespace easy2d
{ {
Destroy(); Destroy();
Audio::Instance()->DeleteVoice(this); Audio::Instance().DeleteVoice(this);
} }
HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count) HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count)

View File

@ -75,7 +75,7 @@ namespace easy2d
class E2D_API Audio class E2D_API Audio
: public ISingleton<Audio> : public Singleton<Audio>
{ {
E2D_DECLARE_SINGLETON(Audio); E2D_DECLARE_SINGLETON(Audio);

View File

@ -21,67 +21,56 @@
#pragma once #pragma once
#include <functional> #include <functional>
#define CLOSURE_PARAMS_TYPE_1 typename Param1
#define CLOSURE_PARAMS_1 Param1
#define CLOSURE_PLACEHOLDERS_1 std::placeholders::_1
#define CLOSURE_PARAMS_TYPE_2 typename Param1, typename Param2
#define CLOSURE_PARAMS_2 Param1, Param2
#define CLOSURE_PLACEHOLDERS_2 std::placeholders::_1, std::placeholders::_2
#define CLOSURE_PARAMS_TYPE_3 typename Param1, typename Param2, typename Param3
#define CLOSURE_PARAMS_3 Param1, Param2, Param3
#define CLOSURE_PLACEHOLDERS_3 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3
#define CLOSURE_PARAMS_TYPE_4 typename Param1, typename Param2, typename Param3, typename Param4
#define CLOSURE_PARAMS_4 Param1, Param2, Param3, Param4
#define CLOSURE_PLACEHOLDERS_4 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4
#define CLOSURE_PARAMS_TYPE_5 typename Param1, typename Param2, typename Param3, typename Param4, typename Param5
#define CLOSURE_PARAMS_5 Param1, Param2, Param3, Param4, Param5
#define CLOSURE_PLACEHOLDERS_5 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5
#define CLOSURE_PARAMS_TYPE_6 typename Param1, typename Param2, typename Param3, typename Param4, typename Param5, typename Param6
#define CLOSURE_PARAMS_6 Param1, Param2, Param3, Param4, Param5, Param6
#define CLOSURE_PLACEHOLDERS_6 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6
#define CLOSURE_EXPAND(x) x
#define CLOSURE_DECLARE(TYPE, PARAMS, PHS)\
template<typename T, typename R, CLOSURE_EXPAND(TYPE)>\
inline std::function<R(CLOSURE_EXPAND(PARAMS))> Closure(T* ptr, R(T::*func)(CLOSURE_EXPAND(PARAMS)))\
{\
return std::bind(func, ptr, CLOSURE_EXPAND(PHS));\
}
namespace easy2d namespace easy2d
{ {
template<typename T, typename R> namespace __closure__detail
inline std::function<R(void)> Closure(T* ptr, R(T::*func)(void))
{ {
return std::bind(func, ptr); // sequence & generater
template<int... _Num>
struct Seq
{
using NextType = Seq<_Num..., sizeof...(_Num)>;
};
template<typename...>
struct Gen;
template<>
struct Gen<>
{
using SeqType = Seq<>;
};
template<typename _Ty1, typename... _Args>
struct Gen<_Ty1, _Args...>
{
using SeqType = typename Gen<_Args...>::SeqType::NextType;
};
// ClosureHelper
template<typename _Ty, typename _Ret, typename... _Args>
struct ClosureHelper
{
template<int... _Num>
static inline std::function<_Ret(_Args...)> MakeFunc(_Ty* _Ptr, _Ret(_Ty::*_Func)(_Args...), Seq<_Num...>)
{
return std::bind(_Func, _Ptr, typename std::_Ph<_Num + 1>()...);
}
};
} }
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_1, CLOSURE_PARAMS_1, CLOSURE_PLACEHOLDERS_1); //
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_2, CLOSURE_PARAMS_2, CLOSURE_PLACEHOLDERS_2); // Closure is a simple function for binding member functions
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_3, CLOSURE_PARAMS_3, CLOSURE_PLACEHOLDERS_3); //
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_4, CLOSURE_PARAMS_4, CLOSURE_PLACEHOLDERS_4);
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_5, CLOSURE_PARAMS_5, CLOSURE_PLACEHOLDERS_5);
CLOSURE_DECLARE(CLOSURE_PARAMS_TYPE_6, CLOSURE_PARAMS_6, CLOSURE_PLACEHOLDERS_6);
}
#undef CLOSURE_PARAMS_TYPE_1 template<typename _Ty, typename _Ret, typename... _Args>
#undef CLOSURE_PARAMS_1 inline std::function<_Ret(_Args...)> Closure(_Ty* _Ptr, _Ret(_Ty::*_Func)(_Args...))
#undef CLOSURE_PLACEHOLDERS_1 {
#undef CLOSURE_PARAMS_TYPE_2 using namespace __closure__detail;
#undef CLOSURE_PARAMS_2 return ClosureHelper<_Ty, _Ret, _Args...>::
#undef CLOSURE_PLACEHOLDERS_2 MakeFunc(_Ptr, _Func, typename Gen<_Args...>::SeqType{});
#undef CLOSURE_PARAMS_TYPE_3 }
#undef CLOSURE_PARAMS_3 }
#undef CLOSURE_PLACEHOLDERS_3
#undef CLOSURE_PARAMS_TYPE_4
#undef CLOSURE_PARAMS_4
#undef CLOSURE_PLACEHOLDERS_4
#undef CLOSURE_PARAMS_TYPE_5
#undef CLOSURE_PARAMS_5
#undef CLOSURE_PLACEHOLDERS_5
#undef CLOSURE_PARAMS_TYPE_6
#undef CLOSURE_PARAMS_6
#undef CLOSURE_PLACEHOLDERS_6
#undef CLOSURE_EXPAND
#undef CLOSURE_DECLARE

View File

@ -28,8 +28,6 @@ namespace easy2d
protected: protected:
Noncopyable() = default; Noncopyable() = default;
virtual ~Noncopyable() {};
private: private:
Noncopyable(const Noncopyable&) = delete; Noncopyable(const Noncopyable&) = delete;

View File

@ -164,7 +164,7 @@ namespace easy2d
return S_OK; return S_OK;
solid_brush_->SetColor(ToD2dColorF(stroke_color)); solid_brush_->SetColor(ToD2dColorF(stroke_color));
auto stroke_style = Factory::Instance()->GetStrokeStyle(stroke); auto stroke_style = Factory::Instance().GetStrokeStyle(stroke);
render_target_->DrawGeometry( render_target_->DrawGeometry(
geometry.Get(), geometry.Get(),
solid_brush_.Get(), solid_brush_.Get(),
@ -349,7 +349,7 @@ namespace easy2d
} }
D2DBitmapPtr bitmap_tmp; D2DBitmapPtr bitmap_tmp;
HRESULT hr = Factory::Instance()->CreateBitmapFromFile( HRESULT hr = Factory::Instance().CreateBitmapFromFile(
bitmap, bitmap,
render_target_, render_target_,
file_path file_path
@ -377,7 +377,7 @@ namespace easy2d
return S_OK; return S_OK;
} }
HRESULT hr = Factory::Instance()->CreateBitmapFromResource( HRESULT hr = Factory::Instance().CreateBitmapFromResource(
bitmap, bitmap,
render_target_, render_target_,
res res
@ -439,7 +439,7 @@ namespace easy2d
if (!text_renderer_) if (!text_renderer_)
return E_UNEXPECTED; return E_UNEXPECTED;
auto stroke_style = Factory::Instance()->GetStrokeStyle(outline_stroke); auto stroke_style = Factory::Instance().GetStrokeStyle(outline_stroke);
text_renderer_->SetTextStyle( text_renderer_->SetTextStyle(
ToD2dColorF(color), ToD2dColorF(color),
has_outline, has_outline,
@ -514,7 +514,7 @@ namespace easy2d
rc.bottom - rc.top rc.bottom - rc.top
); );
hr = Factory::Instance()->CreateHwndRenderTarget( hr = Factory::Instance().CreateHwndRenderTarget(
render_target_, render_target_,
D2D1::RenderTargetProperties( D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1_RENDER_TARGET_TYPE_DEFAULT,
@ -545,7 +545,7 @@ namespace easy2d
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = Factory::Instance()->CreateTextRenderer( hr = Factory::Instance().CreateTextRenderer(
text_renderer_, text_renderer_,
render_target_, render_target_,
solid_brush_ solid_brush_

View File

@ -32,7 +32,7 @@
namespace easy2d namespace easy2d
{ {
class E2D_API RenderSystem class E2D_API RenderSystem
: public ISingleton<RenderSystem> : public Singleton<RenderSystem>
{ {
E2D_DECLARE_SINGLETON(RenderSystem); E2D_DECLARE_SINGLETON(RenderSystem);

View File

@ -25,7 +25,7 @@
namespace easy2d namespace easy2d
{ {
class E2D_API Window class E2D_API Window
: public ISingleton<Window> : public Singleton<Window>
{ {
E2D_DECLARE_SINGLETON(Window); E2D_DECLARE_SINGLETON(Window);

View File

@ -32,10 +32,10 @@ namespace easy2d
{ {
SetResponsible(true); SetResponsible(true);
AddListener(MouseEvent::Hover, Closure(this, &Button::UpdateStatus)); AddListener(Event::MouseHover, Closure(this, &Button::UpdateStatus));
AddListener(MouseEvent::Out, Closure(this, &Button::UpdateStatus)); AddListener(Event::MouseOut, Closure(this, &Button::UpdateStatus));
AddListener(MouseEvent::Down, Closure(this, &Button::UpdateStatus)); AddListener(Event::MouseBtnDown, Closure(this, &Button::UpdateStatus));
AddListener(MouseEvent::Up, Closure(this, &Button::UpdateStatus)); AddListener(Event::MouseBtnUp, Closure(this, &Button::UpdateStatus));
} }
Button::Button(const Callback& click) Button::Button(const Callback& click)
@ -104,28 +104,28 @@ namespace easy2d
if (enabled_ && (evt.target == this)) if (enabled_ && (evt.target == this))
{ {
if (evt.type == MouseEvent::Hover) if (evt.type == Event::MouseHover)
{ {
SetStatus(Status::Hover); SetStatus(Status::Hover);
if (mouse_over_callback_) if (mouse_over_callback_)
mouse_over_callback_(); mouse_over_callback_();
} }
else if (evt.type == MouseEvent::Out) else if (evt.type == Event::MouseOut)
{ {
SetStatus(Status::Normal); SetStatus(Status::Normal);
if (mouse_out_callback_) if (mouse_out_callback_)
mouse_out_callback_(); mouse_out_callback_();
} }
else if (evt.type == MouseEvent::Down && status_ == Status::Hover) else if (evt.type == Event::MouseBtnDown && status_ == Status::Hover)
{ {
SetStatus(Status::Pressed); SetStatus(Status::Pressed);
if (pressed_callback_) if (pressed_callback_)
pressed_callback_(); pressed_callback_();
} }
else if (evt.type == MouseEvent::Up && status_ == Status::Pressed) else if (evt.type == Event::MouseBtnUp && status_ == Status::Pressed)
{ {
SetStatus(Status::Hover); SetStatus(Status::Hover);

View File

@ -62,7 +62,7 @@ namespace easy2d
{ {
// 设置数据的保存路径 // 设置数据的保存路径
String local_app_data_path = Path::GetLocalAppDataPath(); String local_app_data_path = Path::GetLocalAppDataPath();
String title = Window::Instance()->GetTitle(); String title = Window::Instance().GetTitle();
String folder_name = std::to_wstring(std::hash<String>{}(title)); String folder_name = std::to_wstring(std::hash<String>{}(title));
if (!local_app_data_path.empty()) if (!local_app_data_path.empty())
@ -90,7 +90,7 @@ namespace easy2d
{ {
// 设置临时文件保存路径 // 设置临时文件保存路径
wchar_t path[_MAX_PATH]; wchar_t path[_MAX_PATH];
String title = Window::Instance()->GetTitle(); String title = Window::Instance().GetTitle();
String folder_name = std::to_wstring(std::hash<String>{}(title)); String folder_name = std::to_wstring(std::hash<String>{}(title));
if (0 != ::GetTempPath(_MAX_PATH, path)) if (0 != ::GetTempPath(_MAX_PATH, path))