add TimeScale

refactoring

refactoring
This commit is contained in:
Haibo 2018-11-21 19:24:18 +08:00 committed by Nomango
parent b9ac2c3934
commit bf25bd1d41
27 changed files with 561 additions and 532 deletions

View File

@ -96,7 +96,7 @@ namespace easy2d
cache_expired_ = true;
}
void Canvas::OnDraw()
void Canvas::OnRender()
{
if (cache_expired_)
{

View File

@ -218,7 +218,7 @@ namespace easy2d
// 导出为图片
spImage ExportToImage() const;
virtual void OnDraw() override;
virtual void OnRender() override;
protected:
cpBitmap const& GetBitmap() const;

View File

@ -68,7 +68,7 @@ namespace easy2d
texts_.clear();
}
void DebugerNode::OnUpdate(Duration const & dt)
void DebugerNode::Update(Duration const & dt)
{
try
{

View File

@ -39,7 +39,7 @@ namespace easy2d
void ClearDebugText();
void OnUpdate(Duration const& dt) override;
void Update(Duration const& dt) override;
protected:
spText debug_text_;

View File

@ -26,7 +26,6 @@
namespace easy2d
{
FactoryImpl::FactoryImpl()
: initialized_(false)
{
}
@ -35,91 +34,90 @@ namespace easy2d
E2D_LOG("Destroying device independent resources");
}
void FactoryImpl::Init(bool debug)
HRESULT FactoryImpl::Init(bool debug)
{
if (initialized_)
return;
E2D_LOG("Creating device independent resources");
D2D1_FACTORY_OPTIONS fact_options;
fact_options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE;
ThrowIfFailed(
modules::DirectX().D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory),
&fact_options,
reinterpret_cast<void**>(&factory)
)
HRESULT hr = modules::DirectX().D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory),
&fact_options,
reinterpret_cast<void**>(&factory_)
);
ThrowIfFailed(
if (SUCCEEDED(hr))
{
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
reinterpret_cast<void**>(&imaging_factory)
)
);
reinterpret_cast<void**>(&imaging_factory_)
);
}
ThrowIfFailed(
if (SUCCEEDED(hr))
{
modules::DirectX().DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&write_factory)
)
);
reinterpret_cast<IUnknown**>(&write_factory_)
);
}
auto stroke_style = D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_LINE_JOIN_MITER,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f
);
if (SUCCEEDED(hr))
{
auto stroke_style = D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_LINE_JOIN_MITER,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f
);
ThrowIfFailed(
factory->CreateStrokeStyle(
hr = factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&miter_stroke_style
)
);
&miter_stroke_style_
);
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
ThrowIfFailed(
factory->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&bevel_stroke_style
)
);
if (SUCCEEDED(hr))
{
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
hr = factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&bevel_stroke_style_
);
}
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
ThrowIfFailed(
factory->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&round_stroke_style
)
);
initialized_ = true;
if (SUCCEEDED(hr))
{
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
hr = factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&round_stroke_style_
);
}
}
return hr;
}
HRESULT FactoryImpl::CreateHwndRenderTarget(cpHwndRenderTarget & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpHwndRenderTarget hwnd_render_target_tmp;
HRESULT hr = factory->CreateHwndRenderTarget(
HRESULT hr = factory_->CreateHwndRenderTarget(
properties,
hwnd_rt_properties,
&hwnd_render_target_tmp
@ -136,13 +134,13 @@ namespace easy2d
cpSolidColorBrush const& brush
)
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpTextRenderer text_renderer_tmp;
HRESULT hr = ITextRenderer::Create(
&text_renderer_tmp,
factory.Get(),
factory_.Get(),
render_target.Get(),
brush.Get()
);
@ -154,7 +152,7 @@ namespace easy2d
HRESULT FactoryImpl::CreateBitmapFromFile(cpBitmap & bitmap, cpRenderTarget const & rt, String const & file_path)
{
if (imaging_factory == nullptr)
if (imaging_factory_ == nullptr)
{
return E_UNEXPECTED;
}
@ -167,7 +165,7 @@ namespace easy2d
SmartPointer<IWICFormatConverter> converter;
SmartPointer<ID2D1Bitmap> bitmap_tmp;
HRESULT hr = imaging_factory->CreateDecoderFromFilename(
HRESULT hr = imaging_factory_->CreateDecoderFromFilename(
file_path.c_str(),
nullptr,
GENERIC_READ,
@ -182,7 +180,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = imaging_factory->CreateFormatConverter(&converter);
hr = imaging_factory_->CreateFormatConverter(&converter);
}
if (SUCCEEDED(hr))
@ -215,7 +213,7 @@ namespace easy2d
HRESULT FactoryImpl::CreateBitmapFromResource(cpBitmap & bitmap, cpRenderTarget const & rt, Resource const & res)
{
if (imaging_factory == nullptr)
if (imaging_factory_ == nullptr)
{
return E_UNEXPECTED;
}
@ -234,7 +232,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = imaging_factory->CreateStream(&stream);
hr = imaging_factory_->CreateStream(&stream);
}
if (SUCCEEDED(hr))
@ -247,7 +245,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = imaging_factory->CreateDecoderFromStream(
hr = imaging_factory_->CreateDecoderFromStream(
stream.Get(),
nullptr,
WICDecodeMetadataCacheOnLoad,
@ -262,7 +260,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = imaging_factory->CreateFormatConverter(&converter);
hr = imaging_factory_->CreateFormatConverter(&converter);
}
if (SUCCEEDED(hr))
@ -297,11 +295,11 @@ namespace easy2d
HRESULT FactoryImpl::CreateRectangleGeometry(cpRectangleGeometry & geo, Rect const& rect) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpRectangleGeometry rectangle;
HRESULT hr = factory->CreateRectangleGeometry(
HRESULT hr = factory_->CreateRectangleGeometry(
rect,
&rectangle
);
@ -313,11 +311,11 @@ namespace easy2d
HRESULT FactoryImpl::CreateRoundedRectangleGeometry(cpRoundedRectangleGeometry & geo, Rect const & rect, float radius_x, float radius_y) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpRoundedRectangleGeometry rounded_rect;
HRESULT hr = factory->CreateRoundedRectangleGeometry(
HRESULT hr = factory_->CreateRoundedRectangleGeometry(
D2D1::RoundedRect(
rect,
radius_x,
@ -333,11 +331,11 @@ namespace easy2d
HRESULT FactoryImpl::CreateEllipseGeometry(cpEllipseGeometry & geo, Point const & center, float radius_x, float radius_y) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpEllipseGeometry ellipse;
HRESULT hr = factory->CreateEllipseGeometry(
HRESULT hr = factory_->CreateEllipseGeometry(
D2D1::Ellipse(
center,
radius_x,
@ -357,11 +355,11 @@ namespace easy2d
cpGeometry const& geo
) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
cpTransformedGeometry transformed_tmp;
HRESULT hr = factory->CreateTransformedGeometry(
HRESULT hr = factory_->CreateTransformedGeometry(
geo.Get(),
ConvertToD2DMatrix(matrix),
&transformed_tmp
@ -376,19 +374,19 @@ namespace easy2d
HRESULT FactoryImpl::CreatePathGeometry(cpPathGeometry & geometry) const
{
if (!factory)
if (!factory_)
return E_UNEXPECTED;
return factory->CreatePathGeometry(&geometry);
return factory_->CreatePathGeometry(&geometry);
}
HRESULT FactoryImpl::CreateTextFormat(cpTextFormat & text_format, Font const & font, TextStyle const & text_style) const
{
if (!write_factory)
if (!write_factory_)
return E_UNEXPECTED;
cpTextFormat text_format_tmp;
HRESULT hr = write_factory->CreateTextFormat(
HRESULT hr = write_factory_->CreateTextFormat(
font.family.c_str(),
nullptr,
DWRITE_FONT_WEIGHT(font.weight),
@ -422,7 +420,7 @@ namespace easy2d
HRESULT FactoryImpl::CreateTextLayout(cpTextLayout & text_layout, Size& layout_size, String const & text, cpTextFormat const& text_format, TextStyle const & text_style) const
{
if (!write_factory)
if (!write_factory_)
return E_UNEXPECTED;
text_layout = nullptr;
@ -433,7 +431,7 @@ namespace easy2d
if (text_style.wrap)
{
hr = write_factory->CreateTextLayout(
hr = write_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -444,7 +442,7 @@ namespace easy2d
}
else
{
hr = write_factory->CreateTextLayout(
hr = write_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -459,7 +457,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
text_layout_tmp = nullptr;
hr = write_factory->CreateTextLayout(
hr = write_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -503,16 +501,16 @@ namespace easy2d
switch (stroke)
{
case StrokeStyle::Miter:
return miter_stroke_style;
return miter_stroke_style_;
break;
case StrokeStyle::Bevel:
return bevel_stroke_style;
return bevel_stroke_style_;
break;
case StrokeStyle::Round:
return round_stroke_style;
return round_stroke_style_;
break;
}
return miter_stroke_style;
return miter_stroke_style_;
}
}

View File

@ -35,7 +35,7 @@ namespace easy2d
E2D_DECLARE_SINGLETON(FactoryImpl);
public:
void Init(bool debug);
HRESULT Init(bool debug);
HRESULT CreateHwndRenderTarget(
cpHwndRenderTarget& hwnd_render_target,
@ -114,13 +114,12 @@ namespace easy2d
~FactoryImpl();
protected:
bool initialized_;
cpFactory factory;
cpImagingFactory imaging_factory;
cpWriteFactory write_factory;
cpStrokeStyle miter_stroke_style;
cpStrokeStyle bevel_stroke_style;
cpStrokeStyle round_stroke_style;
cpFactory factory_;
cpImagingFactory imaging_factory_;
cpWriteFactory write_factory_;
cpStrokeStyle miter_stroke_style_;
cpStrokeStyle bevel_stroke_style_;
cpStrokeStyle round_stroke_style_;
};
E2D_DECLARE_SINGLETON_TYPE(FactoryImpl, Factory);

View File

@ -20,8 +20,6 @@
#include "Game.h"
#include "logs.h"
#include "input.h"
#include "audio.h"
#include "modules.h"
#include "Factory.h"
#include "Scene.h"
@ -35,13 +33,17 @@
namespace easy2d
{
Game::Game()
: curr_scene_(nullptr)
: initialized_(false)
, window_inactived_(false)
, curr_scene_(nullptr)
, next_scene_(nullptr)
, transition_(nullptr)
, window_(nullptr)
, graphics_(nullptr)
, input_(nullptr)
, audio_(nullptr)
, debug_enabled_(false)
, initialized_(false)
, hwnd_(nullptr)
, window_inactived_(false)
, time_scale_(1.f)
{
::CoInitialize(nullptr);
}
@ -64,72 +66,90 @@ namespace easy2d
debug_enabled_ = options.debug;
Window::Instance()->Init(
options.title,
options.width,
options.height,
options.icon,
Game::WndProc,
debug_enabled_
window_ = Window::Instance();
graphics_ = devices::Graphics::Instance();
input_ = devices::Input::Instance();
audio_ = devices::Audio::Instance();
ThrowIfFailed(
Factory::Instance()->Init(debug_enabled_)
);
const auto window = Window::Instance();
hwnd_ = window->GetHandle();
ThrowIfFailed(
window_->Init(
options.title,
options.width,
options.height,
options.icon,
Game::WndProc,
debug_enabled_
)
);
::SetWindowLongW(hwnd_, GWLP_USERDATA, PtrToUlong(this));
HWND hwnd = window_->GetHandle();
Factory::Instance()->Init(debug_enabled_);
devices::Graphics::Instance()->Init(hwnd_, options.graphics_options, debug_enabled_);
devices::Input::Instance()->Init(hwnd_, window->GetContentScaleX(), window->GetContentScaleY(), debug_enabled_);
devices::Audio::Instance()->Init(debug_enabled_);
ThrowIfFailed(
graphics_->Init(
hwnd,
options.vsync,
debug_enabled_
)
);
ThrowIfFailed(
input_->Init(
hwnd,
window_->GetContentScaleX(),
window_->GetContentScaleY(),
debug_enabled_
)
);
ThrowIfFailed(
audio_->Init(debug_enabled_)
);
// disable imm
::ImmAssociateContext(hwnd_, nullptr);
::ImmAssociateContext(hwnd, nullptr);
// show console if debug mode enabled
HWND console = ::GetConsoleWindow();
if (debug_enabled_)
if (debug_enabled_ && !console)
{
if (console == nullptr)
if (::AllocConsole())
{
if (::AllocConsole())
{
console = ::GetConsoleWindow();
FILE * stdoutStream, *stdinStream, *stderrStream;
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
freopen_s(&stdinStream, "conin$", "r+t", stdin);
freopen_s(&stderrStream, "conout$", "w+t", stderr);
}
console = ::GetConsoleWindow();
FILE * stdoutStream, *stdinStream, *stderrStream;
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
freopen_s(&stdinStream, "conin$", "r+t", stdin);
freopen_s(&stderrStream, "conout$", "w+t", stderr);
}
}
else
else if (!debug_enabled_ && console)
{
if (console)
{
::ShowWindow(console, SW_HIDE);
}
::ShowWindow(console, SW_HIDE);
}
// disable the close button of console
if (console)
{
// disable the close button of console
HMENU hmenu = ::GetSystemMenu(console, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
// use Game instance in message loop
::SetWindowLongW(hwnd, GWLP_USERDATA, PtrToUlong(this));
initialized_ = true;
}
void Game::Run()
{
if (next_scene_)
{
next_scene_->OnEnter();
curr_scene_ = next_scene_;
next_scene_ = nullptr;
}
if (!initialized_)
return;
::ShowWindow(hwnd_, SW_SHOWNORMAL);
::UpdateWindow(hwnd_);
::ShowWindow(window_->GetHandle(), SW_SHOWNORMAL);
::UpdateWindow(window_->GetHandle());
MSG msg = {};
while (::GetMessageW(&msg, nullptr, 0, 0))
@ -141,7 +161,8 @@ namespace easy2d
void Game::Quit()
{
::DestroyWindow(hwnd_);
if (window_)
::DestroyWindow(window_->GetHandle());
}
bool Game::EnterScene(spScene const & scene)
@ -182,15 +203,20 @@ namespace easy2d
return curr_scene_;
}
void Game::SetTimeScale(float scale)
{
time_scale_ = scale;
}
void Game::Update()
{
static auto last = time::Now();
const auto now = time::Now();
const auto dt = now - last;
const auto dt = (now - last) * time_scale_;
last = now;
devices::Input::Instance()->Update();
input_->Update();
if (curr_scene_)
curr_scene_->Update(dt);
@ -228,7 +254,10 @@ namespace easy2d
void Game::Render()
{
auto graphics = devices::Graphics::Instance();
graphics->BeginDraw(hwnd_);
ThrowIfFailed(
graphics->BeginDraw(window_->GetHandle())
);
if (transition_)
{
@ -236,7 +265,7 @@ namespace easy2d
}
else if (curr_scene_)
{
curr_scene_->Visit();
curr_scene_->Render();
}
if (debug_enabled_)
@ -254,13 +283,15 @@ namespace easy2d
next_scene_->DrawBorder();
}
Debuger::Instance()->Visit();
Debuger::Instance()->Render();
}
graphics->EndDraw();
ThrowIfFailed(
graphics->EndDraw()
);
if (!window_inactived_)
::InvalidateRect(hwnd_, NULL, FALSE);
::InvalidateRect(window_->GetHandle(), NULL, FALSE);
}
void Game::Dispatch(MouseEvent const & e)

View File

@ -20,9 +20,11 @@
#pragma once
#include "base.hpp"
#include "window.h"
#include "time.h"
#include "window.h"
#include "render.h"
#include "input.h"
#include "audio.h"
#include "KeyEvent.h"
#include "MouseEvent.h"
@ -34,17 +36,16 @@ namespace easy2d
int width; // 宽度
int height; // 高度
LPCWSTR icon; // 图标
bool vsync; // ´¹Ö±Í¬²½
bool debug; // 调试模式
GraphicsOptions graphics_options; // ͼÐÎäÖȾѡÏî
Options()
: title(L"Easy2D Game")
, width(640)
, height(480)
, icon(nullptr)
, vsync(true)
, debug(false)
, graphics_options()
{}
};
@ -93,6 +94,9 @@ namespace easy2d
// 获取当前场景
spScene const& GetCurrentScene();
// ÉèÖñäËÙ
void SetTimeScale(float scale);
private:
void Render();
@ -112,9 +116,14 @@ namespace easy2d
bool initialized_;
bool debug_enabled_;
bool window_inactived_;
HWND hwnd_;
float time_scale_;
spScene curr_scene_;
spScene next_scene_;
spTransition transition_;
WindowImpl* window_;
devices::GraphicsDevice* graphics_;
devices::InputDevice* input_;
devices::AudioDevice* audio_;
};
}

View File

@ -66,7 +66,7 @@ namespace easy2d
outline_join_ = outline_join;
}
void GeometryNode::OnDraw()
void GeometryNode::OnRender()
{
if (geometry_ && geometry_->geo_)
{
@ -87,12 +87,4 @@ namespace easy2d
}
}
void GeometryNode::DrawBorder()
{
if (visible_)
{
DrawChildrenBorder();
}
}
}

View File

@ -77,10 +77,7 @@ namespace easy2d
// ťńČĄĎßĚőĎཝŃůĘ˝
StrokeStyle SetOutlineJoinStyle() const { return outline_join_; }
virtual void OnDraw() override;
protected:
virtual void DrawBorder() override;
virtual void OnRender() override;
protected:
Color fill_color_;

View File

@ -27,8 +27,7 @@ namespace easy2d
namespace devices
{
InputDevice::InputDevice()
: initialized_(false)
, hwnd_(nullptr)
: hwnd_(nullptr)
, scale_x_(1.f)
, scale_y_(1.f)
{
@ -41,18 +40,15 @@ namespace easy2d
E2D_LOG("Destroying input device");
}
void InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
HRESULT InputDevice::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
{
if (initialized_)
return;
E2D_LOG("Initing input device");
hwnd_ = hwnd;
scale_x_ = scale_x;
scale_y_ = scale_y;
initialized_ = true;
return S_OK;
}
void InputDevice::Update()

View File

@ -32,7 +32,7 @@ namespace easy2d
E2D_DECLARE_SINGLETON(InputDevice);
public:
void Init(HWND hwnd, float scale_x, float scale_y, bool debug);
HRESULT Init(HWND hwnd, float scale_x, float scale_y, bool debug);
// 检测键盘某按键是否正被按下
bool IsDown(
@ -71,7 +71,6 @@ namespace easy2d
~InputDevice();
protected:
bool initialized_;
HWND hwnd_;
float scale_x_;
float scale_y_;

View File

@ -32,6 +32,7 @@ namespace easy2d
{
float default_pivot_x = 0.f;
float default_pivot_y = 0.f;
bool border_enabled = false;
}
void Node::SetDefaultPivot(float pivot_x, float pivot_y)
@ -40,12 +41,23 @@ namespace easy2d
default_pivot_y = pivot_y;
}
void easy2d::Node::EnableBorder()
{
border_enabled = true;
}
void easy2d::Node::DisableBorder()
{
border_enabled = false;
}
Node::Node()
: visible_(true)
: inited_(false)
, visible_(true)
, dirty_sort_(false)
, parent_(nullptr)
, hash_name_(0)
, dirty_sort_(false)
, order_(0)
, z_order_(0)
, opacity_(1.f)
, display_opacity_(1.f)
, children_()
@ -57,11 +69,36 @@ namespace easy2d
{
}
Node::~Node()
void Node::Init()
{
inited_ = true;
}
void Node::Visit()
void Node::OnRender()
{
// normal node renders nothing
}
void Node::Update(Duration const & dt)
{
if (!inited_)
{
Init();
}
UpdateActions(this, dt);
UpdateTasks(dt);
if (!children_.IsEmpty())
{
for (auto child = children_.First(); child; child = child->NextItem())
{
child->Update(dt);
}
}
}
void Node::Render()
{
if (!visible_)
return;
@ -74,26 +111,21 @@ namespace easy2d
{
graphics->SetTransform(final_matrix_);
graphics->SetOpacity(display_opacity_);
OnDraw();
OnRender();
}
else
{
if (dirty_sort_)
{
children_.Sort(
[](spNode const& n1, spNode const& n2) { return n1->GetOrder() < n2->GetOrder(); }
);
dirty_sort_ = false;
}
SortChildren();
// render children those are less than 0 in Z-Order
spNode child = children_.First();
for (spNode next; child; child = next)
{
next = child->NextItem();
if (child->GetOrder() < 0)
if (child->GetZOrder() < 0)
{
child->Visit();
child->Render();
}
else
{
@ -103,49 +135,13 @@ namespace easy2d
graphics->SetTransform(final_matrix_);
graphics->SetOpacity(display_opacity_);
OnDraw();
OnRender();
for (spNode next; child; child = next)
{
next = child->NextItem();
child->Visit();
}
}
}
void Node::Update(Duration const& dt)
{
if (children_.IsEmpty())
{
OnUpdate(dt);
UpdateActions(this, dt);
UpdateTasks(dt);
}
else
{
// 访问 Order 小于零的节点
spNode child = children_.First();
for (spNode next; child; child = next)
{
if (child->GetOrder() < 0)
{
next = child->NextItem();
child->Update(dt);
}
else
{
break;
}
}
OnUpdate(dt);
UpdateActions(this, dt);
UpdateTasks(dt);
for (spNode next; child; child = next)
{
next = child->NextItem();
child->Update(dt);
child->Render();
}
}
}
@ -159,15 +155,22 @@ namespace easy2d
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f);
}
DrawChildrenBorder();
for (auto child = children_.First(); child; child = child->NextItem())
{
child->DrawBorder();
}
}
}
void Node::DrawChildrenBorder()
void Node::SortChildren()
{
for (auto child = children_.First(); child; child = child->NextItem())
if (dirty_sort_)
{
child->DrawBorder();
children_.Sort(
[](spNode const& n1, spNode const& n2) { return n1->GetZOrder() < n2->GetZOrder(); }
);
dirty_sort_ = false;
}
}
@ -200,12 +203,17 @@ namespace easy2d
final_matrix_ = final_matrix_ * parent_->initial_matrix_;
}
UpdateBorder();
// update children's transform
for (auto child = children_.First(); child; child = child->NextItem())
{
child->dirty_transform_ = true;
}
// update border
if (border_enabled)
{
UpdateBorder();
}
}
void Node::UpdateBorder()
@ -213,22 +221,24 @@ namespace easy2d
cpRectangleGeometry rect;
cpTransformedGeometry transformed;
ThrowIfFailed(
Factory::Instance()->CreateRectangleGeometry(
rect,
Rect(Point{}, size_)
)
HRESULT hr = Factory::Instance()->CreateRectangleGeometry(
rect,
Rect(Point{}, size_)
);
ThrowIfFailed(
Factory::Instance()->CreateTransformedGeometry(
if (SUCCEEDED(hr))
{
hr = Factory::Instance()->CreateTransformedGeometry(
transformed,
final_matrix_,
rect
)
);
);
}
border_ = transformed;
if (SUCCEEDED(hr))
{
border_ = transformed;
}
}
bool Node::Dispatch(const MouseEvent & e, bool handled)
@ -281,12 +291,12 @@ namespace easy2d
}
}
void Node::SetOrder(int order)
void Node::SetZOrder(int order)
{
if (order_ == order)
if (z_order_ == order)
return;
order_ = order;
z_order_ = order;
if (parent_)
{
parent_->dirty_sort_ = true;
@ -358,7 +368,21 @@ namespace easy2d
border_color_ = color;
}
void Node::AddChild(spNode const& child, int order)
void Node::SetVisible(bool val)
{
visible_ = val;
}
void Node::SetName(String const& name)
{
if (name_ != name)
{
name_ = name;
hash_name_ = std::hash<String>{}(name);
}
}
void Node::AddChild(spNode const& child, int z_order)
{
if (!child)
logs::Warningln("Node::AddChild failed, child is nullptr");
@ -366,28 +390,31 @@ namespace easy2d
if (child)
{
#ifdef E2D_DEBUG
if (child->parent_)
logs::Errorln("The node to be added already has a parent");
for (Node* parent = parent_; parent; parent = parent->parent_)
if (parent == child)
logs::Errorln("A node cannot be its own parent");
#endif // E2D_DEBUG
children_.PushBack(Node::ItemType(child));
child->parent_ = this;
child->dirty_transform_ = true;
child->SetOrder(order);
child->SetZOrder(z_order);
child->UpdateOpacity();
dirty_sort_ = true;
}
}
void Node::AddChild(const Nodes& nodes, int order)
void Node::AddChild(const Nodes& nodes, int z_order)
{
for (const auto& node : nodes)
{
this->AddChild(node, order);
this->AddChild(node, z_order);
}
}
@ -486,30 +513,22 @@ namespace easy2d
UpdateTransform();
BOOL ret = 0;
cpRectangleGeometry border;
ThrowIfFailed(
border_->FillContainsPoint(
point,
D2D1::Matrix3x2F::Identity(),
&ret
Factory::Instance()->CreateRectangleGeometry(
border,
Rect(Point{}, size_)
)
);
BOOL ret = 0;
// no matter it failed or not
border->FillContainsPoint(
point,
ConvertToD2DMatrix(final_matrix_),
&ret
);
return !!ret;
}
void Node::SetVisible(bool val)
{
visible_ = val;
}
void Node::SetName(String const& name)
{
if (name_ != name)
{
// 保存节点名
name_ = name;
// 保存节点 Hash 名
hash_name_ = std::hash<String>{}(name);
}
}
}
}

View File

@ -50,13 +50,14 @@ namespace easy2d
public:
Node();
virtual ~Node();
// 渲染节点
virtual void OnDraw() {}
// 初始化节点
virtual void Init();
// 更新节点
virtual void OnUpdate(Duration const& dt) {}
virtual void Update(Duration const& dt);
// 渲染节点
virtual void OnRender();
// 获取显示状态
bool IsVisible() const { return visible_; }
@ -67,8 +68,8 @@ namespace easy2d
// 获取名称的 Hash 值
size_t GetHashName() const { return hash_name_; }
// 获取绘图顺序
int GetOrder() const { return order_; }
// 获取 Z 轴顺序
int GetZOrder() const { return z_order_; }
// 获取宽度
virtual float GetWidth() const { return size_.width * transform_.scale.x; }
@ -157,9 +158,9 @@ namespace easy2d
float opacity
);
// 设置绘图顺序
// 设置 Z 轴顺序
// 默认为 0
void SetOrder(
void SetZOrder(
int order
);
@ -176,13 +177,13 @@ namespace easy2d
// 添加子节点
void AddChild(
spNode const& child,
int order = 0 /* 渲染顺序 */
int z_order = 0 /* Z 轴顺序 */
);
// 添加多个子节点
void AddChild(
const Nodes& nodes, /* 节点数组 */
int order = 0 /* 渲染顺序 */
int z_order = 0 /* Z 轴顺序 */
);
// 获取所有名称相同的子节点
@ -220,8 +221,24 @@ namespace easy2d
float pivot_y
);
// 启用边框自动生成
static void EnableBorder();
// 禁用边框自动生成
static void DisableBorder();
protected:
virtual void Visit();
void Render();
void DrawBorder();
void SortChildren();
void UpdateBorder();
void UpdateTransform();
void UpdateOpacity();
virtual bool Dispatch(
const MouseEvent& e,
@ -234,26 +251,14 @@ namespace easy2d
);
protected:
virtual void Update(Duration const& dt);
virtual void DrawBorder();
void DrawChildrenBorder();
void UpdateBorder();
void UpdateTransform();
void UpdateOpacity();
protected:
String name_;
size_t hash_name_;
float display_opacity_;
float opacity_;
int order_;
bool inited_;
bool visible_;
bool dirty_sort_;
int z_order_;
float opacity_;
float display_opacity_;
String name_;
size_t hash_name_;
Node* parent_;
Color border_color_;
Children children_;

View File

@ -127,7 +127,7 @@ namespace easy2d
return image_;
}
void Sprite::OnDraw()
void Sprite::OnRender()
{
if (image_)
{

View File

@ -79,7 +79,7 @@ namespace easy2d
spImage const& GetImage() const;
// äÖȾ¾«Áé
virtual void OnDraw() override;
virtual void OnRender() override;
protected:
spImage image_;

View File

@ -291,7 +291,7 @@ namespace easy2d
style_.outline_stroke = outline_stroke;
}
void Text::OnDraw()
void Text::OnRender()
{
if (text_layout_)
{

View File

@ -199,7 +199,7 @@ namespace easy2d
TextStyle const& style
);
virtual void OnDraw() override;
virtual void OnRender() override;
protected:
void UpdateLayout();

View File

@ -111,7 +111,7 @@ namespace easy2d
);
graphics->PushLayer(out_layer_, out_layer_prop_);
out_scene_->Visit();
out_scene_->Render();
graphics->PopLayer();
graphics->PopClip();
@ -125,7 +125,7 @@ namespace easy2d
);
graphics->PushLayer(in_layer_, in_layer_prop_);
in_scene_->Visit();
in_scene_->Render();
graphics->PopLayer();
graphics->PopClip();

View File

@ -164,7 +164,6 @@ namespace easy2d
AudioDevice::AudioDevice()
: x_audio2_(nullptr)
, mastering_voice_(nullptr)
, initialized_(false)
{
}
@ -185,26 +184,23 @@ namespace easy2d
modules::MediaFoundation().MFShutdown();
}
void AudioDevice::Init(bool debug)
HRESULT AudioDevice::Init(bool debug)
{
if (initialized_)
return;
E2D_LOG("Initing audio device");
ThrowIfFailed(
modules::MediaFoundation().MFStartup(MF_VERSION, MFSTARTUP_FULL)
);
HRESULT hr = modules::MediaFoundation().MFStartup(MF_VERSION, MFSTARTUP_FULL);
ThrowIfFailed(
modules::XAudio2().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR)
);
if (SUCCEEDED(hr))
{
hr = modules::XAudio2().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
}
ThrowIfFailed(
x_audio2_->CreateMasteringVoice(&mastering_voice_)
);
initialized_ = true;
if (SUCCEEDED(hr))
{
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
return hr;
}
HRESULT AudioDevice::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx)

View File

@ -80,7 +80,7 @@ namespace easy2d
E2D_DECLARE_SINGLETON(AudioDevice);
public:
void Init(bool debug);
HRESULT Init(bool debug);
// 开启设备
void Open();
@ -105,7 +105,6 @@ namespace easy2d
~AudioDevice();
protected:
bool initialized_;
IXAudio2* x_audio2_;
IXAudio2MasteringVoice* mastering_voice_;
std::set<Voice*> voice_cache_;

View File

@ -36,8 +36,9 @@ namespace easy2d
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
, opacity_(1.f)
, window_occluded_(false)
, initialized_(false)
, options_()
, vsync_enabled_(true)
, antialias_(true)
, text_antialias_(TextAntialias::ClearType)
{
}
@ -48,54 +49,53 @@ namespace easy2d
ClearImageCache();
}
void GraphicsDevice::Init(HWND hwnd, GraphicsOptions options, bool debug)
HRESULT GraphicsDevice::Init(HWND hwnd, bool vsync, bool debug)
{
if (initialized_)
return;
E2D_LOG("Initing graphics device");
options_ = options;
HRESULT hr = CreateResources(hwnd);
CreateDeviceResources(hwnd);
initialized_ = true;
}
void GraphicsDevice::BeginDraw(HWND hwnd)
{
CreateDeviceResources(hwnd);
window_occluded_ = !!(render_target->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
if (!window_occluded_)
if (SUCCEEDED(hr))
{
render_target->BeginDraw();
render_target->Clear(clear_color_);
vsync_enabled_ = vsync;
}
return hr;
}
void GraphicsDevice::EndDraw()
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_)
{
HRESULT hr = render_target->EndDraw();
hr = render_target_->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
// 并在下一次调用时重建资源
DiscardResources();
hr = S_OK;
fps_text_format_ = nullptr;
fps_text_layout_ = nullptr;
text_renderer = nullptr;
solid_brush = nullptr;
render_target = nullptr;
}
ThrowIfFailed(hr);
}
return hr;
}
void GraphicsDevice::ClearImageCache()
@ -105,20 +105,20 @@ namespace easy2d
HRESULT GraphicsDevice::CreateLayer(cpLayer& layer)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
layer = nullptr;
return render_target->CreateLayer(&layer);
return render_target_->CreateLayer(&layer);
}
HRESULT GraphicsDevice::CreateSolidColorBrush(cpSolidColorBrush & brush) const
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
brush = nullptr;
return render_target->CreateSolidColorBrush(
return render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&brush
);
@ -131,18 +131,18 @@ namespace easy2d
StrokeStyle stroke
)
{
if (!solid_brush ||
!render_target)
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush->SetColor(stroke_color);
solid_brush_->SetColor(stroke_color);
auto stroke_style = Factory::Instance()->GetStrokeStyle(stroke);
render_target->DrawGeometry(
render_target_->DrawGeometry(
geometry.Get(),
solid_brush.Get(),
solid_brush_.Get(),
stroke_width,
stroke_style.Get()
);
@ -151,24 +151,24 @@ namespace easy2d
HRESULT GraphicsDevice::FillGeometry(cpGeometry const & geometry, const Color & fill_color)
{
if (!solid_brush ||
!render_target)
if (!solid_brush_ ||
!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush->SetColor(fill_color);
render_target->FillGeometry(
solid_brush_->SetColor(fill_color);
render_target_->FillGeometry(
geometry.Get(),
solid_brush.Get()
solid_brush_.Get()
);
return S_OK;
}
HRESULT GraphicsDevice::DrawImage(spImage const & image)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
if (!image->GetBitmap())
@ -177,7 +177,7 @@ namespace easy2d
if (window_occluded_)
return S_OK;
render_target->DrawBitmap(
render_target_->DrawBitmap(
image->GetBitmap().Get(),
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
opacity_,
@ -191,7 +191,7 @@ namespace easy2d
cpBitmap const& bitmap
)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
@ -199,7 +199,7 @@ namespace easy2d
// Do not crop bitmap
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
render_target->DrawBitmap(
render_target_->DrawBitmap(
bitmap.Get(),
rect,
opacity_,
@ -211,25 +211,25 @@ namespace easy2d
HRESULT GraphicsDevice::DrawTextLayout(cpTextLayout const& text_layout)
{
if (!text_renderer)
if (!text_renderer_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
return text_layout->Draw(nullptr, text_renderer.Get(), 0, 0);
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)
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target->SetTransform(ConvertToD2DMatrix(clip_matrix));
render_target->PushAxisAlignedClip(
render_target_->SetTransform(ConvertToD2DMatrix(clip_matrix));
render_target_->PushAxisAlignedClip(
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
);
@ -238,33 +238,33 @@ namespace easy2d
HRESULT GraphicsDevice::PopClip()
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target->PopAxisAlignedClip();
render_target_->PopAxisAlignedClip();
return S_OK;
}
HRESULT GraphicsDevice::PushLayer(cpLayer const& layer, LayerProperties const& properties)
{
if (!render_target ||
!solid_brush)
if (!render_target_ ||
!solid_brush_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target->PushLayer(
render_target_->PushLayer(
D2D1::LayerParameters(
properties.area,
nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(),
properties.opacity,
solid_brush.Get(),
solid_brush_.Get(),
D2D1_LAYER_OPTIONS_NONE
),
layer.Get()
@ -274,22 +274,22 @@ namespace easy2d
HRESULT GraphicsDevice::PopLayer()
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target->PopLayer();
render_target_->PopLayer();
return S_OK;
}
HRESULT GraphicsDevice::GetSize(Size & size)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
auto rtsize = render_target->GetSize();
auto rtsize = render_target_->GetSize();
size.width = rtsize.width;
size.height = rtsize.height;
return S_OK;
@ -297,7 +297,7 @@ namespace easy2d
HRESULT GraphicsDevice::CreateBitmapFromFile(cpBitmap& bitmap, String const& file_path)
{
if (render_target == nullptr)
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
@ -312,7 +312,7 @@ namespace easy2d
cpBitmap bitmap_tmp;
HRESULT hr = Factory::Instance()->CreateBitmapFromFile(
bitmap,
render_target,
render_target_,
file_path
);
@ -326,7 +326,7 @@ namespace easy2d
HRESULT GraphicsDevice::CreateBitmapFromResource(cpBitmap& bitmap, Resource const& res)
{
if (render_target == nullptr)
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
@ -340,7 +340,7 @@ namespace easy2d
HRESULT hr = Factory::Instance()->CreateBitmapFromResource(
bitmap,
render_target,
render_target_,
res
);
@ -354,38 +354,38 @@ namespace easy2d
HRESULT GraphicsDevice::CreateBitmapRenderTarget(cpBitmapRenderTarget & brt)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
brt = nullptr;
return render_target->CreateCompatibleRenderTarget(&brt);
return render_target_->CreateCompatibleRenderTarget(&brt);
}
HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
render_target->Resize(D2D1::SizeU(width, height));
render_target_->Resize(D2D1::SizeU(width, height));
return S_OK;
}
HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
render_target->SetTransform(ConvertToD2DMatrix(matrix));
render_target_->SetTransform(ConvertToD2DMatrix(matrix));
return S_OK;
}
HRESULT GraphicsDevice::SetOpacity(float opacity)
{
if (!render_target)
if (!render_target_)
return E_UNEXPECTED;
opacity_ = opacity;
solid_brush->SetOpacity(opacity);
solid_brush_->SetOpacity(opacity);
return S_OK;
}
@ -397,11 +397,11 @@ namespace easy2d
StrokeStyle outline_stroke
)
{
if (!text_renderer)
if (!text_renderer_)
return E_UNEXPECTED;
auto stroke_style = Factory::Instance()->GetStrokeStyle(outline_stroke);
text_renderer->SetTextStyle(
text_renderer_->SetTextStyle(
color,
has_outline,
outline_color,
@ -411,14 +411,56 @@ namespace easy2d
return S_OK;
}
void GraphicsDevice::SetBackgroundColor(const Color& color)
void GraphicsDevice::SetClearColor(const Color& color)
{
clear_color_ = color;
}
void GraphicsDevice::CreateDeviceResources(HWND hwnd)
HRESULT GraphicsDevice::SetAntialiasMode(bool enabled)
{
if (!render_target)
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);
@ -428,65 +470,50 @@ namespace easy2d
rc.bottom - rc.top
);
// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
// 创建一个 Direct2D 渲染目标
ThrowIfFailed(
Factory::Instance()->CreateHwndRenderTarget(
render_target,
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
options_.vsync ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
)
hr = Factory::Instance()->CreateHwndRenderTarget(
render_target_,
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
vsync_enabled_ ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
)
);
render_target->SetAntialiasMode(
options_.antialias ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
);
D2D1_TEXT_ANTIALIAS_MODE mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
switch (options_.text_antialias)
if (SUCCEEDED(hr))
{
case TextAntialias::Default:
mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
break;
case TextAntialias::ClearType:
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
break;
case TextAntialias::GrayScale:
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
break;
case TextAntialias::None:
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
break;
default:
break;
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
}
render_target->SetTextAntialiasMode(mode);
}
if (!solid_brush)
{
ThrowIfFailed(
render_target->CreateSolidColorBrush(
if (SUCCEEDED(hr))
{
hr = render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&solid_brush
)
);
}
&solid_brush_
);
}
if (!text_renderer)
{
ThrowIfFailed(
Factory::Instance()->CreateTextRenderer(
text_renderer,
render_target,
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,20 +37,6 @@ namespace easy2d
None // 不启用抗锯齿
};
// 图形渲染选项
struct GraphicsOptions
{
bool vsync; // 垂直同步
bool antialias; // 抗锯齿
TextAntialias text_antialias; // 文字抗锯齿模式
GraphicsOptions()
: vsync(true)
, antialias(true)
, text_antialias(TextAntialias::ClearType)
{}
};
namespace devices
{
class GraphicsDevice
@ -59,20 +45,34 @@ namespace easy2d
E2D_DECLARE_SINGLETON(GraphicsDevice);
public:
void Init(HWND hwnd, GraphicsOptions options, bool debug);
HRESULT Init(HWND hwnd, bool vsync, bool debug);
// 开始渲染
void BeginDraw(HWND hwnd);
HRESULT BeginDraw(HWND hwnd);
// 结束渲染
void EndDraw();
HRESULT EndDraw();
// 设置背景
void SetBackgroundColor(
// 设置清空屏幕的颜
void SetClearColor(
const Color& color
);
void CreateDeviceResources(HWND hwnd);
// 设置抗锯齿模式
HRESULT SetAntialiasMode(
bool enabled
);
// 设置文字抗锯齿模式
HRESULT SetTextAntialiasMode(
TextAntialias mode
);
HRESULT CreateResources(
HWND hwnd
);
void DiscardResources();
HRESULT CreateLayer(
cpLayer& layer
@ -167,13 +167,14 @@ namespace easy2d
~GraphicsDevice();
protected:
bool initialized_;
bool window_occluded_;
bool vsync_enabled_;
bool antialias_;
TextAntialias text_antialias_;
float opacity_;
GraphicsOptions options_;
cpTextRenderer text_renderer;
cpSolidColorBrush solid_brush;
cpHwndRenderTarget render_target;
cpTextRenderer text_renderer_;
cpSolidColorBrush solid_brush_;
cpHwndRenderTarget render_target_;
D2D1_COLOR_F clear_color_;
cpTextFormat fps_text_format_;
cpTextLayout fps_text_layout_;

View File

@ -39,7 +39,6 @@ namespace easy2d
: handle(nullptr)
, scale_x(1.f)
, scale_y(1.f)
, initialized_(false)
{
}
@ -48,11 +47,8 @@ namespace easy2d
E2D_LOG("Destroying window");
}
void WindowImpl::Init(String title, int width, int height, LPCWSTR icon, WNDPROC proc, bool debug)
HRESULT WindowImpl::Init(String title, int width, int height, LPCWSTR icon, WNDPROC proc, bool debug)
{
if (initialized_)
return;
E2D_LOG("Creating window");
HINSTANCE hinstance = GetModuleHandle(nullptr);
@ -85,10 +81,8 @@ namespace easy2d
GetContentScale(&scale_x, &scale_y);
// 计算窗口大小
Rect client_rect = LocateWindow(width, height, scale_x, scale_y);
// 创建窗口
Rect client_rect = LocateWindow(width, height, scale_x, scale_y);
handle = ::CreateWindowEx(
NULL,
REGISTER_CLASS,
@ -107,13 +101,9 @@ namespace easy2d
if (handle == nullptr)
{
::UnregisterClass(REGISTER_CLASS, hinstance);
const char* err = "Create window failed!";
logs::Errorln(HRESULT_FROM_WIN32(GetLastError()), err);
throw std::runtime_error(err);
return HRESULT_FROM_WIN32(GetLastError());
}
initialized_ = true;
return S_OK;
}
String WindowImpl::GetTitle() const

View File

@ -30,7 +30,7 @@ namespace easy2d
E2D_DECLARE_SINGLETON(WindowImpl);
public:
void Init(
HRESULT Init(
String title,
int width,
int height,
@ -72,7 +72,6 @@ namespace easy2d
~WindowImpl();
private:
bool initialized_;
HWND handle;
float scale_x;
float scale_y;

View File

@ -220,31 +220,6 @@ namespace easy2d
return Node::Dispatch(e, handled);
}
void Button::Visit()
{
Node::Visit();
if (IsVisible() &&
!enabled_ &&
normal_ &&
normal_->ContainsPoint(devices::Input::Instance()->GetMousePos()))
{
HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO);
if (hcursor)
{
::SetCursor(hcursor);
}
}
else if (status_ == Status::Mouseover || status_ == Status::Selected)
{
HCURSOR hcursor = ::LoadCursor(nullptr, IDC_HAND);
if (hcursor)
{
::SetCursor(hcursor);
}
}
}
void Button::SetStatus(Status status)
{
if (status_ != status)

View File

@ -120,9 +120,6 @@ namespace easy2d
bool handled
) override;
// 遍历节点
virtual void Visit() override;
private:
spNode normal_;
spNode mouseover_;