add Events and EventDispatcher

This commit is contained in:
Haibo 2018-11-22 19:31:44 +08:00 committed by Nomango
parent bf25bd1d41
commit 406ea51b57
43 changed files with 1734 additions and 1404 deletions

View File

@ -44,7 +44,7 @@ namespace easy2d
void ActionManager::AddAction(spAction const& action)
{
if (!action)
logs::Warningln("Node::RunAction failed, action is nullptr");
logs::Warningln("AddAction failed, action is nullptr");
if (action)
{

View File

@ -46,19 +46,34 @@ namespace easy2d
Round = 2 /* Ô˛˝Ç */
};
// 囚徒囚峙
// 夕蚊奉來
struct LayerProperties
{
Rect area;
float opacity;
};
// 報炎囚峙
enum class MouseButton : int
{
Left = VK_LBUTTON, // 報炎恣囚
Right = VK_RBUTTON, // 報炎嘔囚
Middle = VK_MBUTTON // 報炎嶄囚
};
// 梓囚囚峙
enum class KeyCode : int
{
Unknown = 0,
Up = VK_UP,
Left = VK_LEFT,
Right = VK_RIGHT,
Down = VK_DOWN,
Enter = VK_RETURN,
Space = VK_SPACE,
Esc = VK_ESCAPE,
Ctrl = VK_CONTROL,
Shift = VK_SHIFT,
Unknown = 0,
Up = VK_UP,
Left = VK_LEFT,
Right = VK_RIGHT,
Down = VK_DOWN,
Enter = VK_RETURN,
Space = VK_SPACE,
Esc = VK_ESCAPE,
Ctrl = VK_CONTROL,
Shift = VK_SHIFT,
A = 0x41,
B,
@ -122,19 +137,4 @@ namespace easy2d
F11,
F12,
};
// 報炎囚峙
enum class MouseCode : int
{
Left = VK_LBUTTON, /* 報炎恣囚 */
Right = VK_RBUTTON, /* 報炎嘔囚 */
Middle = VK_MBUTTON /* 報炎嶄囚 */
};
// 夕蚊奉來
struct LayerProperties
{
Rect area;
float opacity;
};
}

View File

@ -32,7 +32,7 @@ namespace easy2d
, stroke_width_(1.0f)
{
ThrowIfFailed(
devices::Graphics::Instance()->CreateBitmapRenderTarget(render_target_)
Graphics::Instance()->CreateBitmapRenderTarget(render_target_)
);
auto properties = D2D1::BrushProperties();
@ -105,7 +105,7 @@ namespace easy2d
if (bitmap_cached_)
{
devices::Graphics::Instance()->DrawBitmap(bitmap_cached_);
Graphics::Instance()->DrawBitmap(bitmap_cached_);
}
}

View File

@ -20,49 +20,37 @@
#pragma once
#include "macros.h"
#include "BaseTypes.hpp"
namespace easy2d
{
// 按键消息
class KeyEvent
typedef UINT EventType;
class Event
{
public:
// 按键消息类型
enum class Type : int
Event(EventType type) : type(type), has_target(false) {}
EventType type;
bool has_target;
};
class SysEvent
: public Event
{
public:
enum Type
{
Down = 0x0100, // 按下
Up // 抬起
First = WM_NULL,
WindowActivate, // 窗口获得焦点
WindowDeavtivate, // 窗口失去焦点
WindowClose, // 关闭窗口
Last
};
public:
explicit KeyEvent(
UINT message,
WPARAM w_param,
LPARAM l_param
);
SysEvent(EventType type) : Event(type) {}
// 获取事件类型
KeyEvent::Type GetType() const;
// 获取按键键值
KeyCode GetCode() const;
// 获取按键次数
int GetCount() const;
protected:
UINT message_;
WPARAM w_param_;
LPARAM l_param_;
};
// 按键消息处理接口
class KeyEventHandler
{
public:
// 处理按键消息
virtual void Handle(KeyEvent e) = 0;
static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; }
};
}

View File

@ -0,0 +1,135 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "EventDispatcher.h"
#include "logs.h"
namespace easy2d
{
void EventDispatcher::DispatchEvent(Event* e)
{
if (listeners_.IsEmpty())
return;
spEventListener next;
for (auto listener = listeners_.First(); listener; listener = next)
{
next = listener->NextItem();
if (listener->type_ == e->type)
{
listener->callback_(e);
}
}
}
void EventDispatcher::AddListener(spEventListener const & listener)
{
if (!listener)
logs::Warningln("AddListener failed, action is nullptr");
if (listener)
{
listeners_.PushBack(EventListener::ItemType(listener));
}
}
void EventDispatcher::AddListener(EventType type, EventCallback callback, String const& name)
{
spEventListener listener = new EventListener(type, callback, name);
if (listener)
{
listeners_.PushBack(EventListener::ItemType(listener));
}
}
void EventDispatcher::StartListeners(String const & listener_name)
{
for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{
if (listener->GetName() == listener_name)
{
listener->Start();
}
}
}
void EventDispatcher::StopListeners(String const & listener_name)
{
for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{
if (listener->GetName() == listener_name)
{
listener->Stop();
}
}
}
void EventDispatcher::RemoveListeners(String const & listener_name)
{
spEventListener next;
for (auto listener = listeners_.First(); listener; listener = next)
{
next = listener->NextItem();
if (listener->GetName() == listener_name)
{
listeners_.Remove(listener);
}
}
}
void EventDispatcher::StartListeners(EventType type)
{
for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{
if (listener->type_ == type)
{
listener->Start();
}
}
}
void EventDispatcher::StopListeners(EventType type)
{
for (auto listener = listeners_.First(); listener; listener = listener->NextItem())
{
if (listener->type_ == type)
{
listener->Stop();
}
}
}
void EventDispatcher::RemoveListeners(EventType type)
{
spEventListener next;
for (auto listener = listeners_.First(); listener; listener = next)
{
next = listener->NextItem();
if (listener->type_ == type)
{
listeners_.Remove(listener);
}
}
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "EventListener.h"
namespace easy2d
{
class EventDispatcher
{
using Listeners = intrusive::List<spEventListener>;
public:
// 添加监听器
void AddListener(
spEventListener const& listener
);
// 添加监听器
void AddListener(
EventType type,
EventCallback callback,
String const& name = L""
);
// 启动监听器
void StartListeners(
String const& listener_name
);
// 停止监听器
void StopListeners(
String const& listener_name
);
// 移除监听器
void RemoveListeners(
String const& listener_name
);
// 启动监听器
void StartListeners(
EventType type
);
// 停止监听器
void StopListeners(
EventType type
);
// 移除监听器
void RemoveListeners(
EventType type
);
virtual void DispatchEvent(Event* e);
protected:
Listeners listeners_;
};
}

View File

@ -0,0 +1,63 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "EventListener.h"
namespace easy2d
{
EventListener::EventListener(EventType type, EventCallback const & callback, String const & name)
: type_(type)
, callback_(callback)
, name_(name)
, running_(true)
{
}
EventListener::~EventListener()
{
}
void EventListener::Start()
{
running_ = true;
}
void EventListener::Stop()
{
running_ = false;
}
bool EventListener::IsRunning() const
{
return running_;
}
String const & EventListener::GetName() const
{
return name_;
}
void EventListener::SetName(String const & name)
{
name_ = name;
}
}

65
core/base/EventListener.h Normal file
View File

@ -0,0 +1,65 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "base.hpp"
#include "intrusive/List.hpp"
#include "Event.hpp"
namespace easy2d
{
typedef std::function<void(Event*)> EventCallback;
class EventDispatcher;
class EventListener
: public RefCounter
, protected intrusive::ListItem<spEventListener>
{
friend class EventDispatcher;
friend class intrusive::List<spEventListener>;
public:
EventListener(
EventType type,
EventCallback const& callback,
String const& name = L""
);
virtual ~EventListener();
void Start();
void Stop();
void SetName(String const& name);
bool IsRunning() const;
String const& GetName() const;
protected:
bool running_;
String name_;
EventType type_;
EventCallback callback_;
};
}

View File

@ -23,26 +23,24 @@
#include "modules.h"
#include "Factory.h"
#include "Scene.h"
#include "Transition.h"
#include "Debuger.h"
#include "Transition.h"
#include "KeyEvent.hpp"
#include "MouseEvent.hpp"
#include "../math/Matrix.hpp"
#include <thread>
#include <windowsx.h>
#include <imm.h>
#pragma comment (lib ,"imm32.lib")
namespace easy2d
{
Game::Game()
: initialized_(false)
, window_inactived_(false)
: active_(false)
, debug_(false)
, curr_scene_(nullptr)
, next_scene_(nullptr)
, transition_(nullptr)
, window_(nullptr)
, graphics_(nullptr)
, input_(nullptr)
, audio_(nullptr)
, debug_enabled_(false)
, time_scale_(1.f)
{
::CoInitialize(nullptr);
@ -61,52 +59,44 @@ namespace easy2d
void Game::Init(const Options& options)
{
if (initialized_)
return;
debug_enabled_ = options.debug;
window_ = Window::Instance();
graphics_ = devices::Graphics::Instance();
input_ = devices::Input::Instance();
audio_ = devices::Audio::Instance();
debug_ = options.debug;
ThrowIfFailed(
Factory::Instance()->Init(debug_enabled_)
Factory::Instance()->Init(debug_)
);
ThrowIfFailed(
window_->Init(
Window::Instance()->Init(
options.title,
options.width,
options.height,
options.icon,
Game::WndProc,
debug_enabled_
debug_
)
);
HWND hwnd = window_->GetHandle();
HWND hwnd = Window::Instance()->GetHandle();
ThrowIfFailed(
graphics_->Init(
Graphics::Instance()->Init(
hwnd,
options.vsync,
debug_enabled_
debug_
)
);
ThrowIfFailed(
input_->Init(
Input::Instance()->Init(
hwnd,
window_->GetContentScaleX(),
window_->GetContentScaleY(),
debug_enabled_
Window::Instance()->GetContentScaleX(),
Window::Instance()->GetContentScaleY(),
debug_
)
);
ThrowIfFailed(
audio_->Init(debug_enabled_)
Audio::Instance()->Init(debug_)
);
// disable imm
@ -114,7 +104,7 @@ namespace easy2d
// show console if debug mode enabled
HWND console = ::GetConsoleWindow();
if (debug_enabled_ && !console)
if (debug_ && !console)
{
if (::AllocConsole())
{
@ -125,7 +115,7 @@ namespace easy2d
freopen_s(&stderrStream, "conout$", "w+t", stderr);
}
}
else if (!debug_enabled_ && console)
else if (!debug_ && console)
{
::ShowWindow(console, SW_HIDE);
}
@ -139,54 +129,47 @@ namespace easy2d
// use Game instance in message loop
::SetWindowLongW(hwnd, GWLP_USERDATA, PtrToUlong(this));
initialized_ = true;
}
void Game::Run()
{
if (!initialized_)
return;
HWND hwnd = Window::Instance()->GetHandle();
::ShowWindow(window_->GetHandle(), SW_SHOWNORMAL);
::UpdateWindow(window_->GetHandle());
MSG msg = {};
while (::GetMessageW(&msg, nullptr, 0, 0))
if (hwnd)
{
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
::ShowWindow(hwnd, SW_SHOWNORMAL);
::UpdateWindow(hwnd);
MSG msg = {};
while (::GetMessageW(&msg, nullptr, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}
}
}
void Game::Quit()
{
if (window_)
::DestroyWindow(window_->GetHandle());
Window::Instance()->Destroy();
}
bool Game::EnterScene(spScene const & scene)
void Game::EnterScene(spScene const & scene)
{
if (!scene)
{
logs::Warningln("Game::EnterScene failed, scene is nullptr");
return false;
}
if (curr_scene_ == scene ||
next_scene_ == scene)
return false;
if (curr_scene_ == scene || next_scene_ == scene)
return;
next_scene_ = scene;
return true;
}
bool Game::EnterScene(spScene const& scene, spTransition const& transition)
void Game::EnterScene(spScene const& scene, spTransition const& transition)
{
if (!EnterScene(scene))
return false;
EnterScene(scene);
if (transition)
if (transition && next_scene_)
{
if (transition_)
{
@ -195,7 +178,6 @@ namespace easy2d
transition_ = transition;
transition_->Init(curr_scene_, next_scene_);
}
return true;
}
spScene const& Game::GetCurrentScene()
@ -216,7 +198,7 @@ namespace easy2d
const auto dt = (now - last) * time_scale_;
last = now;
input_->Update();
Input::Instance()->Update();
if (curr_scene_)
curr_scene_->Update(dt);
@ -224,7 +206,7 @@ namespace easy2d
if (next_scene_)
next_scene_->Update(dt);
if (debug_enabled_)
if (debug_)
Debuger::Instance()->Update(dt);
if (transition_)
@ -251,12 +233,12 @@ namespace easy2d
}
}
void Game::Render()
void Game::Render(HWND hwnd)
{
auto graphics = devices::Graphics::Instance();
auto graphics = Graphics::Instance();
ThrowIfFailed(
graphics->BeginDraw(window_->GetHandle())
graphics->BeginDraw(hwnd)
);
if (transition_)
@ -268,7 +250,7 @@ namespace easy2d
curr_scene_->Render();
}
if (debug_enabled_)
if (debug_)
{
graphics->SetTransform(math::Matrix());
graphics->SetOpacity(1.f);
@ -290,36 +272,13 @@ namespace easy2d
graphics->EndDraw()
);
if (!window_inactived_)
::InvalidateRect(window_->GetHandle(), NULL, FALSE);
if (active_)
::InvalidateRect(hwnd, NULL, FALSE);
}
void Game::Dispatch(MouseEvent const & e)
bool Game::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
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))
);
bool unhandled = false;
switch (msg)
{
@ -328,96 +287,185 @@ namespace easy2d
PAINTSTRUCT ps;
::BeginPaint(hwnd, &ps);
game->Update();
game->Render();
Update();
Render(hwnd);
::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_LBUTTONDBLCLK:
//case WM_MBUTTONUP:
//case WM_MBUTTONDOWN:
//case WM_MBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
//case WM_RBUTTONDBLCLK:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
{
game->Dispatch(MouseEvent(msg, w_param, l_param));
float x = GET_X_LPARAM(lparam) * Window::Instance()->GetContentScaleX();
float y = GET_Y_LPARAM(lparam) * Window::Instance()->GetContentScaleY();
float wheel_delta = 0.f;
MouseEvent::Type type;
if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN)
type = MouseEvent::Down;
else if (msg == WM_LBUTTONUP || msg == WM_RBUTTONUP)
type = MouseEvent::Up;
else if (msg == WM_MOUSEMOVE)
type = MouseEvent::Move;
else
{
type = MouseEvent::Wheel;
wheel_delta = GET_WHEEL_DELTA_WPARAM(wparam) / 120.f;
}
MouseEvent event(type, x, y, wheel_delta);
if (wparam & MK_LBUTTON || wparam & MK_RBUTTON)
event.button_down = true;
Dispatch(&event);
}
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);
KeyEvent event(msg, KeyCode(wparam));
Dispatch(&event);
}
break;
case WM_DISPLAYCHANGE:
{
E2D_LOG("The display resolution has changed");
::InvalidateRect(hwnd, nullptr, FALSE);
}
result = 0;
was_handled = true;
break;
case WM_CLOSE:
{
if (game->OnClose())
E2D_LOG("Received a message to close the window");
SysEvent event(SysEvent::WindowClose);
Dispatch(&event);
if (OnClose())
{
::DestroyWindow(hwnd);
}
}
result = 0;
was_handled = true;
break;
case WM_DESTROY:
{
game->OnExit();
E2D_LOG("Window was destroyed");
OnExit();
::PostQuitMessage(0);
}
result = 1;
was_handled = true;
break;
case WM_SIZE:
{
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{
active_ = false;
E2D_LOG("Window minimized");
}
else if (SIZE_RESTORED == wparam)
{
active_ = true;
::InvalidateRect(hwnd, nullptr, FALSE);
E2D_LOG("Window restored");
}
UINT width = LOWORD(lparam);
UINT height = HIWORD(lparam);
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
Graphics::Instance()->Resize(width, height);
}
unhandled = true;
break;
case WM_ACTIVATE:
{
if (WA_INACTIVE == wparam)
{
E2D_LOG("Window deactivated");
SysEvent event(SysEvent::WindowDeavtivate);
Dispatch(&event);
}
else
{
E2D_LOG("Window activated");
SysEvent event(SysEvent::WindowActivate);
Dispatch(&event);
}
}
unhandled = true;
break;
case WM_SETTEXT:
{
E2D_LOG("Window title changed");
}
unhandled = true;
break;
case WM_SETICON:
{
E2D_LOG("Window icon changed");
}
unhandled = true;
break;
default:
unhandled = true;
break;
}
return !unhandled;
}
void Game::Dispatch(Event * event)
{
if (transition_)
return;
if (curr_scene_)
curr_scene_->DispatchEvent(event);
}
LRESULT CALLBACK Game::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
LRESULT result = 0;
bool was_handled = false;
Game * game = reinterpret_cast<Game*>(
static_cast<LONG_PTR>(::GetWindowLongW(hwnd, GWLP_USERDATA))
);
if (game)
{
was_handled = game->HandleMessage(hwnd, msg, wparam, lparam);
}
if (!was_handled)
{
result = ::DefWindowProcW(hwnd, msg, w_param, l_param);
result = ::DefWindowProcW(hwnd, msg, wparam, lparam);
}
return result;
}
}
}

View File

@ -25,8 +25,7 @@
#include "render.h"
#include "input.h"
#include "audio.h"
#include "KeyEvent.h"
#include "MouseEvent.h"
#include "Event.hpp"
namespace easy2d
{
@ -62,11 +61,10 @@ namespace easy2d
virtual ~Game();
// 退出
// 退出游戏
virtual void OnExit() {}
// 窗口关闭时
// 返回值:返回 false 将阻止窗口关闭
// 窗口关闭
virtual bool OnClose() { return true; }
// 初始化
@ -81,12 +79,12 @@ namespace easy2d
void Quit();
// 切换场景
bool EnterScene(
void EnterScene(
spScene const& scene /* 场景 */
);
// 切换场景
bool EnterScene(
void EnterScene(
spScene const& scene, /* 场景 */
spTransition const& transition /* 场景动画 */
);
@ -98,32 +96,29 @@ namespace easy2d
void SetTimeScale(float scale);
private:
void Render();
void Render(HWND);
void Update();
void Dispatch(
MouseEvent const& e
bool HandleMessage(
HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam
);
void Dispatch(
KeyEvent const& e
Event* event
);
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
private:
bool initialized_;
bool debug_enabled_;
bool window_inactived_;
bool debug_;
bool active_;
float time_scale_;
spScene curr_scene_;
spScene next_scene_;
spTransition transition_;
WindowImpl* window_;
devices::GraphicsDevice* graphics_;
devices::InputDevice* input_;
devices::AudioDevice* audio_;
};
}

View File

@ -70,7 +70,7 @@ namespace easy2d
{
if (geometry_ && geometry_->geo_)
{
auto graphics = devices::Graphics::Instance();
auto graphics = Graphics::Instance();
graphics->SetTransform(geometry_->GetTransformMatrix() * GetTransformMatrix());
graphics->FillGeometry(

View File

@ -70,7 +70,7 @@ namespace easy2d
bool Image::Load(Resource const& res)
{
cpBitmap bitmap;
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(bitmap, res);
HRESULT hr = Graphics::Instance()->CreateBitmapFromResource(bitmap, res);
if (FAILED(hr))
{
logs::Errorln(hr, "Load Image from resource failed!");
@ -94,7 +94,7 @@ namespace easy2d
String image_file_path = image_file.GetPath();
cpBitmap bitmap;
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(bitmap, image_file_path);
HRESULT hr = Graphics::Instance()->CreateBitmapFromFile(bitmap, image_file_path);
if (FAILED(hr))
{
logs::Errorln(hr, "Load Image from file failed!");

View File

@ -24,88 +24,92 @@
namespace easy2d
{
namespace devices
InputDevice::InputDevice()
: hwnd_(nullptr)
, scale_x_(1.f)
, scale_y_(1.f)
{
InputDevice::InputDevice()
: hwnd_(nullptr)
, scale_x_(1.f)
, scale_y_(1.f)
{
ZeroMemory(keys_, sizeof(keys_));
ZeroMemory(keys_cache_, sizeof(keys_cache_));
}
ZeroMemory(keys_, sizeof(keys_));
ZeroMemory(keys_cache_, sizeof(keys_cache_));
}
InputDevice::~InputDevice()
{
E2D_LOG("Destroying input device");
}
InputDevice::~InputDevice()
{
E2D_LOG("Destroying input device");
}
HRESULT InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
{
E2D_LOG("Initing input device");
HRESULT InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
{
E2D_LOG("Initing input device");
hwnd_ = hwnd;
scale_x_ = scale_x;
scale_y_ = scale_y;
hwnd_ = hwnd;
scale_x_ = scale_x;
scale_y_ = scale_y;
return S_OK;
}
return S_OK;
}
void InputDevice::Update()
{
memcpy(keys_cache_, keys_, sizeof(keys_cache_));
GetKeyboardState(keys_);
void InputDevice::Update()
{
memcpy(keys_cache_, keys_, sizeof(keys_cache_));
GetKeyboardState(keys_);
}
POINT client_cursor_pos;
GetCursorPos(&client_cursor_pos);
ScreenToClient(hwnd_, &client_cursor_pos);
bool InputDevice::IsDown(KeyCode code)
{
return !!(keys_[static_cast<int>(code)] & 0x80);
}
mouse_pos_ = Point(client_cursor_pos.x * scale_x_, client_cursor_pos.y * scale_y_);
}
bool InputDevice::IsDown(MouseButton btn)
{
return !!(keys_[static_cast<int>(btn)] & 0x80);
}
bool InputDevice::IsDown(KeyCode code)
{
if (keys_[static_cast<int>(code)] & 0x80)
return true;
return false;
}
bool InputDevice::WasPressed(KeyCode code)
{
return !(keys_cache_[static_cast<int>(code)] & 0x80)
&& (keys_[static_cast<int>(code)] & 0x80);
}
bool InputDevice::IsDown(MouseCode code)
{
if (keys_[static_cast<int>(code)] & 0x80)
return true;
return false;
}
bool InputDevice::WasPressed(MouseButton btn)
{
return !(keys_cache_[static_cast<int>(btn)] & 0x80)
&& (keys_[static_cast<int>(btn)] & 0x80);
}
bool InputDevice::WasPressed(KeyCode code)
{
if (keys_cache_[static_cast<int>(code)] & 0x80 &&
!(keys_[static_cast<int>(code)] & 0x80))
return true;
return false;
}
bool InputDevice::WasReleased(KeyCode code)
{
return (keys_cache_[static_cast<int>(code)] & 0x80)
&& !(keys_[static_cast<int>(code)] & 0x80);
}
bool InputDevice::WasPressed(MouseCode code)
{
if (keys_cache_[static_cast<int>(code)] & 0x80 &&
!(keys_[static_cast<int>(code)] & 0x80))
return true;
return false;
}
bool InputDevice::WasReleased(MouseButton btn)
{
return (keys_cache_[static_cast<int>(btn)] & 0x80)
&& !(keys_[static_cast<int>(btn)] & 0x80);
}
float InputDevice::GetMouseX()
{
return mouse_pos_.x;
}
float InputDevice::GetMouseX()
{
POINT pos;
::GetCursorPos(&pos);
::ScreenToClient(hwnd_, &pos);
return pos.x * scale_x_;
}
float InputDevice::GetMouseY()
{
return mouse_pos_.y;
}
float InputDevice::GetMouseY()
{
POINT pos;
::GetCursorPos(&pos);
::ScreenToClient(hwnd_, &pos);
return pos.y * scale_y_;
}
Point InputDevice::GetMousePos()
{
return mouse_pos_;
}
Point InputDevice::GetMousePos()
{
POINT pos;
::GetCursorPos(&pos);
::ScreenToClient(hwnd_, &pos);
return Point{ pos.x * scale_x_, pos.y * scale_y_ };
}
}

View File

@ -24,61 +24,67 @@
namespace easy2d
{
namespace devices
class InputDevice
: protected Noncopyable
{
class InputDevice
: protected Noncopyable
{
E2D_DECLARE_SINGLETON(InputDevice);
E2D_DECLARE_SINGLETON(InputDevice);
public:
HRESULT Init(HWND hwnd, float scale_x, float scale_y, bool debug);
public:
HRESULT Init(HWND hwnd, float scale_x, float scale_y, bool debug);
// 检测键盘按键是否正被按下
bool IsDown(
KeyCode code
);
// 检测键盘按键是否正被按下
bool IsDown(
KeyCode code
);
// 检测鼠标按键是否正被按下
bool IsDown(
MouseCode code
);
// 检测鼠标按键是否正被按下
bool IsDown(
MouseButton btn
);
// 检测键盘按键是否点击
bool WasPressed(
KeyCode code
);
// 检测键盘按键是否刚被点击
bool WasPressed(
KeyCode code
);
// 检测鼠标按键是否点击
bool WasPressed(
MouseCode code
);
// 检测鼠标按键是否刚被点击
bool WasPressed(
MouseButton btn
);
// 获得鼠标X轴坐标值
float GetMouseX();
// 检测键盘按键是否刚抬起
bool WasReleased(
KeyCode code
);
// 获得鼠标Y轴坐标值
float GetMouseY();
// 检测鼠标按键是否刚抬起
bool WasReleased(
MouseButton btn
);
// 获得鼠标坐标值
Point GetMousePos();
// 获得鼠标 x 坐标
float GetMouseX();
void Update();
// 获得鼠标 y 坐标
float GetMouseY();
protected:
InputDevice();
// 获得鼠标坐标
Point GetMousePos();
~InputDevice();
void Update();
protected:
HWND hwnd_;
float scale_x_;
float scale_y_;
BYTE keys_[256];
BYTE keys_cache_[256];
Point mouse_pos_;
};
protected:
InputDevice();
E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input);
}
~InputDevice();
protected:
HWND hwnd_;
float scale_x_;
float scale_y_;
BYTE keys_[256];
BYTE keys_cache_[256];
};
E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input);
}

View File

@ -18,29 +18,30 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "KeyEvent.h"
#pragma once
#include "Event.hpp"
#include "BaseTypes.hpp"
namespace easy2d
{
KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param)
: message_(message)
, w_param_(w_param)
, l_param_(l_param)
class KeyEvent
: public Event
{
}
public:
enum Type
{
First = WM_KEYFIRST,
KeyCode KeyEvent::GetCode() const
{
return static_cast<KeyCode>(w_param_);
}
Down, // 键按下
Up, // 键抬起
int KeyEvent::GetCount() const
{
return static_cast<int>((DWORD)l_param_ & 0x0000FFFF);
}
Last // 结束标志
};
KeyEvent::Type KeyEvent::GetType() const
{
return Type(message_);
}
KeyEvent(EventType type, KeyCode key) : Event(type), key(key) {}
static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; }
KeyCode key;
};
}

View File

@ -1,85 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "MouseEvent.h"
#include "window.h"
namespace easy2d
{
MouseEvent::MouseEvent(UINT message, WPARAM w_param, LPARAM l_param)
: message_(message)
, w_param_(w_param)
, l_param_(l_param)
{
}
float MouseEvent::GetX() const
{
return ((float)(short)LOWORD(l_param_)) * Window::Instance()->GetContentScaleX();
}
float MouseEvent::GetY() const
{
return ((float)(short)HIWORD(l_param_)) * Window::Instance()->GetContentScaleY();
}
Point MouseEvent::GetPosition() const
{
return Point(
((float)(short)LOWORD(l_param_)) * Window::Instance()->GetContentScaleX(),
((float)(short)HIWORD(l_param_)) * Window::Instance()->GetContentScaleY()
);
}
bool MouseEvent::IsShiftDown() const
{
return GET_KEYSTATE_WPARAM(w_param_) == MK_SHIFT;
}
bool MouseEvent::IsCtrlDown() const
{
return GET_KEYSTATE_WPARAM(w_param_) == MK_CONTROL;
}
float MouseEvent::GetWheelDelta() const
{
return static_cast<float>(GET_WHEEL_DELTA_WPARAM(w_param_));
}
bool MouseEvent::IsLButtonDown() const
{
return GET_KEYSTATE_WPARAM(w_param_) == MK_LBUTTON;
}
bool MouseEvent::IsRButtonDown() const
{
return GET_KEYSTATE_WPARAM(w_param_) == MK_RBUTTON;
}
bool MouseEvent::IsMButtonDown() const
{
return GET_KEYSTATE_WPARAM(w_param_) == MK_MBUTTON;
}
MouseEvent::Type MouseEvent::GetType() const
{
return Type(message_);
}
}

View File

@ -1,97 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "macros.h"
#include "BaseTypes.hpp"
namespace easy2d
{
// 鼠标消息
class MouseEvent
{
public:
// 鼠标消息类型
enum class Type : int
{
Move = 0x0200, // 鼠标移动
LeftDown, // 鼠标左键按下
LeftUp, // 鼠标左键抬起
LeftDoubleClick, // 鼠标左键双击
RightDown, // 鼠标右键按下
RightUp, // 鼠标右键抬起
RightDoubleClick, // 鼠标右键双击
MiddleDown, // 鼠标中键按下
MiddleUp, // 鼠标中键抬起
MiddleDoubleClick, // 鼠标中键双击
Wheel // 滑动滚轮
};
public:
explicit MouseEvent(
UINT message,
WPARAM w_param,
LPARAM l_param
);
// 获取鼠标横坐标
float GetX() const;
// 获取鼠标纵坐标
float GetY() const;
// 获取鼠标坐标
Point GetPosition() const;
// 获取事件类型
MouseEvent::Type GetType() const;
float GetWheelDelta() const;
// 鼠标左键是否按下
bool IsLButtonDown() const;
// 鼠标右键是否按下
bool IsRButtonDown() const;
// 鼠标中键是否按下
bool IsMButtonDown() const;
// Shift 键是否按下
bool IsShiftDown() const;
// Ctrl 键是否按下
bool IsCtrlDown() const;
protected:
UINT message_;
WPARAM w_param_;
LPARAM l_param_;
};
// 鼠标消息处理接口
class MouseEventHandler
{
public:
// 处理鼠标消息
virtual void Handle(MouseEvent e) = 0;
};
}

51
core/base/MouseEvent.hpp Normal file
View File

@ -0,0 +1,51 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "Event.hpp"
namespace easy2d
{
class MouseEvent
: public Event
{
public:
enum Type
{
First = WM_MOUSEFIRST,
Move, // 移动
Down, // 按下
Up, // 抬起
Wheel, // 滚轮滚动
Last // 结束标志
};
MouseEvent(EventType type, float x, float y, float wheel_delta) : Event(type), x(x), y(y), wheel_delta(wheel_delta), button_down(false) {}
static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; }
float x;
float y;
float wheel_delta;
bool button_down;
};
}

View File

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

View File

@ -105,7 +105,7 @@ namespace easy2d
UpdateTransform();
auto graphics = devices::Graphics::Instance();
auto graphics = Graphics::Instance();
if (children_.IsEmpty())
{
@ -146,13 +146,36 @@ namespace easy2d
}
}
void Node::DispatchEvent(Event * e)
{
if (!visible_)
return;
this->HandleEvent(e);
if (!e->has_target)
{
EventDispatcher::DispatchEvent(e);
}
}
void Node::HandleEvent(Event * e)
{
spNode prev;
for (auto child = children_.Last(); child; child = prev)
{
prev = child->PrevItem();
child->HandleEvent(e);
}
}
void Node::DrawBorder()
{
if (visible_)
{
if (border_)
{
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f);
Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f);
}
for (auto child = children_.First(); child; child = child->NextItem())
@ -180,6 +203,16 @@ namespace easy2d
return final_matrix_;
}
spNode Node::GetParent() const
{
return parent_;
}
spScene Node::GetScene() const
{
return scene_;
}
void Node::UpdateTransform()
{
if (!dirty_transform_)
@ -241,44 +274,6 @@ namespace easy2d
}
}
bool Node::Dispatch(const MouseEvent & e, bool handled)
{
if (visible_)
{
spNode prev;
for (auto child = children_.Last(); child; child = prev)
{
prev = child->PrevItem();
handled = child->Dispatch(e, handled);
}
auto handler = dynamic_cast<MouseEventHandler*>(this);
if (handler)
handler->Handle(e);
}
return handled;
}
bool Node::Dispatch(const KeyEvent & e, bool handled)
{
if (visible_)
{
spNode prev;
for (auto child = children_.Last(); child; child = prev)
{
prev = child->PrevItem();
handled = child->Dispatch(e, handled);
}
auto handler = dynamic_cast<KeyEventHandler*>(this);
if (handler)
handler->Handle(e);
}
return handled;
}
void Node::UpdateOpacity()
{
if (parent_)
@ -291,6 +286,15 @@ namespace easy2d
}
}
void Node::SetScene(Scene * scene)
{
scene_ = scene;
for (auto child = children_.First(); child; child = child->NextItem())
{
child->scene_ = scene;
}
}
void Node::SetZOrder(int order)
{
if (z_order_ == order)
@ -402,6 +406,7 @@ namespace easy2d
children_.PushBack(Node::ItemType(child));
child->parent_ = this;
child->SetScene(this->scene_);
child->dirty_transform_ = true;
child->SetZOrder(z_order);
child->UpdateOpacity();
@ -471,12 +476,12 @@ namespace easy2d
logs::Warningln("Node::RemoveChild failed, child is nullptr");
if (children_.IsEmpty())
{
return false;
}
if (child)
{
child->parent_ = nullptr;
if (child->scene_) child->SetScene(nullptr);
children_.Remove(Node::ItemType(child));
return true;
}
@ -497,7 +502,9 @@ namespace easy2d
next = child->NextItem();
if (child->hash_name_ == hash_code && child->name_ == child_name)
children_.Remove(child);
{
RemoveChild(child);
}
}
}

View File

@ -22,10 +22,9 @@
#include "base.hpp"
#include "time.h"
#include "Unit.h"
#include "KeyEvent.h"
#include "MouseEvent.h"
#include "ActionManager.h"
#include "TaskManager.h"
#include "ActionManager.h"
#include "EventDispatcher.h"
#include "intrusive/List.hpp"
namespace easy2d
@ -35,8 +34,9 @@ namespace easy2d
// 节点
class Node
: public Unit
, public ActionManager
, public TaskManager
, public ActionManager
, public EventDispatcher
, protected intrusive::ListItem<spNode>
{
friend class Game;
@ -59,6 +59,9 @@ namespace easy2d
// 渲染节点
virtual void OnRender();
// 处理事件
virtual void HandleEvent(Event* e);
// 获取显示状态
bool IsVisible() const { return visible_; }
@ -96,7 +99,10 @@ namespace easy2d
virtual math::Matrix const& GetTransformMatrix() override;
// 获取父节点
virtual spNode GetParent() const { return parent_; }
spNode GetParent() const;
// 获取所在场景
spScene GetScene() const;
// 设置是否显示
void SetVisible(
@ -215,6 +221,8 @@ namespace easy2d
// 从父节点移除
void RemoveFromParent();
virtual void DispatchEvent(Event* e) override;
// 设置默认支点
static void SetDefaultPivot(
float pivot_x,
@ -240,15 +248,7 @@ namespace easy2d
void UpdateOpacity();
virtual bool Dispatch(
const MouseEvent& e,
bool handled
);
virtual bool Dispatch(
const KeyEvent& e,
bool handled
);
void SetScene(Scene* scene);
protected:
bool inited_;
@ -260,6 +260,7 @@ namespace easy2d
String name_;
size_t hash_name_;
Node* parent_;
Scene* scene_;
Color border_color_;
Children children_;
cpGeometry border_;

View File

@ -20,14 +20,38 @@
#include "Scene.h"
#include "Node.h"
#include "logs.h"
namespace easy2d
{
Scene::Scene()
{
AddListener(SysEvent::WindowActivate, std::bind(&Scene::OnActivate, this));
AddListener(SysEvent::WindowDeavtivate, std::bind(&Scene::OnDeactivate, this));
scene_ = this;
}
Scene::~Scene()
{
}
void Scene::OnEnter()
{
E2D_LOG("Scene entered");
}
void Scene::OnExit()
{
E2D_LOG("Scene exited");
}
void Scene::OnDeactivate()
{
}
void Scene::OnActivate()
{
}
}

View File

@ -33,9 +33,15 @@ namespace easy2d
virtual ~Scene();
// 进入场景
virtual void OnEnter() {}
virtual void OnEnter();
// 退出场景
virtual void OnExit() {}
virtual void OnExit();
// 窗口获得焦点
virtual void OnActivate();
// 窗口失去焦点
virtual void OnDeactivate();
};
}

View File

@ -131,7 +131,7 @@ namespace easy2d
{
if (image_)
{
devices::Graphics::Instance()->DrawImage(image_);
Graphics::Instance()->DrawImage(image_);
}
}
}

View File

@ -43,7 +43,7 @@ namespace easy2d
void TaskManager::AddTask(spTask const& task)
{
if (!task)
logs::Warningln("Node::AddTask failed, action is nullptr");
logs::Warningln("AddTask failed, task is nullptr");
if (task)
{

View File

@ -295,7 +295,7 @@ namespace easy2d
{
if (text_layout_)
{
auto graphics = devices::Graphics::Instance();
auto graphics = Graphics::Instance();
graphics->SetTextStyle(
style_.color,
style_.outline,

View File

@ -66,14 +66,14 @@ namespace easy2d
if (in_scene_)
{
ThrowIfFailed(
devices::Graphics::Instance()->CreateLayer(in_layer_)
Graphics::Instance()->CreateLayer(in_layer_)
);
}
if (out_scene_)
{
ThrowIfFailed(
devices::Graphics::Instance()->CreateLayer(out_layer_)
Graphics::Instance()->CreateLayer(out_layer_)
);
}
@ -101,7 +101,7 @@ namespace easy2d
void Transition::Render()
{
auto graphics = devices::Graphics::Instance();
auto graphics = Graphics::Instance();
if (out_scene_)
{

View File

@ -46,7 +46,7 @@ namespace easy2d
{
Destroy();
devices::Audio::Instance()->DeleteVoice(this);
Audio::Instance()->DeleteVoice(this);
}
HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count)
@ -155,90 +155,88 @@ namespace easy2d
}
namespace devices
//-------------------------------------------------------
// AudioDevice
//-------------------------------------------------------
AudioDevice::AudioDevice()
: x_audio2_(nullptr)
, mastering_voice_(nullptr)
{
//-------------------------------------------------------
// AudioDevice
//-------------------------------------------------------
AudioDevice::AudioDevice()
: x_audio2_(nullptr)
, mastering_voice_(nullptr)
{
}
AudioDevice::~AudioDevice()
{
E2D_LOG("Destroying audio device");
ClearVoiceCache();
if (mastering_voice_)
{
mastering_voice_->DestroyVoice();
mastering_voice_ = nullptr;
}
SafeRelease(x_audio2_);
modules::MediaFoundation().MFShutdown();
}
HRESULT AudioDevice::Init(bool debug)
{
E2D_LOG("Initing audio device");
HRESULT hr = modules::MediaFoundation().MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (SUCCEEDED(hr))
{
hr = modules::XAudio2().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
}
if (SUCCEEDED(hr))
{
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
return hr;
}
HRESULT AudioDevice::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx)
{
HRESULT hr;
IXAudio2SourceVoice* source_voice;
hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr))
{
voice.SetSourceVoice(source_voice);
voice_cache_.insert(&voice);
}
return hr;
}
void AudioDevice::DeleteVoice(Voice* voice)
{
voice_cache_.erase(voice);
}
void AudioDevice::ClearVoiceCache()
{
for (auto voice : voice_cache_)
{
voice->Destroy();
}
voice_cache_.clear();
}
void AudioDevice::Open()
{
x_audio2_->StartEngine();
}
void AudioDevice::Close()
{
x_audio2_->StopEngine();
}
}
AudioDevice::~AudioDevice()
{
E2D_LOG("Destroying audio device");
ClearVoiceCache();
if (mastering_voice_)
{
mastering_voice_->DestroyVoice();
mastering_voice_ = nullptr;
}
SafeRelease(x_audio2_);
modules::MediaFoundation().MFShutdown();
}
HRESULT AudioDevice::Init(bool debug)
{
E2D_LOG("Initing audio device");
HRESULT hr = modules::MediaFoundation().MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (SUCCEEDED(hr))
{
hr = modules::XAudio2().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
}
if (SUCCEEDED(hr))
{
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
return hr;
}
HRESULT AudioDevice::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx)
{
HRESULT hr;
IXAudio2SourceVoice* source_voice;
hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr))
{
voice.SetSourceVoice(source_voice);
voice_cache_.insert(&voice);
}
return hr;
}
void AudioDevice::DeleteVoice(Voice* voice)
{
voice_cache_.erase(voice);
}
void AudioDevice::ClearVoiceCache()
{
for (auto voice : voice_cache_)
{
voice->Destroy();
}
voice_cache_.clear();
}
void AudioDevice::Open()
{
x_audio2_->StartEngine();
}
void AudioDevice::Close()
{
x_audio2_->StopEngine();
}
}

View File

@ -72,44 +72,42 @@ namespace easy2d
IXAudio2SourceVoice* source_voice_;
};
namespace devices
class AudioDevice
: protected Noncopyable
{
class AudioDevice
: protected Noncopyable
{
E2D_DECLARE_SINGLETON(AudioDevice);
E2D_DECLARE_SINGLETON(AudioDevice);
public:
HRESULT Init(bool debug);
public:
HRESULT Init(bool debug);
// ¿ªÆôÉ豸
void Open();
// ¿ªÆôÉ豸
void Open();
// ¹Ø±ÕÉ豸
void Close();
// ¹Ø±ÕÉ豸
void Close();
HRESULT CreateVoice(
Voice& voice,
const WAVEFORMATEX* wfx
);
HRESULT CreateVoice(
Voice& voice,
const WAVEFORMATEX* wfx
);
void DeleteVoice(
Voice* voice
);
void DeleteVoice(
Voice* voice
);
void ClearVoiceCache();
void ClearVoiceCache();
protected:
AudioDevice();
protected:
AudioDevice();
~AudioDevice();
~AudioDevice();
protected:
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
std::set<Voice*> voice_cache_;
};
protected:
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
std::set<Voice*> voice_cache_;
};
E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio);
}
E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio);
}

View File

@ -24,6 +24,7 @@
#include "ObjectBase.h"
#include "intrusive/SmartPointer.hpp"
#include "d2dres.hpp"
#include <assert.h>
#ifndef E2D_DECLARE_SMART_PTR
#define E2D_DECLARE_SMART_PTR(class_name)\
@ -43,6 +44,7 @@ namespace easy2d
E2D_DECLARE_SMART_PTR(Image);
E2D_DECLARE_SMART_PTR(Music);
E2D_DECLARE_SMART_PTR(Task);
E2D_DECLARE_SMART_PTR(EventListener);
E2D_DECLARE_SMART_PTR(Frames);
E2D_DECLARE_SMART_PTR(Geometry);

View File

@ -28,493 +28,490 @@
namespace easy2d
{
namespace devices
GraphicsDevice::GraphicsDevice()
: fps_text_format_(nullptr)
, fps_text_layout_(nullptr)
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
, opacity_(1.f)
, window_occluded_(false)
, vsync_enabled_(true)
, antialias_(true)
, text_antialias_(TextAntialias::ClearType)
{
GraphicsDevice::GraphicsDevice()
: fps_text_format_(nullptr)
, fps_text_layout_(nullptr)
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
, opacity_(1.f)
, window_occluded_(false)
, vsync_enabled_(true)
, antialias_(true)
, text_antialias_(TextAntialias::ClearType)
}
GraphicsDevice::~GraphicsDevice()
{
E2D_LOG("Destroying graphics device");
ClearImageCache();
}
HRESULT GraphicsDevice::Init(HWND hwnd, bool vsync, bool debug)
{
E2D_LOG("Initing graphics device");
HRESULT hr = CreateResources(hwnd);
if (SUCCEEDED(hr))
{
vsync_enabled_ = vsync;
}
return hr;
}
GraphicsDevice::~GraphicsDevice()
HRESULT GraphicsDevice::BeginDraw(HWND hwnd)
{
HRESULT hr = CreateResources(hwnd);
if (SUCCEEDED(hr))
{
E2D_LOG("Destroying graphics device");
window_occluded_ = !!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
ClearImageCache();
}
HRESULT GraphicsDevice::Init(HWND hwnd, bool vsync, bool debug)
{
E2D_LOG("Initing graphics device");
HRESULT hr = CreateResources(hwnd);
if (SUCCEEDED(hr))
{
vsync_enabled_ = vsync;
}
return hr;
}
HRESULT GraphicsDevice::BeginDraw(HWND hwnd)
{
HRESULT hr = CreateResources(hwnd);
if (SUCCEEDED(hr))
{
window_occluded_ = !!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
if (!window_occluded_)
{
render_target_->BeginDraw();
render_target_->Clear(clear_color_);
}
}
return hr;
}
HRESULT GraphicsDevice::EndDraw()
{
HRESULT hr = S_OK;
if (!window_occluded_)
{
hr = render_target_->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
// 并在下一次调用时重建资源
DiscardResources();
hr = S_OK;
}
render_target_->BeginDraw();
render_target_->Clear(clear_color_);
}
return hr;
}
void GraphicsDevice::ClearImageCache()
{
bitmap_cache_.clear();
}
HRESULT GraphicsDevice::CreateLayer(cpLayer& layer)
{
if (!render_target_)
return E_UNEXPECTED;
layer = nullptr;
return render_target_->CreateLayer(&layer);
}
HRESULT GraphicsDevice::CreateSolidColorBrush(cpSolidColorBrush & brush) const
{
if (!render_target_)
return E_UNEXPECTED;
brush = nullptr;
return render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&brush
);
}
HRESULT GraphicsDevice::DrawGeometry(
cpGeometry const& geometry,
Color const& stroke_color,
float stroke_width,
StrokeStyle stroke
)
{
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush_->SetColor(stroke_color);
auto stroke_style = Factory::Instance()->GetStrokeStyle(stroke);
render_target_->DrawGeometry(
geometry.Get(),
solid_brush_.Get(),
stroke_width,
stroke_style.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::FillGeometry(cpGeometry const & geometry, const Color & fill_color)
{
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush_->SetColor(fill_color);
render_target_->FillGeometry(
geometry.Get(),
solid_brush_.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::DrawImage(spImage const & image)
{
if (!render_target_)
return E_UNEXPECTED;
if (!image->GetBitmap())
return S_OK;
if (window_occluded_)
return S_OK;
render_target_->DrawBitmap(
image->GetBitmap().Get(),
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
opacity_,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
image->GetCropRect()
);
return S_OK;
}
HRESULT GraphicsDevice::DrawBitmap(
cpBitmap const& bitmap
)
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
// Do not crop bitmap
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
render_target_->DrawBitmap(
bitmap.Get(),
rect,
opacity_,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
rect
);
return S_OK;
}
HRESULT GraphicsDevice::DrawTextLayout(cpTextLayout const& text_layout)
{
if (!text_renderer_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
}
HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size)
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->SetTransform(ConvertToD2DMatrix(clip_matrix));
render_target_->PushAxisAlignedClip(
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
);
return S_OK;
}
HRESULT GraphicsDevice::PopClip()
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopAxisAlignedClip();
return S_OK;
}
HRESULT GraphicsDevice::PushLayer(cpLayer const& layer, LayerProperties const& properties)
{
if (!render_target_ ||
!solid_brush_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PushLayer(
D2D1::LayerParameters(
properties.area,
nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(),
properties.opacity,
solid_brush_.Get(),
D2D1_LAYER_OPTIONS_NONE
),
layer.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::PopLayer()
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopLayer();
return S_OK;
}
HRESULT GraphicsDevice::GetSize(Size & size)
{
if (!render_target_)
return E_UNEXPECTED;
auto rtsize = render_target_->GetSize();
size.width = rtsize.width;
size.height = rtsize.height;
return S_OK;
}
HRESULT GraphicsDevice::CreateBitmapFromFile(cpBitmap& bitmap, String const& file_path)
{
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
size_t hash_code = std::hash<String>{}(file_path);
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
cpBitmap bitmap_tmp;
HRESULT hr = Factory::Instance()->CreateBitmapFromFile(
bitmap,
render_target_,
file_path
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT GraphicsDevice::CreateBitmapFromResource(cpBitmap& bitmap, Resource const& res)
{
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
size_t hash_code = res.GetHashCode();
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
HRESULT hr = Factory::Instance()->CreateBitmapFromResource(
bitmap,
render_target_,
res
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT GraphicsDevice::CreateBitmapRenderTarget(cpBitmapRenderTarget & brt)
{
if (!render_target_)
return E_UNEXPECTED;
brt = nullptr;
return render_target_->CreateCompatibleRenderTarget(&brt);
}
HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->Resize(D2D1::SizeU(width, height));
return S_OK;
}
HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->SetTransform(ConvertToD2DMatrix(matrix));
return S_OK;
}
HRESULT GraphicsDevice::SetOpacity(float opacity)
{
if (!render_target_)
return E_UNEXPECTED;
opacity_ = opacity;
solid_brush_->SetOpacity(opacity);
return S_OK;
}
HRESULT GraphicsDevice::SetTextStyle(
Color const& color,
bool has_outline,
Color const& outline_color,
float outline_width,
StrokeStyle outline_stroke
)
{
if (!text_renderer_)
return E_UNEXPECTED;
auto stroke_style = Factory::Instance()->GetStrokeStyle(outline_stroke);
text_renderer_->SetTextStyle(
color,
has_outline,
outline_color,
outline_width,
stroke_style.Get()
);
return S_OK;
}
void GraphicsDevice::SetClearColor(const Color& color)
{
clear_color_ = color;
}
HRESULT GraphicsDevice::SetAntialiasMode(bool enabled)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->SetAntialiasMode(
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
);
antialias_ = enabled;
return S_OK;
}
HRESULT GraphicsDevice::SetTextAntialiasMode(TextAntialias mode)
{
if (!render_target_)
return E_UNEXPECTED;
text_antialias_ = mode;
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
switch (text_antialias_)
{
case TextAntialias::Default:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
break;
case TextAntialias::ClearType:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
break;
case TextAntialias::GrayScale:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
break;
case TextAntialias::None:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
break;
default:
break;
}
render_target_->SetTextAntialiasMode(antialias_mode);
return S_OK;
}
HRESULT GraphicsDevice::CreateResources(HWND hwnd)
{
HRESULT hr = S_OK;
if (!render_target_)
{
RECT rc;
::GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
hr = Factory::Instance()->CreateHwndRenderTarget(
render_target_,
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
vsync_enabled_ ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
)
);
if (SUCCEEDED(hr))
{
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
}
if (SUCCEEDED(hr))
{
hr = render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&solid_brush_
);
}
if (SUCCEEDED(hr))
{
hr = Factory::Instance()->CreateTextRenderer(
text_renderer_,
render_target_,
solid_brush_
);
}
}
return hr;
}
void GraphicsDevice::DiscardResources()
{
// FIXME! 应通知 Game 类销毁所有节点的 device resources
fps_text_format_ = nullptr;
fps_text_layout_ = nullptr;
text_renderer_ = nullptr;
solid_brush_ = nullptr;
render_target_ = nullptr;
}
return hr;
}
HRESULT GraphicsDevice::EndDraw()
{
HRESULT hr = S_OK;
if (!window_occluded_)
{
hr = render_target_->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
// 并在下一次调用时重建资源
DiscardResources();
hr = S_OK;
}
}
return hr;
}
void GraphicsDevice::ClearImageCache()
{
bitmap_cache_.clear();
}
HRESULT GraphicsDevice::CreateLayer(cpLayer& layer)
{
if (!render_target_)
return E_UNEXPECTED;
layer = nullptr;
return render_target_->CreateLayer(&layer);
}
HRESULT GraphicsDevice::CreateSolidColorBrush(cpSolidColorBrush & brush) const
{
if (!render_target_)
return E_UNEXPECTED;
brush = nullptr;
return render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&brush
);
}
HRESULT GraphicsDevice::DrawGeometry(
cpGeometry const& geometry,
Color const& stroke_color,
float stroke_width,
StrokeStyle stroke
)
{
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush_->SetColor(stroke_color);
auto stroke_style = Factory::Instance()->GetStrokeStyle(stroke);
render_target_->DrawGeometry(
geometry.Get(),
solid_brush_.Get(),
stroke_width,
stroke_style.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::FillGeometry(cpGeometry const & geometry, const Color & fill_color)
{
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush_->SetColor(fill_color);
render_target_->FillGeometry(
geometry.Get(),
solid_brush_.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::DrawImage(spImage const & image)
{
if (!render_target_)
return E_UNEXPECTED;
if (!image->GetBitmap())
return S_OK;
if (window_occluded_)
return S_OK;
render_target_->DrawBitmap(
image->GetBitmap().Get(),
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
opacity_,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
image->GetCropRect()
);
return S_OK;
}
HRESULT GraphicsDevice::DrawBitmap(
cpBitmap const& bitmap
)
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
// Do not crop bitmap
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
render_target_->DrawBitmap(
bitmap.Get(),
rect,
opacity_,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
rect
);
return S_OK;
}
HRESULT GraphicsDevice::DrawTextLayout(cpTextLayout const& text_layout)
{
if (!text_renderer_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
}
HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size)
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->SetTransform(ConvertToD2DMatrix(clip_matrix));
render_target_->PushAxisAlignedClip(
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
);
return S_OK;
}
HRESULT GraphicsDevice::PopClip()
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopAxisAlignedClip();
return S_OK;
}
HRESULT GraphicsDevice::PushLayer(cpLayer const& layer, LayerProperties const& properties)
{
if (!render_target_ ||
!solid_brush_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PushLayer(
D2D1::LayerParameters(
properties.area,
nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(),
properties.opacity,
solid_brush_.Get(),
D2D1_LAYER_OPTIONS_NONE
),
layer.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::PopLayer()
{
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopLayer();
return S_OK;
}
HRESULT GraphicsDevice::GetSize(Size & size)
{
if (!render_target_)
return E_UNEXPECTED;
auto rtsize = render_target_->GetSize();
size.width = rtsize.width;
size.height = rtsize.height;
return S_OK;
}
HRESULT GraphicsDevice::CreateBitmapFromFile(cpBitmap& bitmap, String const& file_path)
{
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
size_t hash_code = std::hash<String>{}(file_path);
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
cpBitmap bitmap_tmp;
HRESULT hr = Factory::Instance()->CreateBitmapFromFile(
bitmap,
render_target_,
file_path
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT GraphicsDevice::CreateBitmapFromResource(cpBitmap& bitmap, Resource const& res)
{
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
size_t hash_code = res.GetHashCode();
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
HRESULT hr = Factory::Instance()->CreateBitmapFromResource(
bitmap,
render_target_,
res
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT GraphicsDevice::CreateBitmapRenderTarget(cpBitmapRenderTarget & brt)
{
if (!render_target_)
return E_UNEXPECTED;
brt = nullptr;
return render_target_->CreateCompatibleRenderTarget(&brt);
}
HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->Resize(D2D1::SizeU(width, height));
return S_OK;
}
HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->SetTransform(ConvertToD2DMatrix(matrix));
return S_OK;
}
HRESULT GraphicsDevice::SetOpacity(float opacity)
{
if (!render_target_)
return E_UNEXPECTED;
opacity_ = opacity;
solid_brush_->SetOpacity(opacity);
return S_OK;
}
HRESULT GraphicsDevice::SetTextStyle(
Color const& color,
bool has_outline,
Color const& outline_color,
float outline_width,
StrokeStyle outline_stroke
)
{
if (!text_renderer_)
return E_UNEXPECTED;
auto stroke_style = Factory::Instance()->GetStrokeStyle(outline_stroke);
text_renderer_->SetTextStyle(
color,
has_outline,
outline_color,
outline_width,
stroke_style.Get()
);
return S_OK;
}
void GraphicsDevice::SetClearColor(const Color& color)
{
clear_color_ = color;
}
HRESULT GraphicsDevice::SetAntialiasMode(bool enabled)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->SetAntialiasMode(
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
);
antialias_ = enabled;
return S_OK;
}
HRESULT GraphicsDevice::SetTextAntialiasMode(TextAntialias mode)
{
if (!render_target_)
return E_UNEXPECTED;
text_antialias_ = mode;
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
switch (text_antialias_)
{
case TextAntialias::Default:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
break;
case TextAntialias::ClearType:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
break;
case TextAntialias::GrayScale:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
break;
case TextAntialias::None:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
break;
default:
break;
}
render_target_->SetTextAntialiasMode(antialias_mode);
return S_OK;
}
HRESULT GraphicsDevice::CreateResources(HWND hwnd)
{
HRESULT hr = S_OK;
if (!render_target_)
{
RECT rc;
::GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
hr = Factory::Instance()->CreateHwndRenderTarget(
render_target_,
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
vsync_enabled_ ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
)
);
if (SUCCEEDED(hr))
{
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
}
if (SUCCEEDED(hr))
{
hr = render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&solid_brush_
);
}
if (SUCCEEDED(hr))
{
hr = Factory::Instance()->CreateTextRenderer(
text_renderer_,
render_target_,
solid_brush_
);
}
}
return hr;
}
void GraphicsDevice::DiscardResources()
{
// FIXME! 应通知 Game 类销毁所有节点的 device resources
fps_text_format_ = nullptr;
fps_text_layout_ = nullptr;
text_renderer_ = nullptr;
solid_brush_ = nullptr;
render_target_ = nullptr;
}
}

View File

@ -37,150 +37,148 @@ namespace easy2d
None // 不启用抗锯齿
};
namespace devices
class GraphicsDevice
: protected Noncopyable
{
class GraphicsDevice
: protected Noncopyable
{
E2D_DECLARE_SINGLETON(GraphicsDevice);
E2D_DECLARE_SINGLETON(GraphicsDevice);
public:
HRESULT Init(HWND hwnd, bool vsync, bool debug);
public:
HRESULT Init(HWND hwnd, bool vsync, bool debug);
// 开始渲染
HRESULT BeginDraw(HWND hwnd);
// 开始渲染
HRESULT BeginDraw(HWND hwnd);
// 结束渲染
HRESULT EndDraw();
// 结束渲染
HRESULT EndDraw();
// 设置清空屏幕的颜色
void SetClearColor(
const Color& color
);
// 设置清空屏幕的颜色
void SetClearColor(
const Color& color
);
// 设置抗锯齿模式
HRESULT SetAntialiasMode(
bool enabled
);
// 设置抗锯齿模式
HRESULT SetAntialiasMode(
bool enabled
);
// 设置文字抗锯齿模式
HRESULT SetTextAntialiasMode(
TextAntialias mode
);
// 设置文字抗锯齿模式
HRESULT SetTextAntialiasMode(
TextAntialias mode
);
HRESULT CreateResources(
HWND hwnd
);
HRESULT CreateResources(
HWND hwnd
);
void DiscardResources();
void DiscardResources();
HRESULT CreateLayer(
cpLayer& layer
);
HRESULT CreateLayer(
cpLayer& layer
);
HRESULT CreateSolidColorBrush(
cpSolidColorBrush& brush
) const;
HRESULT CreateSolidColorBrush(
cpSolidColorBrush& brush
) const;
HRESULT CreateBitmapFromFile(
cpBitmap& bitmap,
String const& file_path
);
HRESULT CreateBitmapFromFile(
cpBitmap& bitmap,
String const& file_path
);
HRESULT CreateBitmapFromResource(
cpBitmap& bitmap,
Resource const& res
);
HRESULT CreateBitmapFromResource(
cpBitmap& bitmap,
Resource const& res
);
HRESULT CreateBitmapRenderTarget(
cpBitmapRenderTarget& brt
);
HRESULT CreateBitmapRenderTarget(
cpBitmapRenderTarget& brt
);
HRESULT SetTransform(
const math::Matrix& matrix
);
HRESULT SetTransform(
const math::Matrix& matrix
);
HRESULT SetOpacity(
float opacity
);
HRESULT SetOpacity(
float opacity
);
HRESULT SetTextStyle(
const Color& color,
bool has_outline,
const Color& outline_color,
float outline_width,
StrokeStyle outline_stroke
);
HRESULT SetTextStyle(
const Color& color,
bool has_outline,
const Color& outline_color,
float outline_width,
StrokeStyle outline_stroke
);
HRESULT DrawGeometry(
cpGeometry const& geometry,
const Color& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);
HRESULT DrawGeometry(
cpGeometry const& geometry,
const Color& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);
HRESULT FillGeometry(
cpGeometry const& geometry,
const Color& fill_color
);
HRESULT FillGeometry(
cpGeometry const& geometry,
const Color& fill_color
);
HRESULT DrawImage(
spImage const& image
);
HRESULT DrawImage(
spImage const& image
);
HRESULT DrawBitmap(
cpBitmap const& bitmap
);
HRESULT DrawBitmap(
cpBitmap const& bitmap
);
HRESULT DrawTextLayout(
cpTextLayout const& text_layout
);
HRESULT DrawTextLayout(
cpTextLayout const& text_layout
);
HRESULT PushClip(
const math::Matrix& clip_matrix,
const Size& clip_size
);
HRESULT PushClip(
const math::Matrix& clip_matrix,
const Size& clip_size
);
HRESULT PopClip();
HRESULT PopClip();
HRESULT PushLayer(
cpLayer const& layer,
LayerProperties const& properties
);
HRESULT PushLayer(
cpLayer const& layer,
LayerProperties const& properties
);
HRESULT PopLayer();
HRESULT PopLayer();
HRESULT GetSize(
Size& size
);
HRESULT GetSize(
Size& size
);
HRESULT Resize(
UINT32 width,
UINT32 height
);
HRESULT Resize(
UINT32 width,
UINT32 height
);
void ClearImageCache();
void ClearImageCache();
protected:
GraphicsDevice();
protected:
GraphicsDevice();
~GraphicsDevice();
~GraphicsDevice();
protected:
bool window_occluded_;
bool vsync_enabled_;
bool antialias_;
TextAntialias text_antialias_;
float opacity_;
cpTextRenderer text_renderer_;
cpSolidColorBrush solid_brush_;
cpHwndRenderTarget render_target_;
D2D1_COLOR_F clear_color_;
cpTextFormat fps_text_format_;
cpTextLayout fps_text_layout_;
std::map<size_t, cpBitmap> bitmap_cache_;
};
protected:
bool window_occluded_;
bool vsync_enabled_;
bool antialias_;
TextAntialias text_antialias_;
float opacity_;
cpTextRenderer text_renderer_;
cpSolidColorBrush solid_brush_;
cpHwndRenderTarget render_target_;
D2D1_COLOR_F clear_color_;
cpTextFormat fps_text_format_;
cpTextLayout fps_text_layout_;
std::map<size_t, cpBitmap> bitmap_cache_;
};
E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics);
}
E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics);
}

View File

@ -81,7 +81,6 @@ namespace easy2d
GetContentScale(&scale_x, &scale_y);
Rect client_rect = LocateWindow(width, height, scale_x, scale_y);
handle = ::CreateWindowEx(
NULL,
@ -197,6 +196,12 @@ namespace easy2d
return scale_y;
}
void WindowImpl::Destroy()
{
if (handle)
::DestroyWindow(handle);
}
namespace
{
void GetContentScale(float* scale_x, float* scale_y)

View File

@ -66,6 +66,8 @@ namespace easy2d
float GetContentScaleY() const;
void Destroy();
protected:
WindowImpl();

View File

@ -50,21 +50,13 @@
#include "base/TextStyle.hpp"
#include "base/noncopyable.hpp"
#include "base/RefCounter.hpp"
#include "base/intrusive/SmartPointer.hpp"
#include "base/intrusive/List.hpp"
#include "base/RefCounter.hpp"
#include "base/ObjectBase.h"
#include "base/Unit.h"
#include "base/Geometry.h"
#include "base/Image.h"
#include "base/Frames.h"
#include "base/Node.h"
#include "base/Scene.h"
#include "base/Sprite.h"
#include "base/Text.h"
#include "base/Canvas.h"
#include "base/GeometryNode.h"
#include "base/Music.h"
#include "base/Task.h"
#include "base/Action.hpp"
@ -73,10 +65,24 @@
#include "base/Animation.h"
#include "base/Delay.h"
#include "base/Transition.h"
#include "base/Debuger.h"
#include "base/TaskManager.h"
#include "base/ActionManager.h"
#include "base/KeyEvent.h"
#include "base/MouseEvent.h"
#include "base/Event.hpp"
#include "base/MouseEvent.hpp"
#include "base/KeyEvent.hpp"
#include "base/EventListener.h"
#include "base/EventDispatcher.h"
#include "base/Unit.h"
#include "base/Geometry.h"
#include "base/Node.h"
#include "base/Scene.h"
#include "base/Sprite.h"
#include "base/Text.h"
#include "base/Canvas.h"
#include "base/GeometryNode.h"
#include "base/Debuger.h"
#include "base/Factory.h"
#include "base/Game.h"

View File

@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "Button.h"
#include "../base/input.h"
#include "../base/MouseEvent.hpp"
#define SAFE_SET(pointer, func, ...) if (pointer) { pointer->##func(__VA_ARGS__); }
@ -171,53 +171,55 @@ namespace easy2d
SAFE_SET(disabled_, SetPivot, pivot_x, pivot_y);
}
bool Button::Dispatch(const MouseEvent & e, bool handled)
void Button::HandleEvent(Event* e)
{
if (!handled && enabled_ && IsVisible() && normal_)
if (e && MouseEvent::Check(e) && !e->has_target)
{
bool contains = normal_->ContainsPoint(e.GetPosition());
if (e.GetType() == MouseEvent::Type::LeftUp && is_selected_ && contains)
MouseEvent* me = static_cast<MouseEvent*>(e);
if (enabled_ && IsVisible() && normal_)
{
if (callback_)
bool contains = normal_->ContainsPoint(Point{ me->x, me->y });
if (me->type == MouseEvent::Up && is_selected_ && contains)
{
callback_();
if (callback_)
{
callback_();
}
is_selected_ = false;
SetStatus(Status::Normal);
me->has_target = true;
}
is_selected_ = false;
SetStatus(Status::Normal);
return true;
}
else if (e.GetType() == MouseEvent::Type::LeftDown)
{
is_selected_ = contains;
SetStatus(contains ? Status::Selected : Status::Normal);
else if (me->type == MouseEvent::Down)
{
is_selected_ = contains;
SetStatus(contains ? Status::Selected : Status::Normal);
if (contains)
return true;
}
else if (e.GetType() == MouseEvent::Type::LeftUp)
{
is_selected_ = false;
}
else if (e.GetType() == MouseEvent::Type::Move && is_selected_ && contains)
{
SetStatus(Status::Selected);
return true;
}
else
{
if (!e.IsLButtonDown() && is_selected_)
me->has_target = contains;
}
else if (me->type == MouseEvent::Up)
{
is_selected_ = false;
}
else if (me->type == MouseEvent::Move && is_selected_ && contains)
{
SetStatus(Status::Selected);
me->has_target = true;
}
else
{
if (!me->button_down && is_selected_)
{
is_selected_ = false;
}
SetStatus(contains ? Status::Mouseover : Status::Normal);
SetStatus(contains ? Status::Mouseover : Status::Normal);
if (contains)
return true;
me->has_target = contains;
}
}
}
return Node::Dispatch(e, handled);
Node::HandleEvent(e);
}
void Button::SetStatus(Status status)

View File

@ -102,6 +102,8 @@ namespace easy2d
float pivot_y
) override;
virtual void HandleEvent(Event* e) override;
private:
// 按钮状态枚举
enum class Status { Normal, Mouseover, Selected };
@ -114,12 +116,6 @@ namespace easy2d
// 刷新按钮显示
virtual void UpdateVisible();
// 分发鼠标消息
virtual bool Dispatch(
const MouseEvent& e,
bool handled
) override;
private:
spNode normal_;
spNode mouseover_;

View File

@ -32,6 +32,9 @@
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Delay.h" />
<ClInclude Include="..\..\core\base\Event.hpp" />
<ClInclude Include="..\..\core\base\EventDispatcher.h" />
<ClInclude Include="..\..\core\base\EventListener.h" />
<ClInclude Include="..\..\core\base\Factory.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Frames.h" />
@ -42,11 +45,11 @@
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\KeyEvent.hpp" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />
<ClInclude Include="..\..\core\base\modules.h" />
<ClInclude Include="..\..\core\base\MouseEvent.h" />
<ClInclude Include="..\..\core\base\MouseEvent.hpp" />
<ClInclude Include="..\..\core\base\Music.h" />
<ClInclude Include="..\..\core\base\Node.h" />
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
@ -96,6 +99,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Delay.cpp" />
<ClCompile Include="..\..\core\base\EventDispatcher.cpp" />
<ClCompile Include="..\..\core\base\EventListener.cpp" />
<ClCompile Include="..\..\core\base\Factory.cpp" />
<ClCompile Include="..\..\core\base\Frames.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
@ -103,10 +108,8 @@
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" />
<ClCompile Include="..\..\core\base\logs.cpp" />
<ClCompile Include="..\..\core\base\modules.cpp" />
<ClCompile Include="..\..\core\base\MouseEvent.cpp" />
<ClCompile Include="..\..\core\base\Music.cpp" />
<ClCompile Include="..\..\core\base\Node.cpp" />
<ClCompile Include="..\..\core\base\ObjectBase.cpp" />

View File

@ -71,12 +71,6 @@
<ClInclude Include="..\..\core\base\window.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\math\Matrix.hpp">
<Filter>math</Filter>
</ClInclude>
@ -197,6 +191,21 @@
<ClInclude Include="..\..\core\base\Factory.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventDispatcher.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Event.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventListener.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -276,12 +285,6 @@
<ClCompile Include="..\..\core\base\window.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\KeyEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\MouseEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\math\rand.cpp">
<Filter>math</Filter>
</ClCompile>
@ -348,5 +351,11 @@
<ClCompile Include="..\..\core\base\Factory.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventDispatcher.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventListener.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -32,6 +32,9 @@
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Delay.h" />
<ClInclude Include="..\..\core\base\Event.hpp" />
<ClInclude Include="..\..\core\base\EventDispatcher.h" />
<ClInclude Include="..\..\core\base\EventListener.h" />
<ClInclude Include="..\..\core\base\Factory.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Frames.h" />
@ -42,11 +45,11 @@
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\KeyEvent.hpp" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />
<ClInclude Include="..\..\core\base\modules.h" />
<ClInclude Include="..\..\core\base\MouseEvent.h" />
<ClInclude Include="..\..\core\base\MouseEvent.hpp" />
<ClInclude Include="..\..\core\base\Music.h" />
<ClInclude Include="..\..\core\base\Node.h" />
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
@ -96,6 +99,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Delay.cpp" />
<ClCompile Include="..\..\core\base\EventDispatcher.cpp" />
<ClCompile Include="..\..\core\base\EventListener.cpp" />
<ClCompile Include="..\..\core\base\Factory.cpp" />
<ClCompile Include="..\..\core\base\Frames.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
@ -103,10 +108,8 @@
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" />
<ClCompile Include="..\..\core\base\logs.cpp" />
<ClCompile Include="..\..\core\base\modules.cpp" />
<ClCompile Include="..\..\core\base\MouseEvent.cpp" />
<ClCompile Include="..\..\core\base\Music.cpp" />
<ClCompile Include="..\..\core\base\Node.cpp" />
<ClCompile Include="..\..\core\base\ObjectBase.cpp" />

View File

@ -71,12 +71,6 @@
<ClInclude Include="..\..\core\base\window.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\math\Matrix.hpp">
<Filter>math</Filter>
</ClInclude>
@ -197,6 +191,21 @@
<ClInclude Include="..\..\core\base\Factory.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventDispatcher.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Event.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventListener.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -276,12 +285,6 @@
<ClCompile Include="..\..\core\base\window.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\KeyEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\MouseEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\math\rand.cpp">
<Filter>math</Filter>
</ClCompile>
@ -348,5 +351,11 @@
<ClCompile Include="..\..\core\base\Factory.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventDispatcher.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventListener.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -32,6 +32,9 @@
<ClInclude Include="..\..\core\base\d2dres.hpp" />
<ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Delay.h" />
<ClInclude Include="..\..\core\base\Event.hpp" />
<ClInclude Include="..\..\core\base\EventDispatcher.h" />
<ClInclude Include="..\..\core\base\EventListener.h" />
<ClInclude Include="..\..\core\base\Factory.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Frames.h" />
@ -42,11 +45,11 @@
<ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" />
<ClInclude Include="..\..\core\base\intrusive\SmartPointer.hpp" />
<ClInclude Include="..\..\core\base\KeyEvent.h" />
<ClInclude Include="..\..\core\base\KeyEvent.hpp" />
<ClInclude Include="..\..\core\base\logs.h" />
<ClInclude Include="..\..\core\base\macros.h" />
<ClInclude Include="..\..\core\base\modules.h" />
<ClInclude Include="..\..\core\base\MouseEvent.h" />
<ClInclude Include="..\..\core\base\MouseEvent.hpp" />
<ClInclude Include="..\..\core\base\Music.h" />
<ClInclude Include="..\..\core\base\Node.h" />
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
@ -96,6 +99,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Delay.cpp" />
<ClCompile Include="..\..\core\base\EventDispatcher.cpp" />
<ClCompile Include="..\..\core\base\EventListener.cpp" />
<ClCompile Include="..\..\core\base\Factory.cpp" />
<ClCompile Include="..\..\core\base\Frames.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
@ -103,10 +108,8 @@
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" />
<ClCompile Include="..\..\core\base\logs.cpp" />
<ClCompile Include="..\..\core\base\modules.cpp" />
<ClCompile Include="..\..\core\base\MouseEvent.cpp" />
<ClCompile Include="..\..\core\base\Music.cpp" />
<ClCompile Include="..\..\core\base\Node.cpp" />
<ClCompile Include="..\..\core\base\ObjectBase.cpp" />

View File

@ -71,12 +71,6 @@
<ClInclude Include="..\..\core\base\window.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\math\Matrix.hpp">
<Filter>math</Filter>
</ClInclude>
@ -197,6 +191,21 @@
<ClInclude Include="..\..\core\base\Factory.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventDispatcher.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Event.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\KeyEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\MouseEvent.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\EventListener.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -276,12 +285,6 @@
<ClCompile Include="..\..\core\base\window.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\KeyEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\MouseEvent.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\math\rand.cpp">
<Filter>math</Filter>
</ClCompile>
@ -348,5 +351,11 @@
<ClCompile Include="..\..\core\base\Factory.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventDispatcher.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\EventListener.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
</Project>