update: code style
This commit is contained in:
		
							parent
							
								
									0f1ba104dd
								
							
						
					
					
						commit
						b129a1bf18
					
				|  | @ -20,86 +20,90 @@ | |||
| 
 | ||||
| #include "..\e2daction.h" | ||||
| 
 | ||||
| easy2d::Action::Action()  | ||||
| 	: running_(false) | ||||
| 	, done_(false) | ||||
| 	, initialized_(false) | ||||
| 	, target_(nullptr) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Action::~Action() | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Action::IsRunning() | ||||
| { | ||||
| 	return running_; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Action::Action() | ||||
| 		: running_(false) | ||||
| 		, done_(false) | ||||
| 		, initialized_(false) | ||||
| 		, target_(nullptr) | ||||
| 	{ | ||||
| 		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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::Animate::Animate()  | ||||
| 	: frame_index_(0) | ||||
| 	, animation_(nullptr) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	Animate::Animate() | ||||
| 		: frame_index_(0) | ||||
| 		, animation_(nullptr) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Animate::Animate(Animation * animation) | ||||
| 	: frame_index_(0) | ||||
| 	, animation_(nullptr) | ||||
| { | ||||
| 	this->SetAnimation(animation); | ||||
| } | ||||
| 	Animate::Animate(Animation * animation) | ||||
| 		: frame_index_(0) | ||||
| 		, animation_(nullptr) | ||||
| 	{ | ||||
| 		this->SetAnimation(animation); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Animate::~Animate() | ||||
| { | ||||
| 	SafeRelease(animation_); | ||||
| } | ||||
| 	Animate::~Animate() | ||||
| 	{ | ||||
| 		SafeRelease(animation_); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Animation * easy2d::Animate::GetAnimation() const | ||||
| { | ||||
| 	return animation_; | ||||
| } | ||||
| 	Animation * Animate::GetAnimation() const | ||||
| 	{ | ||||
| 		return animation_; | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Animate::SetAnimation(Animation * animation) | ||||
| { | ||||
| 	if (animation && animation != animation_) | ||||
| 	void Animate::SetAnimation(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_) | ||||
| 		{ | ||||
| 			animation_->Release(); | ||||
| 			return new Animate(animation_); | ||||
| 		} | ||||
| 		animation_ = animation; | ||||
| 		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; | ||||
| 		return nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	while ((Time::Now() - started_).Seconds() >= animation_->GetInterval()) | ||||
| 	Animate * Animate::Reverse() const | ||||
| 	{ | ||||
| 		auto& frames = animation_->GetFrames(); | ||||
| 		auto target = dynamic_cast<Sprite*>(target_); | ||||
| 
 | ||||
| 		if (target) | ||||
| 		if (animation_) | ||||
| 		{ | ||||
| 			target->Load(frames[frame_index_]); | ||||
| 		} | ||||
| 
 | ||||
| 		started_ += Duration::Second * animation_->GetInterval(); | ||||
| 		++frame_index_; | ||||
| 
 | ||||
| 		if (frame_index_ == frames.size()) | ||||
| 		{ | ||||
| 			this->Stop(); | ||||
| 			break; | ||||
| 			auto animation = animation_->Reverse(); | ||||
| 			if (animation) | ||||
| 			{ | ||||
| 				return new Animate(animation); | ||||
| 			} | ||||
| 		} | ||||
| 		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" | ||||
| 
 | ||||
| easy2d::Animation::Animation() | ||||
| 	: interval_(1) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Animation::Animation() | ||||
| 		: interval_(1) | ||||
| 	{ | ||||
| 		SafeRelease(frame); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Animation::SetInterval(float interval) | ||||
| { | ||||
| 	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) | ||||
| 	Animation::Animation(const Images& frames) | ||||
| 		: interval_(1) | ||||
| 	{ | ||||
| 		frames_.push_back(frame); | ||||
| 		frame->Retain(); | ||||
| 		this->Add(frames); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Animation::Add(const Images& frames) | ||||
| { | ||||
| 	for (const auto &image : frames) | ||||
| 	Animation::Animation(float interval) | ||||
| 		: interval_(interval) | ||||
| 	{ | ||||
| 		this->Add(image); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| float easy2d::Animation::GetInterval() const | ||||
| { | ||||
| 	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) | ||||
| 	Animation::Animation(float interval, const Images& frames) | ||||
| 		: interval_(interval) | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	auto& oldFrames = this->GetFrames(); | ||||
| 	Images frames(oldFrames.size()); | ||||
| 
 | ||||
| 	if (!oldFrames.empty()) | ||||
| 	void Animation::SetInterval(float interval) | ||||
| 	{ | ||||
| 		for (auto iter = oldFrames.crbegin(), | ||||
| 			iterCrend = oldFrames.crend(); | ||||
| 			iter != iterCrend; | ||||
| 			++iter) | ||||
| 		interval_ = std::max(interval, 0.f); | ||||
| 	} | ||||
| 
 | ||||
| 	void Animation::Add(Image * frame) | ||||
| 	{ | ||||
| 		E2D_WARNING_IF(frame == nullptr, "Animation::Add failed, frame Is nullptr."); | ||||
| 		if (frame) | ||||
| 		{ | ||||
| 			Image* frame = *iter; | ||||
| 			if (frame) | ||||
| 			frames_.push_back(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" | ||||
| 
 | ||||
| easy2d::CallFunc::CallFunc(const Callback& func) : | ||||
| 	callback_(func) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	CallFunc::CallFunc(const Callback& func) : | ||||
| 		callback_(func) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::CallFunc * easy2d::CallFunc::Clone() const | ||||
| { | ||||
| 	return new CallFunc(callback_); | ||||
| } | ||||
| 	CallFunc * CallFunc::Clone() const | ||||
| 	{ | ||||
| 		return new CallFunc(callback_); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::CallFunc * easy2d::CallFunc::Reverse() const | ||||
| { | ||||
| 	return new CallFunc(callback_); | ||||
| } | ||||
| 	CallFunc * CallFunc::Reverse() const | ||||
| 	{ | ||||
| 		return new CallFunc(callback_); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::CallFunc::Init() | ||||
| { | ||||
| } | ||||
| 	void CallFunc::Init() | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::CallFunc::Update() | ||||
| { | ||||
| 	callback_(); | ||||
| 	this->Stop(); | ||||
| } | ||||
| 	void CallFunc::Update() | ||||
| 	{ | ||||
| 		callback_(); | ||||
| 		this->Stop(); | ||||
| 	} | ||||
| } | ||||
|  | @ -20,47 +20,50 @@ | |||
| 
 | ||||
| #include "..\e2daction.h" | ||||
| 
 | ||||
| easy2d::Delay::Delay(float duration) | ||||
| 	: delta_(0) | ||||
| 	, delay_(std::max(duration, 0.f)) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Delay * easy2d::Delay::Clone() const | ||||
| { | ||||
| 	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_) | ||||
| 	Delay::Delay(float duration) | ||||
| 		: delta_(0) | ||||
| 		, delay_(std::max(duration, 0.f)) | ||||
| 	{ | ||||
| 		this->Stop(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Delay::ResetTime() | ||||
| { | ||||
| 	Action::ResetTime(); | ||||
| 	started_ = Time::Now() - Duration::Second * delta_; | ||||
| } | ||||
| 	Delay * Delay::Clone() const | ||||
| 	{ | ||||
| 		return new Delay(delay_); | ||||
| 	} | ||||
| 
 | ||||
| 	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" | ||||
| 
 | ||||
| easy2d::FadeIn::FadeIn(float duration) | ||||
| 	: OpacityTo(duration, 1) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	FadeIn::FadeIn(float duration) | ||||
| 		: OpacityTo(duration, 1) | ||||
| 	{ | ||||
| 	} | ||||
| } | ||||
|  | @ -20,7 +20,10 @@ | |||
| 
 | ||||
| #include "..\e2daction.h" | ||||
| 
 | ||||
| easy2d::FadeOut::FadeOut(float duration) | ||||
| 	: OpacityTo(duration, 0) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	FadeOut::FadeOut(float duration) | ||||
| 		: OpacityTo(duration, 0) | ||||
| 	{ | ||||
| 	} | ||||
| } | ||||
|  | @ -20,45 +20,48 @@ | |||
| 
 | ||||
| #include "..\e2daction.h" | ||||
| 
 | ||||
| easy2d::FiniteTimeAction::FiniteTimeAction(float duration) | ||||
| 	: delta_(0) | ||||
| 	, duration_(std::max(duration, 0.f)) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void easy2d::FiniteTimeAction::Reset() | ||||
| { | ||||
| 	Action::Reset(); | ||||
| 	delta_ = 0; | ||||
| } | ||||
| 
 | ||||
| void easy2d::FiniteTimeAction::Init() | ||||
| { | ||||
| 	Action::Init(); | ||||
| } | ||||
| 
 | ||||
| void easy2d::FiniteTimeAction::Update() | ||||
| { | ||||
| 	Action::Update(); | ||||
| 
 | ||||
| 	if (duration_ == 0) | ||||
| 	FiniteTimeAction::FiniteTimeAction(float duration) | ||||
| 		: delta_(0) | ||||
| 		, duration_(std::max(duration, 0.f)) | ||||
| 	{ | ||||
| 		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(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 		else | ||||
| 		{ | ||||
| 			delta_ = std::min((Time::Now() - started_).Seconds() / duration_, 1.f); | ||||
| 
 | ||||
| void easy2d::FiniteTimeAction::ResetTime() | ||||
| { | ||||
| 	Action::ResetTime(); | ||||
| 	started_ = Time::Now() - Duration::Second * (delta_ * duration_); | ||||
| } | ||||
| 			if (delta_ >= 1) | ||||
| 			{ | ||||
| 				this->Stop(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void FiniteTimeAction::ResetTime() | ||||
| 	{ | ||||
| 		Action::ResetTime(); | ||||
| 		started_ = Time::Now() - Duration::Second * (delta_ * duration_); | ||||
| 	} | ||||
| } | ||||
|  | @ -21,53 +21,56 @@ | |||
| #include "..\e2daction.h" | ||||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps) | ||||
| 	: FiniteTimeAction(duration) | ||||
| 	, delta_pos_(vec) | ||||
| 	, height_(height) | ||||
| 	, jumps_(jumps) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::JumpBy * easy2d::JumpBy::Clone() const | ||||
| { | ||||
| 	return new JumpBy(duration_, delta_pos_, height_, jumps_); | ||||
| } | ||||
| 
 | ||||
| easy2d::JumpBy * easy2d::JumpBy::Reverse() const | ||||
| { | ||||
| 	return new JumpBy(duration_, -delta_pos_, height_, jumps_); | ||||
| } | ||||
| 
 | ||||
| void easy2d::JumpBy::Init() | ||||
| { | ||||
| 	FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 		, delta_pos_(vec) | ||||
| 		, height_(height) | ||||
| 		, jumps_(jumps) | ||||
| 	{ | ||||
| 		prev_pos_ = start_pos_ = target_->GetPosition(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::JumpBy::Update() | ||||
| { | ||||
| 	FiniteTimeAction::Update(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	JumpBy * JumpBy::Clone() const | ||||
| 	{ | ||||
| 		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; | ||||
| 		return new JumpBy(duration_, delta_pos_, height_, jumps_); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps) | ||||
| 	: JumpBy(duration, Point(), height, jumps) | ||||
| 	, end_pos_(pos) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	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 | ||||
| { | ||||
| 	return new JumpTo(duration_, end_pos_, height_, jumps_); | ||||
| } | ||||
| 	JumpTo * JumpTo::Clone() const | ||||
| 	{ | ||||
| 		return new JumpTo(duration_, end_pos_, height_, jumps_); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::JumpTo::Init() | ||||
| { | ||||
| 	JumpBy::Init(); | ||||
| 	delta_pos_ = end_pos_ - start_pos_; | ||||
| } | ||||
| 	void JumpTo::Init() | ||||
| 	{ | ||||
| 		JumpBy::Init(); | ||||
| 		delta_pos_ = end_pos_ - start_pos_; | ||||
| 	} | ||||
| } | ||||
|  | @ -20,97 +20,100 @@ | |||
| 
 | ||||
| #include "..\e2daction.h" | ||||
| 
 | ||||
| easy2d::Loop::Loop(Action * action, int times /* = -1 */) | ||||
| 	: action_(action) | ||||
| 	, times_(0) | ||||
| 	, total_times_(times) | ||||
| namespace easy2d | ||||
| { | ||||
| 	E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!"); | ||||
| 
 | ||||
| 	if (action) | ||||
| 	Loop::Loop(Action * action, int times /* = -1 */) | ||||
| 		: action_(action) | ||||
| 		, times_(0) | ||||
| 		, total_times_(times) | ||||
| 	{ | ||||
| 		action_ = action; | ||||
| 		action_->Retain(); | ||||
| 	} | ||||
| } | ||||
| 		E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!"); | ||||
| 
 | ||||
| easy2d::Loop::~Loop() | ||||
| { | ||||
| 	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()) | ||||
| 		if (action) | ||||
| 		{ | ||||
| 			++times_; | ||||
| 
 | ||||
| 			Action::Reset(); | ||||
| 			action_->Reset(); | ||||
| 			action_ = action; | ||||
| 			action_->Retain(); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 
 | ||||
| 	Loop::~Loop() | ||||
| 	{ | ||||
| 		this->Stop(); | ||||
| 		SafeRelease(action_); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Loop::Reset() | ||||
| { | ||||
| 	Action::Reset(); | ||||
| 	Loop * Loop::Clone() const | ||||
| 	{ | ||||
| 		if (action_) | ||||
| 		{ | ||||
| 			return new Loop(action_->Clone()); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return nullptr; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (action_) action_->Reset(); | ||||
| 	times_ = 0; | ||||
| } | ||||
| 	Loop * Loop::Reverse() const | ||||
| 	{ | ||||
| 		if (action_) | ||||
| 		{ | ||||
| 			return new Loop(action_->Clone()); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			return nullptr; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Loop::ResetTime() | ||||
| { | ||||
| 	if (action_) action_->ResetTime(); | ||||
| } | ||||
| 	void Loop::Init() | ||||
| 	{ | ||||
| 		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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::MoveBy::MoveBy(float duration, Point vector) | ||||
| 	: FiniteTimeAction(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| 	delta_pos_ = vector; | ||||
| } | ||||
| 
 | ||||
| void easy2d::MoveBy::Init() | ||||
| { | ||||
| 	FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	MoveBy::MoveBy(float duration, Point vector) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 	{ | ||||
| 		prev_pos_ = start_pos_ = target_->GetPosition(); | ||||
| 		delta_pos_ = vector; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::MoveBy::Update() | ||||
| { | ||||
| 	FiniteTimeAction::Update(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	void MoveBy::Init() | ||||
| 	{ | ||||
| 		Point currentPos = target_->GetPosition(); | ||||
| 		Point diff = currentPos - prev_pos_; | ||||
| 		start_pos_ = start_pos_ + diff; | ||||
| 		FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 		Point newPos = start_pos_ + (delta_pos_ * delta_); | ||||
| 		target_->SetPosition(newPos); | ||||
| 
 | ||||
| 		prev_pos_ = newPos; | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			prev_pos_ = start_pos_ = target_->GetPosition(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| easy2d::MoveBy * easy2d::MoveBy::Clone() const | ||||
| { | ||||
| 	return new MoveBy(duration_, delta_pos_); | ||||
| } | ||||
| 	void MoveBy::Update() | ||||
| 	{ | ||||
| 		FiniteTimeAction::Update(); | ||||
| 
 | ||||
| easy2d::MoveBy * easy2d::MoveBy::Reverse() const | ||||
| { | ||||
| 	return new MoveBy(duration_, -delta_pos_); | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::MoveTo::MoveTo(float duration, Point pos) | ||||
| 	: MoveBy(duration, Point()) | ||||
| namespace easy2d | ||||
| { | ||||
| 	end_pos_ = pos; | ||||
| } | ||||
| 	MoveTo::MoveTo(float duration, Point pos) | ||||
| 		: MoveBy(duration, Point()) | ||||
| 	{ | ||||
| 		end_pos_ = pos; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::MoveTo * easy2d::MoveTo::Clone() const | ||||
| { | ||||
| 	return new MoveTo(duration_, end_pos_); | ||||
| } | ||||
| 	MoveTo * MoveTo::Clone() const | ||||
| 	{ | ||||
| 		return new MoveTo(duration_, end_pos_); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::MoveTo::Init() | ||||
| { | ||||
| 	MoveBy::Init(); | ||||
| 	delta_pos_ = end_pos_ - start_pos_; | ||||
| } | ||||
| 	void MoveTo::Init() | ||||
| 	{ | ||||
| 		MoveBy::Init(); | ||||
| 		delta_pos_ = end_pos_ - start_pos_; | ||||
| 	} | ||||
| } | ||||
|  | @ -22,38 +22,41 @@ | |||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::OpacityBy::OpacityBy(float duration, float opacity) | ||||
| 	: FiniteTimeAction(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| 	delta_val_ = opacity; | ||||
| } | ||||
| 
 | ||||
| void easy2d::OpacityBy::Init() | ||||
| { | ||||
| 	FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	OpacityBy::OpacityBy(float duration, float opacity) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 	{ | ||||
| 		start_val_ = target_->GetOpacity(); | ||||
| 		delta_val_ = opacity; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::OpacityBy::Update() | ||||
| { | ||||
| 	FiniteTimeAction::Update(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	void OpacityBy::Init() | ||||
| 	{ | ||||
| 		target_->SetOpacity(start_val_ + delta_val_ * delta_); | ||||
| 		FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			start_val_ = target_->GetOpacity(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| easy2d::OpacityBy * easy2d::OpacityBy::Clone() const | ||||
| { | ||||
| 	return new OpacityBy(duration_, delta_val_); | ||||
| } | ||||
| 	void OpacityBy::Update() | ||||
| 	{ | ||||
| 		FiniteTimeAction::Update(); | ||||
| 
 | ||||
| easy2d::OpacityBy * easy2d::OpacityBy::Reverse() const | ||||
| { | ||||
| 	return new OpacityBy(duration_, -delta_val_); | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::OpacityTo::OpacityTo(float duration, float opacity) | ||||
| 	: OpacityBy(duration, 0) | ||||
| namespace easy2d | ||||
| { | ||||
| 	end_val_ = opacity; | ||||
| } | ||||
| 	OpacityTo::OpacityTo(float duration, float opacity) | ||||
| 		: OpacityBy(duration, 0) | ||||
| 	{ | ||||
| 		end_val_ = opacity; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::OpacityTo * easy2d::OpacityTo::Clone() const | ||||
| { | ||||
| 	return new OpacityTo(duration_, end_val_); | ||||
| } | ||||
| 	OpacityTo * OpacityTo::Clone() const | ||||
| 	{ | ||||
| 		return new OpacityTo(duration_, end_val_); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::OpacityTo::Init() | ||||
| { | ||||
| 	OpacityBy::Init(); | ||||
| 	delta_val_ = end_val_ - start_val_; | ||||
| } | ||||
| 	void OpacityTo::Init() | ||||
| 	{ | ||||
| 		OpacityBy::Init(); | ||||
| 		delta_val_ = end_val_ - start_val_; | ||||
| 	} | ||||
| } | ||||
|  | @ -22,38 +22,41 @@ | |||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::RotateBy::RotateBy(float duration, float rotation) | ||||
| 	: FiniteTimeAction(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| 	delta_val_ = rotation; | ||||
| } | ||||
| 
 | ||||
| void easy2d::RotateBy::Init() | ||||
| { | ||||
| 	FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	RotateBy::RotateBy(float duration, float rotation) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 	{ | ||||
| 		start_val_ = target_->GetRotation(); | ||||
| 		delta_val_ = rotation; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::RotateBy::Update() | ||||
| { | ||||
| 	FiniteTimeAction::Update(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	void RotateBy::Init() | ||||
| 	{ | ||||
| 		target_->SetRotation(start_val_ + delta_val_ * delta_); | ||||
| 		FiniteTimeAction::Init(); | ||||
| 
 | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			start_val_ = target_->GetRotation(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| easy2d::RotateBy * easy2d::RotateBy::Clone() const | ||||
| { | ||||
| 	return new RotateBy(duration_, delta_val_); | ||||
| } | ||||
| 	void RotateBy::Update() | ||||
| 	{ | ||||
| 		FiniteTimeAction::Update(); | ||||
| 
 | ||||
| easy2d::RotateBy * easy2d::RotateBy::Reverse() const | ||||
| { | ||||
| 	return new RotateBy(duration_, -delta_val_); | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::RotateTo::RotateTo(float duration, float rotation) | ||||
| 	: RotateBy(duration, 0) | ||||
| namespace easy2d | ||||
| { | ||||
| 	end_val_ = rotation; | ||||
| } | ||||
| 	RotateTo::RotateTo(float duration, float rotation) | ||||
| 		: RotateBy(duration, 0) | ||||
| 	{ | ||||
| 		end_val_ = rotation; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::RotateTo * easy2d::RotateTo::Clone() const | ||||
| { | ||||
| 	return new RotateTo(duration_, end_val_); | ||||
| } | ||||
| 	RotateTo * RotateTo::Clone() const | ||||
| 	{ | ||||
| 		return new RotateTo(duration_, end_val_); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::RotateTo::Init() | ||||
| { | ||||
| 	RotateBy::Init(); | ||||
| 	delta_val_ = end_val_ - start_val_; | ||||
| } | ||||
| 	void RotateTo::Init() | ||||
| 	{ | ||||
| 		RotateBy::Init(); | ||||
| 		delta_val_ = end_val_ - start_val_; | ||||
| 	} | ||||
| } | ||||
|  | @ -22,47 +22,50 @@ | |||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::ScaleBy::ScaleBy(float duration, float scale) | ||||
| 	: FiniteTimeAction(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| 	delta_x_ = scale; | ||||
| 	delta_y_ = scale; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	ScaleBy::ScaleBy(float duration, float scale) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 	{ | ||||
| 		start_scale_x_ = target_->GetScaleX(); | ||||
| 		start_scale_y_ = target_->GetScaleY(); | ||||
| 		delta_x_ = scale; | ||||
| 		delta_y_ = scale; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::ScaleBy::Update() | ||||
| { | ||||
| 	FiniteTimeAction::Update(); | ||||
| 
 | ||||
| 	if (target_) | ||||
| 	ScaleBy::ScaleBy(float duration, float scale_x, float scale_y) | ||||
| 		: FiniteTimeAction(duration) | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	return new ScaleBy(duration_, delta_x_, delta_y_); | ||||
| } | ||||
| 	void ScaleBy::Init() | ||||
| 	{ | ||||
| 		FiniteTimeAction::Init(); | ||||
| 
 | ||||
| easy2d::ScaleBy * easy2d::ScaleBy::Reverse() const | ||||
| { | ||||
| 	return new ScaleBy(duration_, -delta_x_, -delta_y_); | ||||
| 		if (target_) | ||||
| 		{ | ||||
| 			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 "..\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) | ||||
| 	: ScaleBy(duration, 0, 0) | ||||
| namespace easy2d | ||||
| { | ||||
| 	end_scale_x_ = scale_x; | ||||
| 	end_scale_y_ = scale_y; | ||||
| } | ||||
| 	ScaleTo::ScaleTo(float duration, float scale) | ||||
| 		: ScaleBy(duration, 0, 0) | ||||
| 	{ | ||||
| 		end_scale_x_ = scale; | ||||
| 		end_scale_y_ = scale; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::ScaleTo * easy2d::ScaleTo::Clone() const | ||||
| { | ||||
| 	return new ScaleTo(duration_, end_scale_x_, end_scale_y_); | ||||
| } | ||||
| 	ScaleTo::ScaleTo(float duration, float scale_x, float scale_y) | ||||
| 		: ScaleBy(duration, 0, 0) | ||||
| 	{ | ||||
| 		end_scale_x_ = scale_x; | ||||
| 		end_scale_y_ = scale_y; | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::ScaleTo::Init() | ||||
| { | ||||
| 	ScaleBy::Init(); | ||||
| 	delta_x_ = end_scale_x_ - start_scale_x_; | ||||
| 	delta_y_ = end_scale_y_ - start_scale_y_; | ||||
| } | ||||
| 	ScaleTo * ScaleTo::Clone() const | ||||
| 	{ | ||||
| 		return new ScaleTo(duration_, end_scale_x_, end_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" | ||||
| 
 | ||||
| easy2d::Sequence::Sequence() | ||||
| 	: action_index_(0) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Sequence::Sequence(const Actions& actions) | ||||
| 	: action_index_(0) | ||||
| namespace easy2d | ||||
| { | ||||
| 	this->Add(actions); | ||||
| } | ||||
| 
 | ||||
| easy2d::Sequence::~Sequence() | ||||
| { | ||||
| 	for (auto action : actions_) | ||||
| 	Sequence::Sequence() | ||||
| 		: action_index_(0) | ||||
| 	{ | ||||
| 		SafeRelease(action); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Sequence::Init() | ||||
| { | ||||
| 	Action::Init(); | ||||
| 	// 将所有动作与目标绑定
 | ||||
| 	if (target_) | ||||
| 	Sequence::Sequence(const Actions& actions) | ||||
| 		: action_index_(0) | ||||
| 	{ | ||||
| 		this->Add(actions); | ||||
| 	} | ||||
| 
 | ||||
| 	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_) | ||||
| 		{ | ||||
| 			action->target_ = target_; | ||||
| 			action->ResetTime(); | ||||
| 		} | ||||
| 	} | ||||
| 	// 初始化第一个动作
 | ||||
| 	actions_[0]->Init(); | ||||
| } | ||||
| 
 | ||||
| void easy2d::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 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_) | ||||
| 	void Sequence::Add(Action * action) | ||||
| 	{ | ||||
| 		if (action) | ||||
| 		{ | ||||
| 			sequence->Add(action->Clone()); | ||||
| 			actions_.push_back(action); | ||||
| 			action->Retain(); | ||||
| 		} | ||||
| 	} | ||||
| 	return sequence; | ||||
| } | ||||
| 
 | ||||
| easy2d::Sequence * easy2d::Sequence::Reverse() const | ||||
| { | ||||
| 	auto sequence = new Sequence(); | ||||
| 	if (sequence && !actions_.empty()) | ||||
| 	void Sequence::Add(const Actions& actions) | ||||
| 	{ | ||||
| 		std::vector<Action*> newActions(actions_.size()); | ||||
| 		for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) | ||||
| 		for (const auto &action : actions) | ||||
| 		{ | ||||
| 			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" | ||||
| 
 | ||||
| easy2d::Spawn::Spawn() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Spawn::Spawn(const Actions& actions) | ||||
| namespace easy2d | ||||
| { | ||||
| 	this->Add(actions); | ||||
| } | ||||
| 
 | ||||
| easy2d::Spawn::~Spawn() | ||||
| { | ||||
| 	for (auto action : actions_) | ||||
| 	Spawn::Spawn() | ||||
| 	{ | ||||
| 		SafeRelease(action); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Spawn::Init() | ||||
| { | ||||
| 	Action::Init(); | ||||
| 	Spawn::Spawn(const Actions& actions) | ||||
| 	{ | ||||
| 		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_) | ||||
| 		{ | ||||
| 			action->target_ = target_; | ||||
| 			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(); | ||||
| 			action->ResetTime(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (done_num == actions_.size()) | ||||
| 	{ | ||||
| 		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_) | ||||
| 	void Spawn::Add(Action * action) | ||||
| 	{ | ||||
| 		if (action) | ||||
| 		{ | ||||
| 			spawn->Add(action->Clone()); | ||||
| 			actions_.push_back(action); | ||||
| 			action->Retain(); | ||||
| 		} | ||||
| 	} | ||||
| 	return spawn; | ||||
| } | ||||
| 
 | ||||
| easy2d::Spawn * easy2d::Spawn::Reverse() const | ||||
| { | ||||
| 	auto spawn = new Spawn(); | ||||
| 	if (spawn && !actions_.empty()) | ||||
| 	void Spawn::Add(const Actions& actions) | ||||
| 	{ | ||||
| 		std::vector<Action*> newActions(actions_.size()); | ||||
| 		for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) | ||||
| 		for (const auto &action : actions) | ||||
| 		{ | ||||
| 			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() | ||||
| 	: callback_(nullptr) | ||||
| 	, status_(Status::Normal) | ||||
| 	, enabled_(true) | ||||
| 	, is_selected_(false) | ||||
| 	, normal_(nullptr) | ||||
| 	, mouseover_(nullptr) | ||||
| 	, selected_(nullptr) | ||||
| 	, disabled_(nullptr) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Button::Button(Node * normal, 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->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) | ||||
| 	Button::Button() | ||||
| 		: callback_(nullptr) | ||||
| 		, status_(Status::Normal) | ||||
| 		, enabled_(true) | ||||
| 		, is_selected_(false) | ||||
| 		, normal_(nullptr) | ||||
| 		, mouseover_(nullptr) | ||||
| 		, selected_(nullptr) | ||||
| 		, disabled_(nullptr) | ||||
| 	{ | ||||
| 		this->SetSize(normal->GetWidth(), normal->GetHeight()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Button::SetMouseOver(Node * mouseover) | ||||
| { | ||||
| 	SET_BUTTON_NODE(mouseover_, mouseover); | ||||
| } | ||||
| 
 | ||||
| void easy2d::Button::SetSelected(Node * selected) | ||||
| { | ||||
| 	SET_BUTTON_NODE(selected_, selected); | ||||
| } | ||||
| 
 | ||||
| void easy2d::Button::SetDisabled(Node * disabled) | ||||
| { | ||||
| 	SET_BUTTON_NODE(disabled_, disabled); | ||||
| } | ||||
| 
 | ||||
| void easy2d::Button::SetEnabled(bool enabled) | ||||
| { | ||||
| 	if (enabled_ != enabled) | ||||
| 	Button::Button(Node * normal, const Callback& func) | ||||
| 		: callback_(nullptr) | ||||
| 		, status_(Status::Normal) | ||||
| 		, enabled_(true) | ||||
| 		, is_selected_(false) | ||||
| 		, normal_(nullptr) | ||||
| 		, mouseover_(nullptr) | ||||
| 		, selected_(nullptr) | ||||
| 		, disabled_(nullptr) | ||||
| 	{ | ||||
| 		enabled_ = enabled; | ||||
| 		UpdateVisible(); | ||||
| 		this->SetNormal(normal); | ||||
| 		this->SetCallbackOnClick(func); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Button::SetCallbackOnClick(const Callback& func) | ||||
| { | ||||
| 	callback_ = func; | ||||
| } | ||||
| 
 | ||||
| void easy2d::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 easy2d::Button::Dispatch(const MouseEvent & e, bool handled) | ||||
| { | ||||
| 	if (!handled && enabled_ && IsVisible() && normal_) | ||||
| 	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) | ||||
| 	{ | ||||
| 		bool contains = normal_->ContainsPoint(e.GetPosition()); | ||||
| 		if (e.GetType() == MouseEvent::Type::LeftUp && is_selected_ && contains) | ||||
| 		this->SetNormal(normal); | ||||
| 		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_(); | ||||
| 			} | ||||
| 			is_selected_ = false; | ||||
| 			SetStatus(Status::Normal); | ||||
| 			return true; | ||||
| 		} | ||||
| 		else if (e.GetType() == MouseEvent::Type::LeftDown) | ||||
| 		{ | ||||
| 			is_selected_ = contains; | ||||
| 			SetStatus(contains ? Status::Selected : Status::Normal); | ||||
| 			 | ||||
| 			if (contains) | ||||
| 				if (callback_) | ||||
| 				{ | ||||
| 					callback_(); | ||||
| 				} | ||||
| 				is_selected_ = false; | ||||
| 				SetStatus(Status::Normal); | ||||
| 				return true; | ||||
| 		} | ||||
| 		else if (e.GetType() == MouseEvent::Type::LeftUp) | ||||
| 		{ | ||||
| 			is_selected_ = false; | ||||
| 		} | ||||
| 		else if (e.GetType() == MouseEvent::Type::MoveBy && is_selected_ && contains) | ||||
| 		{ | ||||
| 			SetStatus(Status::Selected); | ||||
| 			return true; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (!e.IsLButtonDown() && is_selected_) | ||||
| 			} | ||||
| 			else if (e.GetType() == MouseEvent::Type::LeftDown) | ||||
| 			{ | ||||
| 				is_selected_ = contains; | ||||
| 				SetStatus(contains ? Status::Selected : Status::Normal); | ||||
| 
 | ||||
| 				if (contains) | ||||
| 					return true; | ||||
| 			} | ||||
| 			else if (e.GetType() == MouseEvent::Type::LeftUp) | ||||
| 			{ | ||||
| 				is_selected_ = false; | ||||
| 			} | ||||
| 
 | ||||
| 			SetStatus(contains ? Status::Mouseover : Status::Normal); | ||||
| 
 | ||||
| 			if (contains) | ||||
| 			else if (e.GetType() == MouseEvent::Type::MoveBy && is_selected_ && contains) | ||||
| 			{ | ||||
| 				SetStatus(Status::Selected); | ||||
| 				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 easy2d::Button::Visit() | ||||
| { | ||||
| 	Node::Visit(); | ||||
| 
 | ||||
| 	if (IsVisible() && | ||||
| 		!enabled_ && | ||||
| 		normal_ && | ||||
| 		normal_->ContainsPoint(Device::GetInput()->GetMousePos())) | ||||
| 	void Button::SetStatus(Status status) | ||||
| 	{ | ||||
| 		HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO); | ||||
| 		if (hcursor) | ||||
| 		if (status_ != status) | ||||
| 		{ | ||||
| 			::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) | ||||
| { | ||||
| 	if (status_ != status) | ||||
| 	void Button::UpdateVisible() | ||||
| 	{ | ||||
| 		status_ = status; | ||||
| 		UpdateVisible(); | ||||
| 	} | ||||
| } | ||||
| 		SAFE_SET(normal_, SetVisible, false); | ||||
| 		SAFE_SET(mouseover_, SetVisible, false); | ||||
| 		SAFE_SET(selected_, SetVisible, false); | ||||
| 		SAFE_SET(disabled_, SetVisible, false); | ||||
| 
 | ||||
| void easy2d::Button::UpdateVisible() | ||||
| { | ||||
| 	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_) | ||||
| 		if (enabled_) | ||||
| 		{ | ||||
| 			selected_->SetVisible(true); | ||||
| 		} | ||||
| 		else if (status_ == Status::Mouseover && mouseover_) | ||||
| 		{ | ||||
| 			mouseover_->SetVisible(true); | ||||
| 			if (status_ == Status::Selected && selected_) | ||||
| 			{ | ||||
| 				selected_->SetVisible(true); | ||||
| 			} | ||||
| 			else if (status_ == Status::Mouseover && mouseover_) | ||||
| 			{ | ||||
| 				mouseover_->SetVisible(true); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if (normal_) normal_->SetVisible(true); | ||||
| 			} | ||||
| 		} | ||||
| 		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" | ||||
| 
 | ||||
| easy2d::Menu::Menu() | ||||
| 	: enabled_(true) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Menu::Menu(const std::vector<Button*>& buttons) | ||||
| 	: enabled_(true) | ||||
| namespace easy2d | ||||
| { | ||||
| 	for (const auto& button : buttons) | ||||
| 	Menu::Menu() | ||||
| 		: enabled_(true) | ||||
| 	{ | ||||
| 		this->AddButton(button); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Menu::IsEnable() const | ||||
| { | ||||
| 	return enabled_; | ||||
| } | ||||
| 
 | ||||
| size_t easy2d::Menu::GetButtonCount() const | ||||
| { | ||||
| 	return buttons_.size(); | ||||
| } | ||||
| 
 | ||||
| void easy2d::Menu::SetEnabled(bool enabled) | ||||
| { | ||||
| 	if (enabled_ != enabled) | ||||
| 	Menu::Menu(const std::vector<Button*>& buttons) | ||||
| 		: enabled_(true) | ||||
| 	{ | ||||
| 		enabled_ = enabled; | ||||
| 
 | ||||
| 		for (const auto& button : buttons_) | ||||
| 		for (const auto& button : buttons) | ||||
| 		{ | ||||
| 			button->SetEnabled(enabled); | ||||
| 			this->AddButton(button); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Menu::AddButton(Button * button) | ||||
| { | ||||
| 	if (button) | ||||
| 	bool Menu::IsEnable() const | ||||
| 	{ | ||||
| 		this->AddChild(button); | ||||
| 		buttons_.push_back(button); | ||||
| 		button->SetEnabled(enabled_); | ||||
| 		return enabled_; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Menu::RemoveButton(Button * button) | ||||
| { | ||||
| 	if (buttons_.empty()) | ||||
| 	size_t Menu::GetButtonCount() const | ||||
| 	{ | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
| 	this->RemoveChild(button); | ||||
| 
 | ||||
| 	if (button) | ||||
| 	const std::vector<Button*>& Menu::GetAllButtons() const | ||||
| 	{ | ||||
| 		auto iter = std::find(buttons_.begin(), buttons_.end(), button); | ||||
| 		if (iter != buttons_.end()) | ||||
| 		{ | ||||
| 			// ÒÆ³ý°´Å¥Ç°£¬½«ËüÆôÓÃ
 | ||||
| 			button->SetEnabled(true); | ||||
| 			buttons_.erase(iter); | ||||
| 			return true; | ||||
| 		} | ||||
| 		return buttons_; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| const std::vector<easy2d::Button*>& easy2d::Menu::GetAllButtons() const | ||||
| { | ||||
| 	return buttons_; | ||||
| } | ||||
| } | ||||
|  | @ -61,7 +61,7 @@ namespace easy2d | |||
| 		Point operator - () const; | ||||
| 		bool operator== (const Point& other) const; | ||||
| 
 | ||||
| 		explicit operator easy2d::Size() const; | ||||
| 		explicit operator Size() const; | ||||
| 
 | ||||
| 		// 判断两点间距离
 | ||||
| 		static float Distance( | ||||
|  | @ -102,7 +102,7 @@ namespace easy2d | |||
| 		Size operator - () 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> | ||||
| 		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) | ||||
| 		{ | ||||
| 			return easy2d::Random::RandomReal(min, max); | ||||
| 			return Random::RandomReal(min, max); | ||||
| 		} | ||||
| 
 | ||||
| 		// 取得范围内的一个浮点数随机数
 | ||||
| 		static inline double Range(double min, double max) | ||||
| 		{ | ||||
| 			return easy2d::Random::RandomReal(min, max); | ||||
| 			return Random::RandomReal(min, max); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
|  |  | |||
|  | @ -21,80 +21,83 @@ | |||
| #include "..\e2devent.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param) | ||||
| 	: message_(message) | ||||
| 	, w_param_(w_param) | ||||
| 	, l_param_(l_param) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::KeyCode easy2d::KeyEvent::GetCode() const | ||||
| { | ||||
| 	switch (w_param_) | ||||
| 	KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param) | ||||
| 		: message_(message) | ||||
| 		, w_param_(w_param) | ||||
| 		, l_param_(l_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 | ||||
| { | ||||
| 	return static_cast<int>((DWORD)l_param_ & 0x0000FFFF); | ||||
| } | ||||
| 	KeyCode KeyEvent::GetCode() const | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	return Type(message_); | ||||
| } | ||||
| 	int KeyEvent::GetCount() const | ||||
| 	{ | ||||
| 		return static_cast<int>((DWORD)l_param_ & 0x0000FFFF); | ||||
| 	} | ||||
| 
 | ||||
| 	KeyEvent::Type KeyEvent::GetType() const | ||||
| 	{ | ||||
| 		return Type(message_); | ||||
| 	} | ||||
| } | ||||
|  | @ -21,65 +21,68 @@ | |||
| #include "..\e2devent.h" | ||||
| #include "..\e2dmodule.h" | ||||
| 
 | ||||
| easy2d::MouseEvent::MouseEvent(UINT message, WPARAM w_param, LPARAM l_param) | ||||
| 	: message_(message) | ||||
| 	, w_param_(w_param) | ||||
| 	, l_param_(l_param) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	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 dpi = Graphics::GetDpi(); | ||||
| 	return ((float)(short)LOWORD(l_param_)) * 96.f / dpi; | ||||
| } | ||||
| 	float MouseEvent::GetX() const | ||||
| 	{ | ||||
| 		float dpi = Graphics::GetDpi(); | ||||
| 		return ((float)(short)LOWORD(l_param_)) * 96.f / dpi; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::MouseEvent::GetY() const | ||||
| { | ||||
| 	float dpi = Graphics::GetDpi(); | ||||
| 	return ((float)(short)HIWORD(l_param_)) * 96.f / dpi; | ||||
| } | ||||
| 	float MouseEvent::GetY() const | ||||
| 	{ | ||||
| 		float dpi = Graphics::GetDpi(); | ||||
| 		return ((float)(short)HIWORD(l_param_)) * 96.f / dpi; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::MouseEvent::GetPosition() const | ||||
| { | ||||
| 	float dpi = Graphics::GetDpi(); | ||||
| 	return Point( | ||||
| 		((float)(short)LOWORD(l_param_)) * 96.f / dpi, | ||||
| 		((float)(short)HIWORD(l_param_)) * 96.f / dpi | ||||
| 	); | ||||
| } | ||||
| 	Point MouseEvent::GetPosition() const | ||||
| 	{ | ||||
| 		float dpi = Graphics::GetDpi(); | ||||
| 		return Point( | ||||
| 			((float)(short)LOWORD(l_param_)) * 96.f / dpi, | ||||
| 			((float)(short)HIWORD(l_param_)) * 96.f / dpi | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::MouseEvent::IsShiftDown() const | ||||
| { | ||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_SHIFT; | ||||
| } | ||||
| 	bool MouseEvent::IsShiftDown() const | ||||
| 	{ | ||||
| 		return GET_KEYSTATE_WPARAM(w_param_) == MK_SHIFT; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::MouseEvent::IsCtrlDown() const | ||||
| { | ||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_CONTROL; | ||||
| } | ||||
| 	bool MouseEvent::IsCtrlDown() const | ||||
| 	{ | ||||
| 		return GET_KEYSTATE_WPARAM(w_param_) == MK_CONTROL; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::MouseEvent::GetWheelDelta() const | ||||
| { | ||||
| 	return static_cast<float>(GET_WHEEL_DELTA_WPARAM(w_param_)); | ||||
| } | ||||
| 	float MouseEvent::GetWheelDelta() const | ||||
| 	{ | ||||
| 		return static_cast<float>(GET_WHEEL_DELTA_WPARAM(w_param_)); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::MouseEvent::IsLButtonDown() const | ||||
| { | ||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_LBUTTON; | ||||
| } | ||||
| 	bool MouseEvent::IsLButtonDown() const | ||||
| 	{ | ||||
| 		return GET_KEYSTATE_WPARAM(w_param_) == MK_LBUTTON; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::MouseEvent::IsRButtonDown() const | ||||
| { | ||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_RBUTTON; | ||||
| } | ||||
| 	bool MouseEvent::IsRButtonDown() const | ||||
| 	{ | ||||
| 		return GET_KEYSTATE_WPARAM(w_param_) == MK_RBUTTON; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::MouseEvent::IsMButtonDown() const | ||||
| { | ||||
| 	return GET_KEYSTATE_WPARAM(w_param_) == MK_MBUTTON; | ||||
| } | ||||
| 	bool MouseEvent::IsMButtonDown() const | ||||
| 	{ | ||||
| 		return GET_KEYSTATE_WPARAM(w_param_) == MK_MBUTTON; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::MouseEvent::Type easy2d::MouseEvent::GetType() const | ||||
| { | ||||
| 	return Type(message_); | ||||
| } | ||||
| 	MouseEvent::Type MouseEvent::GetType() const | ||||
| 	{ | ||||
| 		return Type(message_); | ||||
| 	} | ||||
| } | ||||
|  | @ -21,47 +21,50 @@ | |||
| #include "..\e2dmodule.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Audio::Audio() | ||||
| 	: x_audio2_(nullptr) | ||||
| 	, mastering_voice_(nullptr) | ||||
| namespace easy2d | ||||
| { | ||||
| 	ThrowIfFailed( | ||||
| 		MFStartup(MF_VERSION) | ||||
| 	); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		XAudio2Create(&x_audio2_) | ||||
| 	); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		x_audio2_->CreateMasteringVoice(&mastering_voice_) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| easy2d::Audio::~Audio() | ||||
| { | ||||
| 	if (mastering_voice_) | ||||
| 	Audio::Audio() | ||||
| 		: x_audio2_(nullptr) | ||||
| 		, mastering_voice_(nullptr) | ||||
| 	{ | ||||
| 		mastering_voice_->DestroyVoice(); | ||||
| 		mastering_voice_ = nullptr; | ||||
| 		ThrowIfFailed( | ||||
| 			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) | ||||
| { | ||||
| 	return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); | ||||
| } | ||||
| 		MFShutdown(); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Audio::Open() | ||||
| { | ||||
| 	x_audio2_->StartEngine(); | ||||
| } | ||||
| 	HRESULT Audio::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx) | ||||
| 	{ | ||||
| 		return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Audio::Close() | ||||
| { | ||||
| 	x_audio2_->StopEngine(); | ||||
| } | ||||
| 	void Audio::Open() | ||||
| 	{ | ||||
| 		x_audio2_->StartEngine(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Audio::Close() | ||||
| 	{ | ||||
| 		x_audio2_->StopEngine(); | ||||
| 	} | ||||
| } | ||||
|  | @ -20,49 +20,56 @@ | |||
| 
 | ||||
| #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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	namespace | ||||
| 	{ | ||||
| 		delete audio_device; | ||||
| 		audio_device = nullptr; | ||||
| 		Graphics *	graphics_device = nullptr; | ||||
| 		Input *		input_device = nullptr; | ||||
| 		Audio *		audio_device = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (input_device) | ||||
| 	Graphics * Device::GetGraphics() | ||||
| 	{ | ||||
| 		delete input_device; | ||||
| 		input_device = nullptr; | ||||
| 		return graphics_device; | ||||
| 	} | ||||
| 
 | ||||
| 	if (graphics_device) | ||||
| 	Input * Device::GetInput() | ||||
| 	{ | ||||
| 		delete graphics_device; | ||||
| 		graphics_device = nullptr; | ||||
| 		return input_device; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	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 | ||||
| { | ||||
| 	// 文字渲染器
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 	// TextRenderer
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| 	class TextRenderer | ||||
| 		: public IDWriteTextRenderer | ||||
| 	{ | ||||
|  | @ -505,320 +508,324 @@ namespace easy2d | |||
| 
 | ||||
| 		return S_OK; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Graphics::Graphics(HWND hwnd) | ||||
| 	: factory_(nullptr) | ||||
| 	, 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_ | ||||
| 		) | ||||
| 	); | ||||
| 	//-------------------------------------------------------
 | ||||
| 	// Graphics
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| 	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_ | ||||
| 		) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	Graphics::Graphics(HWND hwnd) | ||||
| 		: factory_(nullptr) | ||||
| 		, 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)) | ||||
| 	{ | ||||
| 		// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
 | ||||
| 		// 并在下一次调用时重建资源
 | ||||
| 		hr = S_OK; | ||||
| 		ThrowIfFailed( | ||||
| 			D2D1CreateFactory( | ||||
| 				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_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_); | ||||
| 	} | ||||
| 
 | ||||
| 	ThrowIfFailed(hr); | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	void Graphics::BeginDraw() | ||||
| 	{ | ||||
| 		ThrowIfFailed( | ||||
| 			write_factory_->CreateTextFormat( | ||||
| 				L"", | ||||
| 		render_target_->BeginDraw(); | ||||
| 		render_target_->Clear(clear_color_); | ||||
| 	} | ||||
| 
 | ||||
| 	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, | ||||
| 				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 | ||||
| 			) | ||||
| 		); | ||||
| 				text_renderer_, | ||||
| 				10, | ||||
| 				0 | ||||
| 			); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	++render_times_; | ||||
| 	if (duration >= 100) | ||||
| 	ID2D1HwndRenderTarget * Graphics::GetRenderTarget() const | ||||
| 	{ | ||||
| 		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_ | ||||
| 			) | ||||
| 		); | ||||
| 		return render_target_; | ||||
| 	} | ||||
| 
 | ||||
| 	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( | ||||
| 			D2D1::ColorF(D2D1::ColorF::White), | ||||
| 			TRUE, | ||||
| 			D2D1::ColorF(D2D1::ColorF::Black, 0.4f), | ||||
| 			1.5f, | ||||
| 			D2D1_LINE_JOIN_ROUND | ||||
| 		); | ||||
| 
 | ||||
| 		fps_text_layout_->Draw( | ||||
| 			nullptr, | ||||
| 			text_renderer_, | ||||
| 			10, | ||||
| 			0 | ||||
| 			D2D1_COLOR_F(fill_color), | ||||
| 			has_outline, | ||||
| 			D2D1_COLOR_F(outline_color), | ||||
| 			outline_width, | ||||
| 			D2D1_LINE_JOIN(outline_stroke) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| ID2D1HwndRenderTarget * easy2d::Graphics::GetRenderTarget() const | ||||
| { | ||||
| 	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_) | ||||
| 	float Graphics::GetDpi() | ||||
| 	{ | ||||
| 		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_ | ||||
| 			) | ||||
| 		); | ||||
| 		static float dpi = -1; | ||||
| 		if (dpi < 0) | ||||
| 		{ | ||||
| 			HDC hdc = ::GetDC(0); | ||||
| 			dpi = static_cast<float>(::GetDeviceCaps(hdc, LOGPIXELSX)); | ||||
| 			::ReleaseDC(0, hdc); | ||||
| 		} | ||||
| 		return dpi; | ||||
| 	} | ||||
| 	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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Input::Input(HWND hwnd) | ||||
| 	: direct_input_(nullptr) | ||||
| 	, keyboard_device_(nullptr) | ||||
| 	, mouse_device_(nullptr) | ||||
| namespace easy2d | ||||
| { | ||||
| 	ZeroMemory(key_buffer_, sizeof(key_buffer_)); | ||||
| 	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(); | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Input::Input(HWND hwnd) | ||||
| 		: direct_input_(nullptr) | ||||
| 		, keyboard_device_(nullptr) | ||||
| 		, mouse_device_(nullptr) | ||||
| 	{ | ||||
| 		HRESULT hr = keyboard_device_->Poll(); | ||||
| 		if (FAILED(hr)) | ||||
| 		ZeroMemory(key_buffer_, sizeof(key_buffer_)); | ||||
| 		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(); | ||||
| 			while (hr == DIERR_INPUTLOST) | ||||
| 			HRESULT hr = keyboard_device_->Poll(); | ||||
| 			if (FAILED(hr)) | ||||
| 			{ | ||||
| 				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_) | ||||
| 	{ | ||||
| 		HRESULT hr = mouse_device_->Poll(); | ||||
| 		if (FAILED(hr)) | ||||
| 		if (mouse_device_) | ||||
| 		{ | ||||
| 			hr = mouse_device_->Acquire(); | ||||
| 			while (hr == DIERR_INPUTLOST) | ||||
| 			HRESULT hr = mouse_device_->Poll(); | ||||
| 			if (FAILED(hr)) | ||||
| 			{ | ||||
| 				hr = mouse_device_->Acquire(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			mouse_device_->GetDeviceState( | ||||
| 				sizeof(mouse_state_), | ||||
| 				(void**)&mouse_state_ | ||||
| 			); | ||||
| 				while (hr == DIERR_INPUTLOST) | ||||
| 					hr = mouse_device_->Acquire(); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				mouse_device_->GetDeviceState( | ||||
| 					sizeof(mouse_state_), | ||||
| 					(void**)&mouse_state_ | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Input::IsDown(KeyCode key) | ||||
| { | ||||
| 	if (key_buffer_[static_cast<int>(key)] & 0x80) | ||||
| 		return true; | ||||
| 	return false; | ||||
| } | ||||
| 	bool Input::IsDown(KeyCode key) | ||||
| 	{ | ||||
| 		if (key_buffer_[static_cast<int>(key)] & 0x80) | ||||
| 			return true; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Input::IsDown(MouseCode code) | ||||
| { | ||||
| 	if (mouse_state_.rgbButtons[static_cast<int>(code)] & 0x80) | ||||
| 		return true; | ||||
| 	return false; | ||||
| } | ||||
| 	bool Input::IsDown(MouseCode code) | ||||
| 	{ | ||||
| 		if (mouse_state_.rgbButtons[static_cast<int>(code)] & 0x80) | ||||
| 			return true; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Input::GetMouseX() | ||||
| { | ||||
| 	return GetMousePos().x; | ||||
| } | ||||
| 	float Input::GetMouseX() | ||||
| 	{ | ||||
| 		return GetMousePos().x; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Input::GetMouseY() | ||||
| { | ||||
| 	return GetMousePos().y; | ||||
| } | ||||
| 	float Input::GetMouseY() | ||||
| 	{ | ||||
| 		return GetMousePos().y; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Input::GetMousePos() | ||||
| { | ||||
| 	POINT mousePos; | ||||
| 	::GetCursorPos(&mousePos); | ||||
| 	::ScreenToClient(Game::GetInstance()->GetHWnd(), &mousePos); | ||||
| 	float dpi = Graphics::GetDpi(); | ||||
| 	return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi); | ||||
| } | ||||
| 	Point Input::GetMousePos() | ||||
| 	{ | ||||
| 		POINT mousePos; | ||||
| 		::GetCursorPos(&mousePos); | ||||
| 		::ScreenToClient(Game::GetInstance()->GetHWnd(), &mousePos); | ||||
| 		float dpi = Graphics::GetDpi(); | ||||
| 		return Point(mousePos.x * 96.f / dpi, mousePos.y * 96.f / dpi); | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Input::GetMouseDeltaX() | ||||
| { | ||||
| 	return (float)mouse_state_.lX; | ||||
| } | ||||
| 	float Input::GetMouseDeltaX() | ||||
| 	{ | ||||
| 		return (float)mouse_state_.lX; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Input::GetMouseDeltaY() | ||||
| { | ||||
| 	return (float)mouse_state_.lY; | ||||
| } | ||||
| 	float Input::GetMouseDeltaY() | ||||
| 	{ | ||||
| 		return (float)mouse_state_.lY; | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Input::GetMouseDeltaZ() | ||||
| { | ||||
| 	return (float)mouse_state_.lZ; | ||||
| } | ||||
| 	float Input::GetMouseDeltaZ() | ||||
| 	{ | ||||
| 		return (float)mouse_state_.lZ; | ||||
| 	} | ||||
| } | ||||
|  | @ -21,230 +21,233 @@ | |||
| #include "..\e2dobject.h" | ||||
| #include "..\e2dmodule.h" | ||||
| 
 | ||||
| easy2d::Canvas::Canvas(float width, float height) | ||||
| 	: render_target_(nullptr) | ||||
| 	, fill_brush_(nullptr) | ||||
| 	, line_brush_(nullptr) | ||||
| 	, stroke_style_(nullptr) | ||||
| 	, stroke_width_(1.0f) | ||||
| 	, stroke_(Stroke::Miter) | ||||
| namespace easy2d | ||||
| { | ||||
| 	render_target_ = Device::GetGraphics()->GetRenderTarget(); | ||||
| 	render_target_->AddRef(); | ||||
| 
 | ||||
| 	ThrowIfFailed( | ||||
| 		render_target_->CreateSolidColorBrush( | ||||
| 			D2D1::ColorF(D2D1::ColorF::White), | ||||
| 			&fill_brush_ | ||||
| 		) | ||||
| 	); | ||||
| 
 | ||||
| 	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) | ||||
| 	Canvas::Canvas(float width, float height) | ||||
| 		: render_target_(nullptr) | ||||
| 		, fill_brush_(nullptr) | ||||
| 		, line_brush_(nullptr) | ||||
| 		, stroke_style_(nullptr) | ||||
| 		, stroke_width_(1.0f) | ||||
| 		, stroke_(Stroke::Miter) | ||||
| 	{ | ||||
| 	case easy2d::Stroke::Miter: | ||||
| 		stroke_style_ = Device::GetGraphics()->GetMiterStrokeStyle(); | ||||
| 		break; | ||||
| 	case easy2d::Stroke::Bevel: | ||||
| 		stroke_style_ = Device::GetGraphics()->GetBevelStrokeStyle(); | ||||
| 		break; | ||||
| 	case easy2d::Stroke::Round: | ||||
| 		stroke_style_ = Device::GetGraphics()->GetRoundStrokeStyle(); | ||||
| 		break; | ||||
| 		render_target_ = Device::GetGraphics()->GetRenderTarget(); | ||||
| 		render_target_->AddRef(); | ||||
| 
 | ||||
| 		ThrowIfFailed( | ||||
| 			render_target_->CreateSolidColorBrush( | ||||
| 				D2D1::ColorF(D2D1::ColorF::White), | ||||
| 				&fill_brush_ | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		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 | ||||
| { | ||||
| 	return line_brush_->GetColor(); | ||||
| } | ||||
| 	Canvas::~Canvas() | ||||
| 	{ | ||||
| 		SafeRelease(line_brush_); | ||||
| 		SafeRelease(fill_brush_); | ||||
| 		SafeRelease(render_target_); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color easy2d::Canvas::GetFillColor() const | ||||
| { | ||||
| 	return fill_brush_->GetColor(); | ||||
| } | ||||
| 	void Canvas::SetLineColor(const Color & color) | ||||
| 	{ | ||||
| 		line_brush_->SetColor(D2D_COLOR_F(color)); | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Canvas::GetStrokeWidth() const | ||||
| { | ||||
| 	return stroke_width_; | ||||
| } | ||||
| 	void Canvas::SetFillColor(const Color & color) | ||||
| 	{ | ||||
| 		fill_brush_->SetColor(D2D_COLOR_F(color)); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Stroke easy2d::Canvas::GetStrokeStyle() const | ||||
| { | ||||
| 	return stroke_; | ||||
| } | ||||
| 	void Canvas::SetStrokeWidth(float width) | ||||
| 	{ | ||||
| 		stroke_width_ = std::max(width, 0.f); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::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::SetStrokeStyle(Stroke strokeStyle) | ||||
| 	{ | ||||
| 		switch (strokeStyle) | ||||
| 		{ | ||||
| 		case Stroke::Miter: | ||||
| 			stroke_style_ = Device::GetGraphics()->GetMiterStrokeStyle(); | ||||
| 			break; | ||||
| 		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) | ||||
| { | ||||
| 	render_target_->DrawEllipse( | ||||
| 		D2D1::Ellipse( | ||||
| 			D2D1::Point2F( | ||||
| 				center.x, | ||||
| 				center.y | ||||
| 	Color Canvas::GetLineColor() const | ||||
| 	{ | ||||
| 		return line_brush_->GetColor(); | ||||
| 	} | ||||
| 
 | ||||
| 	Color Canvas::GetFillColor() const | ||||
| 	{ | ||||
| 		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, | ||||
| 			radius | ||||
| 		), | ||||
| 		line_brush_, | ||||
| 		stroke_width_, | ||||
| 		stroke_style_ | ||||
| 	); | ||||
| } | ||||
| 			line_brush_, | ||||
| 			stroke_width_, | ||||
| 			stroke_style_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) | ||||
| { | ||||
| 	render_target_->DrawEllipse( | ||||
| 		D2D1::Ellipse( | ||||
| 			D2D1::Point2F( | ||||
| 				center.x, | ||||
| 				center.y | ||||
| 	void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) | ||||
| 	{ | ||||
| 		render_target_->DrawEllipse( | ||||
| 			D2D1::Ellipse( | ||||
| 				D2D1::Point2F( | ||||
| 					center.x, | ||||
| 					center.y | ||||
| 				), | ||||
| 				radius_x, | ||||
| 				radius_y | ||||
| 			), | ||||
| 			radius_x, | ||||
| 			radius_y | ||||
| 		), | ||||
| 		line_brush_, | ||||
| 		stroke_width_, | ||||
| 		stroke_style_ | ||||
| 	); | ||||
| } | ||||
| 			line_brush_, | ||||
| 			stroke_width_, | ||||
| 			stroke_style_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::DrawRect(const Rect & rect) | ||||
| { | ||||
| 	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( | ||||
| 	void Canvas::DrawRect(const Rect & rect) | ||||
| 	{ | ||||
| 		render_target_->DrawRectangle( | ||||
| 			D2D1::RectF( | ||||
| 				rect.origin.x, | ||||
| 				rect.origin.y, | ||||
| 				rect.origin.x + rect.size.width, | ||||
| 				rect.origin.y + rect.size.height | ||||
| 			), | ||||
| 			radius_x, | ||||
| 			radius_y | ||||
| 		), | ||||
| 		line_brush_, | ||||
| 		stroke_width_, | ||||
| 		stroke_style_ | ||||
| 	); | ||||
| } | ||||
| 			line_brush_, | ||||
| 			stroke_width_, | ||||
| 			stroke_style_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::FillCircle(const Point & center, float radius) | ||||
| { | ||||
| 	render_target_->FillEllipse( | ||||
| 		D2D1::Ellipse( | ||||
| 			D2D1::Point2F( | ||||
| 				center.x, | ||||
| 				center.y | ||||
| 	void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) | ||||
| 	{ | ||||
| 		render_target_->DrawRoundedRectangle( | ||||
| 			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 | ||||
| 			), | ||||
| 			radius, | ||||
| 			radius | ||||
| 		), | ||||
| 		fill_brush_ | ||||
| 	); | ||||
| } | ||||
| 			line_brush_, | ||||
| 			stroke_width_, | ||||
| 			stroke_style_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) | ||||
| { | ||||
| 	render_target_->FillEllipse( | ||||
| 		D2D1::Ellipse( | ||||
| 			D2D1::Point2F( | ||||
| 				center.x, | ||||
| 				center.y | ||||
| 	void Canvas::FillCircle(const Point & center, float radius) | ||||
| 	{ | ||||
| 		render_target_->FillEllipse( | ||||
| 			D2D1::Ellipse( | ||||
| 				D2D1::Point2F( | ||||
| 					center.x, | ||||
| 					center.y | ||||
| 				), | ||||
| 				radius, | ||||
| 				radius | ||||
| 			), | ||||
| 			radius_x, | ||||
| 			radius_y | ||||
| 		), | ||||
| 		fill_brush_ | ||||
| 	); | ||||
| } | ||||
| 			fill_brush_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::FillRect(const Rect & rect) | ||||
| { | ||||
| 	render_target_->FillRectangle( | ||||
| 		D2D1::RectF( | ||||
| 			rect.origin.x, | ||||
| 			rect.origin.y, | ||||
| 			rect.origin.x + rect.size.width, | ||||
| 			rect.origin.y + rect.size.height | ||||
| 		), | ||||
| 		fill_brush_ | ||||
| 	); | ||||
| } | ||||
| 	void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) | ||||
| 	{ | ||||
| 		render_target_->FillEllipse( | ||||
| 			D2D1::Ellipse( | ||||
| 				D2D1::Point2F( | ||||
| 					center.x, | ||||
| 					center.y | ||||
| 				), | ||||
| 				radius_x, | ||||
| 				radius_y | ||||
| 			), | ||||
| 			fill_brush_ | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) | ||||
| { | ||||
| 	render_target_->FillRoundedRectangle( | ||||
| 		D2D1::RoundedRect( | ||||
| 	void Canvas::FillRect(const Rect & rect) | ||||
| 	{ | ||||
| 		render_target_->FillRectangle( | ||||
| 			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_ | ||||
| 	); | ||||
| } | ||||
| 			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 "..\e2dtool.h" | ||||
| 
 | ||||
| std::map<size_t, ID2D1Bitmap*> easy2d::Image::bitmap_cache_; | ||||
| 
 | ||||
| easy2d::Image::Image() | ||||
| 	: bitmap_(nullptr) | ||||
| 	, crop_rect_() | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	std::map<size_t, ID2D1Bitmap*> Image::bitmap_cache_; | ||||
| 
 | ||||
| easy2d::Image::Image(Resource& res) | ||||
| 	: bitmap_(nullptr) | ||||
| 	, 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)) | ||||
| 	Image::Image() | ||||
| 		: bitmap_(nullptr) | ||||
| 		, crop_rect_() | ||||
| 	{ | ||||
| 		E2D_WARNING("Load Image from file failed!"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| 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)) | ||||
| 	Image::Image(Resource& res) | ||||
| 		: bitmap_(nullptr) | ||||
| 		, crop_rect_() | ||||
| 	{ | ||||
| 		E2D_WARNING("Load Image from file failed!"); | ||||
| 		return false; | ||||
| 		this->Load(res); | ||||
| 	} | ||||
| 
 | ||||
| 	this->SetBitmap(bitmap_cache_.at(std::hash<std::wstring>{}(file_name))); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void easy2d::Image::Crop(const Rect& crop_rect) | ||||
| { | ||||
| 	if (bitmap_) | ||||
| 	Image::Image(Resource& res, const Rect& crop_rect) | ||||
| 		: bitmap_(nullptr) | ||||
| 		, crop_rect_() | ||||
| 	{ | ||||
| 		auto bitmap_size = bitmap_->GetSize(); | ||||
| 		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); | ||||
| 		this->Load(res); | ||||
| 		this->Crop(crop_rect); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| float easy2d::Image::GetWidth() const | ||||
| { | ||||
| 	return crop_rect_.size.width; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Image::Image(const std::wstring & file_name) | ||||
| 		: bitmap_(nullptr) | ||||
| 		, crop_rect_() | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	if (bitmap_) | ||||
| 	Image::~Image() | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	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()) | ||||
| 	{ | ||||
| 		this->SetBitmap(bitmap_cache_.at(res.GetHashCode())); | ||||
| 		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)) | ||||
| 	bool Image::Load(const std::wstring & file_name) | ||||
| 	{ | ||||
| 		// 创建 WIC 流
 | ||||
| 		hr = imaging_factory->CreateStream(&stream); | ||||
| 		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!"); | ||||
| 			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) | ||||
| 	{ | ||||
| 		// 初始化流
 | ||||
| 		hr = stream->InitializeFromMemory( | ||||
| 			static_cast<WICInProcPointer>(res.GetData()), | ||||
| 			res.GetDataSize() | ||||
| 		); | ||||
| 		if (bitmap_) | ||||
| 		{ | ||||
| 			auto bitmap_size = bitmap_->GetSize(); | ||||
| 			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 | ||||
| 	{ | ||||
| 		// 创建流的解码器
 | ||||
| 		hr = imaging_factory->CreateDecoderFromStream( | ||||
| 			stream, | ||||
| 		return crop_rect_.size.width; | ||||
| 	} | ||||
| 
 | ||||
| 	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, | ||||
| 			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); | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	void Image::ClearCache() | ||||
| 	{ | ||||
| 		// 创建初始化框架
 | ||||
| 		hr = decoder->GetFrame(0, &source); | ||||
| 		if (bitmap_cache_.empty()) | ||||
| 			return; | ||||
| 
 | ||||
| 		for (const auto& bitmap : bitmap_cache_) | ||||
| 		{ | ||||
| 			bitmap.second->Release(); | ||||
| 		} | ||||
| 		bitmap_cache_.clear(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	void Image::SetBitmap(ID2D1Bitmap * bitmap) | ||||
| 	{ | ||||
| 		// 创建图片格式转换器
 | ||||
| 		hr = imaging_factory->CreateFormatConverter(&converter); | ||||
| 		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; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::Scene::Scene() | ||||
| 	: root_(nullptr) | ||||
| 	, transform_(D2D1::Matrix3x2F::Identity()) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Scene::Scene(Node * root) | ||||
| 	: root_(nullptr) | ||||
| 	, transform_(D2D1::Matrix3x2F::Identity()) | ||||
| { | ||||
| 	this->SetRoot(root); | ||||
| } | ||||
| 
 | ||||
| easy2d::Scene::~Scene() | ||||
| { | ||||
| 	if (root_) | ||||
| 	Scene::Scene() | ||||
| 		: root_(nullptr) | ||||
| 		, transform_(D2D1::Matrix3x2F::Identity()) | ||||
| 	{ | ||||
| 		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(); | ||||
| 		root->SetParentScene(this); | ||||
| 		this->SetRoot(root); | ||||
| 	} | ||||
| 
 | ||||
| 	root_ = root; | ||||
| } | ||||
| 
 | ||||
| easy2d::Node * easy2d::Scene::GetRoot() const | ||||
| { | ||||
| 	return root_; | ||||
| } | ||||
| 
 | ||||
| void easy2d::Scene::Draw() | ||||
| { | ||||
| 	if (root_) | ||||
| 	Scene::~Scene() | ||||
| 	{ | ||||
| 		root_->Visit(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Scene::Dispatch(const MouseEvent & e) | ||||
| { | ||||
| 	auto handler = dynamic_cast<MouseEventHandler*>(this); | ||||
| 	if (handler) | ||||
| 	{ | ||||
| 		handler->Handle(e); | ||||
| 		if (root_) | ||||
| 		{ | ||||
| 			root_->SetParentScene(nullptr); | ||||
| 			root_->Release(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (root_) | ||||
| 	void Scene::SetRoot(Node * root) | ||||
| 	{ | ||||
| 		root_->Dispatch(e, false); | ||||
| 	} | ||||
| } | ||||
| 		if (root_ == root) | ||||
| 			return; | ||||
| 
 | ||||
| void easy2d::Scene::Dispatch(const KeyEvent & e) | ||||
| { | ||||
| 	auto handler = dynamic_cast<KeyEventHandler*>(this); | ||||
| 	if (handler) | ||||
| 	{ | ||||
| 		handler->Handle(e); | ||||
| 		if (root_) | ||||
| 		{ | ||||
| 			root_->SetParentScene(nullptr); | ||||
| 			root_->Release(); | ||||
| 		} | ||||
| 
 | ||||
| 		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) | ||||
| { | ||||
| 	transform_ = matrix; | ||||
| 
 | ||||
| 	if (root_) | ||||
| 	void Scene::Draw() | ||||
| 	{ | ||||
| 		root_->dirty_transform_ = true; | ||||
| 		if (root_) | ||||
| 		{ | ||||
| 			root_->Visit(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const D2D1::Matrix3x2F & easy2d::Scene::GetTransform() const | ||||
| { | ||||
| 	return transform_; | ||||
| } | ||||
| 	void Scene::Dispatch(const MouseEvent & e) | ||||
| 	{ | ||||
| 		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 "..\e2dmodule.h" | ||||
| 
 | ||||
| easy2d::Sprite::Sprite() | ||||
| 	: image_(nullptr) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	Sprite::Sprite() | ||||
| 		: image_(nullptr) | ||||
| 	{ | ||||
| 		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; | ||||
| 		image_->Retain(); | ||||
| 
 | ||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Sprite::Load(Resource& res) | ||||
| { | ||||
| 	if (!image_) | ||||
| 	{ | ||||
| 		image_ = new Image(); | ||||
| 		image_->Retain(); | ||||
| 		if (image_->Load(res)) | ||||
| 		{ | ||||
| 			Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if (image_->Load(res)) | ||||
| 	bool Sprite::Load(const std::wstring & file_name) | ||||
| 	{ | ||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 		if (!image_) | ||||
| 		{ | ||||
| 			image_ = new Image(); | ||||
| 			image_->Retain(); | ||||
| 		} | ||||
| 
 | ||||
| bool easy2d::Sprite::Load(const std::wstring & file_name) | ||||
| { | ||||
| 	if (!image_) | ||||
| 	{ | ||||
| 		image_ = new Image(); | ||||
| 		image_->Retain(); | ||||
| 		if (image_->Load(file_name)) | ||||
| 		{ | ||||
| 			Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if (image_->Load(file_name)) | ||||
| 	void Sprite::Crop(const Rect& crop_rect) | ||||
| 	{ | ||||
| 		Node::SetSize(image_->GetWidth(), image_->GetHeight()); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| 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_->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()) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Task::Task(const Callback & func, const std::wstring & name) | ||||
| 	: running_(true) | ||||
| 	, stopped_(false) | ||||
| 	, run_times_(0) | ||||
| 	, total_times_(-1) | ||||
| 	, delay_() | ||||
| 	, callback_(func) | ||||
| 	, name_(name) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Task::Task(const Callback & func, float delay, int times, const std::wstring & name) | ||||
| 	: running_(true) | ||||
| 	, stopped_(false) | ||||
| 	, run_times_(0) | ||||
| 	, delay_(Duration::Second * std::max(delay, 0.f)) | ||||
| 	, total_times_(times) | ||||
| 	, 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) | ||||
| 	Task::Task(const Callback & func, const std::wstring & name) | ||||
| 		: running_(true) | ||||
| 		, stopped_(false) | ||||
| 		, run_times_(0) | ||||
| 		, total_times_(-1) | ||||
| 		, delay_() | ||||
| 		, callback_(func) | ||||
| 		, name_(name) | ||||
| 	{ | ||||
| 		stopped_ = true; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	++run_times_; | ||||
| 	last_time_ += delay_; | ||||
| 
 | ||||
| 	if (callback_) | ||||
| 	Task::Task(const Callback & func, float delay, int times, const std::wstring & name) | ||||
| 		: running_(true) | ||||
| 		, stopped_(false) | ||||
| 		, 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; | ||||
| 		return; | ||||
| 		running_ = true; | ||||
| 		last_time_ = Time::Now(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Task::ResetTime() | ||||
| { | ||||
| 	last_time_ = Time::Now(); | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Task::IsReady() const | ||||
| { | ||||
| 	if (running_) | ||||
| 	void Task::Stop() | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	return running_; | ||||
| } | ||||
| 	void Task::ResetTime() | ||||
| 	{ | ||||
| 		last_time_ = Time::Now(); | ||||
| 	} | ||||
| 
 | ||||
| const std::wstring& easy2d::Task::GetName() const | ||||
| { | ||||
| 	return name_; | ||||
| } | ||||
| 	bool Task::IsReady() const | ||||
| 	{ | ||||
| 		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 "..\e2dmodule.h" | ||||
| 
 | ||||
| //-------------------------------------------------------
 | ||||
| // Style
 | ||||
| //-------------------------------------------------------
 | ||||
| 
 | ||||
| easy2d::Text::Style::Style() | ||||
| 	: 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) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	//-------------------------------------------------------
 | ||||
| 	// Style
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| easy2d::Text::Text(const std::wstring & text, const Font & font, const Style & style) | ||||
| 	: font_(font) | ||||
| 	, style_(style) | ||||
| 	, text_layout_(nullptr) | ||||
| 	, text_format_(nullptr) | ||||
| 	, text_(text) | ||||
| { | ||||
| 	Reset(); | ||||
| } | ||||
| 	Text::Style::Style() | ||||
| 		: 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::~Text() | ||||
| { | ||||
| 	SafeRelease(text_format_); | ||||
| 	SafeRelease(text_layout_); | ||||
| } | ||||
| 	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) | ||||
| 	{} | ||||
| 
 | ||||
| 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 | ||||
| { | ||||
| 	return style_; | ||||
| } | ||||
| 	//-------------------------------------------------------
 | ||||
| 	// Text
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| const std::wstring& easy2d::Text::GetFontFamily() const | ||||
| { | ||||
| 	return font_.family; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Text::Text() | ||||
| 		: font_() | ||||
| 		, style_() | ||||
| 		, text_layout_(nullptr) | ||||
| 		, text_format_(nullptr) | ||||
| 	{ | ||||
| 		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(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Text::SetWrapWidth(float wrap_width) | ||||
| { | ||||
| 	if (style_.wrap_width != wrap_width) | ||||
| 	Text::~Text() | ||||
| 	{ | ||||
| 		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(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Text::SetLineSpacing(float line_spacing) | ||||
| { | ||||
| 	if (style_.line_spacing != line_spacing) | ||||
| 	void Text::SetWrapWidth(float wrap_width) | ||||
| 	{ | ||||
| 		style_.line_spacing = line_spacing; | ||||
| 		Reset(); | ||||
| 		if (style_.wrap_width != wrap_width) | ||||
| 		{ | ||||
| 			style_.wrap_width = std::max(wrap_width, 0.f); | ||||
| 
 | ||||
| 			if (style_.wrap) | ||||
| 			{ | ||||
| 				Reset(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Text::SetAlignment(Align align) | ||||
| { | ||||
| 	if (style_.alignment != align) | ||||
| 	void Text::SetLineSpacing(float line_spacing) | ||||
| 	{ | ||||
| 		style_.alignment = align; | ||||
| 		Reset(); | ||||
| 		if (style_.line_spacing != line_spacing) | ||||
| 		{ | ||||
| 			style_.line_spacing = line_spacing; | ||||
| 			Reset(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Text::SetUnderline(bool underline) | ||||
| { | ||||
| 	if (style_.underline != underline) | ||||
| 	void Text::SetAlignment(Align align) | ||||
| 	{ | ||||
| 		style_.underline = underline; | ||||
| 		if (!text_format_) | ||||
| 			CreateFormat(); | ||||
| 		if (style_.alignment != align) | ||||
| 		{ | ||||
| 			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(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Text::SetStrikethrough(bool strikethrough) | ||||
| { | ||||
| 	if (style_.strikethrough != strikethrough) | ||||
| 	void Text::CreateFormat() | ||||
| 	{ | ||||
| 		style_.strikethrough = strikethrough; | ||||
| 		if (!text_format_) | ||||
| 			CreateFormat(); | ||||
| 		CreateLayout(); | ||||
| 	} | ||||
| } | ||||
| 		SafeRelease(text_format_); | ||||
| 
 | ||||
| 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( | ||||
| 			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_ | ||||
| 			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_ | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		// 获取文本布局的宽度和高度
 | ||||
| 		DWRITE_TEXT_METRICS metrics; | ||||
| 		text_layout_->GetMetrics(&metrics); | ||||
| 		// 重设文本宽高
 | ||||
| 		this->SetSize(metrics.width, metrics.height); | ||||
| 		// 设置文字对齐方式
 | ||||
| 		text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment)); | ||||
| 
 | ||||
| 		// 重新创建 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_); | ||||
| 		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 (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( | ||||
| 				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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Data::Data(const std::wstring & key, const std::wstring & field) | ||||
| 	: key_(key) | ||||
| 	, field_(field) | ||||
| 	, data_path_(Path::GetDataPath()) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	Data::Data(const std::wstring & key, const std::wstring & field) | ||||
| 		: key_(key) | ||||
| 		, field_(field) | ||||
| 		, data_path_(Path::GetDataPath()) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::Exists() const | ||||
| { | ||||
| 	wchar_t temp[256] = { 0 }; | ||||
| 	::GetPrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		L"", | ||||
| 		temp, | ||||
| 		255, | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return temp[0] == L'\0'; | ||||
| } | ||||
| 	bool Data::Exists() const | ||||
| 	{ | ||||
| 		wchar_t temp[256] = { 0 }; | ||||
| 		::GetPrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			L"", | ||||
| 			temp, | ||||
| 			255, | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return temp[0] == L'\0'; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::SaveInt(int value) | ||||
| { | ||||
| 	BOOL ret = ::WritePrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		std::to_wstring(value).c_str(), | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return ret == TRUE; | ||||
| } | ||||
| 	bool Data::SaveInt(int value) | ||||
| 	{ | ||||
| 		BOOL ret = ::WritePrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			std::to_wstring(value).c_str(), | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return ret == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::SaveFloat(float value) | ||||
| { | ||||
| 	BOOL ret = ::WritePrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		std::to_wstring(value).c_str(), | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return ret == TRUE; | ||||
| } | ||||
| 	bool Data::SaveFloat(float value) | ||||
| 	{ | ||||
| 		BOOL ret = ::WritePrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			std::to_wstring(value).c_str(), | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return ret == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::SaveDouble(double value) | ||||
| { | ||||
| 	BOOL ret = ::WritePrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		std::to_wstring(value).c_str(), | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return ret == TRUE; | ||||
| } | ||||
| 	bool Data::SaveDouble(double value) | ||||
| 	{ | ||||
| 		BOOL ret = ::WritePrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			std::to_wstring(value).c_str(), | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return ret == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::SaveBool(bool value) | ||||
| { | ||||
| 	BOOL ret = ::WritePrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		(value ? L"1" : L"0"), | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return ret == TRUE; | ||||
| } | ||||
| 	bool Data::SaveBool(bool value) | ||||
| 	{ | ||||
| 		BOOL ret = ::WritePrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			(value ? L"1" : L"0"), | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return ret == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::SaveString(const std::wstring& value) | ||||
| { | ||||
| 	BOOL ret = ::WritePrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		value.c_str(), | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return ret == TRUE; | ||||
| } | ||||
| 	bool Data::SaveString(const std::wstring& value) | ||||
| 	{ | ||||
| 		BOOL ret = ::WritePrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			value.c_str(), | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return ret == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| int easy2d::Data::GetInt() const | ||||
| { | ||||
| 	return ::GetPrivateProfileIntW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		0, | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| } | ||||
| 	int Data::GetInt() const | ||||
| 	{ | ||||
| 		return ::GetPrivateProfileIntW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			0, | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Data::GetFloat() const | ||||
| { | ||||
| 	wchar_t temp[32] = { 0 }; | ||||
| 	::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||
| 	return std::stof(temp); | ||||
| } | ||||
| 	float Data::GetFloat() const | ||||
| 	{ | ||||
| 		wchar_t temp[32] = { 0 }; | ||||
| 		::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||
| 		return std::stof(temp); | ||||
| 	} | ||||
| 
 | ||||
| double easy2d::Data::GetDouble() const | ||||
| { | ||||
| 	wchar_t temp[32] = { 0 }; | ||||
| 	::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||
| 	return std::stod(temp); | ||||
| } | ||||
| 	double Data::GetDouble() const | ||||
| 	{ | ||||
| 		wchar_t temp[32] = { 0 }; | ||||
| 		::GetPrivateProfileStringW(field_.c_str(), key_.c_str(), L"0.0", temp, 31, data_path_.c_str()); | ||||
| 		return std::stod(temp); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Data::GetBool() const | ||||
| { | ||||
| 	int nValue = ::GetPrivateProfileIntW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		0, | ||||
| 		data_path_.c_str()); | ||||
| 	return nValue == TRUE; | ||||
| } | ||||
| 	bool Data::GetBool() const | ||||
| 	{ | ||||
| 		int nValue = ::GetPrivateProfileIntW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			0, | ||||
| 			data_path_.c_str()); | ||||
| 		return nValue == TRUE; | ||||
| 	} | ||||
| 
 | ||||
| std::wstring easy2d::Data::GetString() | ||||
| { | ||||
| 	wchar_t temp[256] = { 0 }; | ||||
| 	::GetPrivateProfileStringW( | ||||
| 		field_.c_str(), | ||||
| 		key_.c_str(), | ||||
| 		L"", | ||||
| 		temp, | ||||
| 		255, | ||||
| 		data_path_.c_str() | ||||
| 	); | ||||
| 	return temp; | ||||
| } | ||||
| 	std::wstring Data::GetString() | ||||
| 	{ | ||||
| 		wchar_t temp[256] = { 0 }; | ||||
| 		::GetPrivateProfileStringW( | ||||
| 			field_.c_str(), | ||||
| 			key_.c_str(), | ||||
| 			L"", | ||||
| 			temp, | ||||
| 			255, | ||||
| 			data_path_.c_str() | ||||
| 		); | ||||
| 		return temp; | ||||
| 	} | ||||
| } | ||||
|  | @ -23,270 +23,273 @@ | |||
| #include <cwctype> | ||||
| #include <shobjidl.h>  | ||||
| 
 | ||||
| std::list<std::wstring>	easy2d::File::search_paths_; | ||||
| 
 | ||||
| easy2d::File::File() | ||||
| 	: file_path_() | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	std::list<std::wstring>	File::search_paths_; | ||||
| 
 | ||||
| easy2d::File::File(const std::wstring & file_name) | ||||
| 	: file_path_(file_name) | ||||
| { | ||||
| 	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 | ||||
| 	File::File() | ||||
| 		: file_path_() | ||||
| 	{ | ||||
| 		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; | ||||
| 		} | ||||
| 
 | ||||
| 		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 | ||||
| { | ||||
| 	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) | ||||
| 	bool File::Exists() const | ||||
| 	{ | ||||
| 		// 截取扩展名
 | ||||
| 		file_ext = file_path_.substr(pos); | ||||
| 		// 转换为小写字母
 | ||||
| 		std::transform(file_ext.begin(), file_ext.end(), file_ext.begin(), std::towlower); | ||||
| 		if (::PathFileExists(file_path_.c_str())) | ||||
| 			return true; | ||||
| 		return false; | ||||
| 	} | ||||
| 	return file_ext; | ||||
| } | ||||
| 
 | ||||
| bool easy2d::File::Delete() | ||||
| { | ||||
| 	if (::DeleteFile(file_path_.c_str())) | ||||
| 		return true; | ||||
| 	return false; | ||||
| } | ||||
| 	const std::wstring& File::GetPath() const | ||||
| 	{ | ||||
| 		return file_path_; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::File easy2d::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 | ||||
| 	); | ||||
| 	std::wstring File::GetExtension() const | ||||
| 	{ | ||||
| 		std::wstring file_ext; | ||||
| 		// 找到文件名中的最后一个 '.' 的位置
 | ||||
| 		size_t pos = file_path_.find_last_of(L'.'); | ||||
| 		// 判断 pos 是否是有效位置
 | ||||
| 		if (pos != std::wstring::npos) | ||||
| 		{ | ||||
| 			// 截取扩展名
 | ||||
| 			file_ext = file_path_.substr(pos); | ||||
| 			// 转换为小写字母
 | ||||
| 			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; | ||||
| 
 | ||||
| 	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 easy2d::File::AddSearchPath(const std::wstring & path) | ||||
| { | ||||
| 	std::wstring tmp = path; | ||||
| 	size_t pos = 0; | ||||
| 	while ((pos = tmp.find(L"/", pos)) != std::wstring::npos) | ||||
| 	void File::AddSearchPath(const std::wstring & path) | ||||
| 	{ | ||||
| 		tmp.replace(pos, 1, L"\\"); | ||||
| 		pos++; | ||||
| 		std::wstring tmp = path; | ||||
| 		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"\\"); | ||||
| 	} | ||||
| 	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)); | ||||
| 		std::wstring file_path; | ||||
| 		HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) | ||||
| 		{ | ||||
| 			if (!title.empty()) | ||||
| 			{ | ||||
| 				file_open->SetTitle(title.c_str()); | ||||
| 			} | ||||
| 			IFileOpenDialog *file_open; | ||||
| 
 | ||||
| 			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); | ||||
| 			hr = ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, | ||||
| 				IID_IFileOpenDialog, reinterpret_cast<void**>(&file_open)); | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				IShellItem *item; | ||||
| 				hr = file_open->GetResult(&item); | ||||
| 				if (!title.empty()) | ||||
| 				{ | ||||
| 					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)) | ||||
| 				{ | ||||
| 					PWSTR str_file_path; | ||||
| 					hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | ||||
| 
 | ||||
| 					IShellItem *item; | ||||
| 					hr = file_open->GetResult(&item); | ||||
| 					if (SUCCEEDED(hr)) | ||||
| 					{ | ||||
| 						file_path = str_file_path; | ||||
| 						::CoTaskMemFree(str_file_path); | ||||
| 						PWSTR 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) | ||||
| { | ||||
| 	std::wstring file_path; | ||||
| 	HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); | ||||
| 	 | ||||
| 	if (SUCCEEDED(hr)) | ||||
| 	File File::ShowSaveDialog(const std::wstring & title, const std::wstring& def_file, const std::wstring & def_ext) | ||||
| 	{ | ||||
| 		IFileSaveDialog *file_save; | ||||
| 
 | ||||
| 		hr = ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL, | ||||
| 			IID_IFileSaveDialog, reinterpret_cast<void**>(&file_save)); | ||||
| 		std::wstring file_path; | ||||
| 		HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) | ||||
| 		{ | ||||
| 			if (!title.empty()) | ||||
| 			{ | ||||
| 				file_save->SetTitle(title.c_str()); | ||||
| 			} | ||||
| 			IFileSaveDialog *file_save; | ||||
| 
 | ||||
| 			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); | ||||
| 			hr = ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL, | ||||
| 				IID_IFileSaveDialog, reinterpret_cast<void**>(&file_save)); | ||||
| 
 | ||||
| 			if (SUCCEEDED(hr)) | ||||
| 			{ | ||||
| 				IShellItem *item; | ||||
| 				hr = file_save->GetResult(&item); | ||||
| 				if (!title.empty()) | ||||
| 				{ | ||||
| 					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)) | ||||
| 				{ | ||||
| 					PWSTR str_file_path; | ||||
| 					hr = item->GetDisplayName(SIGDN_FILESYSPATH, &str_file_path); | ||||
| 
 | ||||
| 					IShellItem *item; | ||||
| 					hr = file_save->GetResult(&item); | ||||
| 					if (SUCCEEDED(hr)) | ||||
| 					{ | ||||
| 						file_path = str_file_path; | ||||
| 						::CoTaskMemFree(str_file_path); | ||||
| 						PWSTR 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" | ||||
| 
 | ||||
| 
 | ||||
| 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 | ||||
| 	{ | ||||
| 		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 | ||||
| 	{ | ||||
| 		WAVEFORMATEX* wave_format_; | ||||
|  | @ -304,252 +306,255 @@ namespace easy2d | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 	// Music
 | ||||
| 	//-------------------------------------------------------
 | ||||
| 
 | ||||
| easy2d::Music::Music() | ||||
| 	: opened_(false) | ||||
| 	, playing_(false) | ||||
| 	, wave_data_(nullptr) | ||||
| 	, size_(0) | ||||
| 	, voice_(nullptr) | ||||
| { | ||||
| } | ||||
| 	Music::Music() | ||||
| 		: opened_(false) | ||||
| 		, playing_(false) | ||||
| 		, wave_data_(nullptr) | ||||
| 		, size_(0) | ||||
| 		, voice_(nullptr) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Music::Music(const std::wstring& file_path) | ||||
| 	: opened_(false) | ||||
| 	, playing_(false) | ||||
| 	, wave_data_(nullptr) | ||||
| 	, size_(0) | ||||
| 	, voice_(nullptr) | ||||
| { | ||||
| 	Load(file_path); | ||||
| } | ||||
| 	Music::Music(const std::wstring& file_path) | ||||
| 		: opened_(false) | ||||
| 		, playing_(false) | ||||
| 		, wave_data_(nullptr) | ||||
| 		, size_(0) | ||||
| 		, voice_(nullptr) | ||||
| 	{ | ||||
| 		Load(file_path); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Music::Music(Resource& res) | ||||
| 	: opened_(false) | ||||
| 	, playing_(false) | ||||
| 	, wave_data_(nullptr) | ||||
| 	, size_(0) | ||||
| 	, voice_(nullptr) | ||||
| { | ||||
| 	Load(res); | ||||
| } | ||||
| 	Music::Music(Resource& res) | ||||
| 		: opened_(false) | ||||
| 		, playing_(false) | ||||
| 		, wave_data_(nullptr) | ||||
| 		, size_(0) | ||||
| 		, voice_(nullptr) | ||||
| 	{ | ||||
| 		Load(res); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Music::~Music() | ||||
| { | ||||
| 	Close(); | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Music::Load(const std::wstring & file_path) | ||||
| { | ||||
| 	if (opened_) | ||||
| 	Music::~Music() | ||||
| 	{ | ||||
| 		Close(); | ||||
| 	} | ||||
| 
 | ||||
| 	File music_file; | ||||
| 	if (!music_file.Open(file_path)) | ||||
| 	bool Music::Load(const std::wstring & file_path) | ||||
| 	{ | ||||
| 		E2D_WARNING("Media file not found."); | ||||
| 		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_) | ||||
| 		if (opened_) | ||||
| 		{ | ||||
| 			delete[] wave_data_; | ||||
| 			wave_data_ = nullptr; | ||||
| 			Close(); | ||||
| 		} | ||||
| 		TraceError(L"Create source voice error", hr); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	opened_ = true; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 		File music_file; | ||||
| 		if (!music_file.Open(file_path)) | ||||
| 		{ | ||||
| 			delete[] wave_data_; | ||||
| 			wave_data_ = nullptr; | ||||
| 			E2D_WARNING("Media file not found."); | ||||
| 			return false; | ||||
| 		} | ||||
| 		TraceError(L"Create source voice error", hr); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	opened_ = true; | ||||
| 	return true; | ||||
| } | ||||
| 		// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
 | ||||
| 		// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
 | ||||
| 		std::wstring music_file_path = music_file.GetPath(); | ||||
| 
 | ||||
| bool easy2d::Music::Play(int loop_count) | ||||
| { | ||||
| 	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())) | ||||
| 		Transcoder transcoder; | ||||
| 		if (!transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_)) | ||||
| 		{ | ||||
| 			playing_ = false; | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Music::Resume() | ||||
| { | ||||
| 	if (voice_) | ||||
| 	{ | ||||
| 		if (SUCCEEDED(voice_->Start())) | ||||
| 		HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); | ||||
| 		if (FAILED(hr)) | ||||
| 		{ | ||||
| 			playing_ = true; | ||||
| 			if (wave_data_) | ||||
| 			{ | ||||
| 				delete[] wave_data_; | ||||
| 				wave_data_ = nullptr; | ||||
| 			} | ||||
| 			TraceError(L"Create source voice error", hr); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Music::Stop() | ||||
| { | ||||
| 	if (voice_) | ||||
| 		opened_ = true; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	bool Music::Load(Resource& res) | ||||
| 	{ | ||||
| 		if (SUCCEEDED(voice_->Stop())) | ||||
| 		if (opened_) | ||||
| 		{ | ||||
| 			voice_->ExitLoop(); | ||||
| 			voice_->FlushSourceBuffers(); | ||||
| 			playing_ = false; | ||||
| 			Close(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Music::Close() | ||||
| { | ||||
| 	if (voice_) | ||||
| 	{ | ||||
| 		voice_->Stop(); | ||||
| 		voice_->FlushSourceBuffers(); | ||||
| 		voice_->DestroyVoice(); | ||||
| 		voice_ = nullptr; | ||||
| 		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_; | ||||
| 				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_; | ||||
| 		wave_data_ = nullptr; | ||||
| 	} | ||||
| 		if (!opened_) | ||||
| 		{ | ||||
| 			E2D_WARNING("Music must be opened first!"); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 	opened_ = false; | ||||
| 	playing_ = false; | ||||
| } | ||||
| 		if (voice_ == nullptr) | ||||
| 		{ | ||||
| 			E2D_WARNING("IXAudio2SourceVoice Null pointer exception!"); | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| bool easy2d::Music::IsPlaying() const | ||||
| { | ||||
| 	if (opened_ && voice_) | ||||
| 	{ | ||||
| 		XAUDIO2_VOICE_STATE state; | ||||
| 		voice_->GetState(&state); | ||||
| 		if (state.BuffersQueued && playing_) | ||||
| 			return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 		if (state.BuffersQueued) | ||||
| 		{ | ||||
| 			Stop(); | ||||
| 		} | ||||
| 
 | ||||
| float easy2d::Music::GetVolume() const | ||||
| { | ||||
| 	if (voice_) | ||||
| 		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 Music::Pause() | ||||
| 	{ | ||||
| 		float volume = 0.f; | ||||
| 		voice_->GetVolume(&volume); | ||||
| 		return volume; | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			if (SUCCEEDED(voice_->Stop())) | ||||
| 			{ | ||||
| 				playing_ = false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return 0.f; | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Music::SetVolume(float volume) | ||||
| { | ||||
| 	if (voice_) | ||||
| 	void Music::Resume() | ||||
| 	{ | ||||
| 		volume = std::min(std::max(volume, -224.f), 224.f); | ||||
| 		return SUCCEEDED(voice_->SetVolume(volume)); | ||||
| 		if (voice_) | ||||
| 		{ | ||||
| 			if (SUCCEEDED(voice_->Start())) | ||||
| 			{ | ||||
| 				playing_ = true; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| IXAudio2SourceVoice * easy2d::Music::GetSourceVoice() const | ||||
| { | ||||
| 	return voice_; | ||||
| } | ||||
| 	void Music::Stop() | ||||
| 	{ | ||||
| 		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> | ||||
| 
 | ||||
| 
 | ||||
| namespace | ||||
| namespace easy2d | ||||
| { | ||||
| 	// 创建指定文件夹
 | ||||
| 	bool CreateFolder(const std::wstring & dir_path) | ||||
| 	namespace | ||||
| 	{ | ||||
| 		if (dir_path.empty() || dir_path.size() >= MAX_PATH) | ||||
| 			return false; | ||||
| 
 | ||||
| 		wchar_t tmp_dir_path[MAX_PATH] = { 0 }; | ||||
| 		size_t length = dir_path.length(); | ||||
| 
 | ||||
| 		for (size_t i = 0; i < length; ++i) | ||||
| 		// 创建指定文件夹
 | ||||
| 		bool CreateFolder(const std::wstring & dir_path) | ||||
| 		{ | ||||
| 			tmp_dir_path[i] = dir_path.at(i); | ||||
| 			if (tmp_dir_path[i] == L'\\' || tmp_dir_path[i] == L'/' || i == (length - 1)) | ||||
| 			if (dir_path.empty() || dir_path.size() >= MAX_PATH) | ||||
| 				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() | ||||
| { | ||||
| 	static std::wstring data_path; | ||||
| 	if (data_path.empty()) | ||||
| 	const std::wstring& Path::GetDataPath() | ||||
| 	{ | ||||
| 		// 设置数据的保存路径
 | ||||
| 		std::wstring local_app_data_path = Path::GetLocalAppDataPath(); | ||||
| 		std::wstring title = Game::GetInstance()->GetTitle(); | ||||
| 		std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); | ||||
| 
 | ||||
| 		if (!local_app_data_path.empty()) | ||||
| 		static std::wstring data_path; | ||||
| 		if (data_path.empty()) | ||||
| 		{ | ||||
| 			data_path.append(local_app_data_path) | ||||
| 				.append(L"\\Easy2DGameData\\") | ||||
| 				.append(folder_name) | ||||
| 				.append(L"\\"); | ||||
| 			// 设置数据的保存路径
 | ||||
| 			std::wstring local_app_data_path = Path::GetLocalAppDataPath(); | ||||
| 			std::wstring title = Game::GetInstance()->GetTitle(); | ||||
| 			std::wstring folder_name = std::to_wstring(std::hash<std::wstring>{}(title)); | ||||
| 
 | ||||
| 			File file(data_path); | ||||
| 			if (!file.Exists() && !CreateFolder(data_path)) | ||||
| 			if (!local_app_data_path.empty()) | ||||
| 			{ | ||||
| 				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() | ||||
| { | ||||
| 	static std::wstring temp_path; | ||||
| 	if (temp_path.empty()) | ||||
| 	const std::wstring& Path::GetLocalAppDataPath() | ||||
| 	{ | ||||
| 		// 设置临时文件保存路径
 | ||||
| 		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)) | ||||
| 		static std::wstring local_app_data_path; | ||||
| 		if (local_app_data_path.empty()) | ||||
| 		{ | ||||
| 			temp_path.append(path) | ||||
| 				.append(L"\\Easy2DGameTemp\\") | ||||
| 				.append(folder_name) | ||||
| 				.append(L"\\"); | ||||
| 			// 获取 AppData/Local 文件夹的路径
 | ||||
| 			wchar_t path[MAX_PATH] = { 0 }; | ||||
| 			::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path); | ||||
| 			local_app_data_path = path; | ||||
| 		} | ||||
| 
 | ||||
| 			File file(temp_path); | ||||
| 			if (!file.Exists() && !CreateFolder(temp_path)) | ||||
| 		return local_app_data_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" | ||||
| 
 | ||||
| 
 | ||||
| std::map<size_t, easy2d::Music*> easy2d::Player::musics_; | ||||
| 
 | ||||
| easy2d::Player::Player() | ||||
| 	: volume_(1.f) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	std::map<size_t, Music*> Player::musics_; | ||||
| 
 | ||||
| easy2d::Player::~Player() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| bool easy2d::Player::Load(const std::wstring & file_path) | ||||
| { | ||||
| 	if (file_path.empty()) | ||||
| 		return false; | ||||
| 
 | ||||
| 	Music * music = new (std::nothrow) Music(); | ||||
| 
 | ||||
| 	if (music) | ||||
| 	Player::Player() | ||||
| 		: volume_(1.f) | ||||
| 	{ | ||||
| 		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) | ||||
| { | ||||
| 	if (file_path.empty()) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (Load(file_path)) | ||||
| 	Player::~Player() | ||||
| 	{ | ||||
| 		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) | ||||
| { | ||||
| 	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) | ||||
| 	bool Player::Load(const std::wstring & file_path) | ||||
| 	{ | ||||
| 		if (music->Load(res)) | ||||
| 		{ | ||||
| 			music->SetVolume(volume_); | ||||
| 			musics_.insert(std::make_pair(hash_code, music)); | ||||
| 			return true; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			music->Release(); | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 		if (file_path.empty()) | ||||
| 			return false; | ||||
| 
 | ||||
| bool easy2d::Player::Play(Resource& res, int loop_count) | ||||
| { | ||||
| 	if (Load(res)) | ||||
| 		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 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(); | ||||
| 		auto music = musics_[hash_code]; | ||||
| 		if (music->Play(loop_count)) | ||||
| 		{ | ||||
| 		if (musics_.end() != musics_.find(hash_code)) | ||||
| 			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) | ||||
| { | ||||
| 	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_) | ||||
| 	void Player::PauseAll() | ||||
| 	{ | ||||
| 		pair.second->SetVolume(volume_); | ||||
| 		for (const auto& pair : musics_) | ||||
| 		{ | ||||
| 			pair.second->Pause(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Player::PauseAll() | ||||
| { | ||||
| 	for (const auto& pair : musics_) | ||||
| 	void Player::ResumeAll() | ||||
| 	{ | ||||
| 		pair.second->Pause(); | ||||
| 		for (const auto& pair : musics_) | ||||
| 		{ | ||||
| 			pair.second->Resume(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Player::ResumeAll() | ||||
| { | ||||
| 	for (const auto& pair : musics_) | ||||
| 	void Player::StopAll() | ||||
| 	{ | ||||
| 		pair.second->Resume(); | ||||
| 		for (const auto& pair : musics_) | ||||
| 		{ | ||||
| 			pair.second->Stop(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Player::StopAll() | ||||
| { | ||||
| 	for (const auto& pair : musics_) | ||||
| 	void Player::ClearCache() | ||||
| 	{ | ||||
| 		pair.second->Stop(); | ||||
| 	} | ||||
| } | ||||
| 		if (musics_.empty()) | ||||
| 			return; | ||||
| 
 | ||||
| void easy2d::Player::ClearCache() | ||||
| { | ||||
| 	if (musics_.empty()) | ||||
| 		return; | ||||
| 
 | ||||
| 	for (const auto& pair : musics_) | ||||
| 	{ | ||||
| 		pair.second->Release(); | ||||
| 		for (const auto& pair : musics_) | ||||
| 		{ | ||||
| 			pair.second->Release(); | ||||
| 		} | ||||
| 		musics_.clear(); | ||||
| 	} | ||||
| 	musics_.clear(); | ||||
| } | ||||
| } | ||||
|  | @ -21,40 +21,43 @@ | |||
| #include "..\e2dtransition.h" | ||||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::BoxTransition::BoxTransition(float duration) | ||||
| 	: Transition(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	BoxTransition::BoxTransition(float duration) | ||||
| 		: Transition(duration) | ||||
| 	{ | ||||
| 		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; | ||||
| 		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_ | ||||
| 		); | ||||
| 		Transition::Init(prev, next, game); | ||||
| 
 | ||||
| 		in_layer_param_.opacity = 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::EmergeTransition::EmergeTransition(float duration) | ||||
| 	: Transition(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	EmergeTransition::EmergeTransition(float duration) | ||||
| 		: Transition(duration) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| void easy2d::EmergeTransition::Init(Scene * prev, Scene * next, Game * game) | ||||
| { | ||||
| 	Transition::Init(prev, next, game); | ||||
| 	 | ||||
| 	out_layer_param_.opacity = 1; | ||||
| 	in_layer_param_.opacity = 0; | ||||
| } | ||||
| 	void EmergeTransition::Init(Scene * prev, Scene * next, Game * game) | ||||
| 	{ | ||||
| 		Transition::Init(prev, next, game); | ||||
| 
 | ||||
| void easy2d::EmergeTransition::Update() | ||||
| { | ||||
| 	Transition::Update(); | ||||
| 		out_layer_param_.opacity = 1; | ||||
| 		in_layer_param_.opacity = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	out_layer_param_.opacity = 1 - process_; | ||||
| 	in_layer_param_.opacity = process_; | ||||
| } | ||||
| 	void EmergeTransition::Update() | ||||
| 	{ | ||||
| 		Transition::Update(); | ||||
| 
 | ||||
| 		out_layer_param_.opacity = 1 - process_; | ||||
| 		in_layer_param_.opacity = process_; | ||||
| 	} | ||||
| } | ||||
|  | @ -21,31 +21,34 @@ | |||
| #include "..\e2dtransition.h" | ||||
| #include "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::FadeTransition::FadeTransition(float duration) | ||||
| 	: Transition(duration) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	FadeTransition::FadeTransition(float duration) | ||||
| 		: Transition(duration) | ||||
| 	{ | ||||
| 		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; | ||||
| 	} | ||||
| 	else | ||||
| 
 | ||||
| 	void FadeTransition::Update() | ||||
| 	{ | ||||
| 		out_layer_param_.opacity = 0; | ||||
| 		in_layer_param_.opacity = (process_ - 0.5f) * 2; | ||||
| 		Transition::Update(); | ||||
| 
 | ||||
| 		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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::MoveTransition::MoveTransition(float duration, Direction direction) | ||||
| 	: Transition(duration) | ||||
| 	, direction_(direction) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void easy2d::MoveTransition::Init(Scene * prev, Scene * next, Game * game) | ||||
| { | ||||
| 	Transition::Init(prev, next, game); | ||||
| 	 | ||||
| 	switch (direction_) | ||||
| 	MoveTransition::MoveTransition(float duration, Direction direction) | ||||
| 		: Transition(duration) | ||||
| 		, direction_(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()); | ||||
| 	} | ||||
| 	 | ||||
| 	if (in_scene_) | ||||
| 	{ | ||||
| 		in_scene_->SetTransform( | ||||
| 			D2D1::Matrix3x2F::Translation( | ||||
| 				start_pos_.x, | ||||
| 				start_pos_.y | ||||
| 			) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 		Transition::Init(prev, next, game); | ||||
| 
 | ||||
| void easy2d::MoveTransition::Update() | ||||
| { | ||||
| 	Transition::Update(); | ||||
| 		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_) | ||||
| 	{ | ||||
| 		auto translation = pos_delta_ * process_; | ||||
| 		out_scene_->SetTransform( | ||||
| 			D2D1::Matrix3x2F::Translation( | ||||
| 				translation.x, | ||||
| 				translation.y | ||||
| 			) | ||||
| 		); | ||||
| 		if (out_scene_) | ||||
| 		{ | ||||
| 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		} | ||||
| 
 | ||||
| 		if (in_scene_) | ||||
| 		{ | ||||
| 			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_; | ||||
| 		in_scene_->SetTransform( | ||||
| 			D2D1::Matrix3x2F::Translation( | ||||
| 				translation.x, | ||||
| 				translation.y | ||||
| 			) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 		Transition::Update(); | ||||
| 
 | ||||
| void easy2d::MoveTransition::Reset() | ||||
| { | ||||
| 	if (out_scene_) | ||||
| 	{ | ||||
| 		out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		if (out_scene_) | ||||
| 		{ | ||||
| 			auto translation = pos_delta_ * process_; | ||||
| 			out_scene_->SetTransform( | ||||
| 				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 "..\e2dobject.h" | ||||
| 
 | ||||
| easy2d::RotationTransition::RotationTransition(float duration, float rotation) | ||||
| 	: Transition(duration) | ||||
| 	, rotation_(rotation) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void easy2d::RotationTransition::Init(Scene * prev, Scene * next, Game * game) | ||||
| { | ||||
| 	Transition::Init(prev, next, game); | ||||
| 
 | ||||
| 	if (out_scene_) | ||||
| 	RotationTransition::RotationTransition(float duration, float rotation) | ||||
| 		: Transition(duration) | ||||
| 		, rotation_(rotation) | ||||
| 	{ | ||||
| 		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() | ||||
| { | ||||
| 	Transition::Update(); | ||||
| 		auto center_pos = D2D1::Point2F( | ||||
| 			window_size_.width / 2, | ||||
| 			window_size_.height / 2 | ||||
| 		); | ||||
| 
 | ||||
| 	auto center_pos = D2D1::Point2F( | ||||
| 		window_size_.width / 2, | ||||
| 		window_size_.height / 2 | ||||
| 	); | ||||
| 		if (process_ < .5f) | ||||
| 		{ | ||||
| 			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_) | ||||
| 		{ | ||||
| 			out_scene_->SetTransform( | ||||
| 				D2D1::Matrix3x2F::Scale( | ||||
| 					(.5f - process_) * 2, | ||||
| 					(.5f - process_) * 2, | ||||
| 					center_pos | ||||
| 				) * D2D1::Matrix3x2F::Rotation( | ||||
| 					rotation_ * (.5f - process_) * 2, | ||||
| 					center_pos | ||||
| 				) | ||||
| 			); | ||||
| 			out_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 
 | ||||
| 		if (in_scene_) | ||||
| 		{ | ||||
| 			out_layer_param_.opacity = 0; | ||||
| 			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 | ||||
| 				) | ||||
| 			); | ||||
| 			in_scene_->SetTransform(D2D1::Matrix3x2F::Identity()); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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 "..\e2dmodule.h" | ||||
| 
 | ||||
| easy2d::Transition::Transition(float duration) | ||||
| 	: 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_() | ||||
| namespace easy2d | ||||
| { | ||||
| 	duration_ = std::max(duration, 0.f); | ||||
| } | ||||
| 
 | ||||
| easy2d::Transition::~Transition() | ||||
| { | ||||
| 	SafeRelease(out_layer_); | ||||
| 	SafeRelease(in_layer_); | ||||
| 	SafeRelease(out_scene_); | ||||
| 	SafeRelease(in_scene_); | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Transition::Transition(float duration) | ||||
| 		: 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_() | ||||
| 	{ | ||||
| 		ThrowIfFailed( | ||||
| 			graphics->GetRenderTarget()->CreateLayer(&in_layer_) | ||||
| 		); | ||||
| 		duration_ = std::max(duration, 0.f); | ||||
| 	} | ||||
| 
 | ||||
| 	if (out_scene_) | ||||
| 	Transition::~Transition() | ||||
| 	{ | ||||
| 		ThrowIfFailed( | ||||
| 			graphics->GetRenderTarget()->CreateLayer(&out_layer_) | ||||
| 		); | ||||
| 		SafeRelease(out_layer_); | ||||
| 		SafeRelease(in_layer_); | ||||
| 		SafeRelease(out_scene_); | ||||
| 		SafeRelease(in_scene_); | ||||
| 	} | ||||
| 
 | ||||
| 	window_size_ = game->GetSize(); | ||||
| 	out_layer_param_ = in_layer_param_ = D2D1::LayerParameters( | ||||
| 		D2D1::RectF( | ||||
| 			0.f, | ||||
| 			0.f, | ||||
| 			window_size_.width, | ||||
| 			window_size_.height | ||||
| 		), | ||||
| 		nullptr, | ||||
| 		D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | ||||
| 		D2D1::Matrix3x2F::Identity(), | ||||
| 		1.f, | ||||
| 		graphics->GetSolidBrush(), | ||||
| 		D2D1_LAYER_OPTIONS_NONE | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| void easy2d::Transition::Update() | ||||
| { | ||||
| 	if (duration_ == 0) | ||||
| 	bool Transition::IsDone() | ||||
| 	{ | ||||
| 		process_ = 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		process_ = (Time::Now() - started_).Seconds() / duration_; | ||||
| 		process_ = std::min(process_, 1.f); | ||||
| 		return done_; | ||||
| 	} | ||||
| 
 | ||||
| 	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() | ||||
| { | ||||
| 	auto render_target = Device::GetGraphics()->GetRenderTarget(); | ||||
| 		if (out_scene_) | ||||
| 			out_scene_->Retain(); | ||||
| 
 | ||||
| 	if (out_scene_) | ||||
| 	{ | ||||
| 		render_target->SetTransform(out_scene_->GetTransform()); | ||||
| 		render_target->PushAxisAlignedClip( | ||||
| 		if (in_scene_) | ||||
| 			in_scene_->Retain(); | ||||
| 
 | ||||
| 		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( | ||||
| 				0.f, | ||||
| 				0.f, | ||||
| 				window_size_.width, | ||||
| 				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()); | ||||
| 		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_); | ||||
| 		if (duration_ == 0) | ||||
| 		{ | ||||
| 			process_ = 1; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			process_ = (Time::Now() - started_).Seconds() / duration_; | ||||
| 			process_ = std::min(process_, 1.f); | ||||
| 		} | ||||
| 
 | ||||
| 		in_scene_->Draw(); | ||||
| 
 | ||||
| 		render_target->PopLayer(); | ||||
| 		render_target->PopAxisAlignedClip(); | ||||
| 		if (process_ >= 1) | ||||
| 		{ | ||||
| 			this->Stop(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void easy2d::Transition::Stop() | ||||
| { | ||||
| 	done_ = true; | ||||
| 	Reset(); | ||||
| } | ||||
| 	void Transition::Draw() | ||||
| 	{ | ||||
| 		auto render_target = Device::GetGraphics()->GetRenderTarget(); | ||||
| 
 | ||||
| 		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" | ||||
| 
 | ||||
| static const UINT kRedShift = 16; | ||||
| 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 easy2d | ||||
| { | ||||
| } | ||||
| 	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) | ||||
| 	: r(r) | ||||
| 	, g(g) | ||||
| 	, b(b) | ||||
| 	, a(1.f) | ||||
| { | ||||
| } | ||||
| 		const UINT RED_MASK = 0xff << RED_SHIFT; | ||||
| 		const UINT GREEN_MASK = 0xff << GREEN_SHIFT; | ||||
| 		const UINT BLUE_MASK = 0xff << BLUE_SHIFT; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color::Color(float r, float g, float b, float alpha) | ||||
| 	: r(r) | ||||
| 	, g(g) | ||||
| 	, b(b) | ||||
| 	, a(alpha) | ||||
| { | ||||
| } | ||||
| 	Color::Color() | ||||
| 		: r(0) | ||||
| 		, g(0) | ||||
| 		, b(0) | ||||
| 		, a(1.f) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color::Color(UINT rgb) | ||||
| 	: r(((rgb & kRedMask) >> kRedShift) / 255.f) | ||||
| 	, g(((rgb & kGreenMask) >> kGreenShift) / 255.f) | ||||
| 	, b(((rgb & kBlueMask) >> kBlueShift) / 255.f) | ||||
| 	, a(1.f) | ||||
| { | ||||
| } | ||||
| 	Color::Color(float r, float g, float b) | ||||
| 		: r(r) | ||||
| 		, g(g) | ||||
| 		, b(b) | ||||
| 		, a(1.f) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color::Color(UINT rgb, float alpha) | ||||
| 	: r(((rgb & kRedMask) >> kRedShift) / 255.f) | ||||
| 	, g(((rgb & kGreenMask) >> kGreenShift) / 255.f) | ||||
| 	, b(((rgb & kBlueMask) >> kBlueShift) / 255.f) | ||||
| 	, a(alpha) | ||||
| { | ||||
| } | ||||
| 	Color::Color(float r, float g, float b, float alpha) | ||||
| 		: r(r) | ||||
| 		, g(g) | ||||
| 		, b(b) | ||||
| 		, a(alpha) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color::Color(const D2D1_COLOR_F& color) | ||||
| 	: r(color.r) | ||||
| 	, g(color.g) | ||||
| 	, b(color.b) | ||||
| 	, a(color.a) | ||||
| { | ||||
| } | ||||
| 	Color::Color(UINT rgb) | ||||
| 		: r(((rgb & RED_MASK) >> RED_SHIFT) / 255.f) | ||||
| 		, g(((rgb & GREEN_MASK) >> GREEN_SHIFT) / 255.f) | ||||
| 		, b(((rgb & BLUE_MASK) >> BLUE_SHIFT) / 255.f) | ||||
| 		, a(1.f) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Color::operator D2D1_COLOR_F() const | ||||
| { | ||||
| 	return D2D1::ColorF(r, g, b, a); | ||||
| } | ||||
| 	Color::Color(UINT rgb, float alpha) | ||||
| 		: r(((rgb & RED_MASK) >> RED_SHIFT) / 255.f) | ||||
| 		, 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> | ||||
| 
 | ||||
| 
 | ||||
| const easy2d::Duration easy2d::Duration::Millisecond = easy2d::Duration(1); | ||||
| 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) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	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) | ||||
| 	: 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)) | ||||
| 	namespace | ||||
| 	{ | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
| 	if (str.empty() || str == L"0") { return d; } | ||||
| 
 | ||||
| 	// ·ûºÅλ
 | ||||
| 	if (str[0] == L'-' || str[0] == L'+') | ||||
| 	bool Duration::operator==(const Duration & other) const | ||||
| 	{ | ||||
| 		negative = (str[0] == L'-'); | ||||
| 		pos++; | ||||
| 		return milliseconds_ == other.milliseconds_; | ||||
| 	} | ||||
| 
 | ||||
| 	while (pos < len) | ||||
| 	bool Duration::operator!=(const Duration & other) const | ||||
| 	{ | ||||
| 		// ÊýÖµ
 | ||||
| 		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; | ||||
| 		return milliseconds_ != other.milliseconds_; | ||||
| 	} | ||||
| 
 | ||||
| 	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 | ||||
| { | ||||
| 	return milliseconds_ == other.milliseconds_; | ||||
| } | ||||
| 	bool Duration::operator>=(const Duration & other) const | ||||
| 	{ | ||||
| 		return milliseconds_ >= other.milliseconds_; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Duration::operator!=(const Duration & other) const | ||||
| { | ||||
| 	return milliseconds_ != other.milliseconds_; | ||||
| } | ||||
| 	bool Duration::operator<(const Duration & other) const | ||||
| 	{ | ||||
| 		return milliseconds_ < other.milliseconds_; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Duration::operator>(const Duration & other) const | ||||
| { | ||||
| 	return milliseconds_ > other.milliseconds_; | ||||
| } | ||||
| 	bool Duration::operator<=(const Duration & other) const | ||||
| 	{ | ||||
| 		return milliseconds_ <= other.milliseconds_; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Duration::operator>=(const Duration & other) const | ||||
| { | ||||
| 	return milliseconds_ >= other.milliseconds_; | ||||
| } | ||||
| 	Duration Duration::operator+(const Duration & other) const | ||||
| 	{ | ||||
| 		return Duration(milliseconds_ + other.milliseconds_); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Duration::operator<(const Duration & other) const | ||||
| { | ||||
| 	return milliseconds_ < other.milliseconds_; | ||||
| } | ||||
| 	Duration Duration::operator-(const Duration & other) const | ||||
| 	{ | ||||
| 		return Duration(milliseconds_ - other.milliseconds_); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Duration::operator<=(const Duration & other) const | ||||
| { | ||||
| 	return milliseconds_ <= other.milliseconds_; | ||||
| } | ||||
| 	Duration Duration::operator-() const | ||||
| 	{ | ||||
| 		return Duration(-milliseconds_); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator+(const Duration & other) const | ||||
| { | ||||
| 	return Duration(milliseconds_ + other.milliseconds_); | ||||
| } | ||||
| 	Duration Duration::operator*(int value) const | ||||
| 	{ | ||||
| 		return Duration(milliseconds_ * value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator-(const Duration & other) const | ||||
| { | ||||
| 	return Duration(milliseconds_ - other.milliseconds_); | ||||
| } | ||||
| 	Duration Duration::operator/(int value) const | ||||
| 	{ | ||||
| 		return Duration(milliseconds_ / value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator-() const | ||||
| { | ||||
| 	return Duration(-milliseconds_); | ||||
| } | ||||
| 	Duration Duration::operator*(float value) const | ||||
| 	{ | ||||
| 		return Duration(static_cast<int>(milliseconds_ * value)); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator*(int value) const | ||||
| { | ||||
| 	return Duration(milliseconds_ * value); | ||||
| } | ||||
| 	Duration Duration::operator/(float value) const | ||||
| 	{ | ||||
| 		return Duration(static_cast<int>(milliseconds_ / value)); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator/(int value) const | ||||
| { | ||||
| 	return Duration(milliseconds_ / value); | ||||
| } | ||||
| 	Duration Duration::operator*(double value) const | ||||
| 	{ | ||||
| 		return Duration(static_cast<int>(milliseconds_ * value)); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator*(float value) const | ||||
| { | ||||
| 	return Duration(static_cast<int>(milliseconds_ * value)); | ||||
| } | ||||
| 	Duration Duration::operator/(double value) const | ||||
| 	{ | ||||
| 		return Duration(static_cast<int>(milliseconds_ / value)); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator/(float value) const | ||||
| { | ||||
| 	return Duration(static_cast<int>(milliseconds_ / value)); | ||||
| } | ||||
| 	Duration & Duration::operator+=(const Duration &other) | ||||
| 	{ | ||||
| 		milliseconds_ += other.milliseconds_; | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator*(double value) const | ||||
| { | ||||
| 	return Duration(static_cast<int>(milliseconds_ * value)); | ||||
| } | ||||
| 	Duration & Duration::operator-=(const Duration &other) | ||||
| 	{ | ||||
| 		milliseconds_ -= other.milliseconds_; | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::Duration::operator/(double value) const | ||||
| { | ||||
| 	return Duration(static_cast<int>(milliseconds_ / value)); | ||||
| } | ||||
| 	Duration & Duration::operator*=(int value) | ||||
| 	{ | ||||
| 		milliseconds_ *= value; | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator+=(const Duration &other) | ||||
| { | ||||
| 	milliseconds_ += other.milliseconds_; | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration & Duration::operator/=(int value) | ||||
| 	{ | ||||
| 		milliseconds_ /= value; | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator-=(const Duration &other) | ||||
| { | ||||
| 	milliseconds_ -= other.milliseconds_; | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration & Duration::operator*=(float value) | ||||
| 	{ | ||||
| 		milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator*=(int value) | ||||
| { | ||||
| 	milliseconds_ *= value; | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration & Duration::operator/=(float value) | ||||
| 	{ | ||||
| 		milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator/=(int value) | ||||
| { | ||||
| 	milliseconds_ /= value; | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration & Duration::operator*=(double value) | ||||
| 	{ | ||||
| 		milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator*=(float value) | ||||
| { | ||||
| 	milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration & Duration::operator/=(double value) | ||||
| 	{ | ||||
| 		milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator/=(float value) | ||||
| { | ||||
| 	milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration operator*(int value, const Duration & dur) | ||||
| 	{ | ||||
| 		return dur * value; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator*=(double value) | ||||
| { | ||||
| 	milliseconds_ = static_cast<int>(milliseconds_ * value); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration operator/(int value, const Duration & dur) | ||||
| 	{ | ||||
| 		return dur / value; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration & easy2d::Duration::operator/=(double value) | ||||
| { | ||||
| 	milliseconds_ = static_cast<int>(milliseconds_ / value); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Duration operator*(float value, const Duration & dur) | ||||
| 	{ | ||||
| 		return dur * value; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::operator*(int value, const Duration & dur) | ||||
| { | ||||
| 	return dur * value; | ||||
| } | ||||
| 	Duration operator/(float value, const Duration & dur) | ||||
| 	{ | ||||
| 		return dur / value; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::operator/(int value, const Duration & dur) | ||||
| { | ||||
| 	return dur / value; | ||||
| } | ||||
| 	Duration operator*(double value, const Duration & dur) | ||||
| 	{ | ||||
| 		return dur * value; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::operator*(float value, const Duration & dur) | ||||
| { | ||||
| 	return dur * value; | ||||
| } | ||||
| 	Duration operator/(double value, const Duration & dur) | ||||
| 	{ | ||||
| 		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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Font::Font(const std::wstring & family, float size, UINT weight, bool italic) | ||||
| 	: family(family) | ||||
| 	, size(size) | ||||
| 	, weight(weight) | ||||
| 	, italic(italic) | ||||
| namespace easy2d | ||||
| { | ||||
| 	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> | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Point::Point() | ||||
| namespace easy2d | ||||
| { | ||||
| 	x = 0; | ||||
| 	y = 0; | ||||
| } | ||||
| 	Point::Point() | ||||
| 	{ | ||||
| 		x = 0; | ||||
| 		y = 0; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point::Point(float x, float y) | ||||
| { | ||||
| 	this->x = x; | ||||
| 	this->y = y; | ||||
| } | ||||
| 	Point::Point(float x, float y) | ||||
| 	{ | ||||
| 		this->x = x; | ||||
| 		this->y = y; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point::Point(const Point & other) | ||||
| { | ||||
| 	x = other.x; | ||||
| 	y = other.y; | ||||
| } | ||||
| 	Point::Point(const Point & other) | ||||
| 	{ | ||||
| 		x = other.x; | ||||
| 		y = other.y; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Point::operator+(const Point & p) const | ||||
| { | ||||
| 	return Point(x + p.x, y + p.y); | ||||
| } | ||||
| 	Point Point::operator+(const Point & p) const | ||||
| 	{ | ||||
| 		return Point(x + p.x, y + p.y); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Point::operator-(const Point & p) const | ||||
| { | ||||
| 	return Point(x - p.x, y - p.y); | ||||
| } | ||||
| 	Point Point::operator-(const Point & p) const | ||||
| 	{ | ||||
| 		return Point(x - p.x, y - p.y); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Point::operator*(float value) const | ||||
| { | ||||
| 	return Point(x * value, y * value); | ||||
| } | ||||
| 	Point Point::operator*(float value) const | ||||
| 	{ | ||||
| 		return Point(x * value, y * value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Point::operator/(float value) const | ||||
| { | ||||
| 	return Point(x / value, y / value); | ||||
| } | ||||
| 	Point Point::operator/(float value) const | ||||
| 	{ | ||||
| 		return Point(x / value, y / value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point::operator easy2d::Size() const | ||||
| { | ||||
| 	return Size(x, y); | ||||
| } | ||||
| 	Point::operator Size() const | ||||
| 	{ | ||||
| 		return Size(x, y); | ||||
| 	} | ||||
| 
 | ||||
| float easy2d::Point::Distance(const Point &p1, const Point &p2) | ||||
| { | ||||
| 	return sqrt( | ||||
| 		(p1.x - p2.x) * (p1.x - p2.x) +  | ||||
| 		(p1.y - p2.y) * (p1.y - p2.y) | ||||
| 	); | ||||
| } | ||||
| 	float Point::Distance(const Point &p1, const Point &p2) | ||||
| 	{ | ||||
| 		return sqrt( | ||||
| 			(p1.x - p2.x) * (p1.x - p2.x) + | ||||
| 			(p1.y - p2.y) * (p1.y - p2.y) | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Point easy2d::Point::operator-() const | ||||
| { | ||||
| 	return Point(-x, -y); | ||||
| } | ||||
| 	Point Point::operator-() const | ||||
| 	{ | ||||
| 		return Point(-x, -y); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Point::operator==(const Point & point) const | ||||
| { | ||||
| 	return (x == point.x) && (y == point.y); | ||||
| } | ||||
| 	bool Point::operator==(const Point & point) const | ||||
| 	{ | ||||
| 		return (x == point.x) && (y == point.y); | ||||
| 	} | ||||
| } | ||||
|  | @ -20,9 +20,12 @@ | |||
| 
 | ||||
| #include "..\e2dutil.h" | ||||
| 
 | ||||
| std::default_random_engine &easy2d::Random::GetEngine() | ||||
| namespace easy2d | ||||
| { | ||||
| 	static std::random_device device; | ||||
| 	static std::default_random_engine engine(device()); | ||||
| 	return engine; | ||||
| } | ||||
| 	std::default_random_engine &Random::GetEngine() | ||||
| 	{ | ||||
| 		static std::random_device device; | ||||
| 		static std::default_random_engine engine(device()); | ||||
| 		return engine; | ||||
| 	} | ||||
| } | ||||
|  | @ -20,56 +20,59 @@ | |||
| 
 | ||||
| #include "..\e2dutil.h" | ||||
| 
 | ||||
| easy2d::Rect::Rect(void) | ||||
| 	: origin() | ||||
| 	, size() | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Rect::Rect(float x, float y, float width, float height) | ||||
| 	: 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)) | ||||
| 	Rect::Rect(void) | ||||
| 		: origin() | ||||
| 		, size() | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool easy2d::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); | ||||
| } | ||||
| 	Rect::Rect(float x, float y, float width, float height) | ||||
| 		: origin(x, y) | ||||
| 		, size(width, height) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	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" | ||||
| 
 | ||||
| easy2d::Ref::Ref() | ||||
| namespace easy2d | ||||
| { | ||||
| 	// 当对象被创建时,意味着它已经被引用了一次
 | ||||
| 	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) | ||||
| 	Ref::Ref() | ||||
| 	{ | ||||
| 		delete this; | ||||
| 		return 0; | ||||
| 		// 当对象被创建时,意味着它已经被引用了一次
 | ||||
| 		ref_count_ = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	return new_count; | ||||
| } | ||||
| 	Ref::~Ref() | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| LONG easy2d::Ref::GetRefCount() const | ||||
| { | ||||
| 	return ref_count_; | ||||
| } | ||||
| 	LONG Ref::Retain() | ||||
| 	{ | ||||
| 		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" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Resource::Resource(LPCWSTR name, LPCWSTR type) | ||||
| 	: name_(name) | ||||
| 	, type_(type) | ||||
| 	, data_(nullptr) | ||||
| 	, data_size_(0) | ||||
| 	, loaded_(false) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 
 | ||||
| LPCWSTR easy2d::Resource::GetName() const | ||||
| { | ||||
| 	return name_; | ||||
| } | ||||
| 
 | ||||
| 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_) | ||||
| 	Resource::Resource(LPCWSTR name, LPCWSTR type) | ||||
| 		: name_(name) | ||||
| 		, type_(type) | ||||
| 		, data_(nullptr) | ||||
| 		, data_size_(0) | ||||
| 		, loaded_(false) | ||||
| 	{ | ||||
| 		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" | ||||
| 
 | ||||
| easy2d::Size::Size() | ||||
| namespace easy2d | ||||
| { | ||||
| 	width = 0; | ||||
| 	height = 0; | ||||
| } | ||||
| 	Size::Size() | ||||
| 	{ | ||||
| 		width = 0; | ||||
| 		height = 0; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size::Size(float width, float height) | ||||
| { | ||||
| 	this->width = width; | ||||
| 	this->height = height; | ||||
| } | ||||
| 	Size::Size(float width, float height) | ||||
| 	{ | ||||
| 		this->width = width; | ||||
| 		this->height = height; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size::Size(const Size & other) | ||||
| { | ||||
| 	width = other.width; | ||||
| 	height = other.height; | ||||
| } | ||||
| 	Size::Size(const Size & other) | ||||
| 	{ | ||||
| 		width = other.width; | ||||
| 		height = other.height; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size easy2d::Size::operator+(const Size & other) const | ||||
| { | ||||
| 	return Size(width + other.width, height + other.height); | ||||
| } | ||||
| 	Size Size::operator+(const Size & other) const | ||||
| 	{ | ||||
| 		return Size(width + other.width, height + other.height); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size easy2d::Size::operator-(const Size & other) const | ||||
| { | ||||
| 	return Size(width - other.width, height - other.height); | ||||
| } | ||||
| 	Size Size::operator-(const Size & other) const | ||||
| 	{ | ||||
| 		return Size(width - other.width, height - other.height); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size easy2d::Size::operator*(float value) const | ||||
| { | ||||
| 	return Size(width * value, height * value); | ||||
| } | ||||
| 	Size Size::operator*(float value) const | ||||
| 	{ | ||||
| 		return Size(width * value, height * value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size easy2d::Size::operator/(float value) const | ||||
| { | ||||
| 	return Size(width / value, height / value); | ||||
| } | ||||
| 	Size Size::operator/(float value) const | ||||
| 	{ | ||||
| 		return Size(width / value, height / value); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size::operator easy2d::Point() const | ||||
| { | ||||
| 	return Point(width, height); | ||||
| } | ||||
| 	Size::operator Point() const | ||||
| 	{ | ||||
| 		return Point(width, height); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Size easy2d::Size::operator-() const | ||||
| { | ||||
| 	return Size(-width, -height); | ||||
| } | ||||
| 	Size Size::operator-() const | ||||
| 	{ | ||||
| 		return Size(-width, -height); | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Size::operator==(const Size & other) const | ||||
| { | ||||
| 	return (width == other.width) && (height == other.height); | ||||
| } | ||||
| 	bool Size::operator==(const Size & other) const | ||||
| 	{ | ||||
| 		return (width == other.width) && (height == other.height); | ||||
| 	} | ||||
| } | ||||
|  | @ -20,86 +20,89 @@ | |||
| 
 | ||||
| #include "..\e2dutil.h" | ||||
| 
 | ||||
| using namespace std::chrono; | ||||
| 
 | ||||
| 
 | ||||
| easy2d::Time::Time() | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	using namespace std::chrono; | ||||
| 
 | ||||
| easy2d::Time::Time(std::chrono::steady_clock::time_point time) | ||||
| 	: time_(time) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| easy2d::Time::Time(const Time & other) | ||||
| 	: time_(other.time_) | ||||
| { | ||||
| } | ||||
| 	Time::Time() | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Time::Time(Time && other) | ||||
| 	: time_(std::move(other.time_)) | ||||
| { | ||||
| } | ||||
| 	Time::Time(std::chrono::steady_clock::time_point time) | ||||
| 		: time_(time) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| time_t easy2d::Time::GetTimeStamp() const | ||||
| { | ||||
| 	auto& duration = time_point_cast<milliseconds>(time_).time_since_epoch(); | ||||
| 	return static_cast<time_t>(duration.count()); | ||||
| } | ||||
| 	Time::Time(const Time & other) | ||||
| 		: time_(other.time_) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Time::IsZero() const | ||||
| { | ||||
| 	return time_.time_since_epoch().count() == 0LL; | ||||
| } | ||||
| 	Time::Time(Time && other) | ||||
| 		: time_(std::move(other.time_)) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Time easy2d::Time::operator+(const Duration & other) const | ||||
| { | ||||
| 	return Time(time_ + milliseconds(other.Milliseconds())); | ||||
| } | ||||
| 	time_t Time::GetTimeStamp() const | ||||
| 	{ | ||||
| 		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 | ||||
| { | ||||
| 	return Time(time_ - milliseconds(other.Milliseconds())); | ||||
| } | ||||
| 	bool Time::IsZero() const | ||||
| 	{ | ||||
| 		return time_.time_since_epoch().count() == 0LL; | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Time & easy2d::Time::operator+=(const Duration & other) | ||||
| { | ||||
| 	time_ += milliseconds(other.Milliseconds()); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Time Time::operator+(const Duration & other) const | ||||
| 	{ | ||||
| 		return Time(time_ + milliseconds(other.Milliseconds())); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Time & easy2d::Time::operator-=(const Duration &other) | ||||
| { | ||||
| 	time_ -= milliseconds(other.Milliseconds()); | ||||
| 	return (*this); | ||||
| } | ||||
| 	Time Time::operator-(const Duration & other) const | ||||
| 	{ | ||||
| 		return Time(time_ - milliseconds(other.Milliseconds())); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Duration easy2d::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 Duration & other) | ||||
| 	{ | ||||
| 		time_ += milliseconds(other.Milliseconds()); | ||||
| 		return (*this); | ||||
| 	} | ||||
| 
 | ||||
| easy2d::Time& easy2d::Time::operator=(const Time & other) E2D_NOEXCEPT | ||||
| { | ||||
| 	if (this == &other) | ||||
| 	Time & Time::operator-=(const Duration &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; | ||||
| 	} | ||||
| 
 | ||||
| 	time_ = other.time_; | ||||
| 	return *this; | ||||
| } | ||||
| 	Time& Time::operator=(Time && other) E2D_NOEXCEPT | ||||
| 	{ | ||||
| 		if (this == &other) | ||||
| 			return *this; | ||||
| 
 | ||||
| easy2d::Time& easy2d::Time::operator=(Time && other) E2D_NOEXCEPT | ||||
| { | ||||
| 	if (this == &other) | ||||
| 		time_ = std::move(other.time_); | ||||
| 		return *this; | ||||
| 	} | ||||
| 
 | ||||
| 	time_ = std::move(other.time_); | ||||
| 	return *this; | ||||
| } | ||||
| 
 | ||||
| easy2d::Time easy2d::Time::Now() | ||||
| { | ||||
| 	return Time(steady_clock::now()); | ||||
| } | ||||
| 	Time Time::Now() | ||||
| 	{ | ||||
| 		return Time(steady_clock::now()); | ||||
| 	} | ||||
| } | ||||
|  | @ -21,49 +21,52 @@ | |||
| #include "..\e2dutil.h" | ||||
| 
 | ||||
| 
 | ||||
| easy2d::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) | ||||
| namespace easy2d | ||||
| { | ||||
| } | ||||
| 	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 | ||||
| { | ||||
| 	auto pivot = D2D1::Point2F(size.width * pivot_x, size.height * pivot_y); | ||||
| 	auto matrix = D2D1::Matrix3x2F::Scale( | ||||
| 		scale_x, | ||||
| 		scale_y, | ||||
| 		pivot | ||||
| 	) * D2D1::Matrix3x2F::Skew( | ||||
| 		skew_x, | ||||
| 		skew_y, | ||||
| 		pivot | ||||
| 	) * D2D1::Matrix3x2F::Rotation( | ||||
| 		rotation, | ||||
| 		pivot | ||||
| 	) * D2D1::Matrix3x2F::Translation( | ||||
| 		position.x - pivot.x, | ||||
| 		position.y - pivot.y | ||||
| 	); | ||||
| 	return matrix; | ||||
| } | ||||
| 	Transform::operator D2D1::Matrix3x2F() const | ||||
| 	{ | ||||
| 		auto pivot = D2D1::Point2F(size.width * pivot_x, size.height * pivot_y); | ||||
| 		auto matrix = D2D1::Matrix3x2F::Scale( | ||||
| 			scale_x, | ||||
| 			scale_y, | ||||
| 			pivot | ||||
| 		) * D2D1::Matrix3x2F::Skew( | ||||
| 			skew_x, | ||||
| 			skew_y, | ||||
| 			pivot | ||||
| 		) * D2D1::Matrix3x2F::Rotation( | ||||
| 			rotation, | ||||
| 			pivot | ||||
| 		) * D2D1::Matrix3x2F::Translation( | ||||
| 			position.x - pivot.x, | ||||
| 			position.y - pivot.y | ||||
| 		); | ||||
| 		return matrix; | ||||
| 	} | ||||
| 
 | ||||
| bool easy2d::Transform::operator==(const Transform & other) const | ||||
| { | ||||
| 	return position == other.position && | ||||
| 		size == other.size && | ||||
| 		scale_x == other.scale_x && | ||||
| 		scale_y == other.scale_y && | ||||
| 		skew_x == other.skew_x && | ||||
| 		skew_y == other.skew_y && | ||||
| 		rotation == other.rotation && | ||||
| 		pivot_x == other.pivot_x && | ||||
| 		pivot_y == other.pivot_y; | ||||
| } | ||||
| 	bool Transform::operator==(const Transform & other) const | ||||
| 	{ | ||||
| 		return position == other.position && | ||||
| 			size == other.size && | ||||
| 			scale_x == other.scale_x && | ||||
| 			scale_y == other.scale_y && | ||||
| 			skew_x == other.skew_x && | ||||
| 			skew_y == other.skew_y && | ||||
| 			rotation == other.rotation && | ||||
| 			pivot_x == other.pivot_x && | ||||
| 			pivot_y == other.pivot_y; | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue