update: modern singleton pattern
This commit is contained in:
		
							parent
							
								
									2b366e42be
								
							
						
					
					
						commit
						d2532c09db
					
				|  | @ -38,6 +38,8 @@ namespace easy2d | ||||||
| 		friend class Sequence; | 		friend class Sequence; | ||||||
| 		friend class Spawn; | 		friend class Spawn; | ||||||
| 
 | 
 | ||||||
|  | 		E2D_DISABLE_COPY(Action); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Action(); | 		Action(); | ||||||
| 
 | 
 | ||||||
|  | @ -92,9 +94,6 @@ namespace easy2d | ||||||
| 		// 获取动作结束状态
 | 		// 获取动作结束状态
 | ||||||
| 		virtual bool IsDone() const; | 		virtual bool IsDone() const; | ||||||
| 
 | 
 | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(Action); |  | ||||||
| 
 |  | ||||||
| 	protected: | 	protected: | ||||||
| 		String			name_; | 		String			name_; | ||||||
| 		bool			running_; | 		bool			running_; | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ namespace easy2d | ||||||
| 	// Loop
 | 	// Loop
 | ||||||
| 	//-------------------------------------------------------
 | 	//-------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| 	Loop::Loop(Action * action, int times /* = -1 */) | 	Loop::Loop(Action * action, int times) | ||||||
| 		: action_(action) | 		: action_(action) | ||||||
| 		, times_(0) | 		, times_(0) | ||||||
| 		, total_times_(times) | 		, total_times_(times) | ||||||
|  |  | ||||||
|  | @ -27,6 +27,8 @@ namespace easy2d | ||||||
| 	class Loop | 	class Loop | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Loop); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit Loop( | 		explicit Loop( | ||||||
| 			Action * action,	/* 执行循环的动作 */ | 			Action * action,	/* 执行循环的动作 */ | ||||||
|  | @ -45,8 +47,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Loop); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -67,6 +67,8 @@ namespace easy2d | ||||||
| 	class Sequence | 	class Sequence | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Sequence); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		typedef std::vector<Action*> Actions; | 		typedef std::vector<Action*> Actions; | ||||||
| 
 | 
 | ||||||
|  | @ -98,8 +100,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Sequence); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -119,6 +119,8 @@ namespace easy2d | ||||||
| 	class Spawn | 	class Spawn | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Spawn); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		typedef std::vector<Action*> Actions; | 		typedef std::vector<Action*> Actions; | ||||||
| 
 | 
 | ||||||
|  | @ -150,8 +152,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Spawn); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,6 +27,8 @@ namespace easy2d | ||||||
| 	class FiniteTimeAction | 	class FiniteTimeAction | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(FiniteTimeAction); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		// 创建特定时长的持续动作
 | 		// 创建特定时长的持续动作
 | ||||||
| 		explicit FiniteTimeAction( | 		explicit FiniteTimeAction( | ||||||
|  | @ -37,8 +39,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(FiniteTimeAction); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -58,6 +58,8 @@ namespace easy2d | ||||||
| 	class MoveBy | 	class MoveBy | ||||||
| 		: public FiniteTimeAction | 		: public FiniteTimeAction | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(MoveBy); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit MoveBy( | 		explicit MoveBy( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -71,8 +73,6 @@ namespace easy2d | ||||||
| 		virtual MoveBy * Reverse() const override; | 		virtual MoveBy * Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(MoveBy); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -90,6 +90,8 @@ namespace easy2d | ||||||
| 	class MoveTo | 	class MoveTo | ||||||
| 		: public MoveBy | 		: public MoveBy | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(MoveTo); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit MoveTo( | 		explicit MoveTo( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -107,8 +109,6 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(MoveTo); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -121,6 +121,8 @@ namespace easy2d | ||||||
| 	class JumpBy | 	class JumpBy | ||||||
| 		: public FiniteTimeAction | 		: public FiniteTimeAction | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(JumpBy); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit JumpBy( | 		explicit JumpBy( | ||||||
| 			float duration,			/* 持续时长 */ | 			float duration,			/* 持续时长 */ | ||||||
|  | @ -136,8 +138,6 @@ namespace easy2d | ||||||
| 		virtual JumpBy * Reverse() const override; | 		virtual JumpBy * Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(JumpBy); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -157,6 +157,8 @@ namespace easy2d | ||||||
| 	class JumpTo | 	class JumpTo | ||||||
| 		: public JumpBy | 		: public JumpBy | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(JumpTo); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit JumpTo( | 		explicit JumpTo( | ||||||
| 			float duration,			/* 持续时长 */ | 			float duration,			/* 持续时长 */ | ||||||
|  | @ -176,8 +178,6 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(JumpTo); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -190,6 +190,8 @@ namespace easy2d | ||||||
| 	class ScaleBy | 	class ScaleBy | ||||||
| 		: public FiniteTimeAction | 		: public FiniteTimeAction | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(ScaleBy); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit ScaleBy( | 		explicit ScaleBy( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -209,8 +211,6 @@ namespace easy2d | ||||||
| 		virtual ScaleBy * Reverse() const override; | 		virtual ScaleBy * Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(ScaleBy); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -229,6 +229,8 @@ namespace easy2d | ||||||
| 	class ScaleTo | 	class ScaleTo | ||||||
| 		: public ScaleBy | 		: public ScaleBy | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(ScaleTo); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit ScaleTo( | 		explicit ScaleTo( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -252,8 +254,6 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(ScaleTo); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -267,6 +267,8 @@ namespace easy2d | ||||||
| 	class OpacityBy | 	class OpacityBy | ||||||
| 		: public FiniteTimeAction | 		: public FiniteTimeAction | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(OpacityBy); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit OpacityBy( | 		explicit OpacityBy( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -280,8 +282,6 @@ namespace easy2d | ||||||
| 		virtual OpacityBy * Reverse() const override; | 		virtual OpacityBy * Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(OpacityBy); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -298,6 +298,8 @@ namespace easy2d | ||||||
| 	class OpacityTo | 	class OpacityTo | ||||||
| 		: public OpacityBy | 		: public OpacityBy | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(OpacityTo); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit OpacityTo( | 		explicit OpacityTo( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -315,8 +317,6 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(OpacityTo); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -329,14 +329,13 @@ namespace easy2d | ||||||
| 	class FadeIn | 	class FadeIn | ||||||
| 		: public OpacityTo | 		: public OpacityTo | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(FadeIn); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		// 创建淡入动作
 | 		// 创建淡入动作
 | ||||||
| 		explicit FadeIn( | 		explicit FadeIn( | ||||||
| 			float duration		/* 持续时长 */ | 			float duration		/* 持续时长 */ | ||||||
| 		); | 		); | ||||||
| 
 |  | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(FadeIn); |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -344,14 +343,13 @@ namespace easy2d | ||||||
| 	class FadeOut | 	class FadeOut | ||||||
| 		: public OpacityTo | 		: public OpacityTo | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(FadeOut); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		// 创建淡出动作
 | 		// 创建淡出动作
 | ||||||
| 		explicit FadeOut( | 		explicit FadeOut( | ||||||
| 			float duration		/* 持续时长 */ | 			float duration		/* 持续时长 */ | ||||||
| 		); | 		); | ||||||
| 
 |  | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(FadeOut); |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -359,6 +357,8 @@ namespace easy2d | ||||||
| 	class RotateBy | 	class RotateBy | ||||||
| 		: public FiniteTimeAction | 		: public FiniteTimeAction | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(RotateBy); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit RotateBy( | 		explicit RotateBy( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -372,8 +372,6 @@ namespace easy2d | ||||||
| 		virtual RotateBy * Reverse() const override; | 		virtual RotateBy * Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(RotateBy); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -390,6 +388,8 @@ namespace easy2d | ||||||
| 	class RotateTo | 	class RotateTo | ||||||
| 		: public RotateBy | 		: public RotateBy | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(RotateTo); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit RotateTo( | 		explicit RotateTo( | ||||||
| 			float duration,		/* 持续时长 */ | 			float duration,		/* 持续时长 */ | ||||||
|  | @ -407,8 +407,6 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(RotateTo); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  | @ -421,6 +419,8 @@ namespace easy2d | ||||||
| 	class Delay | 	class Delay | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Delay); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		explicit Delay( | 		explicit Delay( | ||||||
| 			float duration	/* 延迟时长(秒) */ | 			float duration	/* 延迟时长(秒) */ | ||||||
|  | @ -436,8 +436,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Delay); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace easy2d | ||||||
| 	class Animation | 	class Animation | ||||||
| 		: public RefCounter | 		: public RefCounter | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Animation); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		typedef std::vector<Image*> Images; | 		typedef std::vector<Image*> Images; | ||||||
| 
 | 
 | ||||||
|  | @ -75,9 +77,6 @@ namespace easy2d | ||||||
| 		// 获取帧动画的倒转
 | 		// 获取帧动画的倒转
 | ||||||
| 		Animation * Reverse() const; | 		Animation * Reverse() const; | ||||||
| 
 | 
 | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(Animation); |  | ||||||
| 
 |  | ||||||
| 	protected: | 	protected: | ||||||
| 		float	interval_; | 		float	interval_; | ||||||
| 		Images	frames_; | 		Images	frames_; | ||||||
|  | @ -88,6 +87,8 @@ namespace easy2d | ||||||
| 	class Animate | 	class Animate | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Animate); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Animate(); | 		Animate(); | ||||||
| 
 | 
 | ||||||
|  | @ -115,8 +116,6 @@ namespace easy2d | ||||||
| 		virtual void Reset() override; | 		virtual void Reset() override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Animate); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ | ||||||
| #include "../math/vector.hpp" | #include "../math/vector.hpp" | ||||||
| #include "Color.h" | #include "Color.h" | ||||||
| #include "Size.h" | #include "Size.h" | ||||||
|  | #include "Rect.hpp" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
|  | @ -33,9 +34,9 @@ namespace easy2d | ||||||
| 	//     计算两点间距离: float distance = p1.Distance(p2);
 | 	//     计算两点间距离: float distance = p1.Distance(p2);
 | ||||||
| 	//     坐标可以相加减: Point p = Point(10, 10) + Point(20, 20);  // p 的坐标是 (30, 30)
 | 	//     坐标可以相加减: Point p = Point(10, 10) + Point(20, 20);  // p 的坐标是 (30, 30)
 | ||||||
| 	//
 | 	//
 | ||||||
| 	typedef math::Vector2 Point; | 	using Point = math::Vector2; | ||||||
| 
 | 
 | ||||||
| 	typedef std::wstring String; | 	using String = std::wstring; | ||||||
| 
 | 
 | ||||||
| 	// 方向
 | 	// 方向
 | ||||||
| 	enum class Direction : int | 	enum class Direction : int | ||||||
|  | @ -138,4 +139,11 @@ namespace easy2d | ||||||
| 		Right	= VK_RBUTTON,	/* 鼠标右键 */ | 		Right	= VK_RBUTTON,	/* 鼠标右键 */ | ||||||
| 		Middle	= VK_MBUTTON	/* 鼠标中键 */ | 		Middle	= VK_MBUTTON	/* 鼠标中键 */ | ||||||
| 	}; | 	}; | ||||||
|  | 
 | ||||||
|  | 	// 图层属性
 | ||||||
|  | 	struct LayerProperties | ||||||
|  | 	{ | ||||||
|  | 		Rect area; | ||||||
|  | 		float opacity; | ||||||
|  | 	}; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace easy2d | ||||||
| 	class CallFunc | 	class CallFunc | ||||||
| 		: public Action | 		: public Action | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(CallFunc); | ||||||
|  | 
 | ||||||
| 		typedef std::function<void()> Callback; | 		typedef std::function<void()> Callback; | ||||||
| 
 | 
 | ||||||
| 	  public: | 	  public: | ||||||
|  | @ -42,8 +44,6 @@ namespace easy2d | ||||||
| 		virtual CallFunc *Reverse() const override; | 		virtual CallFunc *Reverse() const override; | ||||||
| 
 | 
 | ||||||
| 	  protected: | 	  protected: | ||||||
| 		E2D_DISABLE_COPY(CallFunc); |  | ||||||
| 
 |  | ||||||
| 		// 初始化动作
 | 		// 初始化动作
 | ||||||
| 		virtual void Initialize() override; | 		virtual void Initialize() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -88,7 +88,7 @@ namespace easy2d | ||||||
| 	{ | 	{ | ||||||
| 		SafeRelease(stroke_style_); | 		SafeRelease(stroke_style_); | ||||||
| 
 | 
 | ||||||
| 		stroke_style_ = render::instance.GetStrokeStyle(stroke); | 		stroke_style_ = devices::Graphics::Instance().GetStrokeStyle(stroke); | ||||||
| 
 | 
 | ||||||
| 		if (stroke_style_) | 		if (stroke_style_) | ||||||
| 			stroke_style_->AddRef(); | 			stroke_style_->AddRef(); | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace easy2d | ||||||
| 	class Canvas | 	class Canvas | ||||||
| 		: public Node | 		: public Node | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Canvas); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Canvas( | 		Canvas( | ||||||
| 			float width, | 			float width, | ||||||
|  | @ -124,12 +126,9 @@ namespace easy2d | ||||||
| 			float radius_y | 			float radius_y | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 	private: |  | ||||||
| 		E2D_DISABLE_COPY(Canvas); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		float					stroke_width_; | 		float					stroke_width_; | ||||||
| 		StrokeStyle					stroke_; | 		StrokeStyle				stroke_; | ||||||
| 		ID2D1RenderTarget*		render_target_; | 		ID2D1RenderTarget*		render_target_; | ||||||
| 		ID2D1SolidColorBrush*	fill_brush_; | 		ID2D1SolidColorBrush*	fill_brush_; | ||||||
| 		ID2D1SolidColorBrush*	line_brush_; | 		ID2D1SolidColorBrush*	line_brush_; | ||||||
|  |  | ||||||
|  | @ -34,16 +34,6 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace |  | ||||||
| 	{ |  | ||||||
| 		Game * instance = nullptr; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Game * Game::GetInstance() |  | ||||||
| 	{ |  | ||||||
| 		return instance; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Game::Game() | 	Game::Game() | ||||||
| 		: quit_(true) | 		: quit_(true) | ||||||
| 		, curr_scene_(nullptr) | 		, curr_scene_(nullptr) | ||||||
|  | @ -51,12 +41,6 @@ namespace easy2d | ||||||
| 		, transition_(nullptr) | 		, transition_(nullptr) | ||||||
| 		, debug_mode_(false) | 		, debug_mode_(false) | ||||||
| 	{ | 	{ | ||||||
| 		if (instance) |  | ||||||
| 		{ |  | ||||||
| 			throw std::runtime_error("同时只能存在一个游戏实例"); |  | ||||||
| 		} |  | ||||||
| 		instance = this; |  | ||||||
| 
 |  | ||||||
| 		::CoInitialize(nullptr); | 		::CoInitialize(nullptr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -66,25 +50,14 @@ namespace easy2d | ||||||
| 		SafeRelease(curr_scene_); | 		SafeRelease(curr_scene_); | ||||||
| 		SafeRelease(next_scene_); | 		SafeRelease(next_scene_); | ||||||
| 
 | 
 | ||||||
| 		Image::ClearCache(); |  | ||||||
| 		Player::ClearCache(); |  | ||||||
| 
 |  | ||||||
| 		render::instance.Uninitialize(); |  | ||||||
| 		audio::instance.Uninitialize(); |  | ||||||
| 		window::instance.Destroy(); |  | ||||||
| 		modules::Uninitialize(); |  | ||||||
| 
 |  | ||||||
| 		instance = nullptr; |  | ||||||
| 
 |  | ||||||
| 		::CoUninitialize(); | 		::CoUninitialize(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Game::Initialize(const window::Property& property) | 	void Game::Initialize(const Options& options) | ||||||
| 	{ | 	{ | ||||||
| 		modules::Initialize(); | 		Window::Instance().Initialize(options.title, options.width, options.height, options.icon, options.debug); | ||||||
| 		window::instance.Initialize(property); | 		devices::Graphics::Instance().Initialize(Window::Instance().GetHandle()); | ||||||
| 		render::instance.Initialize(window::instance.handle); | 		devices::Audio::Instance().Initialize(); | ||||||
| 		audio::instance.Initialize(); |  | ||||||
| 
 | 
 | ||||||
| 		// 若开启了调试模式,打开控制台
 | 		// 若开启了调试模式,打开控制台
 | ||||||
| 		HWND console = ::GetConsoleWindow(); | 		HWND console = ::GetConsoleWindow(); | ||||||
|  | @ -117,7 +90,7 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		::SetWindowLongPtrW( | 		::SetWindowLongPtrW( | ||||||
| 			window::instance.handle, | 			Window::Instance().GetHandle(), | ||||||
| 			GWLP_USERDATA, | 			GWLP_USERDATA, | ||||||
| 			PtrToUlong(this) | 			PtrToUlong(this) | ||||||
| 		); | 		); | ||||||
|  | @ -134,8 +107,8 @@ namespace easy2d | ||||||
| 			next_scene_ = nullptr; | 			next_scene_ = nullptr; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		::ShowWindow(window::instance.handle, SW_SHOWNORMAL); | 		::ShowWindow(Window::Instance().GetHandle(), SW_SHOWNORMAL); | ||||||
| 		::UpdateWindow(window::instance.handle); | 		::UpdateWindow(Window::Instance().GetHandle()); | ||||||
| 
 | 
 | ||||||
| 		const int64_t min_interval = 5; | 		const int64_t min_interval = 5; | ||||||
| 		auto last = time::Now(); | 		auto last = time::Now(); | ||||||
|  | @ -151,10 +124,10 @@ namespace easy2d | ||||||
| 				float dt = (now - last).Seconds(); | 				float dt = (now - last).Seconds(); | ||||||
| 				last = now; | 				last = now; | ||||||
| 
 | 
 | ||||||
| 				input::instance.Update( | 				devices::Input::Instance().Update( | ||||||
| 					window::instance.handle, | 					Window::Instance().GetHandle(), | ||||||
| 					window::instance.xscale, | 					Window::Instance().GetContentScaleX(), | ||||||
| 					window::instance.yscale | 					Window::Instance().GetContentScaleY() | ||||||
| 				); | 				); | ||||||
| 
 | 
 | ||||||
| 				OnUpdate(dt); | 				OnUpdate(dt); | ||||||
|  | @ -277,7 +250,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Game::DrawScene() | 	void Game::DrawScene() | ||||||
| 	{ | 	{ | ||||||
| 		render::instance.BeginDraw(window::instance.handle); | 		devices::Graphics::Instance().BeginDraw(Window::Instance().GetHandle()); | ||||||
| 
 | 
 | ||||||
| 		if (transition_) | 		if (transition_) | ||||||
| 		{ | 		{ | ||||||
|  | @ -292,21 +265,21 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 			if (curr_scene_ && curr_scene_->GetRoot()) | 			if (curr_scene_ && curr_scene_->GetRoot()) | ||||||
| 			{ | 			{ | ||||||
| 				render::instance.SetTransform(math::Matrix()); | 				devices::Graphics::Instance().SetTransform(math::Matrix()); | ||||||
| 				render::instance.SetBrushOpacity(1.f); | 				devices::Graphics::Instance().SetBrushOpacity(1.f); | ||||||
| 				curr_scene_->GetRoot()->DrawBorder(); | 				curr_scene_->GetRoot()->DrawBorder(); | ||||||
| 			} | 			} | ||||||
| 			if (next_scene_ && next_scene_->GetRoot()) | 			if (next_scene_ && next_scene_->GetRoot()) | ||||||
| 			{ | 			{ | ||||||
| 				render::instance.SetTransform(math::Matrix()); | 				devices::Graphics::Instance().SetTransform(math::Matrix()); | ||||||
| 				render::instance.SetBrushOpacity(1.f); | 				devices::Graphics::Instance().SetBrushOpacity(1.f); | ||||||
| 				next_scene_->GetRoot()->DrawBorder(); | 				next_scene_->GetRoot()->DrawBorder(); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			render::instance.DrawDebugInfo(); | 			devices::Graphics::Instance().DrawDebugInfo(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		render::instance.EndDraw(); | 		devices::Graphics::Instance().EndDraw(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Game::SetDebugMode(bool enabled) | 	void Game::SetDebugMode(bool enabled) | ||||||
|  |  | ||||||
|  | @ -27,12 +27,32 @@ namespace easy2d | ||||||
| 	class Scene; | 	class Scene; | ||||||
| 	class Transition; | 	class Transition; | ||||||
| 
 | 
 | ||||||
|  | 	struct Options | ||||||
|  | 	{ | ||||||
|  | 		String	title;	/* 标题 */ | ||||||
|  | 		int		width;	/* 宽度 */ | ||||||
|  | 		int		height;	/* 高度 */ | ||||||
|  | 		LPCWSTR	icon;	/* 图标 */ | ||||||
|  | 		bool	debug;	/* 调试模式 */ | ||||||
|  | 
 | ||||||
|  | 		Options() | ||||||
|  | 			: title(L"Easy2D Game") | ||||||
|  | 			, width(640) | ||||||
|  | 			, height(480) | ||||||
|  | 			, icon(nullptr) | ||||||
|  | 			, debug(false) | ||||||
|  | 		{} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	class Game | 	class Game | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Game); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Game(); | 		Game(); | ||||||
| 
 | 
 | ||||||
| 		~Game(); | 		virtual ~Game(); | ||||||
| 
 | 
 | ||||||
| 		// 更新时
 | 		// 更新时
 | ||||||
| 		virtual void OnUpdate(float dt) {} | 		virtual void OnUpdate(float dt) {} | ||||||
|  | @ -46,7 +66,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		// 初始化
 | 		// 初始化
 | ||||||
| 		void Initialize( | 		void Initialize( | ||||||
| 			const window::Property& property	/* 窗口属性 */ | 			const Options& options	/* 属性 */ | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 运行
 | 		// 运行
 | ||||||
|  | @ -80,12 +100,6 @@ namespace easy2d | ||||||
| 			float dt | 			float dt | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 获取实例
 |  | ||||||
| 		static Game * GetInstance(); |  | ||||||
| 
 |  | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(Game); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		bool		debug_mode_; | 		bool		debug_mode_; | ||||||
| 		bool		quit_; | 		bool		quit_; | ||||||
|  |  | ||||||
|  | @ -25,11 +25,6 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace |  | ||||||
| 	{ |  | ||||||
| 		std::map<size_t, ID2D1Bitmap*> bitmap_cache_; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Image::Image() | 	Image::Image() | ||||||
| 		: bitmap_(nullptr) | 		: bitmap_(nullptr) | ||||||
| 		, crop_rect_() | 		, crop_rect_() | ||||||
|  | @ -73,13 +68,12 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	bool Image::Load(Resource& res) | 	bool Image::Load(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		if (!Image::CacheBitmap(res)) | 		HRESULT hr = devices::Graphics::Instance().CreateBitmapFromResource(res, &bitmap_); | ||||||
|  | 		if (FAILED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			E2D_WARNING("Load Image from file failed!"); | 			logs::Trace(L"Load Image from resource failed!", hr); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); |  | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -87,16 +81,23 @@ namespace easy2d | ||||||
| 	{ | 	{ | ||||||
| 		E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name."); | 		E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name."); | ||||||
| 
 | 
 | ||||||
| 		if (file_name.empty()) | 		File image_file; | ||||||
| 			return false; | 		if (!image_file.Open(file_name)) | ||||||
| 
 |  | ||||||
| 		if (!Image::CacheBitmap(file_name)) |  | ||||||
| 		{ | 		{ | ||||||
| 			E2D_WARNING("Load Image from file failed!"); | 			E2D_WARNING("Image file not found!"); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		this->SetBitmap(bitmap_cache_.at(std::hash<String>{}(file_name))); | 		// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
 | ||||||
|  | 		// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
 | ||||||
|  | 		String image_file_path = image_file.GetPath(); | ||||||
|  | 
 | ||||||
|  | 		HRESULT hr = devices::Graphics::Instance().CreateBitmapFromFile(image_file_path, &bitmap_); | ||||||
|  | 		if (FAILED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			logs::Trace(L"Load Image from file failed!", hr); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -186,70 +187,6 @@ namespace easy2d | ||||||
| 		return bitmap_; | 		return bitmap_; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Image::CacheBitmap(Resource& res) |  | ||||||
| 	{ |  | ||||||
| 		size_t hash_code = res.GetHashCode(); |  | ||||||
| 		if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) |  | ||||||
| 		{ |  | ||||||
| 			return true; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		ID2D1Bitmap* bitmap = nullptr; |  | ||||||
| 		HRESULT hr = render::instance.CreateBitmapFromResource(res, &bitmap); |  | ||||||
| 
 |  | ||||||
| 		if (SUCCEEDED(hr)) |  | ||||||
| 		{ |  | ||||||
| 			bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			logs::Trace(L"CreateBitmapFromFile", hr); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return SUCCEEDED(hr); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	bool Image::CacheBitmap(const String & file_name) |  | ||||||
| 	{ |  | ||||||
| 		size_t hash_code = std::hash<String>{}(file_name); |  | ||||||
| 		if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) |  | ||||||
| 			return true; |  | ||||||
| 
 |  | ||||||
| 		File image_file; |  | ||||||
| 		if (!image_file.Open(file_name)) |  | ||||||
| 			return false; |  | ||||||
| 
 |  | ||||||
| 		// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
 |  | ||||||
| 		// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
 |  | ||||||
| 		String image_file_path = image_file.GetPath(); |  | ||||||
| 
 |  | ||||||
| 		ID2D1Bitmap* bitmap = nullptr; |  | ||||||
| 		HRESULT hr = render::instance.CreateBitmapFromFile(file_name, &bitmap); |  | ||||||
| 
 |  | ||||||
| 		if (SUCCEEDED(hr)) |  | ||||||
| 		{ |  | ||||||
| 			bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			logs::Trace(L"CreateBitmapFromFile", hr); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return SUCCEEDED(hr); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void Image::ClearCache() |  | ||||||
| 	{ |  | ||||||
| 		if (bitmap_cache_.empty()) |  | ||||||
| 			return; |  | ||||||
| 
 |  | ||||||
| 		for (const auto& bitmap : bitmap_cache_) |  | ||||||
| 		{ |  | ||||||
| 			bitmap.second->Release(); |  | ||||||
| 		} |  | ||||||
| 		bitmap_cache_.clear(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void Image::SetBitmap(ID2D1Bitmap * bitmap) | 	void Image::SetBitmap(ID2D1Bitmap * bitmap) | ||||||
| 	{ | 	{ | ||||||
| 		if (bitmap_ == bitmap) | 		if (bitmap_ == bitmap) | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ namespace easy2d | ||||||
| 	class Image | 	class Image | ||||||
| 		: public RefCounter | 		: public RefCounter | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Image); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Image(); | 		Image(); | ||||||
| 
 | 
 | ||||||
|  | @ -100,22 +102,7 @@ namespace easy2d | ||||||
| 		// 获取 ID2D1Bitmap 对象
 | 		// 获取 ID2D1Bitmap 对象
 | ||||||
| 		ID2D1Bitmap * GetBitmap() const; | 		ID2D1Bitmap * GetBitmap() const; | ||||||
| 
 | 
 | ||||||
| 		// 헌왕뻠닸
 |  | ||||||
| 		static void ClearCache(); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		E2D_DISABLE_COPY(Image); |  | ||||||
| 
 |  | ||||||
| 		// 뻠닸 Bitmap 栗都
 |  | ||||||
| 		static bool CacheBitmap( |  | ||||||
| 			const String& file_name |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		// 뻠닸 Bitmap 栗都
 |  | ||||||
| 		static bool CacheBitmap( |  | ||||||
| 			Resource& res |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		// 设置 Bitmap
 | 		// 设置 Bitmap
 | ||||||
| 		void SetBitmap( | 		void SetBitmap( | ||||||
| 			ID2D1Bitmap * bitmap | 			ID2D1Bitmap * bitmap | ||||||
|  |  | ||||||
|  | @ -22,10 +22,8 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace input | 	namespace devices | ||||||
| 	{ | 	{ | ||||||
| 		InputDevice instance; |  | ||||||
| 
 |  | ||||||
| 		InputDevice::InputDevice() | 		InputDevice::InputDevice() | ||||||
| 		{ | 		{ | ||||||
| 			ZeroMemory(keys_, sizeof(keys_)); | 			ZeroMemory(keys_, sizeof(keys_)); | ||||||
|  | @ -35,7 +33,7 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void InputDevice::Update(HWND hwnd, float xscale, float yscale) | 		void InputDevice::Update(HWND hwnd, float scale_x, float scale_y) | ||||||
| 		{ | 		{ | ||||||
| 			::GetKeyboardState(keys_); | 			::GetKeyboardState(keys_); | ||||||
| 
 | 
 | ||||||
|  | @ -43,7 +41,7 @@ namespace easy2d | ||||||
| 			::GetCursorPos(&client_cursor_pos); | 			::GetCursorPos(&client_cursor_pos); | ||||||
| 			::ScreenToClient(hwnd, &client_cursor_pos); | 			::ScreenToClient(hwnd, &client_cursor_pos); | ||||||
| 
 | 
 | ||||||
| 			mouse_pos_ = Point(client_cursor_pos.x * xscale, client_cursor_pos.y * yscale); | 			mouse_pos_ = Point(client_cursor_pos.x * scale_x, client_cursor_pos.y * scale_y); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bool InputDevice::IsDown(KeyCode code) | 		bool InputDevice::IsDown(KeyCode code) | ||||||
|  |  | ||||||
|  | @ -20,14 +20,18 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "base.h" | #include "base.h" | ||||||
|  | #include "Singleton.hpp" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace input | 	namespace devices | ||||||
| 	{ | 	{ | ||||||
| 		// 输入设备
 |  | ||||||
| 		class InputDevice | 		class InputDevice | ||||||
| 		{ | 		{ | ||||||
|  | 			E2D_DECLARE_SINGLETON(InputDevice); | ||||||
|  | 
 | ||||||
|  | 			E2D_DISABLE_COPY(InputDevice); | ||||||
|  | 
 | ||||||
| 		public: | 		public: | ||||||
| 			InputDevice(); | 			InputDevice(); | ||||||
| 
 | 
 | ||||||
|  | @ -55,8 +59,8 @@ namespace easy2d | ||||||
| 			// 刷新设备状态
 | 			// 刷新设备状态
 | ||||||
| 			void Update( | 			void Update( | ||||||
| 				HWND hwnd, | 				HWND hwnd, | ||||||
| 				float xscale, | 				float scale_x, | ||||||
| 				float yscale | 				float scale_y | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 		protected: | 		protected: | ||||||
|  | @ -64,6 +68,6 @@ namespace easy2d | ||||||
| 			Point mouse_pos_; | 			Point mouse_pos_; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		extern InputDevice instance; | 		E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -32,19 +32,19 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	float MouseEvent::GetX() const | 	float MouseEvent::GetX() const | ||||||
| 	{ | 	{ | ||||||
| 		return ((float)(short)LOWORD(l_param_)) * window::instance.xscale; | 		return ((float)(short)LOWORD(l_param_)) * Window::Instance().GetContentScaleX(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	float MouseEvent::GetY() const | 	float MouseEvent::GetY() const | ||||||
| 	{ | 	{ | ||||||
| 		return ((float)(short)HIWORD(l_param_)) * window::instance.yscale; | 		return ((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Point MouseEvent::GetPosition() const | 	Point MouseEvent::GetPosition() const | ||||||
| 	{ | 	{ | ||||||
| 		return Point( | 		return Point( | ||||||
| 			((float)(short)LOWORD(l_param_)) * window::instance.xscale, | 			((float)(short)LOWORD(l_param_)) * Window::Instance().GetContentScaleX(), | ||||||
| 			((float)(short)HIWORD(l_param_)) * window::instance.yscale | 			((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY() | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,11 +19,11 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #include "Music.h" | #include "Music.h" | ||||||
| #include "Transcoder.h" | #include "../utils/Transcoder.h" | ||||||
| #include "File.h" | #include "../utils/File.h" | ||||||
| #include "../base/modules.h" | #include "modules.h" | ||||||
| #include "../base/audio.h" | #include "audio.h" | ||||||
| #include "../base/logs.h" | #include "logs.h" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
|  | @ -71,7 +71,7 @@ namespace easy2d | ||||||
| 		File music_file; | 		File music_file; | ||||||
| 		if (!music_file.Open(file_path)) | 		if (!music_file.Open(file_path)) | ||||||
| 		{ | 		{ | ||||||
| 			E2D_WARNING("Media file not found."); | 			logs::Trace(L"Media file not found."); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -80,12 +80,14 @@ namespace easy2d | ||||||
| 		String music_file_path = music_file.GetPath(); | 		String music_file_path = music_file.GetPath(); | ||||||
| 
 | 
 | ||||||
| 		Transcoder transcoder; | 		Transcoder transcoder; | ||||||
| 		if (!transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_)) | 		HRESULT hr = transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_); | ||||||
|  | 		if (FAILED(hr)) | ||||||
| 		{ | 		{ | ||||||
|  | 			logs::Trace(L"Load media from file failed.", hr); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | 		hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||||
| 		if (FAILED(hr)) | 		if (FAILED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			if (wave_data_) | 			if (wave_data_) | ||||||
|  | @ -109,12 +111,15 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		Transcoder transcoder; | 		Transcoder transcoder; | ||||||
| 		if (!transcoder.LoadMediaResource(res, &wave_data_, &size_)) | 		HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_); | ||||||
|  | 
 | ||||||
|  | 		if (FAILED(hr)) | ||||||
| 		{ | 		{ | ||||||
|  | 			logs::Trace(L"Load media from resource failed.", hr); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | 		hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||||
| 		if (FAILED(hr)) | 		if (FAILED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			if (wave_data_) | 			if (wave_data_) | ||||||
|  | @ -134,48 +139,26 @@ namespace easy2d | ||||||
| 	{ | 	{ | ||||||
| 		if (!opened_) | 		if (!opened_) | ||||||
| 		{ | 		{ | ||||||
| 			E2D_WARNING("Music must be opened first!"); | 			logs::Trace(L"Music must be opened first!"); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (voice_ == nullptr) | 		UINT32 buffers_queued = 0; | ||||||
| 		{ | 		voice_.GetBuffersQueued(&buffers_queued); | ||||||
| 			E2D_WARNING("IXAudio2SourceVoice Null pointer exception!"); | 		if (buffers_queued) | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		XAUDIO2_VOICE_STATE state; |  | ||||||
| 		voice_->GetState(&state); |  | ||||||
| 		if (state.BuffersQueued) |  | ||||||
| 		{ |  | ||||||
| 			Stop(); | 			Stop(); | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		if (loop_count < 0) | 		if (loop_count < 0) | ||||||
| 		{ |  | ||||||
| 			loop_count = XAUDIO2_LOOP_INFINITE; | 			loop_count = XAUDIO2_LOOP_INFINITE; | ||||||
| 		} |  | ||||||
| 		else | 		else | ||||||
| 		{ |  | ||||||
| 			loop_count = std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1); | 			loop_count = std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1); | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		// Ìá½» wave Ñù±¾Êý¾Ý
 | 		HRESULT hr = voice_.Play(wave_data_, size_, static_cast<UINT32>(loop_count)); | ||||||
| 		XAUDIO2_BUFFER buffer = { 0 }; | 		if (FAILED(hr)) | ||||||
| 		buffer.pAudioData = wave_data_; |  | ||||||
| 		buffer.Flags = XAUDIO2_END_OF_STREAM; |  | ||||||
| 		buffer.AudioBytes = size_; |  | ||||||
| 		buffer.LoopCount = loop_count; |  | ||||||
| 
 |  | ||||||
| 		HRESULT hr; |  | ||||||
| 		if (FAILED(hr = voice_->SubmitSourceBuffer(&buffer))) |  | ||||||
| 		{ | 		{ | ||||||
| 			logs::Trace(L"Submitting source buffer error", hr); | 			logs::Trace(L"Submitting source buffer error", hr); | ||||||
| 			return false; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		hr = voice_->Start(0); |  | ||||||
| 
 |  | ||||||
| 		playing_ = SUCCEEDED(hr); | 		playing_ = SUCCEEDED(hr); | ||||||
| 
 | 
 | ||||||
| 		return playing_; | 		return playing_; | ||||||
|  | @ -183,48 +166,25 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Music::Pause() | 	void Music::Pause() | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		if (SUCCEEDED(voice_.Pause())) | ||||||
| 		{ | 			playing_ = false; | ||||||
| 			if (SUCCEEDED(voice_->Stop())) |  | ||||||
| 			{ |  | ||||||
| 				playing_ = false; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Music::Resume() | 	void Music::Resume() | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		if (SUCCEEDED(voice_.Resume())) | ||||||
| 		{ | 			playing_ = true; | ||||||
| 			if (SUCCEEDED(voice_->Start())) |  | ||||||
| 			{ |  | ||||||
| 				playing_ = true; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Music::Stop() | 	void Music::Stop() | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		if (SUCCEEDED(voice_.Stop())) | ||||||
| 		{ | 			playing_ = false; | ||||||
| 			if (SUCCEEDED(voice_->Stop())) |  | ||||||
| 			{ |  | ||||||
| 				voice_->ExitLoop(); |  | ||||||
| 				voice_->FlushSourceBuffers(); |  | ||||||
| 				playing_ = false; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Music::Close() | 	void Music::Close() | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		voice_.Destroy(); | ||||||
| 		{ |  | ||||||
| 			voice_->Stop(); |  | ||||||
| 			voice_->FlushSourceBuffers(); |  | ||||||
| 			voice_->DestroyVoice(); |  | ||||||
| 			voice_ = nullptr; |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		if (wave_data_) | 		if (wave_data_) | ||||||
| 		{ | 		{ | ||||||
|  | @ -238,11 +198,11 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	bool Music::IsPlaying() const | 	bool Music::IsPlaying() const | ||||||
| 	{ | 	{ | ||||||
| 		if (opened_ && voice_) | 		if (opened_) | ||||||
| 		{ | 		{ | ||||||
| 			XAUDIO2_VOICE_STATE state; | 			UINT32 buffers_queued = 0; | ||||||
| 			voice_->GetState(&state); | 			voice_.GetBuffersQueued(&buffers_queued); | ||||||
| 			if (state.BuffersQueued && playing_) | 			if (buffers_queued && playing_) | ||||||
| 				return true; | 				return true; | ||||||
| 		} | 		} | ||||||
| 		return false; | 		return false; | ||||||
|  | @ -250,27 +210,13 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	float Music::GetVolume() const | 	float Music::GetVolume() const | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		float volume = 0.f; | ||||||
| 		{ | 		voice_.GetVolume(&volume); | ||||||
| 			float volume = 0.f; | 		return volume; | ||||||
| 			voice_->GetVolume(&volume); |  | ||||||
| 			return volume; |  | ||||||
| 		} |  | ||||||
| 		return 0.f; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Music::SetVolume(float volume) | 	bool Music::SetVolume(float volume) | ||||||
| 	{ | 	{ | ||||||
| 		if (voice_) | 		return SUCCEEDED(voice_.SetVolume(volume)); | ||||||
| 		{ |  | ||||||
| 			volume = std::min(std::max(volume, -224.f), 224.f); |  | ||||||
| 			return SUCCEEDED(voice_->SetVolume(volume)); |  | ||||||
| 		} |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	IXAudio2SourceVoice * Music::GetSourceVoice() const |  | ||||||
| 	{ |  | ||||||
| 		return voice_; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -19,9 +19,10 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "../base/base.h" | #include "base.h" | ||||||
| #include "../base/RefCounter.h" | #include "audio.h" | ||||||
| #include "../base/Resource.h" | #include "RefCounter.h" | ||||||
|  | #include "Resource.h" | ||||||
| #include <xaudio2.h> | #include <xaudio2.h> | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
|  | @ -30,6 +31,8 @@ namespace easy2d | ||||||
| 	class Music | 	class Music | ||||||
| 		: public RefCounter | 		: public RefCounter | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Music); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Music(); | 		Music(); | ||||||
| 
 | 
 | ||||||
|  | @ -81,17 +84,11 @@ namespace easy2d | ||||||
| 			float volume	/* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */ | 			float volume	/* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */ | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 获取 IXAudio2SourceVoice 对象
 |  | ||||||
| 		IXAudio2SourceVoice * GetSourceVoice() const; |  | ||||||
| 
 |  | ||||||
| 	protected: | 	protected: | ||||||
| 		E2D_DISABLE_COPY(Music); | 		bool	opened_; | ||||||
| 
 | 		bool	playing_; | ||||||
| 	protected: | 		UINT32	size_; | ||||||
| 		bool					opened_; | 		BYTE*	wave_data_; | ||||||
| 		bool					playing_; | 		Voice	voice_; | ||||||
| 		UINT32					size_; |  | ||||||
| 		BYTE*					wave_data_; |  | ||||||
| 		IXAudio2SourceVoice*	voice_; |  | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
|  | @ -77,12 +77,12 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		if (clip_enabled_) | 		if (clip_enabled_) | ||||||
| 		{ | 		{ | ||||||
| 			render::instance.PushClip(final_matrix_, transform_.size); | 			devices::Graphics::Instance().PushClip(final_matrix_, transform_.size); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (children_.empty()) | 		if (children_.empty()) | ||||||
| 		{ | 		{ | ||||||
| 			render::instance.SetTransform(final_matrix_); | 			devices::Graphics::Instance().SetTransform(final_matrix_); | ||||||
| 			OnDraw(); | 			OnDraw(); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
|  | @ -114,7 +114,7 @@ namespace easy2d | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			render::instance.SetTransform(final_matrix_); | 			devices::Graphics::Instance().SetTransform(final_matrix_); | ||||||
| 			OnDraw(); | 			OnDraw(); | ||||||
| 
 | 
 | ||||||
| 			// 访问剩余节点
 | 			// 访问剩余节点
 | ||||||
|  | @ -124,7 +124,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		if (clip_enabled_) | 		if (clip_enabled_) | ||||||
| 		{ | 		{ | ||||||
| 			render::instance.PopClip(); | 			devices::Graphics::Instance().PopClip(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -171,7 +171,7 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 			if (border_) | 			if (border_) | ||||||
| 			{ | 			{ | ||||||
| 				render::instance.DrawGeometry(border_, border_color_, 1.f, 1.5f); | 				devices::Graphics::Instance().DrawGeometry(border_, border_color_, 1.f, 1.5f); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			for (const auto& child : children_) | 			for (const auto& child : children_) | ||||||
|  | @ -212,7 +212,7 @@ namespace easy2d | ||||||
| 		SafeRelease(border_); | 		SafeRelease(border_); | ||||||
| 		 | 		 | ||||||
| 		ThrowIfFailed( | 		ThrowIfFailed( | ||||||
| 			render::instance.CreateRectGeometry(final_matrix_, transform_.size, &border_) | 			devices::Graphics::Instance().CreateRectGeometry(final_matrix_, transform_.size, &border_) | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 通知子节点进行转换
 | 		// 通知子节点进行转换
 | ||||||
|  |  | ||||||
|  | @ -40,6 +40,8 @@ namespace easy2d | ||||||
| 		friend class Game; | 		friend class Game; | ||||||
| 		friend class Scene; | 		friend class Scene; | ||||||
| 
 | 
 | ||||||
|  | 		E2D_DISABLE_COPY(Node); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		typedef std::vector<Node*> Nodes; | 		typedef std::vector<Node*> Nodes; | ||||||
| 		typedef std::vector<Action*> Actions; | 		typedef std::vector<Action*> Actions; | ||||||
|  | @ -418,8 +420,6 @@ namespace easy2d | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		E2D_DISABLE_COPY(Node); |  | ||||||
| 
 |  | ||||||
| 		// 渲染节点边缘
 | 		// 渲染节点边缘
 | ||||||
| 		void DrawBorder(); | 		void DrawBorder(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,8 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "BaseTypes.h" | #include "../math/vector.hpp" | ||||||
|  | #include "Size.h" | ||||||
| #include <d2d1.h> | #include <d2d1.h> | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
|  | @ -34,9 +35,11 @@ namespace easy2d | ||||||
| 	//
 | 	//
 | ||||||
| 	class Rect | 	class Rect | ||||||
| 	{ | 	{ | ||||||
|  | 		using Point = math::Vector2; | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Point origin;	// 左上角坐标
 | 		Point	origin;	// 左上角坐标
 | ||||||
| 		Size  size;		// 宽度和高度
 | 		Size	size;	// 宽度和高度
 | ||||||
| 
 | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Rect() {} | 		Rect() {} | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ namespace easy2d | ||||||
| 	class Scene | 	class Scene | ||||||
| 		: public RefCounter | 		: public RefCounter | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Scene); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Scene(); | 		Scene(); | ||||||
| 
 | 
 | ||||||
|  | @ -79,9 +81,6 @@ namespace easy2d | ||||||
| 		// »ñȡת»»¾ØÕó
 | 		// »ñȡת»»¾ØÕó
 | ||||||
| 		const math::Matrix& GetTransform() const; | 		const math::Matrix& GetTransform() const; | ||||||
| 
 | 
 | ||||||
| 	private: |  | ||||||
| 		E2D_DISABLE_COPY(Scene); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		Node*			root_; | 		Node*			root_; | ||||||
| 		math::Matrix	transform_; | 		math::Matrix	transform_; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,77 @@ | ||||||
|  | // Copyright (c) 2016-2018 Easy2D - Nomango
 | ||||||
|  | // 
 | ||||||
|  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||||
|  | // of this software and associated documentation files (the "Software"), to deal
 | ||||||
|  | // in the Software without restriction, including without limitation the rights
 | ||||||
|  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||||
|  | // copies of the Software, and to permit persons to whom the Software is
 | ||||||
|  | // furnished to do so, subject to the following conditions:
 | ||||||
|  | // 
 | ||||||
|  | // The above copyright notice and this permission notice shall be included in
 | ||||||
|  | // all copies or substantial portions of the Software.
 | ||||||
|  | // 
 | ||||||
|  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||||
|  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||||
|  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||||
|  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||||
|  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||||
|  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | ||||||
|  | // THE SOFTWARE.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | namespace easy2d | ||||||
|  | { | ||||||
|  | 	template <typename T> | ||||||
|  | 	class ISingleton | ||||||
|  | 	{ | ||||||
|  | 	public: | ||||||
|  | 		static inline T& Instance(); | ||||||
|  | 
 | ||||||
|  | 		static inline void Destroy(); | ||||||
|  | 
 | ||||||
|  | 	private: | ||||||
|  | 		ISingleton() {} | ||||||
|  | 
 | ||||||
|  | 		~ISingleton() {} | ||||||
|  | 
 | ||||||
|  | 		ISingleton(const ISingleton&) = delete; | ||||||
|  | 
 | ||||||
|  | 		ISingleton & operator= (const ISingleton &) = delete; | ||||||
|  | 
 | ||||||
|  | 		static std::unique_ptr<T> instance_; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	template<typename T> | ||||||
|  | 	inline T & easy2d::ISingleton<T>::Instance() | ||||||
|  | 	{ | ||||||
|  | 		if (!instance_) | ||||||
|  | 			instance_.reset(new (std::nothrow) T); | ||||||
|  | 		return *instance_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template<typename T> | ||||||
|  | 	inline void easy2d::ISingleton<T>::Destroy() | ||||||
|  | 	{ | ||||||
|  | 		if (instance_) | ||||||
|  | 			instance_.reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template<typename T> | ||||||
|  | 	std::unique_ptr<T> easy2d::ISingleton<T>::instance_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Class that will implement the singleton mode,
 | ||||||
|  | // must use the macro in it's delare file
 | ||||||
|  | 
 | ||||||
|  | #ifndef E2D_DECLARE_SINGLETON | ||||||
|  | #define E2D_DECLARE_SINGLETON( type )			\ | ||||||
|  | 	friend class ::std::unique_ptr< type >;		\ | ||||||
|  | 	friend struct ::std::default_delete< type >;\ | ||||||
|  | 	friend class ::easy2d::ISingleton< type > | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifndef E2D_DECLARE_SINGLETON_TYPE | ||||||
|  | #define E2D_DECLARE_SINGLETON_TYPE( type, singleton_type ) using singleton_type = ::easy2d::ISingleton< type > | ||||||
|  | #endif | ||||||
|  | @ -135,7 +135,7 @@ namespace easy2d | ||||||
| 		if (image_ && image_->GetBitmap()) | 		if (image_ && image_->GetBitmap()) | ||||||
| 		{ | 		{ | ||||||
| 			auto crop_pos = image_->GetCropPos(); | 			auto crop_pos = image_->GetCropPos(); | ||||||
| 			render::instance.DrawImage( | 			devices::Graphics::Instance().DrawImage( | ||||||
| 				image_, | 				image_, | ||||||
| 				GetDisplayOpacity(), | 				GetDisplayOpacity(), | ||||||
| 				Rect(Point(), GetTransform().size), | 				Rect(Point(), GetTransform().size), | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace easy2d | ||||||
| 	class Sprite | 	class Sprite | ||||||
| 		: public Node | 		: public Node | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Sprite); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Sprite(); | 		Sprite(); | ||||||
| 
 | 
 | ||||||
|  | @ -81,9 +83,6 @@ namespace easy2d | ||||||
| 		// äÖČžžŤÁé
 | 		// äÖČžžŤÁé
 | ||||||
| 		virtual void OnDraw() const override; | 		virtual void OnDraw() const override; | ||||||
| 
 | 
 | ||||||
| 	private: |  | ||||||
| 		E2D_DISABLE_COPY(Sprite); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		Image* image_; | 		Image* image_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | @ -318,16 +318,16 @@ namespace easy2d | ||||||
| 			// 创建文本区域
 | 			// 创建文本区域
 | ||||||
| 			D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height); | 			D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height); | ||||||
| 			// 设置画刷颜色和透明度
 | 			// 设置画刷颜色和透明度
 | ||||||
| 			render::instance.SetBrushOpacity(GetDisplayOpacity()); | 			devices::Graphics::Instance().SetBrushOpacity(GetDisplayOpacity()); | ||||||
| 			// 获取文本渲染器
 | 			// 获取文本渲染器
 | ||||||
| 			render::instance.SetTextStyle( | 			devices::Graphics::Instance().SetTextStyle( | ||||||
| 				style_.color, | 				style_.color, | ||||||
| 				style_.outline, | 				style_.outline, | ||||||
| 				style_.outline_color, | 				style_.outline_color, | ||||||
| 				style_.outline_width, | 				style_.outline_width, | ||||||
| 				style_.outline_stroke | 				style_.outline_stroke | ||||||
| 			); | 			); | ||||||
| 			render::instance.DrawTextLayout(text_layout_); | 			devices::Graphics::Instance().DrawTextLayout(text_layout_); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -344,7 +344,7 @@ namespace easy2d | ||||||
| 		SafeRelease(text_format_); | 		SafeRelease(text_format_); | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed( | 		ThrowIfFailed( | ||||||
| 			render::instance.CreateTextFormat( | 			devices::Graphics::Instance().CreateTextFormat( | ||||||
| 				&text_format_, | 				&text_format_, | ||||||
| 				font_ | 				font_ | ||||||
| 			) | 			) | ||||||
|  | @ -399,7 +399,7 @@ namespace easy2d | ||||||
| 		if (style_.wrap) | 		if (style_.wrap) | ||||||
| 		{ | 		{ | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				render::instance.CreateTextLayout( | 				devices::Graphics::Instance().CreateTextLayout( | ||||||
| 					&text_layout_, | 					&text_layout_, | ||||||
| 					text_, | 					text_, | ||||||
| 					text_format_, | 					text_format_, | ||||||
|  | @ -416,7 +416,7 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 			// 为防止文本对齐问题,根据先创建 layout 以获取宽度
 | 			// 为防止文本对齐问题,根据先创建 layout 以获取宽度
 | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				render::instance.CreateTextLayout( | 				devices::Graphics::Instance().CreateTextLayout( | ||||||
| 					&text_layout_, | 					&text_layout_, | ||||||
| 					text_, | 					text_, | ||||||
| 					text_format_, | 					text_format_, | ||||||
|  | @ -433,7 +433,7 @@ namespace easy2d | ||||||
| 			// 重新创建 layout
 | 			// 重新创建 layout
 | ||||||
| 			SafeRelease(text_layout_); | 			SafeRelease(text_layout_); | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				render::instance.CreateTextLayout( | 				devices::Graphics::Instance().CreateTextLayout( | ||||||
| 					&text_layout_, | 					&text_layout_, | ||||||
| 					text_, | 					text_, | ||||||
| 					text_format_, | 					text_format_, | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace easy2d | ||||||
| 	class Text | 	class Text | ||||||
| 		: public Node | 		: public Node | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Text); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		// 文本对齐方式
 | 		// 文本对齐方式
 | ||||||
| 		enum class Align | 		enum class Align | ||||||
|  | @ -221,8 +223,6 @@ namespace easy2d | ||||||
| 		virtual void OnDraw() const override; | 		virtual void OnDraw() const override; | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		E2D_DISABLE_COPY(Text); |  | ||||||
| 
 |  | ||||||
| 		// 重新排版文字
 | 		// 重新排版文字
 | ||||||
| 		void Reset(); | 		void Reset(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ namespace easy2d | ||||||
| 		bShowOutline_ = outline; | 		bShowOutline_ = outline; | ||||||
| 		sOutlineColor_ = outline_color; | 		sOutlineColor_ = outline_color; | ||||||
| 		fOutlineWidth = 2 * outline_width; | 		fOutlineWidth = 2 * outline_width; | ||||||
| 		pCurrStrokeStyle_ = render::instance.GetStrokeStyle(StrokeStyle(outlineJoin)); | 		pCurrStrokeStyle_ = devices::Graphics::Instance().GetStrokeStyle(StrokeStyle(outlineJoin)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	STDMETHODIMP ITextRenderer::DrawGlyphRun( | 	STDMETHODIMP ITextRenderer::DrawGlyphRun( | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
| #include "Node.h" | #include "Node.h" | ||||||
| #include "Scene.h" | #include "Scene.h" | ||||||
| #include "window.h" | #include "window.h" | ||||||
|  | #include "render.h" | ||||||
| #include "../math/Matrix.hpp" | #include "../math/Matrix.hpp" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
|  | @ -73,22 +74,19 @@ namespace easy2d | ||||||
| 		if (in_scene_) | 		if (in_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				render::instance.CreateLayer(&in_layer_) | 				devices::Graphics::Instance().CreateLayer(&in_layer_) | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (out_scene_) | 		if (out_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				render::instance.CreateLayer(&out_layer_) | 				devices::Graphics::Instance().CreateLayer(&out_layer_) | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		window_size_ = window::instance.GetSize(); | 		window_size_ = Window::Instance().GetSize(); | ||||||
| 		out_layer_prop_ = in_layer_prop_ = render::LayerProperties{ | 		out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f }; | ||||||
| 			Rect(Point(), window_size_), |  | ||||||
| 			1.f |  | ||||||
| 		}; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Transition::Update() | 	void Transition::Update() | ||||||
|  | @ -113,30 +111,30 @@ namespace easy2d | ||||||
| 	{ | 	{ | ||||||
| 		if (out_scene_) | 		if (out_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			render::instance.PushClip( | 			devices::Graphics::Instance().PushClip( | ||||||
| 				out_scene_->GetTransform(), | 				out_scene_->GetTransform(), | ||||||
| 				window_size_ | 				window_size_ | ||||||
| 			); | 			); | ||||||
| 			render::instance.PushLayer(out_layer_, out_layer_prop_); | 			devices::Graphics::Instance().PushLayer(out_layer_, out_layer_prop_); | ||||||
| 
 | 
 | ||||||
| 			out_scene_->Draw(); | 			out_scene_->Draw(); | ||||||
| 
 | 
 | ||||||
| 			render::instance.PopLayer(); | 			devices::Graphics::Instance().PopLayer(); | ||||||
| 			render::instance.PopClip(); | 			devices::Graphics::Instance().PopClip(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (in_scene_) | 		if (in_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			render::instance.PushClip( | 			devices::Graphics::Instance().PushClip( | ||||||
| 				in_scene_->GetTransform(), | 				in_scene_->GetTransform(), | ||||||
| 				window_size_ | 				window_size_ | ||||||
| 			); | 			); | ||||||
| 			render::instance.PushLayer(in_layer_, in_layer_prop_); | 			devices::Graphics::Instance().PushLayer(in_layer_, in_layer_prop_); | ||||||
| 
 | 
 | ||||||
| 			in_scene_->Draw(); | 			in_scene_->Draw(); | ||||||
| 
 | 
 | ||||||
| 			render::instance.PopLayer(); | 			devices::Graphics::Instance().PopLayer(); | ||||||
| 			render::instance.PopClip(); | 			devices::Graphics::Instance().PopClip(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,7 +21,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| #include "base.h" | #include "base.h" | ||||||
| #include "time.h" | #include "time.h" | ||||||
| #include "render.h" |  | ||||||
| #include "RefCounter.h" | #include "RefCounter.h" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
|  | @ -75,8 +74,8 @@ namespace easy2d | ||||||
| 		Scene*			in_scene_; | 		Scene*			in_scene_; | ||||||
| 		ID2D1Layer*		out_layer_; | 		ID2D1Layer*		out_layer_; | ||||||
| 		ID2D1Layer*		in_layer_; | 		ID2D1Layer*		in_layer_; | ||||||
| 		render::LayerProperties out_layer_prop_; | 		LayerProperties out_layer_prop_; | ||||||
| 		render::LayerProperties in_layer_prop_; | 		LayerProperties in_layer_prop_; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,18 +27,161 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace audio | 	//-------------------------------------------------------
 | ||||||
|  | 	// Voice
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | 	Voice::Voice() | ||||||
|  | 		: source_voice_(nullptr) | ||||||
| 	{ | 	{ | ||||||
| 		AudioDevice instance; | 	} | ||||||
|  | 
 | ||||||
|  | 	Voice::Voice(IXAudio2SourceVoice * source_voice) | ||||||
|  | 		: source_voice_(source_voice) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Voice::~Voice() | ||||||
|  | 	{ | ||||||
|  | 		Destroy(); | ||||||
|  | 
 | ||||||
|  | 		devices::Audio::Instance().DeleteVoice(this); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count) | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		XAUDIO2_BUFFER buffer = { 0 }; | ||||||
|  | 		buffer.pAudioData = wave_data; | ||||||
|  | 		buffer.Flags = XAUDIO2_END_OF_STREAM; | ||||||
|  | 		buffer.AudioBytes = data_size; | ||||||
|  | 		buffer.LoopCount = loop_count; | ||||||
|  | 
 | ||||||
|  | 		HRESULT hr = source_voice_->SubmitSourceBuffer(&buffer); | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			hr = source_voice_->Start(); | ||||||
|  | 		} | ||||||
|  | 		return hr; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::Pause() | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		return source_voice_->Stop(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::Resume() | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		return source_voice_->Start(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::Stop() | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		HRESULT hr = source_voice_->Stop(); | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			hr = source_voice_->ExitLoop(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			hr = source_voice_->FlushSourceBuffers(); | ||||||
|  | 		} | ||||||
|  | 		return hr; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::GetVolume(float * volume) const | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		if (volume == nullptr) | ||||||
|  | 			return E_POINTER; | ||||||
|  | 
 | ||||||
|  | 		source_voice_->GetVolume(volume); | ||||||
|  | 		return S_OK; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::SetVolume(float volume) | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		volume = std::min(std::max(volume, -224.f), 224.f); | ||||||
|  | 		return source_voice_->SetVolume(volume); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HRESULT Voice::GetBuffersQueued(UINT32 * queued) const | ||||||
|  | 	{ | ||||||
|  | 		if (!source_voice_) | ||||||
|  | 			return E_UNEXPECTED; | ||||||
|  | 
 | ||||||
|  | 		if (queued == nullptr) | ||||||
|  | 			return E_POINTER; | ||||||
|  | 
 | ||||||
|  | 		XAUDIO2_VOICE_STATE state; | ||||||
|  | 		source_voice_->GetState(&state); | ||||||
|  | 		*queued = state.BuffersQueued; | ||||||
|  | 		return S_OK; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Voice::Destroy() | ||||||
|  | 	{ | ||||||
|  | 		if (source_voice_) | ||||||
|  | 		{ | ||||||
|  | 			source_voice_->Stop(); | ||||||
|  | 			source_voice_->FlushSourceBuffers(); | ||||||
|  | 			source_voice_->DestroyVoice(); | ||||||
|  | 			source_voice_ = nullptr; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Voice::SetSourceVoice(IXAudio2SourceVoice * source_voice) | ||||||
|  | 	{ | ||||||
|  | 		Destroy(); | ||||||
|  | 		source_voice_ = source_voice; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	namespace devices | ||||||
|  | 	{ | ||||||
|  | 		//-------------------------------------------------------
 | ||||||
|  | 		// AudioDevice
 | ||||||
|  | 		//-------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| 		AudioDevice::AudioDevice() | 		AudioDevice::AudioDevice() | ||||||
| 			: x_audio2_(nullptr) | 			: x_audio2_(nullptr) | ||||||
| 			, mastering_voice_(nullptr) | 			, mastering_voice_(nullptr) | ||||||
| 		{ | 		{ | ||||||
|  | 			modules::Initialize(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		AudioDevice::~AudioDevice() | 		AudioDevice::~AudioDevice() | ||||||
| 		{ | 		{ | ||||||
|  | 			ClearVoiceCache(); | ||||||
|  | 
 | ||||||
|  | 			if (mastering_voice_) | ||||||
|  | 			{ | ||||||
|  | 				mastering_voice_->DestroyVoice(); | ||||||
|  | 				mastering_voice_ = nullptr; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(x_audio2_); | ||||||
|  | 
 | ||||||
|  | 			modules::MediaFoundation.MFShutdown(); | ||||||
|  | 
 | ||||||
|  | 			modules::Destroy(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void AudioDevice::Initialize() | 		void AudioDevice::Initialize() | ||||||
|  | @ -56,22 +199,42 @@ namespace easy2d | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void AudioDevice::Uninitialize() | 		HRESULT AudioDevice::CreateVoice(Voice* voice, WAVEFORMATEX * wfx) | ||||||
| 		{ | 		{ | ||||||
| 			if (mastering_voice_) | 			HRESULT hr; | ||||||
|  | 			IXAudio2SourceVoice* source_voice; | ||||||
|  | 
 | ||||||
|  | 			if (!voice) | ||||||
|  | 				return E_POINTER; | ||||||
|  | 			 | ||||||
|  | 			hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); | ||||||
|  | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				mastering_voice_->DestroyVoice(); | 				voice->SetSourceVoice(source_voice); | ||||||
| 				mastering_voice_ = nullptr; | 				voice_cache_.push_back(voice); | ||||||
| 			} | 			} | ||||||
| 
 | 			return hr; | ||||||
| 			SafeRelease(x_audio2_); |  | ||||||
| 
 |  | ||||||
| 			modules::MediaFoundation.MFShutdown(); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT AudioDevice::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx) | 		void AudioDevice::DeleteVoice(Voice * voice) | ||||||
| 		{ | 		{ | ||||||
| 			return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); | 			for (auto iter = voice_cache_.begin(); iter != voice_cache_.end(); ++iter) | ||||||
|  | 			{ | ||||||
|  | 				if (*iter == voice) | ||||||
|  | 				{ | ||||||
|  | 					voice_cache_.erase(iter); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		void AudioDevice::ClearVoiceCache() | ||||||
|  | 		{ | ||||||
|  | 			for (auto voice : voice_cache_) | ||||||
|  | 			{ | ||||||
|  | 				voice->Destroy(); | ||||||
|  | 			} | ||||||
|  | 			voice_cache_.clear(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void AudioDevice::Open() | 		void AudioDevice::Open() | ||||||
|  |  | ||||||
|  | @ -20,41 +20,97 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "macros.h" | #include "macros.h" | ||||||
|  | #include "Singleton.hpp" | ||||||
| #include <xaudio2.h> | #include <xaudio2.h> | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace audio | 	class Voice | ||||||
|  | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Voice); | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		Voice(); | ||||||
|  | 
 | ||||||
|  | 		Voice( | ||||||
|  | 			IXAudio2SourceVoice* source_voice | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		~Voice(); | ||||||
|  | 
 | ||||||
|  | 		HRESULT Play( | ||||||
|  | 			const BYTE* wave_data, | ||||||
|  | 			UINT32 data_size, | ||||||
|  | 			UINT32 loop_count | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		HRESULT Pause(); | ||||||
|  | 
 | ||||||
|  | 		HRESULT Resume(); | ||||||
|  | 
 | ||||||
|  | 		HRESULT Stop(); | ||||||
|  | 
 | ||||||
|  | 		HRESULT GetVolume( | ||||||
|  | 			float* volume | ||||||
|  | 		) const; | ||||||
|  | 
 | ||||||
|  | 		HRESULT SetVolume( | ||||||
|  | 			float volume | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		HRESULT GetBuffersQueued( | ||||||
|  | 			UINT32* queued | ||||||
|  | 		) const; | ||||||
|  | 
 | ||||||
|  | 		void Destroy(); | ||||||
|  | 
 | ||||||
|  | 		void SetSourceVoice( | ||||||
|  | 			IXAudio2SourceVoice* source_voice | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 	protected: | ||||||
|  | 		IXAudio2SourceVoice* source_voice_; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	namespace devices | ||||||
| 	{ | 	{ | ||||||
| 		// 音频设备
 |  | ||||||
| 		class AudioDevice | 		class AudioDevice | ||||||
| 		{ | 		{ | ||||||
|  | 			E2D_DECLARE_SINGLETON(AudioDevice); | ||||||
|  | 
 | ||||||
|  | 			E2D_DISABLE_COPY(AudioDevice); | ||||||
|  | 
 | ||||||
| 		public: | 		public: | ||||||
| 			AudioDevice(); |  | ||||||
| 
 |  | ||||||
| 			~AudioDevice(); |  | ||||||
| 
 |  | ||||||
| 			void Initialize(); | 			void Initialize(); | ||||||
| 
 | 
 | ||||||
| 			void Uninitialize(); |  | ||||||
| 
 |  | ||||||
| 			// 开启设备
 | 			// 开启设备
 | ||||||
| 			void Open(); | 			void Open(); | ||||||
| 
 | 
 | ||||||
| 			// 关闭设备
 | 			// 关闭设备
 | ||||||
| 			void Close(); | 			void Close(); | ||||||
| 
 | 
 | ||||||
| 			// 创建音源
 |  | ||||||
| 			HRESULT CreateVoice( | 			HRESULT CreateVoice( | ||||||
| 				IXAudio2SourceVoice ** voice, | 				Voice* voice, | ||||||
| 				WAVEFORMATEX * wfx | 				WAVEFORMATEX * wfx | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | 			void DeleteVoice( | ||||||
|  | 				Voice* voice | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			void ClearVoiceCache(); | ||||||
|  | 
 | ||||||
|  | 		protected: | ||||||
|  | 			AudioDevice(); | ||||||
|  | 
 | ||||||
|  | 			~AudioDevice(); | ||||||
|  | 
 | ||||||
| 		protected: | 		protected: | ||||||
| 			IXAudio2 * x_audio2_; | 			IXAudio2 * x_audio2_; | ||||||
| 			IXAudio2MasteringVoice*	mastering_voice_; | 			IXAudio2MasteringVoice*	mastering_voice_; | ||||||
|  | 			std::list<Voice*> voice_cache_; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		extern AudioDevice instance; | 		E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,7 +20,6 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "BaseTypes.h" | #include "BaseTypes.h" | ||||||
| #include "Rect.hpp" |  | ||||||
| #include <stdexcept> | #include <stdexcept> | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
|  |  | ||||||
|  | @ -80,6 +80,7 @@ | ||||||
| #include <list> | #include <list> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
|  | #include <memory> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #if VS_VER >= VS_2015 | #if VS_VER >= VS_2015 | ||||||
|  | @ -89,9 +90,10 @@ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define E2D_DISABLE_COPY(Class)					\ | #define E2D_DISABLE_COPY(Class)						\ | ||||||
| 	Class(const Class &) = delete;				\ | 	private:										\ | ||||||
| 	Class & operator= (const Class &) = delete | 		Class(const Class &) = delete;				\ | ||||||
|  | 		Class & operator= (const Class &) = delete | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #if defined( DEBUG ) || defined( _DEBUG ) | #if defined( DEBUG ) || defined( _DEBUG ) | ||||||
|  |  | ||||||
|  | @ -26,6 +26,8 @@ namespace easy2d | ||||||
| 	{ | 	{ | ||||||
| 		namespace | 		namespace | ||||||
| 		{ | 		{ | ||||||
|  | 			int initialize_count = 0; | ||||||
|  | 
 | ||||||
| 			inline void SafeFreeLibrary(HMODULE instance) | 			inline void SafeFreeLibrary(HMODULE instance) | ||||||
| 			{ | 			{ | ||||||
| 				if (instance) | 				if (instance) | ||||||
|  | @ -38,6 +40,10 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		void Initialize() | 		void Initialize() | ||||||
| 		{ | 		{ | ||||||
|  | 			initialize_count++; | ||||||
|  | 			if (initialize_count > 1) | ||||||
|  | 				return; | ||||||
|  | 
 | ||||||
| 			const auto xaudio2_dll_names = | 			const auto xaudio2_dll_names = | ||||||
| 			{ | 			{ | ||||||
| 				L"xaudio2_9.dll", | 				L"xaudio2_9.dll", | ||||||
|  | @ -86,8 +92,12 @@ namespace easy2d | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void Uninitialize() | 		void Destroy() | ||||||
| 		{ | 		{ | ||||||
|  | 			initialize_count--; | ||||||
|  | 			if (initialize_count > 0) | ||||||
|  | 				return; | ||||||
|  | 
 | ||||||
| 			SafeFreeLibrary(XAudio2.instance); | 			SafeFreeLibrary(XAudio2.instance); | ||||||
| 			SafeFreeLibrary(MediaFoundation.mfplat); | 			SafeFreeLibrary(MediaFoundation.mfplat); | ||||||
| 			SafeFreeLibrary(MediaFoundation.mfreadwrite); | 			SafeFreeLibrary(MediaFoundation.mfreadwrite); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,12 @@ namespace easy2d | ||||||
| { | { | ||||||
|     namespace modules |     namespace modules | ||||||
| 	{ | 	{ | ||||||
|  | 		// modules can be initialized multiple times,
 | ||||||
|  | 		// but it needs to be destroyed every time
 | ||||||
|  | 		void Initialize(); | ||||||
|  | 
 | ||||||
|  | 		void Destroy(); | ||||||
|  | 
 | ||||||
| 		// XAudio2 functions
 | 		// XAudio2 functions
 | ||||||
| 		typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); | 		typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); | ||||||
| 
 | 
 | ||||||
|  | @ -66,13 +72,5 @@ namespace easy2d | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		extern Module_MediaFoundation MediaFoundation; | 		extern Module_MediaFoundation MediaFoundation; | ||||||
| 
 |  | ||||||
| 		//
 |  | ||||||
| 		// Functions
 |  | ||||||
| 		//
 |  | ||||||
| 
 |  | ||||||
| 		void Initialize(); |  | ||||||
| 
 |  | ||||||
| 		void Uninitialize(); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
| #include "render.h" | #include "render.h" | ||||||
| #include "time.h" | #include "time.h" | ||||||
| #include "base.h" | #include "base.h" | ||||||
|  | #include "modules.h" | ||||||
| 
 | 
 | ||||||
| #pragma comment(lib, "d2d1.lib") | #pragma comment(lib, "d2d1.lib") | ||||||
| #pragma comment(lib, "dwrite.lib") | #pragma comment(lib, "dwrite.lib") | ||||||
|  | @ -28,33 +29,49 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace render | 	namespace devices | ||||||
| 	{ | 	{ | ||||||
| 		GraphicsDevice instance; |  | ||||||
| 
 |  | ||||||
| 		GraphicsDevice::GraphicsDevice() | 		GraphicsDevice::GraphicsDevice() | ||||||
| 			: fps_text_format_(nullptr) | 			: fps_text_format_(nullptr) | ||||||
| 			, fps_text_layout_(nullptr) | 			, fps_text_layout_(nullptr) | ||||||
| 			, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) | 			, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) | ||||||
| 		{ | 		{ | ||||||
| 			ZeroMemory(&d2d, sizeof(D2DResources)); | 			ZeroMemory(&d2d, sizeof(D2DResources)); | ||||||
|  | 
 | ||||||
|  | 			modules::Initialize(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		GraphicsDevice::~GraphicsDevice() | 		GraphicsDevice::~GraphicsDevice() | ||||||
| 		{ | 		{ | ||||||
|  | 			ClearImageCache(); | ||||||
|  | 
 | ||||||
| 			SafeRelease(fps_text_format_); | 			SafeRelease(fps_text_format_); | ||||||
| 			SafeRelease(fps_text_layout_); | 			SafeRelease(fps_text_layout_); | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(d2d.text_renderer); | ||||||
|  | 			SafeRelease(d2d.solid_brush); | ||||||
|  | 			SafeRelease(d2d.render_target); | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(d2d.miter_stroke_style); | ||||||
|  | 			SafeRelease(d2d.bevel_stroke_style); | ||||||
|  | 			SafeRelease(d2d.round_stroke_style); | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(d2d.imaging_factory); | ||||||
|  | 			SafeRelease(d2d.write_factory); | ||||||
|  | 			SafeRelease(d2d.factory); | ||||||
|  | 
 | ||||||
|  | 			modules::Destroy(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void GraphicsDevice::Initialize(HWND hwnd) | 		void GraphicsDevice::Initialize(HWND hwnd) | ||||||
| 		{ | 		{ | ||||||
| 			if (d2d.Factory) | 			if (d2d.factory) | ||||||
| 				return; | 				return; | ||||||
| 
 | 
 | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				D2D1CreateFactory( | 				D2D1CreateFactory( | ||||||
| 					D2D1_FACTORY_TYPE_SINGLE_THREADED, | 					D2D1_FACTORY_TYPE_SINGLE_THREADED, | ||||||
| 					&d2d.Factory | 					&d2d.factory | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | @ -64,7 +81,7 @@ namespace easy2d | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					CLSCTX_INPROC_SERVER, | 					CLSCTX_INPROC_SERVER, | ||||||
| 					IID_IWICImagingFactory, | 					IID_IWICImagingFactory, | ||||||
| 					reinterpret_cast<void**>(&d2d.WICImagingFactory) | 					reinterpret_cast<void**>(&d2d.imaging_factory) | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +89,7 @@ namespace easy2d | ||||||
| 				DWriteCreateFactory( | 				DWriteCreateFactory( | ||||||
| 					DWRITE_FACTORY_TYPE_SHARED, | 					DWRITE_FACTORY_TYPE_SHARED, | ||||||
| 					__uuidof(IDWriteFactory), | 					__uuidof(IDWriteFactory), | ||||||
| 					reinterpret_cast<IUnknown**>(&d2d.DWriteFactory) | 					reinterpret_cast<IUnknown**>(&d2d.write_factory) | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | @ -87,65 +104,50 @@ namespace easy2d | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				d2d.Factory->CreateStrokeStyle( | 				d2d.factory->CreateStrokeStyle( | ||||||
| 					stroke_style, | 					stroke_style, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					0, | 					0, | ||||||
| 					&d2d.MiterStrokeStyle | 					&d2d.miter_stroke_style | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; | 			stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; | ||||||
| 
 | 
 | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				d2d.Factory->CreateStrokeStyle( | 				d2d.factory->CreateStrokeStyle( | ||||||
| 					stroke_style, | 					stroke_style, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					0, | 					0, | ||||||
| 					&d2d.BevelStrokeStyle | 					&d2d.bevel_stroke_style | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; | 			stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; | ||||||
| 
 | 
 | ||||||
| 			ThrowIfFailed( | 			ThrowIfFailed( | ||||||
| 				d2d.Factory->CreateStrokeStyle( | 				d2d.factory->CreateStrokeStyle( | ||||||
| 					stroke_style, | 					stroke_style, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					0, | 					0, | ||||||
| 					&d2d.RoundStrokeStyle | 					&d2d.round_stroke_style | ||||||
| 				) | 				) | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			CreateDeviceResources(hwnd); | 			CreateDeviceResources(hwnd); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void GraphicsDevice::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); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		void GraphicsDevice::BeginDraw(HWND hwnd) | 		void GraphicsDevice::BeginDraw(HWND hwnd) | ||||||
| 		{ | 		{ | ||||||
| 			CreateDeviceResources(hwnd); | 			CreateDeviceResources(hwnd); | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->BeginDraw(); | 			d2d.render_target->BeginDraw(); | ||||||
| 			d2d.HwndRenderTarget->Clear(clear_color_); | 			d2d.render_target->Clear(clear_color_); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void GraphicsDevice::EndDraw() | 		void GraphicsDevice::EndDraw() | ||||||
| 		{ | 		{ | ||||||
| 			HRESULT hr = d2d.HwndRenderTarget->EndDraw(); | 			HRESULT hr = d2d.render_target->EndDraw(); | ||||||
| 
 | 
 | ||||||
| 			if (hr == D2DERR_RECREATE_TARGET) | 			if (hr == D2DERR_RECREATE_TARGET) | ||||||
| 			{ | 			{ | ||||||
|  | @ -155,36 +157,48 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 				SafeRelease(fps_text_format_); | 				SafeRelease(fps_text_format_); | ||||||
| 				SafeRelease(fps_text_layout_); | 				SafeRelease(fps_text_layout_); | ||||||
| 				SafeRelease(d2d.TextRenderer); | 				SafeRelease(d2d.text_renderer); | ||||||
| 				SafeRelease(d2d.SolidColorBrush); | 				SafeRelease(d2d.solid_brush); | ||||||
| 				SafeRelease(d2d.HwndRenderTarget); | 				SafeRelease(d2d.render_target); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			ThrowIfFailed(hr); | 			ThrowIfFailed(hr); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		void GraphicsDevice::ClearImageCache() | ||||||
|  | 		{ | ||||||
|  | 			if (bitmap_cache_.empty()) | ||||||
|  | 				return; | ||||||
|  | 
 | ||||||
|  | 			for (const auto& bitmap : bitmap_cache_) | ||||||
|  | 			{ | ||||||
|  | 				bitmap.second->Release(); | ||||||
|  | 			} | ||||||
|  | 			bitmap_cache_.clear(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateRectGeometry( | 		HRESULT GraphicsDevice::CreateRectGeometry( | ||||||
| 			const math::Matrix& matrix, | 			const math::Matrix& matrix, | ||||||
| 			const Size& size, | 			const Size& size, | ||||||
| 			ID2D1Geometry** geometry | 			ID2D1Geometry** geometry | ||||||
| 		) const | 		) const | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.Factory) | 			if (!d2d.factory) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			HRESULT hr; | 			HRESULT hr; | ||||||
| 
 | 
 | ||||||
| 			ID2D1RectangleGeometry * rectangle = nullptr; | 			ID2D1RectangleGeometry * rectangle = nullptr; | ||||||
| 			ID2D1TransformedGeometry * transformed = nullptr; | 			ID2D1TransformedGeometry * transformed = nullptr; | ||||||
| 			 | 
 | ||||||
| 			hr = d2d.Factory->CreateRectangleGeometry( | 			hr = d2d.factory->CreateRectangleGeometry( | ||||||
| 				D2D1::RectF(0, 0, size.width, size.height), | 				D2D1::RectF(0, 0, size.width, size.height), | ||||||
| 				&rectangle | 				&rectangle | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				hr = d2d.Factory->CreateTransformedGeometry( | 				hr = d2d.factory->CreateTransformedGeometry( | ||||||
| 					rectangle, | 					rectangle, | ||||||
| 					matrix, | 					matrix, | ||||||
| 					&transformed | 					&transformed | ||||||
|  | @ -202,10 +216,10 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateTextFormat(IDWriteTextFormat ** text_format, const Font & font) const | 		HRESULT GraphicsDevice::CreateTextFormat(IDWriteTextFormat ** text_format, const Font & font) const | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.DWriteFactory) | 			if (!d2d.write_factory) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			return d2d.DWriteFactory->CreateTextFormat( | 			return d2d.write_factory->CreateTextFormat( | ||||||
| 				font.family.c_str(), | 				font.family.c_str(), | ||||||
| 				nullptr, | 				nullptr, | ||||||
| 				DWRITE_FONT_WEIGHT(font.weight), | 				DWRITE_FONT_WEIGHT(font.weight), | ||||||
|  | @ -219,11 +233,11 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateTextLayout(IDWriteTextLayout ** text_layout, const String & text, IDWriteTextFormat * text_format, float wrap_width) const | 		HRESULT GraphicsDevice::CreateTextLayout(IDWriteTextLayout ** text_layout, const String & text, IDWriteTextFormat * text_format, float wrap_width) const | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.DWriteFactory) | 			if (!d2d.write_factory) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			UINT32 length = static_cast<UINT32>(text.length()); | 			UINT32 length = static_cast<UINT32>(text.length()); | ||||||
| 			return d2d.DWriteFactory->CreateTextLayout( | 			return d2d.write_factory->CreateTextLayout( | ||||||
| 				text.c_str(), | 				text.c_str(), | ||||||
| 				length, | 				length, | ||||||
| 				text_format, | 				text_format, | ||||||
|  | @ -235,10 +249,10 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateLayer(ID2D1Layer ** layer) | 		HRESULT GraphicsDevice::CreateLayer(ID2D1Layer ** layer) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			return d2d.HwndRenderTarget->CreateLayer(layer); | 			return d2d.render_target->CreateLayer(layer); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::DrawGeometry( | 		HRESULT GraphicsDevice::DrawGeometry( | ||||||
|  | @ -249,15 +263,15 @@ namespace easy2d | ||||||
| 			StrokeStyle stroke | 			StrokeStyle stroke | ||||||
| 		) | 		) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.SolidColorBrush || | 			if (!d2d.solid_brush || | ||||||
| 				!d2d.HwndRenderTarget) | 				!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.SolidColorBrush->SetColor(border_color); | 			d2d.solid_brush->SetColor(border_color); | ||||||
| 			d2d.SolidColorBrush->SetOpacity(opacity); | 			d2d.solid_brush->SetOpacity(opacity); | ||||||
| 			d2d.HwndRenderTarget->DrawGeometry( | 			d2d.render_target->DrawGeometry( | ||||||
| 				geometry, | 				geometry, | ||||||
| 				d2d.SolidColorBrush, | 				d2d.solid_brush, | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke) | 				GetStrokeStyle(stroke) | ||||||
| 			); | 			); | ||||||
|  | @ -270,13 +284,13 @@ namespace easy2d | ||||||
| 			switch (stroke) | 			switch (stroke) | ||||||
| 			{ | 			{ | ||||||
| 			case StrokeStyle::Miter: | 			case StrokeStyle::Miter: | ||||||
| 				stroke_style = d2d.MiterStrokeStyle; | 				stroke_style = d2d.miter_stroke_style; | ||||||
| 				break; | 				break; | ||||||
| 			case StrokeStyle::Bevel: | 			case StrokeStyle::Bevel: | ||||||
| 				stroke_style = d2d.BevelStrokeStyle; | 				stroke_style = d2d.bevel_stroke_style; | ||||||
| 				break; | 				break; | ||||||
| 			case StrokeStyle::Round: | 			case StrokeStyle::Round: | ||||||
| 				stroke_style = d2d.RoundStrokeStyle; | 				stroke_style = d2d.round_stroke_style; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			return stroke_style; | 			return stroke_style; | ||||||
|  | @ -289,10 +303,10 @@ namespace easy2d | ||||||
| 			const Rect & source_rect | 			const Rect & source_rect | ||||||
| 		) | 		) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->DrawBitmap( | 			d2d.render_target->DrawBitmap( | ||||||
| 				image->GetBitmap(), | 				image->GetBitmap(), | ||||||
| 				dest_rect, | 				dest_rect, | ||||||
| 				opacity, | 				opacity, | ||||||
|  | @ -304,19 +318,19 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::DrawTextLayout(IDWriteTextLayout * text_layout) | 		HRESULT GraphicsDevice::DrawTextLayout(IDWriteTextLayout * text_layout) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.TextRenderer) | 			if (!d2d.text_renderer) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			return text_layout->Draw(nullptr, d2d.TextRenderer, 0, 0); | 			return text_layout->Draw(nullptr, d2d.text_renderer, 0, 0); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size) | 		HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->SetTransform(clip_matrix); | 			d2d.render_target->SetTransform(clip_matrix); | ||||||
| 			d2d.HwndRenderTarget->PushAxisAlignedClip( | 			d2d.render_target->PushAxisAlignedClip( | ||||||
| 				D2D1::RectF(0, 0, clip_size.width, clip_size.height), | 				D2D1::RectF(0, 0, clip_size.width, clip_size.height), | ||||||
| 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | ||||||
| 			); | 			); | ||||||
|  | @ -325,27 +339,27 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::PopClip() | 		HRESULT GraphicsDevice::PopClip() | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->PopAxisAlignedClip(); | 			d2d.render_target->PopAxisAlignedClip(); | ||||||
| 			return S_OK; | 			return S_OK; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::PushLayer(ID2D1Layer * layer, LayerProperties properties) | 		HRESULT GraphicsDevice::PushLayer(ID2D1Layer * layer, LayerProperties properties) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget || | 			if (!d2d.render_target || | ||||||
| 				!d2d.SolidColorBrush) | 				!d2d.solid_brush) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->PushLayer( | 			d2d.render_target->PushLayer( | ||||||
| 				D2D1::LayerParameters( | 				D2D1::LayerParameters( | ||||||
| 					properties.area, | 					properties.area, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | 					D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | ||||||
| 					D2D1::Matrix3x2F::Identity(), | 					D2D1::Matrix3x2F::Identity(), | ||||||
| 					properties.opacity, | 					properties.opacity, | ||||||
| 					d2d.SolidColorBrush, | 					d2d.solid_brush, | ||||||
| 					D2D1_LAYER_OPTIONS_NONE | 					D2D1_LAYER_OPTIONS_NONE | ||||||
| 				), | 				), | ||||||
| 				layer | 				layer | ||||||
|  | @ -355,17 +369,17 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::PopLayer() | 		HRESULT GraphicsDevice::PopLayer() | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->PopLayer(); | 			d2d.render_target->PopLayer(); | ||||||
| 			return S_OK; | 			return S_OK; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateBitmapFromFile(const String & file_path, ID2D1Bitmap ** bitmap) | 		HRESULT GraphicsDevice::CreateBitmapFromFile(const String & file_path, ID2D1Bitmap ** bitmap) | ||||||
| 		{ | 		{ | ||||||
| 			if (d2d.WICImagingFactory == nullptr || | 			if (d2d.imaging_factory == nullptr || | ||||||
| 				d2d.HwndRenderTarget == nullptr) | 				d2d.render_target == nullptr) | ||||||
| 			{ | 			{ | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 			} | 			} | ||||||
|  | @ -375,13 +389,20 @@ namespace easy2d | ||||||
| 				return E_POINTER; | 				return E_POINTER; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			size_t hash_code = std::hash<String>{}(file_path); | ||||||
|  | 			if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) | ||||||
|  | 			{ | ||||||
|  | 				*bitmap = bitmap_cache_[hash_code]; | ||||||
|  | 				return S_OK; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			IWICBitmapDecoder*		decoder = nullptr; | 			IWICBitmapDecoder*		decoder = nullptr; | ||||||
| 			IWICBitmapFrameDecode*	source = nullptr; | 			IWICBitmapFrameDecode*	source = nullptr; | ||||||
| 			IWICStream*				stream = nullptr; | 			IWICStream*				stream = nullptr; | ||||||
| 			IWICFormatConverter*	converter = nullptr; | 			IWICFormatConverter*	converter = nullptr; | ||||||
| 
 | 
 | ||||||
| 			// 创建解码器
 | 			// 创建解码器
 | ||||||
| 			HRESULT hr = d2d.WICImagingFactory->CreateDecoderFromFilename( | 			HRESULT hr = d2d.imaging_factory->CreateDecoderFromFilename( | ||||||
| 				file_path.c_str(), | 				file_path.c_str(), | ||||||
| 				nullptr, | 				nullptr, | ||||||
| 				GENERIC_READ, | 				GENERIC_READ, | ||||||
|  | @ -398,7 +419,7 @@ namespace easy2d | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 创建图片格式转换器
 | 				// 创建图片格式转换器
 | ||||||
| 				hr = d2d.WICImagingFactory->CreateFormatConverter(&converter); | 				hr = d2d.imaging_factory->CreateFormatConverter(&converter); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
|  | @ -417,13 +438,18 @@ namespace easy2d | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 从 WIC 位图创建一个 Direct2D 位图
 | 				// 从 WIC 位图创建一个 Direct2D 位图
 | ||||||
| 				hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap( | 				hr = d2d.render_target->CreateBitmapFromWicBitmap( | ||||||
| 					converter, | 					converter, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					bitmap | 					bitmap | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			if (SUCCEEDED(hr)) | ||||||
|  | 			{ | ||||||
|  | 				bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			// 释放相关资源
 | 			// 释放相关资源
 | ||||||
| 			SafeRelease(decoder); | 			SafeRelease(decoder); | ||||||
| 			SafeRelease(source); | 			SafeRelease(source); | ||||||
|  | @ -435,8 +461,8 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::CreateBitmapFromResource(Resource & res, ID2D1Bitmap ** bitmap) | 		HRESULT GraphicsDevice::CreateBitmapFromResource(Resource & res, ID2D1Bitmap ** bitmap) | ||||||
| 		{ | 		{ | ||||||
| 			if (d2d.WICImagingFactory == nullptr || | 			if (d2d.imaging_factory == nullptr || | ||||||
| 				d2d.HwndRenderTarget == nullptr) | 				d2d.render_target == nullptr) | ||||||
| 			{ | 			{ | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 			} | 			} | ||||||
|  | @ -446,6 +472,13 @@ namespace easy2d | ||||||
| 				return E_POINTER; | 				return E_POINTER; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			size_t hash_code = res.GetHashCode(); | ||||||
|  | 			if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) | ||||||
|  | 			{ | ||||||
|  | 				*bitmap = bitmap_cache_[hash_code]; | ||||||
|  | 				return S_OK; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			HRESULT hr; | 			HRESULT hr; | ||||||
| 
 | 
 | ||||||
| 			HINSTANCE				hinstance = GetModuleHandle(nullptr); | 			HINSTANCE				hinstance = GetModuleHandle(nullptr); | ||||||
|  | @ -453,14 +486,14 @@ namespace easy2d | ||||||
| 			IWICBitmapFrameDecode*	source = nullptr; | 			IWICBitmapFrameDecode*	source = nullptr; | ||||||
| 			IWICStream*				stream = nullptr; | 			IWICStream*				stream = nullptr; | ||||||
| 			IWICFormatConverter*	converter = nullptr; | 			IWICFormatConverter*	converter = nullptr; | ||||||
| 			 | 
 | ||||||
| 			// 加载资源
 | 			// 加载资源
 | ||||||
| 			hr = res.Load() ? S_OK : E_FAIL; | 			hr = res.Load() ? S_OK : E_FAIL; | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 创建 WIC 流
 | 				// 创建 WIC 流
 | ||||||
| 				hr = d2d.WICImagingFactory->CreateStream(&stream); | 				hr = d2d.imaging_factory->CreateStream(&stream); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
|  | @ -475,7 +508,7 @@ namespace easy2d | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 创建流的解码器
 | 				// 创建流的解码器
 | ||||||
| 				hr = d2d.WICImagingFactory->CreateDecoderFromStream( | 				hr = d2d.imaging_factory->CreateDecoderFromStream( | ||||||
| 					stream, | 					stream, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					WICDecodeMetadataCacheOnLoad, | 					WICDecodeMetadataCacheOnLoad, | ||||||
|  | @ -492,7 +525,7 @@ namespace easy2d | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 创建图片格式转换器
 | 				// 创建图片格式转换器
 | ||||||
| 				hr = d2d.WICImagingFactory->CreateFormatConverter(&converter); | 				hr = d2d.imaging_factory->CreateFormatConverter(&converter); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
|  | @ -511,13 +544,18 @@ namespace easy2d | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				// 从 WIC 位图创建一个 Direct2D 位图
 | 				// 从 WIC 位图创建一个 Direct2D 位图
 | ||||||
| 				hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap( | 				hr = d2d.render_target->CreateBitmapFromWicBitmap( | ||||||
| 					converter, | 					converter, | ||||||
| 					nullptr, | 					nullptr, | ||||||
| 					bitmap | 					bitmap | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			if (SUCCEEDED(hr)) | ||||||
|  | 			{ | ||||||
|  | 				bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			// 释放相关资源
 | 			// 释放相关资源
 | ||||||
| 			SafeRelease(decoder); | 			SafeRelease(decoder); | ||||||
| 			SafeRelease(source); | 			SafeRelease(source); | ||||||
|  | @ -529,28 +567,28 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height) | 		HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->Resize(D2D1::SizeU(width, height)); | 			d2d.render_target->Resize(D2D1::SizeU(width, height)); | ||||||
| 			return S_OK; | 			return S_OK; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix) | 		HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.HwndRenderTarget->SetTransform(matrix); | 			d2d.render_target->SetTransform(matrix); | ||||||
| 			return S_OK; | 			return S_OK; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		HRESULT GraphicsDevice::SetBrushOpacity(float opacity) | 		HRESULT GraphicsDevice::SetBrushOpacity(float opacity) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.SolidColorBrush->SetOpacity(opacity); | 			d2d.solid_brush->SetOpacity(opacity); | ||||||
| 			return S_OK; | 			return S_OK; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -562,10 +600,10 @@ namespace easy2d | ||||||
| 			StrokeStyle outline_stroke | 			StrokeStyle outline_stroke | ||||||
| 		) | 		) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.TextRenderer) | 			if (!d2d.text_renderer) | ||||||
| 				return E_UNEXPECTED; | 				return E_UNEXPECTED; | ||||||
| 
 | 
 | ||||||
| 			d2d.TextRenderer->SetTextStyle( | 			d2d.text_renderer->SetTextStyle( | ||||||
| 				color, | 				color, | ||||||
| 				has_outline, | 				has_outline, | ||||||
| 				outline_color, | 				outline_color, | ||||||
|  | @ -590,7 +628,7 @@ namespace easy2d | ||||||
| 			if (!fps_text_format_) | 			if (!fps_text_format_) | ||||||
| 			{ | 			{ | ||||||
| 				ThrowIfFailed( | 				ThrowIfFailed( | ||||||
| 					d2d.DWriteFactory->CreateTextFormat( | 					d2d.write_factory->CreateTextFormat( | ||||||
| 						L"", | 						L"", | ||||||
| 						nullptr, | 						nullptr, | ||||||
| 						DWRITE_FONT_WEIGHT_NORMAL, | 						DWRITE_FONT_WEIGHT_NORMAL, | ||||||
|  | @ -621,7 +659,7 @@ namespace easy2d | ||||||
| 				SafeRelease(fps_text_layout_); | 				SafeRelease(fps_text_layout_); | ||||||
| 
 | 
 | ||||||
| 				ThrowIfFailed( | 				ThrowIfFailed( | ||||||
| 					d2d.DWriteFactory->CreateTextLayout( | 					d2d.write_factory->CreateTextLayout( | ||||||
| 						fps_text, | 						fps_text, | ||||||
| 						static_cast<UINT32>(len), | 						static_cast<UINT32>(len), | ||||||
| 						fps_text_format_, | 						fps_text_format_, | ||||||
|  | @ -634,9 +672,9 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 			if (fps_text_layout_) | 			if (fps_text_layout_) | ||||||
| 			{ | 			{ | ||||||
| 				d2d.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); | 				d2d.render_target->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
| 				d2d.SolidColorBrush->SetOpacity(1.0f); | 				d2d.solid_brush->SetOpacity(1.0f); | ||||||
| 				d2d.TextRenderer->SetTextStyle( | 				d2d.text_renderer->SetTextStyle( | ||||||
| 					D2D1::ColorF(D2D1::ColorF::White), | 					D2D1::ColorF(D2D1::ColorF::White), | ||||||
| 					TRUE, | 					TRUE, | ||||||
| 					D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | 					D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | ||||||
|  | @ -644,13 +682,13 @@ namespace easy2d | ||||||
| 					D2D1_LINE_JOIN_ROUND | 					D2D1_LINE_JOIN_ROUND | ||||||
| 				); | 				); | ||||||
| 
 | 
 | ||||||
| 				fps_text_layout_->Draw(nullptr, d2d.TextRenderer, 10, 0); | 				fps_text_layout_->Draw(nullptr, d2d.text_renderer, 10, 0); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void GraphicsDevice::CreateDeviceResources(HWND hwnd) | 		void GraphicsDevice::CreateDeviceResources(HWND hwnd) | ||||||
| 		{ | 		{ | ||||||
| 			if (!d2d.HwndRenderTarget) | 			if (!d2d.render_target) | ||||||
| 			{ | 			{ | ||||||
| 				RECT rc; | 				RECT rc; | ||||||
| 				::GetClientRect(hwnd, &rc); | 				::GetClientRect(hwnd, &rc); | ||||||
|  | @ -663,35 +701,35 @@ namespace easy2d | ||||||
| 				// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 | 				// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 | ||||||
| 				// 创建一个 Direct2D 渲染目标
 | 				// 创建一个 Direct2D 渲染目标
 | ||||||
| 				ThrowIfFailed( | 				ThrowIfFailed( | ||||||
| 					d2d.Factory->CreateHwndRenderTarget( | 					d2d.factory->CreateHwndRenderTarget( | ||||||
| 						D2D1::RenderTargetProperties(), | 						D2D1::RenderTargetProperties(), | ||||||
| 						D2D1::HwndRenderTargetProperties( | 						D2D1::HwndRenderTargetProperties( | ||||||
| 							hwnd, | 							hwnd, | ||||||
| 							size, | 							size, | ||||||
| 							D2D1_PRESENT_OPTIONS_NONE), | 							D2D1_PRESENT_OPTIONS_NONE), | ||||||
| 						&d2d.HwndRenderTarget | 						&d2d.render_target | ||||||
| 					) | 					) | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (!d2d.SolidColorBrush) | 			if (!d2d.solid_brush) | ||||||
| 			{ | 			{ | ||||||
| 				ThrowIfFailed( | 				ThrowIfFailed( | ||||||
| 					d2d.HwndRenderTarget->CreateSolidColorBrush( | 					d2d.render_target->CreateSolidColorBrush( | ||||||
| 						D2D1::ColorF(D2D1::ColorF::White), | 						D2D1::ColorF(D2D1::ColorF::White), | ||||||
| 						&d2d.SolidColorBrush | 						&d2d.solid_brush | ||||||
| 					) | 					) | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (!d2d.TextRenderer) | 			if (!d2d.text_renderer) | ||||||
| 			{ | 			{ | ||||||
| 				ThrowIfFailed( | 				ThrowIfFailed( | ||||||
| 					ITextRenderer::Create( | 					ITextRenderer::Create( | ||||||
| 						&d2d.TextRenderer, | 						&d2d.text_renderer, | ||||||
| 						d2d.Factory, | 						d2d.factory, | ||||||
| 						d2d.HwndRenderTarget, | 						d2d.render_target, | ||||||
| 						d2d.SolidColorBrush | 						d2d.solid_brush | ||||||
| 					) | 					) | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "base.h" | #include "base.h" | ||||||
|  | #include "Singleton.hpp" | ||||||
| #include "Font.h" | #include "Font.h" | ||||||
| #include "Resource.h" | #include "Resource.h" | ||||||
| #include "Image.h" | #include "Image.h" | ||||||
|  | @ -28,38 +29,31 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace render | 	namespace devices | ||||||
| 	{ | 	{ | ||||||
| 		typedef struct | 		struct D2DResources | ||||||
| 		{ | 		{ | ||||||
| 			ID2D1Factory*			Factory; | 			ID2D1Factory*			factory; | ||||||
| 			IWICImagingFactory*		WICImagingFactory; | 			IWICImagingFactory*		imaging_factory; | ||||||
| 			IDWriteFactory*			DWriteFactory; | 			IDWriteFactory*			write_factory; | ||||||
| 			ITextRenderer*			TextRenderer; | 			ITextRenderer*			text_renderer; | ||||||
| 			ID2D1SolidColorBrush*	SolidColorBrush; | 			ID2D1SolidColorBrush*	solid_brush; | ||||||
| 			ID2D1HwndRenderTarget*	HwndRenderTarget; | 			ID2D1HwndRenderTarget*	render_target; | ||||||
| 			ID2D1StrokeStyle*		MiterStrokeStyle; | 			ID2D1StrokeStyle*		miter_stroke_style; | ||||||
| 			ID2D1StrokeStyle*		BevelStrokeStyle; | 			ID2D1StrokeStyle*		bevel_stroke_style; | ||||||
| 			ID2D1StrokeStyle*		RoundStrokeStyle; | 			ID2D1StrokeStyle*		round_stroke_style; | ||||||
| 		} D2DResources; | 		}; | ||||||
| 
 | 
 | ||||||
| 		typedef struct |  | ||||||
| 		{ |  | ||||||
| 			Rect area; |  | ||||||
| 			float opacity; |  | ||||||
| 		} LayerProperties; |  | ||||||
| 
 | 
 | ||||||
| 		class GraphicsDevice | 		class GraphicsDevice | ||||||
| 		{ | 		{ | ||||||
|  | 			E2D_DECLARE_SINGLETON(GraphicsDevice); | ||||||
|  | 
 | ||||||
|  | 			E2D_DISABLE_COPY(GraphicsDevice); | ||||||
|  | 
 | ||||||
| 		public: | 		public: | ||||||
| 			GraphicsDevice(); |  | ||||||
| 
 |  | ||||||
| 			~GraphicsDevice(); |  | ||||||
| 
 |  | ||||||
| 			void Initialize(HWND hwnd); | 			void Initialize(HWND hwnd); | ||||||
| 
 | 
 | ||||||
| 			void Uninitialize(); |  | ||||||
| 
 |  | ||||||
| 			// ¿ªÊ¼äÖȾ
 | 			// ¿ªÊ¼äÖȾ
 | ||||||
| 			void BeginDraw(HWND hwnd); | 			void BeginDraw(HWND hwnd); | ||||||
| 
 | 
 | ||||||
|  | @ -166,13 +160,21 @@ namespace easy2d | ||||||
| 				UINT32 height | 				UINT32 height | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | 			void ClearImageCache(); | ||||||
|  | 
 | ||||||
| 		protected: | 		protected: | ||||||
| 			D2D1_COLOR_F		clear_color_; | 			GraphicsDevice(); | ||||||
| 			IDWriteTextFormat*	fps_text_format_; | 
 | ||||||
| 			IDWriteTextLayout*	fps_text_layout_; | 			~GraphicsDevice(); | ||||||
| 			D2DResources		d2d; | 
 | ||||||
|  | 		protected: | ||||||
|  | 			D2DResources					d2d; | ||||||
|  | 			D2D1_COLOR_F					clear_color_; | ||||||
|  | 			IDWriteTextFormat*				fps_text_format_; | ||||||
|  | 			IDWriteTextLayout*				fps_text_layout_; | ||||||
|  | 			std::map<size_t, ID2D1Bitmap*>	bitmap_cache_; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		extern GraphicsDevice instance; | 		E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,332 +33,342 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace window | 	namespace | ||||||
| 	{ | 	{ | ||||||
| 		namespace | 		void GetContentScale(float* scale_x, float* scale_y); | ||||||
|  | 
 | ||||||
|  | 		Rect LocateWindow(int width, int height, float scale_x, float scale_y); | ||||||
|  | 
 | ||||||
|  | 		LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	WindowInfo::WindowInfo() | ||||||
|  | 		: handle(nullptr) | ||||||
|  | 		, scale_x(1.f) | ||||||
|  | 		, scale_y(1.f) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	WindowInfo::~WindowInfo() | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
|  | 			::DestroyWindow(handle); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void WindowInfo::Initialize(String title, int width, int height, LPCWSTR icon, bool debug) | ||||||
|  | 	{ | ||||||
|  | 		HINSTANCE hinstance	= GetModuleHandle(nullptr); | ||||||
|  | 		WNDCLASSEX wcex		= { 0 }; | ||||||
|  | 		wcex.cbSize			= sizeof(WNDCLASSEX); | ||||||
|  | 		wcex.lpszClassName	= REGISTER_CLASS; | ||||||
|  | 		wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; | ||||||
|  | 		wcex.lpfnWndProc	= WndProc; | ||||||
|  | 		wcex.hIcon			= nullptr; | ||||||
|  | 		wcex.cbClsExtra		= 0; | ||||||
|  | 		wcex.cbWndExtra		= sizeof(LONG_PTR); | ||||||
|  | 		wcex.hInstance		= hinstance; | ||||||
|  | 		wcex.hbrBackground	= nullptr; | ||||||
|  | 		wcex.lpszMenuName	= nullptr; | ||||||
|  | 		wcex.hCursor		= ::LoadCursor(nullptr, IDC_ARROW); | ||||||
|  | 
 | ||||||
|  | 		if (icon) | ||||||
| 		{ | 		{ | ||||||
| 			void GetContentScale(float* xscale, float* yscale); | 			wcex.hIcon = (HICON)::LoadImage( | ||||||
| 
 |  | ||||||
| 			Rect LocateWindow(int width, int height); |  | ||||||
| 
 |  | ||||||
| 			LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		WindowInfo instance; |  | ||||||
| 
 |  | ||||||
| 		WindowInfo::WindowInfo() |  | ||||||
| 			: handle(nullptr) |  | ||||||
| 			, xscale(1.f) |  | ||||||
| 			, yscale(1.f) |  | ||||||
| 		{ |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		void WindowInfo::Initialize(const Property& property) |  | ||||||
| 		{ |  | ||||||
| 			HINSTANCE hinstance	= GetModuleHandle(nullptr); |  | ||||||
| 			WNDCLASSEX wcex		= { 0 }; |  | ||||||
| 			wcex.cbSize			= sizeof(WNDCLASSEX); |  | ||||||
| 			wcex.lpszClassName	= REGISTER_CLASS; |  | ||||||
| 			wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; |  | ||||||
| 			wcex.lpfnWndProc	= WndProc; |  | ||||||
| 			wcex.hIcon			= nullptr; |  | ||||||
| 			wcex.cbClsExtra		= 0; |  | ||||||
| 			wcex.cbWndExtra		= sizeof(LONG_PTR); |  | ||||||
| 			wcex.hInstance		= hinstance; |  | ||||||
| 			wcex.hbrBackground	= nullptr; |  | ||||||
| 			wcex.lpszMenuName	= nullptr; |  | ||||||
| 			wcex.hCursor		= ::LoadCursor(nullptr, IDC_ARROW); |  | ||||||
| 
 |  | ||||||
| 			if (property.icon) |  | ||||||
| 			{ |  | ||||||
| 				wcex.hIcon = (HICON)::LoadImage( |  | ||||||
| 					hinstance, |  | ||||||
| 					property.icon, |  | ||||||
| 					IMAGE_ICON, |  | ||||||
| 					0, |  | ||||||
| 					0, |  | ||||||
| 					LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			::RegisterClassEx(&wcex); |  | ||||||
| 
 |  | ||||||
| 			GetContentScale(&xscale, &yscale); |  | ||||||
| 
 |  | ||||||
| 			// 计算窗口大小
 |  | ||||||
| 			Rect client_rect = LocateWindow(property.width, property.height); |  | ||||||
| 
 |  | ||||||
| 			// 创建窗口
 |  | ||||||
| 			handle = ::CreateWindowEx( |  | ||||||
| 				NULL, |  | ||||||
| 				REGISTER_CLASS, |  | ||||||
| 				property.title.c_str(), |  | ||||||
| 				WINDOW_STYLE, |  | ||||||
| 				static_cast<int>(client_rect.origin.x), |  | ||||||
| 				static_cast<int>(client_rect.origin.y), |  | ||||||
| 				static_cast<int>(client_rect.size.width), |  | ||||||
| 				static_cast<int>(client_rect.size.height), |  | ||||||
| 				nullptr, |  | ||||||
| 				nullptr, |  | ||||||
| 				hinstance, | 				hinstance, | ||||||
| 				this | 				icon, | ||||||
|  | 				IMAGE_ICON, | ||||||
|  | 				0, | ||||||
|  | 				0, | ||||||
|  | 				LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | ||||||
| 			); | 			); | ||||||
| 
 |  | ||||||
| 			if (handle == nullptr) |  | ||||||
| 			{ |  | ||||||
| 				::UnregisterClass(REGISTER_CLASS, hinstance); |  | ||||||
| 				throw std::runtime_error("Create window failed"); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// 禁用输入法
 |  | ||||||
| 			::ImmAssociateContext(handle, nullptr); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void WindowInfo::Destroy() | 		::RegisterClassEx(&wcex); | ||||||
|  | 
 | ||||||
|  | 		GetContentScale(&scale_x, &scale_y); | ||||||
|  | 
 | ||||||
|  | 		// 计算窗口大小
 | ||||||
|  | 		Rect client_rect = LocateWindow(width, height, scale_x, scale_y); | ||||||
|  | 
 | ||||||
|  | 		// 创建窗口
 | ||||||
|  | 		handle = ::CreateWindowEx( | ||||||
|  | 			NULL, | ||||||
|  | 			REGISTER_CLASS, | ||||||
|  | 			title.c_str(), | ||||||
|  | 			WINDOW_STYLE, | ||||||
|  | 			static_cast<int>(client_rect.origin.x), | ||||||
|  | 			static_cast<int>(client_rect.origin.y), | ||||||
|  | 			static_cast<int>(client_rect.size.width), | ||||||
|  | 			static_cast<int>(client_rect.size.height), | ||||||
|  | 			nullptr, | ||||||
|  | 			nullptr, | ||||||
|  | 			hinstance, | ||||||
|  | 			this | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		if (handle == nullptr) | ||||||
| 		{ | 		{ | ||||||
| 			if (handle) | 			::UnregisterClass(REGISTER_CLASS, hinstance); | ||||||
| 				::DestroyWindow(handle); | 			throw std::runtime_error("Create window failed"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		String WindowInfo::GetTitle() const | 		// 禁用输入法
 | ||||||
|  | 		::ImmAssociateContext(handle, nullptr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	String WindowInfo::GetTitle() const | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
| 		{ | 		{ | ||||||
| 			if (handle) | 			wchar_t title[256]; | ||||||
| 			{ | 			GetWindowTextW(handle, title, 256); | ||||||
| 				wchar_t title[256]; | 			return title; | ||||||
| 				GetWindowTextW(handle, title, 256); |  | ||||||
| 				return title; |  | ||||||
| 			} |  | ||||||
| 			return String(); |  | ||||||
| 		} | 		} | ||||||
|  | 		return String(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		void WindowInfo::SetTitle(const String& title) | 	void WindowInfo::SetTitle(const String& title) | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
|  | 			::SetWindowText(handle, title.c_str()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Size WindowInfo::GetSize() const | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
| 		{ | 		{ | ||||||
| 			if (handle) | 			RECT rect; | ||||||
| 				::SetWindowText(handle, title.c_str()); | 			GetClientRect(handle, &rect); | ||||||
|  | 			return Size( | ||||||
|  | 				static_cast<float>(rect.right - rect.left), | ||||||
|  | 				static_cast<float>(rect.bottom - rect.top) | ||||||
|  | 			); | ||||||
| 		} | 		} | ||||||
|  | 		return Size(); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		Size WindowInfo::GetSize() const | 	float WindowInfo::GetWidth() const | ||||||
|  | 	{ | ||||||
|  | 		return GetSize().width; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float WindowInfo::GetHeight() const | ||||||
|  | 	{ | ||||||
|  | 		return GetSize().height; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void WindowInfo::SetSize(int width, int height) | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
| 		{ | 		{ | ||||||
| 			if (handle) | 			Rect rect = LocateWindow(width, height, scale_x, scale_y); | ||||||
| 			{ | 			::MoveWindow( | ||||||
| 				RECT rect; | 				handle, | ||||||
| 				GetClientRect(handle, &rect); | 				static_cast<int>(rect.origin.x), | ||||||
| 				return Size( | 				static_cast<int>(rect.origin.y), | ||||||
| 					static_cast<float>(rect.right - rect.left), | 				static_cast<int>(rect.size.width), | ||||||
| 					static_cast<float>(rect.bottom - rect.top) | 				static_cast<int>(rect.size.height), | ||||||
| 				); | 				TRUE | ||||||
| 			} | 			); | ||||||
| 			return Size(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		float WindowInfo::GetWidth() const |  | ||||||
| 		{ |  | ||||||
| 			return GetSize().width; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		float WindowInfo::GetHeight() const |  | ||||||
| 		{ |  | ||||||
| 			return GetSize().height; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		void WindowInfo::SetSize(int width, int height) |  | ||||||
| 		{ |  | ||||||
| 			if (handle) |  | ||||||
| 			{ |  | ||||||
| 				Rect rect = LocateWindow(width, height); |  | ||||||
| 				::MoveWindow( |  | ||||||
| 					handle, |  | ||||||
| 					static_cast<int>(rect.origin.x), |  | ||||||
| 					static_cast<int>(rect.origin.y), |  | ||||||
| 					static_cast<int>(rect.size.width), |  | ||||||
| 					static_cast<int>(rect.size.height), |  | ||||||
| 					TRUE |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		void WindowInfo::SetIcon(LPCWSTR icon_resource) |  | ||||||
| 		{ |  | ||||||
| 			if (handle) |  | ||||||
| 			{ |  | ||||||
| 				HINSTANCE hinstance = GetModuleHandle(nullptr); |  | ||||||
| 				HICON icon = (HICON)::LoadImage( |  | ||||||
| 					hinstance, |  | ||||||
| 					icon_resource, |  | ||||||
| 					IMAGE_ICON, |  | ||||||
| 					0, |  | ||||||
| 					0, |  | ||||||
| 					LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE |  | ||||||
| 				); |  | ||||||
| 
 |  | ||||||
| 				::SendMessage(handle, WM_SETICON, ICON_BIG, (LPARAM)icon); |  | ||||||
| 				::SendMessage(handle, WM_SETICON, ICON_SMALL, (LPARAM)icon); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		namespace |  | ||||||
| 		{ |  | ||||||
| 			void GetContentScale(float* xscale, float* yscale) |  | ||||||
| 			{ |  | ||||||
| 				const float DEFAULT_SCREEN_DPI = 96.f; |  | ||||||
| 				const HDC dc = GetDC(NULL); |  | ||||||
| 				float xdpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSX)); |  | ||||||
| 				float ydpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSY)); |  | ||||||
| 				ReleaseDC(NULL, dc); |  | ||||||
| 
 |  | ||||||
| 				if (xscale) |  | ||||||
| 					*xscale = xdpi / DEFAULT_SCREEN_DPI; |  | ||||||
| 				if (yscale) |  | ||||||
| 					*yscale = ydpi / DEFAULT_SCREEN_DPI; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Rect LocateWindow(int width, int height) |  | ||||||
| 			{ |  | ||||||
| 				int max_width = ::GetSystemMetrics(SM_CXSCREEN); |  | ||||||
| 				int max_height = ::GetSystemMetrics(SM_CYSCREEN); |  | ||||||
| 				RECT rect = |  | ||||||
| 				{ |  | ||||||
| 					0, |  | ||||||
| 					0, |  | ||||||
| 					static_cast<LONG>(math::Ceil(width * instance.xscale)), |  | ||||||
| 					static_cast<LONG>(math::Ceil(height * instance.yscale)) |  | ||||||
| 				}; |  | ||||||
| 
 |  | ||||||
| 				// 计算合适的窗口大小
 |  | ||||||
| 				::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); |  | ||||||
| 				width = static_cast<int>(rect.right - rect.left); |  | ||||||
| 				height = static_cast<int>(rect.bottom - rect.top); |  | ||||||
| 
 |  | ||||||
| 				// 当输入的窗口大小比分辨率大时,给出警告
 |  | ||||||
| 				E2D_WARNING_IF(max_width < width || max_height < height, "The window Is larger than screen!"); |  | ||||||
| 				width = std::min(width, max_width); |  | ||||||
| 				height = std::min(height, max_height); |  | ||||||
| 
 |  | ||||||
| 				return Rect( |  | ||||||
| 					static_cast<float>((max_width - width) / 2), |  | ||||||
| 					static_cast<float>((max_height - height) / 2), |  | ||||||
| 					static_cast<float>(width), |  | ||||||
| 					static_cast<float>(height) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) |  | ||||||
| 			{ |  | ||||||
| 				LRESULT result = 0; |  | ||||||
| 				bool was_handled = false; |  | ||||||
| 
 |  | ||||||
| 				Game * game = reinterpret_cast<Game*>( |  | ||||||
| 					static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)) |  | ||||||
| 				); |  | ||||||
| 
 |  | ||||||
| 				switch (msg) |  | ||||||
| 				{ |  | ||||||
| 
 |  | ||||||
| 				// 处理鼠标消息
 |  | ||||||
| 				case WM_LBUTTONUP: |  | ||||||
| 				case WM_LBUTTONDOWN: |  | ||||||
| 				case WM_LBUTTONDBLCLK: |  | ||||||
| 				case WM_MBUTTONUP: |  | ||||||
| 				case WM_MBUTTONDOWN: |  | ||||||
| 				case WM_MBUTTONDBLCLK: |  | ||||||
| 				case WM_RBUTTONUP: |  | ||||||
| 				case WM_RBUTTONDOWN: |  | ||||||
| 				case WM_RBUTTONDBLCLK: |  | ||||||
| 				case WM_MOUSEMOVE: |  | ||||||
| 				case WM_MOUSEWHEEL: |  | ||||||
| 				{ |  | ||||||
| 					if (game->IsTransitioning()) |  | ||||||
| 						break; |  | ||||||
| 
 |  | ||||||
| 					auto curr_scene = game->GetCurrentScene(); |  | ||||||
| 					if (curr_scene) |  | ||||||
| 					{ |  | ||||||
| 						curr_scene->Dispatch(MouseEvent(msg, w_param, l_param)); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				result = 0; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 处理按键消息
 |  | ||||||
| 				case WM_KEYDOWN: |  | ||||||
| 				case WM_KEYUP: |  | ||||||
| 				{ |  | ||||||
| 					if (game->IsTransitioning()) |  | ||||||
| 						break; |  | ||||||
| 
 |  | ||||||
| 					auto curr_scene = game->GetCurrentScene(); |  | ||||||
| 					if (curr_scene) |  | ||||||
| 					{ |  | ||||||
| 						curr_scene->Dispatch(KeyEvent(msg, w_param, l_param)); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				result = 0; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 处理窗口大小变化消息
 |  | ||||||
| 				case WM_SIZE: |  | ||||||
| 				{ |  | ||||||
| 					UINT width = LOWORD(l_param); |  | ||||||
| 					UINT height = HIWORD(l_param); |  | ||||||
| 
 |  | ||||||
| 					// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
 |  | ||||||
| 					// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
 |  | ||||||
| 					// 错误,因为这个错误将在下一次调用 EndDraw 时产生
 |  | ||||||
| 					render::instance.Resize(width, height); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 处理分辨率变化消息
 |  | ||||||
| 				case WM_DISPLAYCHANGE: |  | ||||||
| 				{ |  | ||||||
| 					// 重绘客户区
 |  | ||||||
| 					::InvalidateRect(hwnd, nullptr, FALSE); |  | ||||||
| 				} |  | ||||||
| 				result = 0; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 重绘窗口
 |  | ||||||
| 				case WM_PAINT: |  | ||||||
| 				{ |  | ||||||
| 					game->DrawScene(); |  | ||||||
| 					::ValidateRect(hwnd, nullptr); |  | ||||||
| 				} |  | ||||||
| 				result = 0; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 窗口关闭消息
 |  | ||||||
| 				case WM_CLOSE: |  | ||||||
| 				{ |  | ||||||
| 					if (game->OnClose()) |  | ||||||
| 					{ |  | ||||||
| 						game->Quit(); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				result = 0; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				// 窗口销毁消息
 |  | ||||||
| 				case WM_DESTROY: |  | ||||||
| 				{ |  | ||||||
| 					::PostQuitMessage(0); |  | ||||||
| 				} |  | ||||||
| 				result = 1; |  | ||||||
| 				was_handled = true; |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (!was_handled) |  | ||||||
| 				{ |  | ||||||
| 					result = ::DefWindowProc(hwnd, msg, w_param, l_param); |  | ||||||
| 				} |  | ||||||
| 				return result; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | 
 | ||||||
|  | 	void WindowInfo::SetIcon(LPCWSTR icon_resource) | ||||||
|  | 	{ | ||||||
|  | 		if (handle) | ||||||
|  | 		{ | ||||||
|  | 			HINSTANCE hinstance = GetModuleHandle(nullptr); | ||||||
|  | 			HICON icon = (HICON)::LoadImage( | ||||||
|  | 				hinstance, | ||||||
|  | 				icon_resource, | ||||||
|  | 				IMAGE_ICON, | ||||||
|  | 				0, | ||||||
|  | 				0, | ||||||
|  | 				LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			::SendMessage(handle, WM_SETICON, ICON_BIG, (LPARAM)icon); | ||||||
|  | 			::SendMessage(handle, WM_SETICON, ICON_SMALL, (LPARAM)icon); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	HWND WindowInfo::GetHandle() const | ||||||
|  | 	{ | ||||||
|  | 		return handle; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float WindowInfo::GetContentScaleX() const | ||||||
|  | 	{ | ||||||
|  | 		return scale_x; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float WindowInfo::GetContentScaleY() const | ||||||
|  | 	{ | ||||||
|  | 		return scale_y; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	namespace | ||||||
|  | 	{ | ||||||
|  | 		void GetContentScale(float* scale_x, float* scale_y) | ||||||
|  | 		{ | ||||||
|  | 			const float DEFAULT_SCREEN_DPI = 96.f; | ||||||
|  | 			const HDC dc = GetDC(NULL); | ||||||
|  | 			float xdpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSX)); | ||||||
|  | 			float ydpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSY)); | ||||||
|  | 			ReleaseDC(NULL, dc); | ||||||
|  | 
 | ||||||
|  | 			if (scale_x) | ||||||
|  | 				*scale_x = xdpi / DEFAULT_SCREEN_DPI; | ||||||
|  | 			if (scale_y) | ||||||
|  | 				*scale_y = ydpi / DEFAULT_SCREEN_DPI; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Rect LocateWindow(int width, int height, float scale_x, float scale_y) | ||||||
|  | 		{ | ||||||
|  | 			int max_width = ::GetSystemMetrics(SM_CXSCREEN); | ||||||
|  | 			int max_height = ::GetSystemMetrics(SM_CYSCREEN); | ||||||
|  | 			RECT rect = | ||||||
|  | 			{ | ||||||
|  | 				0, | ||||||
|  | 				0, | ||||||
|  | 				static_cast<LONG>(math::Ceil(width * scale_x)), | ||||||
|  | 				static_cast<LONG>(math::Ceil(height * scale_y)) | ||||||
|  | 			}; | ||||||
|  | 
 | ||||||
|  | 			// 计算合适的窗口大小
 | ||||||
|  | 			::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); | ||||||
|  | 			width = static_cast<int>(rect.right - rect.left); | ||||||
|  | 			height = static_cast<int>(rect.bottom - rect.top); | ||||||
|  | 
 | ||||||
|  | 			// 当输入的窗口大小比分辨率大时,给出警告
 | ||||||
|  | 			E2D_WARNING_IF(max_width < width || max_height < height, "The window Is larger than screen!"); | ||||||
|  | 			width = std::min(width, max_width); | ||||||
|  | 			height = std::min(height, max_height); | ||||||
|  | 
 | ||||||
|  | 			return Rect( | ||||||
|  | 				static_cast<float>((max_width - width) / 2), | ||||||
|  | 				static_cast<float>((max_height - height) / 2), | ||||||
|  | 				static_cast<float>(width), | ||||||
|  | 				static_cast<float>(height) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) | ||||||
|  | 		{ | ||||||
|  | 			LRESULT result = 0; | ||||||
|  | 			bool was_handled = false; | ||||||
|  | 
 | ||||||
|  | 			Game * game = reinterpret_cast<Game*>( | ||||||
|  | 				static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)) | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 			switch (msg) | ||||||
|  | 			{ | ||||||
|  | 
 | ||||||
|  | 			// 处理鼠标消息
 | ||||||
|  | 			case WM_LBUTTONUP: | ||||||
|  | 			case WM_LBUTTONDOWN: | ||||||
|  | 			case WM_LBUTTONDBLCLK: | ||||||
|  | 			case WM_MBUTTONUP: | ||||||
|  | 			case WM_MBUTTONDOWN: | ||||||
|  | 			case WM_MBUTTONDBLCLK: | ||||||
|  | 			case WM_RBUTTONUP: | ||||||
|  | 			case WM_RBUTTONDOWN: | ||||||
|  | 			case WM_RBUTTONDBLCLK: | ||||||
|  | 			case WM_MOUSEMOVE: | ||||||
|  | 			case WM_MOUSEWHEEL: | ||||||
|  | 			{ | ||||||
|  | 				if (game->IsTransitioning()) | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				auto curr_scene = game->GetCurrentScene(); | ||||||
|  | 				if (curr_scene) | ||||||
|  | 				{ | ||||||
|  | 					curr_scene->Dispatch(MouseEvent(msg, w_param, l_param)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			result = 0; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 处理按键消息
 | ||||||
|  | 			case WM_KEYDOWN: | ||||||
|  | 			case WM_KEYUP: | ||||||
|  | 			{ | ||||||
|  | 				if (game->IsTransitioning()) | ||||||
|  | 					break; | ||||||
|  | 
 | ||||||
|  | 				auto curr_scene = game->GetCurrentScene(); | ||||||
|  | 				if (curr_scene) | ||||||
|  | 				{ | ||||||
|  | 					curr_scene->Dispatch(KeyEvent(msg, w_param, l_param)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			result = 0; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 处理窗口大小变化消息
 | ||||||
|  | 			case WM_SIZE: | ||||||
|  | 			{ | ||||||
|  | 				UINT width = LOWORD(l_param); | ||||||
|  | 				UINT height = HIWORD(l_param); | ||||||
|  | 
 | ||||||
|  | 				// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
 | ||||||
|  | 				// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
 | ||||||
|  | 				// 错误,因为这个错误将在下一次调用 EndDraw 时产生
 | ||||||
|  | 				devices::Graphics::Instance().Resize(width, height); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 处理分辨率变化消息
 | ||||||
|  | 			case WM_DISPLAYCHANGE: | ||||||
|  | 			{ | ||||||
|  | 				// 重绘客户区
 | ||||||
|  | 				::InvalidateRect(hwnd, nullptr, FALSE); | ||||||
|  | 			} | ||||||
|  | 			result = 0; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 重绘窗口
 | ||||||
|  | 			case WM_PAINT: | ||||||
|  | 			{ | ||||||
|  | 				game->DrawScene(); | ||||||
|  | 				::ValidateRect(hwnd, nullptr); | ||||||
|  | 			} | ||||||
|  | 			result = 0; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 窗口关闭消息
 | ||||||
|  | 			case WM_CLOSE: | ||||||
|  | 			{ | ||||||
|  | 				if (game->OnClose()) | ||||||
|  | 				{ | ||||||
|  | 					game->Quit(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			result = 0; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			// 窗口销毁消息
 | ||||||
|  | 			case WM_DESTROY: | ||||||
|  | 			{ | ||||||
|  | 				::PostQuitMessage(0); | ||||||
|  | 			} | ||||||
|  | 			result = 1; | ||||||
|  | 			was_handled = true; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!was_handled) | ||||||
|  | 			{ | ||||||
|  | 				result = ::DefWindowProc(hwnd, msg, w_param, l_param); | ||||||
|  | 			} | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -20,64 +20,64 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "base.h" | #include "base.h" | ||||||
|  | #include "Singleton.hpp" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace window | 	 | ||||||
|  | 
 | ||||||
|  | 	class WindowInfo | ||||||
| 	{ | 	{ | ||||||
| 		typedef struct Property | 		E2D_DECLARE_SINGLETON(WindowInfo); | ||||||
| 		{ |  | ||||||
| 			String	title;	/* 标题 */ |  | ||||||
| 			int		width;	/* 宽度 */ |  | ||||||
| 			int		height;	/* 高度 */ |  | ||||||
| 			LPCWSTR	icon;	/* 图标 */ |  | ||||||
| 
 | 
 | ||||||
| 			Property() | 		E2D_DISABLE_COPY(WindowInfo); | ||||||
| 				: title(L"Easy2D Game") |  | ||||||
| 				, width(640) |  | ||||||
| 				, height(480) |  | ||||||
| 				, icon(nullptr) |  | ||||||
| 			{} |  | ||||||
| 		} Property; |  | ||||||
| 
 | 
 | ||||||
| 		class WindowInfo | 	public: | ||||||
| 		{ | 		void Initialize( | ||||||
| 		public: | 			String	title, | ||||||
| 			HWND handle; | 			int		width, | ||||||
| 			float xscale; | 			int		height, | ||||||
| 			float yscale; | 			LPCWSTR	icon, | ||||||
|  | 			bool	debug | ||||||
|  | 		); | ||||||
| 
 | 
 | ||||||
| 		public: | 		// 获取标题
 | ||||||
| 			WindowInfo(); | 		String GetTitle() const; | ||||||
| 
 | 
 | ||||||
| 			void Initialize( | 		// 设置标题
 | ||||||
| 				const Property& property | 		void SetTitle(const String& title); | ||||||
| 			); |  | ||||||
| 
 | 
 | ||||||
| 			void Destroy(); | 		// 获取窗口大小
 | ||||||
|  | 		Size GetSize() const; | ||||||
| 
 | 
 | ||||||
| 			// 获取标题
 | 		// 获取窗口宽度
 | ||||||
| 			String GetTitle() const; | 		float GetWidth() const; | ||||||
| 
 | 
 | ||||||
| 			// 设置标题
 | 		// 获取窗口高度
 | ||||||
| 			void SetTitle(const String& title); | 		float GetHeight() const; | ||||||
| 
 | 
 | ||||||
| 			// 获取窗口大小
 | 		// 重设窗口大小
 | ||||||
| 			Size GetSize() const; | 		void SetSize(int width, int height); | ||||||
| 
 | 
 | ||||||
| 			// 获取窗口宽度
 | 		// 设置窗口图标
 | ||||||
| 			float GetWidth() const; | 		void SetIcon(LPCWSTR icon_resource); | ||||||
| 
 | 
 | ||||||
| 			// 获取窗口高度
 | 		HWND GetHandle() const; | ||||||
| 			float GetHeight() const; |  | ||||||
| 
 | 
 | ||||||
| 			// 重设窗口大小
 | 		float GetContentScaleX() const; | ||||||
| 			void SetSize(int width, int height); |  | ||||||
| 
 | 
 | ||||||
| 			// 设置窗口图标
 | 		float GetContentScaleY() const; | ||||||
| 			void SetIcon(LPCWSTR icon_resource); |  | ||||||
| 		}; |  | ||||||
| 
 | 
 | ||||||
| 		extern WindowInfo instance; | 	protected: | ||||||
| 	} | 		WindowInfo(); | ||||||
|  | 
 | ||||||
|  | 		~WindowInfo(); | ||||||
|  | 
 | ||||||
|  | 	private: | ||||||
|  | 		HWND handle; | ||||||
|  | 		float scale_x; | ||||||
|  | 		float scale_y; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	E2D_DECLARE_SINGLETON_TYPE(WindowInfo, Window); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ | ||||||
| #include "base/CallFunc.h" | #include "base/CallFunc.h" | ||||||
| #include "base/Canvas.h" | #include "base/Canvas.h" | ||||||
| #include "base/Transition.h" | #include "base/Transition.h" | ||||||
|  | #include "base/Music.h" | ||||||
| 
 | 
 | ||||||
| #include "base/KeyEvent.h" | #include "base/KeyEvent.h" | ||||||
| #include "base/MouseEvent.h" | #include "base/MouseEvent.h" | ||||||
|  | @ -85,9 +86,8 @@ | ||||||
| #include "utils/Path.h" | #include "utils/Path.h" | ||||||
| #include "utils/Data.h" | #include "utils/Data.h" | ||||||
| #include "utils/File.h" | #include "utils/File.h" | ||||||
| #include "utils/Transcoder.h" |  | ||||||
| #include "utils/Music.h" |  | ||||||
| #include "utils/Player.h" | #include "utils/Player.h" | ||||||
|  | #include "utils/Transcoder.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| //
 | //
 | ||||||
|  |  | ||||||
|  | @ -112,9 +112,9 @@ namespace easy2d | ||||||
| 				return *this; | 				return *this; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			inline Matrix& Scale(float xscale, float yscale, const Vector2& center) | 			inline Matrix& Scale(float scale_x, float scale_y, const Vector2& center) | ||||||
| 			{ | 			{ | ||||||
| 				*this = *this * Matrix::Scaling(xscale, yscale, center); | 				*this = *this * Matrix::Scaling(scale_x, scale_y, center); | ||||||
| 				return *this; | 				return *this; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,6 +50,16 @@ namespace easy2d | ||||||
| 			, y(other.y) | 			, y(other.y) | ||||||
| 			{} | 			{} | ||||||
| 
 | 
 | ||||||
|  | 			inline float Length() const | ||||||
|  | 			{ | ||||||
|  | 				return math::Sqrt(x * x + y * y); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			inline float Distance(const Vector2& v) | ||||||
|  | 			{ | ||||||
|  | 				return Vector2(x - v.x, y - v.y).Length(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			inline Vector2 operator + (const Vector2 & other) const | 			inline Vector2 operator + (const Vector2 & other) const | ||||||
| 			{ | 			{ | ||||||
| 				return Vector2(x + other.x, y + other.y); | 				return Vector2(x + other.x, y + other.y); | ||||||
|  | @ -80,13 +90,6 @@ namespace easy2d | ||||||
| 				return (x == other.x) && (y == other.y); | 				return (x == other.x) && (y == other.y); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			inline float Length() const { return math::Sqrt(x * x + y * y); } |  | ||||||
| 
 |  | ||||||
| 			inline float Distance(const Vector2& v) |  | ||||||
| 			{ |  | ||||||
| 				return Vector2(x - v.x, y - v.y).Length(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			inline operator D2D1_POINT_2F () const | 			inline operator D2D1_POINT_2F () const | ||||||
| 			{ | 			{ | ||||||
| 				return D2D1_POINT_2F{ x, y }; | 				return D2D1_POINT_2F{ x, y }; | ||||||
|  |  | ||||||
|  | @ -223,7 +223,7 @@ namespace easy2d | ||||||
| 			if (IsVisible() && | 			if (IsVisible() && | ||||||
| 				!enabled_ && | 				!enabled_ && | ||||||
| 				normal_ && | 				normal_ && | ||||||
| 				normal_->ContainsPoint(input::instance.GetMousePos())) | 				normal_->ContainsPoint(devices::Input::Instance().GetMousePos())) | ||||||
| 			{ | 			{ | ||||||
| 				HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | 				HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | ||||||
| 				if (hcursor) | 				if (hcursor) | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ namespace easy2d | ||||||
| 		class Button | 		class Button | ||||||
| 			: public Node | 			: public Node | ||||||
| 		{ | 		{ | ||||||
|  | 			E2D_DISABLE_COPY(Button); | ||||||
|  | 
 | ||||||
| 			typedef std::function<void()> Callback; | 			typedef std::function<void()> Callback; | ||||||
| 
 | 
 | ||||||
| 		public: | 		public: | ||||||
|  | @ -101,8 +103,6 @@ namespace easy2d | ||||||
| 			) override; | 			) override; | ||||||
| 
 | 
 | ||||||
| 		private: | 		private: | ||||||
| 			E2D_DISABLE_COPY(Button); |  | ||||||
| 
 |  | ||||||
| 			// °´Å¥×´Ì¬Ã¶¾Ù
 | 			// °´Å¥×´Ì¬Ã¶¾Ù
 | ||||||
| 			enum class Status { Normal, Mouseover, Selected }; | 			enum class Status { Normal, Mouseover, Selected }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,8 @@ namespace easy2d | ||||||
| 		class Menu | 		class Menu | ||||||
| 			: public Node | 			: public Node | ||||||
| 		{ | 		{ | ||||||
|  | 			E2D_DISABLE_COPY(Menu); | ||||||
|  | 
 | ||||||
| 		public: | 		public: | ||||||
| 			Menu(); | 			Menu(); | ||||||
| 
 | 
 | ||||||
|  | @ -61,9 +63,6 @@ namespace easy2d | ||||||
| 			// 获取所有按钮
 | 			// 获取所有按钮
 | ||||||
| 			const std::vector<Button*>& GetAllButtons() const; | 			const std::vector<Button*>& GetAllButtons() const; | ||||||
| 
 | 
 | ||||||
| 		private: |  | ||||||
| 			E2D_DISABLE_COPY(Menu); |  | ||||||
| 
 |  | ||||||
| 		private: | 		private: | ||||||
| 			bool enabled_; | 			bool enabled_; | ||||||
| 			std::vector<Button*> buttons_; | 			std::vector<Button*> buttons_; | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 			// 设置数据的保存路径
 | 			// 设置数据的保存路径
 | ||||||
| 			String local_app_data_path = Path::GetLocalAppDataPath(); | 			String local_app_data_path = Path::GetLocalAppDataPath(); | ||||||
| 			String title = window::instance.GetTitle(); | 			String title = Window::Instance().GetTitle(); | ||||||
| 			String folder_name = std::to_wstring(std::hash<String>{}(title)); | 			String folder_name = std::to_wstring(std::hash<String>{}(title)); | ||||||
| 
 | 
 | ||||||
| 			if (!local_app_data_path.empty()) | 			if (!local_app_data_path.empty()) | ||||||
|  | @ -90,7 +90,7 @@ namespace easy2d | ||||||
| 		{ | 		{ | ||||||
| 			// 设置临时文件保存路径
 | 			// 设置临时文件保存路径
 | ||||||
| 			wchar_t path[_MAX_PATH]; | 			wchar_t path[_MAX_PATH]; | ||||||
| 			String title = window::instance.GetTitle(); | 			String title = Window::Instance().GetTitle(); | ||||||
| 			String folder_name = std::to_wstring(std::hash<String>{}(title)); | 			String folder_name = std::to_wstring(std::hash<String>{}(title)); | ||||||
| 
 | 
 | ||||||
| 			if (0 != ::GetTempPath(_MAX_PATH, path)) | 			if (0 != ::GetTempPath(_MAX_PATH, path)) | ||||||
|  |  | ||||||
|  | @ -19,15 +19,10 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #include "Player.h" | #include "Player.h" | ||||||
| #include "Music.h" | #include "../base/Music.h" | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	namespace |  | ||||||
| 	{ |  | ||||||
| 		std::map<size_t, Music*> musics_; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Player::Player() | 	Player::Player() | ||||||
| 		: volume_(1.f) | 		: volume_(1.f) | ||||||
| 	{ | 	{ | ||||||
|  | @ -35,6 +30,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	Player::~Player() | 	Player::~Player() | ||||||
| 	{ | 	{ | ||||||
|  | 		ClearCache(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Player::Load(const String & file_path) | 	bool Player::Load(const String & file_path) | ||||||
|  | @ -51,7 +47,7 @@ namespace easy2d | ||||||
| 				music->SetVolume(volume_); | 				music->SetVolume(volume_); | ||||||
| 
 | 
 | ||||||
| 				size_t hash_code = std::hash<String>{}(file_path); | 				size_t hash_code = std::hash<String>{}(file_path); | ||||||
| 				musics_.insert(std::make_pair(hash_code, music)); | 				musics_cache_.insert(std::make_pair(hash_code, music)); | ||||||
| 				return true; | 				return true; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
|  | @ -69,7 +65,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		if (Load(file_path)) | 		if (Load(file_path)) | ||||||
| 		{ | 		{ | ||||||
| 			auto music = musics_[std::hash<String>{}(file_path)]; | 			auto music = musics_cache_[std::hash<String>{}(file_path)]; | ||||||
| 			if (music->Play(loop_count)) | 			if (music->Play(loop_count)) | ||||||
| 			{ | 			{ | ||||||
| 				return true; | 				return true; | ||||||
|  | @ -84,8 +80,8 @@ namespace easy2d | ||||||
| 			return; | 			return; | ||||||
| 
 | 
 | ||||||
| 		size_t hash_code = std::hash<String>{}(file_path); | 		size_t hash_code = std::hash<String>{}(file_path); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Pause(); | 			musics_cache_[hash_code]->Pause(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Player::Resume(const String & file_path) | 	void Player::Resume(const String & file_path) | ||||||
|  | @ -94,8 +90,8 @@ namespace easy2d | ||||||
| 			return; | 			return; | ||||||
| 
 | 
 | ||||||
| 		size_t hash_code = std::hash<String>{}(file_path); | 		size_t hash_code = std::hash<String>{}(file_path); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Resume(); | 			musics_cache_[hash_code]->Resume(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Player::Stop(const String & file_path) | 	void Player::Stop(const String & file_path) | ||||||
|  | @ -104,8 +100,8 @@ namespace easy2d | ||||||
| 			return; | 			return; | ||||||
| 
 | 
 | ||||||
| 		size_t hash_code = std::hash<String>{}(file_path); | 		size_t hash_code = std::hash<String>{}(file_path); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Stop(); | 			musics_cache_[hash_code]->Stop(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Player::IsPlaying(const String & file_path) | 	bool Player::IsPlaying(const String & file_path) | ||||||
|  | @ -114,15 +110,15 @@ namespace easy2d | ||||||
| 			return false; | 			return false; | ||||||
| 
 | 
 | ||||||
| 		size_t hash_code = std::hash<String>{}(file_path); | 		size_t hash_code = std::hash<String>{}(file_path); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			return musics_[hash_code]->IsPlaying(); | 			return musics_cache_[hash_code]->IsPlaying(); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Player::Load(Resource& res) | 	bool Player::Load(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			return true; | 			return true; | ||||||
| 
 | 
 | ||||||
| 		Music * music = new (std::nothrow) Music(); | 		Music * music = new (std::nothrow) Music(); | ||||||
|  | @ -132,7 +128,7 @@ namespace easy2d | ||||||
| 			if (music->Load(res)) | 			if (music->Load(res)) | ||||||
| 			{ | 			{ | ||||||
| 				music->SetVolume(volume_); | 				music->SetVolume(volume_); | ||||||
| 				musics_.insert(std::make_pair(hash_code, music)); | 				musics_cache_.insert(std::make_pair(hash_code, music)); | ||||||
| 				return true; | 				return true; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
|  | @ -148,7 +144,7 @@ namespace easy2d | ||||||
| 		if (Load(res)) | 		if (Load(res)) | ||||||
| 		{ | 		{ | ||||||
| 			size_t hash_code = res.GetHashCode(); | 			size_t hash_code = res.GetHashCode(); | ||||||
| 			auto music = musics_[hash_code]; | 			auto music = musics_cache_[hash_code]; | ||||||
| 			if (music->Play(loop_count)) | 			if (music->Play(loop_count)) | ||||||
| 			{ | 			{ | ||||||
| 				return true; | 				return true; | ||||||
|  | @ -160,29 +156,29 @@ namespace easy2d | ||||||
| 	void Player::Pause(Resource& res) | 	void Player::Pause(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Pause(); | 			musics_cache_[hash_code]->Pause(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Player::Resume(Resource& res) | 	void Player::Resume(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Resume(); | 			musics_cache_[hash_code]->Resume(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Player::Stop(Resource& res) | 	void Player::Stop(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			musics_[hash_code]->Stop(); | 			musics_cache_[hash_code]->Stop(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Player::IsPlaying(Resource& res) | 	bool Player::IsPlaying(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		if (musics_.end() != musics_.find(hash_code)) | 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||||
| 			return musics_[hash_code]->IsPlaying(); | 			return musics_cache_[hash_code]->IsPlaying(); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -194,7 +190,7 @@ namespace easy2d | ||||||
| 	void Player::SetVolume(float volume) | 	void Player::SetVolume(float volume) | ||||||
| 	{ | 	{ | ||||||
| 		volume_ = std::min(std::max(volume, -224.f), 224.f); | 		volume_ = std::min(std::max(volume, -224.f), 224.f); | ||||||
| 		for (const auto& pair : musics_) | 		for (const auto& pair : musics_cache_) | ||||||
| 		{ | 		{ | ||||||
| 			pair.second->SetVolume(volume_); | 			pair.second->SetVolume(volume_); | ||||||
| 		} | 		} | ||||||
|  | @ -202,7 +198,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Player::PauseAll() | 	void Player::PauseAll() | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& pair : musics_) | 		for (const auto& pair : musics_cache_) | ||||||
| 		{ | 		{ | ||||||
| 			pair.second->Pause(); | 			pair.second->Pause(); | ||||||
| 		} | 		} | ||||||
|  | @ -210,7 +206,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Player::ResumeAll() | 	void Player::ResumeAll() | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& pair : musics_) | 		for (const auto& pair : musics_cache_) | ||||||
| 		{ | 		{ | ||||||
| 			pair.second->Resume(); | 			pair.second->Resume(); | ||||||
| 		} | 		} | ||||||
|  | @ -218,7 +214,7 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Player::StopAll() | 	void Player::StopAll() | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& pair : musics_) | 		for (const auto& pair : musics_cache_) | ||||||
| 		{ | 		{ | ||||||
| 			pair.second->Stop(); | 			pair.second->Stop(); | ||||||
| 		} | 		} | ||||||
|  | @ -226,13 +222,13 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 	void Player::ClearCache() | 	void Player::ClearCache() | ||||||
| 	{ | 	{ | ||||||
| 		if (musics_.empty()) | 		if (musics_cache_.empty()) | ||||||
| 			return; | 			return; | ||||||
| 
 | 
 | ||||||
| 		for (const auto& pair : musics_) | 		for (const auto& pair : musics_cache_) | ||||||
| 		{ | 		{ | ||||||
| 			pair.second->Release(); | 			pair.second->Release(); | ||||||
| 		} | 		} | ||||||
| 		musics_.clear(); | 		musics_cache_.clear(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -24,9 +24,13 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
|  | 	class Music; | ||||||
|  | 
 | ||||||
| 	// 稜있꺄렴포
 | 	// 稜있꺄렴포
 | ||||||
| 	class Player | 	class Player | ||||||
| 	{ | 	{ | ||||||
|  | 		E2D_DISABLE_COPY(Player); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		Player(); | 		Player(); | ||||||
| 
 | 
 | ||||||
|  | @ -112,12 +116,10 @@ namespace easy2d | ||||||
| 		void StopAll(); | 		void StopAll(); | ||||||
| 
 | 
 | ||||||
| 		// 헌뇜뻠닸
 | 		// 헌뇜뻠닸
 | ||||||
| 		static void ClearCache(); | 		void ClearCache(); | ||||||
| 
 |  | ||||||
| 	protected: |  | ||||||
| 		E2D_DISABLE_COPY(Player); |  | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		float volume_; | 		float volume_; | ||||||
|  | 		std::map<size_t, Music*> musics_cache_; | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ namespace easy2d | ||||||
| 		return wave_format_; | 		return wave_format_; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Transcoder::LoadMediaFile(LPCWSTR file_path, BYTE** wave_data, UINT32* wave_data_size) | 	HRESULT Transcoder::LoadMediaFile(LPCWSTR file_path, BYTE** wave_data, UINT32* wave_data_size) | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 
 | 
 | ||||||
|  | @ -64,10 +64,10 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		SafeRelease(reader); | 		SafeRelease(reader); | ||||||
| 
 | 
 | ||||||
| 		return SUCCEEDED(hr); | 		return hr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool Transcoder::LoadMediaResource(Resource& res, BYTE** wave_data, UINT32* wave_data_size) | 	HRESULT Transcoder::LoadMediaResource(Resource& res, BYTE** wave_data, UINT32* wave_data_size) | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT	hr = S_OK; | 		HRESULT	hr = S_OK; | ||||||
| 
 | 
 | ||||||
|  | @ -86,7 +86,7 @@ namespace easy2d | ||||||
| 		if (stream == nullptr) | 		if (stream == nullptr) | ||||||
| 		{ | 		{ | ||||||
| 			logs::Trace(L"SHCreateMemStream"); | 			logs::Trace(L"SHCreateMemStream"); | ||||||
| 			return false; | 			return E_OUTOFMEMORY; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
|  | @ -112,7 +112,7 @@ namespace easy2d | ||||||
| 		SafeRelease(byte_stream); | 		SafeRelease(byte_stream); | ||||||
| 		SafeRelease(reader); | 		SafeRelease(reader); | ||||||
| 
 | 
 | ||||||
| 		return SUCCEEDED(hr); | 		return hr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	HRESULT Transcoder::ReadSource(IMFSourceReader* reader, BYTE** wave_data, UINT32* wave_data_size) | 	HRESULT Transcoder::ReadSource(IMFSourceReader* reader, BYTE** wave_data, UINT32* wave_data_size) | ||||||
|  |  | ||||||
|  | @ -38,13 +38,13 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		WAVEFORMATEX* GetWaveFormatEx() const; | 		WAVEFORMATEX* GetWaveFormatEx() const; | ||||||
| 
 | 
 | ||||||
| 		bool LoadMediaFile( | 		HRESULT LoadMediaFile( | ||||||
| 			LPCWSTR file_path, | 			LPCWSTR file_path, | ||||||
| 			BYTE** wave_data, | 			BYTE** wave_data, | ||||||
| 			UINT32* wave_data_size | 			UINT32* wave_data_size | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		bool LoadMediaResource( | 		HRESULT LoadMediaResource( | ||||||
| 			Resource& res, | 			Resource& res, | ||||||
| 			BYTE** wave_data, | 			BYTE** wave_data, | ||||||
| 			UINT32* wave_data_size | 			UINT32* wave_data_size | ||||||
|  |  | ||||||
|  | @ -38,12 +38,14 @@ | ||||||
|     <ClInclude Include="..\..\core\base\macros.h" /> |     <ClInclude Include="..\..\core\base\macros.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\modules.h" /> |     <ClInclude Include="..\..\core\base\modules.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> |     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Node.h" /> |     <ClInclude Include="..\..\core\base\Node.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> |     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> |     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\render.h" /> |     <ClInclude Include="..\..\core\base\render.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> |     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> |     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\Size.h" /> |     <ClInclude Include="..\..\core\base\Size.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> |     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Task.h" /> |     <ClInclude Include="..\..\core\base\Task.h" /> | ||||||
|  | @ -62,7 +64,6 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> |     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> |     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\File.h" /> |     <ClInclude Include="..\..\core\utils\File.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> |     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> |     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> |     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||||
|  | @ -83,6 +84,7 @@ | ||||||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> |     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> |     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> |     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> |     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> |     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> |     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||||
|  | @ -102,7 +104,6 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> |     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> |     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> |     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> |     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> |     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> |     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||||
|  |  | ||||||
|  | @ -122,9 +122,6 @@ | ||||||
|     <ClInclude Include="..\..\core\utils\File.h"> |     <ClInclude Include="..\..\core\utils\File.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClInclude> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h"> |     <ClInclude Include="..\..\core\utils\Path.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  | @ -140,6 +137,12 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h"> |     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Filter Include="base"> |     <Filter Include="base"> | ||||||
|  | @ -252,9 +255,6 @@ | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp"> |     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> |     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  | @ -270,5 +270,8 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> |     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -38,12 +38,14 @@ | ||||||
|     <ClInclude Include="..\..\core\base\macros.h" /> |     <ClInclude Include="..\..\core\base\macros.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\modules.h" /> |     <ClInclude Include="..\..\core\base\modules.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> |     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Node.h" /> |     <ClInclude Include="..\..\core\base\Node.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> |     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> |     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\render.h" /> |     <ClInclude Include="..\..\core\base\render.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> |     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> |     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\Size.h" /> |     <ClInclude Include="..\..\core\base\Size.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> |     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Task.h" /> |     <ClInclude Include="..\..\core\base\Task.h" /> | ||||||
|  | @ -62,7 +64,6 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> |     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> |     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\File.h" /> |     <ClInclude Include="..\..\core\utils\File.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> |     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> |     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> |     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||||
|  | @ -83,6 +84,7 @@ | ||||||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> |     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> |     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> |     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> |     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> |     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> |     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||||
|  | @ -102,7 +104,6 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> |     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> |     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> |     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> |     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> |     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> |     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||||
|  |  | ||||||
|  | @ -122,9 +122,6 @@ | ||||||
|     <ClInclude Include="..\..\core\utils\File.h"> |     <ClInclude Include="..\..\core\utils\File.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClInclude> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h"> |     <ClInclude Include="..\..\core\utils\Path.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  | @ -140,6 +137,12 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h"> |     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Filter Include="base"> |     <Filter Include="base"> | ||||||
|  | @ -252,9 +255,6 @@ | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp"> |     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> |     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  | @ -270,5 +270,8 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> |     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -38,12 +38,14 @@ | ||||||
|     <ClInclude Include="..\..\core\base\macros.h" /> |     <ClInclude Include="..\..\core\base\macros.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\modules.h" /> |     <ClInclude Include="..\..\core\base\modules.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> |     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Node.h" /> |     <ClInclude Include="..\..\core\base\Node.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> |     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> |     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\render.h" /> |     <ClInclude Include="..\..\core\base\render.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> |     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> |     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||||
|     <ClInclude Include="..\..\core\base\Size.h" /> |     <ClInclude Include="..\..\core\base\Size.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> |     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||||
|     <ClInclude Include="..\..\core\base\Task.h" /> |     <ClInclude Include="..\..\core\base\Task.h" /> | ||||||
|  | @ -62,7 +64,6 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> |     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> |     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\File.h" /> |     <ClInclude Include="..\..\core\utils\File.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> |     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> |     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> |     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||||
|  | @ -83,6 +84,7 @@ | ||||||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> |     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> |     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> |     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> |     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> |     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> |     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||||
|  | @ -102,7 +104,6 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> |     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> |     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> |     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> |     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> |     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> |     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||||
|  |  | ||||||
|  | @ -122,9 +122,6 @@ | ||||||
|     <ClInclude Include="..\..\core\utils\File.h"> |     <ClInclude Include="..\..\core\utils\File.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="..\..\core\utils\Music.h"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClInclude> |  | ||||||
|     <ClInclude Include="..\..\core\utils\Path.h"> |     <ClInclude Include="..\..\core\utils\Path.h"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  | @ -140,6 +137,12 @@ | ||||||
|     <ClInclude Include="..\..\core\ui\Menu.h"> |     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Music.h"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Filter Include="base"> |     <Filter Include="base"> | ||||||
|  | @ -252,9 +255,6 @@ | ||||||
|     <ClCompile Include="..\..\core\utils\File.cpp"> |     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> |  | ||||||
|       <Filter>utils</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> |     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||||
|       <Filter>utils</Filter> |       <Filter>utils</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  | @ -270,5 +270,8 @@ | ||||||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> |     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||||
|       <Filter>ui</Filter> |       <Filter>ui</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||||
|  |       <Filter>base</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
		Loading…
	
		Reference in New Issue