update: modern singleton pattern
This commit is contained in:
		
							parent
							
								
									2b366e42be
								
							
						
					
					
						commit
						d2532c09db
					
				|  | @ -38,6 +38,8 @@ namespace easy2d | |||
| 		friend class Sequence; | ||||
| 		friend class Spawn; | ||||
| 
 | ||||
| 		E2D_DISABLE_COPY(Action); | ||||
| 
 | ||||
| 	public: | ||||
| 		Action(); | ||||
| 
 | ||||
|  | @ -92,9 +94,6 @@ namespace easy2d | |||
| 		// 获取动作结束状态
 | ||||
| 		virtual bool IsDone() const; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Action); | ||||
| 
 | ||||
| 	protected: | ||||
| 		String			name_; | ||||
| 		bool			running_; | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ namespace easy2d | |||
| 	// Loop
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| 	Loop::Loop(Action * action, int times /* = -1 */) | ||||
| 	Loop::Loop(Action * action, int times) | ||||
| 		: action_(action) | ||||
| 		, times_(0) | ||||
| 		, total_times_(times) | ||||
|  |  | |||
|  | @ -27,6 +27,8 @@ namespace easy2d | |||
| 	class Loop | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Loop); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit Loop( | ||||
| 			Action * action,	/* 执行循环的动作 */ | ||||
|  | @ -45,8 +47,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Loop); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -67,6 +67,8 @@ namespace easy2d | |||
| 	class Sequence | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Sequence); | ||||
| 
 | ||||
| 	public: | ||||
| 		typedef std::vector<Action*> Actions; | ||||
| 
 | ||||
|  | @ -98,8 +100,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Sequence); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -119,6 +119,8 @@ namespace easy2d | |||
| 	class Spawn | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Spawn); | ||||
| 
 | ||||
| 	public: | ||||
| 		typedef std::vector<Action*> Actions; | ||||
| 
 | ||||
|  | @ -150,8 +152,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Spawn); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,6 +27,8 @@ namespace easy2d | |||
| 	class FiniteTimeAction | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(FiniteTimeAction); | ||||
| 
 | ||||
| 	public: | ||||
| 		// 创建特定时长的持续动作
 | ||||
| 		explicit FiniteTimeAction( | ||||
|  | @ -37,8 +39,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(FiniteTimeAction); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -58,6 +58,8 @@ namespace easy2d | |||
| 	class MoveBy | ||||
| 		: public FiniteTimeAction | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(MoveBy); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit MoveBy( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -71,8 +73,6 @@ namespace easy2d | |||
| 		virtual MoveBy * Reverse() const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(MoveBy); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -90,6 +90,8 @@ namespace easy2d | |||
| 	class MoveTo | ||||
| 		: public MoveBy | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(MoveTo); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit MoveTo( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -107,8 +109,6 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(MoveTo); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -121,6 +121,8 @@ namespace easy2d | |||
| 	class JumpBy | ||||
| 		: public FiniteTimeAction | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(JumpBy); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit JumpBy( | ||||
| 			float duration,			/* 持续时长 */ | ||||
|  | @ -136,8 +138,6 @@ namespace easy2d | |||
| 		virtual JumpBy * Reverse() const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(JumpBy); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -157,6 +157,8 @@ namespace easy2d | |||
| 	class JumpTo | ||||
| 		: public JumpBy | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(JumpTo); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit JumpTo( | ||||
| 			float duration,			/* 持续时长 */ | ||||
|  | @ -176,8 +178,6 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(JumpTo); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -190,6 +190,8 @@ namespace easy2d | |||
| 	class ScaleBy | ||||
| 		: public FiniteTimeAction | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(ScaleBy); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit ScaleBy( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -209,8 +211,6 @@ namespace easy2d | |||
| 		virtual ScaleBy * Reverse() const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(ScaleBy); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -229,6 +229,8 @@ namespace easy2d | |||
| 	class ScaleTo | ||||
| 		: public ScaleBy | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(ScaleTo); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit ScaleTo( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -252,8 +254,6 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(ScaleTo); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -267,6 +267,8 @@ namespace easy2d | |||
| 	class OpacityBy | ||||
| 		: public FiniteTimeAction | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(OpacityBy); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit OpacityBy( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -280,8 +282,6 @@ namespace easy2d | |||
| 		virtual OpacityBy * Reverse() const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(OpacityBy); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -298,6 +298,8 @@ namespace easy2d | |||
| 	class OpacityTo | ||||
| 		: public OpacityBy | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(OpacityTo); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit OpacityTo( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -315,8 +317,6 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(OpacityTo); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -329,14 +329,13 @@ namespace easy2d | |||
| 	class FadeIn | ||||
| 		: public OpacityTo | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(FadeIn); | ||||
| 
 | ||||
| 	public: | ||||
| 		// 创建淡入动作
 | ||||
| 		explicit FadeIn( | ||||
| 			float duration		/* 持续时长 */ | ||||
| 		); | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(FadeIn); | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -344,14 +343,13 @@ namespace easy2d | |||
| 	class FadeOut | ||||
| 		: public OpacityTo | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(FadeOut); | ||||
| 
 | ||||
| 	public: | ||||
| 		// 创建淡出动作
 | ||||
| 		explicit FadeOut( | ||||
| 			float duration		/* 持续时长 */ | ||||
| 		); | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(FadeOut); | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -359,6 +357,8 @@ namespace easy2d | |||
| 	class RotateBy | ||||
| 		: public FiniteTimeAction | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(RotateBy); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit RotateBy( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -372,8 +372,6 @@ namespace easy2d | |||
| 		virtual RotateBy * Reverse() const override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(RotateBy); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -390,6 +388,8 @@ namespace easy2d | |||
| 	class RotateTo | ||||
| 		: public RotateBy | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(RotateTo); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit RotateTo( | ||||
| 			float duration,		/* 持续时长 */ | ||||
|  | @ -407,8 +407,6 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(RotateTo); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  | @ -421,6 +419,8 @@ namespace easy2d | |||
| 	class Delay | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Delay); | ||||
| 
 | ||||
| 	public: | ||||
| 		explicit Delay( | ||||
| 			float duration	/* 延迟时长(秒) */ | ||||
|  | @ -436,8 +436,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Delay); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ namespace easy2d | |||
| 	class Animation | ||||
| 		: public RefCounter | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Animation); | ||||
| 
 | ||||
| 	public: | ||||
| 		typedef std::vector<Image*> Images; | ||||
| 
 | ||||
|  | @ -75,9 +77,6 @@ namespace easy2d | |||
| 		// 获取帧动画的倒转
 | ||||
| 		Animation * Reverse() const; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Animation); | ||||
| 
 | ||||
| 	protected: | ||||
| 		float	interval_; | ||||
| 		Images	frames_; | ||||
|  | @ -88,6 +87,8 @@ namespace easy2d | |||
| 	class Animate | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Animate); | ||||
| 
 | ||||
| 	public: | ||||
| 		Animate(); | ||||
| 
 | ||||
|  | @ -115,8 +116,6 @@ namespace easy2d | |||
| 		virtual void Reset() override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Animate); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include "../math/vector.hpp" | ||||
| #include "Color.h" | ||||
| #include "Size.h" | ||||
| #include "Rect.hpp" | ||||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
|  | @ -33,9 +34,9 @@ namespace easy2d | |||
| 	//     计算两点间距离: float distance = p1.Distance(p2);
 | ||||
| 	//     坐标可以相加减: 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 | ||||
|  | @ -138,4 +139,11 @@ namespace easy2d | |||
| 		Right	= VK_RBUTTON,	/* 鼠标右键 */ | ||||
| 		Middle	= VK_MBUTTON	/* 鼠标中键 */ | ||||
| 	}; | ||||
| 
 | ||||
| 	// 图层属性
 | ||||
| 	struct LayerProperties | ||||
| 	{ | ||||
| 		Rect area; | ||||
| 		float opacity; | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ namespace easy2d | |||
| 	class CallFunc | ||||
| 		: public Action | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(CallFunc); | ||||
| 
 | ||||
| 		typedef std::function<void()> Callback; | ||||
| 
 | ||||
| 	  public: | ||||
|  | @ -42,8 +44,6 @@ namespace easy2d | |||
| 		virtual CallFunc *Reverse() const override; | ||||
| 
 | ||||
| 	  protected: | ||||
| 		E2D_DISABLE_COPY(CallFunc); | ||||
| 
 | ||||
| 		// 初始化动作
 | ||||
| 		virtual void Initialize() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ namespace easy2d | |||
| 	{ | ||||
| 		SafeRelease(stroke_style_); | ||||
| 
 | ||||
| 		stroke_style_ = render::instance.GetStrokeStyle(stroke); | ||||
| 		stroke_style_ = devices::Graphics::Instance().GetStrokeStyle(stroke); | ||||
| 
 | ||||
| 		if (stroke_style_) | ||||
| 			stroke_style_->AddRef(); | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ namespace easy2d | |||
| 	class Canvas | ||||
| 		: public Node | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Canvas); | ||||
| 
 | ||||
| 	public: | ||||
| 		Canvas( | ||||
| 			float width, | ||||
|  | @ -124,12 +126,9 @@ namespace easy2d | |||
| 			float radius_y | ||||
| 		); | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Canvas); | ||||
| 
 | ||||
| 	private: | ||||
| 		float					stroke_width_; | ||||
| 		StrokeStyle					stroke_; | ||||
| 		StrokeStyle				stroke_; | ||||
| 		ID2D1RenderTarget*		render_target_; | ||||
| 		ID2D1SolidColorBrush*	fill_brush_; | ||||
| 		ID2D1SolidColorBrush*	line_brush_; | ||||
|  |  | |||
|  | @ -34,16 +34,6 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace | ||||
| 	{ | ||||
| 		Game * instance = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	Game * Game::GetInstance() | ||||
| 	{ | ||||
| 		return instance; | ||||
| 	} | ||||
| 
 | ||||
| 	Game::Game() | ||||
| 		: quit_(true) | ||||
| 		, curr_scene_(nullptr) | ||||
|  | @ -51,12 +41,6 @@ namespace easy2d | |||
| 		, transition_(nullptr) | ||||
| 		, debug_mode_(false) | ||||
| 	{ | ||||
| 		if (instance) | ||||
| 		{ | ||||
| 			throw std::runtime_error("同时只能存在一个游戏实例"); | ||||
| 		} | ||||
| 		instance = this; | ||||
| 
 | ||||
| 		::CoInitialize(nullptr); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -66,25 +50,14 @@ namespace easy2d | |||
| 		SafeRelease(curr_scene_); | ||||
| 		SafeRelease(next_scene_); | ||||
| 
 | ||||
| 		Image::ClearCache(); | ||||
| 		Player::ClearCache(); | ||||
| 
 | ||||
| 		render::instance.Uninitialize(); | ||||
| 		audio::instance.Uninitialize(); | ||||
| 		window::instance.Destroy(); | ||||
| 		modules::Uninitialize(); | ||||
| 
 | ||||
| 		instance = nullptr; | ||||
| 
 | ||||
| 		::CoUninitialize(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Game::Initialize(const window::Property& property) | ||||
| 	void Game::Initialize(const Options& options) | ||||
| 	{ | ||||
| 		modules::Initialize(); | ||||
| 		window::instance.Initialize(property); | ||||
| 		render::instance.Initialize(window::instance.handle); | ||||
| 		audio::instance.Initialize(); | ||||
| 		Window::Instance().Initialize(options.title, options.width, options.height, options.icon, options.debug); | ||||
| 		devices::Graphics::Instance().Initialize(Window::Instance().GetHandle()); | ||||
| 		devices::Audio::Instance().Initialize(); | ||||
| 
 | ||||
| 		// 若开启了调试模式,打开控制台
 | ||||
| 		HWND console = ::GetConsoleWindow(); | ||||
|  | @ -117,7 +90,7 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 		::SetWindowLongPtrW( | ||||
| 			window::instance.handle, | ||||
| 			Window::Instance().GetHandle(), | ||||
| 			GWLP_USERDATA, | ||||
| 			PtrToUlong(this) | ||||
| 		); | ||||
|  | @ -134,8 +107,8 @@ namespace easy2d | |||
| 			next_scene_ = nullptr; | ||||
| 		} | ||||
| 
 | ||||
| 		::ShowWindow(window::instance.handle, SW_SHOWNORMAL); | ||||
| 		::UpdateWindow(window::instance.handle); | ||||
| 		::ShowWindow(Window::Instance().GetHandle(), SW_SHOWNORMAL); | ||||
| 		::UpdateWindow(Window::Instance().GetHandle()); | ||||
| 
 | ||||
| 		const int64_t min_interval = 5; | ||||
| 		auto last = time::Now(); | ||||
|  | @ -151,10 +124,10 @@ namespace easy2d | |||
| 				float dt = (now - last).Seconds(); | ||||
| 				last = now; | ||||
| 
 | ||||
| 				input::instance.Update( | ||||
| 					window::instance.handle, | ||||
| 					window::instance.xscale, | ||||
| 					window::instance.yscale | ||||
| 				devices::Input::Instance().Update( | ||||
| 					Window::Instance().GetHandle(), | ||||
| 					Window::Instance().GetContentScaleX(), | ||||
| 					Window::Instance().GetContentScaleY() | ||||
| 				); | ||||
| 
 | ||||
| 				OnUpdate(dt); | ||||
|  | @ -277,7 +250,7 @@ namespace easy2d | |||
| 
 | ||||
| 	void Game::DrawScene() | ||||
| 	{ | ||||
| 		render::instance.BeginDraw(window::instance.handle); | ||||
| 		devices::Graphics::Instance().BeginDraw(Window::Instance().GetHandle()); | ||||
| 
 | ||||
| 		if (transition_) | ||||
| 		{ | ||||
|  | @ -292,21 +265,21 @@ namespace easy2d | |||
| 		{ | ||||
| 			if (curr_scene_ && curr_scene_->GetRoot()) | ||||
| 			{ | ||||
| 				render::instance.SetTransform(math::Matrix()); | ||||
| 				render::instance.SetBrushOpacity(1.f); | ||||
| 				devices::Graphics::Instance().SetTransform(math::Matrix()); | ||||
| 				devices::Graphics::Instance().SetBrushOpacity(1.f); | ||||
| 				curr_scene_->GetRoot()->DrawBorder(); | ||||
| 			} | ||||
| 			if (next_scene_ && next_scene_->GetRoot()) | ||||
| 			{ | ||||
| 				render::instance.SetTransform(math::Matrix()); | ||||
| 				render::instance.SetBrushOpacity(1.f); | ||||
| 				devices::Graphics::Instance().SetTransform(math::Matrix()); | ||||
| 				devices::Graphics::Instance().SetBrushOpacity(1.f); | ||||
| 				next_scene_->GetRoot()->DrawBorder(); | ||||
| 			} | ||||
| 
 | ||||
| 			render::instance.DrawDebugInfo(); | ||||
| 			devices::Graphics::Instance().DrawDebugInfo(); | ||||
| 		} | ||||
| 
 | ||||
| 		render::instance.EndDraw(); | ||||
| 		devices::Graphics::Instance().EndDraw(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Game::SetDebugMode(bool enabled) | ||||
|  |  | |||
|  | @ -27,12 +27,32 @@ namespace easy2d | |||
| 	class Scene; | ||||
| 	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 | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Game); | ||||
| 
 | ||||
| 	public: | ||||
| 		Game(); | ||||
| 
 | ||||
| 		~Game(); | ||||
| 		virtual ~Game(); | ||||
| 
 | ||||
| 		// 更新时
 | ||||
| 		virtual void OnUpdate(float dt) {} | ||||
|  | @ -46,7 +66,7 @@ namespace easy2d | |||
| 
 | ||||
| 		// 初始化
 | ||||
| 		void Initialize( | ||||
| 			const window::Property& property	/* 窗口属性 */ | ||||
| 			const Options& options	/* 属性 */ | ||||
| 		); | ||||
| 
 | ||||
| 		// 运行
 | ||||
|  | @ -80,12 +100,6 @@ namespace easy2d | |||
| 			float dt | ||||
| 		); | ||||
| 
 | ||||
| 		// 获取实例
 | ||||
| 		static Game * GetInstance(); | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Game); | ||||
| 
 | ||||
| 	private: | ||||
| 		bool		debug_mode_; | ||||
| 		bool		quit_; | ||||
|  |  | |||
|  | @ -25,11 +25,6 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace | ||||
| 	{ | ||||
| 		std::map<size_t, ID2D1Bitmap*> bitmap_cache_; | ||||
| 	} | ||||
| 
 | ||||
| 	Image::Image() | ||||
| 		: bitmap_(nullptr) | ||||
| 		, crop_rect_() | ||||
|  | @ -73,13 +68,12 @@ namespace easy2d | |||
| 
 | ||||
| 	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; | ||||
| 		} | ||||
| 
 | ||||
| 		this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -87,16 +81,23 @@ namespace easy2d | |||
| 	{ | ||||
| 		E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name."); | ||||
| 
 | ||||
| 		if (file_name.empty()) | ||||
| 			return false; | ||||
| 
 | ||||
| 		if (!Image::CacheBitmap(file_name)) | ||||
| 		File image_file; | ||||
| 		if (!image_file.Open(file_name)) | ||||
| 		{ | ||||
| 			E2D_WARNING("Load Image from file failed!"); | ||||
| 			E2D_WARNING("Image file not found!"); | ||||
| 			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; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -186,70 +187,6 @@ namespace easy2d | |||
| 		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) | ||||
| 	{ | ||||
| 		if (bitmap_ == bitmap) | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ namespace easy2d | |||
| 	class Image | ||||
| 		: public RefCounter | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Image); | ||||
| 
 | ||||
| 	public: | ||||
| 		Image(); | ||||
| 
 | ||||
|  | @ -100,22 +102,7 @@ namespace easy2d | |||
| 		// 获取 ID2D1Bitmap 对象
 | ||||
| 		ID2D1Bitmap * GetBitmap() const; | ||||
| 
 | ||||
| 		// 헌왕뻠닸
 | ||||
| 		static void ClearCache(); | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Image); | ||||
| 
 | ||||
| 		// 뻠닸 Bitmap 栗都
 | ||||
| 		static bool CacheBitmap( | ||||
| 			const String& file_name | ||||
| 		); | ||||
| 
 | ||||
| 		// 뻠닸 Bitmap 栗都
 | ||||
| 		static bool CacheBitmap( | ||||
| 			Resource& res | ||||
| 		); | ||||
| 
 | ||||
| 		// 设置 Bitmap
 | ||||
| 		void SetBitmap( | ||||
| 			ID2D1Bitmap * bitmap | ||||
|  |  | |||
|  | @ -22,10 +22,8 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace input | ||||
| 	namespace devices | ||||
| 	{ | ||||
| 		InputDevice instance; | ||||
| 
 | ||||
| 		InputDevice::InputDevice() | ||||
| 		{ | ||||
| 			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_); | ||||
| 
 | ||||
|  | @ -43,7 +41,7 @@ namespace easy2d | |||
| 			::GetCursorPos(&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) | ||||
|  |  | |||
|  | @ -20,14 +20,18 @@ | |||
| 
 | ||||
| #pragma once | ||||
| #include "base.h" | ||||
| #include "Singleton.hpp" | ||||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace input | ||||
| 	namespace devices | ||||
| 	{ | ||||
| 		// 输入设备
 | ||||
| 		class InputDevice | ||||
| 		{ | ||||
| 			E2D_DECLARE_SINGLETON(InputDevice); | ||||
| 
 | ||||
| 			E2D_DISABLE_COPY(InputDevice); | ||||
| 
 | ||||
| 		public: | ||||
| 			InputDevice(); | ||||
| 
 | ||||
|  | @ -55,8 +59,8 @@ namespace easy2d | |||
| 			// 刷新设备状态
 | ||||
| 			void Update( | ||||
| 				HWND hwnd, | ||||
| 				float xscale, | ||||
| 				float yscale | ||||
| 				float scale_x, | ||||
| 				float scale_y | ||||
| 			); | ||||
| 
 | ||||
| 		protected: | ||||
|  | @ -64,6 +68,6 @@ namespace easy2d | |||
| 			Point mouse_pos_; | ||||
| 		}; | ||||
| 
 | ||||
| 		extern InputDevice instance; | ||||
| 		E2D_DECLARE_SINGLETON_TYPE(InputDevice, Input); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -32,19 +32,19 @@ namespace easy2d | |||
| 
 | ||||
| 	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 | ||||
| 	{ | ||||
| 		return ((float)(short)HIWORD(l_param_)) * window::instance.yscale; | ||||
| 		return ((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY(); | ||||
| 	} | ||||
| 
 | ||||
| 	Point MouseEvent::GetPosition() const | ||||
| 	{ | ||||
| 		return Point( | ||||
| 			((float)(short)LOWORD(l_param_)) * window::instance.xscale, | ||||
| 			((float)(short)HIWORD(l_param_)) * window::instance.yscale | ||||
| 			((float)(short)LOWORD(l_param_)) * Window::Instance().GetContentScaleX(), | ||||
| 			((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY() | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,11 +19,11 @@ | |||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #include "Music.h" | ||||
| #include "Transcoder.h" | ||||
| #include "File.h" | ||||
| #include "../base/modules.h" | ||||
| #include "../base/audio.h" | ||||
| #include "../base/logs.h" | ||||
| #include "../utils/Transcoder.h" | ||||
| #include "../utils/File.h" | ||||
| #include "modules.h" | ||||
| #include "audio.h" | ||||
| #include "logs.h" | ||||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
|  | @ -71,7 +71,7 @@ namespace easy2d | |||
| 		File music_file; | ||||
| 		if (!music_file.Open(file_path)) | ||||
| 		{ | ||||
| 			E2D_WARNING("Media file not found."); | ||||
| 			logs::Trace(L"Media file not found."); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -80,12 +80,14 @@ namespace easy2d | |||
| 		String music_file_path = music_file.GetPath(); | ||||
| 
 | ||||
| 		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; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||
| 		hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			if (wave_data_) | ||||
|  | @ -109,12 +111,15 @@ namespace easy2d | |||
| 		} | ||||
| 
 | ||||
| 		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; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||
| 		hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			if (wave_data_) | ||||
|  | @ -134,48 +139,26 @@ namespace easy2d | |||
| 	{ | ||||
| 		if (!opened_) | ||||
| 		{ | ||||
| 			E2D_WARNING("Music must be opened first!"); | ||||
| 			logs::Trace(L"Music must be opened first!"); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		if (voice_ == nullptr) | ||||
| 		{ | ||||
| 			E2D_WARNING("IXAudio2SourceVoice Null pointer exception!"); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		XAUDIO2_VOICE_STATE state; | ||||
| 		voice_->GetState(&state); | ||||
| 		if (state.BuffersQueued) | ||||
| 		{ | ||||
| 		UINT32 buffers_queued = 0; | ||||
| 		voice_.GetBuffersQueued(&buffers_queued); | ||||
| 		if (buffers_queued) | ||||
| 			Stop(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (loop_count < 0) | ||||
| 		{ | ||||
| 			loop_count = XAUDIO2_LOOP_INFINITE; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			loop_count = std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1); | ||||
| 		} | ||||
| 
 | ||||
| 		// Ìá½» wave Ñù±¾Êý¾Ý
 | ||||
| 		XAUDIO2_BUFFER buffer = { 0 }; | ||||
| 		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))) | ||||
| 		HRESULT hr = voice_.Play(wave_data_, size_, static_cast<UINT32>(loop_count)); | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			logs::Trace(L"Submitting source buffer error", hr); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		hr = voice_->Start(0); | ||||
| 
 | ||||
| 		playing_ = SUCCEEDED(hr); | ||||
| 
 | ||||
| 		return playing_; | ||||
|  | @ -183,48 +166,25 @@ namespace easy2d | |||
| 
 | ||||
| 	void Music::Pause() | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			if (SUCCEEDED(voice_->Stop())) | ||||
| 			{ | ||||
| 				playing_ = false; | ||||
| 			} | ||||
| 		} | ||||
| 		if (SUCCEEDED(voice_.Pause())) | ||||
| 			playing_ = false; | ||||
| 	} | ||||
| 
 | ||||
| 	void Music::Resume() | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			if (SUCCEEDED(voice_->Start())) | ||||
| 			{ | ||||
| 				playing_ = true; | ||||
| 			} | ||||
| 		} | ||||
| 		if (SUCCEEDED(voice_.Resume())) | ||||
| 			playing_ = true; | ||||
| 	} | ||||
| 
 | ||||
| 	void Music::Stop() | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			if (SUCCEEDED(voice_->Stop())) | ||||
| 			{ | ||||
| 				voice_->ExitLoop(); | ||||
| 				voice_->FlushSourceBuffers(); | ||||
| 				playing_ = false; | ||||
| 			} | ||||
| 		} | ||||
| 		if (SUCCEEDED(voice_.Stop())) | ||||
| 			playing_ = false; | ||||
| 	} | ||||
| 
 | ||||
| 	void Music::Close() | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			voice_->Stop(); | ||||
| 			voice_->FlushSourceBuffers(); | ||||
| 			voice_->DestroyVoice(); | ||||
| 			voice_ = nullptr; | ||||
| 		} | ||||
| 		voice_.Destroy(); | ||||
| 
 | ||||
| 		if (wave_data_) | ||||
| 		{ | ||||
|  | @ -238,11 +198,11 @@ namespace easy2d | |||
| 
 | ||||
| 	bool Music::IsPlaying() const | ||||
| 	{ | ||||
| 		if (opened_ && voice_) | ||||
| 		if (opened_) | ||||
| 		{ | ||||
| 			XAUDIO2_VOICE_STATE state; | ||||
| 			voice_->GetState(&state); | ||||
| 			if (state.BuffersQueued && playing_) | ||||
| 			UINT32 buffers_queued = 0; | ||||
| 			voice_.GetBuffersQueued(&buffers_queued); | ||||
| 			if (buffers_queued && playing_) | ||||
| 				return true; | ||||
| 		} | ||||
| 		return false; | ||||
|  | @ -250,27 +210,13 @@ namespace easy2d | |||
| 
 | ||||
| 	float Music::GetVolume() const | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			float volume = 0.f; | ||||
| 			voice_->GetVolume(&volume); | ||||
| 			return volume; | ||||
| 		} | ||||
| 		return 0.f; | ||||
| 		float volume = 0.f; | ||||
| 		voice_.GetVolume(&volume); | ||||
| 		return volume; | ||||
| 	} | ||||
| 
 | ||||
| 	bool Music::SetVolume(float volume) | ||||
| 	{ | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			volume = std::min(std::max(volume, -224.f), 224.f); | ||||
| 			return SUCCEEDED(voice_->SetVolume(volume)); | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	IXAudio2SourceVoice * Music::GetSourceVoice() const | ||||
| 	{ | ||||
| 		return voice_; | ||||
| 		return SUCCEEDED(voice_.SetVolume(volume)); | ||||
| 	} | ||||
| } | ||||
|  | @ -19,9 +19,10 @@ | |||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "../base/base.h" | ||||
| #include "../base/RefCounter.h" | ||||
| #include "../base/Resource.h" | ||||
| #include "base.h" | ||||
| #include "audio.h" | ||||
| #include "RefCounter.h" | ||||
| #include "Resource.h" | ||||
| #include <xaudio2.h> | ||||
| 
 | ||||
| namespace easy2d | ||||
|  | @ -30,6 +31,8 @@ namespace easy2d | |||
| 	class Music | ||||
| 		: public RefCounter | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Music); | ||||
| 
 | ||||
| 	public: | ||||
| 		Music(); | ||||
| 
 | ||||
|  | @ -81,17 +84,11 @@ namespace easy2d | |||
| 			float volume	/* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */ | ||||
| 		); | ||||
| 
 | ||||
| 		// 获取 IXAudio2SourceVoice 对象
 | ||||
| 		IXAudio2SourceVoice * GetSourceVoice() const; | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Music); | ||||
| 
 | ||||
| 	protected: | ||||
| 		bool					opened_; | ||||
| 		bool					playing_; | ||||
| 		UINT32					size_; | ||||
| 		BYTE*					wave_data_; | ||||
| 		IXAudio2SourceVoice*	voice_; | ||||
| 		bool	opened_; | ||||
| 		bool	playing_; | ||||
| 		UINT32	size_; | ||||
| 		BYTE*	wave_data_; | ||||
| 		Voice	voice_; | ||||
| 	}; | ||||
| } | ||||
|  | @ -77,12 +77,12 @@ namespace easy2d | |||
| 
 | ||||
| 		if (clip_enabled_) | ||||
| 		{ | ||||
| 			render::instance.PushClip(final_matrix_, transform_.size); | ||||
| 			devices::Graphics::Instance().PushClip(final_matrix_, transform_.size); | ||||
| 		} | ||||
| 
 | ||||
| 		if (children_.empty()) | ||||
| 		{ | ||||
| 			render::instance.SetTransform(final_matrix_); | ||||
| 			devices::Graphics::Instance().SetTransform(final_matrix_); | ||||
| 			OnDraw(); | ||||
| 		} | ||||
| 		else | ||||
|  | @ -114,7 +114,7 @@ namespace easy2d | |||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			render::instance.SetTransform(final_matrix_); | ||||
| 			devices::Graphics::Instance().SetTransform(final_matrix_); | ||||
| 			OnDraw(); | ||||
| 
 | ||||
| 			// 访问剩余节点
 | ||||
|  | @ -124,7 +124,7 @@ namespace easy2d | |||
| 
 | ||||
| 		if (clip_enabled_) | ||||
| 		{ | ||||
| 			render::instance.PopClip(); | ||||
| 			devices::Graphics::Instance().PopClip(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -171,7 +171,7 @@ namespace easy2d | |||
| 		{ | ||||
| 			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_) | ||||
|  | @ -212,7 +212,7 @@ namespace easy2d | |||
| 		SafeRelease(border_); | ||||
| 		 | ||||
| 		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 Scene; | ||||
| 
 | ||||
| 		E2D_DISABLE_COPY(Node); | ||||
| 
 | ||||
| 	public: | ||||
| 		typedef std::vector<Node*> Nodes; | ||||
| 		typedef std::vector<Action*> Actions; | ||||
|  | @ -418,8 +420,6 @@ namespace easy2d | |||
| 		); | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Node); | ||||
| 
 | ||||
| 		// 渲染节点边缘
 | ||||
| 		void DrawBorder(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,8 @@ | |||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "BaseTypes.h" | ||||
| #include "../math/vector.hpp" | ||||
| #include "Size.h" | ||||
| #include <d2d1.h> | ||||
| 
 | ||||
| namespace easy2d | ||||
|  | @ -34,9 +35,11 @@ namespace easy2d | |||
| 	//
 | ||||
| 	class Rect | ||||
| 	{ | ||||
| 		using Point = math::Vector2; | ||||
| 
 | ||||
| 	public: | ||||
| 		Point origin;	// 左上角坐标
 | ||||
| 		Size  size;		// 宽度和高度
 | ||||
| 		Point	origin;	// 左上角坐标
 | ||||
| 		Size	size;	// 宽度和高度
 | ||||
| 
 | ||||
| 	public: | ||||
| 		Rect() {} | ||||
|  |  | |||
|  | @ -32,6 +32,8 @@ namespace easy2d | |||
| 	class Scene | ||||
| 		: public RefCounter | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Scene); | ||||
| 
 | ||||
| 	public: | ||||
| 		Scene(); | ||||
| 
 | ||||
|  | @ -79,9 +81,6 @@ namespace easy2d | |||
| 		// »ñȡת»»¾ØÕó
 | ||||
| 		const math::Matrix& GetTransform() const; | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Scene); | ||||
| 
 | ||||
| 	private: | ||||
| 		Node*			root_; | ||||
| 		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()) | ||||
| 		{ | ||||
| 			auto crop_pos = image_->GetCropPos(); | ||||
| 			render::instance.DrawImage( | ||||
| 			devices::Graphics::Instance().DrawImage( | ||||
| 				image_, | ||||
| 				GetDisplayOpacity(), | ||||
| 				Rect(Point(), GetTransform().size), | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ namespace easy2d | |||
| 	class Sprite | ||||
| 		: public Node | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Sprite); | ||||
| 
 | ||||
| 	public: | ||||
| 		Sprite(); | ||||
| 
 | ||||
|  | @ -81,9 +83,6 @@ namespace easy2d | |||
| 		// äÖČžžŤÁé
 | ||||
| 		virtual void OnDraw() const override; | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Sprite); | ||||
| 
 | ||||
| 	private: | ||||
| 		Image* image_; | ||||
| 	}; | ||||
|  |  | |||
|  | @ -318,16 +318,16 @@ namespace easy2d | |||
| 			// 创建文本区域
 | ||||
| 			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_.outline, | ||||
| 				style_.outline_color, | ||||
| 				style_.outline_width, | ||||
| 				style_.outline_stroke | ||||
| 			); | ||||
| 			render::instance.DrawTextLayout(text_layout_); | ||||
| 			devices::Graphics::Instance().DrawTextLayout(text_layout_); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -344,7 +344,7 @@ namespace easy2d | |||
| 		SafeRelease(text_format_); | ||||
| 
 | ||||
| 		ThrowIfFailed( | ||||
| 			render::instance.CreateTextFormat( | ||||
| 			devices::Graphics::Instance().CreateTextFormat( | ||||
| 				&text_format_, | ||||
| 				font_ | ||||
| 			) | ||||
|  | @ -399,7 +399,7 @@ namespace easy2d | |||
| 		if (style_.wrap) | ||||
| 		{ | ||||
| 			ThrowIfFailed( | ||||
| 				render::instance.CreateTextLayout( | ||||
| 				devices::Graphics::Instance().CreateTextLayout( | ||||
| 					&text_layout_, | ||||
| 					text_, | ||||
| 					text_format_, | ||||
|  | @ -416,7 +416,7 @@ namespace easy2d | |||
| 		{ | ||||
| 			// 为防止文本对齐问题,根据先创建 layout 以获取宽度
 | ||||
| 			ThrowIfFailed( | ||||
| 				render::instance.CreateTextLayout( | ||||
| 				devices::Graphics::Instance().CreateTextLayout( | ||||
| 					&text_layout_, | ||||
| 					text_, | ||||
| 					text_format_, | ||||
|  | @ -433,7 +433,7 @@ namespace easy2d | |||
| 			// 重新创建 layout
 | ||||
| 			SafeRelease(text_layout_); | ||||
| 			ThrowIfFailed( | ||||
| 				render::instance.CreateTextLayout( | ||||
| 				devices::Graphics::Instance().CreateTextLayout( | ||||
| 					&text_layout_, | ||||
| 					text_, | ||||
| 					text_format_, | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ namespace easy2d | |||
| 	class Text | ||||
| 		: public Node | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Text); | ||||
| 
 | ||||
| 	public: | ||||
| 		// 文本对齐方式
 | ||||
| 		enum class Align | ||||
|  | @ -221,8 +223,6 @@ namespace easy2d | |||
| 		virtual void OnDraw() const override; | ||||
| 
 | ||||
| 	private: | ||||
| 		E2D_DISABLE_COPY(Text); | ||||
| 
 | ||||
| 		// 重新排版文字
 | ||||
| 		void Reset(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ namespace easy2d | |||
| 		bShowOutline_ = outline; | ||||
| 		sOutlineColor_ = outline_color; | ||||
| 		fOutlineWidth = 2 * outline_width; | ||||
| 		pCurrStrokeStyle_ = render::instance.GetStrokeStyle(StrokeStyle(outlineJoin)); | ||||
| 		pCurrStrokeStyle_ = devices::Graphics::Instance().GetStrokeStyle(StrokeStyle(outlineJoin)); | ||||
| 	} | ||||
| 
 | ||||
| 	STDMETHODIMP ITextRenderer::DrawGlyphRun( | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include "Node.h" | ||||
| #include "Scene.h" | ||||
| #include "window.h" | ||||
| #include "render.h" | ||||
| #include "../math/Matrix.hpp" | ||||
| 
 | ||||
| namespace easy2d | ||||
|  | @ -73,22 +74,19 @@ namespace easy2d | |||
| 		if (in_scene_) | ||||
| 		{ | ||||
| 			ThrowIfFailed( | ||||
| 				render::instance.CreateLayer(&in_layer_) | ||||
| 				devices::Graphics::Instance().CreateLayer(&in_layer_) | ||||
| 			); | ||||
| 		} | ||||
| 
 | ||||
| 		if (out_scene_) | ||||
| 		{ | ||||
| 			ThrowIfFailed( | ||||
| 				render::instance.CreateLayer(&out_layer_) | ||||
| 				devices::Graphics::Instance().CreateLayer(&out_layer_) | ||||
| 			); | ||||
| 		} | ||||
| 
 | ||||
| 		window_size_ = window::instance.GetSize(); | ||||
| 		out_layer_prop_ = in_layer_prop_ = render::LayerProperties{ | ||||
| 			Rect(Point(), window_size_), | ||||
| 			1.f | ||||
| 		}; | ||||
| 		window_size_ = Window::Instance().GetSize(); | ||||
| 		out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f }; | ||||
| 	} | ||||
| 
 | ||||
| 	void Transition::Update() | ||||
|  | @ -113,30 +111,30 @@ namespace easy2d | |||
| 	{ | ||||
| 		if (out_scene_) | ||||
| 		{ | ||||
| 			render::instance.PushClip( | ||||
| 			devices::Graphics::Instance().PushClip( | ||||
| 				out_scene_->GetTransform(), | ||||
| 				window_size_ | ||||
| 			); | ||||
| 			render::instance.PushLayer(out_layer_, out_layer_prop_); | ||||
| 			devices::Graphics::Instance().PushLayer(out_layer_, out_layer_prop_); | ||||
| 
 | ||||
| 			out_scene_->Draw(); | ||||
| 
 | ||||
| 			render::instance.PopLayer(); | ||||
| 			render::instance.PopClip(); | ||||
| 			devices::Graphics::Instance().PopLayer(); | ||||
| 			devices::Graphics::Instance().PopClip(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (in_scene_) | ||||
| 		{ | ||||
| 			render::instance.PushClip( | ||||
| 			devices::Graphics::Instance().PushClip( | ||||
| 				in_scene_->GetTransform(), | ||||
| 				window_size_ | ||||
| 			); | ||||
| 			render::instance.PushLayer(in_layer_, in_layer_prop_); | ||||
| 			devices::Graphics::Instance().PushLayer(in_layer_, in_layer_prop_); | ||||
| 
 | ||||
| 			in_scene_->Draw(); | ||||
| 
 | ||||
| 			render::instance.PopLayer(); | ||||
| 			render::instance.PopClip(); | ||||
| 			devices::Graphics::Instance().PopLayer(); | ||||
| 			devices::Graphics::Instance().PopClip(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,6 @@ | |||
| #pragma once | ||||
| #include "base.h" | ||||
| #include "time.h" | ||||
| #include "render.h" | ||||
| #include "RefCounter.h" | ||||
| 
 | ||||
| namespace easy2d | ||||
|  | @ -75,8 +74,8 @@ namespace easy2d | |||
| 		Scene*			in_scene_; | ||||
| 		ID2D1Layer*		out_layer_; | ||||
| 		ID2D1Layer*		in_layer_; | ||||
| 		render::LayerProperties out_layer_prop_; | ||||
| 		render::LayerProperties in_layer_prop_; | ||||
| 		LayerProperties out_layer_prop_; | ||||
| 		LayerProperties in_layer_prop_; | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,18 +27,161 @@ | |||
| 
 | ||||
| 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() | ||||
| 			: x_audio2_(nullptr) | ||||
| 			, mastering_voice_(nullptr) | ||||
| 		{ | ||||
| 			modules::Initialize(); | ||||
| 		} | ||||
| 
 | ||||
| 		AudioDevice::~AudioDevice() | ||||
| 		{ | ||||
| 			ClearVoiceCache(); | ||||
| 
 | ||||
| 			if (mastering_voice_) | ||||
| 			{ | ||||
| 				mastering_voice_->DestroyVoice(); | ||||
| 				mastering_voice_ = nullptr; | ||||
| 			} | ||||
| 
 | ||||
| 			SafeRelease(x_audio2_); | ||||
| 
 | ||||
| 			modules::MediaFoundation.MFShutdown(); | ||||
| 
 | ||||
| 			modules::Destroy(); | ||||
| 		} | ||||
| 
 | ||||
| 		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(); | ||||
| 				mastering_voice_ = nullptr; | ||||
| 				voice->SetSourceVoice(source_voice); | ||||
| 				voice_cache_.push_back(voice); | ||||
| 			} | ||||
| 
 | ||||
| 			SafeRelease(x_audio2_); | ||||
| 
 | ||||
| 			modules::MediaFoundation.MFShutdown(); | ||||
| 			return hr; | ||||
| 		} | ||||
| 
 | ||||
| 		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() | ||||
|  |  | |||
|  | @ -20,41 +20,97 @@ | |||
| 
 | ||||
| #pragma once | ||||
| #include "macros.h" | ||||
| #include "Singleton.hpp" | ||||
| #include <xaudio2.h> | ||||
| 
 | ||||
| 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 | ||||
| 		{ | ||||
| 			E2D_DECLARE_SINGLETON(AudioDevice); | ||||
| 
 | ||||
| 			E2D_DISABLE_COPY(AudioDevice); | ||||
| 
 | ||||
| 		public: | ||||
| 			AudioDevice(); | ||||
| 
 | ||||
| 			~AudioDevice(); | ||||
| 
 | ||||
| 			void Initialize(); | ||||
| 
 | ||||
| 			void Uninitialize(); | ||||
| 
 | ||||
| 			// 开启设备
 | ||||
| 			void Open(); | ||||
| 
 | ||||
| 			// 关闭设备
 | ||||
| 			void Close(); | ||||
| 
 | ||||
| 			// 创建音源
 | ||||
| 			HRESULT CreateVoice( | ||||
| 				IXAudio2SourceVoice ** voice, | ||||
| 				Voice* voice, | ||||
| 				WAVEFORMATEX * wfx | ||||
| 			); | ||||
| 
 | ||||
| 			void DeleteVoice( | ||||
| 				Voice* voice | ||||
| 			); | ||||
| 
 | ||||
| 			void ClearVoiceCache(); | ||||
| 
 | ||||
| 		protected: | ||||
| 			AudioDevice(); | ||||
| 
 | ||||
| 			~AudioDevice(); | ||||
| 
 | ||||
| 		protected: | ||||
| 			IXAudio2 * x_audio2_; | ||||
| 			IXAudio2MasteringVoice*	mastering_voice_; | ||||
| 			std::list<Voice*> voice_cache_; | ||||
| 		}; | ||||
| 
 | ||||
| 		extern AudioDevice instance; | ||||
| 		E2D_DECLARE_SINGLETON_TYPE(AudioDevice, Audio); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ | |||
| 
 | ||||
| #pragma once | ||||
| #include "BaseTypes.h" | ||||
| #include "Rect.hpp" | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| namespace easy2d | ||||
|  |  | |||
|  | @ -80,6 +80,7 @@ | |||
| #include <list> | ||||
| #include <vector> | ||||
| #include <algorithm> | ||||
| #include <memory> | ||||
| 
 | ||||
| 
 | ||||
| #if VS_VER >= VS_2015 | ||||
|  | @ -89,9 +90,10 @@ | |||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #define E2D_DISABLE_COPY(Class)					\ | ||||
| 	Class(const Class &) = delete;				\ | ||||
| 	Class & operator= (const Class &) = delete | ||||
| #define E2D_DISABLE_COPY(Class)						\ | ||||
| 	private:										\ | ||||
| 		Class(const Class &) = delete;				\ | ||||
| 		Class & operator= (const Class &) = delete | ||||
| 
 | ||||
| 
 | ||||
| #if defined( DEBUG ) || defined( _DEBUG ) | ||||
|  |  | |||
|  | @ -26,6 +26,8 @@ namespace easy2d | |||
| 	{ | ||||
| 		namespace | ||||
| 		{ | ||||
| 			int initialize_count = 0; | ||||
| 
 | ||||
| 			inline void SafeFreeLibrary(HMODULE instance) | ||||
| 			{ | ||||
| 				if (instance) | ||||
|  | @ -38,6 +40,10 @@ namespace easy2d | |||
| 
 | ||||
| 		void Initialize() | ||||
| 		{ | ||||
| 			initialize_count++; | ||||
| 			if (initialize_count > 1) | ||||
| 				return; | ||||
| 
 | ||||
| 			const auto xaudio2_dll_names = | ||||
| 			{ | ||||
| 				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(MediaFoundation.mfplat); | ||||
| 			SafeFreeLibrary(MediaFoundation.mfreadwrite); | ||||
|  |  | |||
|  | @ -29,6 +29,12 @@ namespace easy2d | |||
| { | ||||
|     namespace modules | ||||
| 	{ | ||||
| 		// modules can be initialized multiple times,
 | ||||
| 		// but it needs to be destroyed every time
 | ||||
| 		void Initialize(); | ||||
| 
 | ||||
| 		void Destroy(); | ||||
| 
 | ||||
| 		// XAudio2 functions
 | ||||
| 		typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR); | ||||
| 
 | ||||
|  | @ -66,13 +72,5 @@ namespace easy2d | |||
| 		}; | ||||
| 
 | ||||
| 		extern Module_MediaFoundation MediaFoundation; | ||||
| 
 | ||||
| 		//
 | ||||
| 		// Functions
 | ||||
| 		//
 | ||||
| 
 | ||||
| 		void Initialize(); | ||||
| 
 | ||||
| 		void Uninitialize(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include "render.h" | ||||
| #include "time.h" | ||||
| #include "base.h" | ||||
| #include "modules.h" | ||||
| 
 | ||||
| #pragma comment(lib, "d2d1.lib") | ||||
| #pragma comment(lib, "dwrite.lib") | ||||
|  | @ -28,33 +29,49 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace render | ||||
| 	namespace devices | ||||
| 	{ | ||||
| 		GraphicsDevice instance; | ||||
| 
 | ||||
| 		GraphicsDevice::GraphicsDevice() | ||||
| 			: fps_text_format_(nullptr) | ||||
| 			, fps_text_layout_(nullptr) | ||||
| 			, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) | ||||
| 		{ | ||||
| 			ZeroMemory(&d2d, sizeof(D2DResources)); | ||||
| 
 | ||||
| 			modules::Initialize(); | ||||
| 		} | ||||
| 
 | ||||
| 		GraphicsDevice::~GraphicsDevice() | ||||
| 		{ | ||||
| 			ClearImageCache(); | ||||
| 
 | ||||
| 			SafeRelease(fps_text_format_); | ||||
| 			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) | ||||
| 		{ | ||||
| 			if (d2d.Factory) | ||||
| 			if (d2d.factory) | ||||
| 				return; | ||||
| 
 | ||||
| 			ThrowIfFailed( | ||||
| 				D2D1CreateFactory( | ||||
| 					D2D1_FACTORY_TYPE_SINGLE_THREADED, | ||||
| 					&d2d.Factory | ||||
| 					&d2d.factory | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
|  | @ -64,7 +81,7 @@ namespace easy2d | |||
| 					nullptr, | ||||
| 					CLSCTX_INPROC_SERVER, | ||||
| 					IID_IWICImagingFactory, | ||||
| 					reinterpret_cast<void**>(&d2d.WICImagingFactory) | ||||
| 					reinterpret_cast<void**>(&d2d.imaging_factory) | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
|  | @ -72,7 +89,7 @@ namespace easy2d | |||
| 				DWriteCreateFactory( | ||||
| 					DWRITE_FACTORY_TYPE_SHARED, | ||||
| 					__uuidof(IDWriteFactory), | ||||
| 					reinterpret_cast<IUnknown**>(&d2d.DWriteFactory) | ||||
| 					reinterpret_cast<IUnknown**>(&d2d.write_factory) | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
|  | @ -87,65 +104,50 @@ namespace easy2d | |||
| 			); | ||||
| 
 | ||||
| 			ThrowIfFailed( | ||||
| 				d2d.Factory->CreateStrokeStyle( | ||||
| 				d2d.factory->CreateStrokeStyle( | ||||
| 					stroke_style, | ||||
| 					nullptr, | ||||
| 					0, | ||||
| 					&d2d.MiterStrokeStyle | ||||
| 					&d2d.miter_stroke_style | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
| 			stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; | ||||
| 
 | ||||
| 			ThrowIfFailed( | ||||
| 				d2d.Factory->CreateStrokeStyle( | ||||
| 				d2d.factory->CreateStrokeStyle( | ||||
| 					stroke_style, | ||||
| 					nullptr, | ||||
| 					0, | ||||
| 					&d2d.BevelStrokeStyle | ||||
| 					&d2d.bevel_stroke_style | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
| 			stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; | ||||
| 
 | ||||
| 			ThrowIfFailed( | ||||
| 				d2d.Factory->CreateStrokeStyle( | ||||
| 				d2d.factory->CreateStrokeStyle( | ||||
| 					stroke_style, | ||||
| 					nullptr, | ||||
| 					0, | ||||
| 					&d2d.RoundStrokeStyle | ||||
| 					&d2d.round_stroke_style | ||||
| 				) | ||||
| 			); | ||||
| 
 | ||||
| 			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) | ||||
| 		{ | ||||
| 			CreateDeviceResources(hwnd); | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->BeginDraw(); | ||||
| 			d2d.HwndRenderTarget->Clear(clear_color_); | ||||
| 			d2d.render_target->BeginDraw(); | ||||
| 			d2d.render_target->Clear(clear_color_); | ||||
| 		} | ||||
| 
 | ||||
| 		void GraphicsDevice::EndDraw() | ||||
| 		{ | ||||
| 			HRESULT hr = d2d.HwndRenderTarget->EndDraw(); | ||||
| 			HRESULT hr = d2d.render_target->EndDraw(); | ||||
| 
 | ||||
| 			if (hr == D2DERR_RECREATE_TARGET) | ||||
| 			{ | ||||
|  | @ -155,36 +157,48 @@ namespace easy2d | |||
| 
 | ||||
| 				SafeRelease(fps_text_format_); | ||||
| 				SafeRelease(fps_text_layout_); | ||||
| 				SafeRelease(d2d.TextRenderer); | ||||
| 				SafeRelease(d2d.SolidColorBrush); | ||||
| 				SafeRelease(d2d.HwndRenderTarget); | ||||
| 				SafeRelease(d2d.text_renderer); | ||||
| 				SafeRelease(d2d.solid_brush); | ||||
| 				SafeRelease(d2d.render_target); | ||||
| 			} | ||||
| 
 | ||||
| 			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( | ||||
| 			const math::Matrix& matrix, | ||||
| 			const Size& size, | ||||
| 			ID2D1Geometry** geometry | ||||
| 		) const | ||||
| 		{ | ||||
| 			if (!d2d.Factory) | ||||
| 			if (!d2d.factory) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			HRESULT hr; | ||||
| 
 | ||||
| 			ID2D1RectangleGeometry * rectangle = nullptr; | ||||
| 			ID2D1TransformedGeometry * transformed = nullptr; | ||||
| 			 | ||||
| 			hr = d2d.Factory->CreateRectangleGeometry( | ||||
| 
 | ||||
| 			hr = d2d.factory->CreateRectangleGeometry( | ||||
| 				D2D1::RectF(0, 0, size.width, size.height), | ||||
| 				&rectangle | ||||
| 			); | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				hr = d2d.Factory->CreateTransformedGeometry( | ||||
| 				hr = d2d.factory->CreateTransformedGeometry( | ||||
| 					rectangle, | ||||
| 					matrix, | ||||
| 					&transformed | ||||
|  | @ -202,10 +216,10 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::CreateTextFormat(IDWriteTextFormat ** text_format, const Font & font) const | ||||
| 		{ | ||||
| 			if (!d2d.DWriteFactory) | ||||
| 			if (!d2d.write_factory) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			return d2d.DWriteFactory->CreateTextFormat( | ||||
| 			return d2d.write_factory->CreateTextFormat( | ||||
| 				font.family.c_str(), | ||||
| 				nullptr, | ||||
| 				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 | ||||
| 		{ | ||||
| 			if (!d2d.DWriteFactory) | ||||
| 			if (!d2d.write_factory) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			UINT32 length = static_cast<UINT32>(text.length()); | ||||
| 			return d2d.DWriteFactory->CreateTextLayout( | ||||
| 			return d2d.write_factory->CreateTextLayout( | ||||
| 				text.c_str(), | ||||
| 				length, | ||||
| 				text_format, | ||||
|  | @ -235,10 +249,10 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::CreateLayer(ID2D1Layer ** layer) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			return d2d.HwndRenderTarget->CreateLayer(layer); | ||||
| 			return d2d.render_target->CreateLayer(layer); | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT GraphicsDevice::DrawGeometry( | ||||
|  | @ -249,15 +263,15 @@ namespace easy2d | |||
| 			StrokeStyle stroke | ||||
| 		) | ||||
| 		{ | ||||
| 			if (!d2d.SolidColorBrush || | ||||
| 				!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.solid_brush || | ||||
| 				!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.SolidColorBrush->SetColor(border_color); | ||||
| 			d2d.SolidColorBrush->SetOpacity(opacity); | ||||
| 			d2d.HwndRenderTarget->DrawGeometry( | ||||
| 			d2d.solid_brush->SetColor(border_color); | ||||
| 			d2d.solid_brush->SetOpacity(opacity); | ||||
| 			d2d.render_target->DrawGeometry( | ||||
| 				geometry, | ||||
| 				d2d.SolidColorBrush, | ||||
| 				d2d.solid_brush, | ||||
| 				stroke_width, | ||||
| 				GetStrokeStyle(stroke) | ||||
| 			); | ||||
|  | @ -270,13 +284,13 @@ namespace easy2d | |||
| 			switch (stroke) | ||||
| 			{ | ||||
| 			case StrokeStyle::Miter: | ||||
| 				stroke_style = d2d.MiterStrokeStyle; | ||||
| 				stroke_style = d2d.miter_stroke_style; | ||||
| 				break; | ||||
| 			case StrokeStyle::Bevel: | ||||
| 				stroke_style = d2d.BevelStrokeStyle; | ||||
| 				stroke_style = d2d.bevel_stroke_style; | ||||
| 				break; | ||||
| 			case StrokeStyle::Round: | ||||
| 				stroke_style = d2d.RoundStrokeStyle; | ||||
| 				stroke_style = d2d.round_stroke_style; | ||||
| 				break; | ||||
| 			} | ||||
| 			return stroke_style; | ||||
|  | @ -289,10 +303,10 @@ namespace easy2d | |||
| 			const Rect & source_rect | ||||
| 		) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->DrawBitmap( | ||||
| 			d2d.render_target->DrawBitmap( | ||||
| 				image->GetBitmap(), | ||||
| 				dest_rect, | ||||
| 				opacity, | ||||
|  | @ -304,19 +318,19 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::DrawTextLayout(IDWriteTextLayout * text_layout) | ||||
| 		{ | ||||
| 			if (!d2d.TextRenderer) | ||||
| 			if (!d2d.text_renderer) | ||||
| 				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) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->SetTransform(clip_matrix); | ||||
| 			d2d.HwndRenderTarget->PushAxisAlignedClip( | ||||
| 			d2d.render_target->SetTransform(clip_matrix); | ||||
| 			d2d.render_target->PushAxisAlignedClip( | ||||
| 				D2D1::RectF(0, 0, clip_size.width, clip_size.height), | ||||
| 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | ||||
| 			); | ||||
|  | @ -325,27 +339,27 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::PopClip() | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->PopAxisAlignedClip(); | ||||
| 			d2d.render_target->PopAxisAlignedClip(); | ||||
| 			return S_OK; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT GraphicsDevice::PushLayer(ID2D1Layer * layer, LayerProperties properties) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget || | ||||
| 				!d2d.SolidColorBrush) | ||||
| 			if (!d2d.render_target || | ||||
| 				!d2d.solid_brush) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->PushLayer( | ||||
| 			d2d.render_target->PushLayer( | ||||
| 				D2D1::LayerParameters( | ||||
| 					properties.area, | ||||
| 					nullptr, | ||||
| 					D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | ||||
| 					D2D1::Matrix3x2F::Identity(), | ||||
| 					properties.opacity, | ||||
| 					d2d.SolidColorBrush, | ||||
| 					d2d.solid_brush, | ||||
| 					D2D1_LAYER_OPTIONS_NONE | ||||
| 				), | ||||
| 				layer | ||||
|  | @ -355,17 +369,17 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::PopLayer() | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->PopLayer(); | ||||
| 			d2d.render_target->PopLayer(); | ||||
| 			return S_OK; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT GraphicsDevice::CreateBitmapFromFile(const String & file_path, ID2D1Bitmap ** bitmap) | ||||
| 		{ | ||||
| 			if (d2d.WICImagingFactory == nullptr || | ||||
| 				d2d.HwndRenderTarget == nullptr) | ||||
| 			if (d2d.imaging_factory == nullptr || | ||||
| 				d2d.render_target == nullptr) | ||||
| 			{ | ||||
| 				return E_UNEXPECTED; | ||||
| 			} | ||||
|  | @ -375,13 +389,20 @@ namespace easy2d | |||
| 				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; | ||||
| 			IWICBitmapFrameDecode*	source = nullptr; | ||||
| 			IWICStream*				stream = nullptr; | ||||
| 			IWICFormatConverter*	converter = nullptr; | ||||
| 
 | ||||
| 			// 创建解码器
 | ||||
| 			HRESULT hr = d2d.WICImagingFactory->CreateDecoderFromFilename( | ||||
| 			HRESULT hr = d2d.imaging_factory->CreateDecoderFromFilename( | ||||
| 				file_path.c_str(), | ||||
| 				nullptr, | ||||
| 				GENERIC_READ, | ||||
|  | @ -398,7 +419,7 @@ namespace easy2d | |||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 创建图片格式转换器
 | ||||
| 				hr = d2d.WICImagingFactory->CreateFormatConverter(&converter); | ||||
| 				hr = d2d.imaging_factory->CreateFormatConverter(&converter); | ||||
| 			} | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
|  | @ -417,13 +438,18 @@ namespace easy2d | |||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 从 WIC 位图创建一个 Direct2D 位图
 | ||||
| 				hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap( | ||||
| 				hr = d2d.render_target->CreateBitmapFromWicBitmap( | ||||
| 					converter, | ||||
| 					nullptr, | ||||
| 					bitmap | ||||
| 				); | ||||
| 			} | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); | ||||
| 			} | ||||
| 
 | ||||
| 			// 释放相关资源
 | ||||
| 			SafeRelease(decoder); | ||||
| 			SafeRelease(source); | ||||
|  | @ -435,8 +461,8 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::CreateBitmapFromResource(Resource & res, ID2D1Bitmap ** bitmap) | ||||
| 		{ | ||||
| 			if (d2d.WICImagingFactory == nullptr || | ||||
| 				d2d.HwndRenderTarget == nullptr) | ||||
| 			if (d2d.imaging_factory == nullptr || | ||||
| 				d2d.render_target == nullptr) | ||||
| 			{ | ||||
| 				return E_UNEXPECTED; | ||||
| 			} | ||||
|  | @ -446,6 +472,13 @@ namespace easy2d | |||
| 				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; | ||||
| 
 | ||||
| 			HINSTANCE				hinstance = GetModuleHandle(nullptr); | ||||
|  | @ -453,14 +486,14 @@ namespace easy2d | |||
| 			IWICBitmapFrameDecode*	source = nullptr; | ||||
| 			IWICStream*				stream = nullptr; | ||||
| 			IWICFormatConverter*	converter = nullptr; | ||||
| 			 | ||||
| 
 | ||||
| 			// 加载资源
 | ||||
| 			hr = res.Load() ? S_OK : E_FAIL; | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 创建 WIC 流
 | ||||
| 				hr = d2d.WICImagingFactory->CreateStream(&stream); | ||||
| 				hr = d2d.imaging_factory->CreateStream(&stream); | ||||
| 			} | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
|  | @ -475,7 +508,7 @@ namespace easy2d | |||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 创建流的解码器
 | ||||
| 				hr = d2d.WICImagingFactory->CreateDecoderFromStream( | ||||
| 				hr = d2d.imaging_factory->CreateDecoderFromStream( | ||||
| 					stream, | ||||
| 					nullptr, | ||||
| 					WICDecodeMetadataCacheOnLoad, | ||||
|  | @ -492,7 +525,7 @@ namespace easy2d | |||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 创建图片格式转换器
 | ||||
| 				hr = d2d.WICImagingFactory->CreateFormatConverter(&converter); | ||||
| 				hr = d2d.imaging_factory->CreateFormatConverter(&converter); | ||||
| 			} | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
|  | @ -511,13 +544,18 @@ namespace easy2d | |||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				// 从 WIC 位图创建一个 Direct2D 位图
 | ||||
| 				hr = d2d.HwndRenderTarget->CreateBitmapFromWicBitmap( | ||||
| 				hr = d2d.render_target->CreateBitmapFromWicBitmap( | ||||
| 					converter, | ||||
| 					nullptr, | ||||
| 					bitmap | ||||
| 				); | ||||
| 			} | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				bitmap_cache_.insert(std::make_pair(hash_code, *bitmap)); | ||||
| 			} | ||||
| 
 | ||||
| 			// 释放相关资源
 | ||||
| 			SafeRelease(decoder); | ||||
| 			SafeRelease(source); | ||||
|  | @ -529,28 +567,28 @@ namespace easy2d | |||
| 
 | ||||
| 		HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->Resize(D2D1::SizeU(width, height)); | ||||
| 			d2d.render_target->Resize(D2D1::SizeU(width, height)); | ||||
| 			return S_OK; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.HwndRenderTarget->SetTransform(matrix); | ||||
| 			d2d.render_target->SetTransform(matrix); | ||||
| 			return S_OK; | ||||
| 		} | ||||
| 
 | ||||
| 		HRESULT GraphicsDevice::SetBrushOpacity(float opacity) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.SolidColorBrush->SetOpacity(opacity); | ||||
| 			d2d.solid_brush->SetOpacity(opacity); | ||||
| 			return S_OK; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -562,10 +600,10 @@ namespace easy2d | |||
| 			StrokeStyle outline_stroke | ||||
| 		) | ||||
| 		{ | ||||
| 			if (!d2d.TextRenderer) | ||||
| 			if (!d2d.text_renderer) | ||||
| 				return E_UNEXPECTED; | ||||
| 
 | ||||
| 			d2d.TextRenderer->SetTextStyle( | ||||
| 			d2d.text_renderer->SetTextStyle( | ||||
| 				color, | ||||
| 				has_outline, | ||||
| 				outline_color, | ||||
|  | @ -590,7 +628,7 @@ namespace easy2d | |||
| 			if (!fps_text_format_) | ||||
| 			{ | ||||
| 				ThrowIfFailed( | ||||
| 					d2d.DWriteFactory->CreateTextFormat( | ||||
| 					d2d.write_factory->CreateTextFormat( | ||||
| 						L"", | ||||
| 						nullptr, | ||||
| 						DWRITE_FONT_WEIGHT_NORMAL, | ||||
|  | @ -621,7 +659,7 @@ namespace easy2d | |||
| 				SafeRelease(fps_text_layout_); | ||||
| 
 | ||||
| 				ThrowIfFailed( | ||||
| 					d2d.DWriteFactory->CreateTextLayout( | ||||
| 					d2d.write_factory->CreateTextLayout( | ||||
| 						fps_text, | ||||
| 						static_cast<UINT32>(len), | ||||
| 						fps_text_format_, | ||||
|  | @ -634,9 +672,9 @@ namespace easy2d | |||
| 
 | ||||
| 			if (fps_text_layout_) | ||||
| 			{ | ||||
| 				d2d.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 				d2d.SolidColorBrush->SetOpacity(1.0f); | ||||
| 				d2d.TextRenderer->SetTextStyle( | ||||
| 				d2d.render_target->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 				d2d.solid_brush->SetOpacity(1.0f); | ||||
| 				d2d.text_renderer->SetTextStyle( | ||||
| 					D2D1::ColorF(D2D1::ColorF::White), | ||||
| 					TRUE, | ||||
| 					D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | ||||
|  | @ -644,13 +682,13 @@ namespace easy2d | |||
| 					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) | ||||
| 		{ | ||||
| 			if (!d2d.HwndRenderTarget) | ||||
| 			if (!d2d.render_target) | ||||
| 			{ | ||||
| 				RECT rc; | ||||
| 				::GetClientRect(hwnd, &rc); | ||||
|  | @ -663,35 +701,35 @@ namespace easy2d | |||
| 				// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 | ||||
| 				// 创建一个 Direct2D 渲染目标
 | ||||
| 				ThrowIfFailed( | ||||
| 					d2d.Factory->CreateHwndRenderTarget( | ||||
| 					d2d.factory->CreateHwndRenderTarget( | ||||
| 						D2D1::RenderTargetProperties(), | ||||
| 						D2D1::HwndRenderTargetProperties( | ||||
| 							hwnd, | ||||
| 							size, | ||||
| 							D2D1_PRESENT_OPTIONS_NONE), | ||||
| 						&d2d.HwndRenderTarget | ||||
| 						&d2d.render_target | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!d2d.SolidColorBrush) | ||||
| 			if (!d2d.solid_brush) | ||||
| 			{ | ||||
| 				ThrowIfFailed( | ||||
| 					d2d.HwndRenderTarget->CreateSolidColorBrush( | ||||
| 					d2d.render_target->CreateSolidColorBrush( | ||||
| 						D2D1::ColorF(D2D1::ColorF::White), | ||||
| 						&d2d.SolidColorBrush | ||||
| 						&d2d.solid_brush | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!d2d.TextRenderer) | ||||
| 			if (!d2d.text_renderer) | ||||
| 			{ | ||||
| 				ThrowIfFailed( | ||||
| 					ITextRenderer::Create( | ||||
| 						&d2d.TextRenderer, | ||||
| 						d2d.Factory, | ||||
| 						d2d.HwndRenderTarget, | ||||
| 						d2d.SolidColorBrush | ||||
| 						&d2d.text_renderer, | ||||
| 						d2d.factory, | ||||
| 						d2d.render_target, | ||||
| 						d2d.solid_brush | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| #include "base.h" | ||||
| #include "Singleton.hpp" | ||||
| #include "Font.h" | ||||
| #include "Resource.h" | ||||
| #include "Image.h" | ||||
|  | @ -28,38 +29,31 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace render | ||||
| 	namespace devices | ||||
| 	{ | ||||
| 		typedef struct | ||||
| 		struct D2DResources | ||||
| 		{ | ||||
| 			ID2D1Factory*			Factory; | ||||
| 			IWICImagingFactory*		WICImagingFactory; | ||||
| 			IDWriteFactory*			DWriteFactory; | ||||
| 			ITextRenderer*			TextRenderer; | ||||
| 			ID2D1SolidColorBrush*	SolidColorBrush; | ||||
| 			ID2D1HwndRenderTarget*	HwndRenderTarget; | ||||
| 			ID2D1StrokeStyle*		MiterStrokeStyle; | ||||
| 			ID2D1StrokeStyle*		BevelStrokeStyle; | ||||
| 			ID2D1StrokeStyle*		RoundStrokeStyle; | ||||
| 		} D2DResources; | ||||
| 			ID2D1Factory*			factory; | ||||
| 			IWICImagingFactory*		imaging_factory; | ||||
| 			IDWriteFactory*			write_factory; | ||||
| 			ITextRenderer*			text_renderer; | ||||
| 			ID2D1SolidColorBrush*	solid_brush; | ||||
| 			ID2D1HwndRenderTarget*	render_target; | ||||
| 			ID2D1StrokeStyle*		miter_stroke_style; | ||||
| 			ID2D1StrokeStyle*		bevel_stroke_style; | ||||
| 			ID2D1StrokeStyle*		round_stroke_style; | ||||
| 		}; | ||||
| 
 | ||||
| 		typedef struct | ||||
| 		{ | ||||
| 			Rect area; | ||||
| 			float opacity; | ||||
| 		} LayerProperties; | ||||
| 
 | ||||
| 		class GraphicsDevice | ||||
| 		{ | ||||
| 			E2D_DECLARE_SINGLETON(GraphicsDevice); | ||||
| 
 | ||||
| 			E2D_DISABLE_COPY(GraphicsDevice); | ||||
| 
 | ||||
| 		public: | ||||
| 			GraphicsDevice(); | ||||
| 
 | ||||
| 			~GraphicsDevice(); | ||||
| 
 | ||||
| 			void Initialize(HWND hwnd); | ||||
| 
 | ||||
| 			void Uninitialize(); | ||||
| 
 | ||||
| 			// ¿ªÊ¼äÖȾ
 | ||||
| 			void BeginDraw(HWND hwnd); | ||||
| 
 | ||||
|  | @ -166,13 +160,21 @@ namespace easy2d | |||
| 				UINT32 height | ||||
| 			); | ||||
| 
 | ||||
| 			void ClearImageCache(); | ||||
| 
 | ||||
| 		protected: | ||||
| 			D2D1_COLOR_F		clear_color_; | ||||
| 			IDWriteTextFormat*	fps_text_format_; | ||||
| 			IDWriteTextLayout*	fps_text_layout_; | ||||
| 			D2DResources		d2d; | ||||
| 			GraphicsDevice(); | ||||
| 
 | ||||
| 			~GraphicsDevice(); | ||||
| 
 | ||||
| 		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 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); | ||||
| 
 | ||||
| 			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, | ||||
| 			wcex.hIcon = (HICON)::LoadImage( | ||||
| 				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) | ||||
| 				::DestroyWindow(handle); | ||||
| 			::UnregisterClass(REGISTER_CLASS, hinstance); | ||||
| 			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); | ||||
| 				return title; | ||||
| 			} | ||||
| 			return String(); | ||||
| 			wchar_t title[256]; | ||||
| 			GetWindowTextW(handle, title, 256); | ||||
| 			return title; | ||||
| 		} | ||||
| 		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) | ||||
| 				::SetWindowText(handle, title.c_str()); | ||||
| 			RECT rect; | ||||
| 			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; | ||||
| 				GetClientRect(handle, &rect); | ||||
| 				return Size( | ||||
| 					static_cast<float>(rect.right - rect.left), | ||||
| 					static_cast<float>(rect.bottom - rect.top) | ||||
| 				); | ||||
| 			} | ||||
| 			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; | ||||
| 			} | ||||
| 			Rect rect = LocateWindow(width, height, scale_x, scale_y); | ||||
| 			::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); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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 | ||||
| #include "base.h" | ||||
| #include "Singleton.hpp" | ||||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace window | ||||
| 	 | ||||
| 
 | ||||
| 	class WindowInfo | ||||
| 	{ | ||||
| 		typedef struct Property | ||||
| 		{ | ||||
| 			String	title;	/* 标题 */ | ||||
| 			int		width;	/* 宽度 */ | ||||
| 			int		height;	/* 高度 */ | ||||
| 			LPCWSTR	icon;	/* 图标 */ | ||||
| 		E2D_DECLARE_SINGLETON(WindowInfo); | ||||
| 
 | ||||
| 			Property() | ||||
| 				: title(L"Easy2D Game") | ||||
| 				, width(640) | ||||
| 				, height(480) | ||||
| 				, icon(nullptr) | ||||
| 			{} | ||||
| 		} Property; | ||||
| 		E2D_DISABLE_COPY(WindowInfo); | ||||
| 
 | ||||
| 		class WindowInfo | ||||
| 		{ | ||||
| 		public: | ||||
| 			HWND handle; | ||||
| 			float xscale; | ||||
| 			float yscale; | ||||
| 	public: | ||||
| 		void Initialize( | ||||
| 			String	title, | ||||
| 			int		width, | ||||
| 			int		height, | ||||
| 			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); | ||||
| 
 | ||||
| 			// 获取窗口高度
 | ||||
| 			float GetHeight() const; | ||||
| 		HWND GetHandle() const; | ||||
| 
 | ||||
| 			// 重设窗口大小
 | ||||
| 			void SetSize(int width, int height); | ||||
| 		float GetContentScaleX() const; | ||||
| 
 | ||||
| 			// 设置窗口图标
 | ||||
| 			void SetIcon(LPCWSTR icon_resource); | ||||
| 		}; | ||||
| 		float GetContentScaleY() const; | ||||
| 
 | ||||
| 		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/Canvas.h" | ||||
| #include "base/Transition.h" | ||||
| #include "base/Music.h" | ||||
| 
 | ||||
| #include "base/KeyEvent.h" | ||||
| #include "base/MouseEvent.h" | ||||
|  | @ -85,9 +86,8 @@ | |||
| #include "utils/Path.h" | ||||
| #include "utils/Data.h" | ||||
| #include "utils/File.h" | ||||
| #include "utils/Transcoder.h" | ||||
| #include "utils/Music.h" | ||||
| #include "utils/Player.h" | ||||
| #include "utils/Transcoder.h" | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
|  |  | |||
|  | @ -112,9 +112,9 @@ namespace easy2d | |||
| 				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; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,6 +50,16 @@ namespace easy2d | |||
| 			, 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 | ||||
| 			{ | ||||
| 				return Vector2(x + other.x, y + other.y); | ||||
|  | @ -80,13 +90,6 @@ namespace easy2d | |||
| 				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 | ||||
| 			{ | ||||
| 				return D2D1_POINT_2F{ x, y }; | ||||
|  |  | |||
|  | @ -223,7 +223,7 @@ namespace easy2d | |||
| 			if (IsVisible() && | ||||
| 				!enabled_ && | ||||
| 				normal_ && | ||||
| 				normal_->ContainsPoint(input::instance.GetMousePos())) | ||||
| 				normal_->ContainsPoint(devices::Input::Instance().GetMousePos())) | ||||
| 			{ | ||||
| 				HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | ||||
| 				if (hcursor) | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ namespace easy2d | |||
| 		class Button | ||||
| 			: public Node | ||||
| 		{ | ||||
| 			E2D_DISABLE_COPY(Button); | ||||
| 
 | ||||
| 			typedef std::function<void()> Callback; | ||||
| 
 | ||||
| 		public: | ||||
|  | @ -101,8 +103,6 @@ namespace easy2d | |||
| 			) override; | ||||
| 
 | ||||
| 		private: | ||||
| 			E2D_DISABLE_COPY(Button); | ||||
| 
 | ||||
| 			// °´Å¥×´Ì¬Ã¶¾Ù
 | ||||
| 			enum class Status { Normal, Mouseover, Selected }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,8 @@ namespace easy2d | |||
| 		class Menu | ||||
| 			: public Node | ||||
| 		{ | ||||
| 			E2D_DISABLE_COPY(Menu); | ||||
| 
 | ||||
| 		public: | ||||
| 			Menu(); | ||||
| 
 | ||||
|  | @ -61,9 +63,6 @@ namespace easy2d | |||
| 			// 获取所有按钮
 | ||||
| 			const std::vector<Button*>& GetAllButtons() const; | ||||
| 
 | ||||
| 		private: | ||||
| 			E2D_DISABLE_COPY(Menu); | ||||
| 
 | ||||
| 		private: | ||||
| 			bool enabled_; | ||||
| 			std::vector<Button*> buttons_; | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ namespace easy2d | |||
| 		{ | ||||
| 			// 设置数据的保存路径
 | ||||
| 			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)); | ||||
| 
 | ||||
| 			if (!local_app_data_path.empty()) | ||||
|  | @ -90,7 +90,7 @@ namespace easy2d | |||
| 		{ | ||||
| 			// 设置临时文件保存路径
 | ||||
| 			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)); | ||||
| 
 | ||||
| 			if (0 != ::GetTempPath(_MAX_PATH, path)) | ||||
|  |  | |||
|  | @ -19,15 +19,10 @@ | |||
| // THE SOFTWARE.
 | ||||
| 
 | ||||
| #include "Player.h" | ||||
| #include "Music.h" | ||||
| #include "../base/Music.h" | ||||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	namespace | ||||
| 	{ | ||||
| 		std::map<size_t, Music*> musics_; | ||||
| 	} | ||||
| 
 | ||||
| 	Player::Player() | ||||
| 		: volume_(1.f) | ||||
| 	{ | ||||
|  | @ -35,6 +30,7 @@ namespace easy2d | |||
| 
 | ||||
| 	Player::~Player() | ||||
| 	{ | ||||
| 		ClearCache(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool Player::Load(const String & file_path) | ||||
|  | @ -51,7 +47,7 @@ namespace easy2d | |||
| 				music->SetVolume(volume_); | ||||
| 
 | ||||
| 				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; | ||||
| 			} | ||||
| 			else | ||||
|  | @ -69,7 +65,7 @@ namespace easy2d | |||
| 
 | ||||
| 		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)) | ||||
| 			{ | ||||
| 				return true; | ||||
|  | @ -84,8 +80,8 @@ namespace easy2d | |||
| 			return; | ||||
| 
 | ||||
| 		size_t hash_code = std::hash<String>{}(file_path); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Pause(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Pause(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Player::Resume(const String & file_path) | ||||
|  | @ -94,8 +90,8 @@ namespace easy2d | |||
| 			return; | ||||
| 
 | ||||
| 		size_t hash_code = std::hash<String>{}(file_path); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Resume(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Resume(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Player::Stop(const String & file_path) | ||||
|  | @ -104,8 +100,8 @@ namespace easy2d | |||
| 			return; | ||||
| 
 | ||||
| 		size_t hash_code = std::hash<String>{}(file_path); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Stop(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Stop(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool Player::IsPlaying(const String & file_path) | ||||
|  | @ -114,15 +110,15 @@ namespace easy2d | |||
| 			return false; | ||||
| 
 | ||||
| 		size_t hash_code = std::hash<String>{}(file_path); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			return musics_[hash_code]->IsPlaying(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			return musics_cache_[hash_code]->IsPlaying(); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	bool Player::Load(Resource& res) | ||||
| 	{ | ||||
| 		size_t hash_code = res.GetHashCode(); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			return true; | ||||
| 
 | ||||
| 		Music * music = new (std::nothrow) Music(); | ||||
|  | @ -132,7 +128,7 @@ namespace easy2d | |||
| 			if (music->Load(res)) | ||||
| 			{ | ||||
| 				music->SetVolume(volume_); | ||||
| 				musics_.insert(std::make_pair(hash_code, music)); | ||||
| 				musics_cache_.insert(std::make_pair(hash_code, music)); | ||||
| 				return true; | ||||
| 			} | ||||
| 			else | ||||
|  | @ -148,7 +144,7 @@ namespace easy2d | |||
| 		if (Load(res)) | ||||
| 		{ | ||||
| 			size_t hash_code = res.GetHashCode(); | ||||
| 			auto music = musics_[hash_code]; | ||||
| 			auto music = musics_cache_[hash_code]; | ||||
| 			if (music->Play(loop_count)) | ||||
| 			{ | ||||
| 				return true; | ||||
|  | @ -160,29 +156,29 @@ namespace easy2d | |||
| 	void Player::Pause(Resource& res) | ||||
| 	{ | ||||
| 		size_t hash_code = res.GetHashCode(); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Pause(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Pause(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Player::Resume(Resource& res) | ||||
| 	{ | ||||
| 		size_t hash_code = res.GetHashCode(); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Resume(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Resume(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Player::Stop(Resource& res) | ||||
| 	{ | ||||
| 		size_t hash_code = res.GetHashCode(); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			musics_[hash_code]->Stop(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			musics_cache_[hash_code]->Stop(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool Player::IsPlaying(Resource& res) | ||||
| 	{ | ||||
| 		size_t hash_code = res.GetHashCode(); | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			return musics_[hash_code]->IsPlaying(); | ||||
| 		if (musics_cache_.end() != musics_cache_.find(hash_code)) | ||||
| 			return musics_cache_[hash_code]->IsPlaying(); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -194,7 +190,7 @@ namespace easy2d | |||
| 	void Player::SetVolume(float volume) | ||||
| 	{ | ||||
| 		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_); | ||||
| 		} | ||||
|  | @ -202,7 +198,7 @@ namespace easy2d | |||
| 
 | ||||
| 	void Player::PauseAll() | ||||
| 	{ | ||||
| 		for (const auto& pair : musics_) | ||||
| 		for (const auto& pair : musics_cache_) | ||||
| 		{ | ||||
| 			pair.second->Pause(); | ||||
| 		} | ||||
|  | @ -210,7 +206,7 @@ namespace easy2d | |||
| 
 | ||||
| 	void Player::ResumeAll() | ||||
| 	{ | ||||
| 		for (const auto& pair : musics_) | ||||
| 		for (const auto& pair : musics_cache_) | ||||
| 		{ | ||||
| 			pair.second->Resume(); | ||||
| 		} | ||||
|  | @ -218,7 +214,7 @@ namespace easy2d | |||
| 
 | ||||
| 	void Player::StopAll() | ||||
| 	{ | ||||
| 		for (const auto& pair : musics_) | ||||
| 		for (const auto& pair : musics_cache_) | ||||
| 		{ | ||||
| 			pair.second->Stop(); | ||||
| 		} | ||||
|  | @ -226,13 +222,13 @@ namespace easy2d | |||
| 
 | ||||
| 	void Player::ClearCache() | ||||
| 	{ | ||||
| 		if (musics_.empty()) | ||||
| 		if (musics_cache_.empty()) | ||||
| 			return; | ||||
| 
 | ||||
| 		for (const auto& pair : musics_) | ||||
| 		for (const auto& pair : musics_cache_) | ||||
| 		{ | ||||
| 			pair.second->Release(); | ||||
| 		} | ||||
| 		musics_.clear(); | ||||
| 		musics_cache_.clear(); | ||||
| 	} | ||||
| } | ||||
|  | @ -24,9 +24,13 @@ | |||
| 
 | ||||
| namespace easy2d | ||||
| { | ||||
| 	class Music; | ||||
| 
 | ||||
| 	// 稜있꺄렴포
 | ||||
| 	class Player | ||||
| 	{ | ||||
| 		E2D_DISABLE_COPY(Player); | ||||
| 
 | ||||
| 	public: | ||||
| 		Player(); | ||||
| 
 | ||||
|  | @ -112,12 +116,10 @@ namespace easy2d | |||
| 		void StopAll(); | ||||
| 
 | ||||
| 		// 헌뇜뻠닸
 | ||||
| 		static void ClearCache(); | ||||
| 
 | ||||
| 	protected: | ||||
| 		E2D_DISABLE_COPY(Player); | ||||
| 		void ClearCache(); | ||||
| 
 | ||||
| 	protected: | ||||
| 		float volume_; | ||||
| 		std::map<size_t, Music*> musics_cache_; | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ namespace easy2d | |||
| 		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; | ||||
| 
 | ||||
|  | @ -64,10 +64,10 @@ namespace easy2d | |||
| 
 | ||||
| 		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; | ||||
| 
 | ||||
|  | @ -86,7 +86,7 @@ namespace easy2d | |||
| 		if (stream == nullptr) | ||||
| 		{ | ||||
| 			logs::Trace(L"SHCreateMemStream"); | ||||
| 			return false; | ||||
| 			return E_OUTOFMEMORY; | ||||
| 		} | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) | ||||
|  | @ -112,7 +112,7 @@ namespace easy2d | |||
| 		SafeRelease(byte_stream); | ||||
| 		SafeRelease(reader); | ||||
| 
 | ||||
| 		return SUCCEEDED(hr); | ||||
| 		return hr; | ||||
| 	} | ||||
| 
 | ||||
| 	HRESULT Transcoder::ReadSource(IMFSourceReader* reader, BYTE** wave_data, UINT32* wave_data_size) | ||||
|  |  | |||
|  | @ -38,13 +38,13 @@ namespace easy2d | |||
| 
 | ||||
| 		WAVEFORMATEX* GetWaveFormatEx() const; | ||||
| 
 | ||||
| 		bool LoadMediaFile( | ||||
| 		HRESULT LoadMediaFile( | ||||
| 			LPCWSTR file_path, | ||||
| 			BYTE** wave_data, | ||||
| 			UINT32* wave_data_size | ||||
| 		); | ||||
| 
 | ||||
| 		bool LoadMediaResource( | ||||
| 		HRESULT LoadMediaResource( | ||||
| 			Resource& res, | ||||
| 			BYTE** wave_data, | ||||
| 			UINT32* wave_data_size | ||||
|  |  | |||
|  | @ -38,12 +38,14 @@ | |||
|     <ClInclude Include="..\..\core\base\macros.h" /> | ||||
|     <ClInclude Include="..\..\core\base\modules.h" /> | ||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Node.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||
|     <ClInclude Include="..\..\core\base\render.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\Size.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Task.h" /> | ||||
|  | @ -62,7 +64,6 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\File.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||
|  | @ -83,6 +84,7 @@ | |||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||
|  | @ -102,7 +104,6 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||
|  |  | |||
|  | @ -122,9 +122,6 @@ | |||
|     <ClInclude Include="..\..\core\utils\File.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|  | @ -140,6 +137,12 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Music.h"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="base"> | ||||
|  | @ -252,9 +255,6 @@ | |||
|     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -270,5 +270,8 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  | @ -38,12 +38,14 @@ | |||
|     <ClInclude Include="..\..\core\base\macros.h" /> | ||||
|     <ClInclude Include="..\..\core\base\modules.h" /> | ||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Node.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||
|     <ClInclude Include="..\..\core\base\render.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\Size.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Task.h" /> | ||||
|  | @ -62,7 +64,6 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\File.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||
|  | @ -83,6 +84,7 @@ | |||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||
|  | @ -102,7 +104,6 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||
|  |  | |||
|  | @ -122,9 +122,6 @@ | |||
|     <ClInclude Include="..\..\core\utils\File.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|  | @ -140,6 +137,12 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Music.h"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="base"> | ||||
|  | @ -252,9 +255,6 @@ | |||
|     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -270,5 +270,8 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  | @ -38,12 +38,14 @@ | |||
|     <ClInclude Include="..\..\core\base\macros.h" /> | ||||
|     <ClInclude Include="..\..\core\base\modules.h" /> | ||||
|     <ClInclude Include="..\..\core\base\MouseEvent.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Node.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Rect.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\RefCounter.h" /> | ||||
|     <ClInclude Include="..\..\core\base\render.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Resource.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Scene.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp" /> | ||||
|     <ClInclude Include="..\..\core\base\Size.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Sprite.h" /> | ||||
|     <ClInclude Include="..\..\core\base\Task.h" /> | ||||
|  | @ -62,7 +64,6 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Data.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\File.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Player.h" /> | ||||
|     <ClInclude Include="..\..\core\utils\Transcoder.h" /> | ||||
|  | @ -83,6 +84,7 @@ | |||
|     <ClCompile Include="..\..\core\base\KeyEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\modules.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\MouseEvent.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\Node.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\RefCounter.cpp" /> | ||||
|     <ClCompile Include="..\..\core\base\render.cpp" /> | ||||
|  | @ -102,7 +104,6 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Data.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\File.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Player.cpp" /> | ||||
|     <ClCompile Include="..\..\core\utils\Transcoder.cpp" /> | ||||
|  |  | |||
|  | @ -122,9 +122,6 @@ | |||
|     <ClInclude Include="..\..\core\utils\File.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Music.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\utils\Path.h"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClInclude> | ||||
|  | @ -140,6 +137,12 @@ | |||
|     <ClInclude Include="..\..\core\ui\Menu.h"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Music.h"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\core\base\Singleton.hpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="base"> | ||||
|  | @ -252,9 +255,6 @@ | |||
|     <ClCompile Include="..\..\core\utils\File.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Music.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\utils\Path.cpp"> | ||||
|       <Filter>utils</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -270,5 +270,8 @@ | |||
|     <ClCompile Include="..\..\core\ui\Menu.cpp"> | ||||
|       <Filter>ui</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\core\base\Music.cpp"> | ||||
|       <Filter>base</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
		Loading…
	
		Reference in New Issue