change: add namespace modules & load libraries from dll
refactoring: time package refactoring: the whole project has been changed
This commit is contained in:
parent
b129a1bf18
commit
f4cadddce4
|
|
@ -1,138 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Animate::Animate()
|
||||
: frame_index_(0)
|
||||
, animation_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Animate::Animate(Animation * animation)
|
||||
: frame_index_(0)
|
||||
, animation_(nullptr)
|
||||
{
|
||||
this->SetAnimation(animation);
|
||||
}
|
||||
|
||||
Animate::~Animate()
|
||||
{
|
||||
SafeRelease(animation_);
|
||||
}
|
||||
|
||||
Animation * Animate::GetAnimation() const
|
||||
{
|
||||
return 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_)
|
||||
{
|
||||
return new Animate(animation_);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Animate * Animate::Reverse() const
|
||||
{
|
||||
if (animation_)
|
||||
{
|
||||
auto animation = animation_->Reverse();
|
||||
if (animation)
|
||||
{
|
||||
return new Animate(animation);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
FadeIn::FadeIn(float duration)
|
||||
: OpacityTo(duration, 1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
MoveTo::MoveTo(float duration, Point pos)
|
||||
: MoveBy(duration, Point())
|
||||
{
|
||||
end_pos_ = pos;
|
||||
}
|
||||
|
||||
MoveTo * MoveTo::Clone() const
|
||||
{
|
||||
return new MoveTo(duration_, end_pos_);
|
||||
}
|
||||
|
||||
void MoveTo::Init()
|
||||
{
|
||||
MoveBy::Init();
|
||||
delta_pos_ = end_pos_ - start_pos_;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Sequence::Sequence()
|
||||
: action_index_(0)
|
||||
{
|
||||
}
|
||||
|
||||
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->ResetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Add(Action * action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
actions_.push_back(action);
|
||||
action->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Add(const Actions& actions)
|
||||
{
|
||||
for (const auto &action : actions)
|
||||
{
|
||||
this->Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Spawn::Spawn()
|
||||
{
|
||||
}
|
||||
|
||||
Spawn::Spawn(const Actions& actions)
|
||||
{
|
||||
this->Add(actions);
|
||||
}
|
||||
|
||||
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->ResetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::Add(Action * action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
actions_.push_back(action);
|
||||
action->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::Add(const Actions& actions)
|
||||
{
|
||||
for (const auto &action : actions)
|
||||
{
|
||||
this->Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -18,16 +18,13 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
|
||||
#include "Action.h"
|
||||
#include "base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Action::Action()
|
||||
: running_(false)
|
||||
, done_(false)
|
||||
, initialized_(false)
|
||||
, target_(nullptr)
|
||||
: running_(false), done_(false), initialized_(false), target_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -55,12 +52,12 @@ namespace easy2d
|
|||
done_ = true;
|
||||
}
|
||||
|
||||
const std::wstring& Action::GetName() const
|
||||
const String& Action::GetName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void Action::SetName(const std::wstring& name)
|
||||
void Action::SetName(const String& name)
|
||||
{
|
||||
name_ = name;
|
||||
}
|
||||
|
|
@ -74,7 +71,7 @@ namespace easy2d
|
|||
{
|
||||
initialized_ = false;
|
||||
done_ = false;
|
||||
started_ = Time::Now();
|
||||
started_ = time::Now();
|
||||
}
|
||||
|
||||
bool Action::IsDone() const
|
||||
|
|
@ -89,21 +86,21 @@ namespace easy2d
|
|||
this->Reset();
|
||||
}
|
||||
|
||||
void Action::Init()
|
||||
void Action::Initialize()
|
||||
{
|
||||
initialized_ = true;
|
||||
started_ = Time::Now();
|
||||
started_ = time::Now();
|
||||
}
|
||||
|
||||
void Action::Update()
|
||||
{
|
||||
if (!initialized_)
|
||||
{
|
||||
Init();
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void Action::ResetTime()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "time.h"
|
||||
#include "RefCounter.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
class Node;
|
||||
class Loop;
|
||||
class Sequence;
|
||||
class Spawn;
|
||||
|
||||
// 基础动作
|
||||
class Action
|
||||
: public RefCounter
|
||||
{
|
||||
friend class Loop;
|
||||
friend class Sequence;
|
||||
friend class Spawn;
|
||||
|
||||
public:
|
||||
Action();
|
||||
|
||||
virtual ~Action();
|
||||
|
||||
// 获取动作运行状态
|
||||
virtual bool IsRunning();
|
||||
|
||||
// 继续动作
|
||||
virtual void Resume();
|
||||
|
||||
// 暂停动作
|
||||
virtual void Pause();
|
||||
|
||||
// 停止动作
|
||||
virtual void Stop();
|
||||
|
||||
// 获取动作名称
|
||||
virtual const String& GetName() const;
|
||||
|
||||
// 设置动作名称
|
||||
virtual void SetName(
|
||||
const String& name
|
||||
);
|
||||
|
||||
// 获取动作的拷贝
|
||||
virtual Action * Clone() const = 0;
|
||||
|
||||
// 获取动作的倒转
|
||||
virtual Action * Reverse() const = 0;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset();
|
||||
|
||||
// 获取该动作的执行目标
|
||||
virtual Node * GetTarget();
|
||||
|
||||
// 开始动作
|
||||
virtual void StartWithTarget(
|
||||
Node* target
|
||||
);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize();
|
||||
|
||||
// 更新动作
|
||||
virtual void Update();
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime();
|
||||
|
||||
// 获取动作结束状态
|
||||
virtual bool IsDone() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Action);
|
||||
|
||||
protected:
|
||||
String name_;
|
||||
bool running_;
|
||||
bool done_;
|
||||
bool initialized_;
|
||||
Node* target_;
|
||||
time::TimePoint started_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,368 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "ActionCombined.h"
|
||||
#include "base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// Loop
|
||||
//-------------------------------------------------------
|
||||
|
||||
Loop::Loop(Action * action, int times /* = -1 */)
|
||||
: action_(action)
|
||||
, times_(0)
|
||||
, total_times_(times)
|
||||
{
|
||||
E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!");
|
||||
|
||||
if (action)
|
||||
{
|
||||
action_ = action;
|
||||
action_->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
Loop::~Loop()
|
||||
{
|
||||
SafeRelease(action_);
|
||||
}
|
||||
|
||||
Loop * Loop::Clone() const
|
||||
{
|
||||
if (action_)
|
||||
{
|
||||
return new Loop(action_->Clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Loop * Loop::Reverse() const
|
||||
{
|
||||
if (action_)
|
||||
{
|
||||
return new Loop(action_->Clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Loop::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
|
||||
if (action_)
|
||||
{
|
||||
action_->target_ = target_;
|
||||
action_->Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Sequence
|
||||
//-------------------------------------------------------
|
||||
|
||||
Sequence::Sequence()
|
||||
: action_index_(0)
|
||||
{
|
||||
}
|
||||
|
||||
Sequence::Sequence(const Actions& actions)
|
||||
: action_index_(0)
|
||||
{
|
||||
this->Add(actions);
|
||||
}
|
||||
|
||||
Sequence::~Sequence()
|
||||
{
|
||||
for (auto action : actions_)
|
||||
{
|
||||
SafeRelease(action);
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
// 将所有动作与目标绑定
|
||||
if (target_)
|
||||
{
|
||||
for (const auto& action : actions_)
|
||||
{
|
||||
action->target_ = target_;
|
||||
}
|
||||
}
|
||||
// 初始化第一个动作
|
||||
actions_[0]->Initialize();
|
||||
}
|
||||
|
||||
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_]->Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Reset()
|
||||
{
|
||||
Action::Reset();
|
||||
for (const auto& action : actions_)
|
||||
{
|
||||
action->Reset();
|
||||
}
|
||||
action_index_ = 0;
|
||||
}
|
||||
|
||||
void Sequence::ResetTime()
|
||||
{
|
||||
for (const auto& action : actions_)
|
||||
{
|
||||
action->ResetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Add(Action * action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
actions_.push_back(action);
|
||||
action->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Add(const Actions& actions)
|
||||
{
|
||||
for (const auto &action : actions)
|
||||
{
|
||||
this->Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Spawn
|
||||
//-------------------------------------------------------
|
||||
|
||||
Spawn::Spawn()
|
||||
{
|
||||
}
|
||||
|
||||
Spawn::Spawn(const Actions& actions)
|
||||
{
|
||||
this->Add(actions);
|
||||
}
|
||||
|
||||
Spawn::~Spawn()
|
||||
{
|
||||
for (auto action : actions_)
|
||||
{
|
||||
SafeRelease(action);
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
for (const auto& action : actions_)
|
||||
{
|
||||
action->target_ = target_;
|
||||
action->Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->ResetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::Add(Action * action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
actions_.push_back(action);
|
||||
action->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::Add(const Actions& actions)
|
||||
{
|
||||
for (const auto &action : actions)
|
||||
{
|
||||
this->Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Action.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 循环动作
|
||||
class Loop
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
explicit Loop(
|
||||
Action * action, /* 执行循环的动作 */
|
||||
int times = -1 /* 循环次数 */
|
||||
);
|
||||
|
||||
virtual ~Loop();
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Loop * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Loop * Reverse() const override;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Loop);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
Action * action_;
|
||||
int times_;
|
||||
int total_times_;
|
||||
};
|
||||
|
||||
|
||||
// 顺序动作
|
||||
class Sequence
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Action*> Actions;
|
||||
|
||||
Sequence();
|
||||
|
||||
explicit Sequence(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
virtual ~Sequence();
|
||||
|
||||
// 在结尾添加动作
|
||||
void Add(
|
||||
Action * action
|
||||
);
|
||||
|
||||
// 在结尾添加多个动作
|
||||
void Add(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Sequence * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Sequence * Reverse() const;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Sequence);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
UINT action_index_;
|
||||
Actions actions_;
|
||||
};
|
||||
|
||||
|
||||
// 同步动作
|
||||
class Spawn
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Action*> Actions;
|
||||
|
||||
Spawn();
|
||||
|
||||
explicit Spawn(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
virtual ~Spawn();
|
||||
|
||||
// 在结尾添加动作
|
||||
void Add(
|
||||
Action * action
|
||||
);
|
||||
|
||||
// 在结尾添加多个动作
|
||||
void Add(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Spawn * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Spawn * Reverse() const;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Spawn);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
Actions actions_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "ActionFiniteTime.h"
|
||||
#include "base.h"
|
||||
#include "Node.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// FiniteTimeAction
|
||||
//-------------------------------------------------------
|
||||
|
||||
FiniteTimeAction::FiniteTimeAction(float duration)
|
||||
: delta_(0)
|
||||
, duration_(std::max(duration, 0.f))
|
||||
{
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Reset()
|
||||
{
|
||||
Action::Reset();
|
||||
delta_ = 0;
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Update()
|
||||
{
|
||||
Action::Update();
|
||||
|
||||
if (duration_ == 0)
|
||||
{
|
||||
delta_ = 1;
|
||||
this->Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
delta_ = std::min((time::Now() - started_).Seconds() / duration_, 1.f);
|
||||
|
||||
if (delta_ >= 1)
|
||||
{
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteTimeAction::ResetTime()
|
||||
{
|
||||
Action::ResetTime();
|
||||
started_ = time::Now() - time::Second * (delta_ * duration_);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Move Action
|
||||
//-------------------------------------------------------
|
||||
|
||||
MoveBy::MoveBy(float duration, Point vector)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_pos_ = vector;
|
||||
}
|
||||
|
||||
void MoveBy::Initialize()
|
||||
{
|
||||
FiniteTimeAction::Initialize();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
prev_pos_ = start_pos_ = target_->GetPosition();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
MoveTo::MoveTo(float duration, Point pos)
|
||||
: MoveBy(duration, Point())
|
||||
{
|
||||
end_pos_ = pos;
|
||||
}
|
||||
|
||||
MoveTo * MoveTo::Clone() const
|
||||
{
|
||||
return new MoveTo(duration_, end_pos_);
|
||||
}
|
||||
|
||||
void MoveTo::Initialize()
|
||||
{
|
||||
MoveBy::Initialize();
|
||||
delta_pos_ = end_pos_ - start_pos_;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Jump Action
|
||||
//-------------------------------------------------------
|
||||
|
||||
JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps)
|
||||
: FiniteTimeAction(duration)
|
||||
, delta_pos_(vec)
|
||||
, height_(height)
|
||||
, jumps_(jumps)
|
||||
{
|
||||
}
|
||||
|
||||
JumpBy * JumpBy::Clone() const
|
||||
{
|
||||
return new JumpBy(duration_, delta_pos_, height_, jumps_);
|
||||
}
|
||||
|
||||
JumpBy * JumpBy::Reverse() const
|
||||
{
|
||||
return new JumpBy(duration_, -delta_pos_, height_, jumps_);
|
||||
}
|
||||
|
||||
void JumpBy::Initialize()
|
||||
{
|
||||
FiniteTimeAction::Initialize();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps)
|
||||
: JumpBy(duration, Point(), height, jumps)
|
||||
, end_pos_(pos)
|
||||
{
|
||||
}
|
||||
|
||||
JumpTo * JumpTo::Clone() const
|
||||
{
|
||||
return new JumpTo(duration_, end_pos_, height_, jumps_);
|
||||
}
|
||||
|
||||
void JumpTo::Initialize()
|
||||
{
|
||||
JumpBy::Initialize();
|
||||
delta_pos_ = end_pos_ - start_pos_;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Scale Action
|
||||
//-------------------------------------------------------
|
||||
|
||||
ScaleBy::ScaleBy(float duration, float scale)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_x_ = scale;
|
||||
delta_y_ = scale;
|
||||
}
|
||||
|
||||
ScaleBy::ScaleBy(float duration, float scale_x, float scale_y)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_x_ = scale_x;
|
||||
delta_y_ = scale_y;
|
||||
}
|
||||
|
||||
void ScaleBy::Initialize()
|
||||
{
|
||||
FiniteTimeAction::Initialize();
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
ScaleTo::ScaleTo(float duration, float scale)
|
||||
: ScaleBy(duration, 0, 0)
|
||||
{
|
||||
end_scale_x_ = scale;
|
||||
end_scale_y_ = scale;
|
||||
}
|
||||
|
||||
ScaleTo::ScaleTo(float duration, float scale_x, float scale_y)
|
||||
: ScaleBy(duration, 0, 0)
|
||||
{
|
||||
end_scale_x_ = scale_x;
|
||||
end_scale_y_ = scale_y;
|
||||
}
|
||||
|
||||
ScaleTo * ScaleTo::Clone() const
|
||||
{
|
||||
return new ScaleTo(duration_, end_scale_x_, end_scale_y_);
|
||||
}
|
||||
|
||||
void ScaleTo::Initialize()
|
||||
{
|
||||
ScaleBy::Initialize();
|
||||
delta_x_ = end_scale_x_ - start_scale_x_;
|
||||
delta_y_ = end_scale_y_ - start_scale_y_;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Opacity Action
|
||||
//-------------------------------------------------------
|
||||
|
||||
OpacityBy::OpacityBy(float duration, float opacity)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_val_ = opacity;
|
||||
}
|
||||
|
||||
void OpacityBy::Initialize()
|
||||
{
|
||||
FiniteTimeAction::Initialize();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
start_val_ = target_->GetOpacity();
|
||||
}
|
||||
}
|
||||
|
||||
void OpacityBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
OpacityTo::OpacityTo(float duration, float opacity)
|
||||
: OpacityBy(duration, 0)
|
||||
{
|
||||
end_val_ = opacity;
|
||||
}
|
||||
|
||||
OpacityTo * OpacityTo::Clone() const
|
||||
{
|
||||
return new OpacityTo(duration_, end_val_);
|
||||
}
|
||||
|
||||
void OpacityTo::Initialize()
|
||||
{
|
||||
OpacityBy::Initialize();
|
||||
delta_val_ = end_val_ - start_val_;
|
||||
}
|
||||
|
||||
FadeIn::FadeIn(float duration)
|
||||
: OpacityTo(duration, 1)
|
||||
{
|
||||
}
|
||||
|
||||
FadeOut::FadeOut(float duration)
|
||||
: OpacityTo(duration, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Rotate Action
|
||||
//-------------------------------------------------------
|
||||
|
||||
RotateBy::RotateBy(float duration, float rotation)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_val_ = rotation;
|
||||
}
|
||||
|
||||
void RotateBy::Initialize()
|
||||
{
|
||||
FiniteTimeAction::Initialize();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
start_val_ = target_->GetRotation();
|
||||
}
|
||||
}
|
||||
|
||||
void RotateBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
RotateTo::RotateTo(float duration, float rotation)
|
||||
: RotateBy(duration, 0)
|
||||
{
|
||||
end_val_ = rotation;
|
||||
}
|
||||
|
||||
RotateTo * RotateTo::Clone() const
|
||||
{
|
||||
return new RotateTo(duration_, end_val_);
|
||||
}
|
||||
|
||||
void RotateTo::Initialize()
|
||||
{
|
||||
RotateBy::Initialize();
|
||||
delta_val_ = end_val_ - start_val_;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Delay
|
||||
//-------------------------------------------------------
|
||||
|
||||
Delay::Delay(float duration)
|
||||
: delta_(0)
|
||||
, delay_(std::max(duration, 0.f))
|
||||
{
|
||||
}
|
||||
|
||||
void Delay::Reset()
|
||||
{
|
||||
Action::Reset();
|
||||
delta_ = 0;
|
||||
}
|
||||
|
||||
void Delay::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
}
|
||||
|
||||
void Delay::Update()
|
||||
{
|
||||
Action::Update();
|
||||
|
||||
delta_ = (time::Now() - started_).Seconds();
|
||||
|
||||
if (delta_ >= delay_)
|
||||
{
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Delay::ResetTime()
|
||||
{
|
||||
Action::ResetTime();
|
||||
started_ = time::Now() - time::Second * delta_;
|
||||
}
|
||||
|
||||
Delay * Delay::Clone() const
|
||||
{
|
||||
return new Delay(delay_);
|
||||
}
|
||||
|
||||
Delay * Delay::Reverse() const
|
||||
{
|
||||
return new Delay(delay_);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,98 +18,12 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_ACTION_H__
|
||||
#define __E2D_ACTION_H__
|
||||
|
||||
|
||||
#include "e2dutil.h"
|
||||
#include "e2dobject.h"
|
||||
#pragma once
|
||||
#include "Action.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
class Node;
|
||||
class Loop;
|
||||
class Sequence;
|
||||
class Spawn;
|
||||
|
||||
|
||||
// 基础动作
|
||||
class Action
|
||||
: public Ref
|
||||
{
|
||||
friend class Loop;
|
||||
friend class Sequence;
|
||||
friend class Spawn;
|
||||
|
||||
public:
|
||||
Action();
|
||||
|
||||
virtual ~Action();
|
||||
|
||||
// 获取动作运行状态
|
||||
virtual bool IsRunning();
|
||||
|
||||
// 继续动作
|
||||
virtual void Resume();
|
||||
|
||||
// 暂停动作
|
||||
virtual void Pause();
|
||||
|
||||
// 停止动作
|
||||
virtual void Stop();
|
||||
|
||||
// 获取动作名称
|
||||
virtual const std::wstring& GetName() const;
|
||||
|
||||
// 设置动作名称
|
||||
virtual void SetName(
|
||||
const std::wstring& name
|
||||
);
|
||||
|
||||
// 获取动作的拷贝
|
||||
virtual Action * Clone() const = 0;
|
||||
|
||||
// 获取动作的倒转
|
||||
virtual Action * Reverse() const = 0;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset();
|
||||
|
||||
// 获取该动作的执行目标
|
||||
virtual Node * GetTarget();
|
||||
|
||||
// 开始动作
|
||||
virtual void StartWithTarget(
|
||||
Node* target
|
||||
);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init();
|
||||
|
||||
// 更新动作
|
||||
virtual void Update();
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime();
|
||||
|
||||
// 获取动作结束状态
|
||||
virtual bool IsDone() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Action);
|
||||
|
||||
protected:
|
||||
std::wstring name_;
|
||||
bool running_;
|
||||
bool done_;
|
||||
bool initialized_;
|
||||
Node* target_;
|
||||
Time started_;
|
||||
};
|
||||
|
||||
|
||||
// 持续动作
|
||||
// ³ÖÐø¶¯×÷
|
||||
class FiniteTimeAction
|
||||
: public Action
|
||||
{
|
||||
|
|
@ -126,7 +40,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(FiniteTimeAction);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -160,7 +74,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(MoveBy);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -196,7 +110,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(MoveTo);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
protected:
|
||||
Point end_pos_;
|
||||
|
|
@ -225,7 +139,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(JumpBy);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -265,7 +179,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(JumpTo);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
protected:
|
||||
Point end_pos_;
|
||||
|
|
@ -298,7 +212,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(ScaleBy);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -341,7 +255,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(ScaleTo);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
protected:
|
||||
float end_scale_x_;
|
||||
|
|
@ -369,7 +283,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(OpacityBy);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -404,7 +318,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(OpacityTo);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
protected:
|
||||
float end_val_;
|
||||
|
|
@ -461,7 +375,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(RotateBy);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -496,7 +410,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(RotateTo);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
protected:
|
||||
float end_val_;
|
||||
|
|
@ -525,7 +439,7 @@ namespace easy2d
|
|||
E2D_DISABLE_COPY(Delay);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
|
@ -537,290 +451,4 @@ namespace easy2d
|
|||
float delay_;
|
||||
float delta_;
|
||||
};
|
||||
|
||||
|
||||
// 循环动作
|
||||
class Loop
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
explicit Loop(
|
||||
Action * action, /* 执行循环的动作 */
|
||||
int times = -1 /* 循环次数 */
|
||||
);
|
||||
|
||||
virtual ~Loop();
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Loop * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Loop * Reverse() const override;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Loop);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
Action * action_;
|
||||
int times_;
|
||||
int total_times_;
|
||||
};
|
||||
|
||||
|
||||
// 回调动作
|
||||
class CallFunc
|
||||
: public Action
|
||||
{
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
public:
|
||||
explicit CallFunc(
|
||||
const Callback& func /* 函数对象 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual CallFunc * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual CallFunc * Reverse() const override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(CallFunc);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
protected:
|
||||
Callback callback_;
|
||||
};
|
||||
|
||||
|
||||
// 顺序动作
|
||||
class Sequence
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Action*> Actions;
|
||||
|
||||
Sequence();
|
||||
|
||||
explicit Sequence(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
virtual ~Sequence();
|
||||
|
||||
// 在结尾添加动作
|
||||
void Add(
|
||||
Action * action
|
||||
);
|
||||
|
||||
// 在结尾添加多个动作
|
||||
void Add(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Sequence * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Sequence * Reverse() const;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Sequence);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
UINT action_index_;
|
||||
Actions actions_;
|
||||
};
|
||||
|
||||
|
||||
// 同步动作
|
||||
class Spawn
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Action*> Actions;
|
||||
|
||||
Spawn();
|
||||
|
||||
explicit Spawn(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
virtual ~Spawn();
|
||||
|
||||
// 在结尾添加动作
|
||||
void Add(
|
||||
Action * action
|
||||
);
|
||||
|
||||
// 在结尾添加多个动作
|
||||
void Add(
|
||||
const Actions& actions /* 动作列表 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Spawn * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Spawn * Reverse() const;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Spawn);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
Actions actions_;
|
||||
};
|
||||
|
||||
|
||||
// 帧动画
|
||||
class Animation
|
||||
: public Ref
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Image*> Images;
|
||||
|
||||
Animation();
|
||||
|
||||
explicit Animation(
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
explicit Animation(
|
||||
float interval /* 帧间隔(秒) */
|
||||
);
|
||||
|
||||
explicit Animation(
|
||||
float interval, /* 帧间隔(秒) */
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
virtual ~Animation();
|
||||
|
||||
// 添加关键帧
|
||||
void Add(
|
||||
Image * frame /* 关键帧 */
|
||||
);
|
||||
|
||||
// 添加多个关键帧
|
||||
void Add(
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
// 获取帧间隔
|
||||
float GetInterval() const;
|
||||
|
||||
// 获取关键帧
|
||||
const Images& GetFrames() const;
|
||||
|
||||
// 设置每一帧的时间间隔
|
||||
void SetInterval(
|
||||
float interval /* 帧间隔(秒) */
|
||||
);
|
||||
|
||||
// 获取帧动画的拷贝对象
|
||||
Animation * Clone() const;
|
||||
|
||||
// 获取帧动画的倒转
|
||||
Animation * Reverse() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Animation);
|
||||
|
||||
protected:
|
||||
float interval_;
|
||||
Images frames_;
|
||||
};
|
||||
|
||||
|
||||
// 精灵动作
|
||||
class Animate
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
Animate();
|
||||
|
||||
explicit Animate(
|
||||
Animation * animation
|
||||
);
|
||||
|
||||
virtual ~Animate();
|
||||
|
||||
// 获取动画
|
||||
virtual Animation * GetAnimation() const;
|
||||
|
||||
// 设置动画
|
||||
virtual void SetAnimation(
|
||||
Animation * animation
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Animate * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Animate * Reverse() const override;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Animate);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Init() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
UINT frame_index_;
|
||||
Animation * animation_;
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_ACTION_H__
|
||||
}
|
||||
|
|
@ -18,10 +18,133 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "Animation.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// Animate
|
||||
//-------------------------------------------------------
|
||||
|
||||
Animate::Animate()
|
||||
: frame_index_(0)
|
||||
, animation_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Animate::Animate(Animation * animation)
|
||||
: frame_index_(0)
|
||||
, animation_(nullptr)
|
||||
{
|
||||
this->SetAnimation(animation);
|
||||
}
|
||||
|
||||
Animate::~Animate()
|
||||
{
|
||||
SafeRelease(animation_);
|
||||
}
|
||||
|
||||
Animation * Animate::GetAnimation() const
|
||||
{
|
||||
return animation_;
|
||||
}
|
||||
|
||||
void Animate::SetAnimation(Animation * animation)
|
||||
{
|
||||
if (animation && animation != animation_)
|
||||
{
|
||||
if (animation_)
|
||||
{
|
||||
animation_->Release();
|
||||
}
|
||||
animation_ = animation;
|
||||
animation_->Retain();
|
||||
frame_index_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Animate::Initialize()
|
||||
{
|
||||
Action::Initialize();
|
||||
|
||||
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_ += time::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_)
|
||||
{
|
||||
return new Animate(animation_);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Animate * Animate::Reverse() const
|
||||
{
|
||||
if (animation_)
|
||||
{
|
||||
auto animation = animation_->Reverse();
|
||||
if (animation)
|
||||
{
|
||||
return new Animate(animation);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Animation
|
||||
//-------------------------------------------------------
|
||||
|
||||
Animation::Animation()
|
||||
: interval_(1)
|
||||
{
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Action.h"
|
||||
#include "Image.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 帧动画
|
||||
class Animation
|
||||
: public RefCounter
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Image*> Images;
|
||||
|
||||
Animation();
|
||||
|
||||
explicit Animation(
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
explicit Animation(
|
||||
float interval /* 帧间隔(秒) */
|
||||
);
|
||||
|
||||
explicit Animation(
|
||||
float interval, /* 帧间隔(秒) */
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
virtual ~Animation();
|
||||
|
||||
// 添加关键帧
|
||||
void Add(
|
||||
Image * frame /* 关键帧 */
|
||||
);
|
||||
|
||||
// 添加多个关键帧
|
||||
void Add(
|
||||
const Images& frames /* 关键帧数组 */
|
||||
);
|
||||
|
||||
// 获取帧间隔
|
||||
float GetInterval() const;
|
||||
|
||||
// 获取关键帧
|
||||
const Images& GetFrames() const;
|
||||
|
||||
// 设置每一帧的时间间隔
|
||||
void SetInterval(
|
||||
float interval /* 帧间隔(秒) */
|
||||
);
|
||||
|
||||
// 获取帧动画的拷贝对象
|
||||
Animation * Clone() const;
|
||||
|
||||
// 获取帧动画的倒转
|
||||
Animation * Reverse() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Animation);
|
||||
|
||||
protected:
|
||||
float interval_;
|
||||
Images frames_;
|
||||
};
|
||||
|
||||
|
||||
// 精灵动作
|
||||
class Animate
|
||||
: public Action
|
||||
{
|
||||
public:
|
||||
Animate();
|
||||
|
||||
explicit Animate(
|
||||
Animation * animation
|
||||
);
|
||||
|
||||
virtual ~Animate();
|
||||
|
||||
// 获取动画
|
||||
virtual Animation * GetAnimation() const;
|
||||
|
||||
// 设置动画
|
||||
virtual void SetAnimation(
|
||||
Animation * animation
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual Animate * Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual Animate * Reverse() const override;
|
||||
|
||||
// 重置动作
|
||||
virtual void Reset() override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Animate);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
// 重置动作时间
|
||||
virtual void ResetTime() override;
|
||||
|
||||
protected:
|
||||
UINT frame_index_;
|
||||
Animation * animation_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include "../math/vector.hpp"
|
||||
#include "Color.h"
|
||||
#include "Size.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 坐标
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维空间的坐标: Point origin(0, 0);
|
||||
// 计算两点间距离: float distance = p1.Distance(p2);
|
||||
// 坐标可以相加减: Point p = Point(10, 10) + Point(20, 20); // p 的坐标是 (30, 30)
|
||||
//
|
||||
typedef math::Vector2 Point;
|
||||
|
||||
typedef std::wstring String;
|
||||
|
||||
// 方向
|
||||
enum class Direction : int
|
||||
{
|
||||
Up, /* 上 */
|
||||
Down, /* 下 */
|
||||
Left, /* 左 */
|
||||
Right /* 右 */
|
||||
};
|
||||
|
||||
// 线条相交样式
|
||||
enum class Stroke : int
|
||||
{
|
||||
Miter = 0, /* 斜切 */
|
||||
Bevel = 1, /* 斜角 */
|
||||
Round = 2 /* 圆角 */
|
||||
};
|
||||
|
||||
// 键盘键值
|
||||
enum class KeyCode : int
|
||||
{
|
||||
Unknown = 0,
|
||||
Up = VK_UP,
|
||||
Left = VK_LEFT,
|
||||
Right = VK_RIGHT,
|
||||
Down = VK_DOWN,
|
||||
Enter = VK_RETURN,
|
||||
Space = VK_SPACE,
|
||||
Esc = VK_ESCAPE,
|
||||
Ctrl = VK_CONTROL,
|
||||
Shift = VK_SHIFT,
|
||||
|
||||
A = 0x41,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
|
||||
Num0 = 0x30,
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
|
||||
Numpad0 = VK_NUMPAD0,
|
||||
Numpad1,
|
||||
Numpad2,
|
||||
Numpad3,
|
||||
Numpad4,
|
||||
Numpad5,
|
||||
Numpad6,
|
||||
Numpad7,
|
||||
Numpad8,
|
||||
Numpad9,
|
||||
|
||||
F1 = VK_F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
};
|
||||
|
||||
// 鼠标键值
|
||||
enum class MouseCode : int
|
||||
{
|
||||
Left = VK_LBUTTON, /* 鼠标左键 */
|
||||
Right = VK_RBUTTON, /* 鼠标右键 */
|
||||
Middle = VK_MBUTTON /* 鼠标中键 */
|
||||
};
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "CallFunc.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -37,7 +37,7 @@ namespace easy2d
|
|||
return new CallFunc(callback_);
|
||||
}
|
||||
|
||||
void CallFunc::Init()
|
||||
void CallFunc::Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -46,4 +46,4 @@ namespace easy2d
|
|||
callback_();
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Action.h"
|
||||
#include <functional>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 回调动作
|
||||
class CallFunc
|
||||
: public Action
|
||||
{
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
public:
|
||||
explicit CallFunc(
|
||||
const Callback &func /* 函数对象 */
|
||||
);
|
||||
|
||||
// 获取该动作的拷贝对象
|
||||
virtual CallFunc *Clone() const override;
|
||||
|
||||
// 获取该动作的倒转
|
||||
virtual CallFunc *Reverse() const override;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(CallFunc);
|
||||
|
||||
// 初始化动作
|
||||
virtual void Initialize() override;
|
||||
|
||||
// 更新动作
|
||||
virtual void Update() override;
|
||||
|
||||
protected:
|
||||
Callback callback_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,8 +18,9 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "base.h"
|
||||
#include "Canvas.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -31,7 +32,7 @@ namespace easy2d
|
|||
, stroke_width_(1.0f)
|
||||
, stroke_(Stroke::Miter)
|
||||
{
|
||||
render_target_ = Device::GetGraphics()->GetRenderTarget();
|
||||
render_target_ = render::D2D.HwndRenderTarget;
|
||||
render_target_->AddRef();
|
||||
|
||||
ThrowIfFailed(
|
||||
|
|
@ -56,6 +57,7 @@ namespace easy2d
|
|||
|
||||
Canvas::~Canvas()
|
||||
{
|
||||
SafeRelease(stroke_style_);
|
||||
SafeRelease(line_brush_);
|
||||
SafeRelease(fill_brush_);
|
||||
SafeRelease(render_target_);
|
||||
|
|
@ -78,18 +80,23 @@ namespace easy2d
|
|||
|
||||
void Canvas::SetStrokeStyle(Stroke strokeStyle)
|
||||
{
|
||||
SafeRelease(stroke_style_);
|
||||
|
||||
switch (strokeStyle)
|
||||
{
|
||||
case Stroke::Miter:
|
||||
stroke_style_ = Device::GetGraphics()->GetMiterStrokeStyle();
|
||||
stroke_style_ = render::D2D.MiterStrokeStyle;
|
||||
break;
|
||||
case Stroke::Bevel:
|
||||
stroke_style_ = Device::GetGraphics()->GetBevelStrokeStyle();
|
||||
stroke_style_ = render::D2D.BevelStrokeStyle;
|
||||
break;
|
||||
case Stroke::Round:
|
||||
stroke_style_ = Device::GetGraphics()->GetRoundStrokeStyle();
|
||||
stroke_style_ = render::D2D.RoundStrokeStyle;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stroke_style_)
|
||||
stroke_style_->AddRef();
|
||||
}
|
||||
|
||||
Color Canvas::GetLineColor() const
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Node.h"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// »²¼
|
||||
class Canvas
|
||||
: public Node
|
||||
{
|
||||
public:
|
||||
Canvas(
|
||||
float width,
|
||||
float height
|
||||
);
|
||||
|
||||
virtual ~Canvas();
|
||||
|
||||
// ÉèÖÃÏßÌõÑÕÉ«
|
||||
void SetLineColor(
|
||||
const Color& color
|
||||
);
|
||||
|
||||
// ÉèÖÃÌî³äÑÕÉ«
|
||||
void SetFillColor(
|
||||
const Color& color
|
||||
);
|
||||
|
||||
// ÉèÖÃÏßÌõ¿í¶È
|
||||
void SetStrokeWidth(
|
||||
float width
|
||||
);
|
||||
|
||||
// ÉèÖÃÏßÌõÏཻÑùʽ
|
||||
void SetStrokeStyle(
|
||||
Stroke strokeStyle
|
||||
);
|
||||
|
||||
// »ñÈ¡ÏßÌõÑÕÉ«
|
||||
Color GetLineColor() const;
|
||||
|
||||
// »ñÈ¡Ìî³äÑÕÉ«
|
||||
Color GetFillColor() const;
|
||||
|
||||
// »ñÈ¡ÏßÌõ¿í¶È
|
||||
float GetStrokeWidth() const;
|
||||
|
||||
// »ñÈ¡ÏßÌõÏཻÑùʽ
|
||||
Stroke GetStrokeStyle() const;
|
||||
|
||||
// »Ö±Ïß
|
||||
void DrawLine(
|
||||
const Point& begin,
|
||||
const Point& end
|
||||
);
|
||||
|
||||
// »Ô²Ðα߿ò
|
||||
void DrawCircle(
|
||||
const Point& center,
|
||||
float radius
|
||||
);
|
||||
|
||||
// »ÍÖÔ²Ðα߿ò
|
||||
void DrawEllipse(
|
||||
const Point& center,
|
||||
float radius_x,
|
||||
float radius_y
|
||||
);
|
||||
|
||||
// »¾ØÐα߿ò
|
||||
void DrawRect(
|
||||
const Rect& rect
|
||||
);
|
||||
|
||||
// »Ô²½Ç¾ØÐα߿ò
|
||||
void DrawRoundedRect(
|
||||
const Rect& rect,
|
||||
float radius_x,
|
||||
float radius_y
|
||||
);
|
||||
|
||||
// Ìî³äÔ²ÐÎ
|
||||
void FillCircle(
|
||||
const Point& center,
|
||||
float radius
|
||||
);
|
||||
|
||||
// Ìî³äÍÖÔ²ÐÎ
|
||||
void FillEllipse(
|
||||
const Point& center,
|
||||
float radius_x,
|
||||
float radius_y
|
||||
);
|
||||
|
||||
// Ìî³ä¾ØÐÎ
|
||||
void FillRect(
|
||||
const Rect& rect
|
||||
);
|
||||
|
||||
// Ìî³äÔ²½Ç¾ØÐÎ
|
||||
void FillRoundedRect(
|
||||
const Rect& rect,
|
||||
float radius_x,
|
||||
float radius_y
|
||||
);
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Canvas);
|
||||
|
||||
private:
|
||||
float stroke_width_;
|
||||
Stroke stroke_;
|
||||
ID2D1RenderTarget* render_target_;
|
||||
ID2D1SolidColorBrush* fill_brush_;
|
||||
ID2D1SolidColorBrush* line_brush_;
|
||||
ID2D1StrokeStyle* stroke_style_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,19 +18,19 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
#include "Color.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const UINT RED_SHIFT = 16;
|
||||
const UINT GREEN_SHIFT = 8;
|
||||
const UINT BLUE_SHIFT = 0;
|
||||
const unsigned int RED_SHIFT = 16;
|
||||
const unsigned int GREEN_SHIFT = 8;
|
||||
const unsigned int BLUE_SHIFT = 0;
|
||||
|
||||
const UINT RED_MASK = 0xff << RED_SHIFT;
|
||||
const UINT GREEN_MASK = 0xff << GREEN_SHIFT;
|
||||
const UINT BLUE_MASK = 0xff << BLUE_SHIFT;
|
||||
const unsigned int RED_MASK = 0xff << RED_SHIFT;
|
||||
const unsigned int GREEN_MASK = 0xff << GREEN_SHIFT;
|
||||
const unsigned int BLUE_MASK = 0xff << BLUE_SHIFT;
|
||||
}
|
||||
|
||||
Color::Color()
|
||||
|
|
@ -57,7 +57,7 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
Color::Color(UINT rgb)
|
||||
Color::Color(unsigned int 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)
|
||||
|
|
@ -65,7 +65,7 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
Color::Color(UINT rgb, float alpha)
|
||||
Color::Color(unsigned int 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)
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 颜色
|
||||
//
|
||||
// Usage:
|
||||
// 使用枚举表示颜色: Color blue = Color::Blue;
|
||||
// 使用 RGB 表示一个颜色: Color red(1.0f, 0.0f, 0.0f);
|
||||
// 使用 RGBA 表示一个带透明度的颜色: Color not_black(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
// 使用一个 unsigned int 类型的值表示 RGB: Color black(0x000000);
|
||||
//
|
||||
class Color
|
||||
{
|
||||
public:
|
||||
Color();
|
||||
|
||||
Color(
|
||||
float r,
|
||||
float g,
|
||||
float b
|
||||
);
|
||||
|
||||
Color(
|
||||
float r,
|
||||
float g,
|
||||
float b,
|
||||
float alpha
|
||||
);
|
||||
|
||||
Color(
|
||||
unsigned int rgb
|
||||
);
|
||||
|
||||
Color(
|
||||
unsigned int rgb,
|
||||
float alpha
|
||||
);
|
||||
|
||||
Color(
|
||||
const D2D1_COLOR_F& color
|
||||
);
|
||||
|
||||
operator D2D1_COLOR_F() const;
|
||||
|
||||
public:
|
||||
enum Value : unsigned int
|
||||
{
|
||||
Black = 0x000000,
|
||||
Blue = 0x0000FF,
|
||||
BlueViolet = 0x8A2BE2,
|
||||
Brown = 0xA52A2A,
|
||||
Chocolate = 0xD2691E,
|
||||
DarkBlue = 0x00008B,
|
||||
DarkGray = 0xA9A9A9,
|
||||
DarkGreen = 0x006400,
|
||||
DarkOrange = 0xFF8C00,
|
||||
DarkRed = 0x8B0000,
|
||||
DarkViolet = 0x9400D3,
|
||||
ForestGreen = 0x228B22,
|
||||
Gold = 0xFFD700,
|
||||
Gray = 0x808080,
|
||||
Green = 0x008000,
|
||||
GreenYellow = 0xADFF2F,
|
||||
LightBlue = 0xADD8E6,
|
||||
LightCyan = 0xE0FFFF,
|
||||
LightGreen = 0x90EE90,
|
||||
LightGray = 0xD3D3D3,
|
||||
LightPink = 0xFFB6C1,
|
||||
LightSeaGreen = 0x20B2AA,
|
||||
LightSkyBlue = 0x87CEFA,
|
||||
LightYellow = 0xFFFFE0,
|
||||
Orange = 0xFFA500,
|
||||
OrangeRed = 0xFF4500,
|
||||
Pink = 0xFFC0CB,
|
||||
Purple = 0x800080,
|
||||
Red = 0xFF0000,
|
||||
Silver = 0xC0C0C0,
|
||||
SkyBlue = 0x87CEEB,
|
||||
Snow = 0xFFFAFA,
|
||||
Violet = 0xEE82EE,
|
||||
Wheat = 0xF5DEB3,
|
||||
White = 0xFFFFFF,
|
||||
WhiteSmoke = 0xF5F5F5,
|
||||
Wood = 0xDEB887,
|
||||
Yellow = 0xFFFF00,
|
||||
YellowGreen = 0x9ACD32
|
||||
};
|
||||
|
||||
public:
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,16 +18,15 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
|
||||
#include "Font.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Font::Font(const std::wstring & family, float size, UINT weight, bool italic)
|
||||
Font::Font(const std::wstring & family, float size, unsigned int weight, bool italic)
|
||||
: family(family)
|
||||
, size(size)
|
||||
, weight(weight)
|
||||
, italic(italic)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,37 +18,41 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
FadeTransition::FadeTransition(float duration)
|
||||
: Transition(duration)
|
||||
// 字体
|
||||
class Font
|
||||
{
|
||||
}
|
||||
public:
|
||||
std::wstring family; // 字体族
|
||||
float size; // 字号
|
||||
unsigned int weight; // 粗细值
|
||||
bool italic; // 是否斜体
|
||||
|
||||
void FadeTransition::Init(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Init(prev, next, game);
|
||||
|
||||
out_layer_param_.opacity = 1;
|
||||
in_layer_param_.opacity = 0;
|
||||
}
|
||||
|
||||
void FadeTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
if (process_ < 0.5)
|
||||
public:
|
||||
// 字体粗细值
|
||||
enum Weight : unsigned int
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Thin = 100,
|
||||
ExtraLight = 200,
|
||||
Light = 300,
|
||||
Normal = 400,
|
||||
Medium = 500,
|
||||
Bold = 700,
|
||||
ExtraBold = 800,
|
||||
Black = 900,
|
||||
ExtraBlack = 950
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Font(
|
||||
const std::wstring& family = L"",
|
||||
float size = 22,
|
||||
unsigned int weight = Font::Weight::Normal,
|
||||
bool italic = false
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Game.h"
|
||||
#include "Node.h"
|
||||
#include "Scene.h"
|
||||
#include "Transition.h"
|
||||
#include "Image.h"
|
||||
#include "../utils/Player.h"
|
||||
#include "time.h"
|
||||
#include "render.h"
|
||||
#include "input.h"
|
||||
#include "audio.h"
|
||||
#include "modules.h"
|
||||
#include <thread>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Game * instance = nullptr;
|
||||
}
|
||||
|
||||
Game * Game::GetInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
Game::Game()
|
||||
: quit_(true)
|
||||
, curr_scene_(nullptr)
|
||||
, next_scene_(nullptr)
|
||||
, transition_(nullptr)
|
||||
, debug_mode_(false)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
throw std::runtime_error("同时只能存在一个游戏实例");
|
||||
}
|
||||
instance = this;
|
||||
|
||||
::CoInitialize(nullptr);
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
SafeRelease(transition_);
|
||||
SafeRelease(curr_scene_);
|
||||
SafeRelease(next_scene_);
|
||||
|
||||
Image::ClearCache();
|
||||
Player::ClearCache();
|
||||
|
||||
render::Uninitialize();
|
||||
audio::instance.Uninitialize();
|
||||
window::instance.Destroy();
|
||||
modules::Uninitialize();
|
||||
|
||||
instance = nullptr;
|
||||
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
void Game::Initialize(const window::Property& property)
|
||||
{
|
||||
modules::Initialize();
|
||||
window::instance.Initialize(property);
|
||||
audio::instance.Initialize();
|
||||
render::Initialize(window::instance.handle);
|
||||
|
||||
// 若开启了调试模式,打开控制台
|
||||
HWND console = ::GetConsoleWindow();
|
||||
// 关闭控制台
|
||||
if (debug_mode_)
|
||||
{
|
||||
if (console == nullptr)
|
||||
{
|
||||
// 显示一个新控制台
|
||||
if (::AllocConsole())
|
||||
{
|
||||
console = ::GetConsoleWindow();
|
||||
// 重定向输入输出
|
||||
FILE * stdoutStream, *stdinStream, *stderrStream;
|
||||
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
||||
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
||||
freopen_s(&stderrStream, "conout$", "w+t", stderr);
|
||||
// 禁用控制台关闭按钮
|
||||
HMENU hmenu = ::GetSystemMenu(console, FALSE);
|
||||
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (console)
|
||||
{
|
||||
::ShowWindow(console, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
::SetWindowLongPtrW(
|
||||
window::instance.handle,
|
||||
GWLP_USERDATA,
|
||||
PtrToUlong(this)
|
||||
);
|
||||
}
|
||||
|
||||
void Game::Run()
|
||||
{
|
||||
quit_ = false;
|
||||
|
||||
if (next_scene_)
|
||||
{
|
||||
next_scene_->OnEnter();
|
||||
curr_scene_ = next_scene_;
|
||||
next_scene_ = nullptr;
|
||||
}
|
||||
|
||||
::ShowWindow(window::instance.handle, SW_SHOWNORMAL);
|
||||
::UpdateWindow(window::instance.handle);
|
||||
|
||||
const int min_interval = 5;
|
||||
auto last = time::Now();
|
||||
MSG msg = { 0 };
|
||||
|
||||
while (!quit_)
|
||||
{
|
||||
auto now = time::Now();
|
||||
auto dur = now - last;
|
||||
|
||||
if (dur.Milliseconds() > min_interval)
|
||||
{
|
||||
float dt = (now - last).Seconds();
|
||||
last = now;
|
||||
|
||||
input::instance.Update(
|
||||
window::instance.handle,
|
||||
window::instance.xscale,
|
||||
window::instance.yscale
|
||||
);
|
||||
|
||||
OnUpdate(dt);
|
||||
UpdateScene(dt);
|
||||
DrawScene();
|
||||
|
||||
while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ID2D1HwndRenderTarget 开启了垂直同步,在渲染时会等待显示器刷新,
|
||||
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
|
||||
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
|
||||
int wait = min_interval - dur.Milliseconds();
|
||||
if (wait > 1)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::Quit()
|
||||
{
|
||||
quit_ = true;
|
||||
}
|
||||
|
||||
void Game::EnterScene(Scene * scene, Transition * transition)
|
||||
{
|
||||
if (scene == nullptr)
|
||||
{
|
||||
E2D_WARNING("Next scene is null pointer!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr_scene_ == scene) { return; }
|
||||
|
||||
if (next_scene_)
|
||||
{
|
||||
next_scene_->Release();
|
||||
}
|
||||
next_scene_ = scene;
|
||||
next_scene_->Retain();
|
||||
|
||||
if (transition)
|
||||
{
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Stop();
|
||||
transition_->Release();
|
||||
}
|
||||
transition_ = transition;
|
||||
transition_->Retain();
|
||||
|
||||
transition_->Initialize(curr_scene_, next_scene_, this);
|
||||
}
|
||||
}
|
||||
|
||||
Scene * Game::GetCurrentScene()
|
||||
{
|
||||
return curr_scene_;
|
||||
}
|
||||
|
||||
bool Game::IsTransitioning() const
|
||||
{
|
||||
return transition_ != nullptr;
|
||||
}
|
||||
|
||||
void Game::UpdateScene(float dt)
|
||||
{
|
||||
auto update = [&](Scene * scene) -> void
|
||||
{
|
||||
if (scene)
|
||||
{
|
||||
scene->OnUpdate(dt);
|
||||
Node * root = scene->GetRoot();
|
||||
if (root)
|
||||
{
|
||||
root->UpdateChildren(dt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
update(curr_scene_);
|
||||
update(next_scene_);
|
||||
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Update();
|
||||
|
||||
if (transition_->IsDone())
|
||||
{
|
||||
transition_->Release();
|
||||
transition_ = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (next_scene_)
|
||||
{
|
||||
if (curr_scene_)
|
||||
{
|
||||
curr_scene_->OnExit();
|
||||
curr_scene_->Release();
|
||||
}
|
||||
|
||||
next_scene_->OnEnter();
|
||||
|
||||
curr_scene_ = next_scene_;
|
||||
next_scene_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::DrawScene()
|
||||
{
|
||||
render::instance.BeginDraw(window::instance.handle);
|
||||
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Draw();
|
||||
}
|
||||
else if (curr_scene_)
|
||||
{
|
||||
curr_scene_->Draw();
|
||||
}
|
||||
|
||||
if (debug_mode_)
|
||||
{
|
||||
if (curr_scene_ && curr_scene_->GetRoot())
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.f);
|
||||
curr_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
if (next_scene_ && next_scene_->GetRoot())
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.f);
|
||||
next_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
|
||||
render::instance.DrawDebugInfo();
|
||||
}
|
||||
|
||||
render::instance.EndDraw();
|
||||
}
|
||||
|
||||
void Game::SetDebugMode(bool enabled)
|
||||
{
|
||||
debug_mode_ = enabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
class Scene;
|
||||
class Transition;
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
Game();
|
||||
|
||||
~Game();
|
||||
|
||||
// 更新时
|
||||
virtual void OnUpdate(float dt) {}
|
||||
|
||||
// 退出时
|
||||
virtual void OnExit() {}
|
||||
|
||||
// 窗口关闭时
|
||||
// 返回值:返回 false 将阻止窗口关闭
|
||||
virtual bool OnClose() { return true; }
|
||||
|
||||
// 初始化
|
||||
void Initialize(
|
||||
const window::Property& property /* 窗口属性 */
|
||||
);
|
||||
|
||||
// 运行
|
||||
void Run();
|
||||
|
||||
// 结束
|
||||
void Quit();
|
||||
|
||||
// 调试模式
|
||||
void SetDebugMode(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 切换场景
|
||||
void EnterScene(
|
||||
Scene * scene, /* 场景 */
|
||||
Transition * transition = nullptr /* 场景动画 */
|
||||
);
|
||||
|
||||
// 获取当前场景
|
||||
Scene * GetCurrentScene();
|
||||
|
||||
// 是否正在进行场景过渡
|
||||
bool IsTransitioning() const;
|
||||
|
||||
// 渲染场景画面
|
||||
void DrawScene();
|
||||
|
||||
// 更新场景
|
||||
void UpdateScene(
|
||||
float dt
|
||||
);
|
||||
|
||||
// 获取实例
|
||||
static Game * GetInstance();
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Game);
|
||||
|
||||
private:
|
||||
bool debug_mode_;
|
||||
bool quit_;
|
||||
Scene* curr_scene_;
|
||||
Scene* next_scene_;
|
||||
Transition* transition_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,13 +18,16 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "..\e2dtool.h"
|
||||
#include "Image.h"
|
||||
#include "render.h"
|
||||
#include "../utils/File.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
std::map<size_t, ID2D1Bitmap*> Image::bitmap_cache_;
|
||||
namespace
|
||||
{
|
||||
std::map<size_t, ID2D1Bitmap*> bitmap_cache_;
|
||||
}
|
||||
|
||||
Image::Image()
|
||||
: bitmap_(nullptr)
|
||||
|
|
@ -47,14 +50,14 @@ namespace easy2d
|
|||
this->Crop(crop_rect);
|
||||
}
|
||||
|
||||
Image::Image(const std::wstring & file_name)
|
||||
Image::Image(const String & file_name)
|
||||
: bitmap_(nullptr)
|
||||
, crop_rect_()
|
||||
{
|
||||
this->Load(file_name);
|
||||
}
|
||||
|
||||
Image::Image(const std::wstring & file_name, const Rect & crop_rect)
|
||||
Image::Image(const String & file_name, const Rect & crop_rect)
|
||||
: bitmap_(nullptr)
|
||||
, crop_rect_()
|
||||
{
|
||||
|
|
@ -79,7 +82,7 @@ namespace easy2d
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Image::Load(const std::wstring & file_name)
|
||||
bool Image::Load(const String & file_name)
|
||||
{
|
||||
E2D_WARNING_IF(file_name.empty(), "Image Load failed! Invalid file name.");
|
||||
|
||||
|
|
@ -92,7 +95,7 @@ namespace easy2d
|
|||
return false;
|
||||
}
|
||||
|
||||
this->SetBitmap(bitmap_cache_.at(std::hash<std::wstring>{}(file_name)));
|
||||
this->SetBitmap(bitmap_cache_.at(std::hash<String>{}(file_name)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -193,8 +196,8 @@ namespace easy2d
|
|||
HRESULT hr;
|
||||
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
IWICImagingFactory* imaging_factory = Device::GetGraphics()->GetImagingFactory();
|
||||
ID2D1HwndRenderTarget* render_target = Device::GetGraphics()->GetRenderTarget();
|
||||
IWICImagingFactory* imaging_factory = render::D2D.WICImagingFactory;
|
||||
ID2D1HwndRenderTarget* render_target = render::D2D.HwndRenderTarget;
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
|
|
@ -279,9 +282,9 @@ namespace easy2d
|
|||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool Image::CacheBitmap(const std::wstring & file_name)
|
||||
bool Image::CacheBitmap(const String & file_name)
|
||||
{
|
||||
size_t hash_code = std::hash<std::wstring>{}(file_name);
|
||||
size_t hash_code = std::hash<String>{}(file_name);
|
||||
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
|
||||
return true;
|
||||
|
||||
|
|
@ -291,11 +294,10 @@ namespace easy2d
|
|||
|
||||
// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
|
||||
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
|
||||
std::wstring image_file_path = image_file.GetPath();
|
||||
String image_file_path = image_file.GetPath();
|
||||
|
||||
Graphics* graphics_device = Device::GetGraphics();
|
||||
IWICImagingFactory* imaging_factory = graphics_device->GetImagingFactory();
|
||||
ID2D1HwndRenderTarget* render_target = graphics_device->GetRenderTarget();
|
||||
IWICImagingFactory* imaging_factory = render::D2D.WICImagingFactory;
|
||||
ID2D1HwndRenderTarget* render_target = render::D2D.HwndRenderTarget;
|
||||
IWICBitmapDecoder* decoder = nullptr;
|
||||
IWICBitmapFrameDecode* source = nullptr;
|
||||
IWICStream* stream = nullptr;
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "Resource.h"
|
||||
#include "RefCounter.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 图片
|
||||
class Image
|
||||
: public RefCounter
|
||||
{
|
||||
public:
|
||||
Image();
|
||||
|
||||
explicit Image(
|
||||
Resource& res
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
Resource& res,
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
const String& file_name,
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
virtual ~Image();
|
||||
|
||||
// 加载图片资源
|
||||
bool Load(
|
||||
Resource& res
|
||||
);
|
||||
|
||||
// 加载图片资源
|
||||
bool Load(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
// 将图片裁剪为矩形
|
||||
void Crop(
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
// 获取宽度
|
||||
float GetWidth() const;
|
||||
|
||||
// 获取高度
|
||||
float GetHeight() const;
|
||||
|
||||
// 获取大小
|
||||
Size GetSize() const;
|
||||
|
||||
// 获取源图片宽度
|
||||
float GetSourceWidth() const;
|
||||
|
||||
// 获取源图片高度
|
||||
float GetSourceHeight() const;
|
||||
|
||||
// 获取源图片大小
|
||||
Size GetSourceSize() const;
|
||||
|
||||
// 获取裁剪位置 X 坐标
|
||||
float GetCropX() const;
|
||||
|
||||
// 获取裁剪位置 Y 坐标
|
||||
float GetCropY() const;
|
||||
|
||||
// 获取裁剪位置
|
||||
Point GetCropPos() const;
|
||||
|
||||
// 获取裁剪矩形
|
||||
const Rect& GetCropRect() const;
|
||||
|
||||
// 获取 ID2D1Bitmap 对象
|
||||
ID2D1Bitmap * GetBitmap() const;
|
||||
|
||||
// 清空缓存
|
||||
static void ClearCache();
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Image);
|
||||
|
||||
// 缓存 Bitmap 资源
|
||||
static bool CacheBitmap(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
// 缓存 Bitmap 资源
|
||||
static bool CacheBitmap(
|
||||
Resource& res
|
||||
);
|
||||
|
||||
// 设置 Bitmap
|
||||
void SetBitmap(
|
||||
ID2D1Bitmap * bitmap
|
||||
);
|
||||
|
||||
private:
|
||||
Rect crop_rect_;
|
||||
ID2D1Bitmap* bitmap_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,58 +18,61 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
#include "input.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace
|
||||
namespace input
|
||||
{
|
||||
Graphics * graphics_device = nullptr;
|
||||
Input * input_device = nullptr;
|
||||
Audio * audio_device = nullptr;
|
||||
}
|
||||
InputDevice instance;
|
||||
|
||||
Graphics * Device::GetGraphics()
|
||||
{
|
||||
return graphics_device;
|
||||
}
|
||||
|
||||
Input * Device::GetInput()
|
||||
{
|
||||
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)
|
||||
InputDevice::InputDevice()
|
||||
{
|
||||
delete audio_device;
|
||||
audio_device = nullptr;
|
||||
ZeroMemory(keys_, sizeof(keys_));
|
||||
}
|
||||
|
||||
if (input_device)
|
||||
InputDevice::~InputDevice()
|
||||
{
|
||||
delete input_device;
|
||||
input_device = nullptr;
|
||||
}
|
||||
|
||||
if (graphics_device)
|
||||
void InputDevice::Update(HWND hwnd, float xscale, float yscale)
|
||||
{
|
||||
delete graphics_device;
|
||||
graphics_device = nullptr;
|
||||
::GetKeyboardState(keys_);
|
||||
|
||||
POINT client_cursor_pos;
|
||||
::GetCursorPos(&client_cursor_pos);
|
||||
::ScreenToClient(hwnd, &client_cursor_pos);
|
||||
|
||||
mouse_pos_ = Point(client_cursor_pos.x * xscale, client_cursor_pos.y * yscale);
|
||||
}
|
||||
|
||||
bool InputDevice::IsDown(KeyCode code)
|
||||
{
|
||||
if (keys_[static_cast<int>(code)] & 0x80)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDevice::IsDown(MouseCode code)
|
||||
{
|
||||
if (keys_[static_cast<int>(code)] & 0x80)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
float InputDevice::GetMouseX()
|
||||
{
|
||||
return mouse_pos_.x;
|
||||
}
|
||||
|
||||
float InputDevice::GetMouseY()
|
||||
{
|
||||
return mouse_pos_.y;
|
||||
}
|
||||
|
||||
Point InputDevice::GetMousePos()
|
||||
{
|
||||
return mouse_pos_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,52 +18,52 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Delay::Delay(float duration)
|
||||
: delta_(0)
|
||||
, delay_(std::max(duration, 0.f))
|
||||
namespace input
|
||||
{
|
||||
}
|
||||
|
||||
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_)
|
||||
// 输入设备
|
||||
class InputDevice
|
||||
{
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
public:
|
||||
InputDevice();
|
||||
|
||||
void Delay::ResetTime()
|
||||
{
|
||||
Action::ResetTime();
|
||||
started_ = Time::Now() - Duration::Second * delta_;
|
||||
~InputDevice();
|
||||
|
||||
// 检测键盘某按键是否正被按下
|
||||
bool IsDown(
|
||||
KeyCode code
|
||||
);
|
||||
|
||||
// 检测鼠标按键是否正被按下
|
||||
bool IsDown(
|
||||
MouseCode code
|
||||
);
|
||||
|
||||
// 获得鼠标X轴坐标值
|
||||
float GetMouseX();
|
||||
|
||||
// 获得鼠标Y轴坐标值
|
||||
float GetMouseY();
|
||||
|
||||
// 获得鼠标坐标值
|
||||
Point GetMousePos();
|
||||
|
||||
// 刷新设备状态
|
||||
void Update(
|
||||
HWND hwnd,
|
||||
float xscale,
|
||||
float yscale
|
||||
);
|
||||
|
||||
protected:
|
||||
BYTE keys_[256];
|
||||
Point mouse_pos_;
|
||||
};
|
||||
|
||||
extern InputDevice instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,26 +18,29 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#include "KeyEvent.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
OpacityTo::OpacityTo(float duration, float opacity)
|
||||
: OpacityBy(duration, 0)
|
||||
KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param)
|
||||
: message_(message)
|
||||
, w_param_(w_param)
|
||||
, l_param_(l_param)
|
||||
{
|
||||
end_val_ = opacity;
|
||||
}
|
||||
|
||||
OpacityTo * OpacityTo::Clone() const
|
||||
KeyCode KeyEvent::GetCode() const
|
||||
{
|
||||
return new OpacityTo(duration_, end_val_);
|
||||
return static_cast<KeyCode>(w_param_);
|
||||
}
|
||||
|
||||
void OpacityTo::Init()
|
||||
int KeyEvent::GetCount() const
|
||||
{
|
||||
OpacityBy::Init();
|
||||
delta_val_ = end_val_ - start_val_;
|
||||
return static_cast<int>((DWORD)l_param_ & 0x0000FFFF);
|
||||
}
|
||||
}
|
||||
|
||||
KeyEvent::Type KeyEvent::GetType() const
|
||||
{
|
||||
return Type(message_);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,45 +18,51 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include "BaseTypes.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
RotateBy::RotateBy(float duration, float rotation)
|
||||
: FiniteTimeAction(duration)
|
||||
// 按键消息
|
||||
class KeyEvent
|
||||
{
|
||||
delta_val_ = rotation;
|
||||
}
|
||||
|
||||
void RotateBy::Init()
|
||||
{
|
||||
FiniteTimeAction::Init();
|
||||
|
||||
if (target_)
|
||||
public:
|
||||
// 按键消息类型
|
||||
enum class Type : int
|
||||
{
|
||||
start_val_ = target_->GetRotation();
|
||||
}
|
||||
}
|
||||
Down = 0x0100, // 按下
|
||||
Up // 抬起
|
||||
};
|
||||
|
||||
void RotateBy::Update()
|
||||
public:
|
||||
explicit KeyEvent(
|
||||
UINT message,
|
||||
WPARAM w_param,
|
||||
LPARAM l_param
|
||||
);
|
||||
|
||||
// 获取事件类型
|
||||
KeyEvent::Type GetType() const;
|
||||
|
||||
// 获取按键键值
|
||||
KeyCode GetCode() const;
|
||||
|
||||
// 获取按键次数
|
||||
int GetCount() const;
|
||||
|
||||
protected:
|
||||
UINT message_;
|
||||
WPARAM w_param_;
|
||||
LPARAM l_param_;
|
||||
};
|
||||
|
||||
|
||||
// 按键消息处理接口
|
||||
class KeyEventHandler
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
|
||||
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_);
|
||||
}
|
||||
}
|
||||
public:
|
||||
// 处理按键消息
|
||||
virtual void Handle(KeyEvent e) = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2devent.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "MouseEvent.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -32,22 +32,19 @@ namespace easy2d
|
|||
|
||||
float MouseEvent::GetX() const
|
||||
{
|
||||
float dpi = Graphics::GetDpi();
|
||||
return ((float)(short)LOWORD(l_param_)) * 96.f / dpi;
|
||||
return ((float)(short)LOWORD(l_param_)) * window::instance.xscale;
|
||||
}
|
||||
|
||||
float MouseEvent::GetY() const
|
||||
{
|
||||
float dpi = Graphics::GetDpi();
|
||||
return ((float)(short)HIWORD(l_param_)) * 96.f / dpi;
|
||||
return ((float)(short)HIWORD(l_param_)) * window::instance.yscale;
|
||||
}
|
||||
|
||||
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
|
||||
((float)(short)LOWORD(l_param_)) * window::instance.xscale,
|
||||
((float)(short)HIWORD(l_param_)) * window::instance.yscale
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -18,48 +18,12 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_EVENT_H__
|
||||
#define __E2D_EVENT_H__
|
||||
|
||||
|
||||
#include "e2dutil.h"
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include "BaseTypes.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 按键消息
|
||||
class KeyEvent
|
||||
{
|
||||
public:
|
||||
// 按键消息类型
|
||||
enum class Type : int
|
||||
{
|
||||
Down = 0x0100, // 按下
|
||||
Up // 抬起
|
||||
};
|
||||
|
||||
public:
|
||||
explicit KeyEvent(
|
||||
UINT message,
|
||||
WPARAM w_param,
|
||||
LPARAM l_param
|
||||
);
|
||||
|
||||
// 获取事件类型
|
||||
KeyEvent::Type GetType() const;
|
||||
|
||||
// 获取按键键值
|
||||
KeyCode GetCode() const;
|
||||
|
||||
// 获取按键次数
|
||||
int GetCount() const;
|
||||
|
||||
protected:
|
||||
UINT message_;
|
||||
WPARAM w_param_;
|
||||
LPARAM l_param_;
|
||||
};
|
||||
|
||||
|
||||
// 報炎<E5A0B1>連
|
||||
class MouseEvent
|
||||
{
|
||||
|
|
@ -122,7 +86,12 @@ namespace easy2d
|
|||
LPARAM l_param_;
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_EVENT_H__
|
||||
// 鼠标消息处理接口
|
||||
class MouseEventHandler
|
||||
{
|
||||
public:
|
||||
// 处理鼠标消息
|
||||
virtual void Handle(MouseEvent e) = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,13 +18,14 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2devent.h"
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "Node.h"
|
||||
#include "Scene.h"
|
||||
#include "Task.h"
|
||||
#include "Action.h"
|
||||
#include "time.h"
|
||||
#include "render.h"
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Node::Node()
|
||||
|
|
@ -74,7 +75,7 @@ namespace easy2d
|
|||
if (!visible_)
|
||||
return;
|
||||
|
||||
auto render_target = Device::GetGraphics()->GetRenderTarget();
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
if (clip_enabled_)
|
||||
{
|
||||
render_target->SetTransform(final_matrix_);
|
||||
|
|
@ -175,12 +176,10 @@ namespace easy2d
|
|||
{
|
||||
if (border_)
|
||||
{
|
||||
auto graphics = Device::GetGraphics();
|
||||
auto brush = graphics->GetSolidBrush();
|
||||
brush->SetColor(D2D1_COLOR_F(border_color_));
|
||||
graphics->GetRenderTarget()->DrawGeometry(
|
||||
render::D2D.SolidColorBrush->SetColor(D2D1_COLOR_F(border_color_));
|
||||
render::D2D.HwndRenderTarget->DrawGeometry(
|
||||
border_,
|
||||
brush,
|
||||
render::D2D.SolidColorBrush,
|
||||
1.5f
|
||||
);
|
||||
}
|
||||
|
|
@ -222,7 +221,7 @@ namespace easy2d
|
|||
// 重新构造轮廓
|
||||
SafeRelease(border_);
|
||||
|
||||
ID2D1Factory * factory = Device::GetGraphics()->GetFactory();
|
||||
ID2D1Factory * factory = render::D2D.Factory;
|
||||
ID2D1RectangleGeometry * rectangle = nullptr;
|
||||
ID2D1TransformedGeometry * transformed = nullptr;
|
||||
ThrowIfFailed(
|
||||
|
|
@ -329,7 +328,7 @@ namespace easy2d
|
|||
return visible_;
|
||||
}
|
||||
|
||||
const std::wstring& Node::GetName() const
|
||||
const String& Node::GetName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
|
@ -409,7 +408,7 @@ namespace easy2d
|
|||
return transform_.rotation;
|
||||
}
|
||||
|
||||
const Transform & Node::GetTransform() const
|
||||
const math::Transform & Node::GetTransform() const
|
||||
{
|
||||
return transform_;
|
||||
}
|
||||
|
|
@ -585,7 +584,7 @@ namespace easy2d
|
|||
this->SetSize(size.width, size.height);
|
||||
}
|
||||
|
||||
void Node::SetTransform(const Transform & transform)
|
||||
void Node::SetTransform(const math::Transform & transform)
|
||||
{
|
||||
transform_ = transform;
|
||||
dirty_transform_ = true;
|
||||
|
|
@ -656,10 +655,10 @@ namespace easy2d
|
|||
return parent_scene_;
|
||||
}
|
||||
|
||||
Node::Nodes Node::GetChildren(const std::wstring& name) const
|
||||
Node::Nodes Node::GetChildren(const String& name) const
|
||||
{
|
||||
Nodes children;
|
||||
size_t hash_code = std::hash<std::wstring>{}(name);
|
||||
size_t hash_code = std::hash<String>{}(name);
|
||||
|
||||
for (const auto& child : children_)
|
||||
{
|
||||
|
|
@ -672,9 +671,9 @@ namespace easy2d
|
|||
return children;
|
||||
}
|
||||
|
||||
Node * Node::GetChild(const std::wstring& name) const
|
||||
Node * Node::GetChild(const String& name) const
|
||||
{
|
||||
size_t hash_code = std::hash<std::wstring>{}(name);
|
||||
size_t hash_code = std::hash<String>{}(name);
|
||||
|
||||
for (const auto& child : children_)
|
||||
{
|
||||
|
|
@ -734,14 +733,14 @@ namespace easy2d
|
|||
return false;
|
||||
}
|
||||
|
||||
void Node::RemoveChildren(const std::wstring& child_name)
|
||||
void Node::RemoveChildren(const String& child_name)
|
||||
{
|
||||
if (children_.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t hash_code = std::hash<std::wstring>{}(child_name);
|
||||
size_t hash_code = std::hash<String>{}(child_name);
|
||||
for (auto iter = children_.begin(); iter != children_.end();)
|
||||
{
|
||||
if ((*iter)->hash_name_ == hash_code && (*iter)->name_ == child_name)
|
||||
|
|
@ -795,7 +794,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Node::ResumeAction(const std::wstring& name)
|
||||
void Node::ResumeAction(const String& name)
|
||||
{
|
||||
if (actions_.empty())
|
||||
return;
|
||||
|
|
@ -809,7 +808,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Node::PauseAction(const std::wstring& name)
|
||||
void Node::PauseAction(const String& name)
|
||||
{
|
||||
if (actions_.empty())
|
||||
return;
|
||||
|
|
@ -823,7 +822,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Node::StopAction(const std::wstring& name)
|
||||
void Node::StopAction(const String& name)
|
||||
{
|
||||
if (actions_.empty())
|
||||
return;
|
||||
|
|
@ -923,13 +922,13 @@ namespace easy2d
|
|||
if (iter == tasks_.end())
|
||||
{
|
||||
task->Retain();
|
||||
task->last_time_ = Time::Now();
|
||||
task->last_time_ = time::Now();
|
||||
tasks_.push_back(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::StopTasks(const std::wstring& name)
|
||||
void Node::StopTasks(const String& name)
|
||||
{
|
||||
for (const auto& task : tasks_)
|
||||
{
|
||||
|
|
@ -940,7 +939,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Node::StartTasks(const std::wstring& name)
|
||||
void Node::StartTasks(const String& name)
|
||||
{
|
||||
for (const auto& task : tasks_)
|
||||
{
|
||||
|
|
@ -951,7 +950,7 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
void Node::RemoveTasks(const std::wstring& name)
|
||||
void Node::RemoveTasks(const String& name)
|
||||
{
|
||||
for (const auto& task : tasks_)
|
||||
{
|
||||
|
|
@ -1047,14 +1046,14 @@ namespace easy2d
|
|||
visible_ = value;
|
||||
}
|
||||
|
||||
void Node::SetName(const std::wstring& name)
|
||||
void Node::SetName(const String& name)
|
||||
{
|
||||
if (name_ != name)
|
||||
{
|
||||
// 保存节点名
|
||||
name_ = name;
|
||||
// 保存节点 Hash 名
|
||||
hash_name_ = std::hash<std::wstring>{}(name);
|
||||
hash_name_ = std::hash<String>{}(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,469 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "RefCounter.h"
|
||||
#include "../math/Transform.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
class Game;
|
||||
class Scene;
|
||||
class Action;
|
||||
class Task;
|
||||
|
||||
// 节点
|
||||
class Node
|
||||
: public RefCounter
|
||||
{
|
||||
friend class Game;
|
||||
friend class Scene;
|
||||
|
||||
public:
|
||||
typedef std::vector<Node*> Nodes;
|
||||
typedef std::vector<Action*> Actions;
|
||||
typedef std::vector<Task*> Tasks;
|
||||
|
||||
Node();
|
||||
|
||||
virtual ~Node();
|
||||
|
||||
// 渲染节点
|
||||
virtual void OnDraw() const {}
|
||||
|
||||
// 更新节点
|
||||
virtual void OnUpdate(float dt) {}
|
||||
|
||||
// 获取节点显示状态
|
||||
bool IsVisible() const;
|
||||
|
||||
// 获取节点名称
|
||||
const String& GetName() const;
|
||||
|
||||
// 获取节点名称的 Hash 值
|
||||
size_t GetHashName() const;
|
||||
|
||||
// 获取节点绘图顺序
|
||||
int GetOrder() const;
|
||||
|
||||
// 获取节点坐标
|
||||
const Point& GetPosition() const;
|
||||
|
||||
// 获取节点宽度
|
||||
float GetWidth() const;
|
||||
|
||||
// 获取节点高度
|
||||
float GetHeight() const;
|
||||
|
||||
// 获取节点宽度(不考虑缩放)
|
||||
float GetRealWidth() const;
|
||||
|
||||
// 获取节点高度(不考虑缩放)
|
||||
float GetRealHeight() const;
|
||||
|
||||
// 获取节点大小(不考虑缩放)
|
||||
const Size& GetRealSize() const;
|
||||
|
||||
// 获取节点的支点
|
||||
float GetPivotX() const;
|
||||
|
||||
// 获取节点的支点
|
||||
float GetPivotY() const;
|
||||
|
||||
// 获取节点大小
|
||||
Size GetSize() const;
|
||||
|
||||
// 获取节点横向缩放比例
|
||||
float GetScaleX() const;
|
||||
|
||||
// 获取节点纵向缩放比例
|
||||
float GetScaleY() const;
|
||||
|
||||
// 获取节点横向倾斜角度
|
||||
float GetSkewX() const;
|
||||
|
||||
// 获取节点纵向倾斜角度
|
||||
float GetSkewY() const;
|
||||
|
||||
// 获取节点旋转角度
|
||||
float GetRotation() const;
|
||||
|
||||
// 获取二维转换矩阵
|
||||
const math::Transform& GetTransform() const;
|
||||
|
||||
// 获取节点透明度
|
||||
float GetOpacity() const;
|
||||
|
||||
// 获取显示透明度
|
||||
float GetDisplayOpacity() const;
|
||||
|
||||
// 获取父节点
|
||||
Node * GetParent() const;
|
||||
|
||||
// 获取节点所在场景
|
||||
Scene * GetParentScene() const;
|
||||
|
||||
// 设置节点是否显示
|
||||
void SetVisible(
|
||||
bool value
|
||||
);
|
||||
|
||||
// 设置节点名称
|
||||
void SetName(
|
||||
const String& name
|
||||
);
|
||||
|
||||
// 设置节点横坐标
|
||||
virtual void SetPositionX(
|
||||
float x
|
||||
);
|
||||
|
||||
// 设置节点纵坐标
|
||||
virtual void SetPositionY(
|
||||
float y
|
||||
);
|
||||
|
||||
// 设置节点坐标
|
||||
virtual void SetPosition(
|
||||
const Point & point
|
||||
);
|
||||
|
||||
// 设置节点坐标
|
||||
virtual void SetPosition(
|
||||
float x,
|
||||
float y
|
||||
);
|
||||
|
||||
// 移动节点
|
||||
virtual void MoveBy(
|
||||
float x,
|
||||
float y
|
||||
);
|
||||
|
||||
// 移动节点
|
||||
virtual void MoveBy(
|
||||
const Point & vector
|
||||
);
|
||||
|
||||
// 设置节点绘图顺序
|
||||
// 默认为 0
|
||||
virtual void SetOrder(
|
||||
int order
|
||||
);
|
||||
|
||||
// 设置横向缩放比例
|
||||
// 默认为 1.0
|
||||
virtual void SetScaleX(
|
||||
float scale_x
|
||||
);
|
||||
|
||||
// 设置纵向缩放比例
|
||||
// 默认为 1.0
|
||||
virtual void SetScaleY(
|
||||
float scale_y
|
||||
);
|
||||
|
||||
// 设置缩放比例
|
||||
// 默认为 (1.0, 1.0)
|
||||
virtual void SetScale(
|
||||
float scale_x,
|
||||
float scale_y
|
||||
);
|
||||
|
||||
// 设置缩放比例
|
||||
// 默认为 1.0
|
||||
virtual void SetScale(
|
||||
float scale
|
||||
);
|
||||
|
||||
// 设置横向倾斜角度
|
||||
// 默认为 0
|
||||
virtual void SetSkewX(
|
||||
float skew_x
|
||||
);
|
||||
|
||||
// 设置纵向倾斜角度
|
||||
// 默认为 0
|
||||
virtual void SetSkewY(
|
||||
float skew_y
|
||||
);
|
||||
|
||||
// 设置倾斜角度
|
||||
// 默认为 (0, 0)
|
||||
virtual void SetSkew(
|
||||
float skew_x,
|
||||
float skew_y
|
||||
);
|
||||
|
||||
// 设置旋转角度
|
||||
// 默认为 0
|
||||
virtual void SetRotation(
|
||||
float rotation
|
||||
);
|
||||
|
||||
// 设置透明度
|
||||
// 默认为 1.0, 范围 [0, 1]
|
||||
virtual void SetOpacity(
|
||||
float opacity
|
||||
);
|
||||
|
||||
// 设置支点的横向位置
|
||||
// 默认为 0, 范围 [0, 1]
|
||||
virtual void SetPivotX(
|
||||
float pivot_x
|
||||
);
|
||||
|
||||
// 设置支点的纵向位置
|
||||
// 默认为 0, 范围 [0, 1]
|
||||
virtual void SetPivotY(
|
||||
float pivot_y
|
||||
);
|
||||
|
||||
// 设置支点位置
|
||||
// 默认为 (0, 0), 范围 [0, 1]
|
||||
virtual void SetPivot(
|
||||
float pivot_x,
|
||||
float pivot_y
|
||||
);
|
||||
|
||||
// 修改节点宽度
|
||||
virtual void SetWidth(
|
||||
float width
|
||||
);
|
||||
|
||||
// 修改节点高度
|
||||
virtual void SetHeight(
|
||||
float height
|
||||
);
|
||||
|
||||
// 修改节点大小
|
||||
virtual void SetSize(
|
||||
float width,
|
||||
float height
|
||||
);
|
||||
|
||||
// 修改节点大小
|
||||
virtual void SetSize(
|
||||
const Size & size
|
||||
);
|
||||
|
||||
// 设置二维转换
|
||||
virtual void SetTransform(
|
||||
const math::Transform& transform
|
||||
);
|
||||
|
||||
// 启用或关闭渲染区域裁剪
|
||||
virtual void SetClipEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 设置节点边缘颜色
|
||||
virtual void SetBorderColor(
|
||||
const Color& color
|
||||
);
|
||||
|
||||
// 判断点是否在节点内
|
||||
bool ContainsPoint(
|
||||
const Point& point
|
||||
);
|
||||
|
||||
// 判断两物体是否相交
|
||||
bool Intersects(
|
||||
Node * node
|
||||
);
|
||||
|
||||
// 添加子节点
|
||||
void AddChild(
|
||||
Node * child,
|
||||
int order = 0 /* 渲染顺序 */
|
||||
);
|
||||
|
||||
// 添加多个子节点
|
||||
void AddChild(
|
||||
const Nodes& nodes, /* 节点数组 */
|
||||
int order = 0 /* 渲染顺序 */
|
||||
);
|
||||
|
||||
// 获取所有名称相同的子节点
|
||||
Nodes GetChildren(
|
||||
const String& name
|
||||
) const;
|
||||
|
||||
// 获取名称相同的子节点
|
||||
Node* GetChild(
|
||||
const String& name
|
||||
) const;
|
||||
|
||||
// 获取所有子节点
|
||||
const Nodes& GetAllChildren() const;
|
||||
|
||||
// 获取子节点数量
|
||||
int GetChildrenCount() const;
|
||||
|
||||
// 移除子节点
|
||||
bool RemoveChild(
|
||||
Node * child
|
||||
);
|
||||
|
||||
// 移除所有名称相同的子节点
|
||||
void RemoveChildren(
|
||||
const String& child_name
|
||||
);
|
||||
|
||||
// 移除所有节点
|
||||
void RemoveAllChildren();
|
||||
|
||||
// 从父节点移除
|
||||
void RemoveFromParent();
|
||||
|
||||
// 执行动作
|
||||
void RunAction(
|
||||
Action * action
|
||||
);
|
||||
|
||||
// 继续动作
|
||||
void ResumeAction(
|
||||
const String& name
|
||||
);
|
||||
|
||||
// 暂停动作
|
||||
void PauseAction(
|
||||
const String& name
|
||||
);
|
||||
|
||||
// 停止动作
|
||||
void StopAction(
|
||||
const String& name
|
||||
);
|
||||
|
||||
// 继续所有暂停动作
|
||||
void ResumeAllActions();
|
||||
|
||||
// 暂停所有动作
|
||||
void PauseAllActions();
|
||||
|
||||
// 停止所有动作
|
||||
void StopAllActions();
|
||||
|
||||
// 获取所有动作
|
||||
const Actions& GetAllActions() const;
|
||||
|
||||
// 添加任务
|
||||
void AddTask(
|
||||
Task * task
|
||||
);
|
||||
|
||||
// 启动任务
|
||||
void StartTasks(
|
||||
const String& task_name
|
||||
);
|
||||
|
||||
// 停止任务
|
||||
void StopTasks(
|
||||
const String& task_name
|
||||
);
|
||||
|
||||
// 移除任务
|
||||
void RemoveTasks(
|
||||
const String& task_name
|
||||
);
|
||||
|
||||
// 启动所有任务
|
||||
void StartAllTasks();
|
||||
|
||||
// 停止所有任务
|
||||
void StopAllTasks();
|
||||
|
||||
// 移除所有任务
|
||||
void RemoveAllTasks();
|
||||
|
||||
// 获取所有任务
|
||||
const Tasks& GetAllTasks() const;
|
||||
|
||||
protected:
|
||||
// 遍历节点
|
||||
virtual void Visit();
|
||||
|
||||
// 分发鼠标消息
|
||||
virtual bool Dispatch(
|
||||
const MouseEvent& e,
|
||||
bool handled
|
||||
);
|
||||
|
||||
// 分发按键消息
|
||||
virtual bool Dispatch(
|
||||
const KeyEvent& e,
|
||||
bool handled
|
||||
);
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Node);
|
||||
|
||||
// 渲染节点边缘
|
||||
void DrawBorder();
|
||||
|
||||
// 设置节点所在场景
|
||||
void SetParentScene(
|
||||
Scene * scene
|
||||
);
|
||||
|
||||
// 更新子节点
|
||||
void UpdateChildren(float dt);
|
||||
|
||||
// 更新转换矩阵
|
||||
void UpdateTransform();
|
||||
|
||||
// 更新节点透明度
|
||||
void UpdateOpacity();
|
||||
|
||||
// 更新动作
|
||||
void UpdateActions();
|
||||
|
||||
// 更新任务
|
||||
void UpdateTasks();
|
||||
|
||||
// 更新节点时间
|
||||
void UpdateTime();
|
||||
|
||||
private:
|
||||
String name_;
|
||||
size_t hash_name_;
|
||||
math::Transform transform_;
|
||||
float display_opacity_;
|
||||
float real_opacity_;
|
||||
int order_;
|
||||
bool visible_;
|
||||
bool clip_enabled_;
|
||||
bool dirty_sort_;
|
||||
bool dirty_transform_;
|
||||
Scene* parent_scene_;
|
||||
Node* parent_;
|
||||
Color border_color_;
|
||||
Actions actions_;
|
||||
Tasks tasks_;
|
||||
Nodes children_;
|
||||
ID2D1Geometry* border_;
|
||||
D2D1::Matrix3x2F initial_matrix_;
|
||||
D2D1::Matrix3x2F final_matrix_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "BaseTypes.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 矩形
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维矩形: Rect rect = Rect(10, 20, 30, 40); // 左上角坐标为 (10, 20), 宽为 30, 高为 40
|
||||
// 矩形可以通过 Point + Size 定义, Point 表示矩形左上角坐标, Size 表示矩形宽高
|
||||
// 判断一个点是否在矩形内: bool contains = rect.ContainsPoint(p);
|
||||
// 判断两矩形是否相交: bool intersects = rect1.Intersects(rect2);
|
||||
//
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
Point origin; // 左上角坐标
|
||||
Size size; // 宽度和高度
|
||||
|
||||
public:
|
||||
Rect() {}
|
||||
|
||||
Rect(
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height
|
||||
)
|
||||
: origin(x, y)
|
||||
, size(width, height)
|
||||
{}
|
||||
|
||||
Rect(
|
||||
const Point& pos,
|
||||
const Size& size
|
||||
)
|
||||
: origin(pos.x, pos.y)
|
||||
, size(size.width, size.height)
|
||||
{}
|
||||
|
||||
Rect(
|
||||
const Rect& other
|
||||
)
|
||||
: origin(other.origin.x, other.origin.y)
|
||||
, size(other.size.width, other.size.height)
|
||||
{}
|
||||
|
||||
Rect& operator= (const Rect& other)
|
||||
{
|
||||
origin = other.origin;
|
||||
size = other.size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator== (const Rect& rect) const
|
||||
{
|
||||
return (origin == rect.origin) && (size == rect.size);
|
||||
}
|
||||
|
||||
// 判断点是否在矩形内
|
||||
inline bool ContainsPoint(
|
||||
const Point& point
|
||||
) const
|
||||
{
|
||||
return point.x >= origin.x && point.x <= (origin.y + size.height) &&
|
||||
point.y >= origin.y && point.y <= (origin.y + size.height);
|
||||
}
|
||||
|
||||
// 判断两矩形是否相交
|
||||
inline bool 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -18,28 +18,27 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "RefCounter.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Ref::Ref()
|
||||
RefCounter::RefCounter()
|
||||
{
|
||||
// 当对象被创建时,意味着它已经被引用了一次
|
||||
ref_count_ = 1;
|
||||
ref_count_ = 0;
|
||||
}
|
||||
|
||||
Ref::~Ref()
|
||||
RefCounter::~RefCounter()
|
||||
{
|
||||
}
|
||||
|
||||
LONG Ref::Retain()
|
||||
long RefCounter::Retain()
|
||||
{
|
||||
return ::InterlockedIncrement(&ref_count_);
|
||||
}
|
||||
|
||||
LONG Ref::Release()
|
||||
long RefCounter::Release()
|
||||
{
|
||||
LONG new_count = ::InterlockedDecrement(&ref_count_);
|
||||
long new_count = ::InterlockedDecrement(&ref_count_);
|
||||
|
||||
if (new_count <= 0)
|
||||
{
|
||||
|
|
@ -50,7 +49,7 @@ namespace easy2d
|
|||
return new_count;
|
||||
}
|
||||
|
||||
LONG Ref::GetRefCount() const
|
||||
long RefCounter::GetRefCount() const
|
||||
{
|
||||
return ref_count_;
|
||||
}
|
||||
|
|
@ -18,14 +18,29 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
std::default_random_engine &Random::GetEngine()
|
||||
// 引用计数
|
||||
class RefCounter
|
||||
{
|
||||
static std::random_device device;
|
||||
static std::default_random_engine engine(device());
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
public:
|
||||
RefCounter();
|
||||
|
||||
virtual ~RefCounter();
|
||||
|
||||
// 增加引用计数
|
||||
long Retain();
|
||||
|
||||
// 减少引用计数
|
||||
long Release();
|
||||
|
||||
// 获取引用计数
|
||||
long GetRefCount() const;
|
||||
|
||||
private:
|
||||
long ref_count_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtool.h"
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 资源
|
||||
//
|
||||
// Usage:
|
||||
// Resource 用于获取可执行文件 (exe) 中的资源, 必须在构造函数中指定它的
|
||||
// 资源类型和名称标识符。
|
||||
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1, 那么可以这样指定该资源:
|
||||
// Resource res(MAKEINTRESOURCE(IDR_WAVE_1), L"WAVE");
|
||||
// 如果需要手动加载这份资源, 可以通过 Load 方法获取资源内容
|
||||
// if (res.Load()) {
|
||||
// LPVOID data = res.GetData();
|
||||
// DWORD size = res.GetDataSize();
|
||||
// }
|
||||
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
|
||||
//
|
||||
class Resource
|
||||
{
|
||||
public:
|
||||
Resource(
|
||||
LPCWSTR name, /* 资源名称 */
|
||||
LPCWSTR type /* 资源类型 */
|
||||
);
|
||||
|
||||
bool Load();
|
||||
|
||||
LPCWSTR GetName() const;
|
||||
|
||||
LPCWSTR GetType() const;
|
||||
|
||||
LPVOID GetData() const;
|
||||
|
||||
DWORD GetDataSize() const;
|
||||
|
||||
size_t GetHashCode() const;
|
||||
|
||||
private:
|
||||
bool loaded_;
|
||||
LPCWSTR name_;
|
||||
LPCWSTR type_;
|
||||
LPVOID data_;
|
||||
DWORD data_size_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
#include "..\e2dobject.h"
|
||||
#include "Scene.h"
|
||||
#include "Node.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -120,4 +120,4 @@ namespace easy2d
|
|||
{
|
||||
return transform_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,54 +18,72 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#pragma once
|
||||
#include "RefCounter.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
ScaleBy::ScaleBy(float duration, float scale)
|
||||
: FiniteTimeAction(duration)
|
||||
class Node;
|
||||
|
||||
// 场景
|
||||
class Scene
|
||||
: public RefCounter
|
||||
{
|
||||
delta_x_ = scale;
|
||||
delta_y_ = scale;
|
||||
}
|
||||
public:
|
||||
Scene();
|
||||
|
||||
ScaleBy::ScaleBy(float duration, float scale_x, float scale_y)
|
||||
: FiniteTimeAction(duration)
|
||||
{
|
||||
delta_x_ = scale_x;
|
||||
delta_y_ = scale_y;
|
||||
}
|
||||
explicit Scene(
|
||||
Node * root
|
||||
);
|
||||
|
||||
void ScaleBy::Init()
|
||||
{
|
||||
FiniteTimeAction::Init();
|
||||
virtual ~Scene();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
start_scale_x_ = target_->GetScaleX();
|
||||
start_scale_y_ = target_->GetScaleY();
|
||||
}
|
||||
}
|
||||
// 进入场景
|
||||
virtual void OnEnter() {}
|
||||
|
||||
void ScaleBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
// 退出场景
|
||||
virtual void OnExit() {}
|
||||
|
||||
if (target_)
|
||||
{
|
||||
target_->SetScale(start_scale_x_ + delta_x_ * delta_, start_scale_y_ + delta_y_ * delta_);
|
||||
}
|
||||
}
|
||||
// 更新场景
|
||||
virtual void OnUpdate(float dt) {}
|
||||
|
||||
ScaleBy * ScaleBy::Clone() const
|
||||
{
|
||||
return new ScaleBy(duration_, delta_x_, delta_y_);
|
||||
}
|
||||
// 设置根节点
|
||||
void SetRoot(
|
||||
Node * root
|
||||
);
|
||||
|
||||
ScaleBy * ScaleBy::Reverse() const
|
||||
{
|
||||
return new ScaleBy(duration_, -delta_x_, -delta_y_);
|
||||
}
|
||||
}
|
||||
// 获取根节点
|
||||
Node* GetRoot() const;
|
||||
|
||||
// 渲染场景
|
||||
void Draw();
|
||||
|
||||
// 分发鼠标消息
|
||||
virtual void Dispatch(
|
||||
const MouseEvent& e
|
||||
);
|
||||
|
||||
// 分发按键消息
|
||||
virtual void Dispatch(
|
||||
const KeyEvent& e
|
||||
);
|
||||
|
||||
// 设置转换矩阵
|
||||
void SetTransform(
|
||||
const D2D1::Matrix3x2F& matrix
|
||||
);
|
||||
|
||||
// 获取转换矩阵
|
||||
const D2D1::Matrix3x2F& GetTransform() const;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Scene);
|
||||
|
||||
private:
|
||||
Node* root_;
|
||||
D2D1::Matrix3x2F transform_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
#include "Size.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -60,11 +60,6 @@ namespace easy2d
|
|||
return Size(width / value, height / value);
|
||||
}
|
||||
|
||||
Size::operator Point() const
|
||||
{
|
||||
return Point(width, height);
|
||||
}
|
||||
|
||||
Size Size::operator-() const
|
||||
{
|
||||
return Size(-width, -height);
|
||||
|
|
@ -74,4 +69,4 @@ namespace easy2d
|
|||
{
|
||||
return (width == other.width) && (height == other.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,45 +18,39 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
OpacityBy::OpacityBy(float duration, float opacity)
|
||||
: FiniteTimeAction(duration)
|
||||
// 大小
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维矩形区域的大小: Size s(10, 5); // 宽为 10, 高为 5
|
||||
// 大小可以相加减: Size s = Size(10, 10) + Size(20, 20); // s 的大小是宽高均为 30
|
||||
//
|
||||
class Size
|
||||
{
|
||||
delta_val_ = opacity;
|
||||
}
|
||||
public:
|
||||
float width; // 宽度
|
||||
float height; // 高度
|
||||
|
||||
void OpacityBy::Init()
|
||||
{
|
||||
FiniteTimeAction::Init();
|
||||
public:
|
||||
Size();
|
||||
|
||||
if (target_)
|
||||
{
|
||||
start_val_ = target_->GetOpacity();
|
||||
}
|
||||
}
|
||||
Size(
|
||||
float width,
|
||||
float height
|
||||
);
|
||||
|
||||
void OpacityBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
Size(
|
||||
const Size& other
|
||||
);
|
||||
|
||||
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_);
|
||||
}
|
||||
}
|
||||
Size operator + (const Size & other) const;
|
||||
Size operator - (const Size & other) const;
|
||||
Size operator * (float value) const;
|
||||
Size operator / (float value) const;
|
||||
Size operator - () const;
|
||||
bool operator== (const Size& other) const;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,8 +18,9 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "Sprite.h"
|
||||
#include "render.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -47,13 +48,13 @@ namespace easy2d
|
|||
Crop(crop_rect);
|
||||
}
|
||||
|
||||
Sprite::Sprite(const std::wstring & file_name)
|
||||
Sprite::Sprite(const String & file_name)
|
||||
: image_(nullptr)
|
||||
{
|
||||
Load(file_name);
|
||||
}
|
||||
|
||||
Sprite::Sprite(const std::wstring & file_name, const Rect & crop_rect)
|
||||
Sprite::Sprite(const String & file_name, const Rect & crop_rect)
|
||||
: image_(nullptr)
|
||||
{
|
||||
Load(file_name);
|
||||
|
|
@ -99,7 +100,7 @@ namespace easy2d
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Sprite::Load(const std::wstring & file_name)
|
||||
bool Sprite::Load(const String & file_name)
|
||||
{
|
||||
if (!image_)
|
||||
{
|
||||
|
|
@ -134,7 +135,7 @@ namespace easy2d
|
|||
if (image_ && image_->GetBitmap())
|
||||
{
|
||||
auto crop_pos = image_->GetCropPos();
|
||||
Device::GetGraphics()->GetRenderTarget()->DrawBitmap(
|
||||
render::D2D.HwndRenderTarget->DrawBitmap(
|
||||
image_->GetBitmap(),
|
||||
D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height),
|
||||
GetDisplayOpacity(),
|
||||
|
|
@ -18,53 +18,73 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
#pragma once
|
||||
#include "Node.h"
|
||||
#include "Image.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Audio::Audio()
|
||||
: x_audio2_(nullptr)
|
||||
, mastering_voice_(nullptr)
|
||||
// 精灵
|
||||
class Sprite
|
||||
: public Node
|
||||
{
|
||||
ThrowIfFailed(
|
||||
MFStartup(MF_VERSION)
|
||||
public:
|
||||
Sprite();
|
||||
|
||||
explicit Sprite(
|
||||
Image * image
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
XAudio2Create(&x_audio2_)
|
||||
explicit Sprite(
|
||||
Resource& res
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
x_audio2_->CreateMasteringVoice(&mastering_voice_)
|
||||
explicit Sprite(
|
||||
Resource& res,
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
}
|
||||
|
||||
Audio::~Audio()
|
||||
{
|
||||
if (mastering_voice_)
|
||||
{
|
||||
mastering_voice_->DestroyVoice();
|
||||
mastering_voice_ = nullptr;
|
||||
}
|
||||
explicit Sprite(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
SafeRelease(x_audio2_);
|
||||
explicit Sprite(
|
||||
const String& file_name,
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
MFShutdown();
|
||||
}
|
||||
virtual ~Sprite();
|
||||
|
||||
HRESULT Audio::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx)
|
||||
{
|
||||
return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
}
|
||||
// 加载图片文件
|
||||
bool Load(
|
||||
Resource& res
|
||||
);
|
||||
|
||||
void Audio::Open()
|
||||
{
|
||||
x_audio2_->StartEngine();
|
||||
}
|
||||
// 加载图片文件
|
||||
bool Load(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
void Audio::Close()
|
||||
{
|
||||
x_audio2_->StopEngine();
|
||||
}
|
||||
}
|
||||
// 加载图片
|
||||
bool Load(
|
||||
Image * image
|
||||
);
|
||||
|
||||
// 将图片裁剪为矩形
|
||||
void Crop(
|
||||
const Rect& crop_rect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
// 获取 Image 对象
|
||||
Image * GetImage() const;
|
||||
|
||||
// 渲染精灵
|
||||
virtual void OnDraw() const override;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Sprite);
|
||||
|
||||
private:
|
||||
Image* image_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,12 +18,11 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#include "Task.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Task::Task(const Callback & func, const std::wstring & name)
|
||||
Task::Task(const Callback & func, const String & name)
|
||||
: running_(true)
|
||||
, stopped_(false)
|
||||
, run_times_(0)
|
||||
|
|
@ -34,11 +33,11 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
Task::Task(const Callback & func, float delay, int times, const std::wstring & name)
|
||||
Task::Task(const Callback & func, float delay, int times, const String & name)
|
||||
: running_(true)
|
||||
, stopped_(false)
|
||||
, run_times_(0)
|
||||
, delay_(Duration::Second * std::max(delay, 0.f))
|
||||
, delay_(time::Second * std::max(delay, 0.f))
|
||||
, total_times_(times)
|
||||
, callback_(func)
|
||||
, name_(name)
|
||||
|
|
@ -48,7 +47,7 @@ namespace easy2d
|
|||
void Task::Start()
|
||||
{
|
||||
running_ = true;
|
||||
last_time_ = Time::Now();
|
||||
last_time_ = time::Now();
|
||||
}
|
||||
|
||||
void Task::Stop()
|
||||
|
|
@ -81,7 +80,7 @@ namespace easy2d
|
|||
|
||||
void Task::ResetTime()
|
||||
{
|
||||
last_time_ = Time::Now();
|
||||
last_time_ = time::Now();
|
||||
}
|
||||
|
||||
bool Task::IsReady() const
|
||||
|
|
@ -92,7 +91,7 @@ namespace easy2d
|
|||
{
|
||||
return true;
|
||||
}
|
||||
if (Time::Now() - last_time_ >= delay_)
|
||||
if (time::Now() - last_time_ >= delay_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -105,7 +104,7 @@ namespace easy2d
|
|||
return running_;
|
||||
}
|
||||
|
||||
const std::wstring& Task::GetName() const
|
||||
const String& Task::GetName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "time.h"
|
||||
#include "RefCounter.h"
|
||||
#include <functional>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
class Node;
|
||||
|
||||
// 定时任务
|
||||
class Task
|
||||
: public RefCounter
|
||||
{
|
||||
friend class Node;
|
||||
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
public:
|
||||
explicit Task(
|
||||
const Callback& func, /* 执行函数 */
|
||||
const String& name = L"" /* 任务名称 */
|
||||
);
|
||||
|
||||
explicit Task(
|
||||
const Callback& func, /* 执行函数 */
|
||||
float delay, /* 时间间隔(秒) */
|
||||
int times = -1, /* 执行次数(设 -1 为永久执行) */
|
||||
const String& name = L"" /* 任务名称 */
|
||||
);
|
||||
|
||||
// 启动任务
|
||||
void Start();
|
||||
|
||||
// 停止任务
|
||||
void Stop();
|
||||
|
||||
// 任务是否正在执行
|
||||
bool IsRunning() const;
|
||||
|
||||
// 获取任务名称
|
||||
const String& GetName() const;
|
||||
|
||||
// 任务是否就绪
|
||||
bool IsReady() const;
|
||||
|
||||
// 执行任务
|
||||
void Update();
|
||||
|
||||
// 重置计时
|
||||
void ResetTime();
|
||||
|
||||
private:
|
||||
bool running_;
|
||||
bool stopped_;
|
||||
int run_times_;
|
||||
int total_times_;
|
||||
String name_;
|
||||
time::Duration delay_;
|
||||
time::TimePoint last_time_;
|
||||
Callback callback_;
|
||||
Node * target_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,9 +18,9 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
#include "Text.h"
|
||||
#include "render.h"
|
||||
#include "base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
|
@ -82,7 +82,7 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
Text::Text(const std::wstring & text, const Font & font, const Style & style)
|
||||
Text::Text(const String & text, const Font & font, const Style & style)
|
||||
: font_(font)
|
||||
, style_(style)
|
||||
, text_layout_(nullptr)
|
||||
|
|
@ -98,7 +98,7 @@ namespace easy2d
|
|||
SafeRelease(text_layout_);
|
||||
}
|
||||
|
||||
const std::wstring& Text::GetText() const
|
||||
const String& Text::GetText() const
|
||||
{
|
||||
return text_;
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@ namespace easy2d
|
|||
return style_;
|
||||
}
|
||||
|
||||
const std::wstring& Text::GetFontFamily() const
|
||||
const String& Text::GetFontFamily() const
|
||||
{
|
||||
return font_.family;
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ namespace easy2d
|
|||
return style_.outline;
|
||||
}
|
||||
|
||||
void Text::SetText(const std::wstring& text)
|
||||
void Text::SetText(const String& text)
|
||||
{
|
||||
text_ = text;
|
||||
Reset();
|
||||
|
|
@ -200,7 +200,7 @@ namespace easy2d
|
|||
Reset();
|
||||
}
|
||||
|
||||
void Text::SetFontFamily(const std::wstring& family)
|
||||
void Text::SetFontFamily(const String& family)
|
||||
{
|
||||
font_.family = family;
|
||||
Reset();
|
||||
|
|
@ -315,21 +315,19 @@ namespace easy2d
|
|||
{
|
||||
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());
|
||||
render::D2D.SolidColorBrush->SetOpacity(GetDisplayOpacity());
|
||||
// 获取文本渲染器
|
||||
auto text_renderer = graphics->GetTextRender();
|
||||
graphics->SetTextRendererStyle(
|
||||
render::D2D.TextRenderer->SetTextStyle(
|
||||
style_.color,
|
||||
style_.outline,
|
||||
style_.outline_color,
|
||||
style_.outline_width,
|
||||
style_.outline_stroke
|
||||
static_cast<D2D1_LINE_JOIN>(style_.outline_stroke)
|
||||
);
|
||||
text_layout_->Draw(nullptr, text_renderer, 0, 0);
|
||||
text_layout_->Draw(nullptr, render::D2D.TextRenderer, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +344,7 @@ namespace easy2d
|
|||
SafeRelease(text_format_);
|
||||
|
||||
ThrowIfFailed(
|
||||
Device::GetGraphics()->GetWriteFactory()->CreateTextFormat(
|
||||
render::D2D.DWriteFactory->CreateTextFormat(
|
||||
font_.family.c_str(),
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT(font_.weight),
|
||||
|
|
@ -404,13 +402,12 @@ namespace easy2d
|
|||
}
|
||||
|
||||
UINT32 length = static_cast<UINT32>(text_.size());
|
||||
auto writeFactory = Device::GetGraphics()->GetWriteFactory();
|
||||
|
||||
// 对文本自动换行情况下进行处理
|
||||
if (style_.wrap)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
writeFactory->CreateTextLayout(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
text_format_,
|
||||
|
|
@ -429,7 +426,7 @@ namespace easy2d
|
|||
{
|
||||
// 为防止文本对齐问题,根据先创建 layout 以获取宽度
|
||||
ThrowIfFailed(
|
||||
writeFactory->CreateTextLayout(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
text_format_,
|
||||
|
|
@ -448,7 +445,7 @@ namespace easy2d
|
|||
// 重新创建 layout
|
||||
SafeRelease(text_layout_);
|
||||
ThrowIfFailed(
|
||||
writeFactory->CreateTextLayout(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
text_.c_str(),
|
||||
length,
|
||||
text_format_,
|
||||
|
|
@ -460,14 +457,14 @@ namespace easy2d
|
|||
}
|
||||
|
||||
// 添加下划线和删除线
|
||||
DWRITE_TEXT_RANGE Range = { 0, length };
|
||||
DWRITE_TEXT_RANGE range = { 0, length };
|
||||
if (style_.underline)
|
||||
{
|
||||
text_layout_->SetUnderline(true, Range);
|
||||
text_layout_->SetUnderline(true, range);
|
||||
}
|
||||
if (style_.strikethrough)
|
||||
{
|
||||
text_layout_->SetStrikethrough(true, Range);
|
||||
text_layout_->SetStrikethrough(true, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Node.h"
|
||||
#include "Font.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 文本
|
||||
class Text
|
||||
: public Node
|
||||
{
|
||||
public:
|
||||
// 文本对齐方式
|
||||
enum class Align
|
||||
{
|
||||
Left, /* 左对齐 */
|
||||
Right, /* 右对齐 */
|
||||
Center /* 居中对齐 */
|
||||
};
|
||||
|
||||
// 文本样式
|
||||
class Style
|
||||
{
|
||||
public:
|
||||
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; // 描边线相交样式
|
||||
|
||||
public:
|
||||
Style();
|
||||
|
||||
Style(
|
||||
Color color,
|
||||
Align alignment = Align::Left,
|
||||
bool wrap = false,
|
||||
float wrap_width = 0.f,
|
||||
float line_spacing = 0.f,
|
||||
bool underline = false,
|
||||
bool strikethrough = false,
|
||||
bool outline = true,
|
||||
Color outline_color = Color(Color::Black, 0.5),
|
||||
float outline_width = 1.f,
|
||||
Stroke outline_stroke = Stroke::Round
|
||||
);
|
||||
};
|
||||
|
||||
public:
|
||||
Text();
|
||||
|
||||
explicit Text(
|
||||
const String& text, /* 文字内容 */
|
||||
const Font& font = Font(), /* 字体 */
|
||||
const Style& style = Style() /* 文本样式 */
|
||||
);
|
||||
|
||||
virtual ~Text();
|
||||
|
||||
// 获取文本
|
||||
const String& GetText() const;
|
||||
|
||||
// 获取字体
|
||||
const Font& GetFont() const;
|
||||
|
||||
// 获取文本样式
|
||||
const Style& GetStyle() const;
|
||||
|
||||
// 获取字体族
|
||||
const String& GetFontFamily() const;
|
||||
|
||||
// 获取当前字号
|
||||
float GetFontSize() const;
|
||||
|
||||
// 获取当前字体粗细值
|
||||
UINT GetFontWeight() const;
|
||||
|
||||
// 获取文字颜色
|
||||
const Color& GetColor() const;
|
||||
|
||||
// 获取描边颜色
|
||||
const Color& GetOutlineColor() const;
|
||||
|
||||
// 获取描边线宽
|
||||
float GetOutlineWidth() const;
|
||||
|
||||
// 获取描边线相交样式
|
||||
Stroke GetOutlineStroke() const;
|
||||
|
||||
// 获取文本显示行数
|
||||
int GetLineCount() const;
|
||||
|
||||
// 是否是斜体
|
||||
bool IsItalic() const;
|
||||
|
||||
// 是否显示删除线
|
||||
bool strikethrough() const;
|
||||
|
||||
// 是否显示下划线
|
||||
bool underline() const;
|
||||
|
||||
// 是否显示描边
|
||||
bool outline() const;
|
||||
|
||||
// 设置文本
|
||||
void SetText(
|
||||
const String& text
|
||||
);
|
||||
|
||||
// 设置文本样式
|
||||
void SetStyle(
|
||||
const Style& style
|
||||
);
|
||||
|
||||
// 设置字体
|
||||
void SetFont(
|
||||
const Font& font
|
||||
);
|
||||
|
||||
// 设置字体族
|
||||
void SetFontFamily(
|
||||
const String& family
|
||||
);
|
||||
|
||||
// 设置字号(默认值为 22)
|
||||
void SetFontSize(
|
||||
float size
|
||||
);
|
||||
|
||||
// 设置字体粗细值(默认值为 Text::Font::Weight::Normal)
|
||||
void SetFontWeight(
|
||||
UINT weight
|
||||
);
|
||||
|
||||
// 设置文字颜色(默认值为 Color::WHITE)
|
||||
void SetColor(
|
||||
Color color
|
||||
);
|
||||
|
||||
// 设置文字斜体(默认值为 false)
|
||||
void SetItalic(
|
||||
bool value
|
||||
);
|
||||
|
||||
// 打开或关闭文本自动换行(默认为关闭)
|
||||
void SetWrapEnabled(
|
||||
bool wrap
|
||||
);
|
||||
|
||||
// 设置文本自动换行的宽度(默认为 0)
|
||||
void SetWrapWidth(
|
||||
float wrap_width
|
||||
);
|
||||
|
||||
// 设置行间距(默认为 0)
|
||||
void SetLineSpacing(
|
||||
float line_spacing
|
||||
);
|
||||
|
||||
// 设置对齐方式(默认为 Align::Left)
|
||||
void SetAlignment(
|
||||
Align align
|
||||
);
|
||||
|
||||
// 设置下划线(默认值为 false)
|
||||
void SetUnderline(
|
||||
bool underline
|
||||
);
|
||||
|
||||
// 设置删除线(默认值为 false)
|
||||
void SetStrikethrough(
|
||||
bool strikethrough
|
||||
);
|
||||
|
||||
// 设置是否显示描边
|
||||
void SetOutline(
|
||||
bool outline
|
||||
);
|
||||
|
||||
// 设置描边颜色
|
||||
void SetOutlineColor(
|
||||
Color outline_color
|
||||
);
|
||||
|
||||
// 设置描边线宽
|
||||
void SetOutlineWidth(
|
||||
float outline_width
|
||||
);
|
||||
|
||||
// 设置描边线相交样式
|
||||
void SetOutlineStroke(
|
||||
Stroke outline_stroke
|
||||
);
|
||||
|
||||
// 渲染文字
|
||||
virtual void OnDraw() const override;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Text);
|
||||
|
||||
// 重新排版文字
|
||||
void Reset();
|
||||
|
||||
// 创建文字格式化
|
||||
void CreateFormat();
|
||||
|
||||
// 创建文字布局
|
||||
void CreateLayout();
|
||||
|
||||
private:
|
||||
String text_;
|
||||
Font font_;
|
||||
Style style_;
|
||||
IDWriteTextFormat* text_format_;
|
||||
IDWriteTextLayout* text_layout_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "TextRenderer.h"
|
||||
#include "base.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
ITextRenderer::ITextRenderer(ID2D1Factory* pD2DFactory, ID2D1HwndRenderTarget* pRT, ID2D1SolidColorBrush* pBrush)
|
||||
: cRefCount_(0)
|
||||
, pD2DFactory_(pD2DFactory)
|
||||
, pRT_(pRT)
|
||||
, pBrush_(pBrush)
|
||||
, sFillColor_()
|
||||
, sOutlineColor_()
|
||||
, fOutlineWidth(1)
|
||||
, bShowOutline_(TRUE)
|
||||
, pCurrStrokeStyle_(nullptr)
|
||||
{
|
||||
pD2DFactory->AddRef();
|
||||
pRT->AddRef();
|
||||
pBrush->AddRef();
|
||||
}
|
||||
|
||||
ITextRenderer::~ITextRenderer()
|
||||
{
|
||||
SafeRelease(pD2DFactory_);
|
||||
SafeRelease(pRT_);
|
||||
SafeRelease(pBrush_);
|
||||
}
|
||||
|
||||
HRESULT ITextRenderer::Create(
|
||||
ITextRenderer** ppTextRenderer,
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush)
|
||||
{
|
||||
*ppTextRenderer = new (std::nothrow) ITextRenderer(pD2DFactory, pRT, pBrush);
|
||||
if (*ppTextRenderer)
|
||||
{
|
||||
(*ppTextRenderer)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) ITextRenderer::SetTextStyle(
|
||||
CONST D2D1_COLOR_F &fillColor,
|
||||
BOOL outline,
|
||||
CONST D2D1_COLOR_F &outline_color,
|
||||
FLOAT outline_width,
|
||||
D2D1_LINE_JOIN outlineJoin)
|
||||
{
|
||||
sFillColor_ = fillColor;
|
||||
bShowOutline_ = outline;
|
||||
sOutlineColor_ = outline_color;
|
||||
fOutlineWidth = 2 * outline_width;
|
||||
|
||||
switch (outlineJoin)
|
||||
{
|
||||
case D2D1_LINE_JOIN_MITER:
|
||||
pCurrStrokeStyle_ = render::D2D.MiterStrokeStyle;
|
||||
break;
|
||||
case D2D1_LINE_JOIN_BEVEL:
|
||||
pCurrStrokeStyle_ = render::D2D.BevelStrokeStyle;
|
||||
break;
|
||||
case D2D1_LINE_JOIN_ROUND:
|
||||
pCurrStrokeStyle_ = render::D2D.RoundStrokeStyle;
|
||||
break;
|
||||
default:
|
||||
pCurrStrokeStyle_ = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::DrawGlyphRun(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
__in DWRITE_GLYPH_RUN const* glyphRun,
|
||||
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ID2D1PathGeometry* pPathGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreatePathGeometry(
|
||||
&pPathGeometry
|
||||
);
|
||||
|
||||
ID2D1GeometrySink* pSink = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pPathGeometry->Open(
|
||||
&pSink
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = glyphRun->fontFace->GetGlyphRunOutline(
|
||||
glyphRun->fontEmSize,
|
||||
glyphRun->glyphIndices,
|
||||
glyphRun->glyphAdvances,
|
||||
glyphRun->glyphOffsets,
|
||||
glyphRun->glyphCount,
|
||||
glyphRun->isSideways,
|
||||
glyphRun->bidiLevel % 2,
|
||||
pSink
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSink->Close();
|
||||
}
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pPathGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pPathGeometry);
|
||||
SafeRelease(pSink);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::DrawUnderline(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_UNDERLINE const* underline,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D2D1_RECT_F rect = D2D1::RectF(
|
||||
0,
|
||||
underline->offset,
|
||||
underline->width,
|
||||
underline->offset + underline->thickness
|
||||
);
|
||||
|
||||
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreateRectangleGeometry(
|
||||
&rect,
|
||||
&pRectangleGeometry
|
||||
);
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pRectangleGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pRectangleGeometry);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::DrawStrikethrough(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_STRIKETHROUGH const* strikethrough,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D2D1_RECT_F rect = D2D1::RectF(
|
||||
0,
|
||||
strikethrough->offset,
|
||||
strikethrough->width,
|
||||
strikethrough->offset + strikethrough->thickness
|
||||
);
|
||||
|
||||
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreateRectangleGeometry(
|
||||
&rect,
|
||||
&pRectangleGeometry
|
||||
);
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pRectangleGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pRectangleGeometry);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::DrawInlineObject(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL IsSideways,
|
||||
BOOL IsRightToLeft,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(unsigned long) ITextRenderer::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&cRefCount_);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(unsigned long) ITextRenderer::Release()
|
||||
{
|
||||
unsigned long newCount = InterlockedDecrement(&cRefCount_);
|
||||
|
||||
if (newCount == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return newCount;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::IsPixelSnappingDisabled(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out BOOL* isDisabled)
|
||||
{
|
||||
*isDisabled = FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::GetCurrentTransform(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out DWRITE_MATRIX* transform)
|
||||
{
|
||||
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::GetPixelsPerDip(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out FLOAT* pixelsPerDip)
|
||||
{
|
||||
float x, yUnused;
|
||||
|
||||
pRT_->GetDpi(&x, &yUnused);
|
||||
*pixelsPerDip = x / 96;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP ITextRenderer::QueryInterface(
|
||||
IID const& riid,
|
||||
void** ppvObject)
|
||||
{
|
||||
if (__uuidof(IDWriteTextRenderer) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else if (__uuidof(IDWritePixelSnapping) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else if (__uuidof(IUnknown) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppvObject = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include <d2d1.h>
|
||||
#include <dwrite.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
class ITextRenderer
|
||||
: public IDWriteTextRenderer
|
||||
{
|
||||
public:
|
||||
static HRESULT Create(
|
||||
ITextRenderer** ppTextRenderer,
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush
|
||||
);
|
||||
|
||||
STDMETHOD_(void, SetTextStyle)(
|
||||
CONST D2D1_COLOR_F &fillColor,
|
||||
BOOL outline,
|
||||
CONST D2D1_COLOR_F &outline_color,
|
||||
FLOAT outline_width,
|
||||
D2D1_LINE_JOIN outlineJoin
|
||||
);
|
||||
|
||||
STDMETHOD(DrawGlyphRun)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
__in DWRITE_GLYPH_RUN const* glyphRun,
|
||||
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawUnderline)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_UNDERLINE const* underline,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawStrikethrough)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_STRIKETHROUGH const* strikethrough,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawInlineObject)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL IsSideways,
|
||||
BOOL IsRightToLeft,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(IsPixelSnappingDisabled)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out BOOL* isDisabled
|
||||
);
|
||||
|
||||
STDMETHOD(GetCurrentTransform)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out DWRITE_MATRIX* transform
|
||||
);
|
||||
|
||||
STDMETHOD(GetPixelsPerDip)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out FLOAT* pixelsPerDip
|
||||
);
|
||||
|
||||
public:
|
||||
unsigned long STDMETHODCALLTYPE AddRef();
|
||||
unsigned long STDMETHODCALLTYPE Release();
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
IID const& riid,
|
||||
void** ppvObject
|
||||
);
|
||||
|
||||
private:
|
||||
ITextRenderer(
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush
|
||||
);
|
||||
|
||||
~ITextRenderer();
|
||||
|
||||
private:
|
||||
unsigned long cRefCount_;
|
||||
D2D1_COLOR_F sFillColor_;
|
||||
D2D1_COLOR_F sOutlineColor_;
|
||||
FLOAT fOutlineWidth;
|
||||
BOOL bShowOutline_;
|
||||
ID2D1Factory* pD2DFactory_;
|
||||
ID2D1HwndRenderTarget* pRT_;
|
||||
ID2D1SolidColorBrush* pBrush_;
|
||||
ID2D1StrokeStyle* pCurrStrokeStyle_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,448 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Transition.h"
|
||||
#include "Node.h"
|
||||
#include "Scene.h"
|
||||
#include "render.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// Transition
|
||||
//-------------------------------------------------------
|
||||
|
||||
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_()
|
||||
{
|
||||
duration_ = std::max(duration, 0.f);
|
||||
}
|
||||
|
||||
Transition::~Transition()
|
||||
{
|
||||
SafeRelease(out_layer_);
|
||||
SafeRelease(in_layer_);
|
||||
SafeRelease(out_scene_);
|
||||
SafeRelease(in_scene_);
|
||||
}
|
||||
|
||||
bool Transition::IsDone()
|
||||
{
|
||||
return done_;
|
||||
}
|
||||
|
||||
void Transition::Initialize(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();
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.HwndRenderTarget->CreateLayer(&in_layer_)
|
||||
);
|
||||
}
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.HwndRenderTarget->CreateLayer(&out_layer_)
|
||||
);
|
||||
}
|
||||
|
||||
window_size_ = window::instance.GetSize();
|
||||
out_layer_param_ = in_layer_param_ = D2D1::LayerParameters(
|
||||
D2D1::RectF(
|
||||
0.f,
|
||||
0.f,
|
||||
window_size_.width,
|
||||
window_size_.height
|
||||
),
|
||||
nullptr,
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
||||
D2D1::Matrix3x2F::Identity(),
|
||||
1.f,
|
||||
render::D2D.SolidColorBrush,
|
||||
D2D1_LAYER_OPTIONS_NONE
|
||||
);
|
||||
}
|
||||
|
||||
void Transition::Update()
|
||||
{
|
||||
if (duration_ == 0)
|
||||
{
|
||||
process_ = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
process_ = (time::Now() - started_).Seconds() / duration_;
|
||||
process_ = std::min(process_, 1.f);
|
||||
}
|
||||
|
||||
if (process_ >= 1)
|
||||
{
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Transition::Draw()
|
||||
{
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
render_target->SetTransform(out_scene_->GetTransform());
|
||||
render_target->PushAxisAlignedClip(
|
||||
D2D1::RectF(
|
||||
0.f,
|
||||
0.f,
|
||||
window_size_.width,
|
||||
window_size_.height
|
||||
),
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||
);
|
||||
render_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();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// BoxTransition
|
||||
//-------------------------------------------------------
|
||||
|
||||
BoxTransition::BoxTransition(float duration)
|
||||
: Transition(duration)
|
||||
{
|
||||
}
|
||||
|
||||
void BoxTransition::Initialize(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Initialize(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_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// EmergeTransition
|
||||
//-------------------------------------------------------
|
||||
|
||||
EmergeTransition::EmergeTransition(float duration)
|
||||
: Transition(duration)
|
||||
{
|
||||
}
|
||||
|
||||
void EmergeTransition::Initialize(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
out_layer_param_.opacity = 1;
|
||||
in_layer_param_.opacity = 0;
|
||||
}
|
||||
|
||||
void EmergeTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
out_layer_param_.opacity = 1 - process_;
|
||||
in_layer_param_.opacity = process_;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// FadeTransition
|
||||
//-------------------------------------------------------
|
||||
|
||||
FadeTransition::FadeTransition(float duration)
|
||||
: Transition(duration)
|
||||
{
|
||||
}
|
||||
|
||||
void FadeTransition::Initialize(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
out_layer_param_.opacity = 1;
|
||||
in_layer_param_.opacity = 0;
|
||||
}
|
||||
|
||||
void FadeTransition::Update()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MoveTransition
|
||||
//-------------------------------------------------------
|
||||
|
||||
MoveTransition::MoveTransition(float duration, Direction direction)
|
||||
: Transition(duration)
|
||||
, direction_(direction)
|
||||
{
|
||||
}
|
||||
|
||||
void MoveTransition::Initialize(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Initialize(prev, next, game);
|
||||
|
||||
switch (direction_)
|
||||
{
|
||||
case Direction::Up:
|
||||
pos_delta_ = Point(0, -window_size_.height);
|
||||
start_pos_ = Point(0, window_size_.height);
|
||||
break;
|
||||
case Direction::Down:
|
||||
pos_delta_ = Point(0, window_size_.height);
|
||||
start_pos_ = Point(0, -window_size_.height);
|
||||
break;
|
||||
case Direction::Left:
|
||||
pos_delta_ = Point(-window_size_.width, 0);
|
||||
start_pos_ = Point(window_size_.width, 0);
|
||||
break;
|
||||
case Direction::Right:
|
||||
pos_delta_ = Point(window_size_.width, 0);
|
||||
start_pos_ = Point(-window_size_.width, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Translation(
|
||||
start_pos_.x,
|
||||
start_pos_.y
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTransition::Reset()
|
||||
{
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// RotationTransition
|
||||
//-------------------------------------------------------
|
||||
|
||||
RotationTransition::RotationTransition(float duration, float rotation)
|
||||
: Transition(duration)
|
||||
, rotation_(rotation)
|
||||
{
|
||||
}
|
||||
|
||||
void RotationTransition::Initialize(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Initialize(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;
|
||||
}
|
||||
|
||||
void RotationTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
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;
|
||||
|
||||
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::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,21 +18,19 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_TRANSITION_H__
|
||||
#define __E2D_TRANSITION_H__
|
||||
|
||||
|
||||
#include "e2dutil.h"
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "time.h"
|
||||
#include "RefCounter.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
class Game;
|
||||
class Scene;
|
||||
|
||||
// 场景过渡
|
||||
class Transition
|
||||
: public Ref
|
||||
: public RefCounter
|
||||
{
|
||||
friend class Game;
|
||||
|
||||
|
|
@ -48,7 +46,7 @@ namespace easy2d
|
|||
|
||||
protected:
|
||||
// 初始化场景过渡动画
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -70,7 +68,7 @@ namespace easy2d
|
|||
bool done_;
|
||||
float duration_;
|
||||
float process_;
|
||||
Time started_;
|
||||
time::TimePoint started_;
|
||||
Size window_size_;
|
||||
Scene* out_scene_;
|
||||
Scene* in_scene_;
|
||||
|
|
@ -94,7 +92,7 @@ namespace easy2d
|
|||
// 更新动画
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -114,7 +112,7 @@ namespace easy2d
|
|||
protected:
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -134,7 +132,7 @@ namespace easy2d
|
|||
protected:
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -155,7 +153,7 @@ namespace easy2d
|
|||
protected:
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -183,7 +181,7 @@ namespace easy2d
|
|||
protected:
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void Init(
|
||||
virtual void Initialize(
|
||||
Scene * prev,
|
||||
Scene * next,
|
||||
Game * game
|
||||
|
|
@ -194,8 +192,4 @@ namespace easy2d
|
|||
protected:
|
||||
float rotation_;
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_TRANSITION_H__
|
||||
}
|
||||
|
|
@ -18,102 +18,70 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "audio.h"
|
||||
#include "base.h"
|
||||
#include "modules.h"
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mfreadwrite.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Loop::Loop(Action * action, int times /* = -1 */)
|
||||
: action_(action)
|
||||
, times_(0)
|
||||
, total_times_(times)
|
||||
namespace audio
|
||||
{
|
||||
E2D_WARNING_IF(action == nullptr, "Loop NULL pointer exception!");
|
||||
AudioDevice instance;
|
||||
|
||||
if (action)
|
||||
AudioDevice::AudioDevice()
|
||||
: x_audio2_(nullptr)
|
||||
, mastering_voice_(nullptr)
|
||||
{
|
||||
action_ = action;
|
||||
action_->Retain();
|
||||
}
|
||||
}
|
||||
|
||||
Loop::~Loop()
|
||||
{
|
||||
SafeRelease(action_);
|
||||
}
|
||||
|
||||
Loop * Loop::Clone() const
|
||||
{
|
||||
if (action_)
|
||||
{
|
||||
return new Loop(action_->Clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Loop * Loop::Reverse() const
|
||||
{
|
||||
if (action_)
|
||||
{
|
||||
return new Loop(action_->Clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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_)
|
||||
AudioDevice::~AudioDevice()
|
||||
{
|
||||
action_->Update();
|
||||
}
|
||||
|
||||
if (action_->IsDone())
|
||||
void AudioDevice::Initialize()
|
||||
{
|
||||
ThrowIfFailed(
|
||||
modules::MediaFoundation.MFStartup(MF_VERSION, MFSTARTUP_FULL)
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
modules::XAudio2.XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR)
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
x_audio2_->CreateMasteringVoice(&mastering_voice_)
|
||||
);
|
||||
}
|
||||
|
||||
void AudioDevice::Uninitialize()
|
||||
{
|
||||
if (mastering_voice_)
|
||||
{
|
||||
++times_;
|
||||
|
||||
Action::Reset();
|
||||
action_->Reset();
|
||||
mastering_voice_->DestroyVoice();
|
||||
mastering_voice_ = nullptr;
|
||||
}
|
||||
|
||||
SafeRelease(x_audio2_);
|
||||
|
||||
modules::MediaFoundation.MFShutdown();
|
||||
}
|
||||
else
|
||||
|
||||
HRESULT AudioDevice::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx)
|
||||
{
|
||||
this->Stop();
|
||||
return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
}
|
||||
}
|
||||
|
||||
void Loop::Reset()
|
||||
{
|
||||
Action::Reset();
|
||||
void AudioDevice::Open()
|
||||
{
|
||||
x_audio2_->StartEngine();
|
||||
}
|
||||
|
||||
if (action_) action_->Reset();
|
||||
times_ = 0;
|
||||
}
|
||||
|
||||
void Loop::ResetTime()
|
||||
{
|
||||
if (action_) action_->ResetTime();
|
||||
void AudioDevice::Close()
|
||||
{
|
||||
x_audio2_->StopEngine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,29 +18,43 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include <xaudio2.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
EmergeTransition::EmergeTransition(float duration)
|
||||
: Transition(duration)
|
||||
namespace audio
|
||||
{
|
||||
// 音频设备
|
||||
class AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioDevice();
|
||||
|
||||
~AudioDevice();
|
||||
|
||||
void Initialize();
|
||||
|
||||
void Uninitialize();
|
||||
|
||||
// 开启设备
|
||||
void Open();
|
||||
|
||||
// 关闭设备
|
||||
void Close();
|
||||
|
||||
// 创建音源
|
||||
HRESULT CreateVoice(
|
||||
IXAudio2SourceVoice ** voice,
|
||||
WAVEFORMATEX * wfx
|
||||
);
|
||||
|
||||
protected:
|
||||
IXAudio2 * x_audio2_;
|
||||
IXAudio2MasteringVoice* mastering_voice_;
|
||||
};
|
||||
|
||||
extern AudioDevice instance;
|
||||
}
|
||||
|
||||
void 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::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
out_layer_param_.opacity = 1 - process_;
|
||||
in_layer_param_.opacity = process_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,25 +18,31 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
#pragma once
|
||||
#include "BaseTypes.h"
|
||||
#include "Rect.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps)
|
||||
: JumpBy(duration, Point(), height, jumps)
|
||||
, end_pos_(pos)
|
||||
template<class Interface>
|
||||
inline void SafeRelease(Interface*& p)
|
||||
{
|
||||
if (p != nullptr)
|
||||
{
|
||||
p->Release();
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JumpTo * JumpTo::Clone() const
|
||||
inline void ThrowIfFailed(HRESULT hr)
|
||||
{
|
||||
return new JumpTo(duration_, end_pos_, height_, jumps_);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static char s_str[64] = {};
|
||||
::sprintf_s(s_str, "[easy2d] Failure with HRESULT of %08X", static_cast<unsigned int>(hr));
|
||||
::OutputDebugStringA(s_str);
|
||||
throw std::runtime_error(s_str);
|
||||
}
|
||||
}
|
||||
|
||||
void JumpTo::Init()
|
||||
{
|
||||
JumpBy::Init();
|
||||
delta_pos_ = end_pos_ - start_pos_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,50 +18,39 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
FiniteTimeAction::FiniteTimeAction(float duration)
|
||||
: delta_(0)
|
||||
, duration_(std::max(duration, 0.f))
|
||||
namespace logs
|
||||
{
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Reset()
|
||||
{
|
||||
Action::Reset();
|
||||
delta_ = 0;
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Init()
|
||||
{
|
||||
Action::Init();
|
||||
}
|
||||
|
||||
void FiniteTimeAction::Update()
|
||||
{
|
||||
Action::Update();
|
||||
|
||||
if (duration_ == 0)
|
||||
namespace
|
||||
{
|
||||
delta_ = 1;
|
||||
this->Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
delta_ = std::min((Time::Now() - started_).Seconds() / duration_, 1.f);
|
||||
|
||||
if (delta_ >= 1)
|
||||
inline void OutputDebugStringExW(LPCWSTR pszOutput, ...)
|
||||
{
|
||||
this->Stop();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteTimeAction::ResetTime()
|
||||
{
|
||||
Action::ResetTime();
|
||||
started_ = Time::Now() - Duration::Second * (delta_ * duration_);
|
||||
inline void Trace(LPCWSTR output)
|
||||
{
|
||||
OutputDebugStringExW(L"[easy2d] Error: %s\r\n", output);
|
||||
}
|
||||
|
||||
inline void Trace(LPCWSTR output, HRESULT hr)
|
||||
{
|
||||
OutputDebugStringExW(L"[easy2d] Failure with HRESULT of %08X: %s\r\n", output, static_cast<unsigned int>(hr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,9 +18,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_MACROS_H__
|
||||
#define __E2D_MACROS_H__
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WINVER
|
||||
# define WINVER 0x0700 // Allow use of features specific to Windows 7 or later
|
||||
|
|
@ -47,10 +45,6 @@
|
|||
# define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifndef DIRECTINPUT_VERSION
|
||||
# define DIRECTINPUT_VERSION 0x0800
|
||||
#endif
|
||||
|
||||
#ifndef INITGUID
|
||||
# define INITGUID
|
||||
#endif
|
||||
|
|
@ -59,40 +53,14 @@
|
|||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
#include <wincodec.h>
|
||||
#include <mmsystem.h>
|
||||
#include <d2d1.h>
|
||||
#include <dwrite.h>
|
||||
#include <dinput.h>
|
||||
#include <xaudio2.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mfreadwrite.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
// C++ RunTime Header Files
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
// Import Libraries
|
||||
#pragma comment(lib, "d2d1.lib")
|
||||
#pragma comment(lib, "dwrite.lib")
|
||||
#pragma comment(lib, "windowscodecs.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#pragma comment(lib, "dinput8.lib")
|
||||
#pragma comment(lib, "xaudio2.lib")
|
||||
#pragma comment(lib, "mfplat.lib")
|
||||
#pragma comment(lib, "mfreadwrite.lib")
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
|
|
@ -119,6 +87,3 @@
|
|||
#else
|
||||
# define E2D_WARNING_IF(exp, msg) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __E2D_MACROS_H__
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace modules
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline void SafeFreeLibrary(HMODULE instance)
|
||||
{
|
||||
if (instance)
|
||||
FreeLibrary(instance);
|
||||
}
|
||||
}
|
||||
|
||||
Module_XAudio2 XAudio2;
|
||||
Module_MediaFoundation MediaFoundation;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
const auto xaudio2_dll_names =
|
||||
{
|
||||
L"xaudio2_9.dll",
|
||||
L"xaudio2_8.dll",
|
||||
L"xaudio2_7.dll"
|
||||
};
|
||||
|
||||
for (const auto& name : xaudio2_dll_names)
|
||||
{
|
||||
XAudio2.instance = LoadLibraryW(name);
|
||||
if (XAudio2.instance)
|
||||
{
|
||||
XAudio2.XAudio2Create = (PFN_XAudio2Create)
|
||||
GetProcAddress(XAudio2.instance, "XAudio2Create");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MediaFoundation.mfplat = LoadLibraryW(L"Mfplat.dll");
|
||||
if (MediaFoundation.mfplat)
|
||||
{
|
||||
MediaFoundation.MFStartup = (PFN_MFStartup)
|
||||
GetProcAddress(MediaFoundation.mfplat, "MFStartup");
|
||||
|
||||
MediaFoundation.MFShutdown = (PFN_MFShutdown)
|
||||
GetProcAddress(MediaFoundation.mfplat, "MFShutdown");
|
||||
|
||||
MediaFoundation.MFCreateMediaType = (PFN_MFCreateMediaType)
|
||||
GetProcAddress(MediaFoundation.mfplat, "MFCreateMediaType");
|
||||
|
||||
MediaFoundation.MFCreateWaveFormatExFromMFMediaType = (PFN_MFCreateWaveFormatExFromMFMediaType)
|
||||
GetProcAddress(MediaFoundation.mfplat, "MFCreateWaveFormatExFromMFMediaType");
|
||||
|
||||
MediaFoundation.MFCreateMFByteStreamOnStream = (PFN_MFCreateMFByteStreamOnStream)
|
||||
GetProcAddress(MediaFoundation.mfplat, "MFCreateMFByteStreamOnStream");
|
||||
}
|
||||
|
||||
MediaFoundation.mfreadwrite = LoadLibraryW(L"Mfreadwrite.dll");
|
||||
if (MediaFoundation.mfreadwrite)
|
||||
{
|
||||
MediaFoundation.MFCreateSourceReaderFromURL = (PFN_MFCreateSourceReaderFromURL)
|
||||
GetProcAddress(MediaFoundation.mfreadwrite, "MFCreateSourceReaderFromURL");
|
||||
|
||||
MediaFoundation.MFCreateSourceReaderFromByteStream = (PFN_MFCreateSourceReaderFromByteStream)
|
||||
GetProcAddress(MediaFoundation.mfreadwrite, "MFCreateSourceReaderFromByteStream");
|
||||
}
|
||||
}
|
||||
|
||||
void Uninitialize()
|
||||
{
|
||||
SafeFreeLibrary(XAudio2.instance);
|
||||
SafeFreeLibrary(MediaFoundation.mfplat);
|
||||
SafeFreeLibrary(MediaFoundation.mfreadwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include <xaudio2.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mfreadwrite.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace modules
|
||||
{
|
||||
// XAudio2 functions
|
||||
typedef HRESULT(WINAPI *PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
|
||||
|
||||
struct Module_XAudio2
|
||||
{
|
||||
HMODULE instance;
|
||||
|
||||
PFN_XAudio2Create XAudio2Create;
|
||||
};
|
||||
|
||||
extern Module_XAudio2 XAudio2;
|
||||
|
||||
|
||||
// MediaFoundation functions
|
||||
typedef HRESULT(WINAPI *PFN_MFStartup)(ULONG, DWORD);
|
||||
typedef HRESULT(WINAPI *PFN_MFShutdown)();
|
||||
typedef HRESULT(WINAPI *PFN_MFCreateMediaType)(IMFMediaType**);
|
||||
typedef HRESULT(WINAPI *PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
|
||||
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
|
||||
typedef HRESULT(WINAPI *PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
|
||||
typedef HRESULT(WINAPI *PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
|
||||
|
||||
struct Module_MediaFoundation
|
||||
{
|
||||
HMODULE mfplat;
|
||||
HMODULE mfreadwrite;
|
||||
|
||||
PFN_MFStartup MFStartup;
|
||||
PFN_MFShutdown MFShutdown;
|
||||
PFN_MFCreateMediaType MFCreateMediaType;
|
||||
PFN_MFCreateWaveFormatExFromMFMediaType MFCreateWaveFormatExFromMFMediaType;
|
||||
PFN_MFCreateSourceReaderFromURL MFCreateSourceReaderFromURL;
|
||||
PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
|
||||
PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
|
||||
};
|
||||
|
||||
extern Module_MediaFoundation MediaFoundation;
|
||||
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
|
||||
void Initialize();
|
||||
|
||||
void Uninitialize();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "render.h"
|
||||
#include "time.h"
|
||||
#include "base.h"
|
||||
|
||||
#pragma comment(lib, "d2d1.lib")
|
||||
#pragma comment(lib, "dwrite.lib")
|
||||
#pragma comment(lib, "windowscodecs.lib")
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace render
|
||||
{
|
||||
_D2D_Resource D2D = { 0 };
|
||||
|
||||
void Initialize(HWND hwnd)
|
||||
{
|
||||
if (D2D.Factory)
|
||||
return;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D1CreateFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
&D2D.Factory
|
||||
)
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWICImagingFactory,
|
||||
reinterpret_cast<void**>(&D2D.WICImagingFactory)
|
||||
)
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory),
|
||||
reinterpret_cast<IUnknown**>(&D2D.DWriteFactory)
|
||||
)
|
||||
);
|
||||
|
||||
auto stroke_style = 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
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.MiterStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.BevelStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
|
||||
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateStrokeStyle(
|
||||
stroke_style,
|
||||
nullptr,
|
||||
0,
|
||||
&D2D.RoundStrokeStyle
|
||||
)
|
||||
);
|
||||
|
||||
CreateDeviceResources(hwnd);
|
||||
}
|
||||
|
||||
void CreateDeviceResources(HWND hwnd)
|
||||
{
|
||||
if (!D2D.HwndRenderTarget)
|
||||
{
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
|
||||
D2D1_SIZE_U size = D2D1::SizeU(
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top
|
||||
);
|
||||
|
||||
// 创建设备相关资源。这些资源应在 Direct2D 设备消失时重建
|
||||
// 创建一个 Direct2D 渲染目标
|
||||
ThrowIfFailed(
|
||||
D2D.Factory->CreateHwndRenderTarget(
|
||||
D2D1::RenderTargetProperties(),
|
||||
D2D1::HwndRenderTargetProperties(
|
||||
hwnd,
|
||||
size,
|
||||
D2D1_PRESENT_OPTIONS_NONE),
|
||||
&D2D.HwndRenderTarget
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!D2D.SolidColorBrush)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
D2D.HwndRenderTarget->CreateSolidColorBrush(
|
||||
D2D1::ColorF(D2D1::ColorF::White),
|
||||
&D2D.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!D2D.TextRenderer)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
ITextRenderer::Create(
|
||||
&D2D.TextRenderer,
|
||||
D2D.Factory,
|
||||
D2D.HwndRenderTarget,
|
||||
D2D.SolidColorBrush
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Uninitialize()
|
||||
{
|
||||
SafeRelease(D2D.TextRenderer);
|
||||
SafeRelease(D2D.SolidColorBrush);
|
||||
SafeRelease(D2D.HwndRenderTarget);
|
||||
|
||||
SafeRelease(D2D.MiterStrokeStyle);
|
||||
SafeRelease(D2D.BevelStrokeStyle);
|
||||
SafeRelease(D2D.RoundStrokeStyle);
|
||||
|
||||
SafeRelease(D2D.WICImagingFactory);
|
||||
SafeRelease(D2D.DWriteFactory);
|
||||
SafeRelease(D2D.Factory);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// GraphicsDevice
|
||||
//-------------------------------------------------------
|
||||
|
||||
GraphicsDevice instance;
|
||||
|
||||
GraphicsDevice::GraphicsDevice()
|
||||
: fps_text_format_(nullptr)
|
||||
, fps_text_layout_(nullptr)
|
||||
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
||||
{
|
||||
}
|
||||
|
||||
GraphicsDevice::~GraphicsDevice()
|
||||
{
|
||||
SafeRelease(fps_text_format_);
|
||||
SafeRelease(fps_text_layout_);
|
||||
}
|
||||
|
||||
void GraphicsDevice::BeginDraw(HWND hwnd)
|
||||
{
|
||||
render::CreateDeviceResources(hwnd);
|
||||
render::D2D.HwndRenderTarget->BeginDraw();
|
||||
render::D2D.HwndRenderTarget->Clear(clear_color_);
|
||||
}
|
||||
|
||||
void GraphicsDevice::EndDraw()
|
||||
{
|
||||
HRESULT hr = render::D2D.HwndRenderTarget->EndDraw();
|
||||
|
||||
if (hr == D2DERR_RECREATE_TARGET)
|
||||
{
|
||||
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
|
||||
// 并在下一次调用时重建资源
|
||||
hr = S_OK;
|
||||
|
||||
SafeRelease(fps_text_format_);
|
||||
SafeRelease(fps_text_layout_);
|
||||
SafeRelease(render::D2D.TextRenderer);
|
||||
SafeRelease(render::D2D.SolidColorBrush);
|
||||
SafeRelease(render::D2D.HwndRenderTarget);
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void GraphicsDevice::SetBackgroundColor(const Color& color)
|
||||
{
|
||||
clear_color_ = color;
|
||||
}
|
||||
|
||||
void GraphicsDevice::DrawDebugInfo()
|
||||
{
|
||||
static int render_times_ = 0;
|
||||
static time::TimePoint last_render_time_ = time::Now();
|
||||
int duration = (time::Now() - last_render_time_).Milliseconds();
|
||||
|
||||
if (!fps_text_format_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
render::D2D.DWriteFactory->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(
|
||||
render::D2D.DWriteFactory->CreateTextLayout(
|
||||
fps_text,
|
||||
static_cast<UINT32>(len),
|
||||
fps_text_format_,
|
||||
0,
|
||||
0,
|
||||
&fps_text_layout_
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fps_text_layout_)
|
||||
{
|
||||
render::D2D.HwndRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
render::D2D.SolidColorBrush->SetOpacity(1.0f);
|
||||
render::D2D.TextRenderer->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, render::D2D.TextRenderer, 10, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,59 +18,62 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include "TextRenderer.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
JumpBy::JumpBy(float duration, const Point & vec, float height, int jumps)
|
||||
: FiniteTimeAction(duration)
|
||||
, delta_pos_(vec)
|
||||
, height_(height)
|
||||
, jumps_(jumps)
|
||||
namespace render
|
||||
{
|
||||
}
|
||||
|
||||
JumpBy * JumpBy::Clone() const
|
||||
{
|
||||
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_)
|
||||
typedef struct
|
||||
{
|
||||
prev_pos_ = start_pos_ = target_->GetPosition();
|
||||
}
|
||||
}
|
||||
ID2D1Factory* Factory;
|
||||
IWICImagingFactory* WICImagingFactory;
|
||||
IDWriteFactory* DWriteFactory;
|
||||
ITextRenderer* TextRenderer;
|
||||
ID2D1SolidColorBrush* SolidColorBrush;
|
||||
ID2D1HwndRenderTarget* HwndRenderTarget;
|
||||
ID2D1StrokeStyle* MiterStrokeStyle;
|
||||
ID2D1StrokeStyle* BevelStrokeStyle;
|
||||
ID2D1StrokeStyle* RoundStrokeStyle;
|
||||
} _D2D_Resource;
|
||||
|
||||
void JumpBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
extern _D2D_Resource D2D;
|
||||
|
||||
if (target_)
|
||||
void Initialize(HWND hwnd);
|
||||
|
||||
void CreateDeviceResources(HWND hwnd);
|
||||
|
||||
void Uninitialize();
|
||||
|
||||
class GraphicsDevice
|
||||
{
|
||||
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_;
|
||||
public:
|
||||
GraphicsDevice();
|
||||
|
||||
Point currentPos = target_->GetPosition();
|
||||
~GraphicsDevice();
|
||||
|
||||
Point diff = currentPos - prev_pos_;
|
||||
start_pos_ = diff + start_pos_;
|
||||
// 开始渲染
|
||||
void BeginDraw(HWND hwnd);
|
||||
|
||||
Point newPos = start_pos_ + Point(x, y);
|
||||
target_->SetPosition(newPos);
|
||||
// 结束渲染
|
||||
void EndDraw();
|
||||
|
||||
prev_pos_ = newPos;
|
||||
}
|
||||
// 渲染调试信息
|
||||
void DrawDebugInfo();
|
||||
|
||||
// 设置背景色
|
||||
void SetBackgroundColor(
|
||||
const Color& color
|
||||
);
|
||||
|
||||
protected:
|
||||
D2D1_COLOR_F clear_color_;
|
||||
IDWriteTextFormat* fps_text_format_;
|
||||
IDWriteTextLayout* fps_text_layout_;
|
||||
};
|
||||
|
||||
extern GraphicsDevice instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "time.h"
|
||||
#include <regex>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace time
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// TimePoint
|
||||
//-------------------------------------------------------
|
||||
|
||||
TimePoint::TimePoint()
|
||||
{
|
||||
}
|
||||
|
||||
TimePoint::TimePoint(std::chrono::steady_clock::time_point time)
|
||||
: time_(time)
|
||||
{
|
||||
}
|
||||
|
||||
TimePoint::TimePoint(const TimePoint & other)
|
||||
: time_(other.time_)
|
||||
{
|
||||
}
|
||||
|
||||
TimePoint::TimePoint(TimePoint && other)
|
||||
: time_(std::move(other.time_))
|
||||
{
|
||||
}
|
||||
|
||||
time_t TimePoint::GetTimeStamp() const
|
||||
{
|
||||
auto& duration = time_point_cast<milliseconds>(time_).time_since_epoch();
|
||||
return static_cast<time_t>(duration.count());
|
||||
}
|
||||
|
||||
bool TimePoint::IsZero() const
|
||||
{
|
||||
return time_.time_since_epoch().count() == 0LL;
|
||||
}
|
||||
|
||||
TimePoint TimePoint::operator+(const Duration & other) const
|
||||
{
|
||||
return TimePoint(time_ + milliseconds(other.Milliseconds()));
|
||||
}
|
||||
|
||||
TimePoint TimePoint::operator-(const Duration & other) const
|
||||
{
|
||||
return TimePoint(time_ - milliseconds(other.Milliseconds()));
|
||||
}
|
||||
|
||||
TimePoint & TimePoint::operator+=(const Duration & other)
|
||||
{
|
||||
time_ += milliseconds(other.Milliseconds());
|
||||
return (*this);
|
||||
}
|
||||
|
||||
TimePoint & TimePoint::operator-=(const Duration &other)
|
||||
{
|
||||
time_ -= milliseconds(other.Milliseconds());
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration TimePoint::operator-(const TimePoint & other) const
|
||||
{
|
||||
auto ms = duration_cast<milliseconds>(time_ - other.time_).count();
|
||||
return Duration(static_cast<int>(ms));
|
||||
}
|
||||
|
||||
TimePoint& TimePoint::operator=(const TimePoint & other) E2D_NOEXCEPT
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
time_ = other.time_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TimePoint& TimePoint::operator=(TimePoint && other) E2D_NOEXCEPT
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
time_ = std::move(other.time_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Duration
|
||||
//-------------------------------------------------------
|
||||
|
||||
const Duration Millisecond = Duration(1);
|
||||
const Duration Second = 1000 * Millisecond;
|
||||
const Duration Minute = 60 * Second;
|
||||
const Duration Hour = 60 * Minute;
|
||||
|
||||
namespace
|
||||
{
|
||||
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", Millisecond},
|
||||
{L"s", Second},
|
||||
{L"m", Minute},
|
||||
{L"h", 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);
|
||||
}
|
||||
|
||||
bool Duration::operator==(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ == other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator!=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ != other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator>(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ > other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator>=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ >= other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator<(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ < other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator<=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ <= other.milliseconds_;
|
||||
}
|
||||
|
||||
Duration Duration::operator+(const Duration & other) const
|
||||
{
|
||||
return Duration(milliseconds_ + other.milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator-(const Duration & other) const
|
||||
{
|
||||
return Duration(milliseconds_ - other.milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator-() const
|
||||
{
|
||||
return Duration(-milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator*(int value) const
|
||||
{
|
||||
return Duration(milliseconds_ * value);
|
||||
}
|
||||
|
||||
Duration Duration::operator/(int value) const
|
||||
{
|
||||
return Duration(milliseconds_ / value);
|
||||
}
|
||||
|
||||
Duration Duration::operator*(float value) const
|
||||
{
|
||||
return Duration(static_cast<int>(milliseconds_ * value));
|
||||
}
|
||||
|
||||
Duration 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));
|
||||
}
|
||||
|
||||
Duration Duration::operator/(double value) const
|
||||
{
|
||||
return Duration(static_cast<int>(milliseconds_ / value));
|
||||
}
|
||||
|
||||
Duration & Duration::operator+=(const Duration &other)
|
||||
{
|
||||
milliseconds_ += other.milliseconds_;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator-=(const Duration &other)
|
||||
{
|
||||
milliseconds_ -= other.milliseconds_;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator*=(int value)
|
||||
{
|
||||
milliseconds_ *= value;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator/=(int value)
|
||||
{
|
||||
milliseconds_ /= value;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator*=(float value)
|
||||
{
|
||||
milliseconds_ = static_cast<int>(milliseconds_ * value);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & 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);
|
||||
}
|
||||
|
||||
Duration & Duration::operator/=(double value)
|
||||
{
|
||||
milliseconds_ = static_cast<int>(milliseconds_ / value);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration operator*(int value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(int value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
Duration operator*(float value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(float value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
Duration operator*(double value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(double value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Functions
|
||||
//-------------------------------------------------------
|
||||
|
||||
TimePoint Now()
|
||||
{
|
||||
return TimePoint(steady_clock::now());
|
||||
}
|
||||
|
||||
Duration ParseDuration(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("Time::Duration::Parse: invalid duration");
|
||||
return Duration();
|
||||
}
|
||||
|
||||
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("Time::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("Time::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 = -d;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#include <chrono>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace time
|
||||
{
|
||||
// 时间段
|
||||
//
|
||||
// Usage:
|
||||
// 时间段表示法:
|
||||
// 5 秒: time::Second * 5
|
||||
// 1.5 小时: time::Hour * 1.5
|
||||
// 3 小时 45 分 15 秒: time::Hour * 3 + time::Minute * 45 + time::Second * 15
|
||||
// 时间段格式化: auto d = time::ParseDuration(L"1h35m"); // 1小时35分钟
|
||||
//
|
||||
class Duration
|
||||
{
|
||||
public:
|
||||
Duration();
|
||||
|
||||
explicit Duration(
|
||||
int milliseconds
|
||||
);
|
||||
|
||||
// 转化为毫秒
|
||||
int Milliseconds() const;
|
||||
|
||||
// 转化为秒
|
||||
float Seconds() const;
|
||||
|
||||
// 转化为分钟
|
||||
float Minutes() const;
|
||||
|
||||
// 转化为小时
|
||||
float Hours() const;
|
||||
|
||||
bool operator== (const Duration &) const;
|
||||
bool operator!= (const Duration &) const;
|
||||
bool operator> (const Duration &) const;
|
||||
bool operator>= (const Duration &) const;
|
||||
bool operator< (const Duration &) const;
|
||||
bool operator<= (const Duration &) const;
|
||||
|
||||
Duration operator + (const Duration &) const;
|
||||
Duration operator - (const Duration &) const;
|
||||
Duration operator - () const;
|
||||
Duration operator * (int) const;
|
||||
Duration operator * (float) const;
|
||||
Duration operator * (double) const;
|
||||
Duration operator / (int) const;
|
||||
Duration operator / (float) const;
|
||||
Duration operator / (double) const;
|
||||
|
||||
Duration& operator += (const Duration &);
|
||||
Duration& operator -= (const Duration &);
|
||||
Duration& operator *= (int);
|
||||
Duration& operator *= (float);
|
||||
Duration& operator *= (double);
|
||||
Duration& operator /= (int);
|
||||
Duration& operator /= (float);
|
||||
Duration& operator /= (double);
|
||||
|
||||
friend Duration operator* (int, const Duration &);
|
||||
friend Duration operator* (float, const Duration &);
|
||||
friend Duration operator* (double, const Duration &);
|
||||
friend Duration operator/ (int, const Duration &);
|
||||
friend Duration operator/ (float, const Duration &);
|
||||
friend Duration operator/ (double, const Duration &);
|
||||
|
||||
private:
|
||||
int milliseconds_;
|
||||
};
|
||||
|
||||
extern const Duration Millisecond; // 毫秒
|
||||
extern const Duration Second; // 秒
|
||||
extern const Duration Minute; // 分钟
|
||||
extern const Duration Hour; // 小时
|
||||
|
||||
|
||||
// 时间
|
||||
//
|
||||
// Usage:
|
||||
// 获取当前时间: Time now = time::Now();
|
||||
// 时间操作:
|
||||
// 两时间相减, 得到一个 Duration 对象, 例如:
|
||||
// Time t1 = time::Now();
|
||||
// ... // 做些什么
|
||||
// Time t2 = time::Now();
|
||||
// auto duration = t2 - t1;
|
||||
// 获取两时间相差的毫秒数:
|
||||
// int ms = duration.Milliseconds();
|
||||
//
|
||||
class TimePoint
|
||||
{
|
||||
public:
|
||||
TimePoint();
|
||||
|
||||
explicit TimePoint(
|
||||
std::chrono::steady_clock::time_point
|
||||
);
|
||||
|
||||
TimePoint(
|
||||
const TimePoint& other
|
||||
);
|
||||
|
||||
TimePoint(
|
||||
TimePoint&& other
|
||||
);
|
||||
|
||||
// 获取时间戳
|
||||
time_t GetTimeStamp() const;
|
||||
|
||||
// 是否是零时
|
||||
bool IsZero() const;
|
||||
|
||||
TimePoint operator + (const Duration &) const;
|
||||
TimePoint operator - (const Duration &) const;
|
||||
|
||||
TimePoint& operator += (const Duration &);
|
||||
TimePoint& operator -= (const Duration &);
|
||||
|
||||
Duration operator - (const TimePoint &) const;
|
||||
|
||||
TimePoint& operator = (const TimePoint &) E2D_NOEXCEPT;
|
||||
TimePoint& operator = (TimePoint &&) E2D_NOEXCEPT;
|
||||
|
||||
private:
|
||||
std::chrono::steady_clock::time_point time_;
|
||||
};
|
||||
|
||||
// 获取当前时间
|
||||
TimePoint Now();
|
||||
|
||||
// 时间段格式化
|
||||
// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀
|
||||
// 例如: "300ms", "-1.5h", "2h45m"
|
||||
// 允许的时间单位有 "ms", "s", "m", "h"
|
||||
Duration ParseDuration(const std::wstring& parse_str);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,368 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "window.h"
|
||||
#include "render.h"
|
||||
#include "Game.h"
|
||||
#include "Scene.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
#include "../math/scalar.hpp"
|
||||
#include <imm.h>
|
||||
#pragma comment (lib ,"imm32.lib")
|
||||
|
||||
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
|
||||
#define REGISTER_CLASS L"Easy2DApp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace window
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void GetContentScale(float* xscale, float* yscale);
|
||||
|
||||
Rect LocateWindow(int width, int height);
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
|
||||
}
|
||||
|
||||
WindowInfo instance;
|
||||
|
||||
WindowInfo::WindowInfo()
|
||||
: handle(nullptr)
|
||||
, xscale(1.f)
|
||||
, yscale(1.f)
|
||||
{
|
||||
}
|
||||
|
||||
void WindowInfo::Initialize(const Property& property)
|
||||
{
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
WNDCLASSEX wcex = { 0 };
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.lpszClassName = REGISTER_CLASS;
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.hIcon = nullptr;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
||||
wcex.hInstance = hinstance;
|
||||
wcex.hbrBackground = nullptr;
|
||||
wcex.lpszMenuName = nullptr;
|
||||
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
|
||||
|
||||
if (property.icon)
|
||||
{
|
||||
wcex.hIcon = (HICON)::LoadImage(
|
||||
hinstance,
|
||||
property.icon,
|
||||
IMAGE_ICON,
|
||||
0,
|
||||
0,
|
||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||
);
|
||||
}
|
||||
|
||||
::RegisterClassEx(&wcex);
|
||||
|
||||
GetContentScale(&xscale, &yscale);
|
||||
|
||||
// 计算窗口大小
|
||||
Rect client_rect = LocateWindow(property.width, property.height);
|
||||
|
||||
// 创建窗口
|
||||
handle = ::CreateWindowEx(
|
||||
NULL,
|
||||
REGISTER_CLASS,
|
||||
property.title.c_str(),
|
||||
WINDOW_STYLE,
|
||||
static_cast<int>(client_rect.origin.x),
|
||||
static_cast<int>(client_rect.origin.y),
|
||||
static_cast<int>(client_rect.size.width),
|
||||
static_cast<int>(client_rect.size.height),
|
||||
nullptr,
|
||||
nullptr,
|
||||
hinstance,
|
||||
this
|
||||
);
|
||||
|
||||
if (handle == nullptr)
|
||||
{
|
||||
::UnregisterClass(REGISTER_CLASS, hinstance);
|
||||
throw std::runtime_error("Create window failed");
|
||||
}
|
||||
|
||||
// 禁用输入法
|
||||
::ImmAssociateContext(handle, nullptr);
|
||||
}
|
||||
|
||||
void WindowInfo::Destroy()
|
||||
{
|
||||
if (handle)
|
||||
::DestroyWindow(handle);
|
||||
}
|
||||
|
||||
String WindowInfo::GetTitle() const
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
wchar_t title[256];
|
||||
GetWindowTextW(handle, title, 256);
|
||||
return title;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
void WindowInfo::SetTitle(const String& title)
|
||||
{
|
||||
if (handle)
|
||||
::SetWindowText(handle, title.c_str());
|
||||
}
|
||||
|
||||
Size WindowInfo::GetSize() const
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(handle, &rect);
|
||||
return Size(
|
||||
static_cast<float>(rect.right - rect.left),
|
||||
static_cast<float>(rect.bottom - rect.top)
|
||||
);
|
||||
}
|
||||
return Size();
|
||||
}
|
||||
|
||||
float WindowInfo::GetWidth() const
|
||||
{
|
||||
return GetSize().width;
|
||||
}
|
||||
|
||||
float WindowInfo::GetHeight() const
|
||||
{
|
||||
return GetSize().height;
|
||||
}
|
||||
|
||||
void WindowInfo::SetSize(int width, int height)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
Rect rect = LocateWindow(width, height);
|
||||
::MoveWindow(
|
||||
handle,
|
||||
static_cast<int>(rect.origin.x),
|
||||
static_cast<int>(rect.origin.y),
|
||||
static_cast<int>(rect.size.width),
|
||||
static_cast<int>(rect.size.height),
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowInfo::SetIcon(LPCWSTR icon_resource)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
HICON icon = (HICON)::LoadImage(
|
||||
hinstance,
|
||||
icon_resource,
|
||||
IMAGE_ICON,
|
||||
0,
|
||||
0,
|
||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||
);
|
||||
|
||||
::SendMessage(handle, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
||||
::SendMessage(handle, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void GetContentScale(float* xscale, float* yscale)
|
||||
{
|
||||
const float DEFAULT_SCREEN_DPI = 96.f;
|
||||
const HDC dc = GetDC(NULL);
|
||||
float xdpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSX));
|
||||
float ydpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSY));
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (xscale)
|
||||
*xscale = xdpi / DEFAULT_SCREEN_DPI;
|
||||
if (yscale)
|
||||
*yscale = ydpi / DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
|
||||
Rect LocateWindow(int width, int height)
|
||||
{
|
||||
int max_width = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
int max_height = ::GetSystemMetrics(SM_CYSCREEN);
|
||||
RECT rect =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
static_cast<LONG>(math::Ceil(width * instance.xscale)),
|
||||
static_cast<LONG>(math::Ceil(height * instance.yscale))
|
||||
};
|
||||
|
||||
// 计算合适的窗口大小
|
||||
::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL);
|
||||
width = static_cast<int>(rect.right - rect.left);
|
||||
height = static_cast<int>(rect.bottom - rect.top);
|
||||
|
||||
// 当输入的窗口大小比分辨率大时,给出警告
|
||||
E2D_WARNING_IF(max_width < width || max_height < height, "The window Is larger than screen!");
|
||||
width = std::min(width, max_width);
|
||||
height = std::min(height, max_height);
|
||||
|
||||
return Rect(
|
||||
static_cast<float>((max_width - width) / 2),
|
||||
static_cast<float>((max_height - height) / 2),
|
||||
static_cast<float>(width),
|
||||
static_cast<float>(height)
|
||||
);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
LRESULT result = 0;
|
||||
bool was_handled = false;
|
||||
|
||||
Game * game = reinterpret_cast<Game*>(
|
||||
static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))
|
||||
);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
|
||||
// 处理鼠标消息
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
if (game->IsTransitioning())
|
||||
break;
|
||||
|
||||
auto curr_scene = game->GetCurrentScene();
|
||||
if (curr_scene)
|
||||
{
|
||||
curr_scene->Dispatch(MouseEvent(msg, w_param, l_param));
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 处理按键消息
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
if (game->IsTransitioning())
|
||||
break;
|
||||
|
||||
auto curr_scene = game->GetCurrentScene();
|
||||
if (curr_scene)
|
||||
{
|
||||
curr_scene->Dispatch(KeyEvent(msg, w_param, l_param));
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 处理窗口大小变化消息
|
||||
case WM_SIZE:
|
||||
{
|
||||
UINT width = LOWORD(l_param);
|
||||
UINT height = HIWORD(l_param);
|
||||
|
||||
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
|
||||
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
|
||||
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
|
||||
auto render_target = render::D2D.HwndRenderTarget;
|
||||
if (render_target)
|
||||
{
|
||||
render_target->Resize(D2D1::SizeU(width, height));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 处理分辨率变化消息
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
// 重绘客户区
|
||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 重绘窗口
|
||||
case WM_PAINT:
|
||||
{
|
||||
game->DrawScene();
|
||||
::ValidateRect(hwnd, nullptr);
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 窗口关闭消息
|
||||
case WM_CLOSE:
|
||||
{
|
||||
if (game->OnClose())
|
||||
{
|
||||
game->Quit();
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 窗口销毁消息
|
||||
case WM_DESTROY:
|
||||
{
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
result = 1;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (!was_handled)
|
||||
{
|
||||
result = ::DefWindowProc(hwnd, msg, w_param, l_param);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,46 +18,66 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
BoxTransition::BoxTransition(float duration)
|
||||
: Transition(duration)
|
||||
namespace window
|
||||
{
|
||||
}
|
||||
|
||||
void BoxTransition::Init(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Init(prev, next, game);
|
||||
|
||||
in_layer_param_.opacity = 0;
|
||||
}
|
||||
|
||||
void BoxTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
if (process_ < .5f)
|
||||
typedef struct Property
|
||||
{
|
||||
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
|
||||
String title; /* 标题 */
|
||||
int width; /* 宽度 */
|
||||
int height; /* 高度 */
|
||||
LPCWSTR icon; /* 图标 */
|
||||
|
||||
Property()
|
||||
: title(L"Easy2D Game")
|
||||
, width(640)
|
||||
, height(480)
|
||||
, icon(nullptr)
|
||||
{}
|
||||
} Property;
|
||||
|
||||
class WindowInfo
|
||||
{
|
||||
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_
|
||||
public:
|
||||
HWND handle;
|
||||
float xscale;
|
||||
float yscale;
|
||||
|
||||
public:
|
||||
WindowInfo();
|
||||
|
||||
void Initialize(
|
||||
const Property& property
|
||||
);
|
||||
}
|
||||
|
||||
void Destroy();
|
||||
|
||||
// 获取标题
|
||||
String GetTitle() const;
|
||||
|
||||
// 设置标题
|
||||
void SetTitle(const String& title);
|
||||
|
||||
// 获取窗口大小
|
||||
Size GetSize() const;
|
||||
|
||||
// 获取窗口宽度
|
||||
float GetWidth() const;
|
||||
|
||||
// 获取窗口高度
|
||||
float GetHeight() const;
|
||||
|
||||
// 重设窗口大小
|
||||
void SetSize(int width, int height);
|
||||
|
||||
// 设置窗口图标
|
||||
void SetIcon(LPCWSTR icon_resource);
|
||||
};
|
||||
|
||||
extern WindowInfo instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dcomponent.h"
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
#define SAFE_SET(pointer, func, ...) if (pointer) { pointer->##func(__VA_ARGS__); }
|
||||
|
||||
#define SET_BUTTON_NODE(Old, New) \
|
||||
if (New != Old) \
|
||||
{ \
|
||||
if (Old) this->RemoveChild(Old); \
|
||||
if (New) \
|
||||
{ \
|
||||
New->SetPivot(GetPivotX(), GetPivotY()); \
|
||||
this->AddChild(New); \
|
||||
} \
|
||||
Old = New; \
|
||||
UpdateVisible(); \
|
||||
} \
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Button::Button()
|
||||
: callback_(nullptr)
|
||||
, status_(Status::Normal)
|
||||
, enabled_(true)
|
||||
, is_selected_(false)
|
||||
, normal_(nullptr)
|
||||
, mouseover_(nullptr)
|
||||
, selected_(nullptr)
|
||||
, disabled_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (callback_)
|
||||
{
|
||||
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)
|
||||
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_)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Button::SetStatus(Status status)
|
||||
{
|
||||
if (status_ != status)
|
||||
{
|
||||
status_ = status;
|
||||
UpdateVisible();
|
||||
}
|
||||
}
|
||||
|
||||
void 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_)
|
||||
{
|
||||
selected_->SetVisible(true);
|
||||
}
|
||||
else if (status_ == Status::Mouseover && mouseover_)
|
||||
{
|
||||
mouseover_->SetVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (normal_) normal_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disabled_)
|
||||
{
|
||||
disabled_->SetVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (normal_) normal_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_COMPONENT_H__
|
||||
#define __E2D_COMPONENT_H__
|
||||
|
||||
|
||||
#include "e2dobject.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
class Button
|
||||
: public Node
|
||||
{
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
public:
|
||||
Button();
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * selected, /* 鼠标按下状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * mouseover, /* 鼠标移入状态 */
|
||||
Node * selected, /* 鼠标按下状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * mouseover, /* 鼠标移入状态 */
|
||||
Node * selected, /* 鼠标移入状态 */
|
||||
Node * disabled, /* 按钮禁用状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
// 获取按钮状态是启用还是禁用
|
||||
bool IsEnable() const;
|
||||
|
||||
// 设置按钮启用或禁用
|
||||
void SetEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 设置一般情况下显示的按钮
|
||||
virtual void SetNormal(
|
||||
Node * normal
|
||||
);
|
||||
|
||||
// 设置鼠标移入按钮时显示的按钮
|
||||
virtual void SetMouseOver(
|
||||
Node * mouseover
|
||||
);
|
||||
|
||||
// 设置鼠标按下按钮时显示的按钮
|
||||
virtual void SetSelected(
|
||||
Node * selected
|
||||
);
|
||||
|
||||
// 设置按钮被禁用时显示的按钮
|
||||
virtual void SetDisabled(
|
||||
Node * disabled
|
||||
);
|
||||
|
||||
// 设置按钮点击后的回调函数
|
||||
void SetCallbackOnClick(
|
||||
const Callback& func
|
||||
);
|
||||
|
||||
// 设置支点位置
|
||||
// 默认为 (0, 0), 范围 [0, 1]
|
||||
virtual void SetPivot(
|
||||
float pivot_x,
|
||||
float pivot_y
|
||||
) override;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Button);
|
||||
|
||||
// 按钮状态枚举
|
||||
enum class Status { Normal, Mouseover, Selected };
|
||||
|
||||
// 设置按钮状态
|
||||
virtual void SetStatus(
|
||||
Status status
|
||||
);
|
||||
|
||||
// 刷新按钮显示
|
||||
virtual void UpdateVisible();
|
||||
|
||||
// 分发鼠标消息
|
||||
virtual bool Dispatch(
|
||||
const MouseEvent& e,
|
||||
bool handled
|
||||
) override;
|
||||
|
||||
// 遍历节点
|
||||
virtual void Visit() override;
|
||||
|
||||
private:
|
||||
Node * normal_;
|
||||
Node * mouseover_;
|
||||
Node * selected_;
|
||||
Node * disabled_;
|
||||
bool enabled_;
|
||||
bool is_selected_;
|
||||
Status status_;
|
||||
Callback callback_;
|
||||
};
|
||||
|
||||
|
||||
// 菜单
|
||||
class Menu
|
||||
: public Node
|
||||
{
|
||||
public:
|
||||
Menu();
|
||||
|
||||
explicit Menu(
|
||||
const std::vector<Button*>& buttons /* 按钮数组 */
|
||||
);
|
||||
|
||||
// 获取菜单是否禁用
|
||||
bool IsEnable() const;
|
||||
|
||||
// 获取菜单中的按钮数量
|
||||
size_t GetButtonCount() const;
|
||||
|
||||
// 设置菜单启用或禁用
|
||||
void SetEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 添加按钮
|
||||
void AddButton(
|
||||
Button * button
|
||||
);
|
||||
|
||||
// 移除按钮
|
||||
bool RemoveButton(
|
||||
Button * button
|
||||
);
|
||||
|
||||
// 获取所有按钮
|
||||
const std::vector<Button*>& GetAllButtons() const;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Menu);
|
||||
|
||||
private:
|
||||
bool enabled_;
|
||||
std::vector<Button*> buttons_;
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // !__E2D_COMPONENT_H__
|
||||
327
core/e2dmodule.h
327
core/e2dmodule.h
|
|
@ -1,327 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_MODULE_H__
|
||||
#define __E2D_MODULE_H__
|
||||
|
||||
|
||||
#include "e2dobject.h"
|
||||
#include "e2dtransition.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
// 图形设备
|
||||
class Graphics
|
||||
{
|
||||
public:
|
||||
Graphics(
|
||||
HWND hwnd
|
||||
);
|
||||
|
||||
~Graphics();
|
||||
|
||||
// 开始渲染
|
||||
void BeginDraw();
|
||||
|
||||
// 结束渲染
|
||||
void EndDraw();
|
||||
|
||||
// 渲染调试信息
|
||||
void DrawDebugInfo();
|
||||
|
||||
// 获取 ID2D1Factory 对象
|
||||
ID2D1Factory* GetFactory() const;
|
||||
|
||||
// 获取 IWICImagingFactory 对象
|
||||
IWICImagingFactory* GetImagingFactory() const;
|
||||
|
||||
// 获取 IDWriteFactory 对象
|
||||
IDWriteFactory* GetWriteFactory() const;
|
||||
|
||||
// 获取 ID2D1HwndRenderTarget 对象
|
||||
ID2D1HwndRenderTarget* GetRenderTarget() const;
|
||||
|
||||
// 获取 ID2D1SolidColorBrush 对象
|
||||
ID2D1SolidColorBrush* GetSolidBrush() const;
|
||||
|
||||
// 获取文字渲染工具
|
||||
IDWriteTextRenderer* GetTextRender() const;
|
||||
|
||||
// 获取 Miter 样式的 ID2D1StrokeStyle
|
||||
ID2D1StrokeStyle* GetMiterStrokeStyle();
|
||||
|
||||
// 获取 Bevel 样式的 ID2D1StrokeStyle
|
||||
ID2D1StrokeStyle* GetBevelStrokeStyle();
|
||||
|
||||
// 获取 Round 样式的 ID2D1StrokeStyle
|
||||
ID2D1StrokeStyle* GetRoundStrokeStyle();
|
||||
|
||||
// 设置文字渲染样式
|
||||
void SetTextRendererStyle(
|
||||
const Color& fill_color,
|
||||
bool has_outline,
|
||||
const Color& outline_color,
|
||||
float outline_width,
|
||||
Stroke outline_stroke
|
||||
);
|
||||
|
||||
// 获取 DPI
|
||||
static float GetDpi();
|
||||
|
||||
protected:
|
||||
D2D1_COLOR_F clear_color_;
|
||||
ID2D1Factory* factory_;
|
||||
IWICImagingFactory* imaging_factory_;
|
||||
IDWriteFactory* write_factory_;
|
||||
ID2D1StrokeStyle* miter_stroke_style_;
|
||||
ID2D1StrokeStyle* bevel_stroke_style_;
|
||||
ID2D1StrokeStyle* round_stroke_style_;
|
||||
IDWriteTextRenderer* text_renderer_;
|
||||
IDWriteTextFormat* fps_text_format_;
|
||||
IDWriteTextLayout* fps_text_layout_;
|
||||
ID2D1SolidColorBrush* solid_brush_;
|
||||
ID2D1HwndRenderTarget* render_target_;
|
||||
};
|
||||
|
||||
|
||||
// 输入设备
|
||||
class Input
|
||||
{
|
||||
public:
|
||||
Input(
|
||||
HWND hwnd
|
||||
);
|
||||
|
||||
~Input();
|
||||
|
||||
// 检测键盘某按键是否正被按下
|
||||
bool IsDown(
|
||||
KeyCode key
|
||||
);
|
||||
|
||||
// 检测鼠标按键是否正被按下
|
||||
bool IsDown(
|
||||
MouseCode code
|
||||
);
|
||||
|
||||
// 获得鼠标X轴坐标值
|
||||
float GetMouseX();
|
||||
|
||||
// 获得鼠标Y轴坐标值
|
||||
float GetMouseY();
|
||||
|
||||
// 获得鼠标坐标值
|
||||
Point GetMousePos();
|
||||
|
||||
// 获得鼠标X轴坐标增量
|
||||
float GetMouseDeltaX();
|
||||
|
||||
// 获得鼠标Y轴坐标增量
|
||||
float GetMouseDeltaY();
|
||||
|
||||
// 获得鼠标Z轴(鼠标滚轮)坐标增量
|
||||
float GetMouseDeltaZ();
|
||||
|
||||
// 刷新设备状态
|
||||
void Flush();
|
||||
|
||||
protected:
|
||||
IDirectInput8W * direct_input_;
|
||||
IDirectInputDevice8W* keyboard_device_;
|
||||
IDirectInputDevice8W* mouse_device_;
|
||||
DIMOUSESTATE mouse_state_;
|
||||
char key_buffer_[256];
|
||||
};
|
||||
|
||||
// 音频设备
|
||||
class Audio
|
||||
{
|
||||
public:
|
||||
Audio();
|
||||
|
||||
~Audio();
|
||||
|
||||
// 开启设备
|
||||
void Open();
|
||||
|
||||
// 关闭设备
|
||||
void Close();
|
||||
|
||||
// 创建音源
|
||||
HRESULT CreateVoice(
|
||||
IXAudio2SourceVoice ** voice,
|
||||
WAVEFORMATEX * wfx
|
||||
);
|
||||
|
||||
protected:
|
||||
IXAudio2 * x_audio2_;
|
||||
IXAudio2MasteringVoice* mastering_voice_;
|
||||
};
|
||||
|
||||
|
||||
// 设备
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
// 获取图形设备
|
||||
static Graphics * GetGraphics();
|
||||
|
||||
// 获取输入设备
|
||||
static Input * GetInput();
|
||||
|
||||
// 获取音频设备
|
||||
static Audio * GetAudio();
|
||||
|
||||
// 初始化
|
||||
static void Init(
|
||||
HWND hwnd
|
||||
);
|
||||
|
||||
// 销毁资源
|
||||
static void Destroy();
|
||||
};
|
||||
|
||||
|
||||
// 游戏控制器
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
// 开始时
|
||||
virtual void OnStart() = 0;
|
||||
|
||||
// 更新时
|
||||
virtual void OnUpdate(float dt) {}
|
||||
|
||||
// 退出时
|
||||
virtual void OnExit() {}
|
||||
|
||||
// 窗口关闭时
|
||||
// 返回值:返回 false 将阻止窗口关闭
|
||||
virtual bool OnClose() { return true; }
|
||||
|
||||
// 运行
|
||||
void Run();
|
||||
|
||||
// 结束
|
||||
void Quit();
|
||||
|
||||
// 设置窗口大小
|
||||
void SetSize(
|
||||
int width, /* 窗口宽度 */
|
||||
int height /* 窗口高度 */
|
||||
);
|
||||
|
||||
// 设置窗体标题
|
||||
void SetTitle(
|
||||
const std::wstring& title /* 窗体标题 */
|
||||
);
|
||||
|
||||
// 设置窗体图标
|
||||
void SetIcon(
|
||||
int resource_id /* 图标资源 ID */
|
||||
);
|
||||
|
||||
// 调试模式
|
||||
void SetDebugMode(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 获取窗体标题
|
||||
const std::wstring& GetTitle() const;
|
||||
|
||||
// 获取窗体宽度
|
||||
int GetWidth() const;
|
||||
|
||||
// 获取窗体高度
|
||||
int GetHeight() const;
|
||||
|
||||
// 获取窗体大小
|
||||
Size GetSize() const;
|
||||
|
||||
// 获取窗口句柄
|
||||
HWND GetHWnd() const;
|
||||
|
||||
// 切换场景
|
||||
void EnterScene(
|
||||
Scene * scene, /* 场景 */
|
||||
Transition * transition = nullptr /* 场景动画 */
|
||||
);
|
||||
|
||||
// 获取当前场景
|
||||
Scene * GetCurrentScene();
|
||||
|
||||
// 获取实例
|
||||
static Game * GetInstance();
|
||||
|
||||
protected:
|
||||
Game();
|
||||
|
||||
~Game();
|
||||
|
||||
E2D_DISABLE_COPY(Game);
|
||||
|
||||
private:
|
||||
// 初始化
|
||||
void Init();
|
||||
|
||||
// 根据客户区大小定位窗口
|
||||
Rect Locate(
|
||||
int width,
|
||||
int height
|
||||
);
|
||||
|
||||
// 是否正在进行场景过渡
|
||||
bool IsTransitioning() const;
|
||||
|
||||
// 更新场景内容
|
||||
void UpdateScene(
|
||||
float dt
|
||||
);
|
||||
|
||||
// 渲染场景画面
|
||||
void DrawScene();
|
||||
|
||||
// Win32 窗口消息回调程序
|
||||
static LRESULT CALLBACK WndProc(
|
||||
HWND hwnd,
|
||||
UINT msg,
|
||||
WPARAM w_param,
|
||||
LPARAM l_param
|
||||
);
|
||||
|
||||
private:
|
||||
HWND hwnd_;
|
||||
std::wstring title_;
|
||||
int width_;
|
||||
int height_;
|
||||
int icon_;
|
||||
bool debug_mode_;
|
||||
bool quit_;
|
||||
Scene* curr_scene_;
|
||||
Scene* next_scene_;
|
||||
Transition* transition_;
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_MODULE_H__
|
||||
1106
core/e2dobject.h
1106
core/e2dobject.h
File diff suppressed because it is too large
Load Diff
339
core/e2dtool.h
339
core/e2dtool.h
|
|
@ -1,339 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_TOOL_H__
|
||||
#define __E2D_TOOL_H__
|
||||
|
||||
|
||||
#include "e2dutil.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
// 音乐
|
||||
class Music
|
||||
: public Ref
|
||||
{
|
||||
public:
|
||||
Music();
|
||||
|
||||
Music(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
Music(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
virtual ~Music();
|
||||
|
||||
// 打开音乐文件
|
||||
bool Load(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 打开音乐资源
|
||||
bool Load(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 播放
|
||||
bool Play(
|
||||
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
|
||||
);
|
||||
|
||||
// 暂停
|
||||
void Pause();
|
||||
|
||||
// 继续
|
||||
void Resume();
|
||||
|
||||
// 停止
|
||||
void Stop();
|
||||
|
||||
// 关闭并回收资源
|
||||
void Close();
|
||||
|
||||
// 是否正在播放
|
||||
bool IsPlaying() const;
|
||||
|
||||
// 获取音量
|
||||
float GetVolume() const;
|
||||
|
||||
// 设置音量
|
||||
bool SetVolume(
|
||||
float volume /* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */
|
||||
);
|
||||
|
||||
// 获取 IXAudio2SourceVoice 对象
|
||||
IXAudio2SourceVoice * GetSourceVoice() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Music);
|
||||
|
||||
protected:
|
||||
bool opened_;
|
||||
bool playing_;
|
||||
UINT32 size_;
|
||||
BYTE* wave_data_;
|
||||
IXAudio2SourceVoice* voice_;
|
||||
};
|
||||
|
||||
|
||||
// 音乐播放器
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
Player();
|
||||
|
||||
~Player();
|
||||
|
||||
// 预加载音乐资源
|
||||
bool Load(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 播放音乐
|
||||
bool Play(
|
||||
const std::wstring& file_path, /* 音乐文件路径 */
|
||||
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
|
||||
);
|
||||
|
||||
// 暂停音乐
|
||||
void Pause(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 继续播放音乐
|
||||
void Resume(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 停止音乐
|
||||
void Stop(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 获取音乐播放状态
|
||||
bool IsPlaying(
|
||||
const std::wstring& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 预加载音乐资源
|
||||
bool Load(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 播放音乐
|
||||
bool Play(
|
||||
Resource& res, /* 音乐资源 */
|
||||
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
|
||||
);
|
||||
|
||||
// 暂停音乐
|
||||
void Pause(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 继续播放音乐
|
||||
void Resume(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 停止音乐
|
||||
void Stop(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 获取音乐播放状态
|
||||
bool IsPlaying(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 获取音量
|
||||
float GetVolume() const;
|
||||
|
||||
// 设置音量
|
||||
void SetVolume(
|
||||
float volume /* 1.0 为原始音量 */
|
||||
);
|
||||
|
||||
// 暂停所有音乐
|
||||
void PauseAll();
|
||||
|
||||
// 继续播放所有音乐
|
||||
void ResumeAll();
|
||||
|
||||
// 停止所有音乐
|
||||
void StopAll();
|
||||
|
||||
// 清除缓存
|
||||
static void ClearCache();
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Player);
|
||||
|
||||
protected:
|
||||
float volume_;
|
||||
|
||||
static std::map<size_t, Music*> musics_;
|
||||
};
|
||||
|
||||
|
||||
// 数据管理工具
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
Data(
|
||||
const std::wstring& key, /* 键值 */
|
||||
const std::wstring& field = L"Defalut" /* 字段名称 */
|
||||
);
|
||||
|
||||
// 该数据是否存在
|
||||
bool Exists() const;
|
||||
|
||||
// 保存 int 类型的值
|
||||
bool SaveInt(
|
||||
int value
|
||||
);
|
||||
|
||||
// 保存 float 类型的值
|
||||
bool SaveFloat(
|
||||
float value
|
||||
);
|
||||
|
||||
// 保存 double 类型的值
|
||||
bool SaveDouble(
|
||||
double value
|
||||
);
|
||||
|
||||
// 保存 bool 类型的值
|
||||
bool SaveBool(
|
||||
bool value
|
||||
);
|
||||
|
||||
// 保存 std::wstring 类型的值
|
||||
bool SaveString(
|
||||
const std::wstring& value
|
||||
);
|
||||
|
||||
// 获取 int 类型的值
|
||||
int GetInt() const;
|
||||
|
||||
// 获取 float 类型的值
|
||||
float GetFloat() const;
|
||||
|
||||
// 获取 double 类型的值
|
||||
double GetDouble() const;
|
||||
|
||||
// 获取 bool 类型的值
|
||||
bool GetBool() const;
|
||||
|
||||
// 获取 字符串 类型的值
|
||||
std::wstring GetString();
|
||||
|
||||
protected:
|
||||
std::wstring key_;
|
||||
std::wstring field_;
|
||||
const std::wstring& data_path_;
|
||||
};
|
||||
|
||||
|
||||
// 文件
|
||||
class File
|
||||
{
|
||||
public:
|
||||
File();
|
||||
|
||||
File(
|
||||
const std::wstring& file_name
|
||||
);
|
||||
|
||||
virtual ~File();
|
||||
|
||||
// 打开文件
|
||||
bool Open(
|
||||
const std::wstring& file_name
|
||||
);
|
||||
|
||||
// 文件是否存在
|
||||
bool Exists() const;
|
||||
|
||||
// 删除文件
|
||||
bool Delete();
|
||||
|
||||
// 获取文件路径
|
||||
const std::wstring& GetPath() const;
|
||||
|
||||
// 获取文件扩展名
|
||||
std::wstring GetExtension() const;
|
||||
|
||||
// 释放资源到临时文件目录
|
||||
static File Extract(
|
||||
Resource& res, /* 资源 */
|
||||
const std::wstring& dest_file_name /* 目标文件名 */
|
||||
);
|
||||
|
||||
// 添加文件搜索路径
|
||||
static void AddSearchPath(
|
||||
const std::wstring& path
|
||||
);
|
||||
|
||||
// 弹出打开文件对话框
|
||||
static File ShowOpenDialog(
|
||||
const std::wstring& title = L"打开", /* 对话框标题 */
|
||||
const std::wstring& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */
|
||||
);
|
||||
|
||||
// 弹出保存文件对话框
|
||||
static File ShowSaveDialog(
|
||||
const std::wstring& title = L"保存", /* 对话框标题 */
|
||||
const std::wstring& def_file = L"", /* 默认保存的文件名 */
|
||||
const std::wstring& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */
|
||||
);
|
||||
|
||||
protected:
|
||||
std::wstring file_path_;
|
||||
|
||||
static std::list<std::wstring> search_paths_;
|
||||
};
|
||||
|
||||
|
||||
// 路径
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
// 获取数据的默认保存路径
|
||||
static const std::wstring& GetDataPath();
|
||||
|
||||
// 获取临时文件目录
|
||||
static const std::wstring& GetTemporaryPath();
|
||||
|
||||
// 获取 LocalAppData 目录
|
||||
static const std::wstring& GetLocalAppDataPath();
|
||||
|
||||
// 获取当前程序的运行路径
|
||||
static const std::wstring& GetExeFilePath();
|
||||
};
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_TOOL_H__
|
||||
668
core/e2dutil.h
668
core/e2dutil.h
|
|
@ -1,668 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef __E2D_UTIL_H__
|
||||
#define __E2D_UTIL_H__
|
||||
|
||||
|
||||
#include "e2dmacros.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
|
||||
class Size;
|
||||
|
||||
// 坐标
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维空间的坐标: Point origin(0, 0);
|
||||
// 计算两点间距离: float distance = Point::Distance(p1, p2);
|
||||
// 坐标可以相加减: Point p = Point(10, 10) + Point(20, 20); // p 的坐标是 (30, 30)
|
||||
//
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
float x; // X 坐标
|
||||
float y; // Y 坐标
|
||||
|
||||
public:
|
||||
Point();
|
||||
|
||||
Point(
|
||||
float x,
|
||||
float y
|
||||
);
|
||||
|
||||
Point(
|
||||
const Point& other
|
||||
);
|
||||
|
||||
Point operator + (const Point & other) const;
|
||||
Point operator - (const Point & other) const;
|
||||
Point operator * (float value) const;
|
||||
Point operator / (float value) const;
|
||||
Point operator - () const;
|
||||
bool operator== (const Point& other) const;
|
||||
|
||||
explicit operator Size() const;
|
||||
|
||||
// 判断两点间距离
|
||||
static float Distance(
|
||||
const Point& p1,
|
||||
const Point& p2
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// 大小
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维矩形区域的大小: Size s(10, 5); // 宽为 10, 高为 5
|
||||
// 大小可以相加减: Size s = Size(10, 10) + Size(20, 20); // s 的大小是宽高均为 30
|
||||
//
|
||||
class Size
|
||||
{
|
||||
public:
|
||||
float width; // 宽度
|
||||
float height; // 高度
|
||||
|
||||
public:
|
||||
Size();
|
||||
|
||||
Size(
|
||||
float width,
|
||||
float height
|
||||
);
|
||||
|
||||
Size(
|
||||
const Size& other
|
||||
);
|
||||
|
||||
Size operator + (const Size & other) const;
|
||||
Size operator - (const Size & other) const;
|
||||
Size operator * (float value) const;
|
||||
Size operator / (float value) const;
|
||||
Size operator - () const;
|
||||
bool operator== (const Size& other) const;
|
||||
|
||||
explicit operator Point() const;
|
||||
};
|
||||
|
||||
|
||||
// 矩形
|
||||
//
|
||||
// Usage:
|
||||
// 表示一个二维矩形: Rect rect = Rect(10, 20, 30, 40); // 左上角坐标为 (10, 20), 宽为 30, 高为 40
|
||||
// 矩形可以通过 Point + Size 定义, Point 表示矩形左上角坐标, Size 表示矩形宽高
|
||||
// 判断一个点是否在矩形内: bool contains = rect.ContainsPoint(p);
|
||||
// 判断两矩形是否相交: bool intersects = rect1.Intersects(rect2);
|
||||
//
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
Point origin; // 左上角坐标
|
||||
Size size; // 宽度和高度
|
||||
|
||||
public:
|
||||
Rect();
|
||||
|
||||
Rect(
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height
|
||||
);
|
||||
|
||||
Rect(
|
||||
const Point& pos,
|
||||
const Size& size
|
||||
);
|
||||
|
||||
Rect(
|
||||
const Rect& other
|
||||
);
|
||||
|
||||
Rect& operator= (const Rect& other);
|
||||
|
||||
bool operator== (const Rect& rect) const;
|
||||
|
||||
// 判断点是否在矩形内
|
||||
bool ContainsPoint(
|
||||
const Point& point
|
||||
) const;
|
||||
|
||||
// 判断两矩形是否相交
|
||||
bool Intersects(
|
||||
const Rect& rect
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// 颜色
|
||||
//
|
||||
// Usage:
|
||||
// 使用枚举表示颜色: Color blue = Color::Blue;
|
||||
// 使用 RGB 表示一个颜色: Color red(1.0f, 0.0f, 0.0f);
|
||||
// 使用 RGBA 表示一个带透明度的颜色: Color not_black(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
// 使用一个 UINT 类型的值表示 RGB: Color black(0x000000);
|
||||
//
|
||||
class Color
|
||||
{
|
||||
public:
|
||||
Color();
|
||||
|
||||
Color(
|
||||
float r,
|
||||
float g,
|
||||
float b
|
||||
);
|
||||
|
||||
Color(
|
||||
float r,
|
||||
float g,
|
||||
float b,
|
||||
float alpha
|
||||
);
|
||||
|
||||
Color(
|
||||
UINT rgb
|
||||
);
|
||||
|
||||
Color(
|
||||
UINT rgb,
|
||||
float alpha
|
||||
);
|
||||
|
||||
Color(
|
||||
const D2D1_COLOR_F& color
|
||||
);
|
||||
|
||||
explicit operator D2D1_COLOR_F() const;
|
||||
|
||||
public:
|
||||
enum Value : UINT
|
||||
{
|
||||
Black = 0x000000,
|
||||
Blue = 0x0000FF,
|
||||
BlueViolet = 0x8A2BE2,
|
||||
Brown = 0xA52A2A,
|
||||
Chocolate = 0xD2691E,
|
||||
DarkBlue = 0x00008B,
|
||||
DarkGray = 0xA9A9A9,
|
||||
DarkGreen = 0x006400,
|
||||
DarkOrange = 0xFF8C00,
|
||||
DarkRed = 0x8B0000,
|
||||
DarkViolet = 0x9400D3,
|
||||
ForestGreen = 0x228B22,
|
||||
Gold = 0xFFD700,
|
||||
Gray = 0x808080,
|
||||
Green = 0x008000,
|
||||
GreenYellow = 0xADFF2F,
|
||||
LightBlue = 0xADD8E6,
|
||||
LightCyan = 0xE0FFFF,
|
||||
LightGreen = 0x90EE90,
|
||||
LightGray = 0xD3D3D3,
|
||||
LightPink = 0xFFB6C1,
|
||||
LightSeaGreen = 0x20B2AA,
|
||||
LightSkyBlue = 0x87CEFA,
|
||||
LightYellow = 0xFFFFE0,
|
||||
Orange = 0xFFA500,
|
||||
OrangeRed = 0xFF4500,
|
||||
Pink = 0xFFC0CB,
|
||||
Purple = 0x800080,
|
||||
Red = 0xFF0000,
|
||||
Silver = 0xC0C0C0,
|
||||
SkyBlue = 0x87CEEB,
|
||||
Snow = 0xFFFAFA,
|
||||
Violet = 0xEE82EE,
|
||||
Wheat = 0xF5DEB3,
|
||||
White = 0xFFFFFF,
|
||||
WhiteSmoke = 0xF5F5F5,
|
||||
Wood = 0xDEB887,
|
||||
Yellow = 0xFFFF00,
|
||||
YellowGreen = 0x9ACD32
|
||||
};
|
||||
|
||||
public:
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
|
||||
|
||||
// 方向
|
||||
enum class Direction : int
|
||||
{
|
||||
Up, /* 上 */
|
||||
Down, /* 下 */
|
||||
Left, /* 左 */
|
||||
Right /* 右 */
|
||||
};
|
||||
|
||||
|
||||
// 线条相交样式
|
||||
enum class Stroke : int
|
||||
{
|
||||
Miter = 0, /* 斜切 */
|
||||
Bevel = 1, /* 斜角 */
|
||||
Round = 2 /* 圆角 */
|
||||
};
|
||||
|
||||
|
||||
// 键盘键值
|
||||
enum class KeyCode : int
|
||||
{
|
||||
Unknown = 0,
|
||||
Up = 0xC8,
|
||||
Left = 0xCB,
|
||||
Right = 0xCD,
|
||||
Down = 0xD0,
|
||||
Enter = 0x1C,
|
||||
Space = 0x39,
|
||||
Esc = 0x01,
|
||||
Q = 0x10,
|
||||
W = 0x11,
|
||||
E = 0x12,
|
||||
R = 0x13,
|
||||
T = 0x14,
|
||||
Y = 0x15,
|
||||
U = 0x16,
|
||||
I = 0x17,
|
||||
O = 0x18,
|
||||
P = 0x19,
|
||||
A = 0x1E,
|
||||
S = 0x1F,
|
||||
D = 0x20,
|
||||
F = 0x21,
|
||||
G = 0x22,
|
||||
H = 0x23,
|
||||
J = 0x24,
|
||||
K = 0x25,
|
||||
L = 0x26,
|
||||
Z = 0x2C,
|
||||
X = 0x2D,
|
||||
C = 0x2E,
|
||||
V = 0x2F,
|
||||
B = 0x30,
|
||||
N = 0x31,
|
||||
M = 0x32,
|
||||
Num1 = 0x02,
|
||||
Num2 = 0x03,
|
||||
Num3 = 0x04,
|
||||
Num4 = 0x05,
|
||||
Num5 = 0x06,
|
||||
Num6 = 0x07,
|
||||
Num7 = 0x08,
|
||||
Num8 = 0x09,
|
||||
Num9 = 0x0A,
|
||||
Num0 = 0x0B,
|
||||
Numpad7 = 0x47,
|
||||
Numpad8 = 0x48,
|
||||
Numpad9 = 0x49,
|
||||
Numpad4 = 0x4B,
|
||||
Numpad5 = 0x4C,
|
||||
Numpad6 = 0x4D,
|
||||
Numpad1 = 0x4F,
|
||||
Numpad2 = 0x50,
|
||||
Numpad3 = 0x51,
|
||||
Numpad0 = 0x52,
|
||||
};
|
||||
|
||||
|
||||
// 鼠标键值
|
||||
enum class MouseCode : int
|
||||
{
|
||||
Left, /* 鼠标左键 */
|
||||
Right, /* 鼠标右键 */
|
||||
Middle /* 鼠标中键 */
|
||||
};
|
||||
|
||||
|
||||
// 时间段
|
||||
//
|
||||
// Usage:
|
||||
// 5 秒: Duration::Second * 5
|
||||
// 1.5 小时: Duration::Hour * 1.5
|
||||
// 3 小时 45 分 15 秒: Duration::Hour * 3 + Duration::Minute * 45 + Duration::Second * 15
|
||||
// 时间段转化为秒: float s = duration.Seconds();
|
||||
// 时间段格式化: Duration d = Duration::Parse(L"1h35m"); // 1小时35分钟
|
||||
//
|
||||
class Duration
|
||||
{
|
||||
public:
|
||||
static const Duration Millisecond; // 毫秒
|
||||
static const Duration Second; // 秒
|
||||
static const Duration Minute; // 分钟
|
||||
static const Duration Hour; // 小时
|
||||
|
||||
public:
|
||||
Duration();
|
||||
|
||||
explicit Duration(
|
||||
int milliseconds
|
||||
);
|
||||
|
||||
// 转化为毫秒
|
||||
int Milliseconds() const;
|
||||
|
||||
// 转化为秒
|
||||
float Seconds() const;
|
||||
|
||||
// 转化为分钟
|
||||
float Minutes() const;
|
||||
|
||||
// 转化为小时
|
||||
float Hours() const;
|
||||
|
||||
// 时间段格式化
|
||||
// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀
|
||||
// 例如: "300ms", "-1.5h", "2h45m"
|
||||
// 允许的时间单位有 "ms", "s", "m", "h"
|
||||
static Duration Parse(const std::wstring& str);
|
||||
|
||||
bool operator== (const Duration &) const;
|
||||
bool operator!= (const Duration &) const;
|
||||
bool operator> (const Duration &) const;
|
||||
bool operator>= (const Duration &) const;
|
||||
bool operator< (const Duration &) const;
|
||||
bool operator<= (const Duration &) const;
|
||||
|
||||
Duration operator + (const Duration &) const;
|
||||
Duration operator - (const Duration &) const;
|
||||
Duration operator - () const;
|
||||
Duration operator * (int) const;
|
||||
Duration operator * (float) const;
|
||||
Duration operator * (double) const;
|
||||
Duration operator / (int) const;
|
||||
Duration operator / (float) const;
|
||||
Duration operator / (double) const;
|
||||
|
||||
Duration& operator += (const Duration &);
|
||||
Duration& operator -= (const Duration &);
|
||||
Duration& operator *= (int);
|
||||
Duration& operator *= (float);
|
||||
Duration& operator *= (double);
|
||||
Duration& operator /= (int);
|
||||
Duration& operator /= (float);
|
||||
Duration& operator /= (double);
|
||||
|
||||
friend Duration operator* (int, const Duration &);
|
||||
friend Duration operator* (float, const Duration &);
|
||||
friend Duration operator* (double, const Duration &);
|
||||
friend Duration operator/ (int, const Duration &);
|
||||
friend Duration operator/ (float, const Duration &);
|
||||
friend Duration operator/ (double, const Duration &);
|
||||
|
||||
private:
|
||||
int milliseconds_;
|
||||
};
|
||||
|
||||
|
||||
// 时间点
|
||||
//
|
||||
// Usage:
|
||||
// 使用 Time::Now 方法获取当前时间: Time now = Time::Now();
|
||||
// 两时间相减, 得到的结果是一个 Duration 对象, 例如:
|
||||
// Time t1 = Time::Now();
|
||||
// ... // 做些什么
|
||||
// Time t2 = Time::Now();
|
||||
// 然后获取两时间相差的毫秒数:
|
||||
// int ms = (t2 - t1).Milliseconds();
|
||||
//
|
||||
class Time
|
||||
{
|
||||
public:
|
||||
Time();
|
||||
|
||||
explicit Time(
|
||||
std::chrono::steady_clock::time_point
|
||||
);
|
||||
|
||||
Time(
|
||||
const Time& other
|
||||
);
|
||||
|
||||
Time(
|
||||
Time&& other
|
||||
);
|
||||
|
||||
// 获取时间戳
|
||||
time_t GetTimeStamp() const;
|
||||
|
||||
// 是否是零时
|
||||
bool IsZero() const;
|
||||
|
||||
Time operator + (const Duration &) const;
|
||||
Time operator - (const Duration &) const;
|
||||
|
||||
Time& operator += (const Duration &);
|
||||
Time& operator -= (const Duration &);
|
||||
|
||||
Duration operator - (const Time &) const;
|
||||
|
||||
Time& operator = (const Time &) E2D_NOEXCEPT;
|
||||
Time& operator = (Time &&) E2D_NOEXCEPT;
|
||||
|
||||
// 获取当前时间
|
||||
static Time Now();
|
||||
|
||||
private:
|
||||
std::chrono::steady_clock::time_point time_;
|
||||
};
|
||||
|
||||
|
||||
// 字体
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
std::wstring family; // 字体族
|
||||
float size; // 字号
|
||||
UINT weight; // 粗细值
|
||||
bool italic; // 是否斜体
|
||||
|
||||
public:
|
||||
// 字体粗细值
|
||||
enum Weight : UINT
|
||||
{
|
||||
Thin = 100,
|
||||
ExtraLight = 200,
|
||||
Light = 300,
|
||||
Normal = 400,
|
||||
Medium = 500,
|
||||
Bold = 700,
|
||||
ExtraBold = 800,
|
||||
Black = 900,
|
||||
ExtraBlack = 950
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Font(
|
||||
const std::wstring& family = L"",
|
||||
float size = 22,
|
||||
UINT weight = Font::Weight::Normal,
|
||||
bool italic = false
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// 资源
|
||||
//
|
||||
// Usage:
|
||||
// Resource 用于获取可执行文件 (exe) 中的资源, 必须在构造函数中指定它的
|
||||
// 资源类型和名称标识符。
|
||||
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1, 那么可以这样指定该资源:
|
||||
// Resource res(MAKEINTRESOURCE(IDR_WAVE_1), L"WAVE");
|
||||
// 如果需要手动加载这份资源, 可以通过 Load 方法获取资源内容
|
||||
// if (res.Load()) {
|
||||
// LPVOID data = res.GetData();
|
||||
// DWORD size = res.GetDataSize();
|
||||
// }
|
||||
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
|
||||
//
|
||||
class Resource
|
||||
{
|
||||
public:
|
||||
Resource(
|
||||
LPCWSTR name, /* 资源名称 */
|
||||
LPCWSTR type /* 资源类型 */
|
||||
);
|
||||
|
||||
bool Load();
|
||||
|
||||
LPCWSTR GetName() const;
|
||||
|
||||
LPCWSTR GetType() const;
|
||||
|
||||
LPVOID GetData() const;
|
||||
|
||||
DWORD GetDataSize() const;
|
||||
|
||||
size_t GetHashCode() const;
|
||||
|
||||
private:
|
||||
bool loaded_;
|
||||
LPCWSTR name_;
|
||||
LPCWSTR type_;
|
||||
LPVOID data_;
|
||||
DWORD data_size_;
|
||||
};
|
||||
|
||||
|
||||
// 二维转换
|
||||
class Transform
|
||||
{
|
||||
public:
|
||||
Point position; // 坐标
|
||||
Size size; // 大小
|
||||
float scale_x; // 横向缩放
|
||||
float scale_y; // 纵向缩放
|
||||
float rotation; // 旋转
|
||||
float skew_x; // 横向倾斜角度
|
||||
float skew_y; // 纵向倾斜角度
|
||||
float pivot_x; // 支点横坐标
|
||||
float pivot_y; // 支点纵坐标
|
||||
|
||||
public:
|
||||
Transform();
|
||||
|
||||
explicit operator D2D1::Matrix3x2F() const;
|
||||
|
||||
bool operator== (const Transform& other) const;
|
||||
};
|
||||
|
||||
|
||||
// 随机数产生器
|
||||
//
|
||||
// Usage:
|
||||
// 使用静态方法 Range 获取指定范围内的一个随机数, 如:
|
||||
// int n = Random::Range(1, 5); // 获取 1~6 内的随机整数, 包含 1 和 6
|
||||
// 方法同样适用于浮点数的生成, 如:
|
||||
// double d = Random::Range(1.2, 1.5);
|
||||
// 注意, 随机数的类型取决于参数的类型。
|
||||
//
|
||||
class Random
|
||||
{
|
||||
public:
|
||||
// 取得范围内的一个整型随机数
|
||||
template<typename T>
|
||||
static inline T Range(T min, T max)
|
||||
{
|
||||
return Random::RandomInt(min, max);
|
||||
}
|
||||
|
||||
// 取得范围内的一个浮点数随机数
|
||||
static inline float Range(float min, float max)
|
||||
{
|
||||
return Random::RandomReal(min, max);
|
||||
}
|
||||
|
||||
// 取得范围内的一个浮点数随机数
|
||||
static inline double Range(double min, double max)
|
||||
{
|
||||
return Random::RandomReal(min, max);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static T RandomInt(T min, T max)
|
||||
{
|
||||
std::uniform_int_distribution<T> dist(min, max);
|
||||
return dist(Random::GetEngine());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T RandomReal(T min, T max)
|
||||
{
|
||||
std::uniform_real_distribution<T> dist(min, max);
|
||||
return dist(Random::GetEngine());
|
||||
}
|
||||
|
||||
static std::default_random_engine &GetEngine();
|
||||
};
|
||||
|
||||
|
||||
// 引用计数对象
|
||||
class Ref
|
||||
{
|
||||
public:
|
||||
Ref();
|
||||
|
||||
virtual ~Ref();
|
||||
|
||||
// 增加引用计数
|
||||
LONG Retain();
|
||||
|
||||
// 减少引用计数
|
||||
LONG Release();
|
||||
|
||||
// 获取引用计数
|
||||
LONG GetRefCount() const;
|
||||
|
||||
private:
|
||||
LONG ref_count_;
|
||||
};
|
||||
|
||||
|
||||
template<class Interface>
|
||||
inline void SafeRelease(Interface*& p)
|
||||
{
|
||||
if (p != nullptr)
|
||||
{
|
||||
p->Release();
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void ThrowIfFailed(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static char s_str[64] = {};
|
||||
sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast<unsigned int>(hr));
|
||||
throw std::runtime_error(s_str);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of easy2d namespace
|
||||
|
||||
|
||||
#endif // __E2D_UTIL_H__
|
||||
|
|
@ -36,14 +36,76 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include "e2dmacros.h"
|
||||
#include "e2dutil.h"
|
||||
#include "e2dobject.h"
|
||||
#include "e2dcomponent.h"
|
||||
#include "e2dtool.h"
|
||||
#include "e2daction.h"
|
||||
#include "e2dtransition.h"
|
||||
#include "e2dmodule.h"
|
||||
//
|
||||
// base
|
||||
//
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/base.h"
|
||||
#include "base/modules.h"
|
||||
#include "base/render.h"
|
||||
#include "base/window.h"
|
||||
#include "base/input.h"
|
||||
#include "base/audio.h"
|
||||
#include "base/time.h"
|
||||
#include "base/logs.h"
|
||||
|
||||
#include "base/Size.h"
|
||||
#include "base/Rect.hpp"
|
||||
#include "base/Font.h"
|
||||
#include "base/Color.h"
|
||||
#include "base/Resource.h"
|
||||
|
||||
#include "base/RefCounter.h"
|
||||
#include "base/Image.h"
|
||||
#include "base/Scene.h"
|
||||
#include "base/Node.h"
|
||||
#include "base/Sprite.h"
|
||||
#include "base/Task.h"
|
||||
#include "base/Text.h"
|
||||
#include "base/Action.h"
|
||||
#include "base/ActionCombined.h"
|
||||
#include "base/ActionFiniteTime.h"
|
||||
#include "base/Animation.h"
|
||||
#include "base/CallFunc.h"
|
||||
#include "base/Canvas.h"
|
||||
#include "base/Transition.h"
|
||||
|
||||
#include "base/KeyEvent.h"
|
||||
#include "base/MouseEvent.h"
|
||||
|
||||
#include "base/Game.h"
|
||||
|
||||
|
||||
//
|
||||
// math
|
||||
//
|
||||
|
||||
#include "math/scalar.hpp"
|
||||
#include "math/vector.hpp"
|
||||
#include "math/Matrix.hpp"
|
||||
#include "math/Transform.h"
|
||||
#include "math/rand.h"
|
||||
|
||||
|
||||
//
|
||||
// utils
|
||||
//
|
||||
|
||||
#include "utils/Path.h"
|
||||
#include "utils/Data.h"
|
||||
#include "utils/File.h"
|
||||
#include "utils/Transcoder.h"
|
||||
#include "utils/Music.h"
|
||||
#include "utils/Player.h"
|
||||
|
||||
|
||||
//
|
||||
// ui
|
||||
//
|
||||
|
||||
#include "ui/Button.h"
|
||||
#include "ui/Menu.h"
|
||||
|
||||
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2devent.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
KeyEvent::KeyEvent(UINT message, WPARAM w_param, LPARAM l_param)
|
||||
: message_(message)
|
||||
, w_param_(w_param)
|
||||
, l_param_(l_param)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int KeyEvent::GetCount() const
|
||||
{
|
||||
return static_cast<int>((DWORD)l_param_ & 0x0000FFFF);
|
||||
}
|
||||
|
||||
KeyEvent::Type KeyEvent::GetType() const
|
||||
{
|
||||
return Type(message_);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
class Matrix
|
||||
{
|
||||
float _11;
|
||||
float _12;
|
||||
float _21;
|
||||
float _22;
|
||||
float _31;
|
||||
float _32;
|
||||
|
||||
public:
|
||||
Matrix()
|
||||
: _11(1.f)
|
||||
, _12(0.f)
|
||||
, _21(0.f)
|
||||
, _22(1.f)
|
||||
, _31(0.f)
|
||||
, _32(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
Matrix(
|
||||
float _11,
|
||||
float _12,
|
||||
float _21,
|
||||
float _22,
|
||||
float _31,
|
||||
float _32)
|
||||
{
|
||||
this->_11 = _11;
|
||||
this->_12 = _12;
|
||||
this->_21 = _21;
|
||||
this->_22 = _22;
|
||||
this->_31 = _31;
|
||||
this->_32 = _32;
|
||||
}
|
||||
|
||||
inline Matrix operator*(const Matrix &matrix) const
|
||||
{
|
||||
return Matrix(
|
||||
_11 * matrix._11 + _12 * matrix._21,
|
||||
_11 * matrix._12 + _12 * matrix._22,
|
||||
_21 * matrix._11 + _22 * matrix._21,
|
||||
_21 * matrix._12 + _22 * matrix._22,
|
||||
_31 * matrix._11 + _32 * matrix._21 + matrix._31,
|
||||
_31 * matrix._12 + _32 * matrix._22 + matrix._32
|
||||
);
|
||||
}
|
||||
|
||||
inline Matrix& Identity()
|
||||
{
|
||||
_11 = 1.f;
|
||||
_12 = 0.f;
|
||||
_21 = 0.f;
|
||||
_22 = 1.f;
|
||||
_31 = 0.f;
|
||||
_32 = 0.f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Translate(const Vector2& v)
|
||||
{
|
||||
*this = *this * Matrix::Translation(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Scale(const Vector2& v, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Scaling(v, center);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Rotate(float angle, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Rotation(angle, center);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Matrix& Skew(float angle_x, float angle_y, const Vector2& center)
|
||||
{
|
||||
*this = *this * Matrix::Skewing(angle_x, angle_y, center);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline float Determinant() const
|
||||
{
|
||||
return (_11 * _22) - (_12 * _21);
|
||||
}
|
||||
|
||||
inline bool IsIdentity() const
|
||||
{
|
||||
return _11 == 1.f && _12 == 0.f &&
|
||||
_21 == 0.f && _22 == 1.f &&
|
||||
_31 == 0.f && _32 == 0.f;
|
||||
}
|
||||
|
||||
Vector2 Transform(const Vector2& v) const
|
||||
{
|
||||
return Vector2(
|
||||
v.x * _11 + v.y * _21 + _31,
|
||||
v.x * _12 + v.y * _22 + _32
|
||||
);
|
||||
}
|
||||
|
||||
static Matrix Translation(const Vector2& v)
|
||||
{
|
||||
return Matrix(
|
||||
1.f, 0.f,
|
||||
0.f, 1.f,
|
||||
v.x, v.y
|
||||
);
|
||||
}
|
||||
|
||||
static Matrix Translation(
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
return Translation(Vector2(x, y));
|
||||
}
|
||||
|
||||
static Matrix Scaling(
|
||||
const Vector2& v,
|
||||
const Vector2& center = Vector2())
|
||||
{
|
||||
return Matrix(
|
||||
v.x, 0.f,
|
||||
0.f, v.y,
|
||||
center.x - v.x * center.x,
|
||||
center.y - v.y * center.y
|
||||
);
|
||||
}
|
||||
|
||||
static Matrix Scaling(
|
||||
float x,
|
||||
float y,
|
||||
const Vector2& center = Vector2())
|
||||
{
|
||||
return Scaling(Vector2(x, y), center);
|
||||
}
|
||||
|
||||
static Matrix Rotation(
|
||||
float angle,
|
||||
const Vector2& center = Vector2())
|
||||
{
|
||||
float s = math::Sin(angle);
|
||||
float c = math::Cos(angle);
|
||||
return Matrix(
|
||||
c, s,
|
||||
-s, c,
|
||||
center.x * (1 - c) + center.y * s,
|
||||
center.y * (1 - c) - center.x * s
|
||||
);
|
||||
}
|
||||
|
||||
static Matrix Skewing(
|
||||
float angle_x,
|
||||
float angle_y,
|
||||
const Vector2& center = Vector2())
|
||||
{
|
||||
float tx = math::Tan(angle_x);
|
||||
float ty = math::Tan(angle_y);
|
||||
return Matrix(
|
||||
1.f, tx,
|
||||
ty, 1.f,
|
||||
-center.y * tx, -center.x * ty
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Transform.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../base/BaseTypes.h"
|
||||
#include "../base/Size.h"
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
class Transform
|
||||
{
|
||||
public:
|
||||
Point position; // 坐标
|
||||
Size size; // 大小
|
||||
float scale_x; // 横向缩放
|
||||
float scale_y; // 纵向缩放
|
||||
float rotation; // 旋转
|
||||
float skew_x; // 横向倾斜角度
|
||||
float skew_y; // 纵向倾斜角度
|
||||
float pivot_x; // 支点横坐标
|
||||
float pivot_y; // 支点纵坐标
|
||||
|
||||
public:
|
||||
Transform();
|
||||
|
||||
explicit operator D2D1::Matrix3x2F() const;
|
||||
|
||||
bool operator== (const Transform& other) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -18,12 +18,21 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "rand.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
FadeOut::FadeOut(float duration)
|
||||
: OpacityTo(duration, 0)
|
||||
namespace math
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::random_device device;
|
||||
std::default_random_engine engine(device());
|
||||
}
|
||||
|
||||
std::default_random_engine& GetRandomEngine()
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <random>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
//
|
||||
// 随机数产生器
|
||||
//
|
||||
// Usage:
|
||||
// 获取指定范围内的一个随机数, 如:
|
||||
// int n = math::Rand(1, 5); // 获取 1~6 内的随机整数, 包含 1 和 6
|
||||
// 方法同样适用于浮点数的生成, 如:
|
||||
// double d = math::Rand(1.2, 1.5);
|
||||
// 注意, 获得的随机数类型取决于参数的类型。
|
||||
//
|
||||
|
||||
std::default_random_engine& GetRandomEngine();
|
||||
|
||||
template<typename T>
|
||||
static T RandomInt(T min, T max)
|
||||
{
|
||||
std::uniform_int_distribution<T> dist(min, max);
|
||||
return dist(GetRandomEngine());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T RandomReal(T min, T max)
|
||||
{
|
||||
std::uniform_real_distribution<T> dist(min, max);
|
||||
return dist(GetRandomEngine());
|
||||
}
|
||||
|
||||
inline int Rand(int min, int max)
|
||||
{
|
||||
return RandomInt(min, max);
|
||||
}
|
||||
|
||||
inline unsigned int Rand(unsigned int min, unsigned int max)
|
||||
{
|
||||
return RandomInt(min, max);
|
||||
}
|
||||
|
||||
inline long Rand(long min, long max)
|
||||
{
|
||||
return RandomInt(min, max);
|
||||
}
|
||||
|
||||
inline unsigned long Rand(unsigned long min, unsigned long max)
|
||||
{
|
||||
return RandomInt(min, max);
|
||||
}
|
||||
|
||||
inline char Rand(char min, char max)
|
||||
{
|
||||
return static_cast<char>(
|
||||
RandomInt(static_cast<int>(min), static_cast<int>(max))
|
||||
);
|
||||
}
|
||||
|
||||
inline unsigned char Rand(unsigned char min, unsigned char max)
|
||||
{
|
||||
return static_cast<unsigned char>(
|
||||
RandomInt(static_cast<unsigned int>(min), static_cast<unsigned int>(max))
|
||||
);
|
||||
}
|
||||
|
||||
inline float Rand(float min, float max)
|
||||
{
|
||||
return RandomReal(min, max);
|
||||
}
|
||||
|
||||
inline double Range(double min, double max)
|
||||
{
|
||||
return RandomReal(min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,70 +18,47 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
#pragma once
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Point::Point()
|
||||
namespace math
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
inline int Abs(int v) { return ::abs(v); }
|
||||
|
||||
Point::Point(float x, float y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
inline float Abs(float v) { return ::fabsf(v); }
|
||||
|
||||
Point::Point(const Point & other)
|
||||
{
|
||||
x = other.x;
|
||||
y = other.y;
|
||||
}
|
||||
inline double Abs(double v) { return ::fabs(v); }
|
||||
|
||||
Point Point::operator+(const Point & p) const
|
||||
{
|
||||
return Point(x + p.x, y + p.y);
|
||||
}
|
||||
inline float Sqrt(float v) { return ::sqrtf(v); }
|
||||
|
||||
Point Point::operator-(const Point & p) const
|
||||
{
|
||||
return Point(x - p.x, y - p.y);
|
||||
}
|
||||
inline double Sqrt(double v) { return ::sqrt(v); }
|
||||
|
||||
Point Point::operator*(float value) const
|
||||
{
|
||||
return Point(x * value, y * value);
|
||||
}
|
||||
inline int Sign(int v) { return v < 0 ? -1 : 1; }
|
||||
|
||||
Point Point::operator/(float value) const
|
||||
{
|
||||
return Point(x / value, y / value);
|
||||
}
|
||||
inline float Sign(float v) { return v < 0 ? -1.f : 1.f; }
|
||||
|
||||
Point::operator Size() const
|
||||
{
|
||||
return Size(x, y);
|
||||
}
|
||||
inline double Sign(double v) { return v < 0 ? -1.0 : 1.0; }
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
inline float Sin(float v) { return ::sinf(v); }
|
||||
|
||||
Point Point::operator-() const
|
||||
{
|
||||
return Point(-x, -y);
|
||||
}
|
||||
inline double Sin(double v) { return ::sin(v); }
|
||||
|
||||
bool Point::operator==(const Point & point) const
|
||||
{
|
||||
return (x == point.x) && (y == point.y);
|
||||
inline float Cos(float v) { return ::cosf(v); }
|
||||
|
||||
inline double Cos(double v) { return ::cos(v); }
|
||||
|
||||
inline float Tan(float v) { return ::tanf(v); }
|
||||
|
||||
inline double Tan(double v) { return ::tan(v); }
|
||||
|
||||
inline float Ceil(float v) { return ceil(v); }
|
||||
|
||||
inline double Ceil(double v) { return ceil(v); }
|
||||
|
||||
inline float Floor(float v) { return floor(v); }
|
||||
|
||||
inline double Floor(double v) { return floor(v); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "scalar.hpp"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
class Vector2
|
||||
{
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
|
||||
public:
|
||||
Vector2() : x(0.f), y(0.f) {}
|
||||
|
||||
Vector2(
|
||||
float x,
|
||||
float y
|
||||
)
|
||||
: x(x)
|
||||
, y(y)
|
||||
{}
|
||||
|
||||
Vector2(
|
||||
const Vector2& other
|
||||
)
|
||||
: x(other.x)
|
||||
, y(other.y)
|
||||
{}
|
||||
|
||||
inline Vector2 operator + (const Vector2 & other) const
|
||||
{
|
||||
return Vector2(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
inline Vector2 operator - (const Vector2 & other) const
|
||||
{
|
||||
return Vector2(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
inline Vector2 operator * (float value) const
|
||||
{
|
||||
return Vector2(x * value, y * value);
|
||||
}
|
||||
|
||||
inline Vector2 operator / (float value) const
|
||||
{
|
||||
return Vector2(x / value, y / value);
|
||||
}
|
||||
|
||||
inline Vector2 operator - () const
|
||||
{
|
||||
return Vector2(-x, -y);
|
||||
}
|
||||
|
||||
inline bool operator== (const Vector2& other) const
|
||||
{
|
||||
return (x == other.x) && (y == other.y);
|
||||
}
|
||||
|
||||
inline float Length() const { return math::Sqrt(x * x + y * y); }
|
||||
|
||||
inline float Distance(const Vector2& v)
|
||||
{
|
||||
return Vector2(x - v.x, y - v.y).Length();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,625 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dtool.h"
|
||||
#include "..\e2dtransition.h"
|
||||
#include <thread>
|
||||
#include <imm.h>
|
||||
#pragma comment (lib ,"imm32.lib")
|
||||
|
||||
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
|
||||
#define REGISTER_CLASS L"Easy2DApp"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Game * instance = nullptr;
|
||||
}
|
||||
|
||||
Game * Game::GetInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
Game::Game()
|
||||
: hwnd_(nullptr)
|
||||
, quit_(true)
|
||||
, curr_scene_(nullptr)
|
||||
, next_scene_(nullptr)
|
||||
, transition_(nullptr)
|
||||
, title_(L"Easy2D Game")
|
||||
, width_(640)
|
||||
, height_(480)
|
||||
, icon_(0)
|
||||
, debug_mode_(false)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
throw std::runtime_error("同时只能存在一个游戏实例");
|
||||
}
|
||||
instance = this;
|
||||
|
||||
::CoInitialize(nullptr);
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
SafeRelease(transition_);
|
||||
SafeRelease(curr_scene_);
|
||||
SafeRelease(next_scene_);
|
||||
|
||||
Image::ClearCache();
|
||||
Player::ClearCache();
|
||||
Device::Destroy();
|
||||
|
||||
if (hwnd_)
|
||||
{
|
||||
::DestroyWindow(hwnd_);
|
||||
}
|
||||
|
||||
instance = nullptr;
|
||||
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
void Game::Run()
|
||||
{
|
||||
// 初始化
|
||||
Init();
|
||||
|
||||
// 开始
|
||||
OnStart();
|
||||
|
||||
// 刷新场景
|
||||
if (next_scene_)
|
||||
{
|
||||
next_scene_->OnEnter();
|
||||
curr_scene_ = next_scene_;
|
||||
next_scene_ = nullptr;
|
||||
}
|
||||
::ShowWindow(hwnd_, SW_SHOWNORMAL);
|
||||
::UpdateWindow(hwnd_);
|
||||
|
||||
// 运行
|
||||
const int min_interval = 5;
|
||||
Time last = Time::Now();
|
||||
MSG msg = { 0 };
|
||||
|
||||
while (!quit_)
|
||||
{
|
||||
auto now = Time::Now();
|
||||
auto dur = now - last;
|
||||
|
||||
if (dur.Milliseconds() > min_interval)
|
||||
{
|
||||
float dt = (now - last).Seconds();
|
||||
last = now;
|
||||
|
||||
Device::GetInput()->Flush();
|
||||
OnUpdate(dt);
|
||||
UpdateScene(dt);
|
||||
DrawScene();
|
||||
|
||||
while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ID2D1HwndRenderTarget 开启了垂直同步,在渲染时会等待显示器刷新,
|
||||
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
|
||||
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
|
||||
int wait = min_interval - dur.Milliseconds();
|
||||
if (wait > 1)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::Quit()
|
||||
{
|
||||
quit_ = true;
|
||||
}
|
||||
|
||||
void Game::EnterScene(Scene * scene, Transition * transition)
|
||||
{
|
||||
if (scene == nullptr)
|
||||
{
|
||||
E2D_WARNING("Next scene is null pointer!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr_scene_ == scene) { return; }
|
||||
|
||||
if (next_scene_)
|
||||
{
|
||||
next_scene_->Release();
|
||||
}
|
||||
next_scene_ = scene;
|
||||
next_scene_->Retain();
|
||||
|
||||
if (transition)
|
||||
{
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Stop();
|
||||
transition_->Release();
|
||||
}
|
||||
transition_ = transition;
|
||||
transition_->Retain();
|
||||
|
||||
transition_->Init(curr_scene_, next_scene_, this);
|
||||
}
|
||||
}
|
||||
|
||||
Scene * Game::GetCurrentScene()
|
||||
{
|
||||
return curr_scene_;
|
||||
}
|
||||
|
||||
bool Game::IsTransitioning() const
|
||||
{
|
||||
return transition_ != nullptr;
|
||||
}
|
||||
|
||||
void Game::UpdateScene(float dt)
|
||||
{
|
||||
auto update = [&](Scene * scene) -> void
|
||||
{
|
||||
if (scene)
|
||||
{
|
||||
scene->OnUpdate(dt);
|
||||
Node * root = scene->GetRoot();
|
||||
if (root)
|
||||
{
|
||||
root->UpdateChildren(dt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
update(curr_scene_);
|
||||
update(next_scene_);
|
||||
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Update();
|
||||
|
||||
if (transition_->IsDone())
|
||||
{
|
||||
transition_->Release();
|
||||
transition_ = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (next_scene_)
|
||||
{
|
||||
if (curr_scene_)
|
||||
{
|
||||
curr_scene_->OnExit();
|
||||
curr_scene_->Release();
|
||||
}
|
||||
|
||||
next_scene_->OnEnter();
|
||||
|
||||
curr_scene_ = next_scene_;
|
||||
next_scene_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::DrawScene()
|
||||
{
|
||||
auto graphics = Device::GetGraphics();
|
||||
graphics->BeginDraw();
|
||||
|
||||
if (transition_)
|
||||
{
|
||||
transition_->Draw();
|
||||
}
|
||||
else if (curr_scene_)
|
||||
{
|
||||
curr_scene_->Draw();
|
||||
}
|
||||
|
||||
if (debug_mode_)
|
||||
{
|
||||
if (curr_scene_ && curr_scene_->GetRoot())
|
||||
{
|
||||
graphics->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
graphics->GetSolidBrush()->SetOpacity(1.f);
|
||||
curr_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
if (next_scene_ && next_scene_->GetRoot())
|
||||
{
|
||||
graphics->GetRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
graphics->GetSolidBrush()->SetOpacity(1.f);
|
||||
next_scene_->GetRoot()->DrawBorder();
|
||||
}
|
||||
|
||||
graphics->DrawDebugInfo();
|
||||
}
|
||||
graphics->EndDraw();
|
||||
}
|
||||
|
||||
void Game::Init()
|
||||
{
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
WNDCLASSEX wcex = { 0 };
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.lpszClassName = REGISTER_CLASS;
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||
wcex.lpfnWndProc = Game::WndProc;
|
||||
wcex.hIcon = nullptr;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
||||
wcex.hInstance = hinstance;
|
||||
wcex.hbrBackground = nullptr;
|
||||
wcex.lpszMenuName = nullptr;
|
||||
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
|
||||
|
||||
if (icon_ != 0)
|
||||
{
|
||||
wcex.hIcon = (HICON)::LoadImage(
|
||||
hinstance,
|
||||
MAKEINTRESOURCE(icon_),
|
||||
IMAGE_ICON,
|
||||
0,
|
||||
0,
|
||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||
);
|
||||
}
|
||||
|
||||
// 注册窗口类
|
||||
::RegisterClassEx(&wcex);
|
||||
|
||||
// 计算窗口大小
|
||||
Rect client_rect = Locate(width_, height_);
|
||||
|
||||
// 创建窗口
|
||||
hwnd_ = ::CreateWindowEx(
|
||||
NULL,
|
||||
REGISTER_CLASS,
|
||||
title_.c_str(),
|
||||
WINDOW_STYLE,
|
||||
int(client_rect.origin.x),
|
||||
int(client_rect.origin.y),
|
||||
int(client_rect.size.width),
|
||||
int(client_rect.size.height),
|
||||
nullptr,
|
||||
nullptr,
|
||||
hinstance,
|
||||
this
|
||||
);
|
||||
|
||||
if (hwnd_ == nullptr)
|
||||
{
|
||||
::UnregisterClass(REGISTER_CLASS, hinstance);
|
||||
throw std::runtime_error("Create window failed");
|
||||
return;
|
||||
}
|
||||
|
||||
::SetWindowLongPtrW(
|
||||
hwnd_,
|
||||
GWLP_USERDATA,
|
||||
PtrToUlong(this)
|
||||
);
|
||||
|
||||
// 初始化设备
|
||||
Device::Init(hwnd_);
|
||||
|
||||
// 禁用输入法
|
||||
::ImmAssociateContext(hwnd_, nullptr);
|
||||
|
||||
// 若开启了调试模式,打开控制台
|
||||
HWND console = ::GetConsoleWindow();
|
||||
// 关闭控制台
|
||||
if (debug_mode_)
|
||||
{
|
||||
if (console)
|
||||
{
|
||||
::ShowWindow(console, SW_SHOWNORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 显示一个新控制台
|
||||
if (::AllocConsole())
|
||||
{
|
||||
console = ::GetConsoleWindow();
|
||||
// 重定向输入输出
|
||||
FILE * stdoutStream, *stdinStream, *stderrStream;
|
||||
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
||||
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
||||
freopen_s(&stderrStream, "conout$", "w+t", stderr);
|
||||
// 禁用控制台关闭按钮
|
||||
HMENU hmenu = ::GetSystemMenu(console, FALSE);
|
||||
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (console)
|
||||
{
|
||||
::ShowWindow(console, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
quit_ = false;
|
||||
}
|
||||
|
||||
Rect Game::Locate(int width, int height)
|
||||
{
|
||||
int max_width = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
int max_height = ::GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
float dpi = Graphics::GetDpi();
|
||||
RECT rect = { 0, 0, LONG(ceil(width * dpi / 96.f)), LONG(ceil(height * dpi / 96.f)) };
|
||||
|
||||
// 计算合适的窗口大小
|
||||
::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL);
|
||||
width = static_cast<int>(rect.right - rect.left);
|
||||
height = static_cast<int>(rect.bottom - rect.top);
|
||||
|
||||
// 当输入的窗口大小比分辨率大时,给出警告
|
||||
E2D_WARNING_IF(max_width < width || max_height < height, "The window Is larger than screen!");
|
||||
width = std::min(width, max_width);
|
||||
height = std::min(height, max_height);
|
||||
|
||||
return Rect(
|
||||
static_cast<float>((max_width - width) / 2),
|
||||
static_cast<float>((max_height - height) / 2),
|
||||
static_cast<float>(width),
|
||||
static_cast<float>(height)
|
||||
);
|
||||
}
|
||||
|
||||
int Game::GetWidth() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
int Game::GetHeight() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
Size Game::GetSize() const
|
||||
{
|
||||
return Size(
|
||||
static_cast<float>(width_),
|
||||
static_cast<float>(height_)
|
||||
);
|
||||
}
|
||||
|
||||
HWND Game::GetHWnd() const
|
||||
{
|
||||
return hwnd_;
|
||||
}
|
||||
|
||||
const std::wstring& Game::GetTitle() const
|
||||
{
|
||||
return title_;
|
||||
}
|
||||
|
||||
void Game::SetSize(int width, int height)
|
||||
{
|
||||
if (width_ == width && height_ == height)
|
||||
return;
|
||||
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
if (hwnd_)
|
||||
{
|
||||
Rect rect = Locate(width, height);
|
||||
::MoveWindow(
|
||||
hwnd_,
|
||||
int(rect.origin.x),
|
||||
int(rect.origin.y),
|
||||
int(rect.size.width),
|
||||
int(rect.size.height),
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::SetTitle(const std::wstring& title)
|
||||
{
|
||||
title_ = title;
|
||||
|
||||
if (hwnd_)
|
||||
{
|
||||
::SetWindowText(hwnd_, title.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Game::SetIcon(int resource_id)
|
||||
{
|
||||
icon_ = resource_id;
|
||||
|
||||
if (hwnd_)
|
||||
{
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
HICON icon = (HICON)::LoadImage(
|
||||
hinstance,
|
||||
MAKEINTRESOURCE(resource_id),
|
||||
IMAGE_ICON,
|
||||
0,
|
||||
0,
|
||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||
);
|
||||
|
||||
::SendMessage(hwnd_, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
||||
::SendMessage(hwnd_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::SetDebugMode(bool enabled)
|
||||
{
|
||||
debug_mode_ = enabled;
|
||||
}
|
||||
|
||||
|
||||
LRESULT Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
LRESULT result = 0;
|
||||
bool was_handled = false;
|
||||
Game * game = reinterpret_cast<Game*>(
|
||||
static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))
|
||||
);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
|
||||
// 处理鼠标消息
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
if (game->IsTransitioning())
|
||||
break;
|
||||
|
||||
auto curr_scene = game->GetCurrentScene();
|
||||
if (curr_scene)
|
||||
{
|
||||
curr_scene->Dispatch(MouseEvent(msg, w_param, l_param));
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 处理按键消息
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
if (game->IsTransitioning())
|
||||
break;
|
||||
|
||||
auto curr_scene = game->GetCurrentScene();
|
||||
if (curr_scene)
|
||||
{
|
||||
curr_scene->Dispatch(KeyEvent(msg, w_param, l_param));
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 处理窗口大小变化消息
|
||||
case WM_SIZE:
|
||||
{
|
||||
UINT width = LOWORD(l_param);
|
||||
UINT height = HIWORD(l_param);
|
||||
|
||||
if (w_param == SIZE_RESTORED)
|
||||
{
|
||||
float dpi = Graphics::GetDpi();
|
||||
game->width_ = static_cast<int>(width * 96.f / dpi);
|
||||
game->height_ = static_cast<int>(height * 96.f / dpi);
|
||||
}
|
||||
|
||||
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
|
||||
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
|
||||
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
|
||||
auto render_target = Device::GetGraphics()->GetRenderTarget();
|
||||
if (render_target)
|
||||
{
|
||||
render_target->Resize(D2D1::SizeU(width, height));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 处理窗口标题变化消息
|
||||
case WM_SETTEXT:
|
||||
{
|
||||
game->title_ = (const wchar_t*)l_param;
|
||||
}
|
||||
break;
|
||||
|
||||
// 处理分辨率变化消息
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
// 重绘客户区
|
||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 重绘窗口
|
||||
case WM_PAINT:
|
||||
{
|
||||
game->DrawScene();
|
||||
::ValidateRect(hwnd, nullptr);
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 窗口关闭消息
|
||||
case WM_CLOSE:
|
||||
{
|
||||
if (game->OnClose())
|
||||
{
|
||||
game->Quit();
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
// 窗口销毁消息
|
||||
case WM_DESTROY:
|
||||
{
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
result = 1;
|
||||
was_handled = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (!was_handled)
|
||||
{
|
||||
result = ::DefWindowProc(hwnd, msg, w_param, l_param);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,831 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// TextRenderer
|
||||
//-------------------------------------------------------
|
||||
|
||||
class TextRenderer
|
||||
: public IDWriteTextRenderer
|
||||
{
|
||||
public:
|
||||
static HRESULT Create(
|
||||
IDWriteTextRenderer** ppTextRenderer,
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush
|
||||
);
|
||||
|
||||
STDMETHOD_(void, SetTextStyle)(
|
||||
CONST D2D1_COLOR_F &fillColor,
|
||||
BOOL outline,
|
||||
CONST D2D1_COLOR_F &outline_color,
|
||||
FLOAT outline_width,
|
||||
D2D1_LINE_JOIN outlineJoin
|
||||
);
|
||||
|
||||
STDMETHOD(DrawGlyphRun)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
__in DWRITE_GLYPH_RUN const* glyphRun,
|
||||
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawUnderline)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_UNDERLINE const* underline,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawStrikethrough)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_STRIKETHROUGH const* strikethrough,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(DrawInlineObject)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL IsSideways,
|
||||
BOOL IsRightToLeft,
|
||||
IUnknown* clientDrawingEffect
|
||||
);
|
||||
|
||||
STDMETHOD(IsPixelSnappingDisabled)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out BOOL* isDisabled
|
||||
);
|
||||
|
||||
STDMETHOD(GetCurrentTransform)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out DWRITE_MATRIX* transform
|
||||
);
|
||||
|
||||
STDMETHOD(GetPixelsPerDip)(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out FLOAT* pixelsPerDip
|
||||
);
|
||||
|
||||
public:
|
||||
unsigned long STDMETHODCALLTYPE AddRef();
|
||||
unsigned long STDMETHODCALLTYPE Release();
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
IID const& riid,
|
||||
void** ppvObject
|
||||
);
|
||||
|
||||
private:
|
||||
TextRenderer(
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush
|
||||
);
|
||||
|
||||
~TextRenderer();
|
||||
|
||||
private:
|
||||
unsigned long cRefCount_;
|
||||
D2D1_COLOR_F sFillColor_;
|
||||
D2D1_COLOR_F sOutlineColor_;
|
||||
FLOAT fOutlineWidth;
|
||||
BOOL bShowOutline_;
|
||||
ID2D1Factory* pD2DFactory_;
|
||||
ID2D1HwndRenderTarget* pRT_;
|
||||
ID2D1SolidColorBrush* pBrush_;
|
||||
ID2D1StrokeStyle* pCurrStrokeStyle_;
|
||||
};
|
||||
|
||||
TextRenderer::TextRenderer(ID2D1Factory* pD2DFactory, ID2D1HwndRenderTarget* pRT, ID2D1SolidColorBrush* pBrush)
|
||||
: cRefCount_(0)
|
||||
, pD2DFactory_(pD2DFactory)
|
||||
, pRT_(pRT)
|
||||
, pBrush_(pBrush)
|
||||
, sFillColor_()
|
||||
, sOutlineColor_()
|
||||
, fOutlineWidth(1)
|
||||
, bShowOutline_(TRUE)
|
||||
, pCurrStrokeStyle_(nullptr)
|
||||
{
|
||||
pD2DFactory->AddRef();
|
||||
pRT->AddRef();
|
||||
pBrush->AddRef();
|
||||
}
|
||||
|
||||
TextRenderer::~TextRenderer()
|
||||
{
|
||||
SafeRelease(pD2DFactory_);
|
||||
SafeRelease(pRT_);
|
||||
SafeRelease(pBrush_);
|
||||
}
|
||||
|
||||
HRESULT TextRenderer::Create(
|
||||
IDWriteTextRenderer** ppTextRenderer,
|
||||
ID2D1Factory* pD2DFactory,
|
||||
ID2D1HwndRenderTarget* pRT,
|
||||
ID2D1SolidColorBrush* pBrush
|
||||
)
|
||||
{
|
||||
*ppTextRenderer = new (std::nothrow) TextRenderer(pD2DFactory, pRT, pBrush);
|
||||
if (*ppTextRenderer)
|
||||
{
|
||||
(*ppTextRenderer)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) TextRenderer::SetTextStyle(
|
||||
CONST D2D1_COLOR_F &fillColor,
|
||||
BOOL outline,
|
||||
CONST D2D1_COLOR_F &outline_color,
|
||||
FLOAT outline_width,
|
||||
D2D1_LINE_JOIN outlineJoin
|
||||
)
|
||||
{
|
||||
sFillColor_ = fillColor;
|
||||
bShowOutline_ = outline;
|
||||
sOutlineColor_ = outline_color;
|
||||
fOutlineWidth = 2 * outline_width;
|
||||
|
||||
switch (outlineJoin)
|
||||
{
|
||||
case D2D1_LINE_JOIN_MITER:
|
||||
pCurrStrokeStyle_ = Device::GetGraphics()->GetMiterStrokeStyle();
|
||||
break;
|
||||
case D2D1_LINE_JOIN_BEVEL:
|
||||
pCurrStrokeStyle_ = Device::GetGraphics()->GetBevelStrokeStyle();
|
||||
break;
|
||||
case D2D1_LINE_JOIN_ROUND:
|
||||
pCurrStrokeStyle_ = Device::GetGraphics()->GetRoundStrokeStyle();
|
||||
break;
|
||||
default:
|
||||
pCurrStrokeStyle_ = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawGlyphRun(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
__in DWRITE_GLYPH_RUN const* glyphRun,
|
||||
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ID2D1PathGeometry* pPathGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreatePathGeometry(
|
||||
&pPathGeometry
|
||||
);
|
||||
|
||||
ID2D1GeometrySink* pSink = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pPathGeometry->Open(
|
||||
&pSink
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = glyphRun->fontFace->GetGlyphRunOutline(
|
||||
glyphRun->fontEmSize,
|
||||
glyphRun->glyphIndices,
|
||||
glyphRun->glyphAdvances,
|
||||
glyphRun->glyphOffsets,
|
||||
glyphRun->glyphCount,
|
||||
glyphRun->isSideways,
|
||||
glyphRun->bidiLevel % 2,
|
||||
pSink
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSink->Close();
|
||||
}
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pPathGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pPathGeometry);
|
||||
SafeRelease(pSink);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawUnderline(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_UNDERLINE const* underline,
|
||||
IUnknown* clientDrawingEffect
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D2D1_RECT_F rect = D2D1::RectF(
|
||||
0,
|
||||
underline->offset,
|
||||
underline->width,
|
||||
underline->offset + underline->thickness
|
||||
);
|
||||
|
||||
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreateRectangleGeometry(
|
||||
&rect,
|
||||
&pRectangleGeometry
|
||||
);
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pRectangleGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pRectangleGeometry);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawStrikethrough(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT baselineOriginX,
|
||||
FLOAT baselineOriginY,
|
||||
__in DWRITE_STRIKETHROUGH const* strikethrough,
|
||||
IUnknown* clientDrawingEffect
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D2D1_RECT_F rect = D2D1::RectF(
|
||||
0,
|
||||
strikethrough->offset,
|
||||
strikethrough->width,
|
||||
strikethrough->offset + strikethrough->thickness
|
||||
);
|
||||
|
||||
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
|
||||
hr = pD2DFactory_->CreateRectangleGeometry(
|
||||
&rect,
|
||||
&pRectangleGeometry
|
||||
);
|
||||
|
||||
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
baselineOriginX, baselineOriginY
|
||||
);
|
||||
|
||||
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pD2DFactory_->CreateTransformedGeometry(
|
||||
pRectangleGeometry,
|
||||
&matrix,
|
||||
&pTransformedGeometry
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && bShowOutline_)
|
||||
{
|
||||
pBrush_->SetColor(sOutlineColor_);
|
||||
|
||||
pRT_->DrawGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_,
|
||||
fOutlineWidth,
|
||||
pCurrStrokeStyle_
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pBrush_->SetColor(sFillColor_);
|
||||
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry,
|
||||
pBrush_
|
||||
);
|
||||
}
|
||||
|
||||
SafeRelease(pRectangleGeometry);
|
||||
SafeRelease(pTransformedGeometry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawInlineObject(
|
||||
__maybenull void* clientDrawingContext,
|
||||
FLOAT originX,
|
||||
FLOAT originY,
|
||||
IDWriteInlineObject* inlineObject,
|
||||
BOOL IsSideways,
|
||||
BOOL IsRightToLeft,
|
||||
IUnknown* clientDrawingEffect
|
||||
)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&cRefCount_);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(unsigned long) TextRenderer::Release()
|
||||
{
|
||||
unsigned long newCount = InterlockedDecrement(&cRefCount_);
|
||||
|
||||
if (newCount == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return newCount;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::IsPixelSnappingDisabled(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out BOOL* isDisabled
|
||||
)
|
||||
{
|
||||
*isDisabled = FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::GetCurrentTransform(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out DWRITE_MATRIX* transform
|
||||
)
|
||||
{
|
||||
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::GetPixelsPerDip(
|
||||
__maybenull void* clientDrawingContext,
|
||||
__out FLOAT* pixelsPerDip
|
||||
)
|
||||
{
|
||||
float x, yUnused;
|
||||
|
||||
pRT_->GetDpi(&x, &yUnused);
|
||||
*pixelsPerDip = x / 96;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::QueryInterface(
|
||||
IID const& riid,
|
||||
void** ppvObject
|
||||
)
|
||||
{
|
||||
if (__uuidof(IDWriteTextRenderer) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else if (__uuidof(IDWritePixelSnapping) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else if (__uuidof(IUnknown) == riid)
|
||||
{
|
||||
*ppvObject = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppvObject = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Graphics
|
||||
//-------------------------------------------------------
|
||||
|
||||
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_
|
||||
)
|
||||
);
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
void Graphics::BeginDraw()
|
||||
{
|
||||
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,
|
||||
text_renderer_,
|
||||
10,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ID2D1HwndRenderTarget * Graphics::GetRenderTarget() const
|
||||
{
|
||||
return render_target_;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dmodule.h"
|
||||
#include "..\e2dtool.h"
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Input::Input(HWND hwnd)
|
||||
: direct_input_(nullptr)
|
||||
, keyboard_device_(nullptr)
|
||||
, mouse_device_(nullptr)
|
||||
{
|
||||
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_)
|
||||
{
|
||||
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_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse_device_)
|
||||
{
|
||||
HRESULT hr = mouse_device_->Poll();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = mouse_device_->Acquire();
|
||||
while (hr == DIERR_INPUTLOST)
|
||||
hr = mouse_device_->Acquire();
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_device_->GetDeviceState(
|
||||
sizeof(mouse_state_),
|
||||
(void**)&mouse_state_
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Input::IsDown(KeyCode key)
|
||||
{
|
||||
if (key_buffer_[static_cast<int>(key)] & 0x80)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::IsDown(MouseCode code)
|
||||
{
|
||||
if (mouse_state_.rgbButtons[static_cast<int>(code)] & 0x80)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
float Input::GetMouseX()
|
||||
{
|
||||
return GetMousePos().x;
|
||||
}
|
||||
|
||||
float Input::GetMouseY()
|
||||
{
|
||||
return GetMousePos().y;
|
||||
}
|
||||
|
||||
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 Input::GetMouseDeltaX()
|
||||
{
|
||||
return (float)mouse_state_.lX;
|
||||
}
|
||||
|
||||
float Input::GetMouseDeltaY()
|
||||
{
|
||||
return (float)mouse_state_.lY;
|
||||
}
|
||||
|
||||
float Input::GetMouseDeltaZ()
|
||||
{
|
||||
return (float)mouse_state_.lZ;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,560 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtool.h"
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
|
||||
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_;
|
||||
|
||||
public:
|
||||
Transcoder()
|
||||
: wave_format_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~Transcoder()
|
||||
{
|
||||
if (wave_format_)
|
||||
{
|
||||
::CoTaskMemFree(wave_format_);
|
||||
wave_format_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
WAVEFORMATEX* GetWaveFormatEx()
|
||||
{
|
||||
return wave_format_;
|
||||
}
|
||||
|
||||
bool LoadMediaFile(LPCWSTR file_path, BYTE** wave_data, UINT32* wave_data_size)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
IMFSourceReader* reader = nullptr;
|
||||
|
||||
hr = MFCreateSourceReaderFromURL(
|
||||
file_path,
|
||||
nullptr,
|
||||
&reader
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ReadSource(reader, wave_data, wave_data_size);
|
||||
}
|
||||
|
||||
SafeRelease(reader);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool LoadMediaResource(Resource& res, BYTE** wave_data, UINT32* wave_data_size)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
IStream* stream = nullptr;
|
||||
IMFByteStream* byte_stream = nullptr;
|
||||
IMFSourceReader* reader = nullptr;
|
||||
|
||||
if (!res.Load()) { return false; }
|
||||
|
||||
stream = SHCreateMemStream(
|
||||
static_cast<const BYTE*>(res.GetData()),
|
||||
static_cast<UINT>(res.GetDataSize())
|
||||
);
|
||||
|
||||
if (stream == nullptr)
|
||||
{
|
||||
TraceError(L"SHCreateMemStream");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = MFCreateMFByteStreamOnStream(stream, &byte_stream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = MFCreateSourceReaderFromByteStream(
|
||||
byte_stream,
|
||||
nullptr,
|
||||
&reader
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ReadSource(reader, wave_data, wave_data_size);
|
||||
}
|
||||
|
||||
SafeRelease(stream);
|
||||
SafeRelease(byte_stream);
|
||||
SafeRelease(reader);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
HRESULT ReadSource(IMFSourceReader* reader, BYTE** wave_data, UINT32* wave_data_size)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD max_stream_size = 0;
|
||||
|
||||
IMFMediaType* partial_type = nullptr;
|
||||
IMFMediaType* uncompressed_type = nullptr;
|
||||
|
||||
hr = MFCreateMediaType(&partial_type);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = partial_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = partial_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
|
||||
}
|
||||
|
||||
// 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = reader->SetCurrentMediaType(
|
||||
MF_SOURCE_READER_FIRST_AUDIO_STREAM,
|
||||
0,
|
||||
partial_type
|
||||
);
|
||||
}
|
||||
|
||||
// 从 IMFMediaType 中获取 WAVEFORMAT 结构
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = reader->GetCurrentMediaType(
|
||||
MF_SOURCE_READER_FIRST_AUDIO_STREAM,
|
||||
&uncompressed_type
|
||||
);
|
||||
}
|
||||
|
||||
// 指定音频流
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = reader->SetStreamSelection(
|
||||
MF_SOURCE_READER_FIRST_AUDIO_STREAM,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// 获取 WAVEFORMAT 数据
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 size = 0;
|
||||
hr = MFCreateWaveFormatExFromMFMediaType(
|
||||
uncompressed_type,
|
||||
&wave_format_,
|
||||
&size
|
||||
);
|
||||
}
|
||||
|
||||
// 估算音频流大小
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PROPVARIANT prop;
|
||||
PropVariantInit(&prop);
|
||||
|
||||
hr = reader->GetPresentationAttribute(
|
||||
MF_SOURCE_READER_MEDIASOURCE,
|
||||
MF_PD_DURATION,
|
||||
&prop
|
||||
);
|
||||
|
||||
LONGLONG duration = prop.uhVal.QuadPart;
|
||||
max_stream_size = static_cast<DWORD>(
|
||||
(duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1
|
||||
);
|
||||
PropVariantClear(&prop);
|
||||
}
|
||||
|
||||
// 读取音频数据
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD flags = 0;
|
||||
DWORD position = 0;
|
||||
|
||||
IMFSample* sample = nullptr;
|
||||
IMFMediaBuffer* buffer = nullptr;
|
||||
BYTE* data = new (std::nothrow) BYTE[max_stream_size];
|
||||
|
||||
if (data == nullptr)
|
||||
{
|
||||
TraceError(L"Low memory");
|
||||
hr = E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
hr = reader->ReadSample(
|
||||
MF_SOURCE_READER_FIRST_AUDIO_STREAM,
|
||||
0,
|
||||
nullptr,
|
||||
&flags,
|
||||
nullptr,
|
||||
&sample
|
||||
);
|
||||
|
||||
if (flags & MF_SOURCE_READERF_ENDOFSTREAM) { break; }
|
||||
|
||||
if (sample == nullptr) { continue; }
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = sample->ConvertToContiguousBuffer(&buffer);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
BYTE *audio_data = nullptr;
|
||||
DWORD sample_buffer_length = 0;
|
||||
|
||||
hr = buffer->Lock(
|
||||
&audio_data,
|
||||
nullptr,
|
||||
&sample_buffer_length
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (DWORD i = 0; i < sample_buffer_length; i++)
|
||||
{
|
||||
data[position++] = audio_data[i];
|
||||
}
|
||||
hr = buffer->Unlock();
|
||||
}
|
||||
}
|
||||
SafeRelease(buffer);
|
||||
}
|
||||
SafeRelease(sample);
|
||||
|
||||
if (FAILED(hr)) { break; }
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*wave_data = data;
|
||||
*wave_data_size = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SafeRelease(partial_type);
|
||||
SafeRelease(uncompressed_type);
|
||||
|
||||
return hr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Music
|
||||
//-------------------------------------------------------
|
||||
|
||||
Music::Music()
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Music::Music(const std::wstring& file_path)
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
Load(file_path);
|
||||
}
|
||||
|
||||
Music::Music(Resource& res)
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
Load(res);
|
||||
}
|
||||
|
||||
Music::~Music()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool Music::Load(const std::wstring & file_path)
|
||||
{
|
||||
if (opened_)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
File music_file;
|
||||
if (!music_file.Open(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_)
|
||||
{
|
||||
delete[] wave_data_;
|
||||
wave_data_ = nullptr;
|
||||
}
|
||||
TraceError(L"Create source voice error", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
opened_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Music::Load(Resource& res)
|
||||
{
|
||||
if (opened_)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
Transcoder transcoder;
|
||||
if (!transcoder.LoadMediaResource(res, &wave_data_, &size_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = Device::GetAudio()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (wave_data_)
|
||||
{
|
||||
delete[] wave_data_;
|
||||
wave_data_ = nullptr;
|
||||
}
|
||||
TraceError(L"Create source voice error", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
opened_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool 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 Music::Pause()
|
||||
{
|
||||
if (voice_)
|
||||
{
|
||||
if (SUCCEEDED(voice_->Stop()))
|
||||
{
|
||||
playing_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Music::Resume()
|
||||
{
|
||||
if (voice_)
|
||||
{
|
||||
if (SUCCEEDED(voice_->Start()))
|
||||
{
|
||||
playing_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
MoveTransition::MoveTransition(float duration, Direction direction)
|
||||
: Transition(duration)
|
||||
, direction_(direction)
|
||||
{
|
||||
}
|
||||
|
||||
void MoveTransition::Init(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
Transition::Init(prev, next, game);
|
||||
|
||||
switch (direction_)
|
||||
{
|
||||
case Direction::Up:
|
||||
pos_delta_ = Point(0, -window_size_.height);
|
||||
start_pos_ = Point(0, window_size_.height);
|
||||
break;
|
||||
case Direction::Down:
|
||||
pos_delta_ = Point(0, window_size_.height);
|
||||
start_pos_ = Point(0, -window_size_.height);
|
||||
break;
|
||||
case Direction::Left:
|
||||
pos_delta_ = Point(-window_size_.width, 0);
|
||||
start_pos_ = Point(window_size_.width, 0);
|
||||
break;
|
||||
case Direction::Right:
|
||||
pos_delta_ = Point(window_size_.width, 0);
|
||||
start_pos_ = Point(-window_size_.width, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(
|
||||
D2D1::Matrix3x2F::Translation(
|
||||
start_pos_.x,
|
||||
start_pos_.y
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveTransition::Reset()
|
||||
{
|
||||
if (out_scene_)
|
||||
{
|
||||
out_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
RotationTransition::RotationTransition(float duration, float rotation)
|
||||
: Transition(duration)
|
||||
, rotation_(rotation)
|
||||
{
|
||||
}
|
||||
|
||||
void RotationTransition::Init(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void RotationTransition::Update()
|
||||
{
|
||||
Transition::Update();
|
||||
|
||||
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;
|
||||
|
||||
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::Identity());
|
||||
}
|
||||
|
||||
if (in_scene_)
|
||||
{
|
||||
in_scene_->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtransition.h"
|
||||
#include "..\e2dobject.h"
|
||||
#include "..\e2dmodule.h"
|
||||
|
||||
namespace 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_()
|
||||
{
|
||||
duration_ = std::max(duration, 0.f);
|
||||
}
|
||||
|
||||
Transition::~Transition()
|
||||
{
|
||||
SafeRelease(out_layer_);
|
||||
SafeRelease(in_layer_);
|
||||
SafeRelease(out_scene_);
|
||||
SafeRelease(in_scene_);
|
||||
}
|
||||
|
||||
bool Transition::IsDone()
|
||||
{
|
||||
return done_;
|
||||
}
|
||||
|
||||
void Transition::Init(Scene * prev, Scene * next, Game * game)
|
||||
{
|
||||
started_ = Time::Now();
|
||||
out_scene_ = prev;
|
||||
in_scene_ = next;
|
||||
|
||||
if (out_scene_)
|
||||
out_scene_->Retain();
|
||||
|
||||
if (in_scene_)
|
||||
in_scene_->Retain();
|
||||
|
||||
auto graphics = Device::GetGraphics();
|
||||
if (in_scene_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
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
|
||||
),
|
||||
nullptr,
|
||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
||||
D2D1::Matrix3x2F::Identity(),
|
||||
1.f,
|
||||
graphics->GetSolidBrush(),
|
||||
D2D1_LAYER_OPTIONS_NONE
|
||||
);
|
||||
}
|
||||
|
||||
void Transition::Update()
|
||||
{
|
||||
if (duration_ == 0)
|
||||
{
|
||||
process_ = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
process_ = (Time::Now() - started_).Seconds() / duration_;
|
||||
process_ = std::min(process_, 1.f);
|
||||
}
|
||||
|
||||
if (process_ >= 1)
|
||||
{
|
||||
this->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Button.h"
|
||||
#include "../base/input.h"
|
||||
|
||||
#define SAFE_SET(pointer, func, ...) if (pointer) { pointer->##func(__VA_ARGS__); }
|
||||
|
||||
#define SET_BUTTON_NODE(Old, New) \
|
||||
if (New != Old) \
|
||||
{ \
|
||||
if (Old) this->RemoveChild(Old); \
|
||||
if (New) \
|
||||
{ \
|
||||
New->SetPivot(GetPivotX(), GetPivotY()); \
|
||||
this->AddChild(New); \
|
||||
} \
|
||||
Old = New; \
|
||||
UpdateVisible(); \
|
||||
} \
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace ui
|
||||
{
|
||||
Button::Button()
|
||||
: callback_(nullptr)
|
||||
, status_(Status::Normal)
|
||||
, enabled_(true)
|
||||
, is_selected_(false)
|
||||
, normal_(nullptr)
|
||||
, mouseover_(nullptr)
|
||||
, selected_(nullptr)
|
||||
, disabled_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (callback_)
|
||||
{
|
||||
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)
|
||||
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_)
|
||||
{
|
||||
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(input::instance.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Button::SetStatus(Status status)
|
||||
{
|
||||
if (status_ != status)
|
||||
{
|
||||
status_ = status;
|
||||
UpdateVisible();
|
||||
}
|
||||
}
|
||||
|
||||
void 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_)
|
||||
{
|
||||
selected_->SetVisible(true);
|
||||
}
|
||||
else if (status_ == Status::Mouseover && mouseover_)
|
||||
{
|
||||
mouseover_->SetVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (normal_) normal_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disabled_)
|
||||
{
|
||||
disabled_->SetVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (normal_) normal_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../base/Node.h"
|
||||
#include <functional>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace ui
|
||||
{
|
||||
class Button
|
||||
: public Node
|
||||
{
|
||||
typedef std::function<void()> Callback;
|
||||
|
||||
public:
|
||||
Button();
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * selected, /* 鼠标按下状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * mouseover, /* 鼠标移入状态 */
|
||||
Node * selected, /* 鼠标按下状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
explicit Button(
|
||||
Node * normal, /* 普通状态 */
|
||||
Node * mouseover, /* 鼠标移入状态 */
|
||||
Node * selected, /* 鼠标移入状态 */
|
||||
Node * disabled, /* 按钮禁用状态 */
|
||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
||||
);
|
||||
|
||||
// 获取按钮状态是启用还是禁用
|
||||
bool IsEnable() const;
|
||||
|
||||
// 设置按钮启用或禁用
|
||||
void SetEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 设置一般情况下显示的按钮
|
||||
virtual void SetNormal(
|
||||
Node * normal
|
||||
);
|
||||
|
||||
// 设置鼠标移入按钮时显示的按钮
|
||||
virtual void SetMouseOver(
|
||||
Node * mouseover
|
||||
);
|
||||
|
||||
// 设置鼠标按下按钮时显示的按钮
|
||||
virtual void SetSelected(
|
||||
Node * selected
|
||||
);
|
||||
|
||||
// 设置按钮被禁用时显示的按钮
|
||||
virtual void SetDisabled(
|
||||
Node * disabled
|
||||
);
|
||||
|
||||
// 设置按钮点击后的回调函数
|
||||
void SetCallbackOnClick(
|
||||
const Callback& func
|
||||
);
|
||||
|
||||
// 设置支点位置
|
||||
// 默认为 (0, 0), 范围 [0, 1]
|
||||
virtual void SetPivot(
|
||||
float pivot_x,
|
||||
float pivot_y
|
||||
) override;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Button);
|
||||
|
||||
// 按钮状态枚举
|
||||
enum class Status { Normal, Mouseover, Selected };
|
||||
|
||||
// 设置按钮状态
|
||||
virtual void SetStatus(
|
||||
Status status
|
||||
);
|
||||
|
||||
// 刷新按钮显示
|
||||
virtual void UpdateVisible();
|
||||
|
||||
// 分发鼠标消息
|
||||
virtual bool Dispatch(
|
||||
const MouseEvent& e,
|
||||
bool handled
|
||||
) override;
|
||||
|
||||
// 遍历节点
|
||||
virtual void Visit() override;
|
||||
|
||||
private:
|
||||
Node * normal_;
|
||||
Node * mouseover_;
|
||||
Node * selected_;
|
||||
Node * disabled_;
|
||||
bool enabled_;
|
||||
bool is_selected_;
|
||||
Status status_;
|
||||
Callback callback_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -18,83 +18,85 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dcomponent.h"
|
||||
|
||||
#include "Menu.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Menu::Menu()
|
||||
: enabled_(true)
|
||||
namespace ui
|
||||
{
|
||||
}
|
||||
|
||||
Menu::Menu(const std::vector<Button*>& buttons)
|
||||
: enabled_(true)
|
||||
{
|
||||
for (const auto& button : buttons)
|
||||
Menu::Menu()
|
||||
: enabled_(true)
|
||||
{
|
||||
this->AddButton(button);
|
||||
}
|
||||
}
|
||||
|
||||
bool Menu::IsEnable() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
size_t Menu::GetButtonCount() const
|
||||
{
|
||||
return buttons_.size();
|
||||
}
|
||||
|
||||
void 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 Menu::AddButton(Button * button)
|
||||
{
|
||||
if (button)
|
||||
bool Menu::IsEnable() const
|
||||
{
|
||||
this->AddChild(button);
|
||||
buttons_.push_back(button);
|
||||
button->SetEnabled(enabled_);
|
||||
return enabled_;
|
||||
}
|
||||
}
|
||||
|
||||
bool 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<Button*>& Menu::GetAllButtons() const
|
||||
{
|
||||
return buttons_;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../base/Node.h"
|
||||
#include "Button.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace ui
|
||||
{
|
||||
// 菜单
|
||||
class Menu
|
||||
: public Node
|
||||
{
|
||||
public:
|
||||
Menu();
|
||||
|
||||
explicit Menu(
|
||||
const std::vector<Button*>& buttons /* 按钮数组 */
|
||||
);
|
||||
|
||||
// 获取菜单是否禁用
|
||||
bool IsEnable() const;
|
||||
|
||||
// 获取菜单中的按钮数量
|
||||
size_t GetButtonCount() const;
|
||||
|
||||
// 设置菜单启用或禁用
|
||||
void SetEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 添加按钮
|
||||
void AddButton(
|
||||
Button * button
|
||||
);
|
||||
|
||||
// 移除按钮
|
||||
bool RemoveButton(
|
||||
Button * button
|
||||
);
|
||||
|
||||
// 获取所有按钮
|
||||
const std::vector<Button*>& GetAllButtons() const;
|
||||
|
||||
private:
|
||||
E2D_DISABLE_COPY(Menu);
|
||||
|
||||
private:
|
||||
bool enabled_;
|
||||
std::vector<Button*> buttons_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -18,12 +18,12 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtool.h"
|
||||
|
||||
#include "Data.h"
|
||||
#include "Path.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Data::Data(const std::wstring & key, const std::wstring & field)
|
||||
Data::Data(const String & key, const String & field)
|
||||
: key_(key)
|
||||
, field_(field)
|
||||
, data_path_(Path::GetDataPath())
|
||||
|
|
@ -88,7 +88,7 @@ namespace easy2d
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool Data::SaveString(const std::wstring& value)
|
||||
bool Data::SaveString(const String& value)
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_.c_str(),
|
||||
|
|
@ -133,7 +133,7 @@ namespace easy2d
|
|||
return nValue == TRUE;
|
||||
}
|
||||
|
||||
std::wstring Data::GetString()
|
||||
String Data::GetString()
|
||||
{
|
||||
wchar_t temp[256] = { 0 };
|
||||
::GetPrivateProfileStringW(
|
||||
|
|
@ -18,52 +18,66 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2daction.h"
|
||||
#include "..\e2dobject.h"
|
||||
|
||||
#pragma once
|
||||
#include "../base/base.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
MoveBy::MoveBy(float duration, Point vector)
|
||||
: FiniteTimeAction(duration)
|
||||
// 数据管理工具
|
||||
class Data
|
||||
{
|
||||
delta_pos_ = vector;
|
||||
}
|
||||
public:
|
||||
Data(
|
||||
const String& key, /* 键值 */
|
||||
const String& field = L"Defalut" /* 字段名称 */
|
||||
);
|
||||
|
||||
void MoveBy::Init()
|
||||
{
|
||||
FiniteTimeAction::Init();
|
||||
// 该数据是否存在
|
||||
bool Exists() const;
|
||||
|
||||
if (target_)
|
||||
{
|
||||
prev_pos_ = start_pos_ = target_->GetPosition();
|
||||
}
|
||||
}
|
||||
// 保存 int 类型的值
|
||||
bool SaveInt(
|
||||
int value
|
||||
);
|
||||
|
||||
void MoveBy::Update()
|
||||
{
|
||||
FiniteTimeAction::Update();
|
||||
// 保存 float 类型的值
|
||||
bool SaveFloat(
|
||||
float value
|
||||
);
|
||||
|
||||
if (target_)
|
||||
{
|
||||
Point currentPos = target_->GetPosition();
|
||||
Point diff = currentPos - prev_pos_;
|
||||
start_pos_ = start_pos_ + diff;
|
||||
// 保存 double 类型的值
|
||||
bool SaveDouble(
|
||||
double value
|
||||
);
|
||||
|
||||
Point newPos = start_pos_ + (delta_pos_ * delta_);
|
||||
target_->SetPosition(newPos);
|
||||
// 保存 bool 类型的值
|
||||
bool SaveBool(
|
||||
bool value
|
||||
);
|
||||
|
||||
prev_pos_ = newPos;
|
||||
}
|
||||
}
|
||||
// 保存 String 类型的值
|
||||
bool SaveString(
|
||||
const String& value
|
||||
);
|
||||
|
||||
MoveBy * MoveBy::Clone() const
|
||||
{
|
||||
return new MoveBy(duration_, delta_pos_);
|
||||
}
|
||||
// 获取 int 类型的值
|
||||
int GetInt() const;
|
||||
|
||||
MoveBy * MoveBy::Reverse() const
|
||||
{
|
||||
return new MoveBy(duration_, -delta_pos_);
|
||||
}
|
||||
}
|
||||
// 获取 float 类型的值
|
||||
float GetFloat() const;
|
||||
|
||||
// 获取 double 类型的值
|
||||
double GetDouble() const;
|
||||
|
||||
// 获取 bool 类型的值
|
||||
bool GetBool() const;
|
||||
|
||||
// 获取 字符串 类型的值
|
||||
String GetString();
|
||||
|
||||
protected:
|
||||
String key_;
|
||||
String field_;
|
||||
const String& data_path_;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dutil.h"
|
||||
#include <regex>
|
||||
|
||||
|
||||
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;
|
||||
|
||||
namespace
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool Duration::operator==(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ == other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator!=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ != other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator>(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ > other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator>=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ >= other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator<(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ < other.milliseconds_;
|
||||
}
|
||||
|
||||
bool Duration::operator<=(const Duration & other) const
|
||||
{
|
||||
return milliseconds_ <= other.milliseconds_;
|
||||
}
|
||||
|
||||
Duration Duration::operator+(const Duration & other) const
|
||||
{
|
||||
return Duration(milliseconds_ + other.milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator-(const Duration & other) const
|
||||
{
|
||||
return Duration(milliseconds_ - other.milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator-() const
|
||||
{
|
||||
return Duration(-milliseconds_);
|
||||
}
|
||||
|
||||
Duration Duration::operator*(int value) const
|
||||
{
|
||||
return Duration(milliseconds_ * value);
|
||||
}
|
||||
|
||||
Duration Duration::operator/(int value) const
|
||||
{
|
||||
return Duration(milliseconds_ / value);
|
||||
}
|
||||
|
||||
Duration Duration::operator*(float value) const
|
||||
{
|
||||
return Duration(static_cast<int>(milliseconds_ * value));
|
||||
}
|
||||
|
||||
Duration 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));
|
||||
}
|
||||
|
||||
Duration Duration::operator/(double value) const
|
||||
{
|
||||
return Duration(static_cast<int>(milliseconds_ / value));
|
||||
}
|
||||
|
||||
Duration & Duration::operator+=(const Duration &other)
|
||||
{
|
||||
milliseconds_ += other.milliseconds_;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator-=(const Duration &other)
|
||||
{
|
||||
milliseconds_ -= other.milliseconds_;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator*=(int value)
|
||||
{
|
||||
milliseconds_ *= value;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator/=(int value)
|
||||
{
|
||||
milliseconds_ /= value;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & Duration::operator*=(float value)
|
||||
{
|
||||
milliseconds_ = static_cast<int>(milliseconds_ * value);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration & 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);
|
||||
}
|
||||
|
||||
Duration & Duration::operator/=(double value)
|
||||
{
|
||||
milliseconds_ = static_cast<int>(milliseconds_ / value);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration operator*(int value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(int value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
Duration operator*(float value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(float value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
Duration operator*(double value, const Duration & dur)
|
||||
{
|
||||
return dur * value;
|
||||
}
|
||||
|
||||
Duration operator/(double value, const Duration & dur)
|
||||
{
|
||||
return dur / value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,21 +18,23 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtool.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "File.h"
|
||||
#include <cwctype>
|
||||
#include <shobjidl.h>
|
||||
#include <shobjidl.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
std::list<std::wstring> File::search_paths_;
|
||||
std::list<String> File::search_paths_;
|
||||
|
||||
File::File()
|
||||
: file_path_()
|
||||
{
|
||||
}
|
||||
|
||||
File::File(const std::wstring & file_name)
|
||||
File::File(const String & file_name)
|
||||
: file_path_(file_name)
|
||||
{
|
||||
this->Open(file_name);
|
||||
|
|
@ -42,12 +44,12 @@ namespace easy2d
|
|||
{
|
||||
}
|
||||
|
||||
bool File::Open(const std::wstring & file_name)
|
||||
bool File::Open(const String & file_name)
|
||||
{
|
||||
if (file_name.empty())
|
||||
return false;
|
||||
|
||||
auto FindFile = [](const std::wstring & path) -> bool
|
||||
auto FindFile = [](const String & path) -> bool
|
||||
{
|
||||
if (::PathFileExists(path.c_str()))
|
||||
return true;
|
||||
|
|
@ -78,18 +80,18 @@ namespace easy2d
|
|||
return false;
|
||||
}
|
||||
|
||||
const std::wstring& File::GetPath() const
|
||||
const String& File::GetPath() const
|
||||
{
|
||||
return file_path_;
|
||||
}
|
||||
|
||||
std::wstring File::GetExtension() const
|
||||
String File::GetExtension() const
|
||||
{
|
||||
std::wstring file_ext;
|
||||
String file_ext;
|
||||
// 找到文件名中的最后一个 '.' 的位置
|
||||
size_t pos = file_path_.find_last_of(L'.');
|
||||
// 判断 pos 是否是有效位置
|
||||
if (pos != std::wstring::npos)
|
||||
if (pos != String::npos)
|
||||
{
|
||||
// 截取扩展名
|
||||
file_ext = file_path_.substr(pos);
|
||||
|
|
@ -106,7 +108,7 @@ namespace easy2d
|
|||
return false;
|
||||
}
|
||||
|
||||
File File::Extract(Resource& res, const std::wstring& dest_file_name)
|
||||
File File::Extract(Resource& res, const String& dest_file_name)
|
||||
{
|
||||
File file;
|
||||
HANDLE file_handle = ::CreateFile(
|
||||
|
|
@ -140,11 +142,11 @@ namespace easy2d
|
|||
return file;
|
||||
}
|
||||
|
||||
void File::AddSearchPath(const std::wstring & path)
|
||||
void File::AddSearchPath(const String & path)
|
||||
{
|
||||
std::wstring tmp = path;
|
||||
String tmp = path;
|
||||
size_t pos = 0;
|
||||
while ((pos = tmp.find(L"/", pos)) != std::wstring::npos)
|
||||
while ((pos = tmp.find(L"/", pos)) != String::npos)
|
||||
{
|
||||
tmp.replace(pos, 1, L"\\");
|
||||
pos++;
|
||||
|
|
@ -161,9 +163,9 @@ namespace easy2d
|
|||
}
|
||||
}
|
||||
|
||||
File File::ShowOpenDialog(const std::wstring & title, const std::wstring & filter)
|
||||
File File::ShowOpenDialog(const String & title, const String & filter)
|
||||
{
|
||||
std::wstring file_path;
|
||||
String file_path;
|
||||
HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -223,9 +225,9 @@ namespace easy2d
|
|||
return File(file_path);
|
||||
}
|
||||
|
||||
File File::ShowSaveDialog(const std::wstring & title, const std::wstring& def_file, const std::wstring & def_ext)
|
||||
File File::ShowSaveDialog(const String & title, const String& def_file, const String & def_ext)
|
||||
{
|
||||
std::wstring file_path;
|
||||
String file_path;
|
||||
HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -251,7 +253,7 @@ namespace easy2d
|
|||
{
|
||||
file_save->SetDefaultExtension(def_ext.c_str());
|
||||
|
||||
std::wstring ext = L"*." + def_ext;
|
||||
String ext = L"*." + def_ext;
|
||||
COMDLG_FILTERSPEC spec[] =
|
||||
{
|
||||
{ L"", ext.c_str() }
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../base/base.h"
|
||||
#include "../base/Resource.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 文件
|
||||
class File
|
||||
{
|
||||
public:
|
||||
File();
|
||||
|
||||
File(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
virtual ~File();
|
||||
|
||||
// 打开文件
|
||||
bool Open(
|
||||
const String& file_name
|
||||
);
|
||||
|
||||
// 文件是否存在
|
||||
bool Exists() const;
|
||||
|
||||
// 删除文件
|
||||
bool Delete();
|
||||
|
||||
// 获取文件路径
|
||||
const String& GetPath() const;
|
||||
|
||||
// 获取文件扩展名
|
||||
String GetExtension() const;
|
||||
|
||||
// 释放资源到临时文件目录
|
||||
static File Extract(
|
||||
Resource& res, /* 资源 */
|
||||
const String& dest_file_name /* 目标文件名 */
|
||||
);
|
||||
|
||||
// 添加文件搜索路径
|
||||
static void AddSearchPath(
|
||||
const String& path
|
||||
);
|
||||
|
||||
// 弹出打开文件对话框
|
||||
static File ShowOpenDialog(
|
||||
const String& title = L"打开", /* 对话框标题 */
|
||||
const String& filter = L"" /* 筛选扩展名,例如 "*.jpg;*.jpeg" */
|
||||
);
|
||||
|
||||
// 弹出保存文件对话框
|
||||
static File ShowSaveDialog(
|
||||
const String& title = L"保存", /* 对话框标题 */
|
||||
const String& def_file = L"", /* 默认保存的文件名 */
|
||||
const String& def_ext = L"" /* 默认追加的扩展名,例如 "txt" */
|
||||
);
|
||||
|
||||
protected:
|
||||
String file_path_;
|
||||
|
||||
static std::list<String> search_paths_;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "Music.h"
|
||||
#include "Transcoder.h"
|
||||
#include "File.h"
|
||||
#include "../base/modules.h"
|
||||
#include "../base/audio.h"
|
||||
#include "../base/logs.h"
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
Music::Music()
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Music::Music(const String& file_path)
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
Load(file_path);
|
||||
}
|
||||
|
||||
Music::Music(Resource& res)
|
||||
: opened_(false)
|
||||
, playing_(false)
|
||||
, wave_data_(nullptr)
|
||||
, size_(0)
|
||||
, voice_(nullptr)
|
||||
{
|
||||
Load(res);
|
||||
}
|
||||
|
||||
Music::~Music()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool Music::Load(const String & file_path)
|
||||
{
|
||||
if (opened_)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
File music_file;
|
||||
if (!music_file.Open(file_path))
|
||||
{
|
||||
E2D_WARNING("Media file not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 用户输入的路径不一定是完整路径,因为用户可能通过 File::AddSearchPath 添加
|
||||
// 默认搜索路径,所以需要通过 File::GetPath 获取完整路径
|
||||
String music_file_path = music_file.GetPath();
|
||||
|
||||
Transcoder transcoder;
|
||||
if (!transcoder.LoadMediaFile(music_file_path.c_str(), &wave_data_, &size_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (wave_data_)
|
||||
{
|
||||
delete[] wave_data_;
|
||||
wave_data_ = nullptr;
|
||||
}
|
||||
logs::Trace(L"Create source voice error", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
opened_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Music::Load(Resource& res)
|
||||
{
|
||||
if (opened_)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
Transcoder transcoder;
|
||||
if (!transcoder.LoadMediaResource(res, &wave_data_, &size_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = audio::instance.CreateVoice(&voice_, transcoder.GetWaveFormatEx());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (wave_data_)
|
||||
{
|
||||
delete[] wave_data_;
|
||||
wave_data_ = nullptr;
|
||||
}
|
||||
logs::Trace(L"Create source voice error", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
opened_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool 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)))
|
||||
{
|
||||
logs::Trace(L"Submitting source buffer error", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = voice_->Start(0);
|
||||
|
||||
playing_ = SUCCEEDED(hr);
|
||||
|
||||
return playing_;
|
||||
}
|
||||
|
||||
void Music::Pause()
|
||||
{
|
||||
if (voice_)
|
||||
{
|
||||
if (SUCCEEDED(voice_->Stop()))
|
||||
{
|
||||
playing_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Music::Resume()
|
||||
{
|
||||
if (voice_)
|
||||
{
|
||||
if (SUCCEEDED(voice_->Start()))
|
||||
{
|
||||
playing_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../base/base.h"
|
||||
#include "../base/RefCounter.h"
|
||||
#include "../base/Resource.h"
|
||||
#include <xaudio2.h>
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
// 音乐
|
||||
class Music
|
||||
: public RefCounter
|
||||
{
|
||||
public:
|
||||
Music();
|
||||
|
||||
Music(
|
||||
const String& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
Music(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
virtual ~Music();
|
||||
|
||||
// 打开音乐文件
|
||||
bool Load(
|
||||
const String& file_path /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 打开音乐资源
|
||||
bool Load(
|
||||
Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 播放
|
||||
bool Play(
|
||||
int loop_count = 0 /* 播放循环次数 (-1 为循环播放) */
|
||||
);
|
||||
|
||||
// 暂停
|
||||
void Pause();
|
||||
|
||||
// 继续
|
||||
void Resume();
|
||||
|
||||
// 停止
|
||||
void Stop();
|
||||
|
||||
// 关闭并回收资源
|
||||
void Close();
|
||||
|
||||
// 是否正在播放
|
||||
bool IsPlaying() const;
|
||||
|
||||
// 获取音量
|
||||
float GetVolume() const;
|
||||
|
||||
// 设置音量
|
||||
bool SetVolume(
|
||||
float volume /* 1 为原始音量, 大于 1 为放大音量, 0 为最小音量 */
|
||||
);
|
||||
|
||||
// 获取 IXAudio2SourceVoice 对象
|
||||
IXAudio2SourceVoice * GetSourceVoice() const;
|
||||
|
||||
protected:
|
||||
E2D_DISABLE_COPY(Music);
|
||||
|
||||
protected:
|
||||
bool opened_;
|
||||
bool playing_;
|
||||
UINT32 size_;
|
||||
BYTE* wave_data_;
|
||||
IXAudio2SourceVoice* voice_;
|
||||
};
|
||||
}
|
||||
|
|
@ -18,17 +18,17 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "..\e2dtool.h"
|
||||
#include "..\e2dmodule.h"
|
||||
#include "Path.h"
|
||||
#include "File.h"
|
||||
#include "../base/window.h"
|
||||
#include <shlobj.h>
|
||||
|
||||
|
||||
namespace easy2d
|
||||
{
|
||||
namespace
|
||||
{
|
||||
// 创建指定文件夹
|
||||
bool CreateFolder(const std::wstring & dir_path)
|
||||
bool CreateFolder(const String & dir_path)
|
||||
{
|
||||
if (dir_path.empty() || dir_path.size() >= MAX_PATH)
|
||||
return false;
|
||||
|
|
@ -55,15 +55,15 @@ namespace easy2d
|
|||
}
|
||||
|
||||
|
||||
const std::wstring& Path::GetDataPath()
|
||||
const String& Path::GetDataPath()
|
||||
{
|
||||
static std::wstring data_path;
|
||||
static String data_path;
|
||||
if (data_path.empty())
|
||||
{
|
||||
// 设置数据的保存路径
|
||||
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));
|
||||
String local_app_data_path = Path::GetLocalAppDataPath();
|
||||
String title = window::instance.GetTitle();
|
||||
String folder_name = std::to_wstring(std::hash<String>{}(title));
|
||||
|
||||
if (!local_app_data_path.empty())
|
||||
{
|
||||
|
|
@ -83,15 +83,15 @@ namespace easy2d
|
|||
return data_path;
|
||||
}
|
||||
|
||||
const std::wstring& Path::GetTemporaryPath()
|
||||
const String& Path::GetTemporaryPath()
|
||||
{
|
||||
static std::wstring temp_path;
|
||||
static String 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));
|
||||
String title = window::instance.GetTitle();
|
||||
String folder_name = std::to_wstring(std::hash<String>{}(title));
|
||||
|
||||
if (0 != ::GetTempPath(_MAX_PATH, path))
|
||||
{
|
||||
|
|
@ -110,9 +110,9 @@ namespace easy2d
|
|||
return temp_path;
|
||||
}
|
||||
|
||||
const std::wstring& Path::GetLocalAppDataPath()
|
||||
const String& Path::GetLocalAppDataPath()
|
||||
{
|
||||
static std::wstring local_app_data_path;
|
||||
static String local_app_data_path;
|
||||
if (local_app_data_path.empty())
|
||||
{
|
||||
// 获取 AppData/Local 文件夹的路径
|
||||
|
|
@ -124,9 +124,9 @@ namespace easy2d
|
|||
return local_app_data_path;
|
||||
}
|
||||
|
||||
const std::wstring& Path::GetExeFilePath()
|
||||
const String& Path::GetExeFilePath()
|
||||
{
|
||||
static std::wstring exe_file_path;
|
||||
static String exe_file_path;
|
||||
if (exe_file_path.empty())
|
||||
{
|
||||
TCHAR path[_MAX_PATH] = { 0 };
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue