diff --git a/core/actions/Animate.cpp b/core/actions/Animate.cpp deleted file mode 100644 index 6308fd92..00000000 --- a/core/actions/Animate.cpp +++ /dev/null @@ -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(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(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; - } -} \ No newline at end of file diff --git a/core/actions/FadeIn.cpp b/core/actions/FadeIn.cpp deleted file mode 100644 index d4427df9..00000000 --- a/core/actions/FadeIn.cpp +++ /dev/null @@ -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) - { - } -} \ No newline at end of file diff --git a/core/actions/MoveTo.cpp b/core/actions/MoveTo.cpp deleted file mode 100644 index 33c7e586..00000000 --- a/core/actions/MoveTo.cpp +++ /dev/null @@ -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_; - } -} \ No newline at end of file diff --git a/core/actions/Sequence.cpp b/core/actions/Sequence.cpp deleted file mode 100644 index c8077a5f..00000000 --- a/core/actions/Sequence.cpp +++ /dev/null @@ -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 newActions(actions_.size()); - for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) - { - newActions.push_back((*iter)->Reverse()); - } - sequence->Add(newActions); - } - return sequence; - } -} \ No newline at end of file diff --git a/core/actions/Spawn.cpp b/core/actions/Spawn.cpp deleted file mode 100644 index e00cd3c4..00000000 --- a/core/actions/Spawn.cpp +++ /dev/null @@ -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 newActions(actions_.size()); - for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) - { - newActions.push_back((*iter)->Reverse()); - } - spawn->Add(newActions); - } - return spawn; - } -} \ No newline at end of file diff --git a/core/actions/Action.cpp b/core/base/Action.cpp similarity index 86% rename from core/actions/Action.cpp rename to core/base/Action.cpp index 8d05e7ff..508a7cb7 100644 --- a/core/actions/Action.cpp +++ b/core/base/Action.cpp @@ -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() { } -} \ No newline at end of file +} diff --git a/core/base/Action.h b/core/base/Action.h new file mode 100644 index 00000000..efbc925e --- /dev/null +++ b/core/base/Action.h @@ -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_; + }; +} diff --git a/core/base/ActionCombined.cpp b/core/base/ActionCombined.cpp new file mode 100644 index 00000000..1dc16810 --- /dev/null +++ b/core/base/ActionCombined.cpp @@ -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 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 newActions(actions_.size()); + for (auto iter = actions_.crbegin(), iterCrend = actions_.crend(); iter != iterCrend; ++iter) + { + newActions.push_back((*iter)->Reverse()); + } + spawn->Add(newActions); + } + return spawn; + } +} \ No newline at end of file diff --git a/core/base/ActionCombined.h b/core/base/ActionCombined.h new file mode 100644 index 00000000..48f4264a --- /dev/null +++ b/core/base/ActionCombined.h @@ -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 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 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_; + }; +} diff --git a/core/base/ActionFiniteTime.cpp b/core/base/ActionFiniteTime.cpp new file mode 100644 index 00000000..8aadd7cc --- /dev/null +++ b/core/base/ActionFiniteTime.cpp @@ -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 + +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_); + } +} diff --git a/core/e2daction.h b/core/base/ActionFiniteTime.h similarity index 56% rename from core/e2daction.h rename to core/base/ActionFiniteTime.h index 6c7076f9..bd88f7ce 100644 --- a/core/e2daction.h +++ b/core/base/ActionFiniteTime.h @@ -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 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 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 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 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__ +} diff --git a/core/actions/Animation.cpp b/core/base/Animation.cpp similarity index 57% rename from core/actions/Animation.cpp rename to core/base/Animation.cpp index c6698a5b..6670e0df 100644 --- a/core/actions/Animation.cpp +++ b/core/base/Animation.cpp @@ -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(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(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) { diff --git a/core/base/Animation.h b/core/base/Animation.h new file mode 100644 index 00000000..61c4354f --- /dev/null +++ b/core/base/Animation.h @@ -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 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_; + }; +} diff --git a/core/base/BaseTypes.h b/core/base/BaseTypes.h new file mode 100644 index 00000000..4ed38fbd --- /dev/null +++ b/core/base/BaseTypes.h @@ -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 /* Êó±êÖмü */ + }; +} diff --git a/core/actions/CallFunc.cpp b/core/base/CallFunc.cpp similarity index 96% rename from core/actions/CallFunc.cpp rename to core/base/CallFunc.cpp index 25f4a1d8..2edcc816 100644 --- a/core/actions/CallFunc.cpp +++ b/core/base/CallFunc.cpp @@ -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(); } -} \ No newline at end of file +} diff --git a/core/base/CallFunc.h b/core/base/CallFunc.h new file mode 100644 index 00000000..a99ba630 --- /dev/null +++ b/core/base/CallFunc.h @@ -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 + +namespace easy2d +{ + // »Øµ÷¶¯×÷ + class CallFunc + : public Action + { + typedef std::function 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_; + }; +} diff --git a/core/objects/Canvas.cpp b/core/base/Canvas.cpp similarity index 93% rename from core/objects/Canvas.cpp rename to core/base/Canvas.cpp index d21e8011..6b89ecc9 100644 --- a/core/objects/Canvas.cpp +++ b/core/base/Canvas.cpp @@ -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 diff --git a/core/base/Canvas.h b/core/base/Canvas.h new file mode 100644 index 00000000..a26bb4e2 --- /dev/null +++ b/core/base/Canvas.h @@ -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 + +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_; + }; +} \ No newline at end of file diff --git a/core/utils/Color.cpp b/core/base/Color.cpp similarity index 84% rename from core/utils/Color.cpp rename to core/base/Color.cpp index 53e6d1a1..4a2f4ab9 100644 --- a/core/utils/Color.cpp +++ b/core/base/Color.cpp @@ -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) diff --git a/core/base/Color.h b/core/base/Color.h new file mode 100644 index 00000000..3209df43 --- /dev/null +++ b/core/base/Color.h @@ -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 + +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; + }; +} diff --git a/core/utils/Font.cpp b/core/base/Font.cpp similarity index 91% rename from core/utils/Font.cpp rename to core/base/Font.cpp index 0530c1f0..ec102fb9 100644 --- a/core/utils/Font.cpp +++ b/core/base/Font.cpp @@ -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) { } -} \ No newline at end of file +} diff --git a/core/transitions/FadeTransition.cpp b/core/base/Font.h similarity index 66% rename from core/transitions/FadeTransition.cpp rename to core/base/Font.h index f8c2704a..6cc42e9d 100644 --- a/core/transitions/FadeTransition.cpp +++ b/core/base/Font.h @@ -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 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; - } - } -} \ No newline at end of file + 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 + ); + }; +} diff --git a/core/base/Game.cpp b/core/base/Game.cpp new file mode 100644 index 00000000..61ffc4fd --- /dev/null +++ b/core/base/Game.cpp @@ -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 + +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 ¿ªÆôÁË´¹Ö±Í¬²½£¬ÔÚäÖȾʱ»áµÈ´ýÏÔʾÆ÷ˢУ¬ + // ËüÆðµ½Á˷dz£Îȶ¨µÄÑÓʱ×÷Óã¬ËùÒԴ󲿷Öʱºò²»ÐèÒªÊÖ¶¯¹ÒÆðÏ߳̽øÐÐÑÓʱ¡£ + // ÏÂÃæµÄ´úÂë½öÔÚһЩÇé¿öÏ£¨ÀýÈç´°¿Ú×îС»¯Ê±£©¹ÒÆðỊ̈߳¬·ÀÖ¹Õ¼Óùý¸ß 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; + } +} \ No newline at end of file diff --git a/core/base/Game.h b/core/base/Game.h new file mode 100644 index 00000000..b5b72a3f --- /dev/null +++ b/core/base/Game.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. + +#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_; + }; +} diff --git a/core/objects/Image.cpp b/core/base/Image.cpp similarity index 88% rename from core/objects/Image.cpp rename to core/base/Image.cpp index dec4fb7f..fe7e64ac 100644 --- a/core/objects/Image.cpp +++ b/core/base/Image.cpp @@ -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 Image::bitmap_cache_; + namespace + { + std::map 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{}(file_name))); + this->SetBitmap(bitmap_cache_.at(std::hash{}(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{}(file_name); + size_t hash_code = std::hash{}(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; diff --git a/core/base/Image.h b/core/base/Image.h new file mode 100644 index 00000000..fae528f8 --- /dev/null +++ b/core/base/Image.h @@ -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_; + }; +} diff --git a/core/modules/Device.cpp b/core/base/Input.cpp similarity index 56% rename from core/modules/Device.cpp rename to core/base/Input.cpp index e96a6d19..f8c9c65a 100644 --- a/core/modules/Device.cpp +++ b/core/base/Input.cpp @@ -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(code)] & 0x80) + return true; + return false; + } + + bool InputDevice::IsDown(MouseCode code) + { + if (keys_[static_cast(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_; } } } \ No newline at end of file diff --git a/core/actions/Delay.cpp b/core/base/Input.h similarity index 66% rename from core/actions/Delay.cpp rename to core/base/Input.h index fb246646..45b65481 100644 --- a/core/actions/Delay.cpp +++ b/core/base/Input.h @@ -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(); + + // ¼ì²â¼üÅÌij°´¼üÊÇ·ñÕý±»°´Ï + 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; } -} \ No newline at end of file +} diff --git a/core/actions/OpacityTo.cpp b/core/base/KeyEvent.cpp similarity index 74% rename from core/actions/OpacityTo.cpp rename to core/base/KeyEvent.cpp index 3b60d48d..b325d395 100644 --- a/core/actions/OpacityTo.cpp +++ b/core/base/KeyEvent.cpp @@ -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(w_param_); } - void OpacityTo::Init() + int KeyEvent::GetCount() const { - OpacityBy::Init(); - delta_val_ = end_val_ - start_val_; + return static_cast((DWORD)l_param_ & 0x0000FFFF); } -} \ No newline at end of file + + KeyEvent::Type KeyEvent::GetType() const + { + return Type(message_); + } +} diff --git a/core/actions/RotateBy.cpp b/core/base/KeyEvent.h similarity index 65% rename from core/actions/RotateBy.cpp rename to core/base/KeyEvent.h index 0a769fb8..2e676868 100644 --- a/core/actions/RotateBy.cpp +++ b/core/base/KeyEvent.h @@ -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_); - } -} \ No newline at end of file + public: + // ´¦Àí°´¼üÏûÏ¢ + virtual void Handle(KeyEvent e) = 0; + }; +} diff --git a/core/events/MouseEvent.cpp b/core/base/MouseEvent.cpp similarity index 85% rename from core/events/MouseEvent.cpp rename to core/base/MouseEvent.cpp index da4b2a69..41bf3482 100644 --- a/core/events/MouseEvent.cpp +++ b/core/base/MouseEvent.cpp @@ -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 ); } diff --git a/core/e2devent.h b/core/base/MouseEvent.h similarity index 80% rename from core/e2devent.h rename to core/base/MouseEvent.h index 985380a7..7201b11e 100644 --- a/core/e2devent.h +++ b/core/base/MouseEvent.h @@ -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_; - }; - - // Êó±êÏûÏ¢ 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; + }; +} diff --git a/core/objects/Node.cpp b/core/base/Node.cpp similarity index 93% rename from core/objects/Node.cpp rename to core/base/Node.cpp index b85e4b41..dcf203af 100644 --- a/core/objects/Node.cpp +++ b/core/base/Node.cpp @@ -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 - 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{}(name); + size_t hash_code = std::hash{}(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{}(name); + size_t hash_code = std::hash{}(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{}(child_name); + size_t hash_code = std::hash{}(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{}(name); + hash_name_ = std::hash{}(name); } } diff --git a/core/base/Node.h b/core/base/Node.h new file mode 100644 index 00000000..f39e76ab --- /dev/null +++ b/core/base/Node.h @@ -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 Nodes; + typedef std::vector Actions; + typedef std::vector 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_; + }; +} diff --git a/core/base/Rect.hpp b/core/base/Rect.hpp new file mode 100644 index 00000000..d429dd78 --- /dev/null +++ b/core/base/Rect.hpp @@ -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); + } + }; +} diff --git a/core/utils/Ref.cpp b/core/base/RefCounter.cpp similarity index 84% rename from core/utils/Ref.cpp rename to core/base/RefCounter.cpp index e510d37c..0a57a084 100644 --- a/core/utils/Ref.cpp +++ b/core/base/RefCounter.cpp @@ -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_; } diff --git a/core/utils/Random.cpp b/core/base/RefCounter.h similarity index 80% rename from core/utils/Random.cpp rename to core/base/RefCounter.h index 3c00c46c..2c573b1e 100644 --- a/core/utils/Random.cpp +++ b/core/base/RefCounter.h @@ -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; - } -} \ No newline at end of file + public: + RefCounter(); + + virtual ~RefCounter(); + + // Ôö¼ÓÒýÓüÆÊý + long Retain(); + + // ¼õÉÙÒýÓüÆÊý + long Release(); + + // »ñÈ¡ÒýÓüÆÊý + long GetRefCount() const; + + private: + long ref_count_; + }; +} diff --git a/core/utils/Resource.cpp b/core/base/Resource.cpp similarity index 98% rename from core/utils/Resource.cpp rename to core/base/Resource.cpp index f1484f38..3f88df13 100644 --- a/core/utils/Resource.cpp +++ b/core/base/Resource.cpp @@ -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 { diff --git a/core/base/Resource.h b/core/base/Resource.h new file mode 100644 index 00000000..8dcb1f58 --- /dev/null +++ b/core/base/Resource.h @@ -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_; + }; +} diff --git a/core/objects/Scene.cpp b/core/base/Scene.cpp similarity index 97% rename from core/objects/Scene.cpp rename to core/base/Scene.cpp index 27088f78..a08aad31 100644 --- a/core/objects/Scene.cpp +++ b/core/base/Scene.cpp @@ -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_; } -} \ No newline at end of file +} diff --git a/core/actions/ScaleBy.cpp b/core/base/Scene.h similarity index 56% rename from core/actions/ScaleBy.cpp rename to core/base/Scene.h index 16b99f63..2894109a 100644 --- a/core/actions/ScaleBy.cpp +++ b/core/base/Scene.h @@ -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 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_); - } -} \ No newline at end of file + // »ñÈ¡¸ù½Úµã + 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_; + }; +} diff --git a/core/utils/Size.cpp b/core/base/Size.cpp similarity index 95% rename from core/utils/Size.cpp rename to core/base/Size.cpp index 1c083cbb..80d63109 100644 --- a/core/utils/Size.cpp +++ b/core/base/Size.cpp @@ -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); } -} \ No newline at end of file +} diff --git a/core/actions/OpacityBy.cpp b/core/base/Size.h similarity index 65% rename from core/actions/OpacityBy.cpp rename to core/base/Size.h index b26e7eda..d2f758e8 100644 --- a/core/actions/OpacityBy.cpp +++ b/core/base/Size.h @@ -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_); - } -} \ No newline at end of file + 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; + }; +} diff --git a/core/objects/Sprite.cpp b/core/base/Sprite.cpp similarity index 91% rename from core/objects/Sprite.cpp rename to core/base/Sprite.cpp index 04ff1adf..47825552 100644 --- a/core/objects/Sprite.cpp +++ b/core/base/Sprite.cpp @@ -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 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(), diff --git a/core/modules/Audio.cpp b/core/base/Sprite.h similarity index 58% rename from core/modules/Audio.cpp rename to core/base/Sprite.h index 9332ea3c..23a119c6 100644 --- a/core/modules/Audio.cpp +++ b/core/base/Sprite.h @@ -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(); - } -} \ No newline at end of file + // ¼ÓÔØÍ¼Æ¬ + 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_; + }; +} diff --git a/core/objects/Task.cpp b/core/base/Task.cpp similarity index 87% rename from core/objects/Task.cpp rename to core/base/Task.cpp index 54201176..23fb92d5 100644 --- a/core/objects/Task.cpp +++ b/core/base/Task.cpp @@ -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_; } diff --git a/core/base/Task.h b/core/base/Task.h new file mode 100644 index 00000000..3780cf7f --- /dev/null +++ b/core/base/Task.h @@ -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 + +namespace easy2d +{ + class Node; + + // ¶¨Ê±ÈÎÎñ + class Task + : public RefCounter + { + friend class Node; + + typedef std::function 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_; + }; +} diff --git a/core/objects/Text.cpp b/core/base/Text.cpp similarity index 89% rename from core/objects/Text.cpp rename to core/base/Text.cpp index 3d9fb0cd..67bb7ba8 100644 --- a/core/objects/Text.cpp +++ b/core/base/Text.cpp @@ -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(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(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); } } -} \ No newline at end of file +} diff --git a/core/base/Text.h b/core/base/Text.h new file mode 100644 index 00000000..8f865ceb --- /dev/null +++ b/core/base/Text.h @@ -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_; + }; +} \ No newline at end of file diff --git a/core/base/TextRenderer.cpp b/core/base/TextRenderer.cpp new file mode 100644 index 00000000..78c04942 --- /dev/null +++ b/core/base/TextRenderer.cpp @@ -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(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; + } +} diff --git a/core/base/TextRenderer.h b/core/base/TextRenderer.h new file mode 100644 index 00000000..afd9723b --- /dev/null +++ b/core/base/TextRenderer.h @@ -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 +#include + +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_; + }; +} diff --git a/core/base/Transition.cpp b/core/base/Transition.cpp new file mode 100644 index 00000000..9c74b170 --- /dev/null +++ b/core/base/Transition.cpp @@ -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()); + } + } +} diff --git a/core/e2dtransition.h b/core/base/Transition.h similarity index 92% rename from core/e2dtransition.h rename to core/base/Transition.h index 67bb3256..d8fc34db 100644 --- a/core/e2dtransition.h +++ b/core/base/Transition.h @@ -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__ +} diff --git a/core/actions/Loop.cpp b/core/base/audio.cpp similarity index 53% rename from core/actions/Loop.cpp rename to core/base/audio.cpp index 2e794953..66b2306c 100644 --- a/core/actions/Loop.cpp +++ b/core/base/audio.cpp @@ -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 +#include +#include 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(); + } } } \ No newline at end of file diff --git a/core/transitions/EmergeTransition.cpp b/core/base/audio.h similarity index 70% rename from core/transitions/EmergeTransition.cpp rename to core/base/audio.h index b95b91db..85115d7d 100644 --- a/core/transitions/EmergeTransition.cpp +++ b/core/base/audio.h @@ -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 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_; - } -} \ No newline at end of file +} diff --git a/core/actions/JumpTo.cpp b/core/base/base.h similarity index 71% rename from core/actions/JumpTo.cpp rename to core/base/base.h index 068be28e..080a73a1 100644 --- a/core/actions/JumpTo.cpp +++ b/core/base/base.h @@ -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 namespace easy2d { - JumpTo::JumpTo(float duration, const Point & pos, float height, int jumps) - : JumpBy(duration, Point(), height, jumps) - , end_pos_(pos) + template + 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(hr)); + ::OutputDebugStringA(s_str); + throw std::runtime_error(s_str); + } } - - void JumpTo::Init() - { - JumpBy::Init(); - delta_pos_ = end_pos_ - start_pos_; - } -} \ No newline at end of file +} diff --git a/core/actions/FiniteTimeAction.cpp b/core/base/logs.h similarity index 63% rename from core/actions/FiniteTimeAction.cpp rename to core/base/logs.h index 5a7eb43f..65a9d537 100644 --- a/core/actions/FiniteTimeAction.cpp +++ b/core/base/logs.h @@ -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(hr)); + } } -} \ No newline at end of file +} diff --git a/core/e2dmacros.h b/core/base/macros.h similarity index 75% rename from core/e2dmacros.h rename to core/base/macros.h index 95859de0..2df001c4 100644 --- a/core/e2dmacros.h +++ b/core/base/macros.h @@ -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 #include -#include -#include -#include -#include -#include -#include -#include -#include -#include // C++ RunTime Header Files +#include #include #include #include -#include #include -#include -#include -#include -#include -#include #include -#include - -// 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__ diff --git a/core/base/modules.cpp b/core/base/modules.cpp new file mode 100644 index 00000000..530563cb --- /dev/null +++ b/core/base/modules.cpp @@ -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); + } + } +} \ No newline at end of file diff --git a/core/base/modules.h b/core/base/modules.h new file mode 100644 index 00000000..2ce3327a --- /dev/null +++ b/core/base/modules.h @@ -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 +#include +#include +#include + +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(); + } +} diff --git a/core/base/render.cpp b/core/base/render.cpp new file mode 100644 index 00000000..2dbe1d46 --- /dev/null +++ b/core/base/render.cpp @@ -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(&D2D.WICImagingFactory) + ) + ); + + ThrowIfFailed( + DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&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(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); + } + } + } +} diff --git a/core/actions/JumpBy.cpp b/core/base/render.h similarity index 53% rename from core/actions/JumpBy.cpp rename to core/base/render.h index 4a888f96..47ab40dc 100644 --- a/core/actions/JumpBy.cpp +++ b/core/base/render.h @@ -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; } -} \ No newline at end of file +} diff --git a/core/base/time.cpp b/core/base/time.cpp new file mode 100644 index 00000000..f14ee5c0 --- /dev/null +++ b/core/base/time.cpp @@ -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 + +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(time_).time_since_epoch(); + return static_cast(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(time_ - other.time_).count(); + return Duration(static_cast(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 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(sec) + static_cast(ms) / 1000.f; + } + + float Duration::Minutes() const + { + int64_t min = milliseconds_ / Minute.milliseconds_; + int64_t ms = milliseconds_ % Minute.milliseconds_; + return static_cast(min) + static_cast(ms) / (60 * 1000.f); + } + + float Duration::Hours() const + { + int64_t hour = milliseconds_ / Hour.milliseconds_; + int64_t ms = milliseconds_ % Hour.milliseconds_; + return static_cast(hour) + static_cast(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(milliseconds_ * value)); + } + + Duration Duration::operator/(float value) const + { + return Duration(static_cast(milliseconds_ / value)); + } + + Duration Duration::operator*(double value) const + { + return Duration(static_cast(milliseconds_ * value)); + } + + Duration Duration::operator/(double value) const + { + return Duration(static_cast(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(milliseconds_ * value); + return (*this); + } + + Duration & Duration::operator/=(float value) + { + milliseconds_ = static_cast(milliseconds_ / value); + return (*this); + } + + Duration & Duration::operator*=(double value) + { + milliseconds_ = static_cast(milliseconds_ * value); + return (*this); + } + + Duration & Duration::operator/=(double value) + { + milliseconds_ = static_cast(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; + } + } +} \ No newline at end of file diff --git a/core/base/time.h b/core/base/time.h new file mode 100644 index 00000000..fe46906c --- /dev/null +++ b/core/base/time.h @@ -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 + +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); + } +} \ No newline at end of file diff --git a/core/base/window.cpp b/core/base/window.cpp new file mode 100644 index 00000000..ddcc67df --- /dev/null +++ b/core/base/window.cpp @@ -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 +#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(client_rect.origin.x), + static_cast(client_rect.origin.y), + static_cast(client_rect.size.width), + static_cast(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(rect.right - rect.left), + static_cast(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(rect.origin.x), + static_cast(rect.origin.y), + static_cast(rect.size.width), + static_cast(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(GetDeviceCaps(dc, LOGPIXELSX)); + float ydpi = static_cast(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(math::Ceil(width * instance.xscale)), + static_cast(math::Ceil(height * instance.yscale)) + }; + + // ¼ÆËãºÏÊʵĴ°¿Ú´óС + ::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); + width = static_cast(rect.right - rect.left); + height = static_cast(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((max_width - width) / 2), + static_cast((max_height - height) / 2), + static_cast(width), + static_cast(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( + static_cast(::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; + } + } + } +} \ No newline at end of file diff --git a/core/transitions/BoxTransition.cpp b/core/base/window.h similarity index 57% rename from core/transitions/BoxTransition.cpp rename to core/base/window.h index 74c1c3a4..ee9dc8f8 100644 --- a/core/transitions/BoxTransition.cpp +++ b/core/base/window.h @@ -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; } -} \ No newline at end of file +} diff --git a/core/components/Button.cpp b/core/components/Button.cpp deleted file mode 100644 index adf4ffbc..00000000 --- a/core/components/Button.cpp +++ /dev/null @@ -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); - } - } - } -} \ No newline at end of file diff --git a/core/e2dcomponent.h b/core/e2dcomponent.h deleted file mode 100644 index d946078e..00000000 --- a/core/e2dcomponent.h +++ /dev/null @@ -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 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& buttons /* °´Å¥Êý×é */ - ); - - // »ñÈ¡²Ëµ¥ÊÇ·ñ½ûÓà - bool IsEnable() const; - - // »ñÈ¡²Ëµ¥Öеİ´Å¥ÊýÁ¿ - size_t GetButtonCount() const; - - // ÉèÖò˵¥ÆôÓûò½ûÓà - void SetEnabled( - bool enabled - ); - - // Ìí¼Ó°´Å¥ - void AddButton( - Button * button - ); - - // ÒÆ³ý°´Å¥ - bool RemoveButton( - Button * button - ); - - // »ñÈ¡ËùÓа´Å¥ - const std::vector& GetAllButtons() const; - - private: - E2D_DISABLE_COPY(Menu); - - private: - bool enabled_; - std::vector buttons_; - }; - -} // end of easy2d namespace - - -#endif // !__E2D_COMPONENT_H__ diff --git a/core/e2dmodule.h b/core/e2dmodule.h deleted file mode 100644 index 45a7bcca..00000000 --- a/core/e2dmodule.h +++ /dev/null @@ -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(); - - // ¼ì²â¼üÅÌij°´¼üÊÇ·ñÕý±»°´Ï - 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__ diff --git a/core/e2dobject.h b/core/e2dobject.h deleted file mode 100644 index 8272c537..00000000 --- a/core/e2dobject.h +++ /dev/null @@ -1,1106 +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_OBJECT_H__ -#define __E2D_OBJECT_H__ - - -#include "e2dutil.h" -#include "e2devent.h" - - -namespace easy2d -{ - - // ͼƬ - class Image - : public Ref - { - public: - Image(); - - explicit Image( - Resource& res - ); - - explicit Image( - Resource& res, - const Rect& crop_rect /* ²Ã¼ô¾ØÐÎ */ - ); - - explicit Image( - const std::wstring& file_name - ); - - explicit Image( - const std::wstring& file_name, - const Rect& crop_rect /* ²Ã¼ô¾ØÐÎ */ - ); - - virtual ~Image(); - - // ¼ÓÔØÍ¼Æ¬×ÊÔ´ - bool Load( - Resource& res - ); - - // ¼ÓÔØÍ¼Æ¬×ÊÔ´ - bool Load( - const std::wstring& 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 std::wstring& file_name - ); - - // »º´æ Bitmap ×ÊÔ´ - static bool CacheBitmap( - Resource& res - ); - - // ÉèÖà Bitmap - void SetBitmap( - ID2D1Bitmap * bitmap - ); - - private: - Rect crop_rect_; - ID2D1Bitmap * bitmap_; - - static std::map bitmap_cache_; - }; - - - class Node; - - // ³¡¾° - class Scene - : public Ref - { - public: - Scene(); - - explicit Scene( - Node * root - ); - - virtual ~Scene(); - - // ½øÈ볡¾° - virtual void OnEnter() {} - - // Í˳ö³¡¾° - virtual void OnExit() {} - - // ¸üг¡¾° - virtual void OnUpdate(float dt) {} - - // ÉèÖøù½Úµã - void SetRoot( - Node * root - ); - - // »ñÈ¡¸ù½Úµã - 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_; - }; - - - // ¶¨Ê±ÈÎÎñ - class Task - : public Ref - { - friend class Node; - - typedef std::function Callback; - - public: - explicit Task( - const Callback& func, /* Ö´Ðк¯Êý */ - const std::wstring& name = L"" /* ÈÎÎñÃû³Æ */ - ); - - explicit Task( - const Callback& func, /* Ö´Ðк¯Êý */ - float delay, /* ʱ¼ä¼ä¸ô£¨Ã룩 */ - int times = -1, /* Ö´ÐдÎÊý£¨Éè -1 ΪÓÀ¾ÃÖ´ÐУ© */ - const std::wstring& name = L"" /* ÈÎÎñÃû³Æ */ - ); - - // Æô¶¯ÈÎÎñ - void Start(); - - // Í£Ö¹ÈÎÎñ - void Stop(); - - // ÈÎÎñÊÇ·ñÕýÔÚÖ´ÐÐ - bool IsRunning() const; - - // »ñÈ¡ÈÎÎñÃû³Æ - const std::wstring& GetName() const; - - // ÈÎÎñÊÇ·ñ¾ÍÐ÷ - bool IsReady() const; - - // Ö´ÐÐÈÎÎñ - void Update(); - - // ÖØÖüÆÊ± - void ResetTime(); - - private: - bool running_; - bool stopped_; - int run_times_; - int total_times_; - std::wstring name_; - Duration delay_; - Time last_time_; - Callback callback_; - Node * target_; - }; - - - // °´¼üÏûÏ¢´¦Àí½Ó¿Ú - class KeyEventHandler - { - public: - // ´¦Àí°´¼üÏûÏ¢ - virtual void Handle(KeyEvent e) = 0; - }; - - - // Êó±êÏûÏ¢´¦Àí½Ó¿Ú - class MouseEventHandler - { - public: - // ´¦ÀíÊó±êÏûÏ¢ - virtual void Handle(MouseEvent e) = 0; - }; - - - class Action; - - // ½Úµã - class Node - : public Ref - { - friend class Game; - friend class Scene; - - public: - typedef std::vector Nodes; - typedef std::vector Actions; - typedef std::vector Tasks; - - Node(); - - virtual ~Node(); - - // äÖȾ½Úµã - virtual void OnDraw() const {} - - // ¸üнڵã - virtual void OnUpdate(float dt) {} - - // »ñÈ¡½ÚµãÏÔʾ״̬ - bool IsVisible() const; - - // »ñÈ¡½ÚµãÃû³Æ - const std::wstring& 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 Transform& GetTransform() const; - - // »ñÈ¡½Úµã͸Ã÷¶È - float GetOpacity() const; - - // »ñÈ¡ÏÔʾ͸Ã÷¶È - float GetDisplayOpacity() const; - - // »ñÈ¡¸¸½Úµã - Node * GetParent() const; - - // »ñÈ¡½ÚµãËùÔÚ³¡¾° - Scene * GetParentScene() const; - - // ÉèÖýڵãÊÇ·ñÏÔʾ - void SetVisible( - bool value - ); - - // ÉèÖýڵãÃû³Æ - void SetName( - const std::wstring& 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 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 std::wstring& name - ) const; - - // »ñÈ¡Ãû³ÆÏàͬµÄ×Ó½Úµã - Node* GetChild( - const std::wstring& name - ) const; - - // »ñÈ¡ËùÓÐ×Ó½Úµã - const Nodes& GetAllChildren() const; - - // »ñÈ¡×Ó½ÚµãÊýÁ¿ - int GetChildrenCount() const; - - // ÒÆ³ý×Ó½Úµã - bool RemoveChild( - Node * child - ); - - // ÒÆ³ýËùÓÐÃû³ÆÏàͬµÄ×Ó½Úµã - void RemoveChildren( - const std::wstring& child_name - ); - - // ÒÆ³ýËùÓнڵã - void RemoveAllChildren(); - - // ´Ó¸¸½ÚµãÒÆ³ý - void RemoveFromParent(); - - // Ö´Ðж¯×÷ - void RunAction( - Action * action - ); - - // ¼ÌÐø¶¯×÷ - void ResumeAction( - const std::wstring& name - ); - - // ÔÝÍ£¶¯×÷ - void PauseAction( - const std::wstring& name - ); - - // Í£Ö¹¶¯×÷ - void StopAction( - const std::wstring& name - ); - - // ¼ÌÐøËùÓÐÔÝÍ£¶¯×÷ - void ResumeAllActions(); - - // ÔÝÍ£ËùÓж¯×÷ - void PauseAllActions(); - - // Í£Ö¹ËùÓж¯×÷ - void StopAllActions(); - - // »ñÈ¡ËùÓж¯×÷ - const Actions& GetAllActions() const; - - // Ìí¼ÓÈÎÎñ - void AddTask( - Task * task - ); - - // Æô¶¯ÈÎÎñ - void StartTasks( - const std::wstring& task_name - ); - - // Í£Ö¹ÈÎÎñ - void StopTasks( - const std::wstring& task_name - ); - - // ÒÆ³ýÈÎÎñ - void RemoveTasks( - const std::wstring& 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: - std::wstring name_; - size_t hash_name_; - 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_; - }; - - - // ¾«Áé - class Sprite - : public Node - { - public: - Sprite(); - - explicit Sprite( - Image * image - ); - - explicit Sprite( - Resource& res - ); - - explicit Sprite( - Resource& res, - const Rect& crop_rect /* ²Ã¼ô¾ØÐÎ */ - ); - - explicit Sprite( - const std::wstring& file_name - ); - - explicit Sprite( - const std::wstring& file_name, - const Rect& crop_rect /* ²Ã¼ô¾ØÐÎ */ - ); - - virtual ~Sprite(); - - // ¼ÓÔØÍ¼Æ¬Îļþ - bool Load( - Resource& res - ); - - // ¼ÓÔØÍ¼Æ¬Îļþ - bool Load( - const std::wstring& file_name - ); - - // ¼ÓÔØÍ¼Æ¬ - 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_; - }; - - - // Îı¾ - 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 std::wstring& text, /* ÎÄ×ÖÄÚÈÝ */ - const Font& font = Font(), /* ×ÖÌå */ - const Style& style = Style() /* Îı¾Ñùʽ */ - ); - - virtual ~Text(); - - // »ñÈ¡Îı¾ - const std::wstring& GetText() const; - - // »ñÈ¡×ÖÌå - const Font& GetFont() const; - - // »ñÈ¡Îı¾Ñùʽ - const Style& GetStyle() const; - - // »ñÈ¡×ÖÌå×å - const std::wstring& 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 std::wstring& text - ); - - // ÉèÖÃÎı¾Ñùʽ - void SetStyle( - const Style& style - ); - - // ÉèÖÃ×ÖÌå - void SetFont( - const Font& font - ); - - // ÉèÖÃ×ÖÌå×å - void SetFontFamily( - const std::wstring& 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: - std::wstring text_; - Font font_; - Style style_; - IDWriteTextFormat* text_format_; - IDWriteTextLayout* text_layout_; - }; - - - // »­²¼ - 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_; - }; - -} // end of easy2d namespace - - -#endif // __E2D_OBJECT_H__ diff --git a/core/e2dtool.h b/core/e2dtool.h deleted file mode 100644 index 948f831d..00000000 --- a/core/e2dtool.h +++ /dev/null @@ -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 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 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__ diff --git a/core/e2dutil.h b/core/e2dutil.h deleted file mode 100644 index cf5db84a..00000000 --- a/core/e2dutil.h +++ /dev/null @@ -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 - 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 - static T RandomInt(T min, T max) - { - std::uniform_int_distribution dist(min, max); - return dist(Random::GetEngine()); - } - - template - static T RandomReal(T min, T max) - { - std::uniform_real_distribution 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 - 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(hr)); - throw std::runtime_error(s_str); - } - } - -} // end of easy2d namespace - - -#endif // __E2D_UTIL_H__ diff --git a/core/easy2d.h b/core/easy2d.h index a7b2227f..1f423a5f 100644 --- a/core/easy2d.h +++ b/core/easy2d.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) diff --git a/core/events/KeyEvent.cpp b/core/events/KeyEvent.cpp deleted file mode 100644 index 0c2953b0..00000000 --- a/core/events/KeyEvent.cpp +++ /dev/null @@ -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((DWORD)l_param_ & 0x0000FFFF); - } - - KeyEvent::Type KeyEvent::GetType() const - { - return Type(message_); - } -} \ No newline at end of file diff --git a/core/math/Matrix.hpp b/core/math/Matrix.hpp new file mode 100644 index 00000000..baf613be --- /dev/null +++ b/core/math/Matrix.hpp @@ -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 + ); + } + }; + } +} diff --git a/core/math/Transform.cpp b/core/math/Transform.cpp new file mode 100644 index 00000000..ecfe3192 --- /dev/null +++ b/core/math/Transform.cpp @@ -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; + } + } +} \ No newline at end of file diff --git a/core/math/Transform.h b/core/math/Transform.h new file mode 100644 index 00000000..b733ea18 --- /dev/null +++ b/core/math/Transform.h @@ -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 + +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; + }; + } +} diff --git a/core/actions/FadeOut.cpp b/core/math/rand.cpp similarity index 84% rename from core/actions/FadeOut.cpp rename to core/math/rand.cpp index 11a9384e..5f86ea55 100644 --- a/core/actions/FadeOut.cpp +++ b/core/math/rand.cpp @@ -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; + } } -} \ No newline at end of file +} diff --git a/core/math/rand.h b/core/math/rand.h new file mode 100644 index 00000000..bc300486 --- /dev/null +++ b/core/math/rand.h @@ -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 + +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 + static T RandomInt(T min, T max) + { + std::uniform_int_distribution dist(min, max); + return dist(GetRandomEngine()); + } + + template + static T RandomReal(T min, T max) + { + std::uniform_real_distribution 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( + RandomInt(static_cast(min), static_cast(max)) + ); + } + + inline unsigned char Rand(unsigned char min, unsigned char max) + { + return static_cast( + RandomInt(static_cast(min), static_cast(max)) + ); + } + + inline float Rand(float min, float max) + { + return RandomReal(min, max); + } + + inline double Range(double min, double max) + { + return RandomReal(min, max); + } + } +} \ No newline at end of file diff --git a/core/utils/Point.cpp b/core/math/scalar.hpp similarity index 54% rename from core/utils/Point.cpp rename to core/math/scalar.hpp index 2243336e..423240aa 100644 --- a/core/utils/Point.cpp +++ b/core/math/scalar.hpp @@ -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 - 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); } } -} \ No newline at end of file +} diff --git a/core/math/vector.hpp b/core/math/vector.hpp new file mode 100644 index 00000000..0d1f1c40 --- /dev/null +++ b/core/math/vector.hpp @@ -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(); + } + }; + } +} \ No newline at end of file diff --git a/core/modules/Game.cpp b/core/modules/Game.cpp deleted file mode 100644 index f0c5ddf9..00000000 --- a/core/modules/Game.cpp +++ /dev/null @@ -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 -#include -#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 ¿ªÆôÁË´¹Ö±Í¬²½£¬ÔÚäÖȾʱ»áµÈ´ýÏÔʾÆ÷ˢУ¬ - // ËüÆðµ½Á˷dz£Îȶ¨µÄÑÓʱ×÷Óã¬ËùÒԴ󲿷Öʱºò²»ÐèÒªÊÖ¶¯¹ÒÆðÏ߳̽øÐÐÑÓʱ¡£ - // ÏÂÃæµÄ´úÂë½öÔÚһЩÇé¿öÏ£¨ÀýÈç´°¿Ú×îС»¯Ê±£©¹ÒÆðỊ̈߳¬·ÀÖ¹Õ¼Óùý¸ß 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(rect.right - rect.left); - height = static_cast(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((max_width - width) / 2), - static_cast((max_height - height) / 2), - static_cast(width), - static_cast(height) - ); - } - - int Game::GetWidth() const - { - return width_; - } - - int Game::GetHeight() const - { - return height_; - } - - Size Game::GetSize() const - { - return Size( - static_cast(width_), - static_cast(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( - static_cast(::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(width * 96.f / dpi); - game->height_ = static_cast(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; - } -} \ No newline at end of file diff --git a/core/modules/Graphics.cpp b/core/modules/Graphics.cpp deleted file mode 100644 index d26dfc2d..00000000 --- a/core/modules/Graphics.cpp +++ /dev/null @@ -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(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(&imaging_factory_) - ) - ); - - ThrowIfFailed( - DWriteCreateFactory( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&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(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(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(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(::GetDeviceCaps(hdc, LOGPIXELSX)); - ::ReleaseDC(0, hdc); - } - return dpi; - } -} \ No newline at end of file diff --git a/core/modules/Input.cpp b/core/modules/Input.cpp deleted file mode 100644 index 96ceed47..00000000 --- a/core/modules/Input.cpp +++ /dev/null @@ -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(key)] & 0x80) - return true; - return false; - } - - bool Input::IsDown(MouseCode code) - { - if (mouse_state_.rgbButtons[static_cast(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; - } -} \ No newline at end of file diff --git a/core/tools/Music.cpp b/core/tools/Music.cpp deleted file mode 100644 index 4e07a1f9..00000000 --- a/core/tools/Music.cpp +++ /dev/null @@ -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(res.GetData()), - static_cast(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( - (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_; - } -} \ No newline at end of file diff --git a/core/transitions/MoveTransition.cpp b/core/transitions/MoveTransition.cpp deleted file mode 100644 index 675efb9d..00000000 --- a/core/transitions/MoveTransition.cpp +++ /dev/null @@ -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()); - } - } -} \ No newline at end of file diff --git a/core/transitions/RotationTransition.cpp b/core/transitions/RotationTransition.cpp deleted file mode 100644 index 9648efba..00000000 --- a/core/transitions/RotationTransition.cpp +++ /dev/null @@ -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()); - } - } -} \ No newline at end of file diff --git a/core/transitions/Transition.cpp b/core/transitions/Transition.cpp deleted file mode 100644 index 3ec33296..00000000 --- a/core/transitions/Transition.cpp +++ /dev/null @@ -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(); - } -} \ No newline at end of file diff --git a/core/ui/Button.cpp b/core/ui/Button.cpp new file mode 100644 index 00000000..252f49f8 --- /dev/null +++ b/core/ui/Button.cpp @@ -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); + } + } + } + } +} \ No newline at end of file diff --git a/core/ui/Button.h b/core/ui/Button.h new file mode 100644 index 00000000..705d97f6 --- /dev/null +++ b/core/ui/Button.h @@ -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 + +namespace easy2d +{ + namespace ui + { + class Button + : public Node + { + typedef std::function 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_; + }; + } +} \ No newline at end of file diff --git a/core/components/Menu.cpp b/core/ui/Menu.cpp similarity index 52% rename from core/components/Menu.cpp rename to core/ui/Menu.cpp index c51f7002..6e46bfb9 100644 --- a/core/components/Menu.cpp +++ b/core/ui/Menu.cpp @@ -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& 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& 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& 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& Menu::GetAllButtons() const - { - return buttons_; } } \ No newline at end of file diff --git a/core/ui/Menu.h b/core/ui/Menu.h new file mode 100644 index 00000000..26bba220 --- /dev/null +++ b/core/ui/Menu.h @@ -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& buttons /* °´Å¥Êý×é */ + ); + + // »ñÈ¡²Ëµ¥ÊÇ·ñ½ûÓà + bool IsEnable() const; + + // »ñÈ¡²Ëµ¥Öеİ´Å¥ÊýÁ¿ + size_t GetButtonCount() const; + + // ÉèÖò˵¥ÆôÓûò½ûÓà + void SetEnabled( + bool enabled + ); + + // Ìí¼Ó°´Å¥ + void AddButton( + Button * button + ); + + // ÒÆ³ý°´Å¥ + bool RemoveButton( + Button * button + ); + + // »ñÈ¡ËùÓа´Å¥ + const std::vector& GetAllButtons() const; + + private: + E2D_DISABLE_COPY(Menu); + + private: + bool enabled_; + std::vector buttons_; + }; + } +} \ No newline at end of file diff --git a/core/tools/Data.cpp b/core/utils/Data.cpp similarity index 94% rename from core/tools/Data.cpp rename to core/utils/Data.cpp index cafaa9a7..1ebe8b9a 100644 --- a/core/tools/Data.cpp +++ b/core/utils/Data.cpp @@ -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( diff --git a/core/actions/MoveBy.cpp b/core/utils/Data.h similarity index 57% rename from core/actions/MoveBy.cpp rename to core/utils/Data.h index 4910320b..1efd9717 100644 --- a/core/actions/MoveBy.cpp +++ b/core/utils/Data.h @@ -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_); - } -} \ No newline at end of file + // »ñÈ¡ float ÀàÐ͵ÄÖµ + float GetFloat() const; + + // »ñÈ¡ double ÀàÐ͵ÄÖµ + double GetDouble() const; + + // »ñÈ¡ bool ÀàÐ͵ÄÖµ + bool GetBool() const; + + // »ñÈ¡ ×Ö·û´® ÀàÐ͵ÄÖµ + String GetString(); + + protected: + String key_; + String field_; + const String& data_path_; + }; +} diff --git a/core/utils/Duration.cpp b/core/utils/Duration.cpp deleted file mode 100644 index 5676bb93..00000000 --- a/core/utils/Duration.cpp +++ /dev/null @@ -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 - - -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 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(sec) + static_cast(ms) / 1000.f; - } - - float Duration::Minutes() const - { - int64_t min = milliseconds_ / Minute.milliseconds_; - int64_t ms = milliseconds_ % Minute.milliseconds_; - return static_cast(min) + static_cast(ms) / (60 * 1000.f); - } - - float Duration::Hours() const - { - int64_t hour = milliseconds_ / Hour.milliseconds_; - int64_t ms = milliseconds_ % Hour.milliseconds_; - return static_cast(hour) + static_cast(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(milliseconds_ * value)); - } - - Duration Duration::operator/(float value) const - { - return Duration(static_cast(milliseconds_ / value)); - } - - Duration Duration::operator*(double value) const - { - return Duration(static_cast(milliseconds_ * value)); - } - - Duration Duration::operator/(double value) const - { - return Duration(static_cast(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(milliseconds_ * value); - return (*this); - } - - Duration & Duration::operator/=(float value) - { - milliseconds_ = static_cast(milliseconds_ / value); - return (*this); - } - - Duration & Duration::operator*=(double value) - { - milliseconds_ = static_cast(milliseconds_ * value); - return (*this); - } - - Duration & Duration::operator/=(double value) - { - milliseconds_ = static_cast(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; - } - -} diff --git a/core/tools/File.cpp b/core/utils/File.cpp similarity index 85% rename from core/tools/File.cpp rename to core/utils/File.cpp index bb941b5f..0f28c254 100644 --- a/core/tools/File.cpp +++ b/core/utils/File.cpp @@ -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 -#include +#include +#include + +#pragma comment(lib, "shlwapi.lib") namespace easy2d { - std::list File::search_paths_; + std::list 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() } diff --git a/core/utils/File.h b/core/utils/File.h new file mode 100644 index 00000000..52aa596d --- /dev/null +++ b/core/utils/File.h @@ -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 search_paths_; + }; +} diff --git a/core/utils/Music.cpp b/core/utils/Music.cpp new file mode 100644 index 00000000..1fd38d87 --- /dev/null +++ b/core/utils/Music.cpp @@ -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_; + } +} \ No newline at end of file diff --git a/core/utils/Music.h b/core/utils/Music.h new file mode 100644 index 00000000..4839168e --- /dev/null +++ b/core/utils/Music.h @@ -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 + +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_; + }; +} diff --git a/core/tools/Path.cpp b/core/utils/Path.cpp similarity index 79% rename from core/tools/Path.cpp rename to core/utils/Path.cpp index 7938874e..1c435442 100644 --- a/core/tools/Path.cpp +++ b/core/utils/Path.cpp @@ -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 - 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{}(title)); + String local_app_data_path = Path::GetLocalAppDataPath(); + String title = window::instance.GetTitle(); + String folder_name = std::to_wstring(std::hash{}(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{}(title)); + String title = window::instance.GetTitle(); + String folder_name = std::to_wstring(std::hash{}(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 }; diff --git a/core/actions/RotateTo.cpp b/core/utils/Path.h similarity index 76% rename from core/actions/RotateTo.cpp rename to core/utils/Path.h index 0b77c65c..e68b8c7c 100644 --- a/core/actions/RotateTo.cpp +++ b/core/utils/Path.h @@ -18,26 +18,25 @@ // 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 { - RotateTo::RotateTo(float duration, float rotation) - : RotateBy(duration, 0) + // ·¾¶ + class Path { - end_val_ = rotation; - } + public: + // »ñÈ¡Êý¾ÝµÄĬÈϱ£´æÂ·¾¶ + static const String& GetDataPath(); - RotateTo * RotateTo::Clone() const - { - return new RotateTo(duration_, end_val_); - } + // »ñÈ¡ÁÙʱÎļþĿ¼ + static const String& GetTemporaryPath(); - void RotateTo::Init() - { - RotateBy::Init(); - delta_val_ = end_val_ - start_val_; - } -} \ No newline at end of file + // »ñÈ¡ LocalAppData Ŀ¼ + static const String& GetLocalAppDataPath(); + + // »ñÈ¡µ±Ç°³ÌÐòµÄÔËÐз¾¶ + static const String& GetExeFilePath(); + }; +} diff --git a/core/tools/Player.cpp b/core/utils/Player.cpp similarity index 62% rename from core/tools/Player.cpp rename to core/utils/Player.cpp index 384e6fa8..f4642c13 100644 --- a/core/tools/Player.cpp +++ b/core/utils/Player.cpp @@ -1,9 +1,32 @@ -#include "..\e2dtool.h" +// 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 "Player.h" +#include "Music.h" namespace easy2d { - std::map Player::musics_; + namespace + { + std::map musics_; + } Player::Player() : volume_(1.f) @@ -14,7 +37,7 @@ namespace easy2d { } - bool Player::Load(const std::wstring & file_path) + bool Player::Load(const String & file_path) { if (file_path.empty()) return false; @@ -27,7 +50,7 @@ namespace easy2d { music->SetVolume(volume_); - size_t hash_code = std::hash{}(file_path); + size_t hash_code = std::hash{}(file_path); musics_.insert(std::make_pair(hash_code, music)); return true; } @@ -39,14 +62,14 @@ namespace easy2d return false; } - bool Player::Play(const std::wstring & file_path, int loop_count) + bool Player::Play(const String & file_path, int loop_count) { if (file_path.empty()) return false; if (Load(file_path)) { - auto music = musics_[std::hash{}(file_path)]; + auto music = musics_[std::hash{}(file_path)]; if (music->Play(loop_count)) { return true; @@ -55,42 +78,42 @@ namespace easy2d return false; } - void Player::Pause(const std::wstring & file_path) + void Player::Pause(const String & file_path) { if (file_path.empty()) return; - size_t hash_code = std::hash{}(file_path); + size_t hash_code = std::hash{}(file_path); if (musics_.end() != musics_.find(hash_code)) musics_[hash_code]->Pause(); } - void Player::Resume(const std::wstring & file_path) + void Player::Resume(const String & file_path) { if (file_path.empty()) return; - size_t hash_code = std::hash{}(file_path); + size_t hash_code = std::hash{}(file_path); if (musics_.end() != musics_.find(hash_code)) musics_[hash_code]->Resume(); } - void Player::Stop(const std::wstring & file_path) + void Player::Stop(const String & file_path) { if (file_path.empty()) return; - size_t hash_code = std::hash{}(file_path); + size_t hash_code = std::hash{}(file_path); if (musics_.end() != musics_.find(hash_code)) musics_[hash_code]->Stop(); } - bool Player::IsPlaying(const std::wstring & file_path) + bool Player::IsPlaying(const String & file_path) { if (file_path.empty()) return false; - size_t hash_code = std::hash{}(file_path); + size_t hash_code = std::hash{}(file_path); if (musics_.end() != musics_.find(hash_code)) return musics_[hash_code]->IsPlaying(); return false; diff --git a/core/utils/Player.h b/core/utils/Player.h new file mode 100644 index 00000000..91ecfc5f --- /dev/null +++ b/core/utils/Player.h @@ -0,0 +1,123 @@ +// 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 Player + { + public: + Player(); + + ~Player(); + + // Ô¤¼ÓÔØÒôÀÖ×ÊÔ´ + bool Load( + const String& file_path /* ÒôÀÖÎļþ·¾¶ */ + ); + + // ²¥·ÅÒôÀÖ + bool Play( + const String& file_path, /* ÒôÀÖÎļþ·¾¶ */ + int loop_count = 0 /* ²¥·ÅÑ­»·´ÎÊý (-1 Ϊѭ»·²¥·Å) */ + ); + + // ÔÝÍ£ÒôÀÖ + void Pause( + const String& file_path /* ÒôÀÖÎļþ·¾¶ */ + ); + + // ¼ÌÐø²¥·ÅÒôÀÖ + void Resume( + const String& file_path /* ÒôÀÖÎļþ·¾¶ */ + ); + + // Í£Ö¹ÒôÀÖ + void Stop( + const String& file_path /* ÒôÀÖÎļþ·¾¶ */ + ); + + // »ñÈ¡ÒôÀÖ²¥·Å״̬ + bool IsPlaying( + const String& 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_; + }; +} diff --git a/core/utils/Rect.cpp b/core/utils/Rect.cpp deleted file mode 100644 index cff5859c..00000000 --- a/core/utils/Rect.cpp +++ /dev/null @@ -1,78 +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" - -namespace easy2d -{ - Rect::Rect(void) - : origin() - , size() - { - } - - Rect::Rect(float x, float y, float width, float height) - : origin(x, y) - , size(width, height) - { - } - - Rect::Rect(const Point& pos, const Size& size) - : origin(pos.x, pos.y) - , size(size.width, size.height) - { - } - - Rect::Rect(const Rect& other) - : origin(other.origin.x, other.origin.y) - , size(other.size.width, other.size.height) - { - } - - Rect& Rect::operator= (const Rect& other) - { - origin = other.origin; - size = other.size; - return *this; - } - - bool Rect::operator==(const Rect & rect) const - { - return (origin == rect.origin) && (size == rect.size); - } - - bool Rect::ContainsPoint(const Point& point) const - { - if (point.x >= origin.x && point.x <= (origin.y + size.height) - && point.y >= origin.y && point.y <= (origin.y + size.height)) - { - return true; - } - return false; - } - - bool Rect::Intersects(const Rect& rect) const - { - return !((origin.x + size.width) < rect.origin.x || - (rect.origin.x + rect.size.width) < origin.x || - (origin.y + size.height) < rect.origin.y || - (rect.origin.y + rect.size.height) < origin.y); - } -} \ No newline at end of file diff --git a/core/utils/Time.cpp b/core/utils/Time.cpp deleted file mode 100644 index 3af19e4e..00000000 --- a/core/utils/Time.cpp +++ /dev/null @@ -1,108 +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" - -namespace easy2d -{ - using namespace std::chrono; - - - Time::Time() - { - } - - Time::Time(std::chrono::steady_clock::time_point time) - : time_(time) - { - } - - Time::Time(const Time & other) - : time_(other.time_) - { - } - - Time::Time(Time && other) - : time_(std::move(other.time_)) - { - } - - time_t Time::GetTimeStamp() const - { - auto& duration = time_point_cast(time_).time_since_epoch(); - return static_cast(duration.count()); - } - - bool Time::IsZero() const - { - return time_.time_since_epoch().count() == 0LL; - } - - Time Time::operator+(const Duration & other) const - { - return Time(time_ + milliseconds(other.Milliseconds())); - } - - Time Time::operator-(const Duration & other) const - { - return Time(time_ - milliseconds(other.Milliseconds())); - } - - Time & Time::operator+=(const Duration & other) - { - time_ += milliseconds(other.Milliseconds()); - return (*this); - } - - Time & Time::operator-=(const Duration &other) - { - time_ -= milliseconds(other.Milliseconds()); - return (*this); - } - - Duration Time::operator-(const Time & other) const - { - auto ms = duration_cast(time_ - other.time_).count(); - return Duration(static_cast(ms)); - } - - Time& Time::operator=(const Time & other) E2D_NOEXCEPT - { - if (this == &other) - return *this; - - time_ = other.time_; - return *this; - } - - Time& Time::operator=(Time && other) E2D_NOEXCEPT - { - if (this == &other) - return *this; - - time_ = std::move(other.time_); - return *this; - } - - Time Time::Now() - { - return Time(steady_clock::now()); - } -} \ No newline at end of file diff --git a/core/utils/Transcoder.cpp b/core/utils/Transcoder.cpp new file mode 100644 index 00000000..0e7429f2 --- /dev/null +++ b/core/utils/Transcoder.cpp @@ -0,0 +1,273 @@ +// 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 "Transcoder.h" +#include "../base/base.h" +#include "../base/modules.h" +#include "../base/logs.h" +#include + +namespace easy2d +{ + Transcoder::Transcoder() + : wave_format_(nullptr) + { + } + + Transcoder::~Transcoder() + { + if (wave_format_) + { + ::CoTaskMemFree(wave_format_); + wave_format_ = nullptr; + } + } + + WAVEFORMATEX* Transcoder::GetWaveFormatEx() const + { + return wave_format_; + } + + bool Transcoder::LoadMediaFile(LPCWSTR file_path, BYTE** wave_data, UINT32* wave_data_size) + { + HRESULT hr = S_OK; + + IMFSourceReader* reader = nullptr; + + hr = modules::MediaFoundation.MFCreateSourceReaderFromURL( + file_path, + nullptr, + &reader + ); + + if (SUCCEEDED(hr)) + { + hr = ReadSource(reader, wave_data, wave_data_size); + } + + SafeRelease(reader); + + return SUCCEEDED(hr); + } + + bool Transcoder::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(res.GetData()), + static_cast(res.GetDataSize()) + ); + + if (stream == nullptr) + { + logs::Trace(L"SHCreateMemStream"); + return false; + } + + if (SUCCEEDED(hr)) + { + hr = modules::MediaFoundation.MFCreateMFByteStreamOnStream(stream, &byte_stream); + } + + if (SUCCEEDED(hr)) + { + hr = modules::MediaFoundation.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 Transcoder::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 = modules::MediaFoundation.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 = modules::MediaFoundation.MFCreateWaveFormatExFromMFMediaType( + uncompressed_type, + &wave_format_, + &size, + MFWaveFormatExConvertFlag_Normal + ); + } + + // ¹ÀËãÒôƵÁ÷´óС + 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( + (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) + { + logs::Trace(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; + } +} \ No newline at end of file diff --git a/core/actions/ScaleTo.cpp b/core/utils/Transcoder.h similarity index 66% rename from core/actions/ScaleTo.cpp rename to core/utils/Transcoder.h index 1980e572..e167e40c 100644 --- a/core/actions/ScaleTo.cpp +++ b/core/utils/Transcoder.h @@ -18,35 +18,42 @@ // 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/macros.h" +#include "../base/Resource.h" +#include +#include +#include namespace easy2d { - ScaleTo::ScaleTo(float duration, float scale) - : ScaleBy(duration, 0, 0) + class Transcoder { - end_scale_x_ = scale; - end_scale_y_ = scale; - } + WAVEFORMATEX* wave_format_; - ScaleTo::ScaleTo(float duration, float scale_x, float scale_y) - : ScaleBy(duration, 0, 0) - { - end_scale_x_ = scale_x; - end_scale_y_ = scale_y; - } + public: + Transcoder(); - ScaleTo * ScaleTo::Clone() const - { - return new ScaleTo(duration_, end_scale_x_, end_scale_y_); - } + ~Transcoder(); - void ScaleTo::Init() - { - ScaleBy::Init(); - delta_x_ = end_scale_x_ - start_scale_x_; - delta_y_ = end_scale_y_ - start_scale_y_; - } -} \ No newline at end of file + WAVEFORMATEX* GetWaveFormatEx() const; + + bool LoadMediaFile( + LPCWSTR file_path, + BYTE** wave_data, + UINT32* wave_data_size + ); + + bool LoadMediaResource( + Resource& res, + BYTE** wave_data, + UINT32* wave_data_size + ); + + HRESULT ReadSource( + IMFSourceReader* reader, + BYTE** wave_data, + UINT32* wave_data_size + ); + }; +} diff --git a/core/utils/Transform.cpp b/core/utils/Transform.cpp deleted file mode 100644 index caa8aa29..00000000 --- a/core/utils/Transform.cpp +++ /dev/null @@ -1,72 +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" - - -namespace easy2d -{ - Transform::Transform() - : position() - , size() - , scale_x(1.f) - , scale_y(1.f) - , rotation(0) - , skew_x(0) - , skew_y(0) - , pivot_x(0) - , pivot_y(0) - { - } - - 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; - } -} \ No newline at end of file diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index 17fa455a..28af00e8 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -18,6 +18,95 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {91DBDFCC-4083-427C-AAAD-55715118DB26} Win32Proj @@ -162,79 +251,6 @@ true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index 46a966d6..8b5933b3 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -1,220 +1,274 @@  - - - {be5d9314-b00a-4f11-bd2a-1f720dc32407} - - - {261633d3-3814-40c7-bd6d-201ede6c6ade} - - - {50293f38-87fe-4dde-b938-cf1b7a2921f8} - - - {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} - - - {563b19f2-4c5e-4362-983a-94d2ae724550} - - - {42d46a92-c043-4667-8c20-358319e5c313} - - - {51864c81-02ee-4043-bf09-9ce3cbe5b6da} - - - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - modules - - - modules - - - modules - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - components - - - components - - - events - - - events - - - tools - - - tools - - - tools - - - tools - - - tools - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - utils - - - utils - - - modules - - - modules - - - utils - - - - - - - - - - - + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + math + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + + + + + {896bdedf-6e82-449b-9b6e-0bc69f3699b1} + + + {80bc6386-2b70-4bae-993c-649a55163a1b} + + + {68eac919-ee87-4030-a033-c251731928f5} + + + {07b6d541-4a1b-472a-aae0-daf9d082fe84} + + + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + \ No newline at end of file diff --git a/project/vs2015/Easy2D.vcxproj b/project/vs2015/Easy2D.vcxproj index 21f55335..2279adf3 100644 --- a/project/vs2015/Easy2D.vcxproj +++ b/project/vs2015/Easy2D.vcxproj @@ -18,6 +18,95 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF} Win32Proj @@ -194,79 +283,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/project/vs2015/Easy2D.vcxproj.filters b/project/vs2015/Easy2D.vcxproj.filters index 5556be7b..8b5933b3 100644 --- a/project/vs2015/Easy2D.vcxproj.filters +++ b/project/vs2015/Easy2D.vcxproj.filters @@ -1,220 +1,274 @@  - - - {be5d9314-b00a-4f11-bd2a-1f720dc32407} - - - {261633d3-3814-40c7-bd6d-201ede6c6ade} - - - {50293f38-87fe-4dde-b938-cf1b7a2921f8} - - - {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} - - - {563b19f2-4c5e-4362-983a-94d2ae724550} - - - {42d46a92-c043-4667-8c20-358319e5c313} - - - {51864c81-02ee-4043-bf09-9ce3cbe5b6da} - - - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - modules - - - modules - - - modules - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - components - - - components - - - events - - - events - - - tools - - - tools - - - tools - - - tools - - - tools - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - utils - - - utils - - - modules - - - modules - - - utils - - - actions - - - - - - - - - - - + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + math + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + + + + + {896bdedf-6e82-449b-9b6e-0bc69f3699b1} + + + {80bc6386-2b70-4bae-993c-649a55163a1b} + + + {68eac919-ee87-4030-a033-c251731928f5} + + + {07b6d541-4a1b-472a-aae0-daf9d082fe84} + + + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + \ No newline at end of file diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 71efa195..80dcea56 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -18,12 +18,102 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15.0 {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF} Win32Proj Easy2D - + + @@ -201,79 +291,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index 5556be7b..8b5933b3 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -1,220 +1,274 @@  - - - {be5d9314-b00a-4f11-bd2a-1f720dc32407} - - - {261633d3-3814-40c7-bd6d-201ede6c6ade} - - - {50293f38-87fe-4dde-b938-cf1b7a2921f8} - - - {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} - - - {563b19f2-4c5e-4362-983a-94d2ae724550} - - - {42d46a92-c043-4667-8c20-358319e5c313} - - - {51864c81-02ee-4043-bf09-9ce3cbe5b6da} - - - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - actions - - - modules - - - modules - - - modules - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - utils - - - components - - - components - - - events - - - events - - - tools - - - tools - - - tools - - - tools - - - tools - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - transitions - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - objects - - - utils - - - utils - - - modules - - - modules - - - utils - - - actions - - - - - - - - - - - + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + math + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + + + + + {896bdedf-6e82-449b-9b6e-0bc69f3699b1} + + + {80bc6386-2b70-4bae-993c-649a55163a1b} + + + {68eac919-ee87-4030-a033-c251731928f5} + + + {07b6d541-4a1b-472a-aae0-daf9d082fe84} + + + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + base + + + math + + + math + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + ui + + + ui + \ No newline at end of file