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_) | ||||
| 		{ | ||||
|  | @ -221,25 +211,9 @@ 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