update: GraphicsDevice owns all Direct2D resources
This commit is contained in:
parent
c474d259c5
commit
2b366e42be
|
|
@ -46,8 +46,8 @@ namespace easy2d
|
|||
Right /* ÓÒ */
|
||||
};
|
||||
|
||||
// ÏßÌõÏཻÑùʽ
|
||||
enum class Stroke : int
|
||||
// »±ÊÑùʽ
|
||||
enum class StrokeStyle : int
|
||||
{
|
||||
Miter = 0, /* бÇÐ */
|
||||
Bevel = 1, /* б½Ç */
|
||||
|
|
|
|||
|
|
@ -24,15 +24,21 @@
|
|||
|
||||
namespace easy2d
|
||||
{
|
||||
///////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////
|
||||
// FIXME!!!
|
||||
///////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
Canvas::Canvas(float width, float height)
|
||||
: render_target_(nullptr)
|
||||
, fill_brush_(nullptr)
|
||||
, line_brush_(nullptr)
|
||||
, stroke_style_(nullptr)
|
||||
, stroke_width_(1.0f)
|
||||
, stroke_(Stroke::Miter)
|
||||
, stroke_(StrokeStyle::Miter)
|
||||
{
|
||||
render_target_ = render::D2D.HwndRenderTarget;
|
||||
// render_target_ = render::D2D.HwndRenderTarget;
|
||||
render_target_->AddRef();
|
||||
|
||||
ThrowIfFailed(
|
||||
|
|
@ -78,22 +84,11 @@ namespace easy2d
|
|||
stroke_width_ = std::max(width, 0.f);
|
||||
}
|
||||
|
||||
void Canvas::SetStrokeStyle(Stroke strokeStyle)
|
||||
void Canvas::SetStrokeStyle(StrokeStyle stroke)
|
||||
{
|
||||
SafeRelease(stroke_style_);
|
||||
|
||||
switch (strokeStyle)
|
||||
{
|
||||
case Stroke::Miter:
|
||||
stroke_style_ = render::D2D.MiterStrokeStyle;
|
||||
break;
|
||||
case Stroke::Bevel:
|
||||
stroke_style_ = render::D2D.BevelStrokeStyle;
|
||||
break;
|
||||
case Stroke::Round:
|
||||
stroke_style_ = render::D2D.RoundStrokeStyle;
|
||||
break;
|
||||
}
|
||||
stroke_style_ = render::instance.GetStrokeStyle(stroke);
|
||||
|
||||
if (stroke_style_)
|
||||
stroke_style_->AddRef();
|
||||
|
|
@ -114,7 +109,7 @@ namespace easy2d
|
|||
return stroke_width_;
|
||||
}
|
||||
|
||||
Stroke Canvas::GetStrokeStyle() const
|
||||
StrokeStyle Canvas::GetStrokeStyle() const
|
||||
{
|
||||
return stroke_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace easy2d
|
|||
|
||||
// ÉèÖÃÏßÌõÏཻÑùʽ
|
||||
void SetStrokeStyle(
|
||||
Stroke strokeStyle
|
||||
StrokeStyle stroke
|
||||
);
|
||||
|
||||
// »ñÈ¡ÏßÌõÑÕÉ«
|
||||
|
|
@ -66,7 +66,7 @@ namespace easy2d
|
|||
float GetStrokeWidth() const;
|
||||
|
||||
// »ñÈ¡ÏßÌõÏཻÑùʽ
|
||||
Stroke GetStrokeStyle() const;
|
||||
StrokeStyle GetStrokeStyle() const;
|
||||
|
||||
// »Ö±Ïß
|
||||
void DrawLine(
|
||||
|
|
@ -129,7 +129,7 @@ namespace easy2d
|
|||
|
||||
private:
|
||||
float stroke_width_;
|
||||
Stroke stroke_;
|
||||
StrokeStyle stroke_;
|
||||
ID2D1RenderTarget* render_target_;
|
||||
ID2D1SolidColorBrush* fill_brush_;
|
||||
ID2D1SolidColorBrush* line_brush_;
|
||||
|
|
|
|||
|
|
@ -80,9 +80,4 @@ namespace easy2d
|
|||
, a(color.a)
|
||||
{
|
||||
}
|
||||
|
||||
Color::operator D2D1_COLOR_F() const
|
||||
{
|
||||
return D2D1::ColorF(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,10 @@ namespace easy2d
|
|||
const D2D1_COLOR_F& color
|
||||
);
|
||||
|
||||
operator D2D1_COLOR_F() const;
|
||||
inline operator D2D1_COLOR_F() const
|
||||
{
|
||||
return D2D1_COLOR_F{ r, g, b, a };
|
||||
}
|
||||
|
||||
public:
|
||||
enum Value : unsigned int
|
||||
|
|
|
|||
|
|
@ -23,12 +23,13 @@
|
|||
#include "Scene.h"
|
||||
#include "Transition.h"
|
||||
#include "Image.h"
|
||||
#include "../utils/Player.h"
|
||||
#include "time.h"
|
||||
#include "render.h"
|
||||
#include "input.h"
|
||||
#include "audio.h"
|
||||
#include "modules.h"
|
||||
#include "../utils/Player.h"
|
||||
#include "../math/Matrix.hpp"
|
||||
#include <thread>
|
||||
|
||||
namespace easy2d
|
||||
|
|
@ -68,7 +69,7 @@ namespace easy2d
|
|||
Image::ClearCache();
|
||||
Player::ClearCache();
|
||||
|
||||
render::Uninitialize();
|
||||
render::instance.Uninitialize();
|
||||
audio::instance.Uninitialize();
|
||||
window::instance.Destroy();
|
||||
modules::Uninitialize();
|
||||
|
|
@ -82,8 +83,8 @@ namespace easy2d
|
|||
{
|
||||
modules::Initialize();
|
||||
window::instance.Initialize(property);
|
||||
render::instance.Initialize(window::instance.handle);
|
||||
audio::instance.Initialize();
|
||||
render::Initialize(window::instance.handle);
|
||||
|
||||
// 若开启了调试模式,打开控制台
|
||||
HWND console = ::GetConsoleWindow();
|
||||
|
|
@ -291,14 +292,14 @@ namespace easy2d
|
|||
{
|
||||
if (curr_scene_ && curr_scene_->GetRoot())
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.f);
|
||||
render::instance.SetTransform(math::Matrix());
|
||||
render::instance.SetBrushOpacity(1.f);
|
||||
curr_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
if (next_scene_ && next_scene_->GetRoot())
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.f);
|
||||
render::instance.SetTransform(math::Matrix());
|
||||
render::instance.SetBrushOpacity(1.f);
|
||||
next_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "Image.h"
|
||||
#include "render.h"
|
||||
#include "logs.h"
|
||||
#include "../utils/File.h"
|
||||
|
||||
namespace easy2d
|
||||
|
|
@ -193,91 +194,17 @@ namespace easy2d
|
|||
return true;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
IWICImagingFactory* imaging_factory = render::D2D.WICImagingFactory;
|
||||
ID2D1HwndRenderTarget* render_target = render::D2D.HwndRenderTarget;
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
IWICFormatConverter* converter = nullptr;
|
||||
ID2D1Bitmap* bitmap = nullptr;
|
||||
|
||||
// 加载资源
|
||||
hr = res.Load() ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = imaging_factory->CreateStream(&stream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = stream->InitializeFromMemory(
|
||||
static_cast<WICInProcPointer>(res.GetData()),
|
||||
res.GetDataSize()
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = imaging_factory->CreateDecoderFromStream(
|
||||
stream,
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
hr = imaging_factory->CreateFormatConverter(&converter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = converter->Initialize(
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = render_target->CreateBitmapFromWicBitmap(
|
||||
converter,
|
||||
nullptr,
|
||||
&bitmap
|
||||
);
|
||||
}
|
||||
ID2D1Bitmap* bitmap = nullptr;
|
||||
HRESULT hr = render::instance.CreateBitmapFromResource(res, &bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(decoder);
|
||||
SafeRelease(source);
|
||||
SafeRelease(stream);
|
||||
SafeRelease(converter);
|
||||
else
|
||||
{
|
||||
logs::Trace(L"CreateBitmapFromFile", hr);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
|
@ -296,68 +223,17 @@ namespace easy2d
|
|||
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
|
||||
String image_file_path = image_file.GetPath();
|
||||
|
||||
IWICImagingFactory* imaging_factory = render::D2D.WICImagingFactory;
|
||||
ID2D1HwndRenderTarget* render_target = render::D2D.HwndRenderTarget;
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
IWICFormatConverter* converter = nullptr;
|
||||
ID2D1Bitmap* bitmap = nullptr;
|
||||
|
||||
// 创建解码器
|
||||
HRESULT hr = imaging_factory->CreateDecoderFromFilename(
|
||||
image_file_path.c_str(),
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
hr = imaging_factory->CreateFormatConverter(&converter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = converter->Initialize(
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = render_target->CreateBitmapFromWicBitmap(
|
||||
converter,
|
||||
nullptr,
|
||||
&bitmap
|
||||
);
|
||||
}
|
||||
ID2D1Bitmap* bitmap = nullptr;
|
||||
HRESULT hr = render::instance.CreateBitmapFromFile(file_name, &bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(decoder);
|
||||
SafeRelease(source);
|
||||
SafeRelease(stream);
|
||||
SafeRelease(converter);
|
||||
else
|
||||
{
|
||||
logs::Trace(L"CreateBitmapFromFile", hr);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ namespace easy2d
|
|||
, children_()
|
||||
, actions_()
|
||||
, tasks_()
|
||||
, initial_matrix_(D2D1::Matrix3x2F::Identity())
|
||||
, final_matrix_(D2D1::Matrix3x2F::Identity())
|
||||
, initial_matrix_()
|
||||
, final_matrix_()
|
||||
, border_color_(Color::Red, 0.6f)
|
||||
{
|
||||
}
|
||||
|
|
@ -75,19 +75,14 @@ namespace easy2d
|
|||
if (!visible_)
|
||||
return;
|
||||
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
if (clip_enabled_)
|
||||
{
|
||||
render_target->SetTransform(final_matrix_);
|
||||
render_target->PushAxisAlignedClip(
|
||||
D2D1::RectF(0, 0, transform_.size.width, transform_.size.height),
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||
);
|
||||
render::instance.PushClip(final_matrix_, transform_.size);
|
||||
}
|
||||
|
||||
if (children_.empty())
|
||||
{
|
||||
render_target->SetTransform(final_matrix_);
|
||||
render::instance.SetTransform(final_matrix_);
|
||||
OnDraw();
|
||||
}
|
||||
else
|
||||
|
|
@ -119,7 +114,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
render_target->SetTransform(final_matrix_);
|
||||
render::instance.SetTransform(final_matrix_);
|
||||
OnDraw();
|
||||
|
||||
// 访问剩余节点
|
||||
|
|
@ -129,7 +124,7 @@ namespace easy2d
|
|||
|
||||
if (clip_enabled_)
|
||||
{
|
||||
render_target->PopAxisAlignedClip();
|
||||
render::instance.PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,12 +171,7 @@ namespace easy2d
|
|||
{
|
||||
if (border_)
|
||||
{
|
||||
render::D2D.SolidColorBrush->SetColor(D2D1_COLOR_F(border_color_));
|
||||
render::D2D.HwndRenderTarget->DrawGeometry(
|
||||
border_,
|
||||
render::D2D.SolidColorBrush,
|
||||
1.5f
|
||||
);
|
||||
render::instance.DrawGeometry(border_, border_color_, 1.f, 1.5f);
|
||||
}
|
||||
|
||||
for (const auto& child : children_)
|
||||
|
|
@ -198,14 +188,14 @@ namespace easy2d
|
|||
|
||||
dirty_transform_ = false;
|
||||
|
||||
final_matrix_ = static_cast<D2D1::Matrix3x2F>(transform_);
|
||||
final_matrix_ = transform_.ToMatrix();
|
||||
|
||||
// 根据自身支点计算 Initial 矩阵,子节点将根据这个矩阵进行变换
|
||||
auto pivot = Point(
|
||||
transform_.size.width * transform_.pivot_x,
|
||||
transform_.size.height * transform_.pivot_y
|
||||
);
|
||||
initial_matrix_ = final_matrix_ * D2D1::Matrix3x2F::Translation(pivot.x, pivot.y);
|
||||
initial_matrix_ = final_matrix_ * math::Matrix::Translation(pivot);
|
||||
|
||||
if (parent_)
|
||||
{
|
||||
|
|
@ -220,26 +210,10 @@ namespace easy2d
|
|||
|
||||
// 重新构造轮廓
|
||||
SafeRelease(border_);
|
||||
|
||||
ID2D1Factory * factory = render::D2D.Factory;
|
||||
ID2D1RectangleGeometry * rectangle = nullptr;
|
||||
ID2D1TransformedGeometry * transformed = nullptr;
|
||||
|
||||
ThrowIfFailed(
|
||||
factory->CreateRectangleGeometry(
|
||||
D2D1::RectF(0, 0, transform_.size.width, transform_.size.height),
|
||||
&rectangle
|
||||
)
|
||||
render::instance.CreateRectGeometry(final_matrix_, transform_.size, &border_)
|
||||
);
|
||||
ThrowIfFailed(
|
||||
factory->CreateTransformedGeometry(
|
||||
rectangle,
|
||||
final_matrix_,
|
||||
&transformed
|
||||
)
|
||||
);
|
||||
border_ = transformed;
|
||||
|
||||
SafeRelease(rectangle);
|
||||
|
||||
// 通知子节点进行转换
|
||||
for (const auto& child : children_)
|
||||
|
|
|
|||
|
|
@ -21,9 +21,10 @@
|
|||
#pragma once
|
||||
#include "base.h"
|
||||
#include "RefCounter.h"
|
||||
#include "../math/Transform.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
#include "../math/Transform.h"
|
||||
#include "../math/Matrix.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -446,9 +447,8 @@ namespace easy2d
|
|||
void UpdateTime();
|
||||
|
||||
private:
|
||||
String name_;
|
||||
String name_;
|
||||
size_t hash_name_;
|
||||
math::Transform transform_;
|
||||
float display_opacity_;
|
||||
float real_opacity_;
|
||||
int order_;
|
||||
|
|
@ -463,7 +463,8 @@ namespace easy2d
|
|||
Tasks tasks_;
|
||||
Nodes children_;
|
||||
ID2D1Geometry* border_;
|
||||
D2D1::Matrix3x2F initial_matrix_;
|
||||
D2D1::Matrix3x2F final_matrix_;
|
||||
math::Transform transform_;
|
||||
math::Matrix initial_matrix_;
|
||||
math::Matrix final_matrix_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "BaseTypes.h"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -96,5 +97,10 @@ namespace easy2d
|
|||
(origin.y + size.height) < rect.origin.y ||
|
||||
(rect.origin.y + rect.size.height) < origin.y);
|
||||
}
|
||||
|
||||
inline operator D2D1_RECT_F () const
|
||||
{
|
||||
return D2D1_RECT_F{ origin.x, origin.y, origin.x + size.width, origin.y + size.height };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ namespace easy2d
|
|||
{
|
||||
Scene::Scene()
|
||||
: root_(nullptr)
|
||||
, transform_(D2D1::Matrix3x2F::Identity())
|
||||
, transform_()
|
||||
{
|
||||
}
|
||||
|
||||
Scene::Scene(Node * root)
|
||||
: root_(nullptr)
|
||||
, transform_(D2D1::Matrix3x2F::Identity())
|
||||
, transform_()
|
||||
{
|
||||
this->SetRoot(root);
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Scene::SetTransform(const D2D1::Matrix3x2F& matrix)
|
||||
void Scene::SetTransform(const math::Matrix& matrix)
|
||||
{
|
||||
transform_ = matrix;
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
const D2D1::Matrix3x2F & Scene::GetTransform() const
|
||||
const math::Matrix& Scene::GetTransform() const
|
||||
{
|
||||
return transform_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "RefCounter.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
#include <d2d1.h>
|
||||
#include "../math/Matrix.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -73,17 +73,17 @@ namespace easy2d
|
|||
|
||||
// ÉèÖÃת»»¾ØÕó
|
||||
void SetTransform(
|
||||
const D2D1::Matrix3x2F& matrix
|
||||
const math::Matrix& matrix
|
||||
);
|
||||
|
||||
// »ñȡת»»¾ØÕó
|
||||
const D2D1::Matrix3x2F& GetTransform() const;
|
||||
const math::Matrix& GetTransform() const;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Scene);
|
||||
|
||||
private:
|
||||
Node* root_;
|
||||
D2D1::Matrix3x2F transform_;
|
||||
Node* root_;
|
||||
math::Matrix transform_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -52,5 +53,10 @@ namespace easy2d
|
|||
Size operator / (float val) const;
|
||||
Size operator - () const;
|
||||
bool operator== (const Size& other) const;
|
||||
|
||||
inline operator D2D1_SIZE_F () const
|
||||
{
|
||||
return D2D1_SIZE_F{ width, height };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,17 +135,11 @@ namespace easy2d
|
|||
if (image_ && image_->GetBitmap())
|
||||
{
|
||||
auto crop_pos = image_->GetCropPos();
|
||||
render::D2D.HwndRenderTarget->DrawBitmap(
|
||||
image_->GetBitmap(),
|
||||
D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height),
|
||||
render::instance.DrawImage(
|
||||
image_,
|
||||
GetDisplayOpacity(),
|
||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
||||
D2D1::RectF(
|
||||
crop_pos.x,
|
||||
crop_pos.y,
|
||||
crop_pos.y + GetTransform().size.width,
|
||||
crop_pos.y + GetTransform().size.height
|
||||
)
|
||||
Rect(Point(), GetTransform().size),
|
||||
Rect(crop_pos, GetTransform().size)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace easy2d
|
|||
, outline(true)
|
||||
, outline_color(Color(Color::Black, 0.5))
|
||||
, outline_width(1.f)
|
||||
, outline_stroke(Stroke::Round)
|
||||
, outline_stroke(StrokeStyle::Round)
|
||||
{}
|
||||
|
||||
Text::Style::Style(
|
||||
|
|
@ -53,7 +53,7 @@ namespace easy2d
|
|||
bool outline,
|
||||
Color outline_color,
|
||||
float outline_width,
|
||||
Stroke outline_stroke
|
||||
StrokeStyle outline_stroke
|
||||
)
|
||||
: color(color)
|
||||
, alignment(alignment)
|
||||
|
|
@ -143,7 +143,7 @@ namespace easy2d
|
|||
return style_.outline_width;
|
||||
}
|
||||
|
||||
Stroke Text::GetOutlineStroke() const
|
||||
StrokeStyle Text::GetOutlineStroke() const
|
||||
{
|
||||
return style_.outline_stroke;
|
||||
}
|
||||
|
|
@ -306,7 +306,7 @@ namespace easy2d
|
|||
style_.outline_width = outline_width;
|
||||
}
|
||||
|
||||
void Text::SetOutlineStroke(Stroke outline_stroke)
|
||||
void Text::SetOutlineStroke(StrokeStyle outline_stroke)
|
||||
{
|
||||
style_.outline_stroke = outline_stroke;
|
||||
}
|
||||
|
|
@ -318,16 +318,16 @@ namespace easy2d
|
|||
// 创建文本区域
|
||||
D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height);
|
||||
// 设置画刷颜色和透明度
|
||||
render::D2D.SolidColorBrush->SetOpacity(GetDisplayOpacity());
|
||||
render::instance.SetBrushOpacity(GetDisplayOpacity());
|
||||
// 获取文本渲染器
|
||||
render::D2D.TextRenderer->SetTextStyle(
|
||||
render::instance.SetTextStyle(
|
||||
style_.color,
|
||||
style_.outline,
|
||||
style_.outline_color,
|
||||
style_.outline_width,
|
||||
static_cast<D2D1_LINE_JOIN>(style_.outline_stroke)
|
||||
style_.outline_stroke
|
||||
);
|
||||
text_layout_->Draw(nullptr, render::D2D.TextRenderer, 0, 0);
|
||||
render::instance.DrawTextLayout(text_layout_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,15 +344,9 @@ namespace easy2d
|
|||
SafeRelease(text_format_);
|
||||
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextFormat(
|
||||
font_.family.c_str(),
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT(font_.weight),
|
||||
font_.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
font_.size,
|
||||
L"",
|
||||
&text_format_
|
||||
render::instance.CreateTextFormat(
|
||||
&text_format_,
|
||||
font_
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -401,19 +395,15 @@ namespace easy2d
|
|||
return;
|
||||
}
|
||||
|
||||
UINT32 length = static_cast<UINT32>(text_.size());
|
||||
|
||||
// 对文本自动换行情况下进行处理
|
||||
if (style_.wrap)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
render::instance.CreateTextLayout(
|
||||
&text_layout_,
|
||||
text_,
|
||||
text_format_,
|
||||
style_.wrap_width,
|
||||
0,
|
||||
&text_layout_
|
||||
style_.wrap_width
|
||||
)
|
||||
);
|
||||
// 获取文本布局的宽度和高度
|
||||
|
|
@ -426,13 +416,11 @@ namespace easy2d
|
|||
{
|
||||
// 为防止文本对齐问题,根据先创建 layout 以获取宽度
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
render::instance.CreateTextLayout(
|
||||
&text_layout_,
|
||||
text_,
|
||||
text_format_,
|
||||
0,
|
||||
0,
|
||||
&text_layout_
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -445,19 +433,17 @@ namespace easy2d
|
|||
// 重新创建 layout
|
||||
SafeRelease(text_layout_);
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
render::instance.CreateTextLayout(
|
||||
&text_layout_,
|
||||
text_,
|
||||
text_format_,
|
||||
GetTransform().size.width,
|
||||
0,
|
||||
&text_layout_
|
||||
GetTransform().size.width
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// 添加下划线和删除线
|
||||
DWRITE_TEXT_RANGE range = { 0, length };
|
||||
DWRITE_TEXT_RANGE range = { 0, static_cast<UINT32>(text_.length()) };
|
||||
if (style_.underline)
|
||||
{
|
||||
text_layout_->SetUnderline(true, range);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace easy2d
|
|||
bool outline; // 显示描边
|
||||
Color outline_color; // 描边颜色
|
||||
float outline_width; // 描边线宽
|
||||
Stroke outline_stroke; // Ãè±ßÏßÏཻÑùʽ
|
||||
StrokeStyle outline_stroke; // Ãè±ßÏßÏཻÑùʽ
|
||||
|
||||
public:
|
||||
Style();
|
||||
|
|
@ -67,7 +67,7 @@ namespace easy2d
|
|||
bool outline = true,
|
||||
Color outline_color = Color(Color::Black, 0.5),
|
||||
float outline_width = 1.f,
|
||||
Stroke outline_stroke = Stroke::Round
|
||||
StrokeStyle outline_stroke = StrokeStyle::Round
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ namespace easy2d
|
|||
float GetOutlineWidth() const;
|
||||
|
||||
// 获取描边线相交样式
|
||||
Stroke GetOutlineStroke() const;
|
||||
StrokeStyle GetOutlineStroke() const;
|
||||
|
||||
// 获取文本显示行数
|
||||
int GetLineCount() const;
|
||||
|
|
@ -214,7 +214,7 @@ namespace easy2d
|
|||
|
||||
// 设置描边线相交样式
|
||||
void SetOutlineStroke(
|
||||
Stroke outline_stroke
|
||||
StrokeStyle outline_stroke
|
||||
);
|
||||
|
||||
// 渲染文字
|
||||
|
|
|
|||
|
|
@ -73,22 +73,7 @@ namespace easy2d
|
|||
bShowOutline_ = outline;
|
||||
sOutlineColor_ = outline_color;
|
||||
fOutlineWidth = 2 * outline_width;
|
||||
|
||||
switch (outlineJoin)
|
||||
{
|
||||
case D2D1_LINE_JOIN_MITER:
|
||||
pCurrStrokeStyle_ = render::D2D.MiterStrokeStyle;
|
||||
break;
|
||||
case D2D1_LINE_JOIN_BEVEL:
|
||||
pCurrStrokeStyle_ = render::D2D.BevelStrokeStyle;
|
||||
break;
|
||||
case D2D1_LINE_JOIN_ROUND:
|
||||
pCurrStrokeStyle_ = render::D2D.RoundStrokeStyle;
|
||||
break;
|
||||
default:
|
||||
pCurrStrokeStyle_ = nullptr;
|
||||
break;
|
||||
}
|
||||
pCurrStrokeStyle_ = render::instance.GetStrokeStyle(StrokeStyle(outlineJoin));
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::DrawGlyphRun(
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
#include "Transition.h"
|
||||
#include "Node.h"
|
||||
#include "Scene.h"
|
||||
#include "render.h"
|
||||
#include "window.h"
|
||||
#include "../math/Matrix.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -39,8 +39,8 @@ namespace easy2d
|
|||
, in_scene_(nullptr)
|
||||
, out_layer_(nullptr)
|
||||
, in_layer_(nullptr)
|
||||
, out_layer_param_()
|
||||
, in_layer_param_()
|
||||
, out_layer_prop_()
|
||||
, in_layer_prop_()
|
||||
{
|
||||
duration_ = std::max(duration, 0.f);
|
||||
}
|
||||
|
|
@ -73,32 +73,22 @@ namespace easy2d
|
|||
if (in_scene_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.HwndRenderTarget->CreateLayer(&in_layer_)
|
||||
render::instance.CreateLayer(&in_layer_)
|
||||
);
|
||||
}
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.HwndRenderTarget->CreateLayer(&out_layer_)
|
||||
render::instance.CreateLayer(&out_layer_)
|
||||
);
|
||||
}
|
||||
|
||||
window_size_ = window::instance.GetSize();
|
||||
out_layer_param_ = in_layer_param_ = D2D1::LayerParameters(
|
||||
D2D1::RectF(
|
||||
0.f,
|
||||
0.f,
|
||||
window_size_.width,
|
||||
window_size_.height
|
||||
),
|
||||
nullptr,
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
||||
D2D1::Matrix3x2F::Identity(),
|
||||
1.f,
|
||||
render::D2D.SolidColorBrush,
|
||||
D2D1_LAYER_OPTIONS_NONE
|
||||
);
|
||||
out_layer_prop_ = in_layer_prop_ = render::LayerProperties{
|
||||
Rect(Point(), window_size_),
|
||||
1.f
|
||||
};
|
||||
}
|
||||
|
||||
void Transition::Update()
|
||||
|
|
@ -121,46 +111,32 @@ namespace easy2d
|
|||
|
||||
void Transition::Draw()
|
||||
{
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
render_target->SetTransform(out_scene_->GetTransform());
|
||||
render_target->PushAxisAlignedClip(
|
||||
D2D1::RectF(
|
||||
0.f,
|
||||
0.f,
|
||||
window_size_.width,
|
||||
window_size_.height
|
||||
),
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||
render::instance.PushClip(
|
||||
out_scene_->GetTransform(),
|
||||
window_size_
|
||||
);
|
||||
render_target->PushLayer(out_layer_param_, out_layer_);
|
||||
render::instance.PushLayer(out_layer_, out_layer_prop_);
|
||||
|
||||
out_scene_->Draw();
|
||||
|
||||
render_target->PopLayer();
|
||||
render_target->PopAxisAlignedClip();
|
||||
render::instance.PopLayer();
|
||||
render::instance.PopClip();
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
render_target->SetTransform(in_scene_->GetTransform());
|
||||
render_target->PushAxisAlignedClip(
|
||||
D2D1::RectF(
|
||||
0.f,
|
||||
0.f,
|
||||
window_size_.width,
|
||||
window_size_.height
|
||||
),
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||
render::instance.PushClip(
|
||||
in_scene_->GetTransform(),
|
||||
window_size_
|
||||
);
|
||||
render_target->PushLayer(in_layer_param_, in_layer_);
|
||||
render::instance.PushLayer(in_layer_, in_layer_prop_);
|
||||
|
||||
in_scene_->Draw();
|
||||
|
||||
render_target->PopLayer();
|
||||
render_target->PopAxisAlignedClip();
|
||||
render::instance.PopLayer();
|
||||
render::instance.PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +159,7 @@ namespace easy2d
|
|||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
in_layer_param_.opacity = 0;
|
||||
in_layer_prop_.opacity = 0;
|
||||
}
|
||||
|
||||
void BoxTransition::Update()
|
||||
|
|
@ -192,22 +168,22 @@ namespace easy2d
|
|||
|
||||
if (process_ < .5f)
|
||||
{
|
||||
out_layer_param_.contentBounds = D2D1::RectF(
|
||||
out_layer_prop_.area = Rect(
|
||||
window_size_.width * process_,
|
||||
window_size_.height * process_,
|
||||
window_size_.width * (1 - process_),
|
||||
window_size_.height * (1 - process_)
|
||||
window_size_.width * (1 - process_ * 2),
|
||||
window_size_.height * (1 - process_ * 2)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_layer_param_.opacity = 0;
|
||||
in_layer_param_.opacity = 1;
|
||||
in_layer_param_.contentBounds = D2D1::RectF(
|
||||
out_layer_prop_.opacity = 0;
|
||||
in_layer_prop_.opacity = 1;
|
||||
in_layer_prop_.area = Rect(
|
||||
window_size_.width * (1 - process_),
|
||||
window_size_.height * (1 - process_),
|
||||
window_size_.width * process_,
|
||||
window_size_.height * process_
|
||||
window_size_.width * (2 * process_ - 1),
|
||||
window_size_.height * (2 * process_ - 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -225,16 +201,16 @@ namespace easy2d
|
|||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
out_layer_param_.opacity = 1;
|
||||
in_layer_param_.opacity = 0;
|
||||
out_layer_prop_.opacity = 1;
|
||||
in_layer_prop_.opacity = 0;
|
||||
}
|
||||
|
||||
void EmergeTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
out_layer_param_.opacity = 1 - process_;
|
||||
in_layer_param_.opacity = process_;
|
||||
out_layer_prop_.opacity = 1 - process_;
|
||||
in_layer_prop_.opacity = process_;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
|
|
@ -250,8 +226,8 @@ namespace easy2d
|
|||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
out_layer_param_.opacity = 1;
|
||||
in_layer_param_.opacity = 0;
|
||||
out_layer_prop_.opacity = 1;
|
||||
in_layer_prop_.opacity = 0;
|
||||
}
|
||||
|
||||
void FadeTransition::Update()
|
||||
|
|
@ -260,13 +236,13 @@ namespace easy2d
|
|||
|
||||
if (process_ < 0.5)
|
||||
{
|
||||
out_layer_param_.opacity = 1 - process_ * 2;
|
||||
in_layer_param_.opacity = 0;
|
||||
out_layer_prop_.opacity = 1 - process_ * 2;
|
||||
in_layer_prop_.opacity = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_layer_param_.opacity = 0;
|
||||
in_layer_param_.opacity = (process_ - 0.5f) * 2;
|
||||
out_layer_prop_.opacity = 0;
|
||||
in_layer_prop_.opacity = (process_ - 0.5f) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,13 +282,13 @@ namespace easy2d
|
|||
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
out_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Translation(
|
||||
math::Matrix::Translation(
|
||||
start_pos_.x,
|
||||
start_pos_.y
|
||||
)
|
||||
|
|
@ -328,7 +304,7 @@ namespace easy2d
|
|||
{
|
||||
auto translation = pos_delta_ * process_;
|
||||
out_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Translation(
|
||||
math::Matrix::Translation(
|
||||
translation.x,
|
||||
translation.y
|
||||
)
|
||||
|
|
@ -339,7 +315,7 @@ namespace easy2d
|
|||
{
|
||||
auto translation = start_pos_ + pos_delta_ * process_;
|
||||
in_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Translation(
|
||||
math::Matrix::Translation(
|
||||
translation.x,
|
||||
translation.y
|
||||
)
|
||||
|
|
@ -351,12 +327,12 @@ namespace easy2d
|
|||
{
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
out_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
in_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -376,22 +352,22 @@ namespace easy2d
|
|||
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
out_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
in_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
|
||||
in_layer_param_.opacity = 0;
|
||||
in_layer_prop_.opacity = 0;
|
||||
}
|
||||
|
||||
void RotationTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
auto center_pos = D2D1::Point2F(
|
||||
auto center_pos = math::Vector2(
|
||||
window_size_.width / 2,
|
||||
window_size_.height / 2
|
||||
);
|
||||
|
|
@ -401,11 +377,11 @@ namespace easy2d
|
|||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Scale(
|
||||
(.5f - process_) * 2,
|
||||
math::Matrix::Scaling(
|
||||
(.5f - process_) * 2,
|
||||
(.5f - process_) * 2,
|
||||
center_pos
|
||||
) * D2D1::Matrix3x2F::Rotation(
|
||||
) * math::Matrix::Rotation(
|
||||
rotation_ * (.5f - process_) * 2,
|
||||
center_pos
|
||||
)
|
||||
|
|
@ -416,15 +392,15 @@ namespace easy2d
|
|||
{
|
||||
if (in_scene_)
|
||||
{
|
||||
out_layer_param_.opacity = 0;
|
||||
in_layer_param_.opacity = 1;
|
||||
out_layer_prop_.opacity = 0;
|
||||
in_layer_prop_.opacity = 1;
|
||||
|
||||
in_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Scale(
|
||||
math::Matrix::Scaling(
|
||||
(process_ - .5f) * 2,
|
||||
(process_ - .5f) * 2,
|
||||
center_pos
|
||||
) * D2D1::Matrix3x2F::Rotation(
|
||||
) * math::Matrix::Rotation(
|
||||
rotation_ * (process_ - .5f) * 2,
|
||||
center_pos
|
||||
)
|
||||
|
|
@ -437,12 +413,12 @@ namespace easy2d
|
|||
{
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
out_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
in_scene_->SetTransform(math::Matrix());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
#include "base.h"
|
||||
#include "time.h"
|
||||
#include "render.h"
|
||||
#include "RefCounter.h"
|
||||
|
||||
namespace easy2d
|
||||
|
|
@ -65,17 +66,17 @@ namespace easy2d
|
|||
virtual void Reset() { };
|
||||
|
||||
protected:
|
||||
bool done_;
|
||||
float duration_;
|
||||
float process_;
|
||||
bool done_;
|
||||
float duration_;
|
||||
float process_;
|
||||
time::TimePoint started_;
|
||||
Size window_size_;
|
||||
Scene* out_scene_;
|
||||
Scene* in_scene_;
|
||||
ID2D1Layer * out_layer_;
|
||||
ID2D1Layer * in_layer_;
|
||||
D2D1_LAYER_PARAMETERS out_layer_param_;
|
||||
D2D1_LAYER_PARAMETERS in_layer_param_;
|
||||
Size window_size_;
|
||||
Scene* out_scene_;
|
||||
Scene* in_scene_;
|
||||
ID2D1Layer* out_layer_;
|
||||
ID2D1Layer* in_layer_;
|
||||
render::LayerProperties out_layer_prop_;
|
||||
render::LayerProperties in_layer_prop_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,17 +30,31 @@ namespace easy2d
|
|||
{
|
||||
namespace render
|
||||
{
|
||||
_D2D_Resource D2D = { 0 };
|
||||
GraphicsDevice instance;
|
||||
|
||||
void easy2d::render::Initialize(HWND hwnd)
|
||||
GraphicsDevice::GraphicsDevice()
|
||||
: fps_text_format_(nullptr)
|
||||
, fps_text_layout_(nullptr)
|
||||
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
||||
{
|
||||
if (D2D.Factory)
|
||||
ZeroMemory(&d2d, sizeof(D2DResources));
|
||||
}
|
||||
|
||||
GraphicsDevice::~GraphicsDevice()
|
||||
{
|
||||
SafeRelease(fps_text_format_);
|
||||
SafeRelease(fps_text_layout_);
|
||||
}
|
||||
|
||||
void GraphicsDevice::Initialize(HWND hwnd)
|
||||
{
|
||||
if (d2d.Factory)
|
||||
return;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D1CreateFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
&D2D.Factory
|
||||
&d2d.Factory
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -50,7 +64,7 @@ namespace easy2d
|
|||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWICImagingFactory,
|
||||
reinterpret_cast<void**>(&D2D.WICImagingFactory)
|
||||
reinterpret_cast<void**>(&d2d.WICImagingFactory)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -58,7 +72,7 @@ namespace easy2d
|
|||
DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory),
|
||||
reinterpret_cast<IUnknown**>(&D2D.DWriteFactory)
|
||||
reinterpret_cast<IUnknown**>(&d2d.DWriteFactory)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -73,132 +87,65 @@ namespace easy2d
|
|||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
d2d.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.MiterStrokeStyle
|
||||
&d2d.MiterStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
d2d.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.BevelStrokeStyle
|
||||
&d2d.BevelStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
d2d.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.RoundStrokeStyle
|
||||
&d2d.RoundStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
CreateDeviceResources(hwnd);
|
||||
}
|
||||
|
||||
void easy2d::render::CreateDeviceResources(HWND hwnd)
|
||||
void GraphicsDevice::Uninitialize()
|
||||
{
|
||||
if (!D2D.HwndRenderTarget)
|
||||
{
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
SafeRelease(d2d.TextRenderer);
|
||||
SafeRelease(d2d.SolidColorBrush);
|
||||
SafeRelease(d2d.HwndRenderTarget);
|
||||
|
||||
D2D1_SIZE_U size = D2D1::SizeU(
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top
|
||||
);
|
||||
SafeRelease(d2d.MiterStrokeStyle);
|
||||
SafeRelease(d2d.BevelStrokeStyle);
|
||||
SafeRelease(d2d.RoundStrokeStyle);
|
||||
|
||||
// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
|
||||
// 创建一个 Direct2D 渲染目标
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateHwndRenderTarget(
|
||||
D2D1::RenderTargetProperties(),
|
||||
D2D1::HwndRenderTargetProperties(
|
||||
hwnd,
|
||||
size,
|
||||
D2D1_PRESENT_OPTIONS_NONE),
|
||||
&D2D.HwndRenderTarget
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!D2D.SolidColorBrush)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
D2D.HwndRenderTarget->CreateSolidColorBrush(
|
||||
D2D1::ColorF(D2D1::ColorF::White),
|
||||
&D2D.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!D2D.TextRenderer)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
ITextRenderer::Create(
|
||||
&D2D.TextRenderer,
|
||||
D2D.Factory,
|
||||
D2D.HwndRenderTarget,
|
||||
D2D.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void easy2d::render::Uninitialize()
|
||||
{
|
||||
SafeRelease(D2D.TextRenderer);
|
||||
SafeRelease(D2D.SolidColorBrush);
|
||||
SafeRelease(D2D.HwndRenderTarget);
|
||||
|
||||
SafeRelease(D2D.MiterStrokeStyle);
|
||||
SafeRelease(D2D.BevelStrokeStyle);
|
||||
SafeRelease(D2D.RoundStrokeStyle);
|
||||
|
||||
SafeRelease(D2D.WICImagingFactory);
|
||||
SafeRelease(D2D.DWriteFactory);
|
||||
SafeRelease(D2D.Factory);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// GraphicsDevice
|
||||
//-------------------------------------------------------
|
||||
|
||||
GraphicsDevice instance;
|
||||
|
||||
GraphicsDevice::GraphicsDevice()
|
||||
: fps_text_format_(nullptr)
|
||||
, fps_text_layout_(nullptr)
|
||||
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
||||
{
|
||||
}
|
||||
|
||||
GraphicsDevice::~GraphicsDevice()
|
||||
{
|
||||
SafeRelease(fps_text_format_);
|
||||
SafeRelease(fps_text_layout_);
|
||||
SafeRelease(d2d.WICImagingFactory);
|
||||
SafeRelease(d2d.DWriteFactory);
|
||||
SafeRelease(d2d.Factory);
|
||||
}
|
||||
|
||||
void GraphicsDevice::BeginDraw(HWND hwnd)
|
||||
{
|
||||
render::CreateDeviceResources(hwnd);
|
||||
render::D2D.HwndRenderTarget->BeginDraw();
|
||||
render::D2D.HwndRenderTarget->Clear(clear_color_);
|
||||
CreateDeviceResources(hwnd);
|
||||
|
||||
d2d.HwndRenderTarget->BeginDraw();
|
||||
d2d.HwndRenderTarget->Clear(clear_color_);
|
||||
}
|
||||
|
||||
void GraphicsDevice::EndDraw()
|
||||
{
|
||||
HRESULT hr = render::D2D.HwndRenderTarget->EndDraw();
|
||||
HRESULT hr = d2d.HwndRenderTarget->EndDraw();
|
||||
|
||||
if (hr == D2DERR_RECREATE_TARGET)
|
||||
{
|
||||
|
|
@ -208,14 +155,426 @@ namespace easy2d
|
|||
|
||||
SafeRelease(fps_text_format_);
|
||||
SafeRelease(fps_text_layout_);
|
||||
SafeRelease(render::D2D.TextRenderer);
|
||||
SafeRelease(render::D2D.SolidColorBrush);
|
||||
SafeRelease(render::D2D.HwndRenderTarget);
|
||||
SafeRelease(d2d.TextRenderer);
|
||||
SafeRelease(d2d.SolidColorBrush);
|
||||
SafeRelease(d2d.HwndRenderTarget);
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateRectGeometry(
|
||||
const math::Matrix& matrix,
|
||||
const Size& size,
|
||||
ID2D1Geometry** geometry
|
||||
) const
|
||||
{
|
||||
if (!d2d.Factory)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
ID2D1RectangleGeometry * rectangle = nullptr;
|
||||
ID2D1TransformedGeometry * transformed = nullptr;
|
||||
|
||||
hr = d2d.Factory->CreateRectangleGeometry(
|
||||
D2D1::RectF(0, 0, size.width, size.height),
|
||||
&rectangle
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d.Factory->CreateTransformedGeometry(
|
||||
rectangle,
|
||||
matrix,
|
||||
&transformed
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*geometry = transformed;
|
||||
}
|
||||
|
||||
SafeRelease(rectangle);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateTextFormat(IDWriteTextFormat ** text_format, const Font & font) const
|
||||
{
|
||||
if (!d2d.DWriteFactory)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return d2d.DWriteFactory->CreateTextFormat(
|
||||
font.family.c_str(),
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT(font.weight),
|
||||
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
font.size,
|
||||
L"",
|
||||
text_format
|
||||
);
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateTextLayout(IDWriteTextLayout ** text_layout, const String & text, IDWriteTextFormat * text_format, float wrap_width) const
|
||||
{
|
||||
if (!d2d.DWriteFactory)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
UINT32 length = static_cast<UINT32>(text.length());
|
||||
return d2d.DWriteFactory->CreateTextLayout(
|
||||
text.c_str(),
|
||||
length,
|
||||
text_format,
|
||||
wrap_width,
|
||||
0,
|
||||
text_layout
|
||||
);
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateLayer(ID2D1Layer ** layer)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return d2d.HwndRenderTarget->CreateLayer(layer);
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::DrawGeometry(
|
||||
ID2D1Geometry * geometry,
|
||||
const Color & border_color,
|
||||
float opacity,
|
||||
float stroke_width,
|
||||
StrokeStyle stroke
|
||||
)
|
||||
{
|
||||
if (!d2d.SolidColorBrush ||
|
||||
!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.SolidColorBrush->SetColor(border_color);
|
||||
d2d.SolidColorBrush->SetOpacity(opacity);
|
||||
d2d.HwndRenderTarget->DrawGeometry(
|
||||
geometry,
|
||||
d2d.SolidColorBrush,
|
||||
stroke_width,
|
||||
GetStrokeStyle(stroke)
|
||||
);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ID2D1StrokeStyle * GraphicsDevice::GetStrokeStyle(StrokeStyle stroke) const
|
||||
{
|
||||
ID2D1StrokeStyle * stroke_style = nullptr;
|
||||
switch (stroke)
|
||||
{
|
||||
case StrokeStyle::Miter:
|
||||
stroke_style = d2d.MiterStrokeStyle;
|
||||
break;
|
||||
case StrokeStyle::Bevel:
|
||||
stroke_style = d2d.BevelStrokeStyle;
|
||||
break;
|
||||
case StrokeStyle::Round:
|
||||
stroke_style = d2d.RoundStrokeStyle;
|
||||
break;
|
||||
}
|
||||
return stroke_style;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::DrawImage(
|
||||
Image * image,
|
||||
float opacity,
|
||||
const Rect & dest_rect,
|
||||
const Rect & source_rect
|
||||
)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->DrawBitmap(
|
||||
image->GetBitmap(),
|
||||
dest_rect,
|
||||
opacity,
|
||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
||||
source_rect
|
||||
);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::DrawTextLayout(IDWriteTextLayout * text_layout)
|
||||
{
|
||||
if (!d2d.TextRenderer)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return text_layout->Draw(nullptr, d2d.TextRenderer, 0, 0);
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->SetTransform(clip_matrix);
|
||||
d2d.HwndRenderTarget->PushAxisAlignedClip(
|
||||
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||
);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::PopClip()
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->PopAxisAlignedClip();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::PushLayer(ID2D1Layer * layer, LayerProperties properties)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget ||
|
||||
!d2d.SolidColorBrush)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->PushLayer(
|
||||
D2D1::LayerParameters(
|
||||
properties.area,
|
||||
nullptr,
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
||||
D2D1::Matrix3x2F::Identity(),
|
||||
properties.opacity,
|
||||
d2d.SolidColorBrush,
|
||||
D2D1_LAYER_OPTIONS_NONE
|
||||
),
|
||||
layer
|
||||
);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::PopLayer()
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->PopLayer();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateBitmapFromFile(const String & file_path, ID2D1Bitmap ** bitmap)
|
||||
{
|
||||
if (d2d.WICImagingFactory == nullptr ||
|
||||
d2d.HwndRenderTarget == nullptr)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (bitmap == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
IWICFormatConverter* converter = nullptr;
|
||||
|
||||
// 创建解码器
|
||||
HRESULT hr = d2d.WICImagingFactory->CreateDecoderFromFilename(
|
||||
file_path.c_str(),
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
hr = d2d.WICImagingFactory->CreateFormatConverter(&converter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = converter->Initialize(
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap(
|
||||
converter,
|
||||
nullptr,
|
||||
bitmap
|
||||
);
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(decoder);
|
||||
SafeRelease(source);
|
||||
SafeRelease(stream);
|
||||
SafeRelease(converter);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::CreateBitmapFromResource(Resource & res, ID2D1Bitmap ** bitmap)
|
||||
{
|
||||
if (d2d.WICImagingFactory == nullptr ||
|
||||
d2d.HwndRenderTarget == nullptr)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (bitmap == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
IWICFormatConverter* converter = nullptr;
|
||||
|
||||
// 加载资源
|
||||
hr = res.Load() ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = d2d.WICImagingFactory->CreateStream(&stream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = stream->InitializeFromMemory(
|
||||
static_cast<WICInProcPointer>(res.GetData()),
|
||||
res.GetDataSize()
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = d2d.WICImagingFactory->CreateDecoderFromStream(
|
||||
stream,
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
hr = d2d.WICImagingFactory->CreateFormatConverter(&converter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = converter->Initialize(
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap(
|
||||
converter,
|
||||
nullptr,
|
||||
bitmap
|
||||
);
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(decoder);
|
||||
SafeRelease(source);
|
||||
SafeRelease(stream);
|
||||
SafeRelease(converter);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->Resize(D2D1::SizeU(width, height));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.HwndRenderTarget->SetTransform(matrix);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::SetBrushOpacity(float opacity)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.SolidColorBrush->SetOpacity(opacity);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GraphicsDevice::SetTextStyle(
|
||||
const Color & color,
|
||||
bool has_outline,
|
||||
const Color & outline_color,
|
||||
float outline_width,
|
||||
StrokeStyle outline_stroke
|
||||
)
|
||||
{
|
||||
if (!d2d.TextRenderer)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
d2d.TextRenderer->SetTextStyle(
|
||||
color,
|
||||
has_outline,
|
||||
outline_color,
|
||||
outline_width,
|
||||
static_cast<D2D1_LINE_JOIN>(outline_stroke)
|
||||
);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void GraphicsDevice::SetBackgroundColor(const Color& color)
|
||||
{
|
||||
clear_color_ = color;
|
||||
|
|
@ -231,7 +590,7 @@ namespace easy2d
|
|||
if (!fps_text_format_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextFormat(
|
||||
d2d.DWriteFactory->CreateTextFormat(
|
||||
L"",
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT_NORMAL,
|
||||
|
|
@ -262,7 +621,7 @@ namespace easy2d
|
|||
SafeRelease(fps_text_layout_);
|
||||
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
d2d.DWriteFactory->CreateTextLayout(
|
||||
fps_text,
|
||||
static_cast<UINT32>(len),
|
||||
fps_text_format_,
|
||||
|
|
@ -275,9 +634,9 @@ namespace easy2d
|
|||
|
||||
if (fps_text_layout_)
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.0f);
|
||||
render::D2D.TextRenderer->SetTextStyle(
|
||||
d2d.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
d2d.SolidColorBrush->SetOpacity(1.0f);
|
||||
d2d.TextRenderer->SetTextStyle(
|
||||
D2D1::ColorF(D2D1::ColorF::White),
|
||||
TRUE,
|
||||
D2D1::ColorF(D2D1::ColorF::Black, 0.4f),
|
||||
|
|
@ -285,7 +644,56 @@ namespace easy2d
|
|||
D2D1_LINE_JOIN_ROUND
|
||||
);
|
||||
|
||||
fps_text_layout_->Draw(nullptr, render::D2D.TextRenderer, 10, 0);
|
||||
fps_text_layout_->Draw(nullptr, d2d.TextRenderer, 10, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsDevice::CreateDeviceResources(HWND hwnd)
|
||||
{
|
||||
if (!d2d.HwndRenderTarget)
|
||||
{
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
|
||||
D2D1_SIZE_U size = D2D1::SizeU(
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top
|
||||
);
|
||||
|
||||
// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
|
||||
// 创建一个 Direct2D 渲染目标
|
||||
ThrowIfFailed(
|
||||
d2d.Factory->CreateHwndRenderTarget(
|
||||
D2D1::RenderTargetProperties(),
|
||||
D2D1::HwndRenderTargetProperties(
|
||||
hwnd,
|
||||
size,
|
||||
D2D1_PRESENT_OPTIONS_NONE),
|
||||
&d2d.HwndRenderTarget
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!d2d.SolidColorBrush)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
d2d.HwndRenderTarget->CreateSolidColorBrush(
|
||||
D2D1::ColorF(D2D1::ColorF::White),
|
||||
&d2d.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!d2d.TextRenderer)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
ITextRenderer::Create(
|
||||
&d2d.TextRenderer,
|
||||
d2d.Factory,
|
||||
d2d.HwndRenderTarget,
|
||||
d2d.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@
|
|||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "Font.h"
|
||||
#include "Resource.h"
|
||||
#include "Image.h"
|
||||
#include "TextRenderer.h"
|
||||
#include "../math/Matrix.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -37,15 +41,13 @@ namespace easy2d
|
|||
ID2D1StrokeStyle* MiterStrokeStyle;
|
||||
ID2D1StrokeStyle* BevelStrokeStyle;
|
||||
ID2D1StrokeStyle* RoundStrokeStyle;
|
||||
} _D2D_Resource;
|
||||
} D2DResources;
|
||||
|
||||
extern _D2D_Resource D2D;
|
||||
|
||||
void Initialize(HWND hwnd);
|
||||
|
||||
void CreateDeviceResources(HWND hwnd);
|
||||
|
||||
void Uninitialize();
|
||||
typedef struct
|
||||
{
|
||||
Rect area;
|
||||
float opacity;
|
||||
} LayerProperties;
|
||||
|
||||
class GraphicsDevice
|
||||
{
|
||||
|
|
@ -54,24 +56,121 @@ namespace easy2d
|
|||
|
||||
~GraphicsDevice();
|
||||
|
||||
void Initialize(HWND hwnd);
|
||||
|
||||
void Uninitialize();
|
||||
|
||||
// ¿ªÊ¼äÖȾ
|
||||
void BeginDraw(HWND hwnd);
|
||||
|
||||
// ½áÊøäÖȾ
|
||||
void EndDraw();
|
||||
|
||||
// 渲染调试信息
|
||||
void DrawDebugInfo();
|
||||
|
||||
// ÉèÖñ³¾°É«
|
||||
void SetBackgroundColor(
|
||||
const Color& color
|
||||
);
|
||||
|
||||
// äÖȾµ÷ÊÔÐÅÏ¢
|
||||
void DrawDebugInfo();
|
||||
|
||||
void CreateDeviceResources(HWND hwnd);
|
||||
|
||||
HRESULT CreateRectGeometry(
|
||||
const math::Matrix& matrix,
|
||||
const Size& size,
|
||||
ID2D1Geometry** geometry
|
||||
) const;
|
||||
|
||||
HRESULT CreateTextFormat(
|
||||
IDWriteTextFormat** text_format,
|
||||
const Font& font
|
||||
) const;
|
||||
|
||||
HRESULT CreateTextLayout(
|
||||
IDWriteTextLayout** text_layout,
|
||||
const String& text,
|
||||
IDWriteTextFormat* text_format,
|
||||
float wrap_width
|
||||
) const;
|
||||
|
||||
HRESULT CreateLayer(
|
||||
ID2D1Layer** layer
|
||||
);
|
||||
|
||||
ID2D1StrokeStyle* GetStrokeStyle(
|
||||
StrokeStyle stroke
|
||||
) const;
|
||||
|
||||
HRESULT SetTransform(
|
||||
const math::Matrix& matrix
|
||||
);
|
||||
|
||||
HRESULT SetBrushOpacity(
|
||||
float opacity
|
||||
);
|
||||
|
||||
HRESULT SetTextStyle(
|
||||
const Color& color,
|
||||
bool has_outline,
|
||||
const Color& outline_color,
|
||||
float outline_width,
|
||||
StrokeStyle outline_stroke
|
||||
);
|
||||
|
||||
HRESULT DrawGeometry(
|
||||
ID2D1Geometry* geometry,
|
||||
const Color& border_color,
|
||||
float opacity,
|
||||
float stroke_width,
|
||||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
HRESULT DrawImage(
|
||||
Image* image,
|
||||
float opacity,
|
||||
const Rect& dest_rect,
|
||||
const Rect& source_rect
|
||||
);
|
||||
|
||||
HRESULT DrawTextLayout(
|
||||
IDWriteTextLayout* text_layout
|
||||
);
|
||||
|
||||
HRESULT PushClip(
|
||||
const math::Matrix& clip_matrix,
|
||||
const Size& clip_size
|
||||
);
|
||||
|
||||
HRESULT PopClip();
|
||||
|
||||
HRESULT PushLayer(
|
||||
ID2D1Layer* layer,
|
||||
LayerProperties properties
|
||||
);
|
||||
|
||||
HRESULT PopLayer();
|
||||
|
||||
HRESULT CreateBitmapFromFile(
|
||||
const String& file_path,
|
||||
ID2D1Bitmap** bitmap
|
||||
);
|
||||
|
||||
HRESULT CreateBitmapFromResource(
|
||||
Resource& res,
|
||||
ID2D1Bitmap** bitmap
|
||||
);
|
||||
|
||||
HRESULT Resize(
|
||||
UINT32 width,
|
||||
UINT32 height
|
||||
);
|
||||
|
||||
protected:
|
||||
D2D1_COLOR_F clear_color_;
|
||||
IDWriteTextFormat* fps_text_format_;
|
||||
IDWriteTextLayout* fps_text_layout_;
|
||||
D2DResources d2d;
|
||||
};
|
||||
|
||||
extern GraphicsDevice instance;
|
||||
|
|
|
|||
|
|
@ -173,21 +173,16 @@ namespace easy2d
|
|||
|
||||
std::wstring easy2d::time::Duration::ToString() const
|
||||
{
|
||||
std::wstring result;
|
||||
int64_t ms = milliseconds_ % Second.milliseconds_;
|
||||
int64_t sec = milliseconds_ / Second.milliseconds_;
|
||||
int64_t min = milliseconds_ / Minute.milliseconds_;
|
||||
int64_t hour = milliseconds_ / Hour.milliseconds_;
|
||||
|
||||
min -= hour * 60;
|
||||
sec -= (hour * 60 * 60 + min * 60);
|
||||
|
||||
auto float_to_str = [](float val) -> std::wstring
|
||||
if (milliseconds_ == 0LL)
|
||||
{
|
||||
wchar_t buf[10] = {};
|
||||
::swprintf_s(buf, L"%.2f", val);
|
||||
return std::wstring(buf);
|
||||
};
|
||||
return std::wstring(L"0s");
|
||||
}
|
||||
|
||||
std::wstring result;
|
||||
int64_t hour = milliseconds_ / Hour.milliseconds_;
|
||||
int64_t min = milliseconds_ / Minute.milliseconds_ - hour * 60;
|
||||
int64_t sec = milliseconds_ / Second.milliseconds_ - (hour * 60 * 60 + min * 60);
|
||||
int64_t ms = milliseconds_ % Second.milliseconds_;
|
||||
|
||||
if (milliseconds_ < 0)
|
||||
result.append(L"-");
|
||||
|
|
@ -202,19 +197,22 @@ namespace easy2d
|
|||
result.append(std::to_wstring(min)).append(L"m");
|
||||
}
|
||||
|
||||
if (sec == 0 && ms == 0)
|
||||
{
|
||||
result.append(L"0s");
|
||||
}
|
||||
else if (ms == 0)
|
||||
{
|
||||
result.append(std::to_wstring(sec)).append(L"s");
|
||||
}
|
||||
else
|
||||
if (ms != 0)
|
||||
{
|
||||
auto float_to_str = [](float val) -> std::wstring
|
||||
{
|
||||
wchar_t buf[10] = {};
|
||||
::swprintf_s(buf, L"%.2f", val);
|
||||
return std::wstring(buf);
|
||||
};
|
||||
|
||||
result.append(float_to_str(static_cast<float>(sec) + static_cast<float>(ms) / 1000.f))
|
||||
.append(L"s");
|
||||
}
|
||||
else if (sec != 0)
|
||||
{
|
||||
result.append(std::to_wstring(sec)).append(L"s");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,11 +306,7 @@ namespace easy2d
|
|||
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
|
||||
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
|
||||
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
if (render_target)
|
||||
{
|
||||
render_target->Resize(D2D1::SizeU(width, height));
|
||||
}
|
||||
render::instance.Resize(width, height);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "vector.hpp"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -73,6 +74,15 @@ namespace easy2d
|
|||
);
|
||||
}
|
||||
|
||||
inline operator D2D1_MATRIX_3X2_F () const
|
||||
{
|
||||
return D2D1_MATRIX_3X2_F{
|
||||
_11, _12,
|
||||
_21, _22,
|
||||
_31, _32
|
||||
};
|
||||
}
|
||||
|
||||
inline Matrix& Identity()
|
||||
{
|
||||
_11 = 1.f;
|
||||
|
|
@ -90,12 +100,24 @@ namespace easy2d
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Translate(float x, float y)
|
||||
{
|
||||
*this = *this * Matrix::Translation(x, y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Scale(const Vector2& v, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Scaling(v, center);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Scale(float xscale, float yscale, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Scaling(xscale, yscale, center);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Rotate(float angle, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Rotation(angle, center);
|
||||
|
|
|
|||
|
|
@ -37,25 +37,13 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
Transform::operator D2D1::Matrix3x2F() const
|
||||
Matrix Transform::ToMatrix() const
|
||||
{
|
||||
auto pivot = D2D1::Point2F(size.width * pivot_x, size.height * pivot_y);
|
||||
auto matrix = D2D1::Matrix3x2F::Scale(
|
||||
scale_x,
|
||||
scale_y,
|
||||
pivot
|
||||
) * D2D1::Matrix3x2F::Skew(
|
||||
skew_x,
|
||||
skew_y,
|
||||
pivot
|
||||
) * D2D1::Matrix3x2F::Rotation(
|
||||
rotation,
|
||||
pivot
|
||||
) * D2D1::Matrix3x2F::Translation(
|
||||
position.x - pivot.x,
|
||||
position.y - pivot.y
|
||||
);
|
||||
return matrix;
|
||||
auto pivot = Vector2(size.width * pivot_x, size.height * pivot_y);
|
||||
return Matrix().Scale(scale_x, scale_y, pivot)
|
||||
.Skew(skew_x, skew_y, pivot)
|
||||
.Rotate(rotation, pivot)
|
||||
.Translate(position - pivot);
|
||||
}
|
||||
|
||||
bool Transform::operator==(const Transform & other) const
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#pragma once
|
||||
#include "../base/BaseTypes.h"
|
||||
#include "../base/Size.h"
|
||||
#include <d2d1.h>
|
||||
#include "Matrix.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -43,7 +43,7 @@ namespace easy2d
|
|||
public:
|
||||
Transform();
|
||||
|
||||
explicit operator D2D1::Matrix3x2F() const;
|
||||
Matrix ToMatrix() const;
|
||||
|
||||
bool operator== (const Transform& other) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "scalar.hpp"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -85,6 +86,11 @@ namespace easy2d
|
|||
{
|
||||
return Vector2(x - v.x, y - v.y).Length();
|
||||
}
|
||||
|
||||
inline operator D2D1_POINT_2F () const
|
||||
{
|
||||
return D2D1_POINT_2F{ x, y };
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue