update: code style
This commit is contained in:
		
							parent
							
								
									0f1ba104dd
								
							
						
					
					
						commit
						b129a1bf18
					
				|  | @ -20,86 +20,90 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Action::Action()  |  | ||||||
| 	: running_(false) |  | ||||||
| 	, done_(false) |  | ||||||
| 	, initialized_(false) |  | ||||||
| 	, target_(nullptr) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Action::~Action() | namespace easy2d | ||||||
| { | { | ||||||
| } | 	Action::Action() | ||||||
| 
 | 		: running_(false) | ||||||
| bool easy2d::Action::IsRunning() | 		, done_(false) | ||||||
| { | 		, initialized_(false) | ||||||
| 	return running_; | 		, target_(nullptr) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Resume() |  | ||||||
| { |  | ||||||
| 	running_ = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Pause() |  | ||||||
| { |  | ||||||
| 	running_ = false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Stop() |  | ||||||
| { |  | ||||||
| 	done_ = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const std::wstring& easy2d::Action::GetName() const |  | ||||||
| { |  | ||||||
| 	return name_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::SetName(const std::wstring& name) |  | ||||||
| { |  | ||||||
| 	name_ = name; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Node * easy2d::Action::GetTarget() |  | ||||||
| { |  | ||||||
| 	return target_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Reset() |  | ||||||
| { |  | ||||||
| 	initialized_ = false; |  | ||||||
| 	done_ = false; |  | ||||||
| 	started_ = Time::Now(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Action::IsDone() const |  | ||||||
| { |  | ||||||
| 	return done_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::StartWithTarget(Node* target) |  | ||||||
| { |  | ||||||
| 	target_ = target; |  | ||||||
| 	running_ = true; |  | ||||||
| 	this->Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Init() |  | ||||||
| { |  | ||||||
| 	initialized_ = true; |  | ||||||
| 	started_ = Time::Now(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Action::Update() |  | ||||||
| { |  | ||||||
| 	if (!initialized_) |  | ||||||
| 	{ | 	{ | ||||||
| 		Init(); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Action::ResetTime() | 	Action::~Action() | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Action::IsRunning() | ||||||
|  | 	{ | ||||||
|  | 		return running_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Resume() | ||||||
|  | 	{ | ||||||
|  | 		running_ = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Pause() | ||||||
|  | 	{ | ||||||
|  | 		running_ = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Stop() | ||||||
|  | 	{ | ||||||
|  | 		done_ = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const std::wstring& Action::GetName() const | ||||||
|  | 	{ | ||||||
|  | 		return name_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::SetName(const std::wstring& name) | ||||||
|  | 	{ | ||||||
|  | 		name_ = name; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Node * Action::GetTarget() | ||||||
|  | 	{ | ||||||
|  | 		return target_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Reset() | ||||||
|  | 	{ | ||||||
|  | 		initialized_ = false; | ||||||
|  | 		done_ = false; | ||||||
|  | 		started_ = Time::Now(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Action::IsDone() const | ||||||
|  | 	{ | ||||||
|  | 		return done_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::StartWithTarget(Node* target) | ||||||
|  | 	{ | ||||||
|  | 		target_ = target; | ||||||
|  | 		running_ = true; | ||||||
|  | 		this->Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Init() | ||||||
|  | 	{ | ||||||
|  | 		initialized_ = true; | ||||||
|  | 		started_ = Time::Now(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::Update() | ||||||
|  | 	{ | ||||||
|  | 		if (!initialized_) | ||||||
|  | 		{ | ||||||
|  | 			Init(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Action::ResetTime() | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,115 +21,118 @@ | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Animate::Animate()  | namespace easy2d | ||||||
| 	: frame_index_(0) |  | ||||||
| 	, animation_(nullptr) |  | ||||||
| { | { | ||||||
| } | 	Animate::Animate() | ||||||
|  | 		: frame_index_(0) | ||||||
|  | 		, animation_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Animate::Animate(Animation * animation) | 	Animate::Animate(Animation * animation) | ||||||
| 	: frame_index_(0) | 		: frame_index_(0) | ||||||
| 	, animation_(nullptr) | 		, animation_(nullptr) | ||||||
| { | 	{ | ||||||
| 	this->SetAnimation(animation); | 		this->SetAnimation(animation); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Animate::~Animate() | 	Animate::~Animate() | ||||||
| { | 	{ | ||||||
| 	SafeRelease(animation_); | 		SafeRelease(animation_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Animation * easy2d::Animate::GetAnimation() const | 	Animation * Animate::GetAnimation() const | ||||||
| { | 	{ | ||||||
| 	return animation_; | 		return animation_; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Animate::SetAnimation(Animation * animation) | 	void Animate::SetAnimation(Animation * animation) | ||||||
| { | 	{ | ||||||
| 	if (animation && animation != animation_) | 		if (animation && animation != animation_) | ||||||
|  | 		{ | ||||||
|  | 			if (animation_) | ||||||
|  | 			{ | ||||||
|  | 				animation_->Release(); | ||||||
|  | 			} | ||||||
|  | 			animation_ = animation; | ||||||
|  | 			animation_->Retain(); | ||||||
|  | 			frame_index_ = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Animate::Init() | ||||||
|  | 	{ | ||||||
|  | 		Action::Init(); | ||||||
|  | 
 | ||||||
|  | 		auto target = dynamic_cast<Sprite*>(target_); | ||||||
|  | 		if (target && animation_) | ||||||
|  | 		{ | ||||||
|  | 			target->Load(animation_->GetFrames()[frame_index_]); | ||||||
|  | 			++frame_index_; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Animate::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (!animation_) | ||||||
|  | 		{ | ||||||
|  | 			this->Stop(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		while ((Time::Now() - started_).Seconds() >= animation_->GetInterval()) | ||||||
|  | 		{ | ||||||
|  | 			auto& frames = animation_->GetFrames(); | ||||||
|  | 			auto target = dynamic_cast<Sprite*>(target_); | ||||||
|  | 
 | ||||||
|  | 			if (target) | ||||||
|  | 			{ | ||||||
|  | 				target->Load(frames[frame_index_]); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			started_ += Duration::Second * animation_->GetInterval(); | ||||||
|  | 			++frame_index_; | ||||||
|  | 
 | ||||||
|  | 			if (frame_index_ == frames.size()) | ||||||
|  | 			{ | ||||||
|  | 				this->Stop(); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Animate::ResetTime() | ||||||
|  | 	{ | ||||||
|  | 		Action::ResetTime(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Animate::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 		frame_index_ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Animate * Animate::Clone() const | ||||||
| 	{ | 	{ | ||||||
| 		if (animation_) | 		if (animation_) | ||||||
| 		{ | 		{ | ||||||
| 			animation_->Release(); | 			return new Animate(animation_); | ||||||
| 		} | 		} | ||||||
| 		animation_ = animation; | 		return nullptr; | ||||||
| 		animation_->Retain(); |  | ||||||
| 		frame_index_ = 0; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Animate::Init() |  | ||||||
| { |  | ||||||
| 	Action::Init(); |  | ||||||
| 
 |  | ||||||
| 	auto target = dynamic_cast<Sprite*>(target_); |  | ||||||
| 	if (target && animation_) |  | ||||||
| 	{ |  | ||||||
| 		target->Load(animation_->GetFrames()[frame_index_]); |  | ||||||
| 		++frame_index_; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Animate::Update() |  | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (!animation_) |  | ||||||
| 	{ |  | ||||||
| 		this->Stop(); |  | ||||||
| 		return; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	while ((Time::Now() - started_).Seconds() >= animation_->GetInterval()) | 	Animate * Animate::Reverse() const | ||||||
| 	{ | 	{ | ||||||
| 		auto& frames = animation_->GetFrames(); | 		if (animation_) | ||||||
| 		auto target = dynamic_cast<Sprite*>(target_); |  | ||||||
| 
 |  | ||||||
| 		if (target) |  | ||||||
| 		{ | 		{ | ||||||
| 			target->Load(frames[frame_index_]); | 			auto animation = animation_->Reverse(); | ||||||
| 		} | 			if (animation) | ||||||
| 
 | 			{ | ||||||
| 		started_ += Duration::Second * animation_->GetInterval(); | 				return new Animate(animation); | ||||||
| 		++frame_index_; | 			} | ||||||
| 
 |  | ||||||
| 		if (frame_index_ == frames.size()) |  | ||||||
| 		{ |  | ||||||
| 			this->Stop(); |  | ||||||
| 			break; |  | ||||||
| 		} | 		} | ||||||
|  | 		return nullptr; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void easy2d::Animate::ResetTime() |  | ||||||
| { |  | ||||||
| 	Action::ResetTime(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Animate::Reset() |  | ||||||
| { |  | ||||||
| 	Action::Reset(); |  | ||||||
| 	frame_index_ = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animate * easy2d::Animate::Clone() const |  | ||||||
| { |  | ||||||
| 	if (animation_) |  | ||||||
| 	{ |  | ||||||
| 		return new Animate(animation_); |  | ||||||
| 	} |  | ||||||
| 	return nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animate * easy2d::Animate::Reverse() const |  | ||||||
| { |  | ||||||
| 	if (animation_) |  | ||||||
| 	{ |  | ||||||
| 		auto animation = animation_->Reverse(); |  | ||||||
| 		if (animation) |  | ||||||
| 		{ |  | ||||||
| 			return new Animate(animation); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nullptr; |  | ||||||
| } |  | ||||||
|  | @ -20,101 +20,104 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Animation::Animation() | namespace easy2d | ||||||
| 	: interval_(1) |  | ||||||
| { | { | ||||||
| } | 	Animation::Animation() | ||||||
| 
 | 		: interval_(1) | ||||||
| easy2d::Animation::Animation(const Images& frames) |  | ||||||
| 	: interval_(1) |  | ||||||
| { |  | ||||||
| 	this->Add(frames); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animation::Animation(float interval) |  | ||||||
| 	: interval_(interval) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animation::Animation(float interval, const Images& frames) |  | ||||||
| 	: interval_(interval) |  | ||||||
| { |  | ||||||
| 	this->Add(frames); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animation::~Animation() |  | ||||||
| { |  | ||||||
| 	for (auto frame : frames_) |  | ||||||
| 	{ | 	{ | ||||||
| 		SafeRelease(frame); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Animation::SetInterval(float interval) | 	Animation::Animation(const Images& frames) | ||||||
| { | 		: interval_(1) | ||||||
| 	interval_ = std::max(interval, 0.f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Animation::Add(Image * frame) |  | ||||||
| { |  | ||||||
| 	E2D_WARNING_IF(frame == nullptr, "Animation::Add failed, frame Is nullptr."); |  | ||||||
| 	if (frame) |  | ||||||
| 	{ | 	{ | ||||||
| 		frames_.push_back(frame); | 		this->Add(frames); | ||||||
| 		frame->Retain(); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Animation::Add(const Images& frames) | 	Animation::Animation(float interval) | ||||||
| { | 		: interval_(interval) | ||||||
| 	for (const auto &image : frames) |  | ||||||
| 	{ | 	{ | ||||||
| 		this->Add(image); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| float easy2d::Animation::GetInterval() const | 	Animation::Animation(float interval, const Images& frames) | ||||||
| { | 		: interval_(interval) | ||||||
| 	return interval_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const easy2d::Animation::Images& easy2d::Animation::GetFrames() const |  | ||||||
| { |  | ||||||
| 	return frames_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Animation * easy2d::Animation::Clone() const |  | ||||||
| { |  | ||||||
| 	auto animation = new Animation(interval_); |  | ||||||
| 	if (animation) |  | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& frame : frames_) | 		this->Add(frames); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Animation::~Animation() | ||||||
|  | 	{ | ||||||
|  | 		for (auto frame : frames_) | ||||||
| 		{ | 		{ | ||||||
| 			animation->Add(frame); | 			SafeRelease(frame); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return animation; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Animation * easy2d::Animation::Reverse() const | 	void Animation::SetInterval(float interval) | ||||||
| { |  | ||||||
| 	auto& oldFrames = this->GetFrames(); |  | ||||||
| 	Images frames(oldFrames.size()); |  | ||||||
| 
 |  | ||||||
| 	if (!oldFrames.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		for (auto iter = oldFrames.crbegin(), | 		interval_ = std::max(interval, 0.f); | ||||||
| 			iterCrend = oldFrames.crend(); | 	} | ||||||
| 			iter != iterCrend; | 
 | ||||||
| 			++iter) | 	void Animation::Add(Image * frame) | ||||||
|  | 	{ | ||||||
|  | 		E2D_WARNING_IF(frame == nullptr, "Animation::Add failed, frame Is nullptr."); | ||||||
|  | 		if (frame) | ||||||
| 		{ | 		{ | ||||||
| 			Image* frame = *iter; | 			frames_.push_back(frame); | ||||||
| 			if (frame) | 			frame->Retain(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Animation::Add(const Images& frames) | ||||||
|  | 	{ | ||||||
|  | 		for (const auto &image : frames) | ||||||
|  | 		{ | ||||||
|  | 			this->Add(image); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Animation::GetInterval() const | ||||||
|  | 	{ | ||||||
|  | 		return interval_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Animation::Images& Animation::GetFrames() const | ||||||
|  | 	{ | ||||||
|  | 		return frames_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Animation * Animation::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		auto animation = new Animation(interval_); | ||||||
|  | 		if (animation) | ||||||
|  | 		{ | ||||||
|  | 			for (const auto& frame : frames_) | ||||||
| 			{ | 			{ | ||||||
| 				frames.push_back(frame); | 				animation->Add(frame); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		return animation; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return new Animation(this->GetInterval(), frames); | 	Animation * Animation::Reverse() const | ||||||
| } | 	{ | ||||||
|  | 		auto& oldFrames = this->GetFrames(); | ||||||
|  | 		Images frames(oldFrames.size()); | ||||||
|  | 
 | ||||||
|  | 		if (!oldFrames.empty()) | ||||||
|  | 		{ | ||||||
|  | 			for (auto iter = oldFrames.crbegin(), | ||||||
|  | 				iterCrend = oldFrames.crend(); | ||||||
|  | 				iter != iterCrend; | ||||||
|  | 				++iter) | ||||||
|  | 			{ | ||||||
|  | 				Image* frame = *iter; | ||||||
|  | 				if (frame) | ||||||
|  | 				{ | ||||||
|  | 					frames.push_back(frame); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return new Animation(this->GetInterval(), frames); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,27 +20,30 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::CallFunc::CallFunc(const Callback& func) : | namespace easy2d | ||||||
| 	callback_(func) |  | ||||||
| { | { | ||||||
| } | 	CallFunc::CallFunc(const Callback& func) : | ||||||
|  | 		callback_(func) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::CallFunc * easy2d::CallFunc::Clone() const | 	CallFunc * CallFunc::Clone() const | ||||||
| { | 	{ | ||||||
| 	return new CallFunc(callback_); | 		return new CallFunc(callback_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::CallFunc * easy2d::CallFunc::Reverse() const | 	CallFunc * CallFunc::Reverse() const | ||||||
| { | 	{ | ||||||
| 	return new CallFunc(callback_); | 		return new CallFunc(callback_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::CallFunc::Init() | 	void CallFunc::Init() | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::CallFunc::Update() | 	void CallFunc::Update() | ||||||
| { | 	{ | ||||||
| 	callback_(); | 		callback_(); | ||||||
| 	this->Stop(); | 		this->Stop(); | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -20,47 +20,50 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Delay::Delay(float duration) | namespace easy2d | ||||||
| 	: delta_(0) |  | ||||||
| 	, delay_(std::max(duration, 0.f)) |  | ||||||
| { | { | ||||||
| } | 	Delay::Delay(float duration) | ||||||
| 
 | 		: delta_(0) | ||||||
| easy2d::Delay * easy2d::Delay::Clone() const | 		, delay_(std::max(duration, 0.f)) | ||||||
| { |  | ||||||
| 	return new Delay(delay_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Delay * easy2d::Delay::Reverse() const |  | ||||||
| { |  | ||||||
| 	return new Delay(delay_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Delay::Reset() |  | ||||||
| { |  | ||||||
| 	Action::Reset(); |  | ||||||
| 	delta_ = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Delay::Init() |  | ||||||
| { |  | ||||||
| 	Action::Init(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Delay::Update() |  | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	delta_ = (Time::Now() - started_).Seconds(); |  | ||||||
| 
 |  | ||||||
| 	if (delta_ >= delay_) |  | ||||||
| 	{ | 	{ | ||||||
| 		this->Stop(); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Delay::ResetTime() | 	Delay * Delay::Clone() const | ||||||
| { | 	{ | ||||||
| 	Action::ResetTime(); | 		return new Delay(delay_); | ||||||
| 	started_ = Time::Now() - Duration::Second * delta_; | 	} | ||||||
| } | 
 | ||||||
|  | 	Delay * Delay::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new Delay(delay_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Delay::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 		delta_ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Delay::Init() | ||||||
|  | 	{ | ||||||
|  | 		Action::Init(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Delay::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		delta_ = (Time::Now() - started_).Seconds(); | ||||||
|  | 
 | ||||||
|  | 		if (delta_ >= delay_) | ||||||
|  | 		{ | ||||||
|  | 			this->Stop(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Delay::ResetTime() | ||||||
|  | 	{ | ||||||
|  | 		Action::ResetTime(); | ||||||
|  | 		started_ = Time::Now() - Duration::Second * delta_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,7 +20,10 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::FadeIn::FadeIn(float duration) | namespace easy2d | ||||||
| 	: OpacityTo(duration, 1) |  | ||||||
| { | { | ||||||
| } | 	FadeIn::FadeIn(float duration) | ||||||
|  | 		: OpacityTo(duration, 1) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,7 +20,10 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::FadeOut::FadeOut(float duration) | namespace easy2d | ||||||
| 	: OpacityTo(duration, 0) |  | ||||||
| { | { | ||||||
| } | 	FadeOut::FadeOut(float duration) | ||||||
|  | 		: OpacityTo(duration, 0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,45 +20,48 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::FiniteTimeAction::FiniteTimeAction(float duration) | namespace easy2d | ||||||
| 	: delta_(0) |  | ||||||
| 	, duration_(std::max(duration, 0.f)) |  | ||||||
| { | { | ||||||
| } | 	FiniteTimeAction::FiniteTimeAction(float duration) | ||||||
| 
 | 		: delta_(0) | ||||||
| void easy2d::FiniteTimeAction::Reset() | 		, duration_(std::max(duration, 0.f)) | ||||||
| { |  | ||||||
| 	Action::Reset(); |  | ||||||
| 	delta_ = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::FiniteTimeAction::Init() |  | ||||||
| { |  | ||||||
| 	Action::Init(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::FiniteTimeAction::Update() |  | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (duration_ == 0) |  | ||||||
| 	{ | 	{ | ||||||
| 		delta_ = 1; |  | ||||||
| 		this->Stop(); |  | ||||||
| 	} | 	} | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		delta_ = std::min((Time::Now() - started_).Seconds() / duration_, 1.f); |  | ||||||
| 
 | 
 | ||||||
| 		if (delta_ >= 1) | 	void FiniteTimeAction::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 		delta_ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void FiniteTimeAction::Init() | ||||||
|  | 	{ | ||||||
|  | 		Action::Init(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void FiniteTimeAction::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (duration_ == 0) | ||||||
| 		{ | 		{ | ||||||
|  | 			delta_ = 1; | ||||||
| 			this->Stop(); | 			this->Stop(); | ||||||
| 		} | 		} | ||||||
| 	} | 		else | ||||||
| } | 		{ | ||||||
|  | 			delta_ = std::min((Time::Now() - started_).Seconds() / duration_, 1.f); | ||||||
| 
 | 
 | ||||||
| void easy2d::FiniteTimeAction::ResetTime() | 			if (delta_ >= 1) | ||||||
| { | 			{ | ||||||
| 	Action::ResetTime(); | 				this->Stop(); | ||||||
| 	started_ = Time::Now() - Duration::Second * (delta_ * duration_); | 			} | ||||||
| } | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void FiniteTimeAction::ResetTime() | ||||||
|  | 	{ | ||||||
|  | 		Action::ResetTime(); | ||||||
|  | 		started_ = Time::Now() - Duration::Second * (delta_ * duration_); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,53 +21,56 @@ | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps) | namespace easy2d | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| 	, delta_pos_(vec) |  | ||||||
| 	, height_(height) |  | ||||||
| 	, jumps_(jumps) |  | ||||||
| { | { | ||||||
| } | 	JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps) | ||||||
| 
 | 		: FiniteTimeAction(duration) | ||||||
| easy2d::JumpBy * easy2d::JumpBy::Clone() const | 		, delta_pos_(vec) | ||||||
| { | 		, height_(height) | ||||||
| 	return new JumpBy(duration_, delta_pos_, height_, jumps_); | 		, jumps_(jumps) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::JumpBy * easy2d::JumpBy::Reverse() const |  | ||||||
| { |  | ||||||
| 	return new JumpBy(duration_, -delta_pos_, height_, jumps_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::JumpBy::Init() |  | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		prev_pos_ = start_pos_ = target_->GetPosition(); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::JumpBy::Update() | 	JumpBy * JumpBy::Clone() const | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		float frac = fmod(delta_ * jumps_, 1.f); | 		return new JumpBy(duration_, delta_pos_, height_, jumps_); | ||||||
| 		float x = delta_pos_.x * delta_; |  | ||||||
| 		float y = height_ * 4 * frac * (1 - frac); |  | ||||||
| 		y += delta_pos_.y * delta_; |  | ||||||
| 
 |  | ||||||
| 		Point currentPos = target_->GetPosition(); |  | ||||||
| 
 |  | ||||||
| 		Point diff = currentPos - prev_pos_; |  | ||||||
| 		start_pos_ = diff + start_pos_; |  | ||||||
| 
 |  | ||||||
| 		Point newPos = start_pos_ + Point(x, y); |  | ||||||
| 		target_->SetPosition(newPos); |  | ||||||
| 
 |  | ||||||
| 		prev_pos_ = newPos; |  | ||||||
| 	} | 	} | ||||||
| } | 
 | ||||||
|  | 	JumpBy * JumpBy::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new JumpBy(duration_, -delta_pos_, height_, jumps_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void JumpBy::Init() | ||||||
|  | 	{ | ||||||
|  | 		FiniteTimeAction::Init(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			prev_pos_ = start_pos_ = target_->GetPosition(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void JumpBy::Update() | ||||||
|  | 	{ | ||||||
|  | 		FiniteTimeAction::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			float frac = fmod(delta_ * jumps_, 1.f); | ||||||
|  | 			float x = delta_pos_.x * delta_; | ||||||
|  | 			float y = height_ * 4 * frac * (1 - frac); | ||||||
|  | 			y += delta_pos_.y * delta_; | ||||||
|  | 
 | ||||||
|  | 			Point currentPos = target_->GetPosition(); | ||||||
|  | 
 | ||||||
|  | 			Point diff = currentPos - prev_pos_; | ||||||
|  | 			start_pos_ = diff + start_pos_; | ||||||
|  | 
 | ||||||
|  | 			Point newPos = start_pos_ + Point(x, y); | ||||||
|  | 			target_->SetPosition(newPos); | ||||||
|  | 
 | ||||||
|  | 			prev_pos_ = newPos; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,19 +21,22 @@ | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps) | namespace easy2d | ||||||
| 	: JumpBy(duration, Point(), height, jumps) |  | ||||||
| 	, end_pos_(pos) |  | ||||||
| { | { | ||||||
| } | 	JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps) | ||||||
|  | 		: JumpBy(duration, Point(), height, jumps) | ||||||
|  | 		, end_pos_(pos) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::JumpTo * easy2d::JumpTo::Clone() const | 	JumpTo * JumpTo::Clone() const | ||||||
| { | 	{ | ||||||
| 	return new JumpTo(duration_, end_pos_, height_, jumps_); | 		return new JumpTo(duration_, end_pos_, height_, jumps_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::JumpTo::Init() | 	void JumpTo::Init() | ||||||
| { | 	{ | ||||||
| 	JumpBy::Init(); | 		JumpBy::Init(); | ||||||
| 	delta_pos_ = end_pos_ - start_pos_; | 		delta_pos_ = end_pos_ - start_pos_; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -20,97 +20,100 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Loop::Loop(Action * action, int times /* = -1 */) | namespace easy2d | ||||||
| 	: action_(action) |  | ||||||
| 	, times_(0) |  | ||||||
| 	, total_times_(times) |  | ||||||
| { | { | ||||||
| 	E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!"); | 	Loop::Loop(Action * action, int times /* = -1 */) | ||||||
| 
 | 		: action_(action) | ||||||
| 	if (action) | 		, times_(0) | ||||||
|  | 		, total_times_(times) | ||||||
| 	{ | 	{ | ||||||
| 		action_ = action; | 		E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!"); | ||||||
| 		action_->Retain(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Loop::~Loop() | 		if (action) | ||||||
| { |  | ||||||
| 	SafeRelease(action_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Loop * easy2d::Loop::Clone() const |  | ||||||
| { |  | ||||||
| 	if (action_) |  | ||||||
| 	{ |  | ||||||
| 		return new Loop(action_->Clone()); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		return nullptr; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Loop * easy2d::Loop::Reverse() const |  | ||||||
| { |  | ||||||
| 	if (action_) |  | ||||||
| 	{ |  | ||||||
| 		return new Loop(action_->Clone()); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		return nullptr; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Loop::Init() |  | ||||||
| { |  | ||||||
| 	Action::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (action_) |  | ||||||
| 	{ |  | ||||||
| 		action_->target_ = target_; |  | ||||||
| 		action_->Init(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Loop::Update() |  | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (times_ == total_times_) |  | ||||||
| 	{ |  | ||||||
| 		this->Stop(); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (action_) |  | ||||||
| 	{ |  | ||||||
| 		action_->Update(); |  | ||||||
| 
 |  | ||||||
| 		if (action_->IsDone()) |  | ||||||
| 		{ | 		{ | ||||||
| 			++times_; | 			action_ = action; | ||||||
| 
 | 			action_->Retain(); | ||||||
| 			Action::Reset(); |  | ||||||
| 			action_->Reset(); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	Loop::~Loop() | ||||||
| 	{ | 	{ | ||||||
| 		this->Stop(); | 		SafeRelease(action_); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Loop::Reset() | 	Loop * Loop::Clone() const | ||||||
| { | 	{ | ||||||
| 	Action::Reset(); | 		if (action_) | ||||||
|  | 		{ | ||||||
|  | 			return new Loop(action_->Clone()); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return nullptr; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (action_) action_->Reset(); | 	Loop * Loop::Reverse() const | ||||||
| 	times_ = 0; | 	{ | ||||||
| } | 		if (action_) | ||||||
|  | 		{ | ||||||
|  | 			return new Loop(action_->Clone()); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return nullptr; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Loop::ResetTime() | 	void Loop::Init() | ||||||
| { | 	{ | ||||||
| 	if (action_) action_->ResetTime(); | 		Action::Init(); | ||||||
| } | 
 | ||||||
|  | 		if (action_) | ||||||
|  | 		{ | ||||||
|  | 			action_->target_ = target_; | ||||||
|  | 			action_->Init(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Loop::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (times_ == total_times_) | ||||||
|  | 		{ | ||||||
|  | 			this->Stop(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (action_) | ||||||
|  | 		{ | ||||||
|  | 			action_->Update(); | ||||||
|  | 
 | ||||||
|  | 			if (action_->IsDone()) | ||||||
|  | 			{ | ||||||
|  | 				++times_; | ||||||
|  | 
 | ||||||
|  | 				Action::Reset(); | ||||||
|  | 				action_->Reset(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			this->Stop(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Loop::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 
 | ||||||
|  | 		if (action_) action_->Reset(); | ||||||
|  | 		times_ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Loop::ResetTime() | ||||||
|  | 	{ | ||||||
|  | 		if (action_) action_->ResetTime(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -22,45 +22,48 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::MoveBy::MoveBy(float duration, Point vector) | namespace easy2d | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| { | { | ||||||
| 	delta_pos_ = vector; | 	MoveBy::MoveBy(float duration, Point vector) | ||||||
| } | 		: FiniteTimeAction(duration) | ||||||
| 
 |  | ||||||
| void easy2d::MoveBy::Init() |  | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		prev_pos_ = start_pos_ = target_->GetPosition(); | 		delta_pos_ = vector; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::MoveBy::Update() | 	void MoveBy::Init() | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		Point currentPos = target_->GetPosition(); | 		FiniteTimeAction::Init(); | ||||||
| 		Point diff = currentPos - prev_pos_; |  | ||||||
| 		start_pos_ = start_pos_ + diff; |  | ||||||
| 
 | 
 | ||||||
| 		Point newPos = start_pos_ + (delta_pos_ * delta_); | 		if (target_) | ||||||
| 		target_->SetPosition(newPos); | 		{ | ||||||
| 
 | 			prev_pos_ = start_pos_ = target_->GetPosition(); | ||||||
| 		prev_pos_ = newPos; | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::MoveBy * easy2d::MoveBy::Clone() const | 	void MoveBy::Update() | ||||||
| { | 	{ | ||||||
| 	return new MoveBy(duration_, delta_pos_); | 		FiniteTimeAction::Update(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::MoveBy * easy2d::MoveBy::Reverse() const | 		if (target_) | ||||||
| { | 		{ | ||||||
| 	return new MoveBy(duration_, -delta_pos_); | 			Point currentPos = target_->GetPosition(); | ||||||
|  | 			Point diff = currentPos - prev_pos_; | ||||||
|  | 			start_pos_ = start_pos_ + diff; | ||||||
|  | 
 | ||||||
|  | 			Point newPos = start_pos_ + (delta_pos_ * delta_); | ||||||
|  | 			target_->SetPosition(newPos); | ||||||
|  | 
 | ||||||
|  | 			prev_pos_ = newPos; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	MoveBy * MoveBy::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		return new MoveBy(duration_, delta_pos_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	MoveBy * MoveBy::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new MoveBy(duration_, -delta_pos_); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -21,19 +21,22 @@ | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::MoveTo::MoveTo(float duration, Point pos) | namespace easy2d | ||||||
| 	: MoveBy(duration, Point()) |  | ||||||
| { | { | ||||||
| 	end_pos_ = pos; | 	MoveTo::MoveTo(float duration, Point pos) | ||||||
| } | 		: MoveBy(duration, Point()) | ||||||
|  | 	{ | ||||||
|  | 		end_pos_ = pos; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::MoveTo * easy2d::MoveTo::Clone() const | 	MoveTo * MoveTo::Clone() const | ||||||
| { | 	{ | ||||||
| 	return new MoveTo(duration_, end_pos_); | 		return new MoveTo(duration_, end_pos_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::MoveTo::Init() | 	void MoveTo::Init() | ||||||
| { | 	{ | ||||||
| 	MoveBy::Init(); | 		MoveBy::Init(); | ||||||
| 	delta_pos_ = end_pos_ - start_pos_; | 		delta_pos_ = end_pos_ - start_pos_; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -22,38 +22,41 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::OpacityBy::OpacityBy(float duration, float opacity) | namespace easy2d | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| { | { | ||||||
| 	delta_val_ = opacity; | 	OpacityBy::OpacityBy(float duration, float opacity) | ||||||
| } | 		: FiniteTimeAction(duration) | ||||||
| 
 |  | ||||||
| void easy2d::OpacityBy::Init() |  | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		start_val_ = target_->GetOpacity(); | 		delta_val_ = opacity; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::OpacityBy::Update() | 	void OpacityBy::Init() | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		target_->SetOpacity(start_val_ + delta_val_ * delta_); | 		FiniteTimeAction::Init(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			start_val_ = target_->GetOpacity(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::OpacityBy * easy2d::OpacityBy::Clone() const | 	void OpacityBy::Update() | ||||||
| { | 	{ | ||||||
| 	return new OpacityBy(duration_, delta_val_); | 		FiniteTimeAction::Update(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::OpacityBy * easy2d::OpacityBy::Reverse() const | 		if (target_) | ||||||
| { | 		{ | ||||||
| 	return new OpacityBy(duration_, -delta_val_); | 			target_->SetOpacity(start_val_ + delta_val_ * delta_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	OpacityBy * OpacityBy::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		return new OpacityBy(duration_, delta_val_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	OpacityBy * OpacityBy::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new OpacityBy(duration_, -delta_val_); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -22,19 +22,22 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::OpacityTo::OpacityTo(float duration, float opacity) | namespace easy2d | ||||||
| 	: OpacityBy(duration, 0) |  | ||||||
| { | { | ||||||
| 	end_val_ = opacity; | 	OpacityTo::OpacityTo(float duration, float opacity) | ||||||
| } | 		: OpacityBy(duration, 0) | ||||||
|  | 	{ | ||||||
|  | 		end_val_ = opacity; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::OpacityTo * easy2d::OpacityTo::Clone() const | 	OpacityTo * OpacityTo::Clone() const | ||||||
| { | 	{ | ||||||
| 	return new OpacityTo(duration_, end_val_); | 		return new OpacityTo(duration_, end_val_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::OpacityTo::Init() | 	void OpacityTo::Init() | ||||||
| { | 	{ | ||||||
| 	OpacityBy::Init(); | 		OpacityBy::Init(); | ||||||
| 	delta_val_ = end_val_ - start_val_; | 		delta_val_ = end_val_ - start_val_; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -22,38 +22,41 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::RotateBy::RotateBy(float duration, float rotation) | namespace easy2d | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| { | { | ||||||
| 	delta_val_ = rotation; | 	RotateBy::RotateBy(float duration, float rotation) | ||||||
| } | 		: FiniteTimeAction(duration) | ||||||
| 
 |  | ||||||
| void easy2d::RotateBy::Init() |  | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		start_val_ = target_->GetRotation(); | 		delta_val_ = rotation; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::RotateBy::Update() | 	void RotateBy::Init() | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		target_->SetRotation(start_val_ + delta_val_ * delta_); | 		FiniteTimeAction::Init(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			start_val_ = target_->GetRotation(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::RotateBy * easy2d::RotateBy::Clone() const | 	void RotateBy::Update() | ||||||
| { | 	{ | ||||||
| 	return new RotateBy(duration_, delta_val_); | 		FiniteTimeAction::Update(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::RotateBy * easy2d::RotateBy::Reverse() const | 		if (target_) | ||||||
| { | 		{ | ||||||
| 	return new RotateBy(duration_, -delta_val_); | 			target_->SetRotation(start_val_ + delta_val_ * delta_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	RotateBy * RotateBy::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		return new RotateBy(duration_, delta_val_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	RotateBy * RotateBy::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new RotateBy(duration_, -delta_val_); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -22,19 +22,22 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::RotateTo::RotateTo(float duration, float rotation) | namespace easy2d | ||||||
| 	: RotateBy(duration, 0) |  | ||||||
| { | { | ||||||
| 	end_val_ = rotation; | 	RotateTo::RotateTo(float duration, float rotation) | ||||||
| } | 		: RotateBy(duration, 0) | ||||||
|  | 	{ | ||||||
|  | 		end_val_ = rotation; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::RotateTo * easy2d::RotateTo::Clone() const | 	RotateTo * RotateTo::Clone() const | ||||||
| { | 	{ | ||||||
| 	return new RotateTo(duration_, end_val_); | 		return new RotateTo(duration_, end_val_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::RotateTo::Init() | 	void RotateTo::Init() | ||||||
| { | 	{ | ||||||
| 	RotateBy::Init(); | 		RotateBy::Init(); | ||||||
| 	delta_val_ = end_val_ - start_val_; | 		delta_val_ = end_val_ - start_val_; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -22,47 +22,50 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleBy::ScaleBy(float duration, float scale) | namespace easy2d | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| { | { | ||||||
| 	delta_x_ = scale; | 	ScaleBy::ScaleBy(float duration, float scale) | ||||||
| 	delta_y_ = scale; | 		: FiniteTimeAction(duration) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::ScaleBy::ScaleBy(float duration, float scale_x, float scale_y) |  | ||||||
| 	: FiniteTimeAction(duration) |  | ||||||
| { |  | ||||||
| 	delta_x_ = scale_x; |  | ||||||
| 	delta_y_ = scale_y; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::ScaleBy::Init() |  | ||||||
| { |  | ||||||
| 	FiniteTimeAction::Init(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		start_scale_x_ = target_->GetScaleX(); | 		delta_x_ = scale; | ||||||
| 		start_scale_y_ = target_->GetScaleY(); | 		delta_y_ = scale; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::ScaleBy::Update() | 	ScaleBy::ScaleBy(float duration, float scale_x, float scale_y) | ||||||
| { | 		: FiniteTimeAction(duration) | ||||||
| 	FiniteTimeAction::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (target_) |  | ||||||
| 	{ | 	{ | ||||||
| 		target_->SetScale(start_scale_x_ + delta_x_ * delta_, start_scale_y_ + delta_y_ * delta_); | 		delta_x_ = scale_x; | ||||||
|  | 		delta_y_ = scale_y; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleBy * easy2d::ScaleBy::Clone() const | 	void ScaleBy::Init() | ||||||
| { | 	{ | ||||||
| 	return new ScaleBy(duration_, delta_x_, delta_y_); | 		FiniteTimeAction::Init(); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleBy * easy2d::ScaleBy::Reverse() const | 		if (target_) | ||||||
| { | 		{ | ||||||
| 	return new ScaleBy(duration_, -delta_x_, -delta_y_); | 			start_scale_x_ = target_->GetScaleX(); | ||||||
|  | 			start_scale_y_ = target_->GetScaleY(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void ScaleBy::Update() | ||||||
|  | 	{ | ||||||
|  | 		FiniteTimeAction::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			target_->SetScale(start_scale_x_ + delta_x_ * delta_, start_scale_y_ + delta_y_ * delta_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ScaleBy * ScaleBy::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		return new ScaleBy(duration_, delta_x_, delta_y_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ScaleBy * ScaleBy::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		return new ScaleBy(duration_, -delta_x_, -delta_y_); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -21,28 +21,32 @@ | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleTo::ScaleTo(float duration, float scale) |  | ||||||
| 	: ScaleBy(duration, 0, 0) |  | ||||||
| { |  | ||||||
| 	end_scale_x_ = scale; |  | ||||||
| 	end_scale_y_ = scale; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleTo::ScaleTo(float duration, float scale_x, float scale_y) | namespace easy2d | ||||||
| 	: ScaleBy(duration, 0, 0) |  | ||||||
| { | { | ||||||
| 	end_scale_x_ = scale_x; | 	ScaleTo::ScaleTo(float duration, float scale) | ||||||
| 	end_scale_y_ = scale_y; | 		: ScaleBy(duration, 0, 0) | ||||||
| } | 	{ | ||||||
|  | 		end_scale_x_ = scale; | ||||||
|  | 		end_scale_y_ = scale; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::ScaleTo * easy2d::ScaleTo::Clone() const | 	ScaleTo::ScaleTo(float duration, float scale_x, float scale_y) | ||||||
| { | 		: ScaleBy(duration, 0, 0) | ||||||
| 	return new ScaleTo(duration_, end_scale_x_, end_scale_y_); | 	{ | ||||||
| } | 		end_scale_x_ = scale_x; | ||||||
|  | 		end_scale_y_ = scale_y; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::ScaleTo::Init() | 	ScaleTo * ScaleTo::Clone() const | ||||||
| { | 	{ | ||||||
| 	ScaleBy::Init(); | 		return new ScaleTo(duration_, end_scale_x_, end_scale_y_); | ||||||
| 	delta_x_ = end_scale_x_ - start_scale_x_; | 	} | ||||||
| 	delta_y_ = end_scale_y_ - start_scale_y_; | 
 | ||||||
| } | 	void ScaleTo::Init() | ||||||
|  | 	{ | ||||||
|  | 		ScaleBy::Init(); | ||||||
|  | 		delta_x_ = end_scale_x_ - start_scale_x_; | ||||||
|  | 		delta_y_ = end_scale_y_ - start_scale_y_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,120 +20,124 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Sequence::Sequence() |  | ||||||
| 	: action_index_(0) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Sequence::Sequence(const Actions& actions) | namespace easy2d | ||||||
| 	: action_index_(0) |  | ||||||
| { | { | ||||||
| 	this->Add(actions); | 	Sequence::Sequence() | ||||||
| } | 		: action_index_(0) | ||||||
| 
 |  | ||||||
| easy2d::Sequence::~Sequence() |  | ||||||
| { |  | ||||||
| 	for (auto action : actions_) |  | ||||||
| 	{ | 	{ | ||||||
| 		SafeRelease(action); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Sequence::Init() | 	Sequence::Sequence(const Actions& actions) | ||||||
| { | 		: action_index_(0) | ||||||
| 	Action::Init(); | 	{ | ||||||
| 	// 将所有动作与目标绑定
 | 		this->Add(actions); | ||||||
| 	if (target_) | 	} | ||||||
|  | 
 | ||||||
|  | 	Sequence::~Sequence() | ||||||
|  | 	{ | ||||||
|  | 		for (auto action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			SafeRelease(action); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Sequence::Init() | ||||||
|  | 	{ | ||||||
|  | 		Action::Init(); | ||||||
|  | 		// 将所有动作与目标绑定
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			for (const auto& action : actions_) | ||||||
|  | 			{ | ||||||
|  | 				action->target_ = target_; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// 初始化第一个动作
 | ||||||
|  | 		actions_[0]->Init(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Sequence::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		auto &action = actions_[action_index_]; | ||||||
|  | 		action->Update(); | ||||||
|  | 
 | ||||||
|  | 		if (action->IsDone()) | ||||||
|  | 		{ | ||||||
|  | 			++action_index_; | ||||||
|  | 			if (action_index_ == actions_.size()) | ||||||
|  | 			{ | ||||||
|  | 				this->Stop(); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				actions_[action_index_]->Init(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Sequence::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 		for (const auto& action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			action->Reset(); | ||||||
|  | 		} | ||||||
|  | 		action_index_ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Sequence::ResetTime() | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& action : actions_) | 		for (const auto& action : actions_) | ||||||
| 		{ | 		{ | ||||||
| 			action->target_ = target_; | 			action->ResetTime(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// 初始化第一个动作
 |  | ||||||
| 	actions_[0]->Init(); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Sequence::Update() | 	void Sequence::Add(Action * action) | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	auto &action = actions_[action_index_]; |  | ||||||
| 	action->Update(); |  | ||||||
| 
 |  | ||||||
| 	if (action->IsDone()) |  | ||||||
| 	{ |  | ||||||
| 		++action_index_; |  | ||||||
| 		if (action_index_ == actions_.size()) |  | ||||||
| 		{ |  | ||||||
| 			this->Stop(); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			actions_[action_index_]->Init(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sequence::Reset() |  | ||||||
| { |  | ||||||
| 	Action::Reset(); |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ |  | ||||||
| 		action->Reset(); |  | ||||||
| 	} |  | ||||||
| 	action_index_ = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sequence::ResetTime() |  | ||||||
| { |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ |  | ||||||
| 		action->ResetTime(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sequence::Add(Action * action) |  | ||||||
| { |  | ||||||
| 	if (action) |  | ||||||
| 	{ |  | ||||||
| 		actions_.push_back(action); |  | ||||||
| 		action->Retain(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sequence::Add(const Actions& actions) |  | ||||||
| { |  | ||||||
| 	for (const auto &action : actions) |  | ||||||
| 	{ |  | ||||||
| 		this->Add(action); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sequence * easy2d::Sequence::Clone() const |  | ||||||
| { |  | ||||||
| 	auto sequence = new Sequence(); |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (action) | 		if (action) | ||||||
| 		{ | 		{ | ||||||
| 			sequence->Add(action->Clone()); | 			actions_.push_back(action); | ||||||
|  | 			action->Retain(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return sequence; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Sequence * easy2d::Sequence::Reverse() const | 	void Sequence::Add(const Actions& actions) | ||||||
| { |  | ||||||
| 	auto sequence = new Sequence(); |  | ||||||
| 	if (sequence && !actions_.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		std::vector<Action*> newActions(actions_.size()); | 		for (const auto &action : actions) | ||||||
| 		for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) |  | ||||||
| 		{ | 		{ | ||||||
| 			newActions.push_back((*iter)->Reverse()); | 			this->Add(action); | ||||||
| 		} | 		} | ||||||
| 		sequence->Add(newActions); |  | ||||||
| 	} | 	} | ||||||
| 	return sequence; | 
 | ||||||
|  | 	Sequence * Sequence::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		auto sequence = new Sequence(); | ||||||
|  | 		for (const auto& action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			if (action) | ||||||
|  | 			{ | ||||||
|  | 				sequence->Add(action->Clone()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return sequence; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sequence * Sequence::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		auto sequence = new Sequence(); | ||||||
|  | 		if (sequence && !actions_.empty()) | ||||||
|  | 		{ | ||||||
|  | 			std::vector<Action*> newActions(actions_.size()); | ||||||
|  | 			for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) | ||||||
|  | 			{ | ||||||
|  | 				newActions.push_back((*iter)->Reverse()); | ||||||
|  | 			} | ||||||
|  | 			sequence->Add(newActions); | ||||||
|  | 		} | ||||||
|  | 		return sequence; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -20,118 +20,122 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2daction.h" | #include "..\e2daction.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Spawn::Spawn() |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Spawn::Spawn(const Actions& actions) | namespace easy2d | ||||||
| { | { | ||||||
| 	this->Add(actions); | 	Spawn::Spawn() | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Spawn::~Spawn() |  | ||||||
| { |  | ||||||
| 	for (auto action : actions_) |  | ||||||
| 	{ | 	{ | ||||||
| 		SafeRelease(action); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Spawn::Init() | 	Spawn::Spawn(const Actions& actions) | ||||||
| { | 	{ | ||||||
| 	Action::Init(); | 		this->Add(actions); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (target_) | 	Spawn::~Spawn() | ||||||
|  | 	{ | ||||||
|  | 		for (auto action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			SafeRelease(action); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Spawn::Init() | ||||||
|  | 	{ | ||||||
|  | 		Action::Init(); | ||||||
|  | 
 | ||||||
|  | 		if (target_) | ||||||
|  | 		{ | ||||||
|  | 			for (const auto& action : actions_) | ||||||
|  | 			{ | ||||||
|  | 				action->target_ = target_; | ||||||
|  | 				action->Init(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Spawn::Update() | ||||||
|  | 	{ | ||||||
|  | 		Action::Update(); | ||||||
|  | 
 | ||||||
|  | 		size_t done_num = 0; | ||||||
|  | 		for (const auto& action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			if (action->IsDone()) | ||||||
|  | 			{ | ||||||
|  | 				++done_num; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				action->Update(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (done_num == actions_.size()) | ||||||
|  | 		{ | ||||||
|  | 			this->Stop(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Spawn::Reset() | ||||||
|  | 	{ | ||||||
|  | 		Action::Reset(); | ||||||
|  | 		for (const auto& action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			action->Reset(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Spawn::ResetTime() | ||||||
| 	{ | 	{ | ||||||
| 		for (const auto& action : actions_) | 		for (const auto& action : actions_) | ||||||
| 		{ | 		{ | ||||||
| 			action->target_ = target_; | 			action->ResetTime(); | ||||||
| 			action->Init(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Spawn::Update() |  | ||||||
| { |  | ||||||
| 	Action::Update(); |  | ||||||
| 
 |  | ||||||
| 	size_t done_num = 0; |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ |  | ||||||
| 		if (action->IsDone()) |  | ||||||
| 		{ |  | ||||||
| 			++done_num; |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			action->Update(); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (done_num == actions_.size()) | 	void Spawn::Add(Action * action) | ||||||
| 	{ |  | ||||||
| 		this->Stop(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Spawn::Reset() |  | ||||||
| { |  | ||||||
| 	Action::Reset(); |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ |  | ||||||
| 		action->Reset(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Spawn::ResetTime() |  | ||||||
| { |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ |  | ||||||
| 		action->ResetTime(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Spawn::Add(Action * action) |  | ||||||
| { |  | ||||||
| 	if (action) |  | ||||||
| 	{ |  | ||||||
| 		actions_.push_back(action); |  | ||||||
| 		action->Retain(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Spawn::Add(const Actions& actions) |  | ||||||
| { |  | ||||||
| 	for (const auto &action : actions) |  | ||||||
| 	{ |  | ||||||
| 		this->Add(action); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Spawn * easy2d::Spawn::Clone() const |  | ||||||
| { |  | ||||||
| 	auto spawn = new Spawn(); |  | ||||||
| 	for (const auto& action : actions_) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (action) | 		if (action) | ||||||
| 		{ | 		{ | ||||||
| 			spawn->Add(action->Clone()); | 			actions_.push_back(action); | ||||||
|  | 			action->Retain(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return spawn; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Spawn * easy2d::Spawn::Reverse() const | 	void Spawn::Add(const Actions& actions) | ||||||
| { |  | ||||||
| 	auto spawn = new Spawn(); |  | ||||||
| 	if (spawn && !actions_.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		std::vector<Action*> newActions(actions_.size()); | 		for (const auto &action : actions) | ||||||
| 		for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) |  | ||||||
| 		{ | 		{ | ||||||
| 			newActions.push_back((*iter)->Reverse()); | 			this->Add(action); | ||||||
| 		} | 		} | ||||||
| 		spawn->Add(newActions); |  | ||||||
| 	} | 	} | ||||||
| 	return spawn; | 
 | ||||||
|  | 	Spawn * Spawn::Clone() const | ||||||
|  | 	{ | ||||||
|  | 		auto spawn = new Spawn(); | ||||||
|  | 		for (const auto& action : actions_) | ||||||
|  | 		{ | ||||||
|  | 			if (action) | ||||||
|  | 			{ | ||||||
|  | 				spawn->Add(action->Clone()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return spawn; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Spawn * Spawn::Reverse() const | ||||||
|  | 	{ | ||||||
|  | 		auto spawn = new Spawn(); | ||||||
|  | 		if (spawn && !actions_.empty()) | ||||||
|  | 		{ | ||||||
|  | 			std::vector<Action*> newActions(actions_.size()); | ||||||
|  | 			for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) | ||||||
|  | 			{ | ||||||
|  | 				newActions.push_back((*iter)->Reverse()); | ||||||
|  | 			} | ||||||
|  | 			spawn->Add(newActions); | ||||||
|  | 		} | ||||||
|  | 		return spawn; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -37,246 +37,249 @@ | ||||||
| 	}															\ | 	}															\ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Button::Button() | namespace easy2d | ||||||
| 	: callback_(nullptr) |  | ||||||
| 	, status_(Status::Normal) |  | ||||||
| 	, enabled_(true) |  | ||||||
| 	, is_selected_(false) |  | ||||||
| 	, normal_(nullptr) |  | ||||||
| 	, mouseover_(nullptr) |  | ||||||
| 	, selected_(nullptr) |  | ||||||
| 	, disabled_(nullptr) |  | ||||||
| { | { | ||||||
| } | 	Button::Button() | ||||||
| 
 | 		: callback_(nullptr) | ||||||
| easy2d::Button::Button(Node * normal, const Callback& func) | 		, status_(Status::Normal) | ||||||
| 	: callback_(nullptr) | 		, enabled_(true) | ||||||
| 	, status_(Status::Normal) | 		, is_selected_(false) | ||||||
| 	, enabled_(true) | 		, normal_(nullptr) | ||||||
| 	, is_selected_(false) | 		, mouseover_(nullptr) | ||||||
| 	, normal_(nullptr) | 		, selected_(nullptr) | ||||||
| 	, mouseover_(nullptr) | 		, disabled_(nullptr) | ||||||
| 	, selected_(nullptr) |  | ||||||
| 	, disabled_(nullptr) |  | ||||||
| { |  | ||||||
| 	this->SetNormal(normal); |  | ||||||
| 	this->SetCallbackOnClick(func); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Button::Button(Node * normal, Node * selected, const Callback& func) |  | ||||||
| 	: callback_(nullptr) |  | ||||||
| 	, status_(Status::Normal) |  | ||||||
| 	, enabled_(true) |  | ||||||
| 	, is_selected_(false) |  | ||||||
| 	, normal_(nullptr) |  | ||||||
| 	, mouseover_(nullptr) |  | ||||||
| 	, selected_(nullptr) |  | ||||||
| 	, disabled_(nullptr) |  | ||||||
| { |  | ||||||
| 	this->SetNormal(normal); |  | ||||||
| 	this->SetSelected(selected); |  | ||||||
| 	this->SetCallbackOnClick(func); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Button::Button(Node * normal, Node * mouseover, Node * selected, const Callback& func) |  | ||||||
| 	: callback_(nullptr) |  | ||||||
| 	, status_(Status::Normal) |  | ||||||
| 	, enabled_(true) |  | ||||||
| 	, is_selected_(false) |  | ||||||
| 	, normal_(nullptr) |  | ||||||
| 	, mouseover_(nullptr) |  | ||||||
| 	, selected_(nullptr) |  | ||||||
| 	, disabled_(nullptr) |  | ||||||
| { |  | ||||||
| 	this->SetNormal(normal); |  | ||||||
| 	this->SetMouseOver(mouseover); |  | ||||||
| 	this->SetSelected(selected); |  | ||||||
| 	this->SetCallbackOnClick(func); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Button::Button(Node * normal, Node * mouseover, Node * selected, Node * disabled, const Callback& func) |  | ||||||
| 	: callback_(nullptr) |  | ||||||
| 	, status_(Status::Normal) |  | ||||||
| 	, enabled_(true) |  | ||||||
| 	, is_selected_(false) |  | ||||||
| 	, normal_(nullptr) |  | ||||||
| 	, mouseover_(nullptr) |  | ||||||
| 	, selected_(nullptr) |  | ||||||
| 	, disabled_(nullptr) |  | ||||||
| { |  | ||||||
| 	this->SetNormal(normal); |  | ||||||
| 	this->SetMouseOver(mouseover); |  | ||||||
| 	this->SetSelected(selected); |  | ||||||
| 	this->SetDisabled(disabled); |  | ||||||
| 	this->SetCallbackOnClick(func); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Button::IsEnable() const |  | ||||||
| { |  | ||||||
| 	return enabled_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Button::SetNormal(Node * normal) |  | ||||||
| { |  | ||||||
| 	SET_BUTTON_NODE(normal_, normal); |  | ||||||
| 	if (normal) |  | ||||||
| 	{ | 	{ | ||||||
| 		this->SetSize(normal->GetWidth(), normal->GetHeight()); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Button::SetMouseOver(Node * mouseover) | 	Button::Button(Node * normal, const Callback& func) | ||||||
| { | 		: callback_(nullptr) | ||||||
| 	SET_BUTTON_NODE(mouseover_, mouseover); | 		, status_(Status::Normal) | ||||||
| } | 		, enabled_(true) | ||||||
| 
 | 		, is_selected_(false) | ||||||
| void easy2d::Button::SetSelected(Node * selected) | 		, normal_(nullptr) | ||||||
| { | 		, mouseover_(nullptr) | ||||||
| 	SET_BUTTON_NODE(selected_, selected); | 		, selected_(nullptr) | ||||||
| } | 		, disabled_(nullptr) | ||||||
| 
 |  | ||||||
| void easy2d::Button::SetDisabled(Node * disabled) |  | ||||||
| { |  | ||||||
| 	SET_BUTTON_NODE(disabled_, disabled); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Button::SetEnabled(bool enabled) |  | ||||||
| { |  | ||||||
| 	if (enabled_ != enabled) |  | ||||||
| 	{ | 	{ | ||||||
| 		enabled_ = enabled; | 		this->SetNormal(normal); | ||||||
| 		UpdateVisible(); | 		this->SetCallbackOnClick(func); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Button::SetCallbackOnClick(const Callback& func) | 	Button::Button(Node * normal, Node * selected, const Callback& func) | ||||||
| { | 		: callback_(nullptr) | ||||||
| 	callback_ = func; | 		, status_(Status::Normal) | ||||||
| } | 		, enabled_(true) | ||||||
| 
 | 		, is_selected_(false) | ||||||
| void easy2d::Button::SetPivot(float pivot_x, float pivot_y) | 		, normal_(nullptr) | ||||||
| { | 		, mouseover_(nullptr) | ||||||
| 	Node::SetPivot(pivot_x, pivot_y); | 		, selected_(nullptr) | ||||||
| 	SAFE_SET(normal_, SetPivot, pivot_x, pivot_y); | 		, disabled_(nullptr) | ||||||
| 	SAFE_SET(mouseover_, SetPivot, pivot_x, pivot_y); |  | ||||||
| 	SAFE_SET(selected_, SetPivot, pivot_x, pivot_y); |  | ||||||
| 	SAFE_SET(disabled_, SetPivot, pivot_x, pivot_y); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Button::Dispatch(const MouseEvent & e, bool handled) |  | ||||||
| { |  | ||||||
| 	if (!handled && enabled_ && IsVisible() && normal_) |  | ||||||
| 	{ | 	{ | ||||||
| 		bool contains = normal_->ContainsPoint(e.GetPosition()); | 		this->SetNormal(normal); | ||||||
| 		if (e.GetType() == MouseEvent::Type::LeftUp && is_selected_ && contains) | 		this->SetSelected(selected); | ||||||
|  | 		this->SetCallbackOnClick(func); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Button::Button(Node * normal, Node * mouseover, Node * selected, const Callback& func) | ||||||
|  | 		: callback_(nullptr) | ||||||
|  | 		, status_(Status::Normal) | ||||||
|  | 		, enabled_(true) | ||||||
|  | 		, is_selected_(false) | ||||||
|  | 		, normal_(nullptr) | ||||||
|  | 		, mouseover_(nullptr) | ||||||
|  | 		, selected_(nullptr) | ||||||
|  | 		, disabled_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		this->SetNormal(normal); | ||||||
|  | 		this->SetMouseOver(mouseover); | ||||||
|  | 		this->SetSelected(selected); | ||||||
|  | 		this->SetCallbackOnClick(func); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Button::Button(Node * normal, Node * mouseover, Node * selected, Node * disabled, const Callback& func) | ||||||
|  | 		: callback_(nullptr) | ||||||
|  | 		, status_(Status::Normal) | ||||||
|  | 		, enabled_(true) | ||||||
|  | 		, is_selected_(false) | ||||||
|  | 		, normal_(nullptr) | ||||||
|  | 		, mouseover_(nullptr) | ||||||
|  | 		, selected_(nullptr) | ||||||
|  | 		, disabled_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		this->SetNormal(normal); | ||||||
|  | 		this->SetMouseOver(mouseover); | ||||||
|  | 		this->SetSelected(selected); | ||||||
|  | 		this->SetDisabled(disabled); | ||||||
|  | 		this->SetCallbackOnClick(func); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Button::IsEnable() const | ||||||
|  | 	{ | ||||||
|  | 		return enabled_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetNormal(Node * normal) | ||||||
|  | 	{ | ||||||
|  | 		SET_BUTTON_NODE(normal_, normal); | ||||||
|  | 		if (normal) | ||||||
| 		{ | 		{ | ||||||
| 			if (callback_) | 			this->SetSize(normal->GetWidth(), normal->GetHeight()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetMouseOver(Node * mouseover) | ||||||
|  | 	{ | ||||||
|  | 		SET_BUTTON_NODE(mouseover_, mouseover); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetSelected(Node * selected) | ||||||
|  | 	{ | ||||||
|  | 		SET_BUTTON_NODE(selected_, selected); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetDisabled(Node * disabled) | ||||||
|  | 	{ | ||||||
|  | 		SET_BUTTON_NODE(disabled_, disabled); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetEnabled(bool enabled) | ||||||
|  | 	{ | ||||||
|  | 		if (enabled_ != enabled) | ||||||
|  | 		{ | ||||||
|  | 			enabled_ = enabled; | ||||||
|  | 			UpdateVisible(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetCallbackOnClick(const Callback& func) | ||||||
|  | 	{ | ||||||
|  | 		callback_ = func; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::SetPivot(float pivot_x, float pivot_y) | ||||||
|  | 	{ | ||||||
|  | 		Node::SetPivot(pivot_x, pivot_y); | ||||||
|  | 		SAFE_SET(normal_, SetPivot, pivot_x, pivot_y); | ||||||
|  | 		SAFE_SET(mouseover_, SetPivot, pivot_x, pivot_y); | ||||||
|  | 		SAFE_SET(selected_, SetPivot, pivot_x, pivot_y); | ||||||
|  | 		SAFE_SET(disabled_, SetPivot, pivot_x, pivot_y); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Button::Dispatch(const MouseEvent & e, bool handled) | ||||||
|  | 	{ | ||||||
|  | 		if (!handled && enabled_ && IsVisible() && normal_) | ||||||
|  | 		{ | ||||||
|  | 			bool contains = normal_->ContainsPoint(e.GetPosition()); | ||||||
|  | 			if (e.GetType() == MouseEvent::Type::LeftUp && is_selected_ && contains) | ||||||
| 			{ | 			{ | ||||||
| 				callback_(); | 				if (callback_) | ||||||
| 			} | 				{ | ||||||
| 			is_selected_ = false; | 					callback_(); | ||||||
| 			SetStatus(Status::Normal); | 				} | ||||||
| 			return true; | 				is_selected_ = false; | ||||||
| 		} | 				SetStatus(Status::Normal); | ||||||
| 		else if (e.GetType() == MouseEvent::Type::LeftDown) |  | ||||||
| 		{ |  | ||||||
| 			is_selected_ = contains; |  | ||||||
| 			SetStatus(contains ? Status::Selected : Status::Normal); |  | ||||||
| 			 |  | ||||||
| 			if (contains) |  | ||||||
| 				return true; | 				return true; | ||||||
| 		} | 			} | ||||||
| 		else if (e.GetType() == MouseEvent::Type::LeftUp) | 			else if (e.GetType() == MouseEvent::Type::LeftDown) | ||||||
| 		{ | 			{ | ||||||
| 			is_selected_ = false; | 				is_selected_ = contains; | ||||||
| 		} | 				SetStatus(contains ? Status::Selected : Status::Normal); | ||||||
| 		else if (e.GetType() == MouseEvent::Type::MoveBy && is_selected_ && contains) | 
 | ||||||
| 		{ | 				if (contains) | ||||||
| 			SetStatus(Status::Selected); | 					return true; | ||||||
| 			return true; | 			} | ||||||
| 		} | 			else if (e.GetType() == MouseEvent::Type::LeftUp) | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			if (!e.IsLButtonDown() && is_selected_) |  | ||||||
| 			{ | 			{ | ||||||
| 				is_selected_ = false; | 				is_selected_ = false; | ||||||
| 			} | 			} | ||||||
| 
 | 			else if (e.GetType() == MouseEvent::Type::MoveBy && is_selected_ && contains) | ||||||
| 			SetStatus(contains ? Status::Mouseover : Status::Normal); | 			{ | ||||||
| 
 | 				SetStatus(Status::Selected); | ||||||
| 			if (contains) |  | ||||||
| 				return true; | 				return true; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (!e.IsLButtonDown() && is_selected_) | ||||||
|  | 				{ | ||||||
|  | 					is_selected_ = false; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				SetStatus(contains ? Status::Mouseover : Status::Normal); | ||||||
|  | 
 | ||||||
|  | 				if (contains) | ||||||
|  | 					return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return Node::Dispatch(e, handled); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Button::Visit() | ||||||
|  | 	{ | ||||||
|  | 		Node::Visit(); | ||||||
|  | 
 | ||||||
|  | 		if (IsVisible() && | ||||||
|  | 			!enabled_ && | ||||||
|  | 			normal_ && | ||||||
|  | 			normal_->ContainsPoint(Device::GetInput()->GetMousePos())) | ||||||
|  | 		{ | ||||||
|  | 			HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | ||||||
|  | 			if (hcursor) | ||||||
|  | 			{ | ||||||
|  | 				::SetCursor(hcursor); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (status_ == Status::Mouseover || status_ == Status::Selected) | ||||||
|  | 		{ | ||||||
|  | 			HCURSOR hcursor = ::LoadCursor(nullptr, IDC_HAND); | ||||||
|  | 			if (hcursor) | ||||||
|  | 			{ | ||||||
|  | 				::SetCursor(hcursor); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return Node::Dispatch(e, handled); | 	void Button::SetStatus(Status status) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Button::Visit() |  | ||||||
| { |  | ||||||
| 	Node::Visit(); |  | ||||||
| 
 |  | ||||||
| 	if (IsVisible() && |  | ||||||
| 		!enabled_ && |  | ||||||
| 		normal_ && |  | ||||||
| 		normal_->ContainsPoint(Device::GetInput()->GetMousePos())) |  | ||||||
| 	{ | 	{ | ||||||
| 		HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | 		if (status_ != status) | ||||||
| 		if (hcursor) |  | ||||||
| 		{ | 		{ | ||||||
| 			::SetCursor(hcursor); | 			status_ = status; | ||||||
|  | 			UpdateVisible(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if (status_ == Status::Mouseover || status_ == Status::Selected) |  | ||||||
| 	{ |  | ||||||
| 		HCURSOR hcursor = ::LoadCursor(nullptr, IDC_HAND); |  | ||||||
| 		if (hcursor) |  | ||||||
| 		{ |  | ||||||
| 			::SetCursor(hcursor); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Button::SetStatus(Status status) | 	void Button::UpdateVisible() | ||||||
| { |  | ||||||
| 	if (status_ != status) |  | ||||||
| 	{ | 	{ | ||||||
| 		status_ = status; | 		SAFE_SET(normal_, SetVisible, false); | ||||||
| 		UpdateVisible(); | 		SAFE_SET(mouseover_, SetVisible, false); | ||||||
| 	} | 		SAFE_SET(selected_, SetVisible, false); | ||||||
| } | 		SAFE_SET(disabled_, SetVisible, false); | ||||||
| 
 | 
 | ||||||
| void easy2d::Button::UpdateVisible() | 		if (enabled_) | ||||||
| { |  | ||||||
| 	SAFE_SET(normal_, SetVisible, false); |  | ||||||
| 	SAFE_SET(mouseover_, SetVisible, false); |  | ||||||
| 	SAFE_SET(selected_, SetVisible, false); |  | ||||||
| 	SAFE_SET(disabled_, SetVisible, false); |  | ||||||
| 
 |  | ||||||
| 	if (enabled_) |  | ||||||
| 	{ |  | ||||||
| 		if (status_ == Status::Selected && selected_) |  | ||||||
| 		{ | 		{ | ||||||
| 			selected_->SetVisible(true); | 			if (status_ == Status::Selected && selected_) | ||||||
| 		} | 			{ | ||||||
| 		else if (status_ == Status::Mouseover && mouseover_) | 				selected_->SetVisible(true); | ||||||
| 		{ | 			} | ||||||
| 			mouseover_->SetVisible(true); | 			else if (status_ == Status::Mouseover && mouseover_) | ||||||
|  | 			{ | ||||||
|  | 				mouseover_->SetVisible(true); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (normal_) normal_->SetVisible(true); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			if (normal_) normal_->SetVisible(true); | 			if (disabled_) | ||||||
|  | 			{ | ||||||
|  | 				disabled_->SetVisible(true); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (normal_) normal_->SetVisible(true); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | } | ||||||
| 	{ |  | ||||||
| 		if (disabled_) |  | ||||||
| 		{ |  | ||||||
| 			disabled_->SetVisible(true); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			if (normal_) normal_->SetVisible(true); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -20,77 +20,81 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dcomponent.h" | #include "..\e2dcomponent.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Menu::Menu() |  | ||||||
| 	: enabled_(true) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Menu::Menu(const std::vector<Button*>& buttons) | namespace easy2d | ||||||
| 	: enabled_(true) |  | ||||||
| { | { | ||||||
| 	for (const auto& button : buttons) | 	Menu::Menu() | ||||||
|  | 		: enabled_(true) | ||||||
| 	{ | 	{ | ||||||
| 		this->AddButton(button); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Menu::IsEnable() const | 	Menu::Menu(const std::vector<Button*>& buttons) | ||||||
| { | 		: enabled_(true) | ||||||
| 	return enabled_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t easy2d::Menu::GetButtonCount() const |  | ||||||
| { |  | ||||||
| 	return buttons_.size(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Menu::SetEnabled(bool enabled) |  | ||||||
| { |  | ||||||
| 	if (enabled_ != enabled) |  | ||||||
| 	{ | 	{ | ||||||
| 		enabled_ = enabled; | 		for (const auto& button : buttons) | ||||||
| 
 |  | ||||||
| 		for (const auto& button : buttons_) |  | ||||||
| 		{ | 		{ | ||||||
| 			button->SetEnabled(enabled); | 			this->AddButton(button); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Menu::AddButton(Button * button) | 	bool Menu::IsEnable() const | ||||||
| { |  | ||||||
| 	if (button) |  | ||||||
| 	{ | 	{ | ||||||
| 		this->AddChild(button); | 		return enabled_; | ||||||
| 		buttons_.push_back(button); |  | ||||||
| 		button->SetEnabled(enabled_); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Menu::RemoveButton(Button * button) | 	size_t Menu::GetButtonCount() const | ||||||
| { |  | ||||||
| 	if (buttons_.empty()) |  | ||||||
| 	{ | 	{ | ||||||
|  | 		return buttons_.size(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Menu::SetEnabled(bool enabled) | ||||||
|  | 	{ | ||||||
|  | 		if (enabled_ != enabled) | ||||||
|  | 		{ | ||||||
|  | 			enabled_ = enabled; | ||||||
|  | 
 | ||||||
|  | 			for (const auto& button : buttons_) | ||||||
|  | 			{ | ||||||
|  | 				button->SetEnabled(enabled); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Menu::AddButton(Button * button) | ||||||
|  | 	{ | ||||||
|  | 		if (button) | ||||||
|  | 		{ | ||||||
|  | 			this->AddChild(button); | ||||||
|  | 			buttons_.push_back(button); | ||||||
|  | 			button->SetEnabled(enabled_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Menu::RemoveButton(Button * button) | ||||||
|  | 	{ | ||||||
|  | 		if (buttons_.empty()) | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		this->RemoveChild(button); | ||||||
|  | 
 | ||||||
|  | 		if (button) | ||||||
|  | 		{ | ||||||
|  | 			auto iter = std::find(buttons_.begin(), buttons_.end(), button); | ||||||
|  | 			if (iter != buttons_.end()) | ||||||
|  | 			{ | ||||||
|  | 				// ÒÆ³ý°´Å¥Ç°£¬½«ËüÆôÓÃ
 | ||||||
|  | 				button->SetEnabled(true); | ||||||
|  | 				buttons_.erase(iter); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	this->RemoveChild(button); | 	const std::vector<Button*>& Menu::GetAllButtons() const | ||||||
| 
 |  | ||||||
| 	if (button) |  | ||||||
| 	{ | 	{ | ||||||
| 		auto iter = std::find(buttons_.begin(), buttons_.end(), button); | 		return buttons_; | ||||||
| 		if (iter != buttons_.end()) |  | ||||||
| 		{ |  | ||||||
| 			// ÒÆ³ý°´Å¥Ç°£¬½«ËüÆôÓÃ
 |  | ||||||
| 			button->SetEnabled(true); |  | ||||||
| 			buttons_.erase(iter); |  | ||||||
| 			return true; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return false; | } | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const std::vector<easy2d::Button*>& easy2d::Menu::GetAllButtons() const |  | ||||||
| { |  | ||||||
| 	return buttons_; |  | ||||||
| } |  | ||||||
|  | @ -61,7 +61,7 @@ namespace easy2d | ||||||
| 		Point operator - () const; | 		Point operator - () const; | ||||||
| 		bool operator== (const Point& other) const; | 		bool operator== (const Point& other) const; | ||||||
| 
 | 
 | ||||||
| 		explicit operator easy2d::Size() const; | 		explicit operator Size() const; | ||||||
| 
 | 
 | ||||||
| 		// 判断两点间距离
 | 		// 判断两点间距离
 | ||||||
| 		static float Distance( | 		static float Distance( | ||||||
|  | @ -102,7 +102,7 @@ namespace easy2d | ||||||
| 		Size operator - () const; | 		Size operator - () const; | ||||||
| 		bool operator== (const Size& other) const; | 		bool operator== (const Size& other) const; | ||||||
| 
 | 
 | ||||||
| 		explicit operator easy2d::Point() const; | 		explicit operator Point() const; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -585,19 +585,19 @@ namespace easy2d | ||||||
| 		template<typename T> | 		template<typename T> | ||||||
| 		static inline T Range(T min, T max) | 		static inline T Range(T min, T max) | ||||||
| 		{ | 		{ | ||||||
| 			return easy2d::Random::RandomInt(min, max); | 			return Random::RandomInt(min, max); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// 取得范围内的一个浮点数随机数
 | 		// 取得范围内的一个浮点数随机数
 | ||||||
| 		static inline float Range(float min, float max) | 		static inline float Range(float min, float max) | ||||||
| 		{ | 		{ | ||||||
| 			return easy2d::Random::RandomReal(min, max); | 			return Random::RandomReal(min, max); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// 取得范围内的一个浮点数随机数
 | 		// 取得范围内的一个浮点数随机数
 | ||||||
| 		static inline double Range(double min, double max) | 		static inline double Range(double min, double max) | ||||||
| 		{ | 		{ | ||||||
| 			return easy2d::Random::RandomReal(min, max); | 			return Random::RandomReal(min, max); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
|  |  | ||||||
|  | @ -21,80 +21,83 @@ | ||||||
| #include "..\e2devent.h" | #include "..\e2devent.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param) | namespace easy2d | ||||||
| 	: message_(message) |  | ||||||
| 	, w_param_(w_param) |  | ||||||
| 	, l_param_(l_param) |  | ||||||
| { | { | ||||||
| } | 	KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param) | ||||||
| 
 | 		: message_(message) | ||||||
| easy2d::KeyCode easy2d::KeyEvent::GetCode() const | 		, w_param_(w_param) | ||||||
| { | 		, l_param_(l_param) | ||||||
| 	switch (w_param_) |  | ||||||
| 	{ | 	{ | ||||||
| 	case 'A': return KeyCode::A; |  | ||||||
| 	case 'B': return KeyCode::B; |  | ||||||
| 	case 'C': return KeyCode::C; |  | ||||||
| 	case 'D': return KeyCode::D; |  | ||||||
| 	case 'E': return KeyCode::E; |  | ||||||
| 	case 'F': return KeyCode::F; |  | ||||||
| 	case 'G': return KeyCode::G; |  | ||||||
| 	case 'H': return KeyCode::H; |  | ||||||
| 	case 'I': return KeyCode::I; |  | ||||||
| 	case 'J': return KeyCode::J; |  | ||||||
| 	case 'K': return KeyCode::K; |  | ||||||
| 	case 'L': return KeyCode::L; |  | ||||||
| 	case 'M': return KeyCode::M; |  | ||||||
| 	case 'N': return KeyCode::N; |  | ||||||
| 	case 'O': return KeyCode::O; |  | ||||||
| 	case 'P': return KeyCode::P; |  | ||||||
| 	case 'Q': return KeyCode::Q; |  | ||||||
| 	case 'R': return KeyCode::R; |  | ||||||
| 	case 'S': return KeyCode::S; |  | ||||||
| 	case 'T': return KeyCode::T; |  | ||||||
| 	case 'U': return KeyCode::U; |  | ||||||
| 	case 'V': return KeyCode::V; |  | ||||||
| 	case 'W': return KeyCode::W; |  | ||||||
| 	case 'X': return KeyCode::X; |  | ||||||
| 	case 'Y': return KeyCode::Y; |  | ||||||
| 	case 'Z': return KeyCode::Z; |  | ||||||
| 	case '0': return KeyCode::Num0; |  | ||||||
| 	case '1': return KeyCode::Num1; |  | ||||||
| 	case '2': return KeyCode::Num2; |  | ||||||
| 	case '3': return KeyCode::Num3; |  | ||||||
| 	case '4': return KeyCode::Num4; |  | ||||||
| 	case '5': return KeyCode::Num5; |  | ||||||
| 	case '6': return KeyCode::Num6; |  | ||||||
| 	case '7': return KeyCode::Num7; |  | ||||||
| 	case '8': return KeyCode::Num8; |  | ||||||
| 	case '9': return KeyCode::Num9; |  | ||||||
| 	case VK_NUMPAD0: return KeyCode::Numpad0; |  | ||||||
| 	case VK_NUMPAD1: return KeyCode::Numpad1; |  | ||||||
| 	case VK_NUMPAD2: return KeyCode::Numpad2; |  | ||||||
| 	case VK_NUMPAD3: return KeyCode::Numpad3; |  | ||||||
| 	case VK_NUMPAD4: return KeyCode::Numpad4; |  | ||||||
| 	case VK_NUMPAD5: return KeyCode::Numpad5; |  | ||||||
| 	case VK_NUMPAD6: return KeyCode::Numpad6; |  | ||||||
| 	case VK_NUMPAD7: return KeyCode::Numpad7; |  | ||||||
| 	case VK_NUMPAD8: return KeyCode::Numpad8; |  | ||||||
| 	case VK_NUMPAD9: return KeyCode::Numpad9; |  | ||||||
| 	case VK_UP: return KeyCode::Up; |  | ||||||
| 	case VK_DOWN: return KeyCode::Down; |  | ||||||
| 	case VK_LEFT: return KeyCode::Left; |  | ||||||
| 	case VK_RIGHT: return KeyCode::Right; |  | ||||||
| 	case VK_RETURN: return KeyCode::Enter; |  | ||||||
| 	case VK_SPACE: return KeyCode::Space; |  | ||||||
| 	case VK_ESCAPE: return KeyCode::Esc; |  | ||||||
| 	default: return KeyCode::Unknown; |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| int easy2d::KeyEvent::GetCount() const | 	KeyCode KeyEvent::GetCode() const | ||||||
| { | 	{ | ||||||
| 	return static_cast<int>((DWORD)l_param_ & 0x0000FFFF); | 		switch (w_param_) | ||||||
| } | 		{ | ||||||
|  | 		case 'A': return KeyCode::A; | ||||||
|  | 		case 'B': return KeyCode::B; | ||||||
|  | 		case 'C': return KeyCode::C; | ||||||
|  | 		case 'D': return KeyCode::D; | ||||||
|  | 		case 'E': return KeyCode::E; | ||||||
|  | 		case 'F': return KeyCode::F; | ||||||
|  | 		case 'G': return KeyCode::G; | ||||||
|  | 		case 'H': return KeyCode::H; | ||||||
|  | 		case 'I': return KeyCode::I; | ||||||
|  | 		case 'J': return KeyCode::J; | ||||||
|  | 		case 'K': return KeyCode::K; | ||||||
|  | 		case 'L': return KeyCode::L; | ||||||
|  | 		case 'M': return KeyCode::M; | ||||||
|  | 		case 'N': return KeyCode::N; | ||||||
|  | 		case 'O': return KeyCode::O; | ||||||
|  | 		case 'P': return KeyCode::P; | ||||||
|  | 		case 'Q': return KeyCode::Q; | ||||||
|  | 		case 'R': return KeyCode::R; | ||||||
|  | 		case 'S': return KeyCode::S; | ||||||
|  | 		case 'T': return KeyCode::T; | ||||||
|  | 		case 'U': return KeyCode::U; | ||||||
|  | 		case 'V': return KeyCode::V; | ||||||
|  | 		case 'W': return KeyCode::W; | ||||||
|  | 		case 'X': return KeyCode::X; | ||||||
|  | 		case 'Y': return KeyCode::Y; | ||||||
|  | 		case 'Z': return KeyCode::Z; | ||||||
|  | 		case '0': return KeyCode::Num0; | ||||||
|  | 		case '1': return KeyCode::Num1; | ||||||
|  | 		case '2': return KeyCode::Num2; | ||||||
|  | 		case '3': return KeyCode::Num3; | ||||||
|  | 		case '4': return KeyCode::Num4; | ||||||
|  | 		case '5': return KeyCode::Num5; | ||||||
|  | 		case '6': return KeyCode::Num6; | ||||||
|  | 		case '7': return KeyCode::Num7; | ||||||
|  | 		case '8': return KeyCode::Num8; | ||||||
|  | 		case '9': return KeyCode::Num9; | ||||||
|  | 		case VK_NUMPAD0: return KeyCode::Numpad0; | ||||||
|  | 		case VK_NUMPAD1: return KeyCode::Numpad1; | ||||||
|  | 		case VK_NUMPAD2: return KeyCode::Numpad2; | ||||||
|  | 		case VK_NUMPAD3: return KeyCode::Numpad3; | ||||||
|  | 		case VK_NUMPAD4: return KeyCode::Numpad4; | ||||||
|  | 		case VK_NUMPAD5: return KeyCode::Numpad5; | ||||||
|  | 		case VK_NUMPAD6: return KeyCode::Numpad6; | ||||||
|  | 		case VK_NUMPAD7: return KeyCode::Numpad7; | ||||||
|  | 		case VK_NUMPAD8: return KeyCode::Numpad8; | ||||||
|  | 		case VK_NUMPAD9: return KeyCode::Numpad9; | ||||||
|  | 		case VK_UP: return KeyCode::Up; | ||||||
|  | 		case VK_DOWN: return KeyCode::Down; | ||||||
|  | 		case VK_LEFT: return KeyCode::Left; | ||||||
|  | 		case VK_RIGHT: return KeyCode::Right; | ||||||
|  | 		case VK_RETURN: return KeyCode::Enter; | ||||||
|  | 		case VK_SPACE: return KeyCode::Space; | ||||||
|  | 		case VK_ESCAPE: return KeyCode::Esc; | ||||||
|  | 		default: return KeyCode::Unknown; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::KeyEvent::Type easy2d::KeyEvent::GetType() const | 	int KeyEvent::GetCount() const | ||||||
| { | 	{ | ||||||
| 	return Type(message_); | 		return static_cast<int>((DWORD)l_param_ & 0x0000FFFF); | ||||||
| } | 	} | ||||||
|  | 
 | ||||||
|  | 	KeyEvent::Type KeyEvent::GetType() const | ||||||
|  | 	{ | ||||||
|  | 		return Type(message_); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,65 +21,68 @@ | ||||||
| #include "..\e2devent.h" | #include "..\e2devent.h" | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| easy2d::MouseEvent::MouseEvent(UINT message, WPARAM w_param, LPARAM l_param) | namespace easy2d | ||||||
| 	: message_(message) |  | ||||||
| 	, w_param_(w_param) |  | ||||||
| 	, l_param_(l_param) |  | ||||||
| { | { | ||||||
| } | 	MouseEvent::MouseEvent(UINT message, WPARAM w_param, LPARAM l_param) | ||||||
|  | 		: message_(message) | ||||||
|  | 		, w_param_(w_param) | ||||||
|  | 		, l_param_(l_param) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::MouseEvent::GetX() const | 	float MouseEvent::GetX() const | ||||||
| { | 	{ | ||||||
| 	float dpi = Graphics::GetDpi(); | 		float dpi = Graphics::GetDpi(); | ||||||
| 	return ((float)(short)LOWORD(l_param_)) * 96.f / dpi; | 		return ((float)(short)LOWORD(l_param_)) * 96.f / dpi; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::MouseEvent::GetY() const | 	float MouseEvent::GetY() const | ||||||
| { | 	{ | ||||||
| 	float dpi = Graphics::GetDpi(); | 		float dpi = Graphics::GetDpi(); | ||||||
| 	return ((float)(short)HIWORD(l_param_)) * 96.f / dpi; | 		return ((float)(short)HIWORD(l_param_)) * 96.f / dpi; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::MouseEvent::GetPosition() const | 	Point MouseEvent::GetPosition() const | ||||||
| { | 	{ | ||||||
| 	float dpi = Graphics::GetDpi(); | 		float dpi = Graphics::GetDpi(); | ||||||
| 	return Point( | 		return Point( | ||||||
| 		((float)(short)LOWORD(l_param_)) * 96.f / dpi, | 			((float)(short)LOWORD(l_param_)) * 96.f / dpi, | ||||||
| 		((float)(short)HIWORD(l_param_)) * 96.f / dpi | 			((float)(short)HIWORD(l_param_)) * 96.f / dpi | ||||||
| 	); | 		); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::MouseEvent::IsShiftDown() const | 	bool MouseEvent::IsShiftDown() const | ||||||
| { | 	{ | ||||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_SHIFT; | 		return GET_KEYSTATE_WPARAM(w_param_) == MK_SHIFT; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::MouseEvent::IsCtrlDown() const | 	bool MouseEvent::IsCtrlDown() const | ||||||
| { | 	{ | ||||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_CONTROL; | 		return GET_KEYSTATE_WPARAM(w_param_) == MK_CONTROL; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::MouseEvent::GetWheelDelta() const | 	float MouseEvent::GetWheelDelta() const | ||||||
| { | 	{ | ||||||
| 	return static_cast<float>(GET_WHEEL_DELTA_WPARAM(w_param_)); | 		return static_cast<float>(GET_WHEEL_DELTA_WPARAM(w_param_)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::MouseEvent::IsLButtonDown() const | 	bool MouseEvent::IsLButtonDown() const | ||||||
| { | 	{ | ||||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_LBUTTON; | 		return GET_KEYSTATE_WPARAM(w_param_) == MK_LBUTTON; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::MouseEvent::IsRButtonDown() const | 	bool MouseEvent::IsRButtonDown() const | ||||||
| { | 	{ | ||||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_RBUTTON; | 		return GET_KEYSTATE_WPARAM(w_param_) == MK_RBUTTON; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::MouseEvent::IsMButtonDown() const | 	bool MouseEvent::IsMButtonDown() const | ||||||
| { | 	{ | ||||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_MBUTTON; | 		return GET_KEYSTATE_WPARAM(w_param_) == MK_MBUTTON; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::MouseEvent::Type easy2d::MouseEvent::GetType() const | 	MouseEvent::Type MouseEvent::GetType() const | ||||||
| { | 	{ | ||||||
| 	return Type(message_); | 		return Type(message_); | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -21,47 +21,50 @@ | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Audio::Audio() | namespace easy2d | ||||||
| 	: x_audio2_(nullptr) |  | ||||||
| 	, mastering_voice_(nullptr) |  | ||||||
| { | { | ||||||
| 	ThrowIfFailed( | 	Audio::Audio() | ||||||
| 		MFStartup(MF_VERSION) | 		: x_audio2_(nullptr) | ||||||
| 	); | 		, mastering_voice_(nullptr) | ||||||
| 
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		XAudio2Create(&x_audio2_) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		x_audio2_->CreateMasteringVoice(&mastering_voice_) |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Audio::~Audio() |  | ||||||
| { |  | ||||||
| 	if (mastering_voice_) |  | ||||||
| 	{ | 	{ | ||||||
| 		mastering_voice_->DestroyVoice(); | 		ThrowIfFailed( | ||||||
| 		mastering_voice_ = nullptr; | 			MFStartup(MF_VERSION) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			XAudio2Create(&x_audio2_) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			x_audio2_->CreateMasteringVoice(&mastering_voice_) | ||||||
|  | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	SafeRelease(x_audio2_); | 	Audio::~Audio() | ||||||
|  | 	{ | ||||||
|  | 		if (mastering_voice_) | ||||||
|  | 		{ | ||||||
|  | 			mastering_voice_->DestroyVoice(); | ||||||
|  | 			mastering_voice_ = nullptr; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	MFShutdown(); | 		SafeRelease(x_audio2_); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| HRESULT easy2d::Audio::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx) | 		MFShutdown(); | ||||||
| { | 	} | ||||||
| 	return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Audio::Open() | 	HRESULT Audio::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx) | ||||||
| { | 	{ | ||||||
| 	x_audio2_->StartEngine(); | 		return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Audio::Close() | 	void Audio::Open() | ||||||
| { | 	{ | ||||||
| 	x_audio2_->StopEngine(); | 		x_audio2_->StartEngine(); | ||||||
| } | 	} | ||||||
|  | 
 | ||||||
|  | 	void Audio::Close() | ||||||
|  | 	{ | ||||||
|  | 		x_audio2_->StopEngine(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,49 +20,56 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| static easy2d::Graphics *	graphics_device = nullptr; |  | ||||||
| static easy2d::Input *		input_device = nullptr; |  | ||||||
| static easy2d::Audio *		audio_device = nullptr; |  | ||||||
| 
 | 
 | ||||||
| easy2d::Graphics * easy2d::Device::GetGraphics() | namespace easy2d | ||||||
| { | { | ||||||
| 	return graphics_device; | 	namespace | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Input * easy2d::Device::GetInput() |  | ||||||
| { |  | ||||||
| 	return input_device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Audio * easy2d::Device::GetAudio() |  | ||||||
| { |  | ||||||
| 	return audio_device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Device::Init(HWND hwnd) |  | ||||||
| { |  | ||||||
| 	graphics_device = new (std::nothrow) Graphics(hwnd); |  | ||||||
| 	input_device = new (std::nothrow) Input(hwnd); |  | ||||||
| 	audio_device = new (std::nothrow) Audio(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Device::Destroy() |  | ||||||
| { |  | ||||||
| 	if (audio_device) |  | ||||||
| 	{ | 	{ | ||||||
| 		delete audio_device; | 		Graphics *	graphics_device = nullptr; | ||||||
| 		audio_device = nullptr; | 		Input *		input_device = nullptr; | ||||||
|  | 		Audio *		audio_device = nullptr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (input_device) | 	Graphics * Device::GetGraphics() | ||||||
| 	{ | 	{ | ||||||
| 		delete input_device; | 		return graphics_device; | ||||||
| 		input_device = nullptr; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (graphics_device) | 	Input * Device::GetInput() | ||||||
| 	{ | 	{ | ||||||
| 		delete graphics_device; | 		return input_device; | ||||||
| 		graphics_device = nullptr; |  | ||||||
| 	} | 	} | ||||||
| } | 
 | ||||||
|  | 	Audio * Device::GetAudio() | ||||||
|  | 	{ | ||||||
|  | 		return audio_device; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Device::Init(HWND hwnd) | ||||||
|  | 	{ | ||||||
|  | 		graphics_device = new (std::nothrow) Graphics(hwnd); | ||||||
|  | 		input_device = new (std::nothrow) Input(hwnd); | ||||||
|  | 		audio_device = new (std::nothrow) Audio(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Device::Destroy() | ||||||
|  | 	{ | ||||||
|  | 		if (audio_device) | ||||||
|  | 		{ | ||||||
|  | 			delete audio_device; | ||||||
|  | 			audio_device = nullptr; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (input_device) | ||||||
|  | 		{ | ||||||
|  | 			delete input_device; | ||||||
|  | 			input_device = nullptr; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (graphics_device) | ||||||
|  | 		{ | ||||||
|  | 			delete graphics_device; | ||||||
|  | 			graphics_device = nullptr; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -24,7 +24,10 @@ | ||||||
| 
 | 
 | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	// 文字渲染器
 | 	//-------------------------------------------------------
 | ||||||
|  | 	// TextRenderer
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
|  | 
 | ||||||
| 	class TextRenderer | 	class TextRenderer | ||||||
| 		: public IDWriteTextRenderer | 		: public IDWriteTextRenderer | ||||||
| 	{ | 	{ | ||||||
|  | @ -505,320 +508,324 @@ namespace easy2d | ||||||
| 
 | 
 | ||||||
| 		return S_OK; | 		return S_OK; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Graphics::Graphics(HWND hwnd) | 	//-------------------------------------------------------
 | ||||||
| 	: factory_(nullptr) | 	// Graphics
 | ||||||
| 	, imaging_factory_(nullptr) | 	//-------------------------------------------------------
 | ||||||
| 	, write_factory_(nullptr) |  | ||||||
| 	, miter_stroke_style_(nullptr) |  | ||||||
| 	, bevel_stroke_style_(nullptr) |  | ||||||
| 	, round_stroke_style_(nullptr) |  | ||||||
| 	, fps_text_format_(nullptr) |  | ||||||
| 	, fps_text_layout_(nullptr) |  | ||||||
| 	, render_target_(nullptr) |  | ||||||
| 	, solid_brush_(nullptr) |  | ||||||
| 	, text_renderer_(nullptr) |  | ||||||
| 	, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) |  | ||||||
| { |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		D2D1CreateFactory( |  | ||||||
| 			D2D1_FACTORY_TYPE_SINGLE_THREADED, |  | ||||||
| 			&factory_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 | 
 | ||||||
| 	ThrowIfFailed( | 	Graphics::Graphics(HWND hwnd) | ||||||
| 		CoCreateInstance( | 		: factory_(nullptr) | ||||||
| 			CLSID_WICImagingFactory, | 		, imaging_factory_(nullptr) | ||||||
| 			nullptr, | 		, write_factory_(nullptr) | ||||||
| 			CLSCTX_INPROC_SERVER, | 		, miter_stroke_style_(nullptr) | ||||||
| 			IID_IWICImagingFactory, | 		, bevel_stroke_style_(nullptr) | ||||||
| 			reinterpret_cast<void**>(&imaging_factory_) | 		, round_stroke_style_(nullptr) | ||||||
| 		) | 		, fps_text_format_(nullptr) | ||||||
| 	); | 		, fps_text_layout_(nullptr) | ||||||
| 
 | 		, render_target_(nullptr) | ||||||
| 	ThrowIfFailed( | 		, solid_brush_(nullptr) | ||||||
| 		DWriteCreateFactory( | 		, text_renderer_(nullptr) | ||||||
| 			DWRITE_FACTORY_TYPE_SHARED, | 		, clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) | ||||||
| 			__uuidof(IDWriteFactory), |  | ||||||
| 			reinterpret_cast<IUnknown**>(&write_factory_) |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	RECT rc; |  | ||||||
| 	::GetClientRect(hwnd, &rc); |  | ||||||
| 
 |  | ||||||
| 	D2D1_SIZE_U size = D2D1::SizeU( |  | ||||||
| 		rc.right - rc.left, |  | ||||||
| 		rc.bottom - rc.top |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 |  | ||||||
| 	// 创建一个 Direct2D 渲染目标
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		factory_->CreateHwndRenderTarget( |  | ||||||
| 			D2D1::RenderTargetProperties(), |  | ||||||
| 			D2D1::HwndRenderTargetProperties( |  | ||||||
| 				hwnd, |  | ||||||
| 				size, |  | ||||||
| 				D2D1_PRESENT_OPTIONS_NONE), |  | ||||||
| 			&render_target_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	// 创建画刷
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		render_target_->CreateSolidColorBrush( |  | ||||||
| 			D2D1::ColorF(D2D1::ColorF::White), |  | ||||||
| 			&solid_brush_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	// 创建自定义的文字渲染器
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		TextRenderer::Create( |  | ||||||
| 			&text_renderer_, |  | ||||||
| 			factory_, |  | ||||||
| 			render_target_, |  | ||||||
| 			solid_brush_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Graphics::~Graphics() |  | ||||||
| { |  | ||||||
| 	SafeRelease(fps_text_format_); |  | ||||||
| 	SafeRelease(fps_text_layout_); |  | ||||||
| 	SafeRelease(text_renderer_); |  | ||||||
| 	SafeRelease(solid_brush_); |  | ||||||
| 	SafeRelease(render_target_); |  | ||||||
| 
 |  | ||||||
| 	SafeRelease(miter_stroke_style_); |  | ||||||
| 	SafeRelease(bevel_stroke_style_); |  | ||||||
| 	SafeRelease(round_stroke_style_); |  | ||||||
| 	SafeRelease(factory_); |  | ||||||
| 	SafeRelease(imaging_factory_); |  | ||||||
| 	SafeRelease(write_factory_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Graphics::BeginDraw() |  | ||||||
| { |  | ||||||
| 	render_target_->BeginDraw(); |  | ||||||
| 	render_target_->Clear(clear_color_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Graphics::EndDraw() |  | ||||||
| { |  | ||||||
| 	HRESULT hr = render_target_->EndDraw(); |  | ||||||
| 
 |  | ||||||
| 	if (hr == D2DERR_RECREATE_TARGET) |  | ||||||
| 	{ | 	{ | ||||||
| 		// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
 | 		ThrowIfFailed( | ||||||
| 		// 并在下一次调用时重建资源
 | 			D2D1CreateFactory( | ||||||
| 		hr = S_OK; | 				D2D1_FACTORY_TYPE_SINGLE_THREADED, | ||||||
|  | 				&factory_ | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
| 
 | 
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			CoCreateInstance( | ||||||
|  | 				CLSID_WICImagingFactory, | ||||||
|  | 				nullptr, | ||||||
|  | 				CLSCTX_INPROC_SERVER, | ||||||
|  | 				IID_IWICImagingFactory, | ||||||
|  | 				reinterpret_cast<void**>(&imaging_factory_) | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			DWriteCreateFactory( | ||||||
|  | 				DWRITE_FACTORY_TYPE_SHARED, | ||||||
|  | 				__uuidof(IDWriteFactory), | ||||||
|  | 				reinterpret_cast<IUnknown**>(&write_factory_) | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		RECT rc; | ||||||
|  | 		::GetClientRect(hwnd, &rc); | ||||||
|  | 
 | ||||||
|  | 		D2D1_SIZE_U size = D2D1::SizeU( | ||||||
|  | 			rc.right - rc.left, | ||||||
|  | 			rc.bottom - rc.top | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
 | ||||||
|  | 		// 创建一个 Direct2D 渲染目标
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			factory_->CreateHwndRenderTarget( | ||||||
|  | 				D2D1::RenderTargetProperties(), | ||||||
|  | 				D2D1::HwndRenderTargetProperties( | ||||||
|  | 					hwnd, | ||||||
|  | 					size, | ||||||
|  | 					D2D1_PRESENT_OPTIONS_NONE), | ||||||
|  | 				&render_target_ | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		// 创建画刷
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			render_target_->CreateSolidColorBrush( | ||||||
|  | 				D2D1::ColorF(D2D1::ColorF::White), | ||||||
|  | 				&solid_brush_ | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		// 创建自定义的文字渲染器
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			TextRenderer::Create( | ||||||
|  | 				&text_renderer_, | ||||||
|  | 				factory_, | ||||||
|  | 				render_target_, | ||||||
|  | 				solid_brush_ | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Graphics::~Graphics() | ||||||
|  | 	{ | ||||||
| 		SafeRelease(fps_text_format_); | 		SafeRelease(fps_text_format_); | ||||||
| 		SafeRelease(fps_text_layout_); | 		SafeRelease(fps_text_layout_); | ||||||
| 		SafeRelease(text_renderer_); | 		SafeRelease(text_renderer_); | ||||||
| 		SafeRelease(solid_brush_); | 		SafeRelease(solid_brush_); | ||||||
| 		SafeRelease(render_target_); | 		SafeRelease(render_target_); | ||||||
|  | 
 | ||||||
|  | 		SafeRelease(miter_stroke_style_); | ||||||
|  | 		SafeRelease(bevel_stroke_style_); | ||||||
|  | 		SafeRelease(round_stroke_style_); | ||||||
|  | 		SafeRelease(factory_); | ||||||
|  | 		SafeRelease(imaging_factory_); | ||||||
|  | 		SafeRelease(write_factory_); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ThrowIfFailed(hr); | 	void Graphics::BeginDraw() | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Graphics::DrawDebugInfo() |  | ||||||
| { |  | ||||||
| 	static int render_times_ = 0; |  | ||||||
| 	static Time last_render_time_ = Time::Now(); |  | ||||||
| 	int duration = (Time::Now() - last_render_time_).Milliseconds(); |  | ||||||
| 
 |  | ||||||
| 	if (!fps_text_format_) |  | ||||||
| 	{ | 	{ | ||||||
| 		ThrowIfFailed( | 		render_target_->BeginDraw(); | ||||||
| 			write_factory_->CreateTextFormat( | 		render_target_->Clear(clear_color_); | ||||||
| 				L"", | 	} | ||||||
|  | 
 | ||||||
|  | 	void Graphics::EndDraw() | ||||||
|  | 	{ | ||||||
|  | 		HRESULT hr = render_target_->EndDraw(); | ||||||
|  | 
 | ||||||
|  | 		if (hr == D2DERR_RECREATE_TARGET) | ||||||
|  | 		{ | ||||||
|  | 			// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
 | ||||||
|  | 			// 并在下一次调用时重建资源
 | ||||||
|  | 			hr = S_OK; | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(fps_text_format_); | ||||||
|  | 			SafeRelease(fps_text_layout_); | ||||||
|  | 			SafeRelease(text_renderer_); | ||||||
|  | 			SafeRelease(solid_brush_); | ||||||
|  | 			SafeRelease(render_target_); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed(hr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Graphics::DrawDebugInfo() | ||||||
|  | 	{ | ||||||
|  | 		static int render_times_ = 0; | ||||||
|  | 		static Time last_render_time_ = Time::Now(); | ||||||
|  | 		int duration = (Time::Now() - last_render_time_).Milliseconds(); | ||||||
|  | 
 | ||||||
|  | 		if (!fps_text_format_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				write_factory_->CreateTextFormat( | ||||||
|  | 					L"", | ||||||
|  | 					nullptr, | ||||||
|  | 					DWRITE_FONT_WEIGHT_NORMAL, | ||||||
|  | 					DWRITE_FONT_STYLE_NORMAL, | ||||||
|  | 					DWRITE_FONT_STRETCH_NORMAL, | ||||||
|  | 					20, | ||||||
|  | 					L"", | ||||||
|  | 					&fps_text_format_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				fps_text_format_->SetWordWrapping( | ||||||
|  | 					DWRITE_WORD_WRAPPING_NO_WRAP | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		++render_times_; | ||||||
|  | 		if (duration >= 100) | ||||||
|  | 		{ | ||||||
|  | 			wchar_t fps_text[12] = {}; | ||||||
|  | 			int len = swprintf_s(fps_text, L"FPS: %.1f", 1000.f / duration * render_times_); | ||||||
|  | 
 | ||||||
|  | 			last_render_time_ = Time::Now(); | ||||||
|  | 			render_times_ = 0; | ||||||
|  | 
 | ||||||
|  | 			SafeRelease(fps_text_layout_); | ||||||
|  | 
 | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				write_factory_->CreateTextLayout( | ||||||
|  | 					fps_text, | ||||||
|  | 					static_cast<UINT32>(len), | ||||||
|  | 					fps_text_format_, | ||||||
|  | 					0, | ||||||
|  | 					0, | ||||||
|  | 					&fps_text_layout_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (fps_text_layout_) | ||||||
|  | 		{ | ||||||
|  | 			render_target_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
|  | 			solid_brush_->SetOpacity(1.0f); | ||||||
|  | 			static_cast<TextRenderer*>(text_renderer_)->SetTextStyle( | ||||||
|  | 				D2D1::ColorF(D2D1::ColorF::White), | ||||||
|  | 				TRUE, | ||||||
|  | 				D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | ||||||
|  | 				1.5f, | ||||||
|  | 				D2D1_LINE_JOIN_ROUND | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			fps_text_layout_->Draw( | ||||||
| 				nullptr, | 				nullptr, | ||||||
| 				DWRITE_FONT_WEIGHT_NORMAL, | 				text_renderer_, | ||||||
| 				DWRITE_FONT_STYLE_NORMAL, | 				10, | ||||||
| 				DWRITE_FONT_STRETCH_NORMAL, | 				0 | ||||||
| 				20, | 			); | ||||||
| 				L"", | 		} | ||||||
| 				&fps_text_format_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			fps_text_format_->SetWordWrapping( |  | ||||||
| 				DWRITE_WORD_WRAPPING_NO_WRAP |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	++render_times_; | 	ID2D1HwndRenderTarget * Graphics::GetRenderTarget() const | ||||||
| 	if (duration >= 100) |  | ||||||
| 	{ | 	{ | ||||||
| 		wchar_t fps_text[12] = {}; | 		return render_target_; | ||||||
| 		int len = swprintf_s(fps_text, L"FPS: %.1f", 1000.f / duration * render_times_); |  | ||||||
| 
 |  | ||||||
| 		last_render_time_ = Time::Now(); |  | ||||||
| 		render_times_ = 0; |  | ||||||
| 
 |  | ||||||
| 		SafeRelease(fps_text_layout_); |  | ||||||
| 
 |  | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			write_factory_->CreateTextLayout( |  | ||||||
| 				fps_text, |  | ||||||
| 				static_cast<UINT32>(len), |  | ||||||
| 				fps_text_format_, |  | ||||||
| 				0, |  | ||||||
| 				0, |  | ||||||
| 				&fps_text_layout_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (fps_text_layout_) | 	ID2D1SolidColorBrush * Graphics::GetSolidBrush() const | ||||||
|  | 	{ | ||||||
|  | 		return solid_brush_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IDWriteTextRenderer* Graphics::GetTextRender() const | ||||||
|  | 	{ | ||||||
|  | 		return text_renderer_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ID2D1Factory * Graphics::GetFactory() const | ||||||
|  | 	{ | ||||||
|  | 		return factory_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IWICImagingFactory * Graphics::GetImagingFactory() const | ||||||
|  | 	{ | ||||||
|  | 		return imaging_factory_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IDWriteFactory * Graphics::GetWriteFactory() const | ||||||
|  | 	{ | ||||||
|  | 		return write_factory_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ID2D1StrokeStyle * Graphics::GetMiterStrokeStyle() | ||||||
|  | 	{ | ||||||
|  | 		if (!miter_stroke_style_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				factory_->CreateStrokeStyle( | ||||||
|  | 					D2D1::StrokeStyleProperties( | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_LINE_JOIN_MITER, | ||||||
|  | 						2.0f, | ||||||
|  | 						D2D1_DASH_STYLE_SOLID, | ||||||
|  | 						0.0f), | ||||||
|  | 					nullptr, | ||||||
|  | 					0, | ||||||
|  | 					&miter_stroke_style_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		return miter_stroke_style_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ID2D1StrokeStyle * Graphics::GetBevelStrokeStyle() | ||||||
|  | 	{ | ||||||
|  | 		if (!bevel_stroke_style_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				factory_->CreateStrokeStyle( | ||||||
|  | 					D2D1::StrokeStyleProperties( | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_LINE_JOIN_BEVEL, | ||||||
|  | 						2.0f, | ||||||
|  | 						D2D1_DASH_STYLE_SOLID, | ||||||
|  | 						0.0f), | ||||||
|  | 					nullptr, | ||||||
|  | 					0, | ||||||
|  | 					&bevel_stroke_style_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		return bevel_stroke_style_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ID2D1StrokeStyle * Graphics::GetRoundStrokeStyle() | ||||||
|  | 	{ | ||||||
|  | 		if (!round_stroke_style_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				factory_->CreateStrokeStyle( | ||||||
|  | 					D2D1::StrokeStyleProperties( | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_CAP_STYLE_FLAT, | ||||||
|  | 						D2D1_LINE_JOIN_ROUND, | ||||||
|  | 						2.0f, | ||||||
|  | 						D2D1_DASH_STYLE_SOLID, | ||||||
|  | 						0.0f), | ||||||
|  | 					nullptr, | ||||||
|  | 					0, | ||||||
|  | 					&round_stroke_style_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		return round_stroke_style_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Graphics::SetTextRendererStyle(const Color & fill_color, bool has_outline, const Color & outline_color, float outline_width, Stroke outline_stroke) | ||||||
| 	{ | 	{ | ||||||
| 		render_target_->SetTransform(D2D1::Matrix3x2F::Identity()); |  | ||||||
| 		solid_brush_->SetOpacity(1.0f); |  | ||||||
| 		static_cast<TextRenderer*>(text_renderer_)->SetTextStyle( | 		static_cast<TextRenderer*>(text_renderer_)->SetTextStyle( | ||||||
| 			D2D1::ColorF(D2D1::ColorF::White), | 			D2D1_COLOR_F(fill_color), | ||||||
| 			TRUE, | 			has_outline, | ||||||
| 			D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | 			D2D1_COLOR_F(outline_color), | ||||||
| 			1.5f, | 			outline_width, | ||||||
| 			D2D1_LINE_JOIN_ROUND | 			D2D1_LINE_JOIN(outline_stroke) | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		fps_text_layout_->Draw( |  | ||||||
| 			nullptr, |  | ||||||
| 			text_renderer_, |  | ||||||
| 			10, |  | ||||||
| 			0 |  | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| ID2D1HwndRenderTarget * easy2d::Graphics::GetRenderTarget() const | 	float Graphics::GetDpi() | ||||||
| { |  | ||||||
| 	return render_target_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1SolidColorBrush * easy2d::Graphics::GetSolidBrush() const |  | ||||||
| { |  | ||||||
| 	return solid_brush_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| IDWriteTextRenderer* easy2d::Graphics::GetTextRender() const |  | ||||||
| { |  | ||||||
| 	return text_renderer_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1Factory * easy2d::Graphics::GetFactory() const |  | ||||||
| { |  | ||||||
| 	return factory_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| IWICImagingFactory * easy2d::Graphics::GetImagingFactory() const |  | ||||||
| { |  | ||||||
| 	return imaging_factory_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| IDWriteFactory * easy2d::Graphics::GetWriteFactory() const |  | ||||||
| { |  | ||||||
| 	return write_factory_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1StrokeStyle * easy2d::Graphics::GetMiterStrokeStyle() |  | ||||||
| { |  | ||||||
| 	if (!miter_stroke_style_) |  | ||||||
| 	{ | 	{ | ||||||
| 		ThrowIfFailed( | 		static float dpi = -1; | ||||||
| 			factory_->CreateStrokeStyle( | 		if (dpi < 0) | ||||||
| 				D2D1::StrokeStyleProperties( | 		{ | ||||||
| 					D2D1_CAP_STYLE_FLAT, | 			HDC hdc = ::GetDC(0); | ||||||
| 					D2D1_CAP_STYLE_FLAT, | 			dpi = static_cast<float>(::GetDeviceCaps(hdc, LOGPIXELSX)); | ||||||
| 					D2D1_CAP_STYLE_FLAT, | 			::ReleaseDC(0, hdc); | ||||||
| 					D2D1_LINE_JOIN_MITER, | 		} | ||||||
| 					2.0f, | 		return dpi; | ||||||
| 					D2D1_DASH_STYLE_SOLID, |  | ||||||
| 					0.0f), |  | ||||||
| 				nullptr, |  | ||||||
| 				0, |  | ||||||
| 				&miter_stroke_style_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 	return miter_stroke_style_; | } | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1StrokeStyle * easy2d::Graphics::GetBevelStrokeStyle() |  | ||||||
| { |  | ||||||
| 	if (!bevel_stroke_style_) |  | ||||||
| 	{ |  | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			factory_->CreateStrokeStyle( |  | ||||||
| 				D2D1::StrokeStyleProperties( |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_LINE_JOIN_BEVEL, |  | ||||||
| 					2.0f, |  | ||||||
| 					D2D1_DASH_STYLE_SOLID, |  | ||||||
| 					0.0f), |  | ||||||
| 				nullptr, |  | ||||||
| 				0, |  | ||||||
| 				&bevel_stroke_style_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 	return bevel_stroke_style_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1StrokeStyle * easy2d::Graphics::GetRoundStrokeStyle() |  | ||||||
| { |  | ||||||
| 	if (!round_stroke_style_) |  | ||||||
| 	{ |  | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			factory_->CreateStrokeStyle( |  | ||||||
| 				D2D1::StrokeStyleProperties( |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_CAP_STYLE_FLAT, |  | ||||||
| 					D2D1_LINE_JOIN_ROUND, |  | ||||||
| 					2.0f, |  | ||||||
| 					D2D1_DASH_STYLE_SOLID, |  | ||||||
| 					0.0f), |  | ||||||
| 				nullptr, |  | ||||||
| 				0, |  | ||||||
| 				&round_stroke_style_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 	return round_stroke_style_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Graphics::SetTextRendererStyle(const Color & fill_color, bool has_outline, const Color & outline_color, float outline_width, Stroke outline_stroke) |  | ||||||
| { |  | ||||||
| 	static_cast<TextRenderer*>(text_renderer_)->SetTextStyle( |  | ||||||
| 		D2D1_COLOR_F(fill_color), |  | ||||||
| 		has_outline, |  | ||||||
| 		D2D1_COLOR_F(outline_color), |  | ||||||
| 		outline_width, |  | ||||||
| 		D2D1_LINE_JOIN(outline_stroke) |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Graphics::GetDpi() |  | ||||||
| { |  | ||||||
| 	static float dpi = -1; |  | ||||||
| 	if (dpi < 0) |  | ||||||
| 	{ |  | ||||||
| 		HDC hdc = ::GetDC(0); |  | ||||||
| 		dpi = static_cast<float>(::GetDeviceCaps(hdc, LOGPIXELSX)); |  | ||||||
| 		::ReleaseDC(0, hdc); |  | ||||||
| 	} |  | ||||||
| 	return dpi; |  | ||||||
| } |  | ||||||
|  | @ -22,151 +22,154 @@ | ||||||
| #include "..\e2dtool.h" | #include "..\e2dtool.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Input::Input(HWND hwnd) | namespace easy2d | ||||||
| 	: direct_input_(nullptr) |  | ||||||
| 	, keyboard_device_(nullptr) |  | ||||||
| 	, mouse_device_(nullptr) |  | ||||||
| { | { | ||||||
| 	ZeroMemory(key_buffer_, sizeof(key_buffer_)); | 	Input::Input(HWND hwnd) | ||||||
| 	ZeroMemory(&mouse_state_, sizeof(mouse_state_)); | 		: direct_input_(nullptr) | ||||||
| 
 | 		, keyboard_device_(nullptr) | ||||||
| 	HINSTANCE hinstance = GetModuleHandle(nullptr); | 		, mouse_device_(nullptr) | ||||||
| 
 |  | ||||||
| 	// 初始化接口对象
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		DirectInput8Create( |  | ||||||
| 			hinstance, |  | ||||||
| 			DIRECTINPUT_VERSION, |  | ||||||
| 			IID_IDirectInput8, |  | ||||||
| 			(void**)&direct_input_, |  | ||||||
| 			nullptr |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	// 初始化键盘设备
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		direct_input_->CreateDevice( |  | ||||||
| 			GUID_SysKeyboard, |  | ||||||
| 			&keyboard_device_, |  | ||||||
| 			nullptr |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	keyboard_device_->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); |  | ||||||
| 	keyboard_device_->SetDataFormat(&c_dfDIKeyboard); |  | ||||||
| 	keyboard_device_->Acquire(); |  | ||||||
| 	keyboard_device_->Poll(); |  | ||||||
| 
 |  | ||||||
| 	// 初始化鼠标设备
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		direct_input_->CreateDevice( |  | ||||||
| 			GUID_SysMouse, |  | ||||||
| 			&mouse_device_, |  | ||||||
| 			nullptr |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	mouse_device_->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); |  | ||||||
| 	mouse_device_->SetDataFormat(&c_dfDIMouse); |  | ||||||
| 	mouse_device_->Acquire(); |  | ||||||
| 	mouse_device_->Poll(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Input::~Input() |  | ||||||
| { |  | ||||||
| 	if (keyboard_device_) |  | ||||||
| 		keyboard_device_->Unacquire(); |  | ||||||
| 	if (mouse_device_) |  | ||||||
| 		mouse_device_->Unacquire(); |  | ||||||
| 
 |  | ||||||
| 	SafeRelease(mouse_device_); |  | ||||||
| 	SafeRelease(keyboard_device_); |  | ||||||
| 	SafeRelease(direct_input_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Input::Flush() |  | ||||||
| { |  | ||||||
| 	if (keyboard_device_) |  | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = keyboard_device_->Poll(); | 		ZeroMemory(key_buffer_, sizeof(key_buffer_)); | ||||||
| 		if (FAILED(hr)) | 		ZeroMemory(&mouse_state_, sizeof(mouse_state_)); | ||||||
|  | 
 | ||||||
|  | 		HINSTANCE hinstance = GetModuleHandle(nullptr); | ||||||
|  | 
 | ||||||
|  | 		// 初始化接口对象
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			DirectInput8Create( | ||||||
|  | 				hinstance, | ||||||
|  | 				DIRECTINPUT_VERSION, | ||||||
|  | 				IID_IDirectInput8, | ||||||
|  | 				(void**)&direct_input_, | ||||||
|  | 				nullptr | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		// 初始化键盘设备
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			direct_input_->CreateDevice( | ||||||
|  | 				GUID_SysKeyboard, | ||||||
|  | 				&keyboard_device_, | ||||||
|  | 				nullptr | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		keyboard_device_->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); | ||||||
|  | 		keyboard_device_->SetDataFormat(&c_dfDIKeyboard); | ||||||
|  | 		keyboard_device_->Acquire(); | ||||||
|  | 		keyboard_device_->Poll(); | ||||||
|  | 
 | ||||||
|  | 		// 初始化鼠标设备
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			direct_input_->CreateDevice( | ||||||
|  | 				GUID_SysMouse, | ||||||
|  | 				&mouse_device_, | ||||||
|  | 				nullptr | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		mouse_device_->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); | ||||||
|  | 		mouse_device_->SetDataFormat(&c_dfDIMouse); | ||||||
|  | 		mouse_device_->Acquire(); | ||||||
|  | 		mouse_device_->Poll(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Input::~Input() | ||||||
|  | 	{ | ||||||
|  | 		if (keyboard_device_) | ||||||
|  | 			keyboard_device_->Unacquire(); | ||||||
|  | 		if (mouse_device_) | ||||||
|  | 			mouse_device_->Unacquire(); | ||||||
|  | 
 | ||||||
|  | 		SafeRelease(mouse_device_); | ||||||
|  | 		SafeRelease(keyboard_device_); | ||||||
|  | 		SafeRelease(direct_input_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Input::Flush() | ||||||
|  | 	{ | ||||||
|  | 		if (keyboard_device_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = keyboard_device_->Acquire(); | 			HRESULT hr = keyboard_device_->Poll(); | ||||||
| 			while (hr == DIERR_INPUTLOST) | 			if (FAILED(hr)) | ||||||
|  | 			{ | ||||||
| 				hr = keyboard_device_->Acquire(); | 				hr = keyboard_device_->Acquire(); | ||||||
|  | 				while (hr == DIERR_INPUTLOST) | ||||||
|  | 					hr = keyboard_device_->Acquire(); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				keyboard_device_->GetDeviceState( | ||||||
|  | 					sizeof(key_buffer_), | ||||||
|  | 					(void**)&key_buffer_ | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			keyboard_device_->GetDeviceState( |  | ||||||
| 				sizeof(key_buffer_), |  | ||||||
| 				(void**)&key_buffer_ |  | ||||||
| 			); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	if (mouse_device_) | 		if (mouse_device_) | ||||||
| 	{ |  | ||||||
| 		HRESULT hr = mouse_device_->Poll(); |  | ||||||
| 		if (FAILED(hr)) |  | ||||||
| 		{ | 		{ | ||||||
| 			hr = mouse_device_->Acquire(); | 			HRESULT hr = mouse_device_->Poll(); | ||||||
| 			while (hr == DIERR_INPUTLOST) | 			if (FAILED(hr)) | ||||||
|  | 			{ | ||||||
| 				hr = mouse_device_->Acquire(); | 				hr = mouse_device_->Acquire(); | ||||||
| 		} | 				while (hr == DIERR_INPUTLOST) | ||||||
| 		else | 					hr = mouse_device_->Acquire(); | ||||||
| 		{ | 			} | ||||||
| 			mouse_device_->GetDeviceState( | 			else | ||||||
| 				sizeof(mouse_state_), | 			{ | ||||||
| 				(void**)&mouse_state_ | 				mouse_device_->GetDeviceState( | ||||||
| 			); | 					sizeof(mouse_state_), | ||||||
|  | 					(void**)&mouse_state_ | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Input::IsDown(KeyCode key) | 	bool Input::IsDown(KeyCode key) | ||||||
| { | 	{ | ||||||
| 	if (key_buffer_[static_cast<int>(key)] & 0x80) | 		if (key_buffer_[static_cast<int>(key)] & 0x80) | ||||||
| 		return true; | 			return true; | ||||||
| 	return false; | 		return false; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Input::IsDown(MouseCode code) | 	bool Input::IsDown(MouseCode code) | ||||||
| { | 	{ | ||||||
| 	if (mouse_state_.rgbButtons[static_cast<int>(code)] & 0x80) | 		if (mouse_state_.rgbButtons[static_cast<int>(code)] & 0x80) | ||||||
| 		return true; | 			return true; | ||||||
| 	return false; | 		return false; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Input::GetMouseX() | 	float Input::GetMouseX() | ||||||
| { | 	{ | ||||||
| 	return GetMousePos().x; | 		return GetMousePos().x; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Input::GetMouseY() | 	float Input::GetMouseY() | ||||||
| { | 	{ | ||||||
| 	return GetMousePos().y; | 		return GetMousePos().y; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Input::GetMousePos() | 	Point Input::GetMousePos() | ||||||
| { | 	{ | ||||||
| 	POINT mousePos; | 		POINT mousePos; | ||||||
| 	::GetCursorPos(&mousePos); | 		::GetCursorPos(&mousePos); | ||||||
| 	::ScreenToClient(Game::GetInstance()->GetHWnd(), &mousePos); | 		::ScreenToClient(Game::GetInstance()->GetHWnd(), &mousePos); | ||||||
| 	float dpi = Graphics::GetDpi(); | 		float dpi = Graphics::GetDpi(); | ||||||
| 	return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi); | 		return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Input::GetMouseDeltaX() | 	float Input::GetMouseDeltaX() | ||||||
| { | 	{ | ||||||
| 	return (float)mouse_state_.lX; | 		return (float)mouse_state_.lX; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Input::GetMouseDeltaY() | 	float Input::GetMouseDeltaY() | ||||||
| { | 	{ | ||||||
| 	return (float)mouse_state_.lY; | 		return (float)mouse_state_.lY; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Input::GetMouseDeltaZ() | 	float Input::GetMouseDeltaZ() | ||||||
| { | 	{ | ||||||
| 	return (float)mouse_state_.lZ; | 		return (float)mouse_state_.lZ; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -21,230 +21,233 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Canvas::Canvas(float width, float height) | namespace easy2d | ||||||
| 	: render_target_(nullptr) |  | ||||||
| 	, fill_brush_(nullptr) |  | ||||||
| 	, line_brush_(nullptr) |  | ||||||
| 	, stroke_style_(nullptr) |  | ||||||
| 	, stroke_width_(1.0f) |  | ||||||
| 	, stroke_(Stroke::Miter) |  | ||||||
| { | { | ||||||
| 	render_target_ = Device::GetGraphics()->GetRenderTarget(); | 	Canvas::Canvas(float width, float height) | ||||||
| 	render_target_->AddRef(); | 		: render_target_(nullptr) | ||||||
| 
 | 		, fill_brush_(nullptr) | ||||||
| 	ThrowIfFailed( | 		, line_brush_(nullptr) | ||||||
| 		render_target_->CreateSolidColorBrush( | 		, stroke_style_(nullptr) | ||||||
| 			D2D1::ColorF(D2D1::ColorF::White), | 		, stroke_width_(1.0f) | ||||||
| 			&fill_brush_ | 		, stroke_(Stroke::Miter) | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		render_target_->CreateSolidColorBrush( |  | ||||||
| 			D2D1::ColorF(D2D1::ColorF::White), |  | ||||||
| 			&line_brush_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 	 |  | ||||||
| 	this->SetClipEnabled(true); |  | ||||||
| 	this->SetWidth(width); |  | ||||||
| 	this->SetHeight(height); |  | ||||||
| 	this->SetStrokeStyle(stroke_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Canvas::~Canvas() |  | ||||||
| { |  | ||||||
| 	SafeRelease(line_brush_); |  | ||||||
| 	SafeRelease(fill_brush_); |  | ||||||
| 	SafeRelease(render_target_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Canvas::SetLineColor(const Color & color) |  | ||||||
| { |  | ||||||
| 	line_brush_->SetColor(D2D_COLOR_F(color)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Canvas::SetFillColor(const Color & color) |  | ||||||
| { |  | ||||||
| 	fill_brush_->SetColor(D2D_COLOR_F(color)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Canvas::SetStrokeWidth(float width) |  | ||||||
| { |  | ||||||
| 	stroke_width_ = std::max(width, 0.f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Canvas::SetStrokeStyle(Stroke strokeStyle) |  | ||||||
| { |  | ||||||
| 	switch (strokeStyle) |  | ||||||
| 	{ | 	{ | ||||||
| 	case easy2d::Stroke::Miter: | 		render_target_ = Device::GetGraphics()->GetRenderTarget(); | ||||||
| 		stroke_style_ = Device::GetGraphics()->GetMiterStrokeStyle(); | 		render_target_->AddRef(); | ||||||
| 		break; | 
 | ||||||
| 	case easy2d::Stroke::Bevel: | 		ThrowIfFailed( | ||||||
| 		stroke_style_ = Device::GetGraphics()->GetBevelStrokeStyle(); | 			render_target_->CreateSolidColorBrush( | ||||||
| 		break; | 				D2D1::ColorF(D2D1::ColorF::White), | ||||||
| 	case easy2d::Stroke::Round: | 				&fill_brush_ | ||||||
| 		stroke_style_ = Device::GetGraphics()->GetRoundStrokeStyle(); | 			) | ||||||
| 		break; | 		); | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed( | ||||||
|  | 			render_target_->CreateSolidColorBrush( | ||||||
|  | 				D2D1::ColorF(D2D1::ColorF::White), | ||||||
|  | 				&line_brush_ | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		this->SetClipEnabled(true); | ||||||
|  | 		this->SetWidth(width); | ||||||
|  | 		this->SetHeight(height); | ||||||
|  | 		this->SetStrokeStyle(stroke_); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Color easy2d::Canvas::GetLineColor() const | 	Canvas::~Canvas() | ||||||
| { | 	{ | ||||||
| 	return line_brush_->GetColor(); | 		SafeRelease(line_brush_); | ||||||
| } | 		SafeRelease(fill_brush_); | ||||||
|  | 		SafeRelease(render_target_); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Color easy2d::Canvas::GetFillColor() const | 	void Canvas::SetLineColor(const Color & color) | ||||||
| { | 	{ | ||||||
| 	return fill_brush_->GetColor(); | 		line_brush_->SetColor(D2D_COLOR_F(color)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Canvas::GetStrokeWidth() const | 	void Canvas::SetFillColor(const Color & color) | ||||||
| { | 	{ | ||||||
| 	return stroke_width_; | 		fill_brush_->SetColor(D2D_COLOR_F(color)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Stroke easy2d::Canvas::GetStrokeStyle() const | 	void Canvas::SetStrokeWidth(float width) | ||||||
| { | 	{ | ||||||
| 	return stroke_; | 		stroke_width_ = std::max(width, 0.f); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::DrawLine(const Point & begin, const Point & end) | 	void Canvas::SetStrokeStyle(Stroke strokeStyle) | ||||||
| { | 	{ | ||||||
| 	render_target_->DrawLine( | 		switch (strokeStyle) | ||||||
| 		D2D1::Point2F(begin.x, begin.y), | 		{ | ||||||
| 		D2D1::Point2F(end.x, end.y), | 		case Stroke::Miter: | ||||||
| 		line_brush_, | 			stroke_style_ = Device::GetGraphics()->GetMiterStrokeStyle(); | ||||||
| 		stroke_width_, | 			break; | ||||||
| 		stroke_style_ | 		case Stroke::Bevel: | ||||||
| 	); | 			stroke_style_ = Device::GetGraphics()->GetBevelStrokeStyle(); | ||||||
| } | 			break; | ||||||
|  | 		case Stroke::Round: | ||||||
|  | 			stroke_style_ = Device::GetGraphics()->GetRoundStrokeStyle(); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::DrawCircle(const Point & center, float radius) | 	Color Canvas::GetLineColor() const | ||||||
| { | 	{ | ||||||
| 	render_target_->DrawEllipse( | 		return line_brush_->GetColor(); | ||||||
| 		D2D1::Ellipse( | 	} | ||||||
| 			D2D1::Point2F( | 
 | ||||||
| 				center.x, | 	Color Canvas::GetFillColor() const | ||||||
| 				center.y | 	{ | ||||||
|  | 		return fill_brush_->GetColor(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Canvas::GetStrokeWidth() const | ||||||
|  | 	{ | ||||||
|  | 		return stroke_width_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Stroke Canvas::GetStrokeStyle() const | ||||||
|  | 	{ | ||||||
|  | 		return stroke_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Canvas::DrawLine(const Point & begin, const Point & end) | ||||||
|  | 	{ | ||||||
|  | 		render_target_->DrawLine( | ||||||
|  | 			D2D1::Point2F(begin.x, begin.y), | ||||||
|  | 			D2D1::Point2F(end.x, end.y), | ||||||
|  | 			line_brush_, | ||||||
|  | 			stroke_width_, | ||||||
|  | 			stroke_style_ | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Canvas::DrawCircle(const Point & center, float radius) | ||||||
|  | 	{ | ||||||
|  | 		render_target_->DrawEllipse( | ||||||
|  | 			D2D1::Ellipse( | ||||||
|  | 				D2D1::Point2F( | ||||||
|  | 					center.x, | ||||||
|  | 					center.y | ||||||
|  | 				), | ||||||
|  | 				radius, | ||||||
|  | 				radius | ||||||
| 			), | 			), | ||||||
| 			radius, | 			line_brush_, | ||||||
| 			radius | 			stroke_width_, | ||||||
| 		), | 			stroke_style_ | ||||||
| 		line_brush_, | 		); | ||||||
| 		stroke_width_, | 	} | ||||||
| 		stroke_style_ |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) | 	void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) | ||||||
| { | 	{ | ||||||
| 	render_target_->DrawEllipse( | 		render_target_->DrawEllipse( | ||||||
| 		D2D1::Ellipse( | 			D2D1::Ellipse( | ||||||
| 			D2D1::Point2F( | 				D2D1::Point2F( | ||||||
| 				center.x, | 					center.x, | ||||||
| 				center.y | 					center.y | ||||||
|  | 				), | ||||||
|  | 				radius_x, | ||||||
|  | 				radius_y | ||||||
| 			), | 			), | ||||||
| 			radius_x, | 			line_brush_, | ||||||
| 			radius_y | 			stroke_width_, | ||||||
| 		), | 			stroke_style_ | ||||||
| 		line_brush_, | 		); | ||||||
| 		stroke_width_, | 	} | ||||||
| 		stroke_style_ |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::DrawRect(const Rect & rect) | 	void Canvas::DrawRect(const Rect & rect) | ||||||
| { | 	{ | ||||||
| 	render_target_->DrawRectangle( | 		render_target_->DrawRectangle( | ||||||
| 		D2D1::RectF( |  | ||||||
| 			rect.origin.x, |  | ||||||
| 			rect.origin.y, |  | ||||||
| 			rect.origin.x + rect.size.width, |  | ||||||
| 			rect.origin.y + rect.size.height |  | ||||||
| 		), |  | ||||||
| 		line_brush_, |  | ||||||
| 		stroke_width_, |  | ||||||
| 		stroke_style_ |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) |  | ||||||
| { |  | ||||||
| 	render_target_->DrawRoundedRectangle( |  | ||||||
| 		D2D1::RoundedRect( |  | ||||||
| 			D2D1::RectF( | 			D2D1::RectF( | ||||||
| 				rect.origin.x, | 				rect.origin.x, | ||||||
| 				rect.origin.y, | 				rect.origin.y, | ||||||
| 				rect.origin.x + rect.size.width, | 				rect.origin.x + rect.size.width, | ||||||
| 				rect.origin.y + rect.size.height | 				rect.origin.y + rect.size.height | ||||||
| 			), | 			), | ||||||
| 			radius_x, | 			line_brush_, | ||||||
| 			radius_y | 			stroke_width_, | ||||||
| 		), | 			stroke_style_ | ||||||
| 		line_brush_, | 		); | ||||||
| 		stroke_width_, | 	} | ||||||
| 		stroke_style_ |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::FillCircle(const Point & center, float radius) | 	void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) | ||||||
| { | 	{ | ||||||
| 	render_target_->FillEllipse( | 		render_target_->DrawRoundedRectangle( | ||||||
| 		D2D1::Ellipse( | 			D2D1::RoundedRect( | ||||||
| 			D2D1::Point2F( | 				D2D1::RectF( | ||||||
| 				center.x, | 					rect.origin.x, | ||||||
| 				center.y | 					rect.origin.y, | ||||||
|  | 					rect.origin.x + rect.size.width, | ||||||
|  | 					rect.origin.y + rect.size.height | ||||||
|  | 				), | ||||||
|  | 				radius_x, | ||||||
|  | 				radius_y | ||||||
| 			), | 			), | ||||||
| 			radius, | 			line_brush_, | ||||||
| 			radius | 			stroke_width_, | ||||||
| 		), | 			stroke_style_ | ||||||
| 		fill_brush_ | 		); | ||||||
| 	); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) | 	void Canvas::FillCircle(const Point & center, float radius) | ||||||
| { | 	{ | ||||||
| 	render_target_->FillEllipse( | 		render_target_->FillEllipse( | ||||||
| 		D2D1::Ellipse( | 			D2D1::Ellipse( | ||||||
| 			D2D1::Point2F( | 				D2D1::Point2F( | ||||||
| 				center.x, | 					center.x, | ||||||
| 				center.y | 					center.y | ||||||
|  | 				), | ||||||
|  | 				radius, | ||||||
|  | 				radius | ||||||
| 			), | 			), | ||||||
| 			radius_x, | 			fill_brush_ | ||||||
| 			radius_y | 		); | ||||||
| 		), | 	} | ||||||
| 		fill_brush_ |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::FillRect(const Rect & rect) | 	void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) | ||||||
| { | 	{ | ||||||
| 	render_target_->FillRectangle( | 		render_target_->FillEllipse( | ||||||
| 		D2D1::RectF( | 			D2D1::Ellipse( | ||||||
| 			rect.origin.x, | 				D2D1::Point2F( | ||||||
| 			rect.origin.y, | 					center.x, | ||||||
| 			rect.origin.x + rect.size.width, | 					center.y | ||||||
| 			rect.origin.y + rect.size.height | 				), | ||||||
| 		), | 				radius_x, | ||||||
| 		fill_brush_ | 				radius_y | ||||||
| 	); | 			), | ||||||
| } | 			fill_brush_ | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) | 	void Canvas::FillRect(const Rect & rect) | ||||||
| { | 	{ | ||||||
| 	render_target_->FillRoundedRectangle( | 		render_target_->FillRectangle( | ||||||
| 		D2D1::RoundedRect( |  | ||||||
| 			D2D1::RectF( | 			D2D1::RectF( | ||||||
| 				rect.origin.x, | 				rect.origin.x, | ||||||
| 				rect.origin.y, | 				rect.origin.y, | ||||||
| 				rect.origin.x + rect.size.width, | 				rect.origin.x + rect.size.width, | ||||||
| 				rect.origin.y + rect.size.height | 				rect.origin.y + rect.size.height | ||||||
| 			), | 			), | ||||||
| 			radius_x, | 			fill_brush_ | ||||||
| 			radius_y | 		); | ||||||
| 		), | 	} | ||||||
| 		fill_brush_ | 
 | ||||||
| 	); | 	void Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) | ||||||
| } | 	{ | ||||||
|  | 		render_target_->FillRoundedRectangle( | ||||||
|  | 			D2D1::RoundedRect( | ||||||
|  | 				D2D1::RectF( | ||||||
|  | 					rect.origin.x, | ||||||
|  | 					rect.origin.y, | ||||||
|  | 					rect.origin.x + rect.size.width, | ||||||
|  | 					rect.origin.y + rect.size.height | ||||||
|  | 				), | ||||||
|  | 				radius_x, | ||||||
|  | 				radius_y | ||||||
|  | 			), | ||||||
|  | 			fill_brush_ | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -22,371 +22,374 @@ | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| #include "..\e2dtool.h" | #include "..\e2dtool.h" | ||||||
| 
 | 
 | ||||||
| std::map<size_t, ID2D1Bitmap*> easy2d::Image::bitmap_cache_; | namespace easy2d | ||||||
| 
 |  | ||||||
| easy2d::Image::Image() |  | ||||||
| 	: bitmap_(nullptr) |  | ||||||
| 	, crop_rect_() |  | ||||||
| { | { | ||||||
| } | 	std::map<size_t, ID2D1Bitmap*> Image::bitmap_cache_; | ||||||
| 
 | 
 | ||||||
| easy2d::Image::Image(Resource& res) | 	Image::Image() | ||||||
| 	: bitmap_(nullptr) | 		: bitmap_(nullptr) | ||||||
| 	, crop_rect_() | 		, crop_rect_() | ||||||
| { |  | ||||||
| 	this->Load(res); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Image::Image(Resource& res, const Rect& crop_rect) |  | ||||||
| 	: bitmap_(nullptr) |  | ||||||
| 	, crop_rect_() |  | ||||||
| { |  | ||||||
| 	this->Load(res); |  | ||||||
| 	this->Crop(crop_rect); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Image::Image(const std::wstring & file_name) |  | ||||||
| 	: bitmap_(nullptr) |  | ||||||
| 	, crop_rect_() |  | ||||||
| { |  | ||||||
| 	this->Load(file_name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Image::Image(const std::wstring & file_name, const Rect & crop_rect) |  | ||||||
| 	: bitmap_(nullptr) |  | ||||||
| 	, crop_rect_() |  | ||||||
| { |  | ||||||
| 	this->Load(file_name); |  | ||||||
| 	this->Crop(crop_rect); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Image::~Image() |  | ||||||
| { |  | ||||||
| 	SafeRelease(bitmap_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Image::Load(Resource& res) |  | ||||||
| { |  | ||||||
| 	if (!Image::CacheBitmap(res)) |  | ||||||
| 	{ | 	{ | ||||||
| 		E2D_WARNING("Load Image from file failed!"); |  | ||||||
| 		return false; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); | 	Image::Image(Resource& res) | ||||||
| 	return true; | 		: bitmap_(nullptr) | ||||||
| } | 		, crop_rect_() | ||||||
| 
 |  | ||||||
| bool easy2d::Image::Load(const std::wstring & file_name) |  | ||||||
| { |  | ||||||
| 	E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name."); |  | ||||||
| 
 |  | ||||||
| 	if (file_name.empty()) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	if (!Image::CacheBitmap(file_name)) |  | ||||||
| 	{ | 	{ | ||||||
| 		E2D_WARNING("Load Image from file failed!"); | 		this->Load(res); | ||||||
| 		return false; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	this->SetBitmap(bitmap_cache_.at(std::hash<std::wstring>{}(file_name))); | 	Image::Image(Resource& res, const Rect& crop_rect) | ||||||
| 	return true; | 		: bitmap_(nullptr) | ||||||
| } | 		, crop_rect_() | ||||||
| 
 |  | ||||||
| void easy2d::Image::Crop(const Rect& crop_rect) |  | ||||||
| { |  | ||||||
| 	if (bitmap_) |  | ||||||
| 	{ | 	{ | ||||||
| 		auto bitmap_size = bitmap_->GetSize(); | 		this->Load(res); | ||||||
| 		crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.width); | 		this->Crop(crop_rect); | ||||||
| 		crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.height); |  | ||||||
| 		crop_rect_.size.width = std::min(std::max(crop_rect.size.width, 0.f), bitmap_size.width - crop_rect.origin.x); |  | ||||||
| 		crop_rect_.size.height = std::min(std::max(crop_rect.size.height, 0.f), bitmap_size.height - crop_rect.origin.y); |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| float easy2d::Image::GetWidth() const | 	Image::Image(const std::wstring & file_name) | ||||||
| { | 		: bitmap_(nullptr) | ||||||
| 	return crop_rect_.size.width; | 		, crop_rect_() | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Image::GetHeight() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_.size.height; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Size easy2d::Image::GetSize() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_.size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Image::GetSourceWidth() const |  | ||||||
| { |  | ||||||
| 	if (bitmap_) |  | ||||||
| 	{ | 	{ | ||||||
| 		return bitmap_->GetSize().width; | 		this->Load(file_name); | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	Image::Image(const std::wstring & file_name, const Rect & crop_rect) | ||||||
|  | 		: bitmap_(nullptr) | ||||||
|  | 		, crop_rect_() | ||||||
| 	{ | 	{ | ||||||
| 		return 0; | 		this->Load(file_name); | ||||||
|  | 		this->Crop(crop_rect); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| float easy2d::Image::GetSourceHeight() const | 	Image::~Image() | ||||||
| { |  | ||||||
| 	if (bitmap_) |  | ||||||
| 	{ | 	{ | ||||||
| 		return bitmap_->GetSize().height; | 		SafeRelease(bitmap_); | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	bool Image::Load(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		return 0; | 		if (!Image::CacheBitmap(res)) | ||||||
| 	} | 		{ | ||||||
| } | 			E2D_WARNING("Load Image from file failed!"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Image::GetSourceSize() const | 		this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); | ||||||
| { |  | ||||||
| 	if (bitmap_) |  | ||||||
| 	{ |  | ||||||
| 		auto bitmap_size = bitmap_->GetSize(); |  | ||||||
| 		return Size{ bitmap_size.width, bitmap_size.height }; |  | ||||||
| 	} |  | ||||||
| 	return Size{}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Image::GetCropX() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_.origin.x; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Image::GetCropY() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_.origin.y; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Point easy2d::Image::GetCropPos() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_.origin; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const easy2d::Rect & easy2d::Image::GetCropRect() const |  | ||||||
| { |  | ||||||
| 	return crop_rect_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ID2D1Bitmap * easy2d::Image::GetBitmap() const |  | ||||||
| { |  | ||||||
| 	return bitmap_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Image::CacheBitmap(Resource& res) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) |  | ||||||
| 	{ |  | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	HRESULT hr; | 	bool Image::Load(const std::wstring & file_name) | ||||||
| 
 |  | ||||||
| 	HINSTANCE				hinstance = GetModuleHandle(nullptr); |  | ||||||
| 	IWICImagingFactory*		imaging_factory = Device::GetGraphics()->GetImagingFactory(); |  | ||||||
| 	ID2D1HwndRenderTarget*	render_target = Device::GetGraphics()->GetRenderTarget(); |  | ||||||
| 	IWICBitmapDecoder*		decoder = nullptr; |  | ||||||
| 	IWICBitmapFrameDecode*	source = nullptr; |  | ||||||
| 	IWICStream*				stream = nullptr; |  | ||||||
| 	IWICFormatConverter*	converter = nullptr; |  | ||||||
| 	ID2D1Bitmap*			bitmap = nullptr; |  | ||||||
| 
 |  | ||||||
| 	// 加载资源
 |  | ||||||
| 	hr = res.Load() ? S_OK : E_FAIL; |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ | 	{ | ||||||
| 		// 创建 WIC 流
 | 		E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name."); | ||||||
| 		hr = imaging_factory->CreateStream(&stream); | 
 | ||||||
|  | 		if (file_name.empty()) | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		if (!Image::CacheBitmap(file_name)) | ||||||
|  | 		{ | ||||||
|  | 			E2D_WARNING("Load Image from file failed!"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		this->SetBitmap(bitmap_cache_.at(std::hash<std::wstring>{}(file_name))); | ||||||
|  | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (SUCCEEDED(hr)) | 	void Image::Crop(const Rect& crop_rect) | ||||||
| 	{ | 	{ | ||||||
| 		// 初始化流
 | 		if (bitmap_) | ||||||
| 		hr = stream->InitializeFromMemory( | 		{ | ||||||
| 			static_cast<WICInProcPointer>(res.GetData()), | 			auto bitmap_size = bitmap_->GetSize(); | ||||||
| 			res.GetDataSize() | 			crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.width); | ||||||
| 		); | 			crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.height); | ||||||
|  | 			crop_rect_.size.width = std::min(std::max(crop_rect.size.width, 0.f), bitmap_size.width - crop_rect.origin.x); | ||||||
|  | 			crop_rect_.size.height = std::min(std::max(crop_rect.size.height, 0.f), bitmap_size.height - crop_rect.origin.y); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (SUCCEEDED(hr)) | 	float Image::GetWidth() const | ||||||
| 	{ | 	{ | ||||||
| 		// 创建流的解码器
 | 		return crop_rect_.size.width; | ||||||
| 		hr = imaging_factory->CreateDecoderFromStream( | 	} | ||||||
| 			stream, | 
 | ||||||
|  | 	float Image::GetHeight() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_.size.height; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Size Image::GetSize() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_.size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Image::GetSourceWidth() const | ||||||
|  | 	{ | ||||||
|  | 		if (bitmap_) | ||||||
|  | 		{ | ||||||
|  | 			return bitmap_->GetSize().width; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Image::GetSourceHeight() const | ||||||
|  | 	{ | ||||||
|  | 		if (bitmap_) | ||||||
|  | 		{ | ||||||
|  | 			return bitmap_->GetSize().height; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Size Image::GetSourceSize() const | ||||||
|  | 	{ | ||||||
|  | 		if (bitmap_) | ||||||
|  | 		{ | ||||||
|  | 			auto bitmap_size = bitmap_->GetSize(); | ||||||
|  | 			return Size{ bitmap_size.width, bitmap_size.height }; | ||||||
|  | 		} | ||||||
|  | 		return Size{}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Image::GetCropX() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_.origin.x; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Image::GetCropY() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_.origin.y; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Point Image::GetCropPos() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_.origin; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Rect & Image::GetCropRect() const | ||||||
|  | 	{ | ||||||
|  | 		return crop_rect_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ID2D1Bitmap * Image::GetBitmap() const | ||||||
|  | 	{ | ||||||
|  | 		return bitmap_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Image::CacheBitmap(Resource& res) | ||||||
|  | 	{ | ||||||
|  | 		size_t hash_code = res.GetHashCode(); | ||||||
|  | 		if (bitmap_cache_.find(hash_code) != bitmap_cache_.end()) | ||||||
|  | 		{ | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		HRESULT hr; | ||||||
|  | 
 | ||||||
|  | 		HINSTANCE				hinstance = GetModuleHandle(nullptr); | ||||||
|  | 		IWICImagingFactory*		imaging_factory = Device::GetGraphics()->GetImagingFactory(); | ||||||
|  | 		ID2D1HwndRenderTarget*	render_target = Device::GetGraphics()->GetRenderTarget(); | ||||||
|  | 		IWICBitmapDecoder*		decoder = nullptr; | ||||||
|  | 		IWICBitmapFrameDecode*	source = nullptr; | ||||||
|  | 		IWICStream*				stream = nullptr; | ||||||
|  | 		IWICFormatConverter*	converter = nullptr; | ||||||
|  | 		ID2D1Bitmap*			bitmap = nullptr; | ||||||
|  | 
 | ||||||
|  | 		// 加载资源
 | ||||||
|  | 		hr = res.Load() ? S_OK : E_FAIL; | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建 WIC 流
 | ||||||
|  | 			hr = imaging_factory->CreateStream(&stream); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 初始化流
 | ||||||
|  | 			hr = stream->InitializeFromMemory( | ||||||
|  | 				static_cast<WICInProcPointer>(res.GetData()), | ||||||
|  | 				res.GetDataSize() | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建流的解码器
 | ||||||
|  | 			hr = imaging_factory->CreateDecoderFromStream( | ||||||
|  | 				stream, | ||||||
|  | 				nullptr, | ||||||
|  | 				WICDecodeMetadataCacheOnLoad, | ||||||
|  | 				&decoder | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建初始化框架
 | ||||||
|  | 			hr = decoder->GetFrame(0, &source); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建图片格式转换器
 | ||||||
|  | 			hr = imaging_factory->CreateFormatConverter(&converter); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 图片格式转换成 32bppPBGRA
 | ||||||
|  | 			hr = converter->Initialize( | ||||||
|  | 				source, | ||||||
|  | 				GUID_WICPixelFormat32bppPBGRA, | ||||||
|  | 				WICBitmapDitherTypeNone, | ||||||
|  | 				nullptr, | ||||||
|  | 				0.f, | ||||||
|  | 				WICBitmapPaletteTypeMedianCut | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 从 WIC 位图创建一个 Direct2D 位图
 | ||||||
|  | 			hr = render_target->CreateBitmapFromWicBitmap( | ||||||
|  | 				converter, | ||||||
|  | 				nullptr, | ||||||
|  | 				&bitmap | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 释放相关资源
 | ||||||
|  | 		SafeRelease(decoder); | ||||||
|  | 		SafeRelease(source); | ||||||
|  | 		SafeRelease(stream); | ||||||
|  | 		SafeRelease(converter); | ||||||
|  | 
 | ||||||
|  | 		return SUCCEEDED(hr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Image::CacheBitmap(const std::wstring & file_name) | ||||||
|  | 	{ | ||||||
|  | 		size_t hash_code = std::hash<std::wstring>{}(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 获取完整路径
 | ||||||
|  | 		std::wstring image_file_path = image_file.GetPath(); | ||||||
|  | 
 | ||||||
|  | 		Graphics*				graphics_device = Device::GetGraphics(); | ||||||
|  | 		IWICImagingFactory*		imaging_factory = graphics_device->GetImagingFactory(); | ||||||
|  | 		ID2D1HwndRenderTarget*	render_target = graphics_device->GetRenderTarget(); | ||||||
|  | 		IWICBitmapDecoder*		decoder = nullptr; | ||||||
|  | 		IWICBitmapFrameDecode*	source = nullptr; | ||||||
|  | 		IWICStream*				stream = nullptr; | ||||||
|  | 		IWICFormatConverter*	converter = nullptr; | ||||||
|  | 		ID2D1Bitmap*			bitmap = nullptr; | ||||||
|  | 
 | ||||||
|  | 		// 创建解码器
 | ||||||
|  | 		HRESULT hr = imaging_factory->CreateDecoderFromFilename( | ||||||
|  | 			image_file_path.c_str(), | ||||||
| 			nullptr, | 			nullptr, | ||||||
|  | 			GENERIC_READ, | ||||||
| 			WICDecodeMetadataCacheOnLoad, | 			WICDecodeMetadataCacheOnLoad, | ||||||
| 			&decoder | 			&decoder | ||||||
| 		); | 		); | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建初始化框架
 | ||||||
|  | 			hr = decoder->GetFrame(0, &source); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 创建图片格式转换器
 | ||||||
|  | 			hr = imaging_factory->CreateFormatConverter(&converter); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 图片格式转换成 32bppPBGRA
 | ||||||
|  | 			hr = converter->Initialize( | ||||||
|  | 				source, | ||||||
|  | 				GUID_WICPixelFormat32bppPBGRA, | ||||||
|  | 				WICBitmapDitherTypeNone, | ||||||
|  | 				nullptr, | ||||||
|  | 				0.f, | ||||||
|  | 				WICBitmapPaletteTypeMedianCut | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			// 从 WIC 位图创建一个 Direct2D 位图
 | ||||||
|  | 			hr = render_target->CreateBitmapFromWicBitmap( | ||||||
|  | 				converter, | ||||||
|  | 				nullptr, | ||||||
|  | 				&bitmap | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 释放相关资源
 | ||||||
|  | 		SafeRelease(decoder); | ||||||
|  | 		SafeRelease(source); | ||||||
|  | 		SafeRelease(stream); | ||||||
|  | 		SafeRelease(converter); | ||||||
|  | 
 | ||||||
|  | 		return SUCCEEDED(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (SUCCEEDED(hr)) | 	void Image::ClearCache() | ||||||
| 	{ | 	{ | ||||||
| 		// 创建初始化框架
 | 		if (bitmap_cache_.empty()) | ||||||
| 		hr = decoder->GetFrame(0, &source); | 			return; | ||||||
|  | 
 | ||||||
|  | 		for (const auto& bitmap : bitmap_cache_) | ||||||
|  | 		{ | ||||||
|  | 			bitmap.second->Release(); | ||||||
|  | 		} | ||||||
|  | 		bitmap_cache_.clear(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (SUCCEEDED(hr)) | 	void Image::SetBitmap(ID2D1Bitmap * bitmap) | ||||||
| 	{ | 	{ | ||||||
| 		// 创建图片格式转换器
 | 		if (bitmap_ == bitmap) | ||||||
| 		hr = imaging_factory->CreateFormatConverter(&converter); | 			return; | ||||||
|  | 
 | ||||||
|  | 		if (bitmap_) | ||||||
|  | 		{ | ||||||
|  | 			bitmap_->Release(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (bitmap) | ||||||
|  | 		{ | ||||||
|  | 			bitmap->AddRef(); | ||||||
|  | 
 | ||||||
|  | 			bitmap_ = bitmap; | ||||||
|  | 			crop_rect_.origin.x = crop_rect_.origin.y = 0; | ||||||
|  | 			crop_rect_.size.width = bitmap_->GetSize().width; | ||||||
|  | 			crop_rect_.size.height = bitmap_->GetSize().height; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | } | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 图片格式转换成 32bppPBGRA
 |  | ||||||
| 		hr = converter->Initialize( |  | ||||||
| 			source, |  | ||||||
| 			GUID_WICPixelFormat32bppPBGRA, |  | ||||||
| 			WICBitmapDitherTypeNone, |  | ||||||
| 			nullptr, |  | ||||||
| 			0.f, |  | ||||||
| 			WICBitmapPaletteTypeMedianCut |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 从 WIC 位图创建一个 Direct2D 位图
 |  | ||||||
| 		hr = render_target->CreateBitmapFromWicBitmap( |  | ||||||
| 			converter, |  | ||||||
| 			nullptr, |  | ||||||
| 			&bitmap |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// 释放相关资源
 |  | ||||||
| 	SafeRelease(decoder); |  | ||||||
| 	SafeRelease(source); |  | ||||||
| 	SafeRelease(stream); |  | ||||||
| 	SafeRelease(converter); |  | ||||||
| 
 |  | ||||||
| 	return SUCCEEDED(hr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Image::CacheBitmap(const std::wstring & file_name) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = std::hash<std::wstring>{}(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 获取完整路径
 |  | ||||||
| 	std::wstring image_file_path = image_file.GetPath(); |  | ||||||
| 
 |  | ||||||
| 	Graphics*				graphics_device = Device::GetGraphics(); |  | ||||||
| 	IWICImagingFactory*		imaging_factory = graphics_device->GetImagingFactory(); |  | ||||||
| 	ID2D1HwndRenderTarget*	render_target = graphics_device->GetRenderTarget(); |  | ||||||
| 	IWICBitmapDecoder*		decoder = nullptr; |  | ||||||
| 	IWICBitmapFrameDecode*	source = nullptr; |  | ||||||
| 	IWICStream*				stream = nullptr; |  | ||||||
| 	IWICFormatConverter*	converter = nullptr; |  | ||||||
| 	ID2D1Bitmap*			bitmap = nullptr; |  | ||||||
| 
 |  | ||||||
| 	// 创建解码器
 |  | ||||||
| 	HRESULT hr = imaging_factory->CreateDecoderFromFilename( |  | ||||||
| 		image_file_path.c_str(), |  | ||||||
| 		nullptr, |  | ||||||
| 		GENERIC_READ, |  | ||||||
| 		WICDecodeMetadataCacheOnLoad, |  | ||||||
| 		&decoder |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 创建初始化框架
 |  | ||||||
| 		hr = decoder->GetFrame(0, &source); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 创建图片格式转换器
 |  | ||||||
| 		hr = imaging_factory->CreateFormatConverter(&converter); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 图片格式转换成 32bppPBGRA
 |  | ||||||
| 		hr = converter->Initialize( |  | ||||||
| 			source, |  | ||||||
| 			GUID_WICPixelFormat32bppPBGRA, |  | ||||||
| 			WICBitmapDitherTypeNone, |  | ||||||
| 			nullptr, |  | ||||||
| 			0.f, |  | ||||||
| 			WICBitmapPaletteTypeMedianCut |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		// 从 WIC 位图创建一个 Direct2D 位图
 |  | ||||||
| 		hr = render_target->CreateBitmapFromWicBitmap( |  | ||||||
| 			converter, |  | ||||||
| 			nullptr, |  | ||||||
| 			&bitmap |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		bitmap_cache_.insert(std::make_pair(hash_code, bitmap)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// 释放相关资源
 |  | ||||||
| 	SafeRelease(decoder); |  | ||||||
| 	SafeRelease(source); |  | ||||||
| 	SafeRelease(stream); |  | ||||||
| 	SafeRelease(converter); |  | ||||||
| 
 |  | ||||||
| 	return SUCCEEDED(hr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Image::ClearCache() |  | ||||||
| { |  | ||||||
| 	if (bitmap_cache_.empty()) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	for (const auto& bitmap : bitmap_cache_) |  | ||||||
| 	{ |  | ||||||
| 		bitmap.second->Release(); |  | ||||||
| 	} |  | ||||||
| 	bitmap_cache_.clear(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Image::SetBitmap(ID2D1Bitmap * bitmap) |  | ||||||
| { |  | ||||||
| 	if (bitmap_ == bitmap) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	if (bitmap_) |  | ||||||
| 	{ |  | ||||||
| 		bitmap_->Release(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (bitmap) |  | ||||||
| 	{ |  | ||||||
| 		bitmap->AddRef(); |  | ||||||
| 
 |  | ||||||
| 		bitmap_ = bitmap; |  | ||||||
| 		crop_rect_.origin.x = crop_rect_.origin.y = 0; |  | ||||||
| 		crop_rect_.size.width = bitmap_->GetSize().width; |  | ||||||
| 		crop_rect_.size.height = bitmap_->GetSize().height; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -21,100 +21,103 @@ | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Scene::Scene() | namespace easy2d | ||||||
| 	: root_(nullptr) |  | ||||||
| 	, transform_(D2D1::Matrix3x2F::Identity()) |  | ||||||
| { | { | ||||||
| } | 	Scene::Scene() | ||||||
| 
 | 		: root_(nullptr) | ||||||
| easy2d::Scene::Scene(Node * root) | 		, transform_(D2D1::Matrix3x2F::Identity()) | ||||||
| 	: root_(nullptr) |  | ||||||
| 	, transform_(D2D1::Matrix3x2F::Identity()) |  | ||||||
| { |  | ||||||
| 	this->SetRoot(root); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Scene::~Scene() |  | ||||||
| { |  | ||||||
| 	if (root_) |  | ||||||
| 	{ | 	{ | ||||||
| 		root_->SetParentScene(nullptr); |  | ||||||
| 		root_->Release(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Scene::SetRoot(Node * root) |  | ||||||
| { |  | ||||||
| 	if (root_ == root) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	if (root_) |  | ||||||
| 	{ |  | ||||||
| 		root_->SetParentScene(nullptr); |  | ||||||
| 		root_->Release(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (root) | 	Scene::Scene(Node * root) | ||||||
|  | 		: root_(nullptr) | ||||||
|  | 		, transform_(D2D1::Matrix3x2F::Identity()) | ||||||
| 	{ | 	{ | ||||||
| 		root->Retain(); | 		this->SetRoot(root); | ||||||
| 		root->SetParentScene(this); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	root_ = root; | 	Scene::~Scene() | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Node * easy2d::Scene::GetRoot() const |  | ||||||
| { |  | ||||||
| 	return root_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Scene::Draw() |  | ||||||
| { |  | ||||||
| 	if (root_) |  | ||||||
| 	{ | 	{ | ||||||
| 		root_->Visit(); | 		if (root_) | ||||||
| 	} | 		{ | ||||||
| } | 			root_->SetParentScene(nullptr); | ||||||
| 
 | 			root_->Release(); | ||||||
| void easy2d::Scene::Dispatch(const MouseEvent & e) | 		} | ||||||
| { |  | ||||||
| 	auto handler = dynamic_cast<MouseEventHandler*>(this); |  | ||||||
| 	if (handler) |  | ||||||
| 	{ |  | ||||||
| 		handler->Handle(e); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (root_) | 	void Scene::SetRoot(Node * root) | ||||||
| 	{ | 	{ | ||||||
| 		root_->Dispatch(e, false); | 		if (root_ == root) | ||||||
| 	} | 			return; | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Scene::Dispatch(const KeyEvent & e) | 		if (root_) | ||||||
| { | 		{ | ||||||
| 	auto handler = dynamic_cast<KeyEventHandler*>(this); | 			root_->SetParentScene(nullptr); | ||||||
| 	if (handler) | 			root_->Release(); | ||||||
| 	{ | 		} | ||||||
| 		handler->Handle(e); | 
 | ||||||
|  | 		if (root) | ||||||
|  | 		{ | ||||||
|  | 			root->Retain(); | ||||||
|  | 			root->SetParentScene(this); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		root_ = root; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (root_) | 	Node * Scene::GetRoot() const | ||||||
| 	{ | 	{ | ||||||
| 		root_->Dispatch(e, false); | 		return root_; | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Scene::SetTransform(const D2D1::Matrix3x2F& matrix) | 	void Scene::Draw() | ||||||
| { |  | ||||||
| 	transform_ = matrix; |  | ||||||
| 
 |  | ||||||
| 	if (root_) |  | ||||||
| 	{ | 	{ | ||||||
| 		root_->dirty_transform_ = true; | 		if (root_) | ||||||
|  | 		{ | ||||||
|  | 			root_->Visit(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const D2D1::Matrix3x2F & easy2d::Scene::GetTransform() const | 	void Scene::Dispatch(const MouseEvent & e) | ||||||
| { | 	{ | ||||||
| 	return transform_; | 		auto handler = dynamic_cast<MouseEventHandler*>(this); | ||||||
| } | 		if (handler) | ||||||
|  | 		{ | ||||||
|  | 			handler->Handle(e); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (root_) | ||||||
|  | 		{ | ||||||
|  | 			root_->Dispatch(e, false); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Scene::Dispatch(const KeyEvent & e) | ||||||
|  | 	{ | ||||||
|  | 		auto handler = dynamic_cast<KeyEventHandler*>(this); | ||||||
|  | 		if (handler) | ||||||
|  | 		{ | ||||||
|  | 			handler->Handle(e); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (root_) | ||||||
|  | 		{ | ||||||
|  | 			root_->Dispatch(e, false); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Scene::SetTransform(const D2D1::Matrix3x2F& matrix) | ||||||
|  | 	{ | ||||||
|  | 		transform_ = matrix; | ||||||
|  | 
 | ||||||
|  | 		if (root_) | ||||||
|  | 		{ | ||||||
|  | 			root_->dirty_transform_ = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const D2D1::Matrix3x2F & Scene::GetTransform() const | ||||||
|  | 	{ | ||||||
|  | 		return transform_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,128 +21,131 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Sprite::Sprite() | namespace easy2d | ||||||
| 	: image_(nullptr) |  | ||||||
| { | { | ||||||
| } | 	Sprite::Sprite() | ||||||
| 
 | 		: image_(nullptr) | ||||||
| easy2d::Sprite::Sprite(Image * image) |  | ||||||
| 	: image_(nullptr) |  | ||||||
| { |  | ||||||
| 	Load(image); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sprite::Sprite(Resource& res) |  | ||||||
| 	: image_(nullptr) |  | ||||||
| { |  | ||||||
| 	Load(res); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sprite::Sprite(Resource& res, const Rect& crop_rect) |  | ||||||
| 	: image_(nullptr) |  | ||||||
| { |  | ||||||
| 	Load(res); |  | ||||||
| 	Crop(crop_rect); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sprite::Sprite(const std::wstring & file_name) |  | ||||||
| 	: image_(nullptr) |  | ||||||
| { |  | ||||||
| 	Load(file_name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sprite::Sprite(const std::wstring & file_name, const Rect & crop_rect) |  | ||||||
| 	: image_(nullptr) |  | ||||||
| { |  | ||||||
| 	Load(file_name); |  | ||||||
| 	Crop(crop_rect); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Sprite::~Sprite() |  | ||||||
| { |  | ||||||
| 	SafeRelease(image_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Sprite::Load(Image * image) |  | ||||||
| { |  | ||||||
| 	if (image) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (image_) | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::Sprite(Image * image) | ||||||
|  | 		: image_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		Load(image); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::Sprite(Resource& res) | ||||||
|  | 		: image_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		Load(res); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::Sprite(Resource& res, const Rect& crop_rect) | ||||||
|  | 		: image_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		Load(res); | ||||||
|  | 		Crop(crop_rect); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::Sprite(const std::wstring & file_name) | ||||||
|  | 		: image_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		Load(file_name); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::Sprite(const std::wstring & file_name, const Rect & crop_rect) | ||||||
|  | 		: image_(nullptr) | ||||||
|  | 	{ | ||||||
|  | 		Load(file_name); | ||||||
|  | 		Crop(crop_rect); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Sprite::~Sprite() | ||||||
|  | 	{ | ||||||
|  | 		SafeRelease(image_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Sprite::Load(Image * image) | ||||||
|  | 	{ | ||||||
|  | 		if (image) | ||||||
| 		{ | 		{ | ||||||
| 			image_->Release(); | 			if (image_) | ||||||
|  | 			{ | ||||||
|  | 				image_->Release(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			image_ = image; | ||||||
|  | 			image_->Retain(); | ||||||
|  | 
 | ||||||
|  | 			Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Sprite::Load(Resource& res) | ||||||
|  | 	{ | ||||||
|  | 		if (!image_) | ||||||
|  | 		{ | ||||||
|  | 			image_ = new Image(); | ||||||
|  | 			image_->Retain(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		image_ = image; | 		if (image_->Load(res)) | ||||||
| 		image_->Retain(); | 		{ | ||||||
| 
 | 			Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | 			return true; | ||||||
| 		return true; | 		} | ||||||
| 	} | 		return false; | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Sprite::Load(Resource& res) |  | ||||||
| { |  | ||||||
| 	if (!image_) |  | ||||||
| 	{ |  | ||||||
| 		image_ = new Image(); |  | ||||||
| 		image_->Retain(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (image_->Load(res)) | 	bool Sprite::Load(const std::wstring & file_name) | ||||||
| 	{ | 	{ | ||||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | 		if (!image_) | ||||||
| 		return true; | 		{ | ||||||
| 	} | 			image_ = new Image(); | ||||||
| 	return false; | 			image_->Retain(); | ||||||
| } | 		} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Sprite::Load(const std::wstring & file_name) | 		if (image_->Load(file_name)) | ||||||
| { | 		{ | ||||||
| 	if (!image_) | 			Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||||
| 	{ | 			return true; | ||||||
| 		image_ = new Image(); | 		} | ||||||
| 		image_->Retain(); | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (image_->Load(file_name)) | 	void Sprite::Crop(const Rect& crop_rect) | ||||||
| 	{ | 	{ | ||||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | 		image_->Crop(crop_rect); | ||||||
| 		return true; | 		Node::SetSize( | ||||||
| 	} | 			std::min(std::max(crop_rect.size.width, 0.f), image_->GetSourceWidth() - image_->GetCropX()), | ||||||
| 	return false; | 			std::min(std::max(crop_rect.size.height, 0.f), image_->GetSourceHeight() - image_->GetCropY()) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sprite::Crop(const Rect& crop_rect) |  | ||||||
| { |  | ||||||
| 	image_->Crop(crop_rect); |  | ||||||
| 	Node::SetSize( |  | ||||||
| 		std::min(std::max(crop_rect.size.width, 0.f), image_->GetSourceWidth() - image_->GetCropX()), |  | ||||||
| 		std::min(std::max(crop_rect.size.height, 0.f), image_->GetSourceHeight() - image_->GetCropY()) |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Image * easy2d::Sprite::GetImage() const |  | ||||||
| { |  | ||||||
| 	return image_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Sprite::OnDraw() const |  | ||||||
| { |  | ||||||
| 	if (image_ && image_->GetBitmap()) |  | ||||||
| 	{ |  | ||||||
| 		auto crop_pos = image_->GetCropPos(); |  | ||||||
| 		Device::GetGraphics()->GetRenderTarget()->DrawBitmap( |  | ||||||
| 			image_->GetBitmap(), |  | ||||||
| 			D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height), |  | ||||||
| 			GetDisplayOpacity(), |  | ||||||
| 			D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, |  | ||||||
| 			D2D1::RectF( |  | ||||||
| 				crop_pos.x, |  | ||||||
| 				crop_pos.y, |  | ||||||
| 				crop_pos.y + GetTransform().size.width, |  | ||||||
| 				crop_pos.y + GetTransform().size.height |  | ||||||
| 			) |  | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| } | 
 | ||||||
|  | 	Image * Sprite::GetImage() const | ||||||
|  | 	{ | ||||||
|  | 		return image_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Sprite::OnDraw() const | ||||||
|  | 	{ | ||||||
|  | 		if (image_ && image_->GetBitmap()) | ||||||
|  | 		{ | ||||||
|  | 			auto crop_pos = image_->GetCropPos(); | ||||||
|  | 			Device::GetGraphics()->GetRenderTarget()->DrawBitmap( | ||||||
|  | 				image_->GetBitmap(), | ||||||
|  | 				D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height), | ||||||
|  | 				GetDisplayOpacity(), | ||||||
|  | 				D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, | ||||||
|  | 				D2D1::RectF( | ||||||
|  | 					crop_pos.x, | ||||||
|  | 					crop_pos.y, | ||||||
|  | 					crop_pos.y + GetTransform().size.width, | ||||||
|  | 					crop_pos.y + GetTransform().size.height | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,89 +21,92 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Task::Task(const Callback & func, const std::wstring & name) | namespace easy2d | ||||||
| 	: running_(true) |  | ||||||
| 	, stopped_(false) |  | ||||||
| 	, run_times_(0) |  | ||||||
| 	, total_times_(-1) |  | ||||||
| 	, delay_() |  | ||||||
| 	, callback_(func) |  | ||||||
| 	, name_(name) |  | ||||||
| { | { | ||||||
| } | 	Task::Task(const Callback & func, const std::wstring & name) | ||||||
| 
 | 		: running_(true) | ||||||
| easy2d::Task::Task(const Callback & func, float delay, int times, const std::wstring & name) | 		, stopped_(false) | ||||||
| 	: running_(true) | 		, run_times_(0) | ||||||
| 	, stopped_(false) | 		, total_times_(-1) | ||||||
| 	, run_times_(0) | 		, delay_() | ||||||
| 	, delay_(Duration::Second * std::max(delay, 0.f)) | 		, callback_(func) | ||||||
| 	, total_times_(times) | 		, name_(name) | ||||||
| 	, callback_(func) |  | ||||||
| 	, name_(name) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Task::Start() |  | ||||||
| { |  | ||||||
| 	running_ = true; |  | ||||||
| 	last_time_ = Time::Now(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Task::Stop() |  | ||||||
| { |  | ||||||
| 	running_ = false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Task::Update() |  | ||||||
| { |  | ||||||
| 	if (total_times_ == 0) |  | ||||||
| 	{ | 	{ | ||||||
| 		stopped_ = true; |  | ||||||
| 		return; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	++run_times_; | 	Task::Task(const Callback & func, float delay, int times, const std::wstring & name) | ||||||
| 	last_time_ += delay_; | 		: running_(true) | ||||||
| 
 | 		, stopped_(false) | ||||||
| 	if (callback_) | 		, run_times_(0) | ||||||
|  | 		, delay_(Duration::Second * std::max(delay, 0.f)) | ||||||
|  | 		, total_times_(times) | ||||||
|  | 		, callback_(func) | ||||||
|  | 		, name_(name) | ||||||
| 	{ | 	{ | ||||||
| 		callback_(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (run_times_ == total_times_) | 	void Task::Start() | ||||||
| 	{ | 	{ | ||||||
| 		stopped_ = true; | 		running_ = true; | ||||||
| 		return; | 		last_time_ = Time::Now(); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Task::ResetTime() | 	void Task::Stop() | ||||||
| { |  | ||||||
| 	last_time_ = Time::Now(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Task::IsReady() const |  | ||||||
| { |  | ||||||
| 	if (running_) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (delay_.Milliseconds() == 0) | 		running_ = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Task::Update() | ||||||
|  | 	{ | ||||||
|  | 		if (total_times_ == 0) | ||||||
| 		{ | 		{ | ||||||
| 			return true; | 			stopped_ = true; | ||||||
|  | 			return; | ||||||
| 		} | 		} | ||||||
| 		if (Time::Now() - last_time_ >= delay_) | 
 | ||||||
|  | 		++run_times_; | ||||||
|  | 		last_time_ += delay_; | ||||||
|  | 
 | ||||||
|  | 		if (callback_) | ||||||
| 		{ | 		{ | ||||||
| 			return true; | 			callback_(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (run_times_ == total_times_) | ||||||
|  | 		{ | ||||||
|  | 			stopped_ = true; | ||||||
|  | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Task::IsRunning() const | 	void Task::ResetTime() | ||||||
| { | 	{ | ||||||
| 	return running_; | 		last_time_ = Time::Now(); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| const std::wstring& easy2d::Task::GetName() const | 	bool Task::IsReady() const | ||||||
| { | 	{ | ||||||
| 	return name_; | 		if (running_) | ||||||
| } | 		{ | ||||||
|  | 			if (delay_.Milliseconds() == 0) | ||||||
|  | 			{ | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			if (Time::Now() - last_time_ >= delay_) | ||||||
|  | 			{ | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Task::IsRunning() const | ||||||
|  | 	{ | ||||||
|  | 		return running_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const std::wstring& Task::GetName() const | ||||||
|  | 	{ | ||||||
|  | 		return name_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,449 +21,453 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| //-------------------------------------------------------
 |  | ||||||
| // Style
 |  | ||||||
| //-------------------------------------------------------
 |  | ||||||
| 
 | 
 | ||||||
| easy2d::Text::Style::Style() | namespace easy2d | ||||||
| 	: color(Color::White) |  | ||||||
| 	, alignment(Align::Left) |  | ||||||
| 	, wrap(false) |  | ||||||
| 	, wrap_width(0.f) |  | ||||||
| 	, line_spacing(0.f) |  | ||||||
| 	, underline(false) |  | ||||||
| 	, strikethrough(false) |  | ||||||
| 	, outline(true) |  | ||||||
| 	, outline_color(Color(Color::Black, 0.5)) |  | ||||||
| 	, outline_width(1.f) |  | ||||||
| 	, outline_stroke(Stroke::Round) |  | ||||||
| {} |  | ||||||
| 
 |  | ||||||
| easy2d::Text::Style::Style( |  | ||||||
| 	Color color, |  | ||||||
| 	Align alignment, |  | ||||||
| 	bool wrap, |  | ||||||
| 	float wrap_width, |  | ||||||
| 	float line_spacing, |  | ||||||
| 	bool underline, |  | ||||||
| 	bool strikethrough, |  | ||||||
| 	bool outline, |  | ||||||
| 	Color outline_color, |  | ||||||
| 	float outline_width, |  | ||||||
| 	Stroke outline_stroke |  | ||||||
| ) |  | ||||||
| 	: color(color) |  | ||||||
| 	, alignment(alignment) |  | ||||||
| 	, wrap(wrap) |  | ||||||
| 	, wrap_width(wrap_width) |  | ||||||
| 	, line_spacing(line_spacing) |  | ||||||
| 	, underline(underline) |  | ||||||
| 	, strikethrough(strikethrough) |  | ||||||
| 	, outline(outline) |  | ||||||
| 	, outline_color(outline_color) |  | ||||||
| 	, outline_width(outline_width) |  | ||||||
| 	, outline_stroke(outline_stroke) |  | ||||||
| {} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| //-------------------------------------------------------
 |  | ||||||
| // Text
 |  | ||||||
| //-------------------------------------------------------
 |  | ||||||
| 
 |  | ||||||
| easy2d::Text::Text() |  | ||||||
| 	: font_() |  | ||||||
| 	, style_() |  | ||||||
| 	, text_layout_(nullptr) |  | ||||||
| 	, text_format_(nullptr) |  | ||||||
| { | { | ||||||
| } | 	//-------------------------------------------------------
 | ||||||
|  | 	// Style
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| easy2d::Text::Text(const std::wstring & text, const Font & font, const Style & style) | 	Text::Style::Style() | ||||||
| 	: font_(font) | 		: color(Color::White) | ||||||
| 	, style_(style) | 		, alignment(Align::Left) | ||||||
| 	, text_layout_(nullptr) | 		, wrap(false) | ||||||
| 	, text_format_(nullptr) | 		, wrap_width(0.f) | ||||||
| 	, text_(text) | 		, line_spacing(0.f) | ||||||
| { | 		, underline(false) | ||||||
| 	Reset(); | 		, strikethrough(false) | ||||||
| } | 		, outline(true) | ||||||
|  | 		, outline_color(Color(Color::Black, 0.5)) | ||||||
|  | 		, outline_width(1.f) | ||||||
|  | 		, outline_stroke(Stroke::Round) | ||||||
|  | 	{} | ||||||
| 
 | 
 | ||||||
| easy2d::Text::~Text() | 	Text::Style::Style( | ||||||
| { | 		Color color, | ||||||
| 	SafeRelease(text_format_); | 		Align alignment, | ||||||
| 	SafeRelease(text_layout_); | 		bool wrap, | ||||||
| } | 		float wrap_width, | ||||||
|  | 		float line_spacing, | ||||||
|  | 		bool underline, | ||||||
|  | 		bool strikethrough, | ||||||
|  | 		bool outline, | ||||||
|  | 		Color outline_color, | ||||||
|  | 		float outline_width, | ||||||
|  | 		Stroke outline_stroke | ||||||
|  | 	) | ||||||
|  | 		: color(color) | ||||||
|  | 		, alignment(alignment) | ||||||
|  | 		, wrap(wrap) | ||||||
|  | 		, wrap_width(wrap_width) | ||||||
|  | 		, line_spacing(line_spacing) | ||||||
|  | 		, underline(underline) | ||||||
|  | 		, strikethrough(strikethrough) | ||||||
|  | 		, outline(outline) | ||||||
|  | 		, outline_color(outline_color) | ||||||
|  | 		, outline_width(outline_width) | ||||||
|  | 		, outline_stroke(outline_stroke) | ||||||
|  | 	{} | ||||||
| 
 | 
 | ||||||
| const std::wstring& easy2d::Text::GetText() const |  | ||||||
| { |  | ||||||
| 	return text_; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const easy2d::Font& easy2d::Text::GetFont() const |  | ||||||
| { |  | ||||||
| 	return font_; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const easy2d::Text::Style& easy2d::Text::GetStyle() const | 	//-------------------------------------------------------
 | ||||||
| { | 	// Text
 | ||||||
| 	return style_; | 	//-------------------------------------------------------
 | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const std::wstring& easy2d::Text::GetFontFamily() const | 	Text::Text() | ||||||
| { | 		: font_() | ||||||
| 	return font_.family; | 		, style_() | ||||||
| } | 		, text_layout_(nullptr) | ||||||
| 
 | 		, text_format_(nullptr) | ||||||
| float easy2d::Text::GetFontSize() const |  | ||||||
| { |  | ||||||
| 	return font_.size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| UINT easy2d::Text::GetFontWeight() const |  | ||||||
| { |  | ||||||
| 	return font_.weight; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const easy2d::Color& easy2d::Text::GetColor() const |  | ||||||
| { |  | ||||||
| 	return style_.color; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const easy2d::Color& easy2d::Text::GetOutlineColor() const |  | ||||||
| { |  | ||||||
| 	return style_.outline_color; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Text::GetOutlineWidth() const |  | ||||||
| { |  | ||||||
| 	return style_.outline_width; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Stroke easy2d::Text::GetOutlineStroke() const |  | ||||||
| { |  | ||||||
| 	return style_.outline_stroke; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int easy2d::Text::GetLineCount() const |  | ||||||
| { |  | ||||||
| 	if (text_layout_) |  | ||||||
| 	{ | 	{ | ||||||
| 		DWRITE_TEXT_METRICS metrics; |  | ||||||
| 		text_layout_->GetMetrics(&metrics); |  | ||||||
| 		return static_cast<int>(metrics.lineCount); |  | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	Text::Text(const std::wstring & text, const Font & font, const Style & style) | ||||||
|  | 		: font_(font) | ||||||
|  | 		, style_(style) | ||||||
|  | 		, text_layout_(nullptr) | ||||||
|  | 		, text_format_(nullptr) | ||||||
|  | 		, text_(text) | ||||||
| 	{ | 	{ | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Text::IsItalic() const |  | ||||||
| { |  | ||||||
| 	return font_.italic; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Text::strikethrough() const |  | ||||||
| { |  | ||||||
| 	return style_.strikethrough; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Text::underline() const |  | ||||||
| { |  | ||||||
| 	return style_.underline; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Text::outline() const |  | ||||||
| { |  | ||||||
| 	return style_.outline; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetText(const std::wstring& text) |  | ||||||
| { |  | ||||||
| 	text_ = text; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetStyle(const Style& style) |  | ||||||
| { |  | ||||||
| 	style_ = style; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetFont(const Font & font) |  | ||||||
| { |  | ||||||
| 	font_ = font; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetFontFamily(const std::wstring& family) |  | ||||||
| { |  | ||||||
| 	font_.family = family; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetFontSize(float size) |  | ||||||
| { |  | ||||||
| 	font_.size = size; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetFontWeight(UINT weight) |  | ||||||
| { |  | ||||||
| 	font_.weight = weight; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetColor(Color color) |  | ||||||
| { |  | ||||||
| 	style_.color = color; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetItalic(bool value) |  | ||||||
| { |  | ||||||
| 	font_.italic = value; |  | ||||||
| 	Reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetWrapEnabled(bool wrap) |  | ||||||
| { |  | ||||||
| 	if (style_.wrap != wrap) |  | ||||||
| 	{ |  | ||||||
| 		style_.wrap = wrap; |  | ||||||
| 		Reset(); | 		Reset(); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetWrapWidth(float wrap_width) | 	Text::~Text() | ||||||
| { |  | ||||||
| 	if (style_.wrap_width != wrap_width) |  | ||||||
| 	{ | 	{ | ||||||
| 		style_.wrap_width = std::max(wrap_width, 0.f); | 		SafeRelease(text_format_); | ||||||
|  | 		SafeRelease(text_layout_); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		if (style_.wrap) | 	const std::wstring& Text::GetText() const | ||||||
|  | 	{ | ||||||
|  | 		return text_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Font& Text::GetFont() const | ||||||
|  | 	{ | ||||||
|  | 		return font_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Text::Style& Text::GetStyle() const | ||||||
|  | 	{ | ||||||
|  | 		return style_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const std::wstring& Text::GetFontFamily() const | ||||||
|  | 	{ | ||||||
|  | 		return font_.family; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Text::GetFontSize() const | ||||||
|  | 	{ | ||||||
|  | 		return font_.size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	UINT Text::GetFontWeight() const | ||||||
|  | 	{ | ||||||
|  | 		return font_.weight; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Color& Text::GetColor() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.color; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const Color& Text::GetOutlineColor() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.outline_color; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Text::GetOutlineWidth() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.outline_width; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Stroke Text::GetOutlineStroke() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.outline_stroke; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int Text::GetLineCount() const | ||||||
|  | 	{ | ||||||
|  | 		if (text_layout_) | ||||||
| 		{ | 		{ | ||||||
|  | 			DWRITE_TEXT_METRICS metrics; | ||||||
|  | 			text_layout_->GetMetrics(&metrics); | ||||||
|  | 			return static_cast<int>(metrics.lineCount); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Text::IsItalic() const | ||||||
|  | 	{ | ||||||
|  | 		return font_.italic; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Text::strikethrough() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.strikethrough; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Text::underline() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.underline; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Text::outline() const | ||||||
|  | 	{ | ||||||
|  | 		return style_.outline; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetText(const std::wstring& text) | ||||||
|  | 	{ | ||||||
|  | 		text_ = text; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetStyle(const Style& style) | ||||||
|  | 	{ | ||||||
|  | 		style_ = style; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetFont(const Font & font) | ||||||
|  | 	{ | ||||||
|  | 		font_ = font; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetFontFamily(const std::wstring& family) | ||||||
|  | 	{ | ||||||
|  | 		font_.family = family; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetFontSize(float size) | ||||||
|  | 	{ | ||||||
|  | 		font_.size = size; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetFontWeight(UINT weight) | ||||||
|  | 	{ | ||||||
|  | 		font_.weight = weight; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetColor(Color color) | ||||||
|  | 	{ | ||||||
|  | 		style_.color = color; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetItalic(bool value) | ||||||
|  | 	{ | ||||||
|  | 		font_.italic = value; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetWrapEnabled(bool wrap) | ||||||
|  | 	{ | ||||||
|  | 		if (style_.wrap != wrap) | ||||||
|  | 		{ | ||||||
|  | 			style_.wrap = wrap; | ||||||
| 			Reset(); | 			Reset(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetLineSpacing(float line_spacing) | 	void Text::SetWrapWidth(float wrap_width) | ||||||
| { |  | ||||||
| 	if (style_.line_spacing != line_spacing) |  | ||||||
| 	{ | 	{ | ||||||
| 		style_.line_spacing = line_spacing; | 		if (style_.wrap_width != wrap_width) | ||||||
| 		Reset(); | 		{ | ||||||
|  | 			style_.wrap_width = std::max(wrap_width, 0.f); | ||||||
|  | 
 | ||||||
|  | 			if (style_.wrap) | ||||||
|  | 			{ | ||||||
|  | 				Reset(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetAlignment(Align align) | 	void Text::SetLineSpacing(float line_spacing) | ||||||
| { |  | ||||||
| 	if (style_.alignment != align) |  | ||||||
| 	{ | 	{ | ||||||
| 		style_.alignment = align; | 		if (style_.line_spacing != line_spacing) | ||||||
| 		Reset(); | 		{ | ||||||
|  | 			style_.line_spacing = line_spacing; | ||||||
|  | 			Reset(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetUnderline(bool underline) | 	void Text::SetAlignment(Align align) | ||||||
| { |  | ||||||
| 	if (style_.underline != underline) |  | ||||||
| 	{ | 	{ | ||||||
| 		style_.underline = underline; | 		if (style_.alignment != align) | ||||||
| 		if (!text_format_) | 		{ | ||||||
| 			CreateFormat(); | 			style_.alignment = align; | ||||||
|  | 			Reset(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetUnderline(bool underline) | ||||||
|  | 	{ | ||||||
|  | 		if (style_.underline != underline) | ||||||
|  | 		{ | ||||||
|  | 			style_.underline = underline; | ||||||
|  | 			if (!text_format_) | ||||||
|  | 				CreateFormat(); | ||||||
|  | 			CreateLayout(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetStrikethrough(bool strikethrough) | ||||||
|  | 	{ | ||||||
|  | 		if (style_.strikethrough != strikethrough) | ||||||
|  | 		{ | ||||||
|  | 			style_.strikethrough = strikethrough; | ||||||
|  | 			if (!text_format_) | ||||||
|  | 				CreateFormat(); | ||||||
|  | 			CreateLayout(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetOutline(bool outline) | ||||||
|  | 	{ | ||||||
|  | 		style_.outline = outline; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetOutlineColor(Color outline_color) | ||||||
|  | 	{ | ||||||
|  | 		style_.outline_color = outline_color; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetOutlineWidth(float outline_width) | ||||||
|  | 	{ | ||||||
|  | 		style_.outline_width = outline_width; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::SetOutlineStroke(Stroke outline_stroke) | ||||||
|  | 	{ | ||||||
|  | 		style_.outline_stroke = outline_stroke; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::OnDraw() const | ||||||
|  | 	{ | ||||||
|  | 		if (text_layout_) | ||||||
|  | 		{ | ||||||
|  | 			auto graphics = Device::GetGraphics(); | ||||||
|  | 			// 创建文本区域
 | ||||||
|  | 			D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height); | ||||||
|  | 			// 设置画刷颜色和透明度
 | ||||||
|  | 			graphics->GetSolidBrush()->SetOpacity(GetDisplayOpacity()); | ||||||
|  | 			// 获取文本渲染器
 | ||||||
|  | 			auto text_renderer = graphics->GetTextRender(); | ||||||
|  | 			graphics->SetTextRendererStyle( | ||||||
|  | 				style_.color, | ||||||
|  | 				style_.outline, | ||||||
|  | 				style_.outline_color, | ||||||
|  | 				style_.outline_width, | ||||||
|  | 				style_.outline_stroke | ||||||
|  | 			); | ||||||
|  | 			text_layout_->Draw(nullptr, text_renderer, 0, 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::Reset() | ||||||
|  | 	{ | ||||||
|  | 		// 创建文字格式化
 | ||||||
|  | 		CreateFormat(); | ||||||
|  | 		// 创建文字布局
 | ||||||
| 		CreateLayout(); | 		CreateLayout(); | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetStrikethrough(bool strikethrough) | 	void Text::CreateFormat() | ||||||
| { |  | ||||||
| 	if (style_.strikethrough != strikethrough) |  | ||||||
| 	{ | 	{ | ||||||
| 		style_.strikethrough = strikethrough; | 		SafeRelease(text_format_); | ||||||
| 		if (!text_format_) |  | ||||||
| 			CreateFormat(); |  | ||||||
| 		CreateLayout(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Text::SetOutline(bool outline) |  | ||||||
| { |  | ||||||
| 	style_.outline = outline; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetOutlineColor(Color outline_color) |  | ||||||
| { |  | ||||||
| 	style_.outline_color = outline_color; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetOutlineWidth(float outline_width) |  | ||||||
| { |  | ||||||
| 	style_.outline_width = outline_width; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::SetOutlineStroke(Stroke outline_stroke) |  | ||||||
| { |  | ||||||
| 	style_.outline_stroke = outline_stroke; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::OnDraw() const |  | ||||||
| { |  | ||||||
| 	if (text_layout_) |  | ||||||
| 	{ |  | ||||||
| 		auto graphics = Device::GetGraphics(); |  | ||||||
| 		// 创建文本区域
 |  | ||||||
| 		D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height); |  | ||||||
| 		// 设置画刷颜色和透明度
 |  | ||||||
| 		graphics->GetSolidBrush()->SetOpacity(GetDisplayOpacity()); |  | ||||||
| 		// 获取文本渲染器
 |  | ||||||
| 		auto text_renderer = graphics->GetTextRender(); |  | ||||||
| 		graphics->SetTextRendererStyle( |  | ||||||
| 			style_.color, |  | ||||||
| 			style_.outline, |  | ||||||
| 			style_.outline_color, |  | ||||||
| 			style_.outline_width, |  | ||||||
| 			style_.outline_stroke |  | ||||||
| 		); |  | ||||||
| 		text_layout_->Draw(nullptr, text_renderer, 0, 0); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::Reset() |  | ||||||
| { |  | ||||||
| 	// 创建文字格式化
 |  | ||||||
| 	CreateFormat(); |  | ||||||
| 	// 创建文字布局
 |  | ||||||
| 	CreateLayout(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::CreateFormat() |  | ||||||
| { |  | ||||||
| 	SafeRelease(text_format_); |  | ||||||
| 
 |  | ||||||
| 	ThrowIfFailed( |  | ||||||
| 		Device::GetGraphics()->GetWriteFactory()->CreateTextFormat( |  | ||||||
| 			font_.family.c_str(), |  | ||||||
| 			nullptr, |  | ||||||
| 			DWRITE_FONT_WEIGHT(font_.weight), |  | ||||||
| 			font_.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, |  | ||||||
| 			DWRITE_FONT_STRETCH_NORMAL, |  | ||||||
| 			font_.size, |  | ||||||
| 			L"", |  | ||||||
| 			&text_format_ |  | ||||||
| 		) |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	// 设置文字对齐方式
 |  | ||||||
| 	text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment)); |  | ||||||
| 
 |  | ||||||
| 	// 设置行间距
 |  | ||||||
| 	if (style_.line_spacing == 0.f) |  | ||||||
| 	{ |  | ||||||
| 		text_format_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		text_format_->SetLineSpacing( |  | ||||||
| 			DWRITE_LINE_SPACING_METHOD_UNIFORM, |  | ||||||
| 			style_.line_spacing, |  | ||||||
| 			style_.line_spacing * 0.8f |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// 打开文本自动换行时,设置换行属性
 |  | ||||||
| 	if (style_.wrap) |  | ||||||
| 	{ |  | ||||||
| 		text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Text::CreateLayout() |  | ||||||
| { |  | ||||||
| 	SafeRelease(text_layout_); |  | ||||||
| 
 |  | ||||||
| 	// 文本为空字符串时,重置属性
 |  | ||||||
| 	if (text_.empty()) |  | ||||||
| 	{ |  | ||||||
| 		this->SetSize(0, 0); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (text_format_ == nullptr) |  | ||||||
| 	{ |  | ||||||
| 		E2D_WARNING("Text::CreateLayout failed! text_format_ NULL pointer exception."); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	UINT32 length = static_cast<UINT32>(text_.size()); |  | ||||||
| 	auto writeFactory = Device::GetGraphics()->GetWriteFactory(); |  | ||||||
| 
 |  | ||||||
| 	// 对文本自动换行情况下进行处理
 |  | ||||||
| 	if (style_.wrap) |  | ||||||
| 	{ |  | ||||||
| 		ThrowIfFailed( | 		ThrowIfFailed( | ||||||
| 			writeFactory->CreateTextLayout( | 			Device::GetGraphics()->GetWriteFactory()->CreateTextFormat( | ||||||
| 				text_.c_str(), | 				font_.family.c_str(), | ||||||
| 				length, | 				nullptr, | ||||||
| 				text_format_, | 				DWRITE_FONT_WEIGHT(font_.weight), | ||||||
| 				style_.wrap_width, | 				font_.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, | ||||||
| 				0, | 				DWRITE_FONT_STRETCH_NORMAL, | ||||||
| 				&text_layout_ | 				font_.size, | ||||||
| 			) | 				L"", | ||||||
| 		); | 				&text_format_ | ||||||
| 		// 获取文本布局的宽度和高度
 |  | ||||||
| 		DWRITE_TEXT_METRICS metrics; |  | ||||||
| 		text_layout_->GetMetrics(&metrics); |  | ||||||
| 		// 重设文本宽高
 |  | ||||||
| 		this->SetSize(metrics.layoutWidth, metrics.height); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		// 为防止文本对齐问题,根据先创建 layout 以获取宽度
 |  | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			writeFactory->CreateTextLayout( |  | ||||||
| 				text_.c_str(), |  | ||||||
| 				length, |  | ||||||
| 				text_format_, |  | ||||||
| 				0, |  | ||||||
| 				0, |  | ||||||
| 				&text_layout_ |  | ||||||
| 			) | 			) | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 获取文本布局的宽度和高度
 | 		// 设置文字对齐方式
 | ||||||
| 		DWRITE_TEXT_METRICS metrics; | 		text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment)); | ||||||
| 		text_layout_->GetMetrics(&metrics); |  | ||||||
| 		// 重设文本宽高
 |  | ||||||
| 		this->SetSize(metrics.width, metrics.height); |  | ||||||
| 
 | 
 | ||||||
| 		// 重新创建 layout
 | 		// 设置行间距
 | ||||||
|  | 		if (style_.line_spacing == 0.f) | ||||||
|  | 		{ | ||||||
|  | 			text_format_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			text_format_->SetLineSpacing( | ||||||
|  | 				DWRITE_LINE_SPACING_METHOD_UNIFORM, | ||||||
|  | 				style_.line_spacing, | ||||||
|  | 				style_.line_spacing * 0.8f | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 打开文本自动换行时,设置换行属性
 | ||||||
|  | 		if (style_.wrap) | ||||||
|  | 		{ | ||||||
|  | 			text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Text::CreateLayout() | ||||||
|  | 	{ | ||||||
| 		SafeRelease(text_layout_); | 		SafeRelease(text_layout_); | ||||||
| 		ThrowIfFailed( |  | ||||||
| 			writeFactory->CreateTextLayout( |  | ||||||
| 				text_.c_str(), |  | ||||||
| 				length, |  | ||||||
| 				text_format_, |  | ||||||
| 				GetTransform().size.width, |  | ||||||
| 				0, |  | ||||||
| 				&text_layout_ |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	// 添加下划线和删除线
 | 		// 文本为空字符串时,重置属性
 | ||||||
| 	DWRITE_TEXT_RANGE Range = { 0, length }; | 		if (text_.empty()) | ||||||
| 	if (style_.underline) | 		{ | ||||||
| 	{ | 			this->SetSize(0, 0); | ||||||
| 		text_layout_->SetUnderline(true, Range); | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (text_format_ == nullptr) | ||||||
|  | 		{ | ||||||
|  | 			E2D_WARNING("Text::CreateLayout failed! text_format_ NULL pointer exception."); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		UINT32 length = static_cast<UINT32>(text_.size()); | ||||||
|  | 		auto writeFactory = Device::GetGraphics()->GetWriteFactory(); | ||||||
|  | 
 | ||||||
|  | 		// 对文本自动换行情况下进行处理
 | ||||||
|  | 		if (style_.wrap) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				writeFactory->CreateTextLayout( | ||||||
|  | 					text_.c_str(), | ||||||
|  | 					length, | ||||||
|  | 					text_format_, | ||||||
|  | 					style_.wrap_width, | ||||||
|  | 					0, | ||||||
|  | 					&text_layout_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 			// 获取文本布局的宽度和高度
 | ||||||
|  | 			DWRITE_TEXT_METRICS metrics; | ||||||
|  | 			text_layout_->GetMetrics(&metrics); | ||||||
|  | 			// 重设文本宽高
 | ||||||
|  | 			this->SetSize(metrics.layoutWidth, metrics.height); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			// 为防止文本对齐问题,根据先创建 layout 以获取宽度
 | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				writeFactory->CreateTextLayout( | ||||||
|  | 					text_.c_str(), | ||||||
|  | 					length, | ||||||
|  | 					text_format_, | ||||||
|  | 					0, | ||||||
|  | 					0, | ||||||
|  | 					&text_layout_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			// 获取文本布局的宽度和高度
 | ||||||
|  | 			DWRITE_TEXT_METRICS metrics; | ||||||
|  | 			text_layout_->GetMetrics(&metrics); | ||||||
|  | 			// 重设文本宽高
 | ||||||
|  | 			this->SetSize(metrics.width, metrics.height); | ||||||
|  | 
 | ||||||
|  | 			// 重新创建 layout
 | ||||||
|  | 			SafeRelease(text_layout_); | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				writeFactory->CreateTextLayout( | ||||||
|  | 					text_.c_str(), | ||||||
|  | 					length, | ||||||
|  | 					text_format_, | ||||||
|  | 					GetTransform().size.width, | ||||||
|  | 					0, | ||||||
|  | 					&text_layout_ | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 添加下划线和删除线
 | ||||||
|  | 		DWRITE_TEXT_RANGE Range = { 0, length }; | ||||||
|  | 		if (style_.underline) | ||||||
|  | 		{ | ||||||
|  | 			text_layout_->SetUnderline(true, Range); | ||||||
|  | 		} | ||||||
|  | 		if (style_.strikethrough) | ||||||
|  | 		{ | ||||||
|  | 			text_layout_->SetStrikethrough(true, Range); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	if (style_.strikethrough) | } | ||||||
| 	{ |  | ||||||
| 		text_layout_->SetStrikethrough(true, Range); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -21,126 +21,129 @@ | ||||||
| #include "..\e2dtool.h" | #include "..\e2dtool.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Data::Data(const std::wstring & key, const std::wstring & field) | namespace easy2d | ||||||
| 	: key_(key) |  | ||||||
| 	, field_(field) |  | ||||||
| 	, data_path_(Path::GetDataPath()) |  | ||||||
| { | { | ||||||
| } | 	Data::Data(const std::wstring & key, const std::wstring & field) | ||||||
|  | 		: key_(key) | ||||||
|  | 		, field_(field) | ||||||
|  | 		, data_path_(Path::GetDataPath()) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::Exists() const | 	bool Data::Exists() const | ||||||
| { | 	{ | ||||||
| 	wchar_t temp[256] = { 0 }; | 		wchar_t temp[256] = { 0 }; | ||||||
| 	::GetPrivateProfileStringW( | 		::GetPrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		L"", | 			L"", | ||||||
| 		temp, | 			temp, | ||||||
| 		255, | 			255, | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return temp[0] == L'\0'; | 		return temp[0] == L'\0'; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::SaveInt(int value) | 	bool Data::SaveInt(int value) | ||||||
| { | 	{ | ||||||
| 	BOOL ret = ::WritePrivateProfileStringW( | 		BOOL ret = ::WritePrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		std::to_wstring(value).c_str(), | 			std::to_wstring(value).c_str(), | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return ret == TRUE; | 		return ret == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::SaveFloat(float value) | 	bool Data::SaveFloat(float value) | ||||||
| { | 	{ | ||||||
| 	BOOL ret = ::WritePrivateProfileStringW( | 		BOOL ret = ::WritePrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		std::to_wstring(value).c_str(), | 			std::to_wstring(value).c_str(), | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return ret == TRUE; | 		return ret == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::SaveDouble(double value) | 	bool Data::SaveDouble(double value) | ||||||
| { | 	{ | ||||||
| 	BOOL ret = ::WritePrivateProfileStringW( | 		BOOL ret = ::WritePrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		std::to_wstring(value).c_str(), | 			std::to_wstring(value).c_str(), | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return ret == TRUE; | 		return ret == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::SaveBool(bool value) | 	bool Data::SaveBool(bool value) | ||||||
| { | 	{ | ||||||
| 	BOOL ret = ::WritePrivateProfileStringW( | 		BOOL ret = ::WritePrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		(value ? L"1" : L"0"), | 			(value ? L"1" : L"0"), | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return ret == TRUE; | 		return ret == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::SaveString(const std::wstring& value) | 	bool Data::SaveString(const std::wstring& value) | ||||||
| { | 	{ | ||||||
| 	BOOL ret = ::WritePrivateProfileStringW( | 		BOOL ret = ::WritePrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		value.c_str(), | 			value.c_str(), | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return ret == TRUE; | 		return ret == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| int easy2d::Data::GetInt() const | 	int Data::GetInt() const | ||||||
| { | 	{ | ||||||
| 	return ::GetPrivateProfileIntW( | 		return ::GetPrivateProfileIntW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		0, | 			0, | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Data::GetFloat() const | 	float Data::GetFloat() const | ||||||
| { | 	{ | ||||||
| 	wchar_t temp[32] = { 0 }; | 		wchar_t temp[32] = { 0 }; | ||||||
| 	::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | 		::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||||
| 	return std::stof(temp); | 		return std::stof(temp); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| double easy2d::Data::GetDouble() const | 	double Data::GetDouble() const | ||||||
| { | 	{ | ||||||
| 	wchar_t temp[32] = { 0 }; | 		wchar_t temp[32] = { 0 }; | ||||||
| 	::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | 		::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||||
| 	return std::stod(temp); | 		return std::stod(temp); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Data::GetBool() const | 	bool Data::GetBool() const | ||||||
| { | 	{ | ||||||
| 	int nValue = ::GetPrivateProfileIntW( | 		int nValue = ::GetPrivateProfileIntW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		0, | 			0, | ||||||
| 		data_path_.c_str()); | 			data_path_.c_str()); | ||||||
| 	return nValue == TRUE; | 		return nValue == TRUE; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| std::wstring easy2d::Data::GetString() | 	std::wstring Data::GetString() | ||||||
| { | 	{ | ||||||
| 	wchar_t temp[256] = { 0 }; | 		wchar_t temp[256] = { 0 }; | ||||||
| 	::GetPrivateProfileStringW( | 		::GetPrivateProfileStringW( | ||||||
| 		field_.c_str(), | 			field_.c_str(), | ||||||
| 		key_.c_str(), | 			key_.c_str(), | ||||||
| 		L"", | 			L"", | ||||||
| 		temp, | 			temp, | ||||||
| 		255, | 			255, | ||||||
| 		data_path_.c_str() | 			data_path_.c_str() | ||||||
| 	); | 		); | ||||||
| 	return temp; | 		return temp; | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -23,270 +23,273 @@ | ||||||
| #include <cwctype> | #include <cwctype> | ||||||
| #include <shobjidl.h>  | #include <shobjidl.h>  | ||||||
| 
 | 
 | ||||||
| std::list<std::wstring>	easy2d::File::search_paths_; | namespace easy2d | ||||||
| 
 |  | ||||||
| easy2d::File::File() |  | ||||||
| 	: file_path_() |  | ||||||
| { | { | ||||||
| } | 	std::list<std::wstring>	File::search_paths_; | ||||||
| 
 | 
 | ||||||
| easy2d::File::File(const std::wstring & file_name) | 	File::File() | ||||||
| 	: file_path_(file_name) | 		: file_path_() | ||||||
| { |  | ||||||
| 	this->Open(file_name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::File::~File() |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::File::Open(const std::wstring & file_name) |  | ||||||
| { |  | ||||||
| 	if (file_name.empty()) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	auto FindFile = [](const std::wstring & path) -> bool |  | ||||||
| 	{ | 	{ | ||||||
| 		if (::PathFileExists(path.c_str())) |  | ||||||
| 			return true; |  | ||||||
| 		return false; |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	if (FindFile(file_name)) |  | ||||||
| 	{ |  | ||||||
| 		file_path_ = file_name; |  | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
| 	 | 
 | ||||||
| 	for (const auto& path : search_paths_) | 	File::File(const std::wstring & file_name) | ||||||
|  | 		: file_path_(file_name) | ||||||
| 	{ | 	{ | ||||||
| 		if (FindFile(path + file_name)) | 		this->Open(file_name); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	File::~File() | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool File::Open(const std::wstring & file_name) | ||||||
|  | 	{ | ||||||
|  | 		if (file_name.empty()) | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		auto FindFile = [](const std::wstring & path) -> bool | ||||||
| 		{ | 		{ | ||||||
| 			file_path_ = path + file_name; | 			if (::PathFileExists(path.c_str())) | ||||||
|  | 				return true; | ||||||
|  | 			return false; | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		if (FindFile(file_name)) | ||||||
|  | 		{ | ||||||
|  | 			file_path_ = file_name; | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		for (const auto& path : search_paths_) | ||||||
|  | 		{ | ||||||
|  | 			if (FindFile(path + file_name)) | ||||||
|  | 			{ | ||||||
|  | 				file_path_ = path + file_name; | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::File::Exists() const | 	bool File::Exists() const | ||||||
| { |  | ||||||
| 	if (::PathFileExists(file_path_.c_str())) |  | ||||||
| 		return true; |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const std::wstring& easy2d::File::GetPath() const |  | ||||||
| { |  | ||||||
| 	return file_path_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::wstring easy2d::File::GetExtension() const |  | ||||||
| { |  | ||||||
| 	std::wstring file_ext; |  | ||||||
| 	// 找到文件名中的最后一个 '.' 的位置
 |  | ||||||
| 	size_t pos = file_path_.find_last_of(L'.'); |  | ||||||
| 	// 判断 pos 是否是有效位置
 |  | ||||||
| 	if (pos != std::wstring::npos) |  | ||||||
| 	{ | 	{ | ||||||
| 		// 截取扩展名
 | 		if (::PathFileExists(file_path_.c_str())) | ||||||
| 		file_ext = file_path_.substr(pos); | 			return true; | ||||||
| 		// 转换为小写字母
 | 		return false; | ||||||
| 		std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower); |  | ||||||
| 	} | 	} | ||||||
| 	return file_ext; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::File::Delete() | 	const std::wstring& File::GetPath() const | ||||||
| { | 	{ | ||||||
| 	if (::DeleteFile(file_path_.c_str())) | 		return file_path_; | ||||||
| 		return true; | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::File easy2d::File::Extract(Resource& res, const std::wstring& dest_file_name) | 	std::wstring File::GetExtension() const | ||||||
| { | 	{ | ||||||
| 	File file; | 		std::wstring file_ext; | ||||||
| 	HANDLE file_handle = ::CreateFile( | 		// 找到文件名中的最后一个 '.' 的位置
 | ||||||
| 		dest_file_name.c_str(), | 		size_t pos = file_path_.find_last_of(L'.'); | ||||||
| 		GENERIC_WRITE, | 		// 判断 pos 是否是有效位置
 | ||||||
| 		NULL, | 		if (pos != std::wstring::npos) | ||||||
| 		NULL, | 		{ | ||||||
| 		CREATE_ALWAYS, | 			// 截取扩展名
 | ||||||
| 		FILE_ATTRIBUTE_TEMPORARY, | 			file_ext = file_path_.substr(pos); | ||||||
| 		NULL | 			// 转换为小写字母
 | ||||||
| 	); | 			std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower); | ||||||
|  | 		} | ||||||
|  | 		return file_ext; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool File::Delete() | ||||||
|  | 	{ | ||||||
|  | 		if (::DeleteFile(file_path_.c_str())) | ||||||
|  | 			return true; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	File File::Extract(Resource& res, const std::wstring& dest_file_name) | ||||||
|  | 	{ | ||||||
|  | 		File file; | ||||||
|  | 		HANDLE file_handle = ::CreateFile( | ||||||
|  | 			dest_file_name.c_str(), | ||||||
|  | 			GENERIC_WRITE, | ||||||
|  | 			NULL, | ||||||
|  | 			NULL, | ||||||
|  | 			CREATE_ALWAYS, | ||||||
|  | 			FILE_ATTRIBUTE_TEMPORARY, | ||||||
|  | 			NULL | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		if (file_handle == INVALID_HANDLE_VALUE) | ||||||
|  | 			return file; | ||||||
|  | 
 | ||||||
|  | 		if (res.Load()) | ||||||
|  | 		{ | ||||||
|  | 			// 写入文件
 | ||||||
|  | 			DWORD written_bytes = 0; | ||||||
|  | 			::WriteFile(file_handle, res.GetData(), res.GetDataSize(), &written_bytes, NULL); | ||||||
|  | 			::CloseHandle(file_handle); | ||||||
|  | 
 | ||||||
|  | 			file.Open(dest_file_name); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			::CloseHandle(file_handle); | ||||||
|  | 			::DeleteFile(dest_file_name.c_str()); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	if (file_handle == INVALID_HANDLE_VALUE) |  | ||||||
| 		return file; | 		return file; | ||||||
| 
 |  | ||||||
| 	if (res.Load()) |  | ||||||
| 	{ |  | ||||||
| 		// 写入文件
 |  | ||||||
| 		DWORD written_bytes = 0; |  | ||||||
| 		::WriteFile(file_handle, res.GetData(), res.GetDataSize(), &written_bytes, NULL); |  | ||||||
| 		::CloseHandle(file_handle); |  | ||||||
| 
 |  | ||||||
| 		file.Open(dest_file_name); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		::CloseHandle(file_handle); |  | ||||||
| 		::DeleteFile(dest_file_name.c_str()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return file; | 	void File::AddSearchPath(const std::wstring & path) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::File::AddSearchPath(const std::wstring & path) |  | ||||||
| { |  | ||||||
| 	std::wstring tmp = path; |  | ||||||
| 	size_t pos = 0; |  | ||||||
| 	while ((pos = tmp.find(L"/", pos)) != std::wstring::npos) |  | ||||||
| 	{ | 	{ | ||||||
| 		tmp.replace(pos, 1, L"\\"); | 		std::wstring tmp = path; | ||||||
| 		pos++; | 		size_t pos = 0; | ||||||
|  | 		while ((pos = tmp.find(L"/", pos)) != std::wstring::npos) | ||||||
|  | 		{ | ||||||
|  | 			tmp.replace(pos, 1, L"\\"); | ||||||
|  | 			pos++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (tmp.at(tmp.length() - 1) != L'\\') | ||||||
|  | 		{ | ||||||
|  | 			tmp.append(L"\\"); | ||||||
|  | 		} | ||||||
|  | 		auto iter = std::find(search_paths_.cbegin(), search_paths_.cend(), tmp); | ||||||
|  | 		if (iter == search_paths_.cend()) | ||||||
|  | 		{ | ||||||
|  | 			search_paths_.push_front(path); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (tmp.at(tmp.length() - 1) != L'\\') | 	File File::ShowOpenDialog(const std::wstring & title, const std::wstring & filter) | ||||||
| 	{ | 	{ | ||||||
| 		tmp.append(L"\\"); | 		std::wstring file_path; | ||||||
| 	} | 		HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); | ||||||
| 	auto iter = std::find(search_paths_.cbegin(), search_paths_.cend(), tmp); |  | ||||||
| 	if (iter == search_paths_.cend()) |  | ||||||
| 	{ |  | ||||||
| 		search_paths_.push_front(path); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::File easy2d::File::ShowOpenDialog(const std::wstring & title, const std::wstring & filter) |  | ||||||
| { |  | ||||||
| 	std::wstring file_path; |  | ||||||
| 	HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); |  | ||||||
| 
 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		IFileOpenDialog *file_open; |  | ||||||
| 
 |  | ||||||
| 		hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, |  | ||||||
| 			IID_IFileOpenDialog, reinterpret_cast<void**>(&file_open)); |  | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			if (!title.empty()) | 			IFileOpenDialog *file_open; | ||||||
| 			{ |  | ||||||
| 				file_open->SetTitle(title.c_str()); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			if (!filter.empty()) | 			hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, | ||||||
| 			{ | 				IID_IFileOpenDialog, reinterpret_cast<void**>(&file_open)); | ||||||
| 				COMDLG_FILTERSPEC spec[] = |  | ||||||
| 				{ |  | ||||||
| 					{ L"", filter.c_str() } |  | ||||||
| 				}; |  | ||||||
| 				file_open->SetFileTypes(1, spec); |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				COMDLG_FILTERSPEC spec[] = |  | ||||||
| 				{ |  | ||||||
| 					{ L"所有文件", L"*.*" } |  | ||||||
| 				}; |  | ||||||
| 				file_open->SetFileTypes(1, spec); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			hr = file_open->Show(nullptr); |  | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				IShellItem *item; | 				if (!title.empty()) | ||||||
| 				hr = file_open->GetResult(&item); | 				{ | ||||||
|  | 					file_open->SetTitle(title.c_str()); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (!filter.empty()) | ||||||
|  | 				{ | ||||||
|  | 					COMDLG_FILTERSPEC spec[] = | ||||||
|  | 					{ | ||||||
|  | 						{ L"", filter.c_str() } | ||||||
|  | 					}; | ||||||
|  | 					file_open->SetFileTypes(1, spec); | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					COMDLG_FILTERSPEC spec[] = | ||||||
|  | 					{ | ||||||
|  | 						{ L"所有文件", L"*.*" } | ||||||
|  | 					}; | ||||||
|  | 					file_open->SetFileTypes(1, spec); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				hr = file_open->Show(nullptr); | ||||||
|  | 
 | ||||||
| 				if (SUCCEEDED(hr)) | 				if (SUCCEEDED(hr)) | ||||||
| 				{ | 				{ | ||||||
| 					PWSTR str_file_path; | 					IShellItem *item; | ||||||
| 					hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | 					hr = file_open->GetResult(&item); | ||||||
| 
 |  | ||||||
| 					if (SUCCEEDED(hr)) | 					if (SUCCEEDED(hr)) | ||||||
| 					{ | 					{ | ||||||
| 						file_path = str_file_path; | 						PWSTR str_file_path; | ||||||
| 						::CoTaskMemFree(str_file_path); | 						hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | ||||||
|  | 
 | ||||||
|  | 						if (SUCCEEDED(hr)) | ||||||
|  | 						{ | ||||||
|  | 							file_path = str_file_path; | ||||||
|  | 							::CoTaskMemFree(str_file_path); | ||||||
|  | 						} | ||||||
|  | 						item->Release(); | ||||||
| 					} | 					} | ||||||
| 					item->Release(); |  | ||||||
| 				} | 				} | ||||||
|  | 				file_open->Release(); | ||||||
| 			} | 			} | ||||||
| 			file_open->Release(); | 			::CoUninitialize(); | ||||||
| 		} | 		} | ||||||
| 		::CoUninitialize(); | 		return File(file_path); | ||||||
| 	} | 	} | ||||||
| 	return File(file_path); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::File easy2d::File::ShowSaveDialog(const std::wstring & title, const std::wstring& def_file, const std::wstring & def_ext) | 	File File::ShowSaveDialog(const std::wstring & title, const std::wstring& def_file, const std::wstring & def_ext) | ||||||
| { |  | ||||||
| 	std::wstring file_path; |  | ||||||
| 	HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); |  | ||||||
| 	 |  | ||||||
| 	if (SUCCEEDED(hr)) |  | ||||||
| 	{ | 	{ | ||||||
| 		IFileSaveDialog *file_save; | 		std::wstring file_path; | ||||||
| 
 | 		HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); | ||||||
| 		hr = ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL, |  | ||||||
| 			IID_IFileSaveDialog, reinterpret_cast<void**>(&file_save)); |  | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			if (!title.empty()) | 			IFileSaveDialog *file_save; | ||||||
| 			{ |  | ||||||
| 				file_save->SetTitle(title.c_str()); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			if (!def_file.empty()) | 			hr = ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL, | ||||||
| 			{ | 				IID_IFileSaveDialog, reinterpret_cast<void**>(&file_save)); | ||||||
| 				file_save->SetFileName(def_file.c_str()); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (!def_ext.empty()) |  | ||||||
| 			{ |  | ||||||
| 				file_save->SetDefaultExtension(def_ext.c_str()); |  | ||||||
| 
 |  | ||||||
| 				std::wstring ext = L"*." + def_ext; |  | ||||||
| 				COMDLG_FILTERSPEC spec[] = |  | ||||||
| 				{ |  | ||||||
| 					{ L"", ext.c_str() } |  | ||||||
| 				}; |  | ||||||
| 				file_save->SetFileTypes(1, spec); |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				COMDLG_FILTERSPEC spec[] = |  | ||||||
| 				{ |  | ||||||
| 					{ L"所有文件", L"*.*" } |  | ||||||
| 				}; |  | ||||||
| 				file_save->SetFileTypes(1, spec); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			hr = file_save->Show(nullptr); |  | ||||||
| 
 | 
 | ||||||
| 			if (SUCCEEDED(hr)) | 			if (SUCCEEDED(hr)) | ||||||
| 			{ | 			{ | ||||||
| 				IShellItem *item; | 				if (!title.empty()) | ||||||
| 				hr = file_save->GetResult(&item); | 				{ | ||||||
|  | 					file_save->SetTitle(title.c_str()); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (!def_file.empty()) | ||||||
|  | 				{ | ||||||
|  | 					file_save->SetFileName(def_file.c_str()); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (!def_ext.empty()) | ||||||
|  | 				{ | ||||||
|  | 					file_save->SetDefaultExtension(def_ext.c_str()); | ||||||
|  | 
 | ||||||
|  | 					std::wstring ext = L"*." + def_ext; | ||||||
|  | 					COMDLG_FILTERSPEC spec[] = | ||||||
|  | 					{ | ||||||
|  | 						{ L"", ext.c_str() } | ||||||
|  | 					}; | ||||||
|  | 					file_save->SetFileTypes(1, spec); | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					COMDLG_FILTERSPEC spec[] = | ||||||
|  | 					{ | ||||||
|  | 						{ L"所有文件", L"*.*" } | ||||||
|  | 					}; | ||||||
|  | 					file_save->SetFileTypes(1, spec); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				hr = file_save->Show(nullptr); | ||||||
|  | 
 | ||||||
| 				if (SUCCEEDED(hr)) | 				if (SUCCEEDED(hr)) | ||||||
| 				{ | 				{ | ||||||
| 					PWSTR str_file_path; | 					IShellItem *item; | ||||||
| 					hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | 					hr = file_save->GetResult(&item); | ||||||
| 
 |  | ||||||
| 					if (SUCCEEDED(hr)) | 					if (SUCCEEDED(hr)) | ||||||
| 					{ | 					{ | ||||||
| 						file_path = str_file_path; | 						PWSTR str_file_path; | ||||||
| 						::CoTaskMemFree(str_file_path); | 						hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | ||||||
|  | 
 | ||||||
|  | 						if (SUCCEEDED(hr)) | ||||||
|  | 						{ | ||||||
|  | 							file_path = str_file_path; | ||||||
|  | 							::CoTaskMemFree(str_file_path); | ||||||
|  | 						} | ||||||
|  | 						item->Release(); | ||||||
| 					} | 					} | ||||||
| 					item->Release(); |  | ||||||
| 				} | 				} | ||||||
|  | 				file_save->Release(); | ||||||
| 			} | 			} | ||||||
| 			file_save->Release(); | 			::CoUninitialize(); | ||||||
| 		} | 		} | ||||||
| 		::CoUninitialize(); | 		return File(file_path); | ||||||
| 	} | 	} | ||||||
| 	return File(file_path); | } | ||||||
| } |  | ||||||
|  | @ -22,38 +22,40 @@ | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| namespace |  | ||||||
| { |  | ||||||
| 	void OutputDebugStringExW(LPCWSTR pszOutput, ...) |  | ||||||
| 	{ |  | ||||||
| 		va_list args = NULL; |  | ||||||
| 		va_start(args, pszOutput); |  | ||||||
| 
 |  | ||||||
| 		size_t nLen = _vscwprintf(pszOutput, args) + 1; |  | ||||||
| 		wchar_t* psBuffer = new wchar_t[nLen]; |  | ||||||
| 		_vsnwprintf_s(psBuffer, nLen, nLen, pszOutput, args); |  | ||||||
| 
 |  | ||||||
| 		va_end(args); |  | ||||||
| 
 |  | ||||||
| 		::OutputDebugStringW(psBuffer); |  | ||||||
| 		delete[] psBuffer; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	inline void TraceError(LPCWSTR output) |  | ||||||
| 	{ |  | ||||||
| 		OutputDebugStringExW(L"[easy2d] Music error: %s failed!\r\n", output); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	inline void TraceError(LPCWSTR output, HRESULT hr) |  | ||||||
| 	{ |  | ||||||
| 		OutputDebugStringExW(L"[easy2d] Music error: %s (%#X)\r\n", output, hr); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| namespace easy2d | namespace easy2d | ||||||
| { | { | ||||||
| 	// 音频解码器
 | 	namespace | ||||||
|  | 	{ | ||||||
|  | 		void OutputDebugStringExW(LPCWSTR pszOutput, ...) | ||||||
|  | 		{ | ||||||
|  | 			va_list args = NULL; | ||||||
|  | 			va_start(args, pszOutput); | ||||||
|  | 
 | ||||||
|  | 			size_t nLen = _vscwprintf(pszOutput, args) + 1; | ||||||
|  | 			wchar_t* psBuffer = new wchar_t[nLen]; | ||||||
|  | 			_vsnwprintf_s(psBuffer, nLen, nLen, pszOutput, args); | ||||||
|  | 
 | ||||||
|  | 			va_end(args); | ||||||
|  | 
 | ||||||
|  | 			::OutputDebugStringW(psBuffer); | ||||||
|  | 			delete[] psBuffer; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		inline void TraceError(LPCWSTR output) | ||||||
|  | 		{ | ||||||
|  | 			OutputDebugStringExW(L"[easy2d] Music error: %s failed!\r\n", output); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		inline void TraceError(LPCWSTR output, HRESULT hr) | ||||||
|  | 		{ | ||||||
|  | 			OutputDebugStringExW(L"[easy2d] Music error: %s (%#X)\r\n", output, hr); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
|  | 	// Transcoder
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
|  | 
 | ||||||
| 	class Transcoder | 	class Transcoder | ||||||
| 	{ | 	{ | ||||||
| 		WAVEFORMATEX* wave_format_; | 		WAVEFORMATEX* wave_format_; | ||||||
|  | @ -304,252 +306,255 @@ namespace easy2d | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
|  | 	// Music
 | ||||||
|  | 	//-------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| easy2d::Music::Music() | 	Music::Music() | ||||||
| 	: opened_(false) | 		: opened_(false) | ||||||
| 	, playing_(false) | 		, playing_(false) | ||||||
| 	, wave_data_(nullptr) | 		, wave_data_(nullptr) | ||||||
| 	, size_(0) | 		, size_(0) | ||||||
| 	, voice_(nullptr) | 		, voice_(nullptr) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Music::Music(const std::wstring& file_path) | 	Music::Music(const std::wstring& file_path) | ||||||
| 	: opened_(false) | 		: opened_(false) | ||||||
| 	, playing_(false) | 		, playing_(false) | ||||||
| 	, wave_data_(nullptr) | 		, wave_data_(nullptr) | ||||||
| 	, size_(0) | 		, size_(0) | ||||||
| 	, voice_(nullptr) | 		, voice_(nullptr) | ||||||
| { | 	{ | ||||||
| 	Load(file_path); | 		Load(file_path); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Music::Music(Resource& res) | 	Music::Music(Resource& res) | ||||||
| 	: opened_(false) | 		: opened_(false) | ||||||
| 	, playing_(false) | 		, playing_(false) | ||||||
| 	, wave_data_(nullptr) | 		, wave_data_(nullptr) | ||||||
| 	, size_(0) | 		, size_(0) | ||||||
| 	, voice_(nullptr) | 		, voice_(nullptr) | ||||||
| { | 	{ | ||||||
| 	Load(res); | 		Load(res); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Music::~Music() | 	Music::~Music() | ||||||
| { |  | ||||||
| 	Close(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Music::Load(const std::wstring & file_path) |  | ||||||
| { |  | ||||||
| 	if (opened_) |  | ||||||
| 	{ | 	{ | ||||||
| 		Close(); | 		Close(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	File music_file; | 	bool Music::Load(const std::wstring & file_path) | ||||||
| 	if (!music_file.Open(file_path)) |  | ||||||
| 	{ | 	{ | ||||||
| 		E2D_WARNING("Media file not found."); | 		if (opened_) | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
 |  | ||||||
| 	// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
 |  | ||||||
| 	std::wstring music_file_path = music_file.GetPath(); |  | ||||||
| 
 |  | ||||||
| 	Transcoder transcoder; |  | ||||||
| 	if (!transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_)) |  | ||||||
| 	{ |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); |  | ||||||
| 	if (FAILED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		if (wave_data_) |  | ||||||
| 		{ | 		{ | ||||||
| 			delete[] wave_data_; | 			Close(); | ||||||
| 			wave_data_ = nullptr; |  | ||||||
| 		} | 		} | ||||||
| 		TraceError(L"Create source voice error", hr); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	opened_ = true; | 		File music_file; | ||||||
| 	return true; | 		if (!music_file.Open(file_path)) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Music::Load(Resource& res) |  | ||||||
| { |  | ||||||
| 	if (opened_) |  | ||||||
| 	{ |  | ||||||
| 		Close(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Transcoder transcoder; |  | ||||||
| 	if (!transcoder.LoadMediaResource(res, &wave_data_, &size_)) |  | ||||||
| 	{ |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); |  | ||||||
| 	if (FAILED(hr)) |  | ||||||
| 	{ |  | ||||||
| 		if (wave_data_) |  | ||||||
| 		{ | 		{ | ||||||
| 			delete[] wave_data_; | 			E2D_WARNING("Media file not found."); | ||||||
| 			wave_data_ = nullptr; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		TraceError(L"Create source voice error", hr); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	opened_ = true; | 		// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
 | ||||||
| 	return true; | 		// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
 | ||||||
| } | 		std::wstring music_file_path = music_file.GetPath(); | ||||||
| 
 | 
 | ||||||
| bool easy2d::Music::Play(int loop_count) | 		Transcoder transcoder; | ||||||
| { | 		if (!transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_)) | ||||||
| 	if (!opened_) |  | ||||||
| 	{ |  | ||||||
| 		E2D_WARNING("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) |  | ||||||
| 	{ |  | ||||||
| 		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))) |  | ||||||
| 	{ |  | ||||||
| 		TraceError(L"Submitting source buffer error", hr); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	hr = voice_->Start(0); |  | ||||||
| 
 |  | ||||||
| 	playing_ = SUCCEEDED(hr); |  | ||||||
| 
 |  | ||||||
| 	return playing_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Music::Pause() |  | ||||||
| { |  | ||||||
| 	if (voice_) |  | ||||||
| 	{ |  | ||||||
| 		if (SUCCEEDED(voice_->Stop())) |  | ||||||
| 		{ | 		{ | ||||||
| 			playing_ = false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Music::Resume() | 		HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||||
| { | 		if (FAILED(hr)) | ||||||
| 	if (voice_) |  | ||||||
| 	{ |  | ||||||
| 		if (SUCCEEDED(voice_->Start())) |  | ||||||
| 		{ | 		{ | ||||||
| 			playing_ = true; | 			if (wave_data_) | ||||||
|  | 			{ | ||||||
|  | 				delete[] wave_data_; | ||||||
|  | 				wave_data_ = nullptr; | ||||||
|  | 			} | ||||||
|  | 			TraceError(L"Create source voice error", hr); | ||||||
|  | 			return false; | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Music::Stop() | 		opened_ = true; | ||||||
| { | 		return true; | ||||||
| 	if (voice_) | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Music::Load(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		if (SUCCEEDED(voice_->Stop())) | 		if (opened_) | ||||||
| 		{ | 		{ | ||||||
| 			voice_->ExitLoop(); | 			Close(); | ||||||
| 			voice_->FlushSourceBuffers(); |  | ||||||
| 			playing_ = false; |  | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Music::Close() | 		Transcoder transcoder; | ||||||
| { | 		if (!transcoder.LoadMediaResource(res, &wave_data_, &size_)) | ||||||
| 	if (voice_) | 		{ | ||||||
| 	{ | 			return false; | ||||||
| 		voice_->Stop(); | 		} | ||||||
| 		voice_->FlushSourceBuffers(); | 
 | ||||||
| 		voice_->DestroyVoice(); | 		HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||||
| 		voice_ = nullptr; | 		if (FAILED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			if (wave_data_) | ||||||
|  | 			{ | ||||||
|  | 				delete[] wave_data_; | ||||||
|  | 				wave_data_ = nullptr; | ||||||
|  | 			} | ||||||
|  | 			TraceError(L"Create source voice error", hr); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		opened_ = true; | ||||||
|  | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (wave_data_) | 	bool Music::Play(int loop_count) | ||||||
| 	{ | 	{ | ||||||
| 		delete[] wave_data_; | 		if (!opened_) | ||||||
| 		wave_data_ = nullptr; | 		{ | ||||||
| 	} | 			E2D_WARNING("Music must be opened first!"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	opened_ = false; | 		if (voice_ == nullptr) | ||||||
| 	playing_ = false; | 		{ | ||||||
| } | 			E2D_WARNING("IXAudio2SourceVoice Null pointer exception!"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Music::IsPlaying() const |  | ||||||
| { |  | ||||||
| 	if (opened_ && voice_) |  | ||||||
| 	{ |  | ||||||
| 		XAUDIO2_VOICE_STATE state; | 		XAUDIO2_VOICE_STATE state; | ||||||
| 		voice_->GetState(&state); | 		voice_->GetState(&state); | ||||||
| 		if (state.BuffersQueued && playing_) | 		if (state.BuffersQueued) | ||||||
| 			return true; | 		{ | ||||||
| 	} | 			Stop(); | ||||||
| 	return false; | 		} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| float easy2d::Music::GetVolume() const | 		if (loop_count < 0) | ||||||
| { | 		{ | ||||||
| 	if (voice_) | 			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))) | ||||||
|  | 		{ | ||||||
|  | 			TraceError(L"Submitting source buffer error", hr); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		hr = voice_->Start(0); | ||||||
|  | 
 | ||||||
|  | 		playing_ = SUCCEEDED(hr); | ||||||
|  | 
 | ||||||
|  | 		return playing_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Music::Pause() | ||||||
| 	{ | 	{ | ||||||
| 		float volume = 0.f; | 		if (voice_) | ||||||
| 		voice_->GetVolume(&volume); | 		{ | ||||||
| 		return volume; | 			if (SUCCEEDED(voice_->Stop())) | ||||||
|  | 			{ | ||||||
|  | 				playing_ = false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return 0.f; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Music::SetVolume(float volume) | 	void Music::Resume() | ||||||
| { |  | ||||||
| 	if (voice_) |  | ||||||
| 	{ | 	{ | ||||||
| 		volume = std::min(std::max(volume, -224.f), 224.f); | 		if (voice_) | ||||||
| 		return SUCCEEDED(voice_->SetVolume(volume)); | 		{ | ||||||
|  | 			if (SUCCEEDED(voice_->Start())) | ||||||
|  | 			{ | ||||||
|  | 				playing_ = true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| IXAudio2SourceVoice * easy2d::Music::GetSourceVoice() const | 	void Music::Stop() | ||||||
| { | 	{ | ||||||
| 	return voice_; | 		if (voice_) | ||||||
| } | 		{ | ||||||
|  | 			if (SUCCEEDED(voice_->Stop())) | ||||||
|  | 			{ | ||||||
|  | 				voice_->ExitLoop(); | ||||||
|  | 				voice_->FlushSourceBuffers(); | ||||||
|  | 				playing_ = false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Music::Close() | ||||||
|  | 	{ | ||||||
|  | 		if (voice_) | ||||||
|  | 		{ | ||||||
|  | 			voice_->Stop(); | ||||||
|  | 			voice_->FlushSourceBuffers(); | ||||||
|  | 			voice_->DestroyVoice(); | ||||||
|  | 			voice_ = nullptr; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (wave_data_) | ||||||
|  | 		{ | ||||||
|  | 			delete[] wave_data_; | ||||||
|  | 			wave_data_ = nullptr; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		opened_ = false; | ||||||
|  | 		playing_ = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Music::IsPlaying() const | ||||||
|  | 	{ | ||||||
|  | 		if (opened_ && voice_) | ||||||
|  | 		{ | ||||||
|  | 			XAUDIO2_VOICE_STATE state; | ||||||
|  | 			voice_->GetState(&state); | ||||||
|  | 			if (state.BuffersQueued && playing_) | ||||||
|  | 				return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Music::GetVolume() const | ||||||
|  | 	{ | ||||||
|  | 		if (voice_) | ||||||
|  | 		{ | ||||||
|  | 			float volume = 0.f; | ||||||
|  | 			voice_->GetVolume(&volume); | ||||||
|  | 			return volume; | ||||||
|  | 		} | ||||||
|  | 		return 0.f; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	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_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -23,115 +23,118 @@ | ||||||
| #include <shlobj.h> | #include <shlobj.h> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| namespace | namespace easy2d | ||||||
| { | { | ||||||
| 	// 创建指定文件夹
 | 	namespace | ||||||
| 	bool CreateFolder(const std::wstring & dir_path) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (dir_path.empty() || dir_path.size() >= MAX_PATH) | 		// 创建指定文件夹
 | ||||||
| 			return false; | 		bool CreateFolder(const std::wstring & dir_path) | ||||||
| 
 |  | ||||||
| 		wchar_t tmp_dir_path[MAX_PATH] = { 0 }; |  | ||||||
| 		size_t length = dir_path.length(); |  | ||||||
| 
 |  | ||||||
| 		for (size_t i = 0; i < length; ++i) |  | ||||||
| 		{ | 		{ | ||||||
| 			tmp_dir_path[i] = dir_path.at(i); | 			if (dir_path.empty() || dir_path.size() >= MAX_PATH) | ||||||
| 			if (tmp_dir_path[i] == L'\\' || tmp_dir_path[i] == L'/' || i == (length - 1)) | 				return false; | ||||||
|  | 
 | ||||||
|  | 			wchar_t tmp_dir_path[MAX_PATH] = { 0 }; | ||||||
|  | 			size_t length = dir_path.length(); | ||||||
|  | 
 | ||||||
|  | 			for (size_t i = 0; i < length; ++i) | ||||||
| 			{ | 			{ | ||||||
| 				if (::_waccess(tmp_dir_path, 0) != 0) | 				tmp_dir_path[i] = dir_path.at(i); | ||||||
|  | 				if (tmp_dir_path[i] == L'\\' || tmp_dir_path[i] == L'/' || i == (length - 1)) | ||||||
| 				{ | 				{ | ||||||
| 					if (::_wmkdir(tmp_dir_path) != 0) | 					if (::_waccess(tmp_dir_path, 0) != 0) | ||||||
| 					{ | 					{ | ||||||
| 						return false; | 						if (::_wmkdir(tmp_dir_path) != 0) | ||||||
|  | 						{ | ||||||
|  | 							return false; | ||||||
|  | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 			return true; | ||||||
| 		} | 		} | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| const std::wstring& easy2d::Path::GetDataPath() | 	const std::wstring& Path::GetDataPath() | ||||||
| { |  | ||||||
| 	static std::wstring data_path; |  | ||||||
| 	if (data_path.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		// 设置数据的保存路径
 | 		static std::wstring data_path; | ||||||
| 		std::wstring local_app_data_path = Path::GetLocalAppDataPath(); | 		if (data_path.empty()) | ||||||
| 		std::wstring title = Game::GetInstance()->GetTitle(); |  | ||||||
| 		std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); |  | ||||||
| 
 |  | ||||||
| 		if (!local_app_data_path.empty()) |  | ||||||
| 		{ | 		{ | ||||||
| 			data_path.append(local_app_data_path) | 			// 设置数据的保存路径
 | ||||||
| 				.append(L"\\Easy2DGameData\\") | 			std::wstring local_app_data_path = Path::GetLocalAppDataPath(); | ||||||
| 				.append(folder_name) | 			std::wstring title = Game::GetInstance()->GetTitle(); | ||||||
| 				.append(L"\\"); | 			std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); | ||||||
| 
 | 
 | ||||||
| 			File file(data_path); | 			if (!local_app_data_path.empty()) | ||||||
| 			if (!file.Exists() && !CreateFolder(data_path)) |  | ||||||
| 			{ | 			{ | ||||||
| 				data_path = L""; | 				data_path.append(local_app_data_path) | ||||||
|  | 					.append(L"\\Easy2DGameData\\") | ||||||
|  | 					.append(folder_name) | ||||||
|  | 					.append(L"\\"); | ||||||
|  | 
 | ||||||
|  | 				File file(data_path); | ||||||
|  | 				if (!file.Exists() && !CreateFolder(data_path)) | ||||||
|  | 				{ | ||||||
|  | 					data_path = L""; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			data_path.append(L"Data.ini"); | ||||||
|  | 		} | ||||||
|  | 		return data_path; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const std::wstring& Path::GetTemporaryPath() | ||||||
|  | 	{ | ||||||
|  | 		static std::wstring temp_path; | ||||||
|  | 		if (temp_path.empty()) | ||||||
|  | 		{ | ||||||
|  | 			// 设置临时文件保存路径
 | ||||||
|  | 			wchar_t path[_MAX_PATH]; | ||||||
|  | 			std::wstring title = Game::GetInstance()->GetTitle(); | ||||||
|  | 			std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); | ||||||
|  | 
 | ||||||
|  | 			if (0 != ::GetTempPath(_MAX_PATH, path)) | ||||||
|  | 			{ | ||||||
|  | 				temp_path.append(path) | ||||||
|  | 					.append(L"\\Easy2DGameTemp\\") | ||||||
|  | 					.append(folder_name) | ||||||
|  | 					.append(L"\\"); | ||||||
|  | 
 | ||||||
|  | 				File file(temp_path); | ||||||
|  | 				if (!file.Exists() && !CreateFolder(temp_path)) | ||||||
|  | 				{ | ||||||
|  | 					temp_path = L""; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		data_path.append(L"Data.ini"); | 		return temp_path; | ||||||
| 	} | 	} | ||||||
| 	return data_path; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const std::wstring& easy2d::Path::GetTemporaryPath() | 	const std::wstring& Path::GetLocalAppDataPath() | ||||||
| { |  | ||||||
| 	static std::wstring temp_path; |  | ||||||
| 	if (temp_path.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		// 设置临时文件保存路径
 | 		static std::wstring local_app_data_path; | ||||||
| 		wchar_t path[_MAX_PATH]; | 		if (local_app_data_path.empty()) | ||||||
| 		std::wstring title = Game::GetInstance()->GetTitle(); |  | ||||||
| 		std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); |  | ||||||
| 
 |  | ||||||
| 		if (0 != ::GetTempPath(_MAX_PATH, path)) |  | ||||||
| 		{ | 		{ | ||||||
| 			temp_path.append(path) | 			// 获取 AppData/Local 文件夹的路径
 | ||||||
| 				.append(L"\\Easy2DGameTemp\\") | 			wchar_t path[MAX_PATH] = { 0 }; | ||||||
| 				.append(folder_name) | 			::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path); | ||||||
| 				.append(L"\\"); | 			local_app_data_path = path; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 			File file(temp_path); | 		return local_app_data_path; | ||||||
| 			if (!file.Exists() && !CreateFolder(temp_path)) | 	} | ||||||
|  | 
 | ||||||
|  | 	const std::wstring& Path::GetExeFilePath() | ||||||
|  | 	{ | ||||||
|  | 		static std::wstring exe_file_path; | ||||||
|  | 		if (exe_file_path.empty()) | ||||||
|  | 		{ | ||||||
|  | 			TCHAR path[_MAX_PATH] = { 0 }; | ||||||
|  | 			if (::GetModuleFileName(nullptr, path, _MAX_PATH) != 0) | ||||||
| 			{ | 			{ | ||||||
| 				temp_path = L""; | 				exe_file_path = path; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		return exe_file_path; | ||||||
| 	} | 	} | ||||||
| 	return temp_path; | } | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const std::wstring& easy2d::Path::GetLocalAppDataPath() |  | ||||||
| { |  | ||||||
| 	static std::wstring local_app_data_path; |  | ||||||
| 	if (local_app_data_path.empty()) |  | ||||||
| 	{ |  | ||||||
| 		// 获取 AppData/Local 文件夹的路径
 |  | ||||||
| 		wchar_t path[MAX_PATH] = { 0 }; |  | ||||||
| 		::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path); |  | ||||||
| 		local_app_data_path = path; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return local_app_data_path; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const std::wstring& easy2d::Path::GetExeFilePath() |  | ||||||
| { |  | ||||||
| 	static std::wstring exe_file_path; |  | ||||||
| 	if (exe_file_path.empty()) |  | ||||||
| 	{ |  | ||||||
| 		TCHAR path[_MAX_PATH] = { 0 }; |  | ||||||
| 		if (::GetModuleFileName(nullptr, path, _MAX_PATH) != 0) |  | ||||||
| 		{ |  | ||||||
| 			exe_file_path = path; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return exe_file_path; |  | ||||||
| } |  | ||||||
|  | @ -1,212 +1,215 @@ | ||||||
| #include "..\e2dtool.h" | #include "..\e2dtool.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| std::map<size_t, easy2d::Music*> easy2d::Player::musics_; | namespace easy2d | ||||||
| 
 |  | ||||||
| easy2d::Player::Player() |  | ||||||
| 	: volume_(1.f) |  | ||||||
| { | { | ||||||
| } | 	std::map<size_t, Music*> Player::musics_; | ||||||
| 
 | 
 | ||||||
| easy2d::Player::~Player() | 	Player::Player() | ||||||
| { | 		: volume_(1.f) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Player::Load(const std::wstring & file_path) |  | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	Music * music = new (std::nothrow) Music(); |  | ||||||
| 
 |  | ||||||
| 	if (music) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (music->Load(file_path)) |  | ||||||
| 		{ |  | ||||||
| 			music->SetVolume(volume_); |  | ||||||
| 
 |  | ||||||
| 			size_t hash_code = std::hash<std::wstring>{}(file_path); |  | ||||||
| 			musics_.insert(std::make_pair(hash_code, music)); |  | ||||||
| 			return true; |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			music->Release(); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Player::Play(const std::wstring & file_path, int loop_count) | 	Player::~Player() | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	if (Load(file_path)) |  | ||||||
| 	{ | 	{ | ||||||
| 		auto music = musics_[std::hash<std::wstring>{}(file_path)]; |  | ||||||
| 		if (music->Play(loop_count)) |  | ||||||
| 		{ |  | ||||||
| 			return true; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::Pause(const std::wstring & file_path) | 	bool Player::Load(const std::wstring & file_path) | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	size_t hash_code = std::hash<std::wstring>{}(file_path); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Pause(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Player::Resume(const std::wstring & file_path) |  | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	size_t hash_code = std::hash<std::wstring>{}(file_path); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Resume(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Player::Stop(const std::wstring & file_path) |  | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	size_t hash_code = std::hash<std::wstring>{}(file_path); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Player::IsPlaying(const std::wstring & file_path) |  | ||||||
| { |  | ||||||
| 	if (file_path.empty()) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	size_t hash_code = std::hash<std::wstring>{}(file_path); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		return musics_[hash_code]->IsPlaying(); |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Player::Load(Resource& res) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		return true; |  | ||||||
| 
 |  | ||||||
| 	Music * music = new (std::nothrow) Music(); |  | ||||||
| 
 |  | ||||||
| 	if (music) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (music->Load(res)) | 		if (file_path.empty()) | ||||||
| 		{ | 			return false; | ||||||
| 			music->SetVolume(volume_); |  | ||||||
| 			musics_.insert(std::make_pair(hash_code, music)); |  | ||||||
| 			return true; |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			music->Release(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Player::Play(Resource& res, int loop_count) | 		Music * music = new (std::nothrow) Music(); | ||||||
| { | 
 | ||||||
| 	if (Load(res)) | 		if (music) | ||||||
|  | 		{ | ||||||
|  | 			if (music->Load(file_path)) | ||||||
|  | 			{ | ||||||
|  | 				music->SetVolume(volume_); | ||||||
|  | 
 | ||||||
|  | 				size_t hash_code = std::hash<std::wstring>{}(file_path); | ||||||
|  | 				musics_.insert(std::make_pair(hash_code, music)); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				music->Release(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Player::Play(const std::wstring & file_path, int loop_count) | ||||||
|  | 	{ | ||||||
|  | 		if (file_path.empty()) | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		if (Load(file_path)) | ||||||
|  | 		{ | ||||||
|  | 			auto music = musics_[std::hash<std::wstring>{}(file_path)]; | ||||||
|  | 			if (music->Play(loop_count)) | ||||||
|  | 			{ | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::Pause(const std::wstring & file_path) | ||||||
|  | 	{ | ||||||
|  | 		if (file_path.empty()) | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		size_t hash_code = std::hash<std::wstring>{}(file_path); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			musics_[hash_code]->Pause(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::Resume(const std::wstring & file_path) | ||||||
|  | 	{ | ||||||
|  | 		if (file_path.empty()) | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		size_t hash_code = std::hash<std::wstring>{}(file_path); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			musics_[hash_code]->Resume(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::Stop(const std::wstring & file_path) | ||||||
|  | 	{ | ||||||
|  | 		if (file_path.empty()) | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		size_t hash_code = std::hash<std::wstring>{}(file_path); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			musics_[hash_code]->Stop(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Player::IsPlaying(const std::wstring & file_path) | ||||||
|  | 	{ | ||||||
|  | 		if (file_path.empty()) | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		size_t hash_code = std::hash<std::wstring>{}(file_path); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			return musics_[hash_code]->IsPlaying(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Player::Load(Resource& res) | ||||||
| 	{ | 	{ | ||||||
| 		size_t hash_code = res.GetHashCode(); | 		size_t hash_code = res.GetHashCode(); | ||||||
| 		auto music = musics_[hash_code]; | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
| 		if (music->Play(loop_count)) |  | ||||||
| 		{ |  | ||||||
| 			return true; | 			return true; | ||||||
|  | 
 | ||||||
|  | 		Music * music = new (std::nothrow) Music(); | ||||||
|  | 
 | ||||||
|  | 		if (music) | ||||||
|  | 		{ | ||||||
|  | 			if (music->Load(res)) | ||||||
|  | 			{ | ||||||
|  | 				music->SetVolume(volume_); | ||||||
|  | 				musics_.insert(std::make_pair(hash_code, music)); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				music->Release(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Player::Play(Resource& res, int loop_count) | ||||||
|  | 	{ | ||||||
|  | 		if (Load(res)) | ||||||
|  | 		{ | ||||||
|  | 			size_t hash_code = res.GetHashCode(); | ||||||
|  | 			auto music = musics_[hash_code]; | ||||||
|  | 			if (music->Play(loop_count)) | ||||||
|  | 			{ | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::Pause(Resource& res) | ||||||
|  | 	{ | ||||||
|  | 		size_t hash_code = res.GetHashCode(); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			musics_[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(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::Stop(Resource& res) | ||||||
|  | 	{ | ||||||
|  | 		size_t hash_code = res.GetHashCode(); | ||||||
|  | 		if (musics_.end() != musics_.find(hash_code)) | ||||||
|  | 			musics_[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(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Player::GetVolume() const | ||||||
|  | 	{ | ||||||
|  | 		return volume_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Player::SetVolume(float volume) | ||||||
|  | 	{ | ||||||
|  | 		volume_ = std::min(std::max(volume, -224.f), 224.f); | ||||||
|  | 		for (const auto& pair : musics_) | ||||||
|  | 		{ | ||||||
|  | 			pair.second->SetVolume(volume_); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::Pause(Resource& res) | 	void Player::PauseAll() | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Pause(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Player::Resume(Resource& res) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Resume(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Player::Stop(Resource& res) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		musics_[hash_code]->Stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Player::IsPlaying(Resource& res) |  | ||||||
| { |  | ||||||
| 	size_t hash_code = res.GetHashCode(); |  | ||||||
| 	if (musics_.end() != musics_.find(hash_code)) |  | ||||||
| 		return musics_[hash_code]->IsPlaying(); |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Player::GetVolume() const |  | ||||||
| { |  | ||||||
| 	return volume_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Player::SetVolume(float volume) |  | ||||||
| { |  | ||||||
| 	volume_ = std::min(std::max(volume, -224.f), 224.f); |  | ||||||
| 	for (const auto& pair : musics_) |  | ||||||
| 	{ | 	{ | ||||||
| 		pair.second->SetVolume(volume_); | 		for (const auto& pair : musics_) | ||||||
|  | 		{ | ||||||
|  | 			pair.second->Pause(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::PauseAll() | 	void Player::ResumeAll() | ||||||
| { |  | ||||||
| 	for (const auto& pair : musics_) |  | ||||||
| 	{ | 	{ | ||||||
| 		pair.second->Pause(); | 		for (const auto& pair : musics_) | ||||||
|  | 		{ | ||||||
|  | 			pair.second->Resume(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::ResumeAll() | 	void Player::StopAll() | ||||||
| { |  | ||||||
| 	for (const auto& pair : musics_) |  | ||||||
| 	{ | 	{ | ||||||
| 		pair.second->Resume(); | 		for (const auto& pair : musics_) | ||||||
|  | 		{ | ||||||
|  | 			pair.second->Stop(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::StopAll() | 	void Player::ClearCache() | ||||||
| { |  | ||||||
| 	for (const auto& pair : musics_) |  | ||||||
| 	{ | 	{ | ||||||
| 		pair.second->Stop(); | 		if (musics_.empty()) | ||||||
| 	} | 			return; | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Player::ClearCache() | 		for (const auto& pair : musics_) | ||||||
| { | 		{ | ||||||
| 	if (musics_.empty()) | 			pair.second->Release(); | ||||||
| 		return; | 		} | ||||||
| 
 | 		musics_.clear(); | ||||||
| 	for (const auto& pair : musics_) |  | ||||||
| 	{ |  | ||||||
| 		pair.second->Release(); |  | ||||||
| 	} | 	} | ||||||
| 	musics_.clear(); | } | ||||||
| } |  | ||||||
|  | @ -21,40 +21,43 @@ | ||||||
| #include "..\e2dtransition.h" | #include "..\e2dtransition.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::BoxTransition::BoxTransition(float duration) | namespace easy2d | ||||||
| 	: Transition(duration) |  | ||||||
| { | { | ||||||
| } | 	BoxTransition::BoxTransition(float duration) | ||||||
| 
 | 		: Transition(duration) | ||||||
| void easy2d::BoxTransition::Init(Scene * prev, Scene * next, Game * game) |  | ||||||
| { |  | ||||||
| 	Transition::Init(prev, next, game); |  | ||||||
| 
 |  | ||||||
| 	in_layer_param_.opacity = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::BoxTransition::Update() |  | ||||||
| { |  | ||||||
| 	Transition::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (process_ < .5f) |  | ||||||
| 	{ | 	{ | ||||||
| 		out_layer_param_.contentBounds = D2D1::RectF( |  | ||||||
| 			window_size_.width * process_, |  | ||||||
| 			window_size_.height * process_, |  | ||||||
| 			window_size_.width * (1 - process_), |  | ||||||
| 			window_size_.height * (1 - process_) |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	void BoxTransition::Init(Scene * prev, Scene * next, Game * game) | ||||||
| 	{ | 	{ | ||||||
| 		out_layer_param_.opacity = 0; | 		Transition::Init(prev, next, game); | ||||||
| 		in_layer_param_.opacity = 1; | 
 | ||||||
| 		in_layer_param_.contentBounds = D2D1::RectF( | 		in_layer_param_.opacity = 0; | ||||||
| 			window_size_.width * (1 - process_), |  | ||||||
| 			window_size_.height * (1 - process_), |  | ||||||
| 			window_size_.width * process_, |  | ||||||
| 			window_size_.height * process_ |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| } | 
 | ||||||
|  | 	void BoxTransition::Update() | ||||||
|  | 	{ | ||||||
|  | 		Transition::Update(); | ||||||
|  | 
 | ||||||
|  | 		if (process_ < .5f) | ||||||
|  | 		{ | ||||||
|  | 			out_layer_param_.contentBounds = D2D1::RectF( | ||||||
|  | 				window_size_.width * process_, | ||||||
|  | 				window_size_.height * process_, | ||||||
|  | 				window_size_.width * (1 - process_), | ||||||
|  | 				window_size_.height * (1 - process_) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			out_layer_param_.opacity = 0; | ||||||
|  | 			in_layer_param_.opacity = 1; | ||||||
|  | 			in_layer_param_.contentBounds = D2D1::RectF( | ||||||
|  | 				window_size_.width * (1 - process_), | ||||||
|  | 				window_size_.height * (1 - process_), | ||||||
|  | 				window_size_.width * process_, | ||||||
|  | 				window_size_.height * process_ | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,23 +21,26 @@ | ||||||
| #include "..\e2dtransition.h" | #include "..\e2dtransition.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::EmergeTransition::EmergeTransition(float duration) | namespace easy2d | ||||||
| 	: Transition(duration) |  | ||||||
| { | { | ||||||
| } | 	EmergeTransition::EmergeTransition(float duration) | ||||||
|  | 		: Transition(duration) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| void easy2d::EmergeTransition::Init(Scene * prev, Scene * next, Game * game) | 	void EmergeTransition::Init(Scene * prev, Scene * next, Game * game) | ||||||
| { | 	{ | ||||||
| 	Transition::Init(prev, next, game); | 		Transition::Init(prev, next, game); | ||||||
| 	 |  | ||||||
| 	out_layer_param_.opacity = 1; |  | ||||||
| 	in_layer_param_.opacity = 0; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::EmergeTransition::Update() | 		out_layer_param_.opacity = 1; | ||||||
| { | 		in_layer_param_.opacity = 0; | ||||||
| 	Transition::Update(); | 	} | ||||||
| 
 | 
 | ||||||
| 	out_layer_param_.opacity = 1 - process_; | 	void EmergeTransition::Update() | ||||||
| 	in_layer_param_.opacity = process_; | 	{ | ||||||
| } | 		Transition::Update(); | ||||||
|  | 
 | ||||||
|  | 		out_layer_param_.opacity = 1 - process_; | ||||||
|  | 		in_layer_param_.opacity = process_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,31 +21,34 @@ | ||||||
| #include "..\e2dtransition.h" | #include "..\e2dtransition.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::FadeTransition::FadeTransition(float duration) | namespace easy2d | ||||||
| 	: Transition(duration) |  | ||||||
| { | { | ||||||
| } | 	FadeTransition::FadeTransition(float duration) | ||||||
| 
 | 		: Transition(duration) | ||||||
| void easy2d::FadeTransition::Init(Scene * prev, Scene * next, Game * game) |  | ||||||
| { |  | ||||||
| 	Transition::Init(prev, next, game); |  | ||||||
| 	 |  | ||||||
| 	out_layer_param_.opacity = 1; |  | ||||||
| 	in_layer_param_.opacity = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::FadeTransition::Update() |  | ||||||
| { |  | ||||||
| 	Transition::Update(); |  | ||||||
| 
 |  | ||||||
| 	if (process_ < 0.5) |  | ||||||
| 	{ | 	{ | ||||||
| 		out_layer_param_.opacity = 1 - process_ * 2; | 	} | ||||||
|  | 
 | ||||||
|  | 	void FadeTransition::Init(Scene * prev, Scene * next, Game * game) | ||||||
|  | 	{ | ||||||
|  | 		Transition::Init(prev, next, game); | ||||||
|  | 
 | ||||||
|  | 		out_layer_param_.opacity = 1; | ||||||
| 		in_layer_param_.opacity = 0; | 		in_layer_param_.opacity = 0; | ||||||
| 	} | 	} | ||||||
| 	else | 
 | ||||||
|  | 	void FadeTransition::Update() | ||||||
| 	{ | 	{ | ||||||
| 		out_layer_param_.opacity = 0; | 		Transition::Update(); | ||||||
| 		in_layer_param_.opacity = (process_ - 0.5f) * 2; | 
 | ||||||
|  | 		if (process_ < 0.5) | ||||||
|  | 		{ | ||||||
|  | 			out_layer_param_.opacity = 1 - process_ * 2; | ||||||
|  | 			in_layer_param_.opacity = 0; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			out_layer_param_.opacity = 0; | ||||||
|  | 			in_layer_param_.opacity = (process_ - 0.5f) * 2; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -21,88 +21,91 @@ | ||||||
| #include "..\e2dtransition.h" | #include "..\e2dtransition.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::MoveTransition::MoveTransition(float duration, Direction direction) | namespace easy2d | ||||||
| 	: Transition(duration) |  | ||||||
| 	, direction_(direction) |  | ||||||
| { | { | ||||||
| } | 	MoveTransition::MoveTransition(float duration, Direction direction) | ||||||
| 
 | 		: Transition(duration) | ||||||
| void easy2d::MoveTransition::Init(Scene * prev, Scene * next, Game * game) | 		, direction_(direction) | ||||||
| { |  | ||||||
| 	Transition::Init(prev, next, game); |  | ||||||
| 	 |  | ||||||
| 	switch (direction_) |  | ||||||
| 	{ | 	{ | ||||||
| 	case Direction::Up: |  | ||||||
| 		pos_delta_ = Point(0, -window_size_.height); |  | ||||||
| 		start_pos_ = Point(0, window_size_.height); |  | ||||||
| 		break; |  | ||||||
| 	case Direction::Down: |  | ||||||
| 		pos_delta_ = Point(0, window_size_.height); |  | ||||||
| 		start_pos_ = Point(0, -window_size_.height); |  | ||||||
| 		break; |  | ||||||
| 	case Direction::Left: |  | ||||||
| 		pos_delta_ = Point(-window_size_.width, 0); |  | ||||||
| 		start_pos_ = Point(window_size_.width, 0); |  | ||||||
| 		break; |  | ||||||
| 	case Direction::Right: |  | ||||||
| 		pos_delta_ = Point(window_size_.width, 0); |  | ||||||
| 		start_pos_ = Point(-window_size_.width, 0); |  | ||||||
| 		break; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (out_scene_) | 	void MoveTransition::Init(Scene * prev, Scene * next, Game * game) | ||||||
| 	{ | 	{ | ||||||
| 		out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | 		Transition::Init(prev, next, game); | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	if (in_scene_) |  | ||||||
| 	{ |  | ||||||
| 		in_scene_->SetTransform( |  | ||||||
| 			D2D1::Matrix3x2F::Translation( |  | ||||||
| 				start_pos_.x, |  | ||||||
| 				start_pos_.y |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::MoveTransition::Update() | 		switch (direction_) | ||||||
| { | 		{ | ||||||
| 	Transition::Update(); | 		case Direction::Up: | ||||||
|  | 			pos_delta_ = Point(0, -window_size_.height); | ||||||
|  | 			start_pos_ = Point(0, window_size_.height); | ||||||
|  | 			break; | ||||||
|  | 		case Direction::Down: | ||||||
|  | 			pos_delta_ = Point(0, window_size_.height); | ||||||
|  | 			start_pos_ = Point(0, -window_size_.height); | ||||||
|  | 			break; | ||||||
|  | 		case Direction::Left: | ||||||
|  | 			pos_delta_ = Point(-window_size_.width, 0); | ||||||
|  | 			start_pos_ = Point(window_size_.width, 0); | ||||||
|  | 			break; | ||||||
|  | 		case Direction::Right: | ||||||
|  | 			pos_delta_ = Point(window_size_.width, 0); | ||||||
|  | 			start_pos_ = Point(-window_size_.width, 0); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	if (out_scene_) | 		if (out_scene_) | ||||||
| 	{ | 		{ | ||||||
| 		auto translation = pos_delta_ * process_; | 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
| 		out_scene_->SetTransform( | 		} | ||||||
| 			D2D1::Matrix3x2F::Translation( | 
 | ||||||
| 				translation.x, | 		if (in_scene_) | ||||||
| 				translation.y | 		{ | ||||||
| 			) | 			in_scene_->SetTransform( | ||||||
| 		); | 				D2D1::Matrix3x2F::Translation( | ||||||
|  | 					start_pos_.x, | ||||||
|  | 					start_pos_.y | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (in_scene_) | 	void MoveTransition::Update() | ||||||
| 	{ | 	{ | ||||||
| 		auto translation = start_pos_ + pos_delta_ * process_; | 		Transition::Update(); | ||||||
| 		in_scene_->SetTransform( |  | ||||||
| 			D2D1::Matrix3x2F::Translation( |  | ||||||
| 				translation.x, |  | ||||||
| 				translation.y |  | ||||||
| 			) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::MoveTransition::Reset() | 		if (out_scene_) | ||||||
| { | 		{ | ||||||
| 	if (out_scene_) | 			auto translation = pos_delta_ * process_; | ||||||
| 	{ | 			out_scene_->SetTransform( | ||||||
| 		out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | 				D2D1::Matrix3x2F::Translation( | ||||||
|  | 					translation.x, | ||||||
|  | 					translation.y | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (in_scene_) | ||||||
|  | 		{ | ||||||
|  | 			auto translation = start_pos_ + pos_delta_ * process_; | ||||||
|  | 			in_scene_->SetTransform( | ||||||
|  | 				D2D1::Matrix3x2F::Translation( | ||||||
|  | 					translation.x, | ||||||
|  | 					translation.y | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 
 | ||||||
| 	if (in_scene_) | 	void MoveTransition::Reset() | ||||||
| 	{ | 	{ | ||||||
| 		in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | 		if (out_scene_) | ||||||
|  | 		{ | ||||||
|  | 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (in_scene_) | ||||||
|  | 		{ | ||||||
|  | 			in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -21,84 +21,87 @@ | ||||||
| #include "..\e2dtransition.h" | #include "..\e2dtransition.h" | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::RotationTransition::RotationTransition(float duration, float rotation) | namespace easy2d | ||||||
| 	: Transition(duration) |  | ||||||
| 	, rotation_(rotation) |  | ||||||
| { | { | ||||||
| } | 	RotationTransition::RotationTransition(float duration, float rotation) | ||||||
| 
 | 		: Transition(duration) | ||||||
| void easy2d::RotationTransition::Init(Scene * prev, Scene * next, Game * game) | 		, rotation_(rotation) | ||||||
| { |  | ||||||
| 	Transition::Init(prev, next, game); |  | ||||||
| 
 |  | ||||||
| 	if (out_scene_) |  | ||||||
| 	{ | 	{ | ||||||
| 		out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (in_scene_) | 	void RotationTransition::Init(Scene * prev, Scene * next, Game * game) | ||||||
| 	{ | 	{ | ||||||
| 		in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | 		Transition::Init(prev, next, game); | ||||||
|  | 
 | ||||||
|  | 		if (out_scene_) | ||||||
|  | 		{ | ||||||
|  | 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (in_scene_) | ||||||
|  | 		{ | ||||||
|  | 			in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		in_layer_param_.opacity = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	in_layer_param_.opacity = 0; | 	void RotationTransition::Update() | ||||||
| } | 	{ | ||||||
|  | 		Transition::Update(); | ||||||
| 
 | 
 | ||||||
| void easy2d::RotationTransition::Update() | 		auto center_pos = D2D1::Point2F( | ||||||
| { | 			window_size_.width / 2, | ||||||
| 	Transition::Update(); | 			window_size_.height / 2 | ||||||
|  | 		); | ||||||
| 
 | 
 | ||||||
| 	auto center_pos = D2D1::Point2F( | 		if (process_ < .5f) | ||||||
| 		window_size_.width / 2, | 		{ | ||||||
| 		window_size_.height / 2 | 			if (out_scene_) | ||||||
| 	); | 			{ | ||||||
|  | 				out_scene_->SetTransform( | ||||||
|  | 					D2D1::Matrix3x2F::Scale( | ||||||
|  | 					(.5f - process_) * 2, | ||||||
|  | 						(.5f - process_) * 2, | ||||||
|  | 						center_pos | ||||||
|  | 					) * D2D1::Matrix3x2F::Rotation( | ||||||
|  | 						rotation_ * (.5f - process_) * 2, | ||||||
|  | 						center_pos | ||||||
|  | 					) | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			if (in_scene_) | ||||||
|  | 			{ | ||||||
|  | 				out_layer_param_.opacity = 0; | ||||||
|  | 				in_layer_param_.opacity = 1; | ||||||
| 
 | 
 | ||||||
| 	if (process_ < .5f) | 				in_scene_->SetTransform( | ||||||
|  | 					D2D1::Matrix3x2F::Scale( | ||||||
|  | 					(process_ - .5f) * 2, | ||||||
|  | 						(process_ - .5f) * 2, | ||||||
|  | 						center_pos | ||||||
|  | 					) * D2D1::Matrix3x2F::Rotation( | ||||||
|  | 						rotation_ * (process_ - .5f) * 2, | ||||||
|  | 						center_pos | ||||||
|  | 					) | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void RotationTransition::Reset() | ||||||
| 	{ | 	{ | ||||||
| 		if (out_scene_) | 		if (out_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			out_scene_->SetTransform( | 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
| 				D2D1::Matrix3x2F::Scale( |  | ||||||
| 					(.5f - process_) * 2, |  | ||||||
| 					(.5f - process_) * 2, |  | ||||||
| 					center_pos |  | ||||||
| 				) * D2D1::Matrix3x2F::Rotation( |  | ||||||
| 					rotation_ * (.5f - process_) * 2, |  | ||||||
| 					center_pos |  | ||||||
| 				) |  | ||||||
| 			); |  | ||||||
| 		} | 		} | ||||||
| 	} | 
 | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		if (in_scene_) | 		if (in_scene_) | ||||||
| 		{ | 		{ | ||||||
| 			out_layer_param_.opacity = 0; | 			in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||||
| 			in_layer_param_.opacity = 1; |  | ||||||
| 
 |  | ||||||
| 			in_scene_->SetTransform( |  | ||||||
| 				D2D1::Matrix3x2F::Scale( |  | ||||||
| 					(process_ - .5f) * 2, |  | ||||||
| 					(process_ - .5f) * 2, |  | ||||||
| 					center_pos |  | ||||||
| 				) * D2D1::Matrix3x2F::Rotation( |  | ||||||
| 					rotation_ * (process_ - .5f) * 2, |  | ||||||
| 					center_pos |  | ||||||
| 				) |  | ||||||
| 			); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void easy2d::RotationTransition::Reset() |  | ||||||
| { |  | ||||||
| 	if (out_scene_) |  | ||||||
| 	{ |  | ||||||
| 		out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	if (in_scene_) |  | ||||||
| 	{ |  | ||||||
| 		in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -22,143 +22,146 @@ | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| #include "..\e2dmodule.h" | #include "..\e2dmodule.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Transition::Transition(float duration) | namespace easy2d | ||||||
| 	: done_(false) |  | ||||||
| 	, started_() |  | ||||||
| 	, process_(0) |  | ||||||
| 	, window_size_() |  | ||||||
| 	, out_scene_(nullptr) |  | ||||||
| 	, in_scene_(nullptr) |  | ||||||
| 	, out_layer_(nullptr) |  | ||||||
| 	, in_layer_(nullptr) |  | ||||||
| 	, out_layer_param_() |  | ||||||
| 	, in_layer_param_() |  | ||||||
| { | { | ||||||
| 	duration_ = std::max(duration, 0.f); | 	Transition::Transition(float duration) | ||||||
| } | 		: done_(false) | ||||||
| 
 | 		, started_() | ||||||
| easy2d::Transition::~Transition() | 		, process_(0) | ||||||
| { | 		, window_size_() | ||||||
| 	SafeRelease(out_layer_); | 		, out_scene_(nullptr) | ||||||
| 	SafeRelease(in_layer_); | 		, in_scene_(nullptr) | ||||||
| 	SafeRelease(out_scene_); | 		, out_layer_(nullptr) | ||||||
| 	SafeRelease(in_scene_); | 		, in_layer_(nullptr) | ||||||
| } | 		, out_layer_param_() | ||||||
| 
 | 		, in_layer_param_() | ||||||
| bool easy2d::Transition::IsDone() |  | ||||||
| { |  | ||||||
| 	return done_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Transition::Init(Scene * prev, Scene * next, Game * game) |  | ||||||
| { |  | ||||||
| 	started_ = Time::Now(); |  | ||||||
| 	out_scene_ = prev; |  | ||||||
| 	in_scene_ = next; |  | ||||||
| 
 |  | ||||||
| 	if (out_scene_) |  | ||||||
| 		out_scene_->Retain(); |  | ||||||
| 
 |  | ||||||
| 	if (in_scene_) |  | ||||||
| 		in_scene_->Retain(); |  | ||||||
| 	 |  | ||||||
| 	auto graphics = Device::GetGraphics(); |  | ||||||
| 	if (in_scene_) |  | ||||||
| 	{ | 	{ | ||||||
| 		ThrowIfFailed( | 		duration_ = std::max(duration, 0.f); | ||||||
| 			graphics->GetRenderTarget()->CreateLayer(&in_layer_) |  | ||||||
| 		); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (out_scene_) | 	Transition::~Transition() | ||||||
| 	{ | 	{ | ||||||
| 		ThrowIfFailed( | 		SafeRelease(out_layer_); | ||||||
| 			graphics->GetRenderTarget()->CreateLayer(&out_layer_) | 		SafeRelease(in_layer_); | ||||||
| 		); | 		SafeRelease(out_scene_); | ||||||
|  | 		SafeRelease(in_scene_); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	window_size_ = game->GetSize(); | 	bool Transition::IsDone() | ||||||
| 	out_layer_param_ = in_layer_param_ = D2D1::LayerParameters( |  | ||||||
| 		D2D1::RectF( |  | ||||||
| 			0.f, |  | ||||||
| 			0.f, |  | ||||||
| 			window_size_.width, |  | ||||||
| 			window_size_.height |  | ||||||
| 		), |  | ||||||
| 		nullptr, |  | ||||||
| 		D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, |  | ||||||
| 		D2D1::Matrix3x2F::Identity(), |  | ||||||
| 		1.f, |  | ||||||
| 		graphics->GetSolidBrush(), |  | ||||||
| 		D2D1_LAYER_OPTIONS_NONE |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void easy2d::Transition::Update() |  | ||||||
| { |  | ||||||
| 	if (duration_ == 0) |  | ||||||
| 	{ | 	{ | ||||||
| 		process_ = 1; | 		return done_; | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		process_ = (Time::Now() - started_).Seconds() / duration_; |  | ||||||
| 		process_ = std::min(process_, 1.f); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (process_ >= 1) | 	void Transition::Init(Scene * prev, Scene * next, Game * game) | ||||||
| 	{ | 	{ | ||||||
| 		this->Stop(); | 		started_ = Time::Now(); | ||||||
| 	} | 		out_scene_ = prev; | ||||||
| } | 		in_scene_ = next; | ||||||
| 
 | 
 | ||||||
| void easy2d::Transition::Draw() | 		if (out_scene_) | ||||||
| { | 			out_scene_->Retain(); | ||||||
| 	auto render_target = Device::GetGraphics()->GetRenderTarget(); |  | ||||||
| 
 | 
 | ||||||
| 	if (out_scene_) | 		if (in_scene_) | ||||||
| 	{ | 			in_scene_->Retain(); | ||||||
| 		render_target->SetTransform(out_scene_->GetTransform()); | 
 | ||||||
| 		render_target->PushAxisAlignedClip( | 		auto graphics = Device::GetGraphics(); | ||||||
|  | 		if (in_scene_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				graphics->GetRenderTarget()->CreateLayer(&in_layer_) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (out_scene_) | ||||||
|  | 		{ | ||||||
|  | 			ThrowIfFailed( | ||||||
|  | 				graphics->GetRenderTarget()->CreateLayer(&out_layer_) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		window_size_ = game->GetSize(); | ||||||
|  | 		out_layer_param_ = in_layer_param_ = D2D1::LayerParameters( | ||||||
| 			D2D1::RectF( | 			D2D1::RectF( | ||||||
| 				0.f, | 				0.f, | ||||||
| 				0.f, | 				0.f, | ||||||
| 				window_size_.width, | 				window_size_.width, | ||||||
| 				window_size_.height | 				window_size_.height | ||||||
| 			), | 			), | ||||||
| 			D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | 			nullptr, | ||||||
|  | 			D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | ||||||
|  | 			D2D1::Matrix3x2F::Identity(), | ||||||
|  | 			1.f, | ||||||
|  | 			graphics->GetSolidBrush(), | ||||||
|  | 			D2D1_LAYER_OPTIONS_NONE | ||||||
| 		); | 		); | ||||||
| 		render_target->PushLayer(out_layer_param_, out_layer_); |  | ||||||
| 
 |  | ||||||
| 		out_scene_->Draw(); |  | ||||||
| 
 |  | ||||||
| 		render_target->PopLayer(); |  | ||||||
| 		render_target->PopAxisAlignedClip(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (in_scene_) | 	void Transition::Update() | ||||||
| 	{ | 	{ | ||||||
| 		render_target->SetTransform(in_scene_->GetTransform()); | 		if (duration_ == 0) | ||||||
| 		render_target->PushAxisAlignedClip( | 		{ | ||||||
| 			D2D1::RectF( | 			process_ = 1; | ||||||
| 				0.f, | 		} | ||||||
| 				0.f, | 		else | ||||||
| 				window_size_.width, | 		{ | ||||||
| 				window_size_.height | 			process_ = (Time::Now() - started_).Seconds() / duration_; | ||||||
| 			), | 			process_ = std::min(process_, 1.f); | ||||||
| 			D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | 		} | ||||||
| 		); |  | ||||||
| 		render_target->PushLayer(in_layer_param_, in_layer_); |  | ||||||
| 
 | 
 | ||||||
| 		in_scene_->Draw(); | 		if (process_ >= 1) | ||||||
| 
 | 		{ | ||||||
| 		render_target->PopLayer(); | 			this->Stop(); | ||||||
| 		render_target->PopAxisAlignedClip(); | 		} | ||||||
| 	} | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void easy2d::Transition::Stop() | 	void Transition::Draw() | ||||||
| { | 	{ | ||||||
| 	done_ = true; | 		auto render_target = Device::GetGraphics()->GetRenderTarget(); | ||||||
| 	Reset(); | 
 | ||||||
| } | 		if (out_scene_) | ||||||
|  | 		{ | ||||||
|  | 			render_target->SetTransform(out_scene_->GetTransform()); | ||||||
|  | 			render_target->PushAxisAlignedClip( | ||||||
|  | 				D2D1::RectF( | ||||||
|  | 					0.f, | ||||||
|  | 					0.f, | ||||||
|  | 					window_size_.width, | ||||||
|  | 					window_size_.height | ||||||
|  | 				), | ||||||
|  | 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | ||||||
|  | 			); | ||||||
|  | 			render_target->PushLayer(out_layer_param_, out_layer_); | ||||||
|  | 
 | ||||||
|  | 			out_scene_->Draw(); | ||||||
|  | 
 | ||||||
|  | 			render_target->PopLayer(); | ||||||
|  | 			render_target->PopAxisAlignedClip(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (in_scene_) | ||||||
|  | 		{ | ||||||
|  | 			render_target->SetTransform(in_scene_->GetTransform()); | ||||||
|  | 			render_target->PushAxisAlignedClip( | ||||||
|  | 				D2D1::RectF( | ||||||
|  | 					0.f, | ||||||
|  | 					0.f, | ||||||
|  | 					window_size_.width, | ||||||
|  | 					window_size_.height | ||||||
|  | 				), | ||||||
|  | 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | ||||||
|  | 			); | ||||||
|  | 			render_target->PushLayer(in_layer_param_, in_layer_); | ||||||
|  | 
 | ||||||
|  | 			in_scene_->Draw(); | ||||||
|  | 
 | ||||||
|  | 			render_target->PopLayer(); | ||||||
|  | 			render_target->PopAxisAlignedClip(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Transition::Stop() | ||||||
|  | 	{ | ||||||
|  | 		done_ = true; | ||||||
|  | 		Reset(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,63 +20,69 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| static const UINT kRedShift = 16; | namespace easy2d | ||||||
| static const UINT kGreenShift = 8; |  | ||||||
| static const UINT kBlueShift = 0; |  | ||||||
| 
 |  | ||||||
| static const UINT kRedMask = 0xff << kRedShift; |  | ||||||
| static const UINT kGreenMask = 0xff << kGreenShift; |  | ||||||
| static const UINT kBlueMask = 0xff << kBlueShift; |  | ||||||
| 
 |  | ||||||
| easy2d::Color::Color() |  | ||||||
| 	: r(0) |  | ||||||
| 	, g(0) |  | ||||||
| 	, b(0) |  | ||||||
| 	, a(1.f) |  | ||||||
| { | { | ||||||
| } | 	namespace | ||||||
|  | 	{ | ||||||
|  | 		const UINT RED_SHIFT = 16; | ||||||
|  | 		const UINT GREEN_SHIFT = 8; | ||||||
|  | 		const UINT BLUE_SHIFT = 0; | ||||||
| 
 | 
 | ||||||
| easy2d::Color::Color(float r, float g, float b) | 		const UINT RED_MASK = 0xff << RED_SHIFT; | ||||||
| 	: r(r) | 		const UINT GREEN_MASK = 0xff << GREEN_SHIFT; | ||||||
| 	, g(g) | 		const UINT BLUE_MASK = 0xff << BLUE_SHIFT; | ||||||
| 	, b(b) | 	} | ||||||
| 	, a(1.f) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Color::Color(float r, float g, float b, float alpha) | 	Color::Color() | ||||||
| 	: r(r) | 		: r(0) | ||||||
| 	, g(g) | 		, g(0) | ||||||
| 	, b(b) | 		, b(0) | ||||||
| 	, a(alpha) | 		, a(1.f) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Color::Color(UINT rgb) | 	Color::Color(float r, float g, float b) | ||||||
| 	: r(((rgb & kRedMask) >> kRedShift) / 255.f) | 		: r(r) | ||||||
| 	, g(((rgb & kGreenMask) >> kGreenShift) / 255.f) | 		, g(g) | ||||||
| 	, b(((rgb & kBlueMask) >> kBlueShift) / 255.f) | 		, b(b) | ||||||
| 	, a(1.f) | 		, a(1.f) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Color::Color(UINT rgb, float alpha) | 	Color::Color(float r, float g, float b, float alpha) | ||||||
| 	: r(((rgb & kRedMask) >> kRedShift) / 255.f) | 		: r(r) | ||||||
| 	, g(((rgb & kGreenMask) >> kGreenShift) / 255.f) | 		, g(g) | ||||||
| 	, b(((rgb & kBlueMask) >> kBlueShift) / 255.f) | 		, b(b) | ||||||
| 	, a(alpha) | 		, a(alpha) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Color::Color(const D2D1_COLOR_F& color) | 	Color::Color(UINT rgb) | ||||||
| 	: r(color.r) | 		: r(((rgb & RED_MASK) >> RED_SHIFT) / 255.f) | ||||||
| 	, g(color.g) | 		, g(((rgb & GREEN_MASK) >> GREEN_SHIFT) / 255.f) | ||||||
| 	, b(color.b) | 		, b(((rgb & BLUE_MASK) >> BLUE_SHIFT) / 255.f) | ||||||
| 	, a(color.a) | 		, a(1.f) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Color::operator D2D1_COLOR_F() const | 	Color::Color(UINT rgb, float alpha) | ||||||
| { | 		: r(((rgb & RED_MASK) >> RED_SHIFT) / 255.f) | ||||||
| 	return D2D1::ColorF(r, g, b, a); | 		, g(((rgb & GREEN_MASK) >> GREEN_SHIFT) / 255.f) | ||||||
| } | 		, b(((rgb & BLUE_MASK) >> BLUE_SHIFT) / 255.f) | ||||||
|  | 		, a(alpha) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Color::Color(const D2D1_COLOR_F& color) | ||||||
|  | 		: r(color.r) | ||||||
|  | 		, g(color.g) | ||||||
|  | 		, b(color.b) | ||||||
|  | 		, a(color.a) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Color::operator D2D1_COLOR_F() const | ||||||
|  | 	{ | ||||||
|  | 		return D2D1::ColorF(r, g, b, a); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -22,275 +22,288 @@ | ||||||
| #include <regex> | #include <regex> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| const easy2d::Duration easy2d::Duration::Millisecond = easy2d::Duration(1); | namespace easy2d | ||||||
| const easy2d::Duration easy2d::Duration::Second = 1000 * easy2d::Duration::Millisecond; |  | ||||||
| const easy2d::Duration easy2d::Duration::Minute = 60 * easy2d::Duration::Second; |  | ||||||
| const easy2d::Duration easy2d::Duration::Hour = 60 * easy2d::Duration::Minute; |  | ||||||
| 
 |  | ||||||
| easy2d::Duration::Duration() |  | ||||||
| 	: milliseconds_(0) |  | ||||||
| { | { | ||||||
| } | 	const Duration Duration::Millisecond = Duration(1); | ||||||
|  | 	const Duration Duration::Second = 1000 * Duration::Millisecond; | ||||||
|  | 	const Duration Duration::Minute = 60 * Duration::Second; | ||||||
|  | 	const Duration Duration::Hour = 60 * Duration::Minute; | ||||||
| 
 | 
 | ||||||
| easy2d::Duration::Duration(int milliseconds) | 	namespace | ||||||
| 	: milliseconds_(milliseconds) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int easy2d::Duration::Milliseconds() const |  | ||||||
| { |  | ||||||
| 	return milliseconds_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Duration::Seconds() const |  | ||||||
| { |  | ||||||
| 	int64_t sec = milliseconds_ / Second.milliseconds_; |  | ||||||
| 	int64_t ms = milliseconds_ % Second.milliseconds_; |  | ||||||
| 	return static_cast<float>(sec) + static_cast<float>(ms) / 1000.f; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Duration::Minutes() const |  | ||||||
| { |  | ||||||
| 	int64_t min = milliseconds_ / Minute.milliseconds_; |  | ||||||
| 	int64_t ms = milliseconds_ % Minute.milliseconds_; |  | ||||||
| 	return static_cast<float>(min) + static_cast<float>(ms) / (60 * 1000.f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float easy2d::Duration::Hours() const |  | ||||||
| { |  | ||||||
| 	int64_t hour = milliseconds_ / Hour.milliseconds_; |  | ||||||
| 	int64_t ms = milliseconds_ % Hour.milliseconds_; |  | ||||||
| 	return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Duration easy2d::Duration::Parse(const std::wstring & str) |  | ||||||
| { |  | ||||||
| 	typedef std::map<std::wstring, Duration> UnitMap; |  | ||||||
| 	static const auto regex = std::wregex(L"[-+]?([0-9]*(\\.[0-9]*)?[a-z]+)+"); |  | ||||||
| 	static const auto unit_map = UnitMap{{L"ms", Millisecond}, {L"s", Second}, {L"m", Minute}, {L"h", Hour}}; |  | ||||||
| 
 |  | ||||||
| 	size_t len = str.length(); |  | ||||||
| 	size_t pos = 0; |  | ||||||
| 	bool negative = false; |  | ||||||
| 	Duration d; |  | ||||||
| 
 |  | ||||||
| 	if (!std::regex_match(str, regex)) |  | ||||||
| 	{ | 	{ | ||||||
| 		E2D_WARNING("Duration::Parse: invalid duration"); | 		const auto duration_regex = std::wregex(L"[-+]?([0-9]*(\\.[0-9]*)?[a-z]+)+"); | ||||||
|  | 
 | ||||||
|  | 		typedef std::map<std::wstring, Duration> UnitMap; | ||||||
|  | 		const auto unit_map = UnitMap{ | ||||||
|  | 			{L"ms", Duration::Millisecond}, | ||||||
|  | 			{L"s", Duration::Second}, | ||||||
|  | 			{L"m", Duration::Minute}, | ||||||
|  | 			{L"h", Duration::Hour} | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Duration::Duration() | ||||||
|  | 		: milliseconds_(0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Duration::Duration(int milliseconds) | ||||||
|  | 		: milliseconds_(milliseconds) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int Duration::Milliseconds() const | ||||||
|  | 	{ | ||||||
|  | 		return milliseconds_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Duration::Seconds() const | ||||||
|  | 	{ | ||||||
|  | 		int64_t sec = milliseconds_ / Second.milliseconds_; | ||||||
|  | 		int64_t ms = milliseconds_ % Second.milliseconds_; | ||||||
|  | 		return static_cast<float>(sec) + static_cast<float>(ms) / 1000.f; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Duration::Minutes() const | ||||||
|  | 	{ | ||||||
|  | 		int64_t min = milliseconds_ / Minute.milliseconds_; | ||||||
|  | 		int64_t ms = milliseconds_ % Minute.milliseconds_; | ||||||
|  | 		return static_cast<float>(min) + static_cast<float>(ms) / (60 * 1000.f); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	float Duration::Hours() const | ||||||
|  | 	{ | ||||||
|  | 		int64_t hour = milliseconds_ / Hour.milliseconds_; | ||||||
|  | 		int64_t ms = milliseconds_ % Hour.milliseconds_; | ||||||
|  | 		return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Duration Duration::Parse(const std::wstring & str) | ||||||
|  | 	{ | ||||||
|  | 		size_t len = str.length(); | ||||||
|  | 		size_t pos = 0; | ||||||
|  | 		bool negative = false; | ||||||
|  | 		Duration d; | ||||||
|  | 
 | ||||||
|  | 		if (!std::regex_match(str, duration_regex)) | ||||||
|  | 		{ | ||||||
|  | 			E2D_WARNING("Duration::Parse: invalid duration"); | ||||||
|  | 			return d; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (str.empty() || str == L"0") { return d; } | ||||||
|  | 
 | ||||||
|  | 		// ·ûºÅλ
 | ||||||
|  | 		if (str[0] == L'-' || str[0] == L'+') | ||||||
|  | 		{ | ||||||
|  | 			negative = (str[0] == L'-'); | ||||||
|  | 			pos++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		while (pos < len) | ||||||
|  | 		{ | ||||||
|  | 			// ÊýÖµ
 | ||||||
|  | 			size_t i = pos; | ||||||
|  | 			for (; i < len; ++i) | ||||||
|  | 			{ | ||||||
|  | 				wchar_t ch = str[i]; | ||||||
|  | 				if (!(ch == L'.' || L'0' <= ch && ch <= L'9')) | ||||||
|  | 				{ | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			std::wstring num_str = str.substr(pos, i - pos); | ||||||
|  | 			pos = i; | ||||||
|  | 
 | ||||||
|  | 			if (num_str.empty() || num_str == L".") | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("Duration::Parse: invalid duration"); | ||||||
|  | 				return Duration(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// µ¥Î»
 | ||||||
|  | 			for (; i < len; ++i) | ||||||
|  | 			{ | ||||||
|  | 				wchar_t ch = str[i]; | ||||||
|  | 				if (ch == L'.' || L'0' <= ch && ch <= L'9') | ||||||
|  | 				{ | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			std::wstring unit_str = str.substr(pos, i - pos); | ||||||
|  | 			pos = i; | ||||||
|  | 
 | ||||||
|  | 			if (unit_map.find(unit_str) == unit_map.end()) | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("Duration::Parse: invalid duration"); | ||||||
|  | 				return Duration(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			double num = std::stod(num_str); | ||||||
|  | 			Duration unit = unit_map.at(unit_str); | ||||||
|  | 			d += unit * num; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (negative) | ||||||
|  | 		{ | ||||||
|  | 			d.milliseconds_ = -d.milliseconds_; | ||||||
|  | 		} | ||||||
| 		return d; | 		return d; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (str.empty() || str == L"0") { return d; } | 	bool Duration::operator==(const Duration & other) const | ||||||
| 
 |  | ||||||
| 	// ·ûºÅλ
 |  | ||||||
| 	if (str[0] == L'-' || str[0] == L'+') |  | ||||||
| 	{ | 	{ | ||||||
| 		negative = (str[0] == L'-'); | 		return milliseconds_ == other.milliseconds_; | ||||||
| 		pos++; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	while (pos < len) | 	bool Duration::operator!=(const Duration & other) const | ||||||
| 	{ | 	{ | ||||||
| 		// ÊýÖµ
 | 		return milliseconds_ != other.milliseconds_; | ||||||
| 		size_t i = pos; |  | ||||||
| 		for (; i < len; ++i) |  | ||||||
| 		{ |  | ||||||
| 			wchar_t ch = str[i]; |  | ||||||
| 			if (!(ch == L'.' || L'0' <= ch && ch <= L'9')) |  | ||||||
| 			{ |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		std::wstring num_str = str.substr(pos, i - pos); |  | ||||||
| 		pos = i; |  | ||||||
| 
 |  | ||||||
| 		if (num_str.empty() || num_str == L".") |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("Duration::Parse: invalid duration"); |  | ||||||
| 			return Duration(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// µ¥Î»
 |  | ||||||
| 		for (; i < len; ++i) |  | ||||||
| 		{ |  | ||||||
| 			wchar_t ch = str[i]; |  | ||||||
| 			if (ch == L'.' || L'0' <= ch && ch <= L'9') |  | ||||||
| 			{ |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		std::wstring unit_str = str.substr(pos, i - pos); |  | ||||||
| 		pos = i; |  | ||||||
| 
 |  | ||||||
| 		if (unit_map.find(unit_str) == unit_map.end()) |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("Duration::Parse: invalid duration"); |  | ||||||
| 			return Duration(); |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		double num = std::stod(num_str); |  | ||||||
| 		Duration unit = unit_map.at(unit_str); |  | ||||||
| 		d += unit * num; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (negative) | 	bool Duration::operator>(const Duration & other) const | ||||||
| 	{ | 	{ | ||||||
| 		d.milliseconds_ = -d.milliseconds_; | 		return milliseconds_ > other.milliseconds_; | ||||||
| 	} | 	} | ||||||
| 	return d; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator==(const Duration & other) const | 	bool Duration::operator>=(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ == other.milliseconds_; | 		return milliseconds_ >= other.milliseconds_; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator!=(const Duration & other) const | 	bool Duration::operator<(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ != other.milliseconds_; | 		return milliseconds_ < other.milliseconds_; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator>(const Duration & other) const | 	bool Duration::operator<=(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ > other.milliseconds_; | 		return milliseconds_ <= other.milliseconds_; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator>=(const Duration & other) const | 	Duration Duration::operator+(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ >= other.milliseconds_; | 		return Duration(milliseconds_ + other.milliseconds_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator<(const Duration & other) const | 	Duration Duration::operator-(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ < other.milliseconds_; | 		return Duration(milliseconds_ - other.milliseconds_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Duration::operator<=(const Duration & other) const | 	Duration Duration::operator-() const | ||||||
| { | 	{ | ||||||
| 	return milliseconds_ <= other.milliseconds_; | 		return Duration(-milliseconds_); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator+(const Duration & other) const | 	Duration Duration::operator*(int value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(milliseconds_ + other.milliseconds_); | 		return Duration(milliseconds_ * value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator-(const Duration & other) const | 	Duration Duration::operator/(int value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(milliseconds_ - other.milliseconds_); | 		return Duration(milliseconds_ / value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator-() const | 	Duration Duration::operator*(float value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(-milliseconds_); | 		return Duration(static_cast<int>(milliseconds_ * value)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator*(int value) const | 	Duration Duration::operator/(float value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(milliseconds_ * value); | 		return Duration(static_cast<int>(milliseconds_ / value)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator/(int value) const | 	Duration Duration::operator*(double value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(milliseconds_ / value); | 		return Duration(static_cast<int>(milliseconds_ * value)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator*(float value) const | 	Duration Duration::operator/(double value) const | ||||||
| { | 	{ | ||||||
| 	return Duration(static_cast<int>(milliseconds_ * value)); | 		return Duration(static_cast<int>(milliseconds_ / value)); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator/(float value) const | 	Duration & Duration::operator+=(const Duration &other) | ||||||
| { | 	{ | ||||||
| 	return Duration(static_cast<int>(milliseconds_ / value)); | 		milliseconds_ += other.milliseconds_; | ||||||
| } | 		return (*this); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator*(double value) const | 	Duration & Duration::operator-=(const Duration &other) | ||||||
| { | 	{ | ||||||
| 	return Duration(static_cast<int>(milliseconds_ * value)); | 		milliseconds_ -= other.milliseconds_; | ||||||
| } | 		return (*this); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Duration::operator/(double value) const | 	Duration & Duration::operator*=(int value) | ||||||
| { | 	{ | ||||||
| 	return Duration(static_cast<int>(milliseconds_ / value)); | 		milliseconds_ *= value; | ||||||
| } | 		return (*this); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator+=(const Duration &other) | 	Duration & Duration::operator/=(int value) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ += other.milliseconds_; | 		milliseconds_ /= value; | ||||||
| 	return (*this); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator-=(const Duration &other) | 	Duration & Duration::operator*=(float value) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ -= other.milliseconds_; | 		milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||||
| 	return (*this); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator*=(int value) | 	Duration & Duration::operator/=(float value) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ *= value; | 		milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||||
| 	return (*this); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator/=(int value) | 	Duration & Duration::operator*=(double value) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ /= value; | 		milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||||
| 	return (*this); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator*=(float value) | 	Duration & Duration::operator/=(double value) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ = static_cast<int>(milliseconds_ * value); | 		milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||||
| 	return (*this); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator/=(float value) | 	Duration operator*(int value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ = static_cast<int>(milliseconds_ / value); | 		return dur * value; | ||||||
| 	return (*this); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator*=(double value) | 	Duration operator/(int value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ = static_cast<int>(milliseconds_ * value); | 		return dur / value; | ||||||
| 	return (*this); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Duration & easy2d::Duration::operator/=(double value) | 	Duration operator*(float value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	milliseconds_ = static_cast<int>(milliseconds_ / value); | 		return dur * value; | ||||||
| 	return (*this); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::operator*(int value, const Duration & dur) | 	Duration operator/(float value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	return dur * value; | 		return dur / value; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::operator/(int value, const Duration & dur) | 	Duration operator*(double value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	return dur / value; | 		return dur * value; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::operator*(float value, const Duration & dur) | 	Duration operator/(double value, const Duration & dur) | ||||||
| { | 	{ | ||||||
| 	return dur * value; | 		return dur / value; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::operator/(float value, const Duration & dur) |  | ||||||
| { |  | ||||||
| 	return dur / value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Duration easy2d::operator*(double value, const Duration & dur) |  | ||||||
| { |  | ||||||
| 	return dur * value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Duration easy2d::operator/(double value, const Duration & dur) |  | ||||||
| { |  | ||||||
| 	return dur / value; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -21,10 +21,13 @@ | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Font::Font(const std::wstring & family, float size, UINT weight, bool italic) | namespace easy2d | ||||||
| 	: family(family) |  | ||||||
| 	, size(size) |  | ||||||
| 	, weight(weight) |  | ||||||
| 	, italic(italic) |  | ||||||
| { | { | ||||||
|  | 	Font::Font(const std::wstring & family, float size, UINT weight, bool italic) | ||||||
|  | 		: family(family) | ||||||
|  | 		, size(size) | ||||||
|  | 		, weight(weight) | ||||||
|  | 		, italic(italic) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -22,63 +22,66 @@ | ||||||
| #include <cmath> | #include <cmath> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Point::Point() | namespace easy2d | ||||||
| { | { | ||||||
| 	x = 0; | 	Point::Point() | ||||||
| 	y = 0; | 	{ | ||||||
| } | 		x = 0; | ||||||
|  | 		y = 0; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point::Point(float x, float y) | 	Point::Point(float x, float y) | ||||||
| { | 	{ | ||||||
| 	this->x = x; | 		this->x = x; | ||||||
| 	this->y = y; | 		this->y = y; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point::Point(const Point & other) | 	Point::Point(const Point & other) | ||||||
| { | 	{ | ||||||
| 	x = other.x; | 		x = other.x; | ||||||
| 	y = other.y; | 		y = other.y; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Point::operator+(const Point & p) const | 	Point Point::operator+(const Point & p) const | ||||||
| { | 	{ | ||||||
| 	return Point(x + p.x, y + p.y); | 		return Point(x + p.x, y + p.y); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Point::operator-(const Point & p) const | 	Point Point::operator-(const Point & p) const | ||||||
| { | 	{ | ||||||
| 	return Point(x - p.x, y - p.y); | 		return Point(x - p.x, y - p.y); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Point::operator*(float value) const | 	Point Point::operator*(float value) const | ||||||
| { | 	{ | ||||||
| 	return Point(x * value, y * value); | 		return Point(x * value, y * value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Point::operator/(float value) const | 	Point Point::operator/(float value) const | ||||||
| { | 	{ | ||||||
| 	return Point(x / value, y / value); | 		return Point(x / value, y / value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point::operator easy2d::Size() const | 	Point::operator Size() const | ||||||
| { | 	{ | ||||||
| 	return Size(x, y); | 		return Size(x, y); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| float easy2d::Point::Distance(const Point &p1, const Point &p2) | 	float Point::Distance(const Point &p1, const Point &p2) | ||||||
| { | 	{ | ||||||
| 	return sqrt( | 		return sqrt( | ||||||
| 		(p1.x - p2.x) * (p1.x - p2.x) +  | 			(p1.x - p2.x) * (p1.x - p2.x) + | ||||||
| 		(p1.y - p2.y) * (p1.y - p2.y) | 			(p1.y - p2.y) * (p1.y - p2.y) | ||||||
| 	); | 		); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Point easy2d::Point::operator-() const | 	Point Point::operator-() const | ||||||
| { | 	{ | ||||||
| 	return Point(-x, -y); | 		return Point(-x, -y); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Point::operator==(const Point & point) const | 	bool Point::operator==(const Point & point) const | ||||||
| { | 	{ | ||||||
| 	return (x == point.x) && (y == point.y); | 		return (x == point.x) && (y == point.y); | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -20,9 +20,12 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| std::default_random_engine &easy2d::Random::GetEngine() | namespace easy2d | ||||||
| { | { | ||||||
| 	static std::random_device device; | 	std::default_random_engine &Random::GetEngine() | ||||||
| 	static std::default_random_engine engine(device()); | 	{ | ||||||
| 	return engine; | 		static std::random_device device; | ||||||
| } | 		static std::default_random_engine engine(device()); | ||||||
|  | 		return engine; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,56 +20,59 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Rect::Rect(void) | namespace easy2d | ||||||
| 	: origin() |  | ||||||
| 	, size() |  | ||||||
| { | { | ||||||
| } | 	Rect::Rect(void) | ||||||
| 
 | 		: origin() | ||||||
| easy2d::Rect::Rect(float x, float y, float width, float height) | 		, size() | ||||||
| 	: origin(x, y) |  | ||||||
| 	, size(width, height) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Rect::Rect(const Point& pos, const Size& size) |  | ||||||
| 	: origin(pos.x, pos.y) |  | ||||||
| 	, size(size.width, size.height) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Rect::Rect(const Rect& other) |  | ||||||
| 	: origin(other.origin.x, other.origin.y) |  | ||||||
| 	, size(other.size.width, other.size.height) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Rect& easy2d::Rect::operator= (const Rect& other) |  | ||||||
| { |  | ||||||
| 	origin = other.origin; |  | ||||||
| 	size = other.size; |  | ||||||
| 	return *this; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Rect::operator==(const Rect & rect) const |  | ||||||
| { |  | ||||||
| 	return (origin == rect.origin) && (size == rect.size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Rect::ContainsPoint(const Point& point) const |  | ||||||
| { |  | ||||||
| 	if (point.x >= origin.x && point.x <= (origin.y + size.height) |  | ||||||
| 		&& point.y >= origin.y && point.y <= (origin.y + size.height)) |  | ||||||
| 	{ | 	{ | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Rect::Intersects(const Rect& rect) const | 	Rect::Rect(float x, float y, float width, float height) | ||||||
| { | 		: origin(x, y) | ||||||
| 	return !((origin.x + size.width)			< rect.origin.x || | 		, size(width, height) | ||||||
| 			(rect.origin.x + rect.size.width)	<	  origin.x || | 	{ | ||||||
| 			(origin.y + size.height)			< rect.origin.y || | 	} | ||||||
| 			(rect.origin.y + rect.size.height)	<	  origin.y); | 
 | ||||||
| } | 	Rect::Rect(const Point& pos, const Size& size) | ||||||
|  | 		: origin(pos.x, pos.y) | ||||||
|  | 		, size(size.width, size.height) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Rect::Rect(const Rect& other) | ||||||
|  | 		: origin(other.origin.x, other.origin.y) | ||||||
|  | 		, size(other.size.width, other.size.height) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Rect& Rect::operator= (const Rect& other) | ||||||
|  | 	{ | ||||||
|  | 		origin = other.origin; | ||||||
|  | 		size = other.size; | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Rect::operator==(const Rect & rect) const | ||||||
|  | 	{ | ||||||
|  | 		return (origin == rect.origin) && (size == rect.size); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Rect::ContainsPoint(const Point& point) const | ||||||
|  | 	{ | ||||||
|  | 		if (point.x >= origin.x && point.x <= (origin.y + size.height) | ||||||
|  | 			&& point.y >= origin.y && point.y <= (origin.y + size.height)) | ||||||
|  | 		{ | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Rect::Intersects(const Rect& rect) const | ||||||
|  | 	{ | ||||||
|  | 		return !((origin.x + size.width) < rect.origin.x || | ||||||
|  | 			(rect.origin.x + rect.size.width) < origin.x || | ||||||
|  | 			(origin.y + size.height) < rect.origin.y || | ||||||
|  | 			(rect.origin.y + rect.size.height) < origin.y); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,35 +20,38 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dobject.h" | #include "..\e2dobject.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Ref::Ref() | namespace easy2d | ||||||
| { | { | ||||||
| 	// 当对象被创建时,意味着它已经被引用了一次
 | 	Ref::Ref() | ||||||
| 	ref_count_ = 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| easy2d::Ref::~Ref() |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LONG easy2d::Ref::Retain() |  | ||||||
| { |  | ||||||
| 	return ::InterlockedIncrement(&ref_count_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LONG easy2d::Ref::Release() |  | ||||||
| { |  | ||||||
| 	LONG new_count = ::InterlockedDecrement(&ref_count_); |  | ||||||
| 
 |  | ||||||
| 	if (new_count <= 0) |  | ||||||
| 	{ | 	{ | ||||||
| 		delete this; | 		// 当对象被创建时,意味着它已经被引用了一次
 | ||||||
| 		return 0; | 		ref_count_ = 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return new_count; | 	Ref::~Ref() | ||||||
| } | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| LONG easy2d::Ref::GetRefCount() const | 	LONG Ref::Retain() | ||||||
| { | 	{ | ||||||
| 	return ref_count_; | 		return ::InterlockedIncrement(&ref_count_); | ||||||
| } | 	} | ||||||
|  | 
 | ||||||
|  | 	LONG Ref::Release() | ||||||
|  | 	{ | ||||||
|  | 		LONG new_count = ::InterlockedDecrement(&ref_count_); | ||||||
|  | 
 | ||||||
|  | 		if (new_count <= 0) | ||||||
|  | 		{ | ||||||
|  | 			delete this; | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return new_count; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	LONG Ref::GetRefCount() const | ||||||
|  | 	{ | ||||||
|  | 		return ref_count_; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -21,77 +21,80 @@ | ||||||
| #include "..\e2dtool.h" | #include "..\e2dtool.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Resource::Resource(LPCWSTR name, LPCWSTR type) | namespace easy2d | ||||||
| 	: name_(name) |  | ||||||
| 	, type_(type) |  | ||||||
| 	, data_(nullptr) |  | ||||||
| 	, data_size_(0) |  | ||||||
| 	, loaded_(false) |  | ||||||
| { | { | ||||||
| } | 	Resource::Resource(LPCWSTR name, LPCWSTR type) | ||||||
| 
 | 		: name_(name) | ||||||
| LPCWSTR easy2d::Resource::GetName() const | 		, type_(type) | ||||||
| { | 		, data_(nullptr) | ||||||
| 	return name_; | 		, data_size_(0) | ||||||
| } | 		, loaded_(false) | ||||||
| 
 |  | ||||||
| LPCWSTR easy2d::Resource::GetType() const |  | ||||||
| { |  | ||||||
| 	return type_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LPVOID easy2d::Resource::GetData() const |  | ||||||
| { |  | ||||||
| 	return data_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| DWORD easy2d::Resource::GetDataSize() const |  | ||||||
| { |  | ||||||
| 	return data_size_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t easy2d::Resource::GetHashCode() const |  | ||||||
| { |  | ||||||
| 	return std::hash<LPCWSTR>{}(name_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool easy2d::Resource::Load() |  | ||||||
| { |  | ||||||
| 	if (!loaded_) |  | ||||||
| 	{ | 	{ | ||||||
| 		HRSRC res_info; |  | ||||||
| 		HGLOBAL res_data; |  | ||||||
| 		HINSTANCE hinstance = GetModuleHandle(NULL); |  | ||||||
| 
 |  | ||||||
| 		res_info = FindResourceW(hinstance, name_, type_); |  | ||||||
| 		if (res_info == nullptr) |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("FindResource"); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		res_data = LoadResource(hinstance, res_info); |  | ||||||
| 		if (res_data == nullptr) |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("LoadResource"); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		data_size_ = SizeofResource(hinstance, res_info); |  | ||||||
| 		if (data_size_ == 0) |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("SizeofResource"); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		data_ = LockResource(res_data); |  | ||||||
| 		if (data_ == nullptr) |  | ||||||
| 		{ |  | ||||||
| 			E2D_WARNING("LockResource"); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		loaded_ = true; |  | ||||||
| 	} | 	} | ||||||
| 	return true; | 
 | ||||||
| } | 	LPCWSTR Resource::GetName() const | ||||||
|  | 	{ | ||||||
|  | 		return name_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	LPCWSTR Resource::GetType() const | ||||||
|  | 	{ | ||||||
|  | 		return type_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	LPVOID Resource::GetData() const | ||||||
|  | 	{ | ||||||
|  | 		return data_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	DWORD Resource::GetDataSize() const | ||||||
|  | 	{ | ||||||
|  | 		return data_size_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size_t Resource::GetHashCode() const | ||||||
|  | 	{ | ||||||
|  | 		return std::hash<LPCWSTR>{}(name_); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Resource::Load() | ||||||
|  | 	{ | ||||||
|  | 		if (!loaded_) | ||||||
|  | 		{ | ||||||
|  | 			HRSRC res_info; | ||||||
|  | 			HGLOBAL res_data; | ||||||
|  | 			HINSTANCE hinstance = GetModuleHandle(NULL); | ||||||
|  | 
 | ||||||
|  | 			res_info = FindResourceW(hinstance, name_, type_); | ||||||
|  | 			if (res_info == nullptr) | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("FindResource"); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			res_data = LoadResource(hinstance, res_info); | ||||||
|  | 			if (res_data == nullptr) | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("LoadResource"); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			data_size_ = SizeofResource(hinstance, res_info); | ||||||
|  | 			if (data_size_ == 0) | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("SizeofResource"); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			data_ = LockResource(res_data); | ||||||
|  | 			if (data_ == nullptr) | ||||||
|  | 			{ | ||||||
|  | 				E2D_WARNING("LockResource"); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			loaded_ = true; | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,55 +20,58 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| easy2d::Size::Size() | namespace easy2d | ||||||
| { | { | ||||||
| 	width = 0; | 	Size::Size() | ||||||
| 	height = 0; | 	{ | ||||||
| } | 		width = 0; | ||||||
|  | 		height = 0; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size::Size(float width, float height) | 	Size::Size(float width, float height) | ||||||
| { | 	{ | ||||||
| 	this->width = width; | 		this->width = width; | ||||||
| 	this->height = height; | 		this->height = height; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size::Size(const Size & other) | 	Size::Size(const Size & other) | ||||||
| { | 	{ | ||||||
| 	width = other.width; | 		width = other.width; | ||||||
| 	height = other.height; | 		height = other.height; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Size::operator+(const Size & other) const | 	Size Size::operator+(const Size & other) const | ||||||
| { | 	{ | ||||||
| 	return Size(width + other.width, height + other.height); | 		return Size(width + other.width, height + other.height); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Size::operator-(const Size & other) const | 	Size Size::operator-(const Size & other) const | ||||||
| { | 	{ | ||||||
| 	return Size(width - other.width, height - other.height); | 		return Size(width - other.width, height - other.height); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Size::operator*(float value) const | 	Size Size::operator*(float value) const | ||||||
| { | 	{ | ||||||
| 	return Size(width * value, height * value); | 		return Size(width * value, height * value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Size::operator/(float value) const | 	Size Size::operator/(float value) const | ||||||
| { | 	{ | ||||||
| 	return Size(width / value, height / value); | 		return Size(width / value, height / value); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size::operator easy2d::Point() const | 	Size::operator Point() const | ||||||
| { | 	{ | ||||||
| 	return Point(width, height); | 		return Point(width, height); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Size easy2d::Size::operator-() const | 	Size Size::operator-() const | ||||||
| { | 	{ | ||||||
| 	return Size(-width, -height); | 		return Size(-width, -height); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Size::operator==(const Size & other) const | 	bool Size::operator==(const Size & other) const | ||||||
| { | 	{ | ||||||
| 	return (width == other.width) && (height == other.height); | 		return (width == other.width) && (height == other.height); | ||||||
| } | 	} | ||||||
|  | } | ||||||
|  | @ -20,86 +20,89 @@ | ||||||
| 
 | 
 | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| using namespace std::chrono; | namespace easy2d | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| easy2d::Time::Time() |  | ||||||
| { | { | ||||||
| } | 	using namespace std::chrono; | ||||||
| 
 | 
 | ||||||
| easy2d::Time::Time(std::chrono::steady_clock::time_point time) |  | ||||||
| 	: time_(time) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Time::Time(const Time & other) | 	Time::Time() | ||||||
| 	: time_(other.time_) | 	{ | ||||||
| { | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Time::Time(Time && other) | 	Time::Time(std::chrono::steady_clock::time_point time) | ||||||
| 	: time_(std::move(other.time_)) | 		: time_(time) | ||||||
| { | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| time_t easy2d::Time::GetTimeStamp() const | 	Time::Time(const Time & other) | ||||||
| { | 		: time_(other.time_) | ||||||
| 	auto& duration = time_point_cast<milliseconds>(time_).time_since_epoch(); | 	{ | ||||||
| 	return static_cast<time_t>(duration.count()); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| bool easy2d::Time::IsZero() const | 	Time::Time(Time && other) | ||||||
| { | 		: time_(std::move(other.time_)) | ||||||
| 	return time_.time_since_epoch().count() == 0LL; | 	{ | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Time easy2d::Time::operator+(const Duration & other) const | 	time_t Time::GetTimeStamp() const | ||||||
| { | 	{ | ||||||
| 	return Time(time_ + milliseconds(other.Milliseconds())); | 		auto& duration = time_point_cast<milliseconds>(time_).time_since_epoch(); | ||||||
| } | 		return static_cast<time_t>(duration.count()); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Time easy2d::Time::operator-(const Duration & other) const | 	bool Time::IsZero() const | ||||||
| { | 	{ | ||||||
| 	return Time(time_ - milliseconds(other.Milliseconds())); | 		return time_.time_since_epoch().count() == 0LL; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Time & easy2d::Time::operator+=(const Duration & other) | 	Time Time::operator+(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	time_ += milliseconds(other.Milliseconds()); | 		return Time(time_ + milliseconds(other.Milliseconds())); | ||||||
| 	return (*this); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Time & easy2d::Time::operator-=(const Duration &other) | 	Time Time::operator-(const Duration & other) const | ||||||
| { | 	{ | ||||||
| 	time_ -= milliseconds(other.Milliseconds()); | 		return Time(time_ - milliseconds(other.Milliseconds())); | ||||||
| 	return (*this); | 	} | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| easy2d::Duration easy2d::Time::operator-(const Time & other) const | 	Time & Time::operator+=(const Duration & other) | ||||||
| { | 	{ | ||||||
| 	auto ms = duration_cast<milliseconds>(time_ - other.time_).count(); | 		time_ += milliseconds(other.Milliseconds()); | ||||||
| 	return Duration(static_cast<int>(ms)); | 		return (*this); | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Time& easy2d::Time::operator=(const Time & other) E2D_NOEXCEPT | 	Time & Time::operator-=(const Duration &other) | ||||||
| { | 	{ | ||||||
| 	if (this == &other) | 		time_ -= milliseconds(other.Milliseconds()); | ||||||
|  | 		return (*this); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Duration Time::operator-(const Time & other) const | ||||||
|  | 	{ | ||||||
|  | 		auto ms = duration_cast<milliseconds>(time_ - other.time_).count(); | ||||||
|  | 		return Duration(static_cast<int>(ms)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Time& Time::operator=(const Time & other) E2D_NOEXCEPT | ||||||
|  | 	{ | ||||||
|  | 		if (this == &other) | ||||||
|  | 			return *this; | ||||||
|  | 
 | ||||||
|  | 		time_ = other.time_; | ||||||
| 		return *this; | 		return *this; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	time_ = other.time_; | 	Time& Time::operator=(Time && other) E2D_NOEXCEPT | ||||||
| 	return *this; | 	{ | ||||||
| } | 		if (this == &other) | ||||||
|  | 			return *this; | ||||||
| 
 | 
 | ||||||
| easy2d::Time& easy2d::Time::operator=(Time && other) E2D_NOEXCEPT | 		time_ = std::move(other.time_); | ||||||
| { |  | ||||||
| 	if (this == &other) |  | ||||||
| 		return *this; | 		return *this; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	time_ = std::move(other.time_); | 	Time Time::Now() | ||||||
| 	return *this; | 	{ | ||||||
| } | 		return Time(steady_clock::now()); | ||||||
| 
 | 	} | ||||||
| easy2d::Time easy2d::Time::Now() | } | ||||||
| { |  | ||||||
| 	return Time(steady_clock::now()); |  | ||||||
| } |  | ||||||
|  | @ -21,49 +21,52 @@ | ||||||
| #include "..\e2dutil.h" | #include "..\e2dutil.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| easy2d::Transform::Transform() | namespace easy2d | ||||||
| 	: position() |  | ||||||
| 	, size() |  | ||||||
| 	, scale_x(1.f) |  | ||||||
| 	, scale_y(1.f) |  | ||||||
| 	, rotation(0) |  | ||||||
| 	, skew_x(0) |  | ||||||
| 	, skew_y(0) |  | ||||||
| 	, pivot_x(0) |  | ||||||
| 	, pivot_y(0) |  | ||||||
| { | { | ||||||
| } | 	Transform::Transform() | ||||||
|  | 		: position() | ||||||
|  | 		, size() | ||||||
|  | 		, scale_x(1.f) | ||||||
|  | 		, scale_y(1.f) | ||||||
|  | 		, rotation(0) | ||||||
|  | 		, skew_x(0) | ||||||
|  | 		, skew_y(0) | ||||||
|  | 		, pivot_x(0) | ||||||
|  | 		, pivot_y(0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| easy2d::Transform::operator D2D1::Matrix3x2F() const | 	Transform::operator D2D1::Matrix3x2F() const | ||||||
| { | 	{ | ||||||
| 	auto pivot = D2D1::Point2F(size.width * pivot_x, size.height * pivot_y); | 		auto pivot = D2D1::Point2F(size.width * pivot_x, size.height * pivot_y); | ||||||
| 	auto matrix = D2D1::Matrix3x2F::Scale( | 		auto matrix = D2D1::Matrix3x2F::Scale( | ||||||
| 		scale_x, | 			scale_x, | ||||||
| 		scale_y, | 			scale_y, | ||||||
| 		pivot | 			pivot | ||||||
| 	) * D2D1::Matrix3x2F::Skew( | 		) * D2D1::Matrix3x2F::Skew( | ||||||
| 		skew_x, | 			skew_x, | ||||||
| 		skew_y, | 			skew_y, | ||||||
| 		pivot | 			pivot | ||||||
| 	) * D2D1::Matrix3x2F::Rotation( | 		) * D2D1::Matrix3x2F::Rotation( | ||||||
| 		rotation, | 			rotation, | ||||||
| 		pivot | 			pivot | ||||||
| 	) * D2D1::Matrix3x2F::Translation( | 		) * D2D1::Matrix3x2F::Translation( | ||||||
| 		position.x - pivot.x, | 			position.x - pivot.x, | ||||||
| 		position.y - pivot.y | 			position.y - pivot.y | ||||||
| 	); | 		); | ||||||
| 	return matrix; | 		return matrix; | ||||||
| } | 	} | ||||||
| 
 | 
 | ||||||
| bool easy2d::Transform::operator==(const Transform & other) const | 	bool Transform::operator==(const Transform & other) const | ||||||
| { | 	{ | ||||||
| 	return position == other.position && | 		return position == other.position && | ||||||
| 		size == other.size && | 			size == other.size && | ||||||
| 		scale_x == other.scale_x && | 			scale_x == other.scale_x && | ||||||
| 		scale_y == other.scale_y && | 			scale_y == other.scale_y && | ||||||
| 		skew_x == other.skew_x && | 			skew_x == other.skew_x && | ||||||
| 		skew_y == other.skew_y && | 			skew_y == other.skew_y && | ||||||
| 		rotation == other.rotation && | 			rotation == other.rotation && | ||||||
| 		pivot_x == other.pivot_x && | 			pivot_x == other.pivot_x && | ||||||
| 		pivot_y == other.pivot_y; | 			pivot_y == other.pivot_y; | ||||||
| } | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue