[deploy] Merge pull request #56 from KiwanoEngine/dev
Merge develop branch
This commit is contained in:
commit
2efd06ade3
|
|
@ -17,11 +17,13 @@
|
|||
<ClInclude Include="..\..\src\kiwano\base\Director.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\base\Module.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\base\ObjectBase.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\base\ObjectPool.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\base\RefCounter.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Allocator.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Any.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Cloneable.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Common.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Defer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Exception.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Function.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\IntrusiveList.h" />
|
||||
|
|
@ -132,6 +134,7 @@
|
|||
<ClCompile Include="..\..\src\kiwano\base\Director.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\base\Module.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\base\ObjectBase.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\base\ObjectPool.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\base\RefCounter.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Allocator.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Exception.cpp" />
|
||||
|
|
|
|||
|
|
@ -351,6 +351,12 @@
|
|||
<ClInclude Include="..\..\src\kiwano\utils\ConfigIni.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\base\ObjectPool.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\core\Defer.h">
|
||||
<Filter>core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
|
||||
|
|
@ -575,6 +581,9 @@
|
|||
<ClCompile Include="..\..\src\kiwano\utils\ConfigIni.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\base\ObjectPool.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="suppress_warning.ruleset" />
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ public:
|
|||
|
||||
void DestroyModule() override;
|
||||
|
||||
~AudioModule();
|
||||
|
||||
private:
|
||||
AudioModule();
|
||||
|
||||
~AudioModule();
|
||||
|
||||
private:
|
||||
IXAudio2* x_audio2_;
|
||||
IXAudio2MasteringVoice* mastering_voice_;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
||||
#define KGE_PHYSIC_COMP_NAME "__KGE_PHYSIC_BODY__"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
|
|
@ -48,6 +50,25 @@ PhysicBodyPtr PhysicBody::Create(PhysicWorld* world, Type type)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PhysicBody* PhysicBody::Get(Actor* actor)
|
||||
{
|
||||
if (actor)
|
||||
{
|
||||
static size_t physic_comp_name_hash = 0;
|
||||
if (physic_comp_name_hash == 0)
|
||||
{
|
||||
physic_comp_name_hash = std::hash<String>{}(KGE_PHYSIC_COMP_NAME);
|
||||
}
|
||||
return (PhysicBody*)actor->GetComponent(physic_comp_name_hash);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PhysicBody* PhysicBody::Get(ActorPtr actor)
|
||||
{
|
||||
return PhysicBody::Get(actor.Get());
|
||||
}
|
||||
|
||||
PhysicBody::PhysicBody()
|
||||
: body_(nullptr)
|
||||
, world_(nullptr)
|
||||
|
|
@ -56,7 +77,7 @@ PhysicBody::PhysicBody()
|
|||
, mask_bits_(0xFFFF)
|
||||
, group_index_(0)
|
||||
{
|
||||
SetName("KGE_PHYSIC_BODY");
|
||||
SetName(KGE_PHYSIC_COMP_NAME);
|
||||
}
|
||||
|
||||
PhysicBody::~PhysicBody() {}
|
||||
|
|
@ -65,8 +86,6 @@ void PhysicBody::InitComponent(Actor* actor)
|
|||
{
|
||||
Component::InitComponent(actor);
|
||||
|
||||
actor->SetPhysicBody(this);
|
||||
|
||||
UpdateFromActor(actor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,16 @@ public:
|
|||
/// @param type ÎïÌåÀàÐÍ
|
||||
static PhysicBodyPtr Create(PhysicWorld* world, Type type);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取角色的物理身体
|
||||
/// @param actor 角色
|
||||
static PhysicBody* Get(Actor* actor);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取角色的物理身体
|
||||
/// @param actor 角色
|
||||
static PhysicBody* Get(ActorPtr actor);
|
||||
|
||||
PhysicBody();
|
||||
|
||||
virtual ~PhysicBody();
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ void PhysicWorld::BeforeSimulation(Actor* parent, const Matrix3x2& parent_to_wor
|
|||
{
|
||||
Matrix3x2 child_to_world = child->GetTransformMatrixToParent() * parent_to_world;
|
||||
|
||||
PhysicBody* body = child->GetPhysicBody();
|
||||
PhysicBody* body = PhysicBody::Get(child);
|
||||
if (body)
|
||||
{
|
||||
body->BeforeSimulation(child.Get(), parent_to_world, child_to_world, parent_rotation);
|
||||
|
|
@ -428,7 +428,7 @@ void PhysicWorld::AfterSimulation(Actor* parent, const Matrix3x2& parent_to_worl
|
|||
{
|
||||
for (auto child : parent->GetAllChildren())
|
||||
{
|
||||
PhysicBody* body = child->GetPhysicBody();
|
||||
PhysicBody* body = PhysicBody::Get(child);
|
||||
if (body)
|
||||
{
|
||||
body->AfterSimulation(child.Get(), parent_to_world, parent_rotation);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ Actor::Actor()
|
|||
, cascade_opacity_(false)
|
||||
, show_border_(false)
|
||||
, is_fast_transform_(true)
|
||||
, evt_dispatch_enabled_(true)
|
||||
, parent_(nullptr)
|
||||
, stage_(nullptr)
|
||||
, hash_name_(0)
|
||||
|
|
@ -66,7 +67,6 @@ Actor::Actor()
|
|||
, opacity_(1.f)
|
||||
, displayed_opacity_(1.f)
|
||||
, anchor_(default_anchor_x, default_anchor_y)
|
||||
, physic_body_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ bool Actor::CheckVisibility(RenderContext& ctx) const
|
|||
|
||||
bool Actor::DispatchEvent(Event* evt)
|
||||
{
|
||||
if (!visible_)
|
||||
if (!visible_ || !evt_dispatch_enabled_)
|
||||
return true;
|
||||
|
||||
// Dispatch to children those are greater than 0 in Z-Order
|
||||
|
|
@ -221,6 +221,11 @@ bool Actor::DispatchEvent(Event* evt)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Actor::SetEventDispatchEnabled(bool enabled)
|
||||
{
|
||||
evt_dispatch_enabled_ = enabled;
|
||||
}
|
||||
|
||||
void Actor::DoSerialize(Serializer* serializer) const
|
||||
{
|
||||
ObjectBase::DoSerialize(serializer);
|
||||
|
|
|
|||
|
|
@ -33,11 +33,6 @@ class Stage;
|
|||
class Director;
|
||||
class RenderContext;
|
||||
|
||||
namespace physics
|
||||
{
|
||||
class PhysicBody;
|
||||
}
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Actor);
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -110,6 +105,10 @@ public:
|
|||
/// @brief 是否启用级联透明度
|
||||
bool IsCascadeOpacityEnabled() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否启用事件分发
|
||||
bool IsEventDispatchEnabled() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取名称的 Hash 值
|
||||
size_t GetHashName() const;
|
||||
|
|
@ -391,14 +390,6 @@ public:
|
|||
/// @brief 获取更新时的回调函数
|
||||
UpdateCallback GetCallbackOnUpdate() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取物理身体,仅当kiwano-physics包启用时生效
|
||||
physics::PhysicBody* GetPhysicBody() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置物理身体,仅当kiwano-physics包启用时生效
|
||||
void SetPhysicBody(physics::PhysicBody* body);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 判断点是否在角色内
|
||||
virtual bool ContainsPoint(const Point& point) const;
|
||||
|
|
@ -421,6 +412,11 @@ public:
|
|||
/// @return 是否继续分发该事件
|
||||
virtual bool DispatchEvent(Event* evt);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开启或关闭事件分发功能
|
||||
/// @param enabled 是否开启
|
||||
void SetEventDispatchEnabled(bool enabled);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 序列化
|
||||
void DoSerialize(Serializer* serializer) const override;
|
||||
|
|
@ -482,6 +478,7 @@ private:
|
|||
bool hover_;
|
||||
bool pressed_;
|
||||
bool responsible_;
|
||||
bool evt_dispatch_enabled_;
|
||||
int z_order_;
|
||||
float opacity_;
|
||||
float displayed_opacity_;
|
||||
|
|
@ -502,8 +499,6 @@ private:
|
|||
mutable Matrix3x2 transform_matrix_;
|
||||
mutable Matrix3x2 transform_matrix_inverse_;
|
||||
mutable Matrix3x2 transform_matrix_to_parent_;
|
||||
|
||||
physics::PhysicBody* physic_body_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -533,6 +528,11 @@ inline bool Actor::IsCascadeOpacityEnabled() const
|
|||
return cascade_opacity_;
|
||||
}
|
||||
|
||||
inline bool Actor::IsEventDispatchEnabled() const
|
||||
{
|
||||
return evt_dispatch_enabled_;
|
||||
}
|
||||
|
||||
inline size_t Actor::GetHashName() const
|
||||
{
|
||||
return hash_name_;
|
||||
|
|
@ -688,16 +688,6 @@ inline Actor::UpdateCallback Actor::GetCallbackOnUpdate() const
|
|||
return cb_update_;
|
||||
}
|
||||
|
||||
inline physics::PhysicBody* Actor::GetPhysicBody() const
|
||||
{
|
||||
return physic_body_;
|
||||
}
|
||||
|
||||
inline void Actor::SetPhysicBody(physics::PhysicBody* body)
|
||||
{
|
||||
physic_body_ = body;
|
||||
}
|
||||
|
||||
inline void Actor::ShowBorder(bool show)
|
||||
{
|
||||
show_border_ = show;
|
||||
|
|
|
|||
|
|
@ -36,11 +36,9 @@ namespace kiwano
|
|||
/// @brief 动画辅助类
|
||||
struct ActionHelper
|
||||
{
|
||||
using DoneCallback = Action::DoneCallback;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置循环次数
|
||||
inline ActionHelper& SetLoops(int loops)
|
||||
inline ActionHelper& Loops(int loops)
|
||||
{
|
||||
ptr->SetLoops(loops);
|
||||
return (*this);
|
||||
|
|
@ -48,7 +46,7 @@ struct ActionHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画延迟
|
||||
inline ActionHelper& SetDelay(Duration delay)
|
||||
inline ActionHelper& Delay(Duration delay)
|
||||
{
|
||||
ptr->SetDelay(delay);
|
||||
return (*this);
|
||||
|
|
@ -56,7 +54,7 @@ struct ActionHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画结束回调函数
|
||||
inline ActionHelper& SetDoneCallback(const DoneCallback& cb)
|
||||
inline ActionHelper& DoneCallback(const Action::DoneCallback& cb)
|
||||
{
|
||||
ptr->SetDoneCallback(cb);
|
||||
return (*this);
|
||||
|
|
@ -64,7 +62,7 @@ struct ActionHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画循环结束时的回调函数
|
||||
inline ActionHelper& SetLoopDoneCallback(const DoneCallback& cb)
|
||||
inline ActionHelper& LoopDoneCallback(const Action::DoneCallback& cb)
|
||||
{
|
||||
ptr->SetLoopDoneCallback(cb);
|
||||
return (*this);
|
||||
|
|
@ -80,7 +78,7 @@ struct ActionHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置名称
|
||||
inline ActionHelper& SetName(const String& name)
|
||||
inline ActionHelper& Name(const String& name)
|
||||
{
|
||||
ptr->SetName(name);
|
||||
return (*this);
|
||||
|
|
@ -116,11 +114,9 @@ private:
|
|||
/// @brief 补间动画辅助类
|
||||
struct TweenHelper
|
||||
{
|
||||
using DoneCallback = Action::DoneCallback;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画持续时长
|
||||
inline TweenHelper& SetDuration(Duration dur)
|
||||
inline TweenHelper& Dur(Duration dur)
|
||||
{
|
||||
ptr->SetDuration(dur);
|
||||
return (*this);
|
||||
|
|
@ -128,7 +124,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置循环次数
|
||||
inline TweenHelper& SetLoops(int loops)
|
||||
inline TweenHelper& Loops(int loops)
|
||||
{
|
||||
ptr->SetLoops(loops);
|
||||
return (*this);
|
||||
|
|
@ -136,7 +132,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置缓动函数
|
||||
inline TweenHelper& SetEaseFunc(EaseFunc ease)
|
||||
inline TweenHelper& EaseFunc(EaseFunc ease)
|
||||
{
|
||||
ptr->SetEaseFunc(ease);
|
||||
return (*this);
|
||||
|
|
@ -144,7 +140,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画延迟
|
||||
inline TweenHelper& SetDelay(Duration delay)
|
||||
inline TweenHelper& Delay(Duration delay)
|
||||
{
|
||||
ptr->SetDelay(delay);
|
||||
return (*this);
|
||||
|
|
@ -152,7 +148,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画结束回调函数
|
||||
inline TweenHelper& SetDoneCallback(const DoneCallback& cb)
|
||||
inline TweenHelper& DoneCallback(const Action::DoneCallback& cb)
|
||||
{
|
||||
ptr->SetDoneCallback(cb);
|
||||
return (*this);
|
||||
|
|
@ -160,7 +156,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置动画循环结束时的回调函数
|
||||
inline TweenHelper& SetLoopDoneCallback(const DoneCallback& cb)
|
||||
inline TweenHelper& LoopDoneCallback(const Action::DoneCallback& cb)
|
||||
{
|
||||
ptr->SetLoopDoneCallback(cb);
|
||||
return (*this);
|
||||
|
|
@ -176,7 +172,7 @@ struct TweenHelper
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 设置名称
|
||||
inline TweenHelper& SetName(const String& name)
|
||||
inline TweenHelper& Name(const String& name)
|
||||
{
|
||||
ptr->SetName(name);
|
||||
return (*this);
|
||||
|
|
@ -220,7 +216,7 @@ struct Tween
|
|||
public:
|
||||
/// \~chinese
|
||||
/// @brief 构造相对位移动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param vector 移动向量
|
||||
static inline TweenHelper MoveBy(Duration dur, const Point& vector)
|
||||
{
|
||||
|
|
@ -229,7 +225,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造位移动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param pos 目的坐标
|
||||
static inline TweenHelper MoveTo(Duration dur, const Point& pos)
|
||||
{
|
||||
|
|
@ -238,29 +234,29 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造相对跳跃动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param vec 跳跃位移向量
|
||||
/// @param height 跳跃高度
|
||||
/// @param jumps 跳跃次数
|
||||
static inline TweenHelper JumpBy(Duration duration, const Vec2& vec, float height, int jumps = 1)
|
||||
static inline TweenHelper JumpBy(Duration dur, const Vec2& vec, float height, int jumps = 1)
|
||||
{
|
||||
return TweenHelper(ActionJumpBy::Create(duration, vec, height, jumps));
|
||||
return TweenHelper(ActionJumpBy::Create(dur, vec, height, jumps));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造跳跃动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param pos 目的坐标
|
||||
/// @param height 跳跃高度
|
||||
/// @param jumps 跳跃次数
|
||||
static inline TweenHelper JumpTo(Duration duration, const Point& pos, float height, int jumps = 1)
|
||||
static inline TweenHelper JumpTo(Duration dur, const Point& pos, float height, int jumps = 1)
|
||||
{
|
||||
return TweenHelper(ActionJumpTo::Create(duration, pos, height, jumps));
|
||||
return TweenHelper(ActionJumpTo::Create(dur, pos, height, jumps));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造相对缩放动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param scale_x 横向缩放相对变化值
|
||||
/// @param scale_y 纵向缩放相对变化值
|
||||
static inline TweenHelper ScaleBy(Duration dur, float scale_x, float scale_y)
|
||||
|
|
@ -270,7 +266,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造缩放动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param scale_x 横向缩放目标值
|
||||
/// @param scale_y 纵向缩放目标值
|
||||
static inline TweenHelper ScaleTo(Duration dur, float scale_x, float scale_y)
|
||||
|
|
@ -280,7 +276,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造透明度渐变动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param opacity 目标透明度
|
||||
static inline TweenHelper FadeTo(Duration dur, float opacity)
|
||||
{
|
||||
|
|
@ -289,7 +285,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造淡入动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
static inline TweenHelper FadeIn(Duration dur)
|
||||
{
|
||||
return TweenHelper(ActionFadeIn::Create(dur));
|
||||
|
|
@ -297,7 +293,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造淡出动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
static inline TweenHelper FadeOut(Duration dur)
|
||||
{
|
||||
return TweenHelper(ActionFadeOut::Create(dur));
|
||||
|
|
@ -305,7 +301,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造相对旋转动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param rotation 角度相对变化值
|
||||
static inline TweenHelper RotateBy(Duration dur, float rotation)
|
||||
{
|
||||
|
|
@ -314,7 +310,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造旋转动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param rotation 目标角度
|
||||
static inline TweenHelper RotateTo(Duration dur, float rotation)
|
||||
{
|
||||
|
|
@ -323,20 +319,20 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造路径行走动画
|
||||
/// @param duration 持续时长
|
||||
/// @param dur 持续时长
|
||||
/// @param path 路径形状
|
||||
/// @param rotating 是否沿路径切线方向旋转
|
||||
/// @param start 路径起点(百分比)
|
||||
/// @param end 路径终点(百分比)
|
||||
static inline TweenHelper Walk(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f,
|
||||
static inline TweenHelper Walk(Duration dur, ShapePtr path, bool rotating = false, float start = 0.f,
|
||||
float end = 1.f)
|
||||
{
|
||||
return TweenHelper(ActionWalk::Create(duration, path, rotating, start, end));
|
||||
return TweenHelper(ActionWalk::Create(dur, path, rotating, start, end));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构建帧动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param[in] frame_seq 序列帧
|
||||
static inline TweenHelper Animation(Duration dur, FrameSequencePtr frames)
|
||||
{
|
||||
|
|
@ -345,7 +341,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 构造自定义动画
|
||||
/// @param duration 动画时长
|
||||
/// @param dur 动画时长
|
||||
/// @param tween_func 动画回调函数
|
||||
static inline TweenHelper Custom(Duration dur, ActionCustom::TweenFunc tween_func)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -102,11 +102,11 @@ public:
|
|||
|
||||
void HandleEvent(Event* evt) override;
|
||||
|
||||
virtual ~Director();
|
||||
|
||||
private:
|
||||
Director();
|
||||
|
||||
virtual ~Director();
|
||||
|
||||
private:
|
||||
bool render_border_enabled_;
|
||||
Stack<StagePtr> stages_;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/base/ObjectBase.h>
|
||||
#include <kiwano/base/ObjectPool.h>
|
||||
#include <kiwano/utils/Logger.h>
|
||||
#include <kiwano/utils/Json.h>
|
||||
#include <typeinfo>
|
||||
|
|
@ -56,6 +57,11 @@ ObjectBase::~ObjectBase()
|
|||
#endif
|
||||
}
|
||||
|
||||
void ObjectBase::AutoRelease()
|
||||
{
|
||||
ObjectPool::GetInstance().AddObject(this);
|
||||
}
|
||||
|
||||
const Any& ObjectBase::GetUserData() const
|
||||
{
|
||||
return user_data_;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ public:
|
|||
|
||||
virtual ~ObjectBase();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 自动释放
|
||||
void AutoRelease();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置对象名
|
||||
void SetName(const String& name);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2016-2018 Kiwano - 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 <kiwano/base/ObjectPool.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
List<ObjectPool*> ObjectPool::pools_;
|
||||
|
||||
ObjectPool& ObjectPool::GetInstance()
|
||||
{
|
||||
static ObjectPool instance;
|
||||
return *pools_.back();
|
||||
}
|
||||
|
||||
ObjectPool::ObjectPool()
|
||||
{
|
||||
pools_.push_back(this);
|
||||
}
|
||||
|
||||
ObjectPool::~ObjectPool()
|
||||
{
|
||||
Clear();
|
||||
|
||||
auto iter = std::find(pools_.begin(), pools_.end(), this);
|
||||
if (iter != pools_.end())
|
||||
pools_.erase(iter);
|
||||
}
|
||||
|
||||
void ObjectPool::AddObject(ObjectBase* obj)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
if (!Contains(obj))
|
||||
{
|
||||
obj->Retain();
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
objects_.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectPool::Contains(ObjectBase* obj) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(const_cast<std::mutex&>(mutex_));
|
||||
|
||||
for (auto iter = pools_.rbegin(); iter != pools_.rend(); iter++)
|
||||
for (const auto o : (*iter)->objects_)
|
||||
if (obj == o)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectPool::Clear()
|
||||
{
|
||||
Vector<ObjectBase*> copied;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
copied = std::move(objects_);
|
||||
}
|
||||
|
||||
for (auto obj : copied)
|
||||
obj->Release();
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2016-2018 Kiwano - 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 <kiwano/base/ObjectBase.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 对象池
|
||||
*/
|
||||
class KGE_API ObjectPool
|
||||
: public Noncopyable
|
||||
{
|
||||
public:
|
||||
static ObjectPool& GetInstance();
|
||||
|
||||
ObjectPool();
|
||||
|
||||
virtual ~ObjectPool();
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 添加对象到内存池
|
||||
* @param[in] obj 基础对象
|
||||
*/
|
||||
void AddObject(ObjectBase* obj);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 判断对象是否在对象池中
|
||||
* @param[in] obj 基础对象
|
||||
*/
|
||||
bool Contains(ObjectBase* obj) const;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 清空所有对象
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
ObjectPool(const ObjectPool&) = delete;
|
||||
|
||||
ObjectPool& operator=(const ObjectPool&) = delete;
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
Vector<ObjectBase*> objects_;
|
||||
|
||||
static List<ObjectPool*> pools_;
|
||||
};
|
||||
} // namespace kiwano
|
||||
|
|
@ -47,7 +47,7 @@ ButtonPtr Button::Create(const Callback& click, const Callback& pressed, const C
|
|||
Button::Button()
|
||||
: status_(Status::Normal)
|
||||
{
|
||||
SetName("KGE_BUTTON");
|
||||
SetName("__KGE_BUTTON__");
|
||||
}
|
||||
|
||||
Button::~Button()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#pragma once
|
||||
#include <kiwano/core/Time.h>
|
||||
#include <kiwano/base/ObjectBase.h>
|
||||
#include <kiwano/core/IntrusiveList.h>
|
||||
#include <kiwano/render/RenderContext.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -49,10 +48,8 @@ KGE_DECLARE_SMART_PTR(Component);
|
|||
*/
|
||||
class KGE_API Component
|
||||
: public ObjectBase
|
||||
, protected IntrusiveListValue<ComponentPtr>
|
||||
{
|
||||
friend class ComponentManager;
|
||||
friend IntrusiveList<ComponentPtr>;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/base/component/ComponentManager.h>
|
||||
#include <functional>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -34,46 +35,74 @@ Component* ComponentManager::AddComponent(ComponentPtr component)
|
|||
|
||||
if (component)
|
||||
{
|
||||
component->InitComponent(target_);
|
||||
components_.PushBack(component);
|
||||
size_t hash = std::hash<String>{}(component->GetName());
|
||||
AddComponent(hash, component);
|
||||
}
|
||||
return component.Get();
|
||||
}
|
||||
|
||||
ComponentList& ComponentManager::GetAllComponents()
|
||||
Component* ComponentManager::AddComponent(size_t index, ComponentPtr component)
|
||||
{
|
||||
KGE_ASSERT(component && "AddComponent failed, NULL pointer exception");
|
||||
|
||||
if (component)
|
||||
{
|
||||
component->InitComponent(target_);
|
||||
|
||||
components_.insert(std::make_pair(index, component));
|
||||
}
|
||||
return component.Get();
|
||||
}
|
||||
|
||||
Component* ComponentManager::GetComponent(const String& name)
|
||||
{
|
||||
size_t hash = std::hash<String>{}(name);
|
||||
return GetComponent(hash);
|
||||
}
|
||||
|
||||
Component* ComponentManager::GetComponent(size_t name_hash)
|
||||
{
|
||||
if (!components_.empty())
|
||||
{
|
||||
auto iter = components_.find(name_hash);
|
||||
if (iter != components_.end())
|
||||
{
|
||||
return iter->second.Get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ComponentMap& ComponentManager::GetAllComponents()
|
||||
{
|
||||
return components_;
|
||||
}
|
||||
|
||||
const ComponentList& ComponentManager::GetAllComponents() const
|
||||
const ComponentMap& ComponentManager::GetAllComponents() const
|
||||
{
|
||||
return components_;
|
||||
}
|
||||
|
||||
void ComponentManager::RemoveComponent(ComponentPtr component)
|
||||
{
|
||||
auto iter = std::find(components_.begin(), components_.end(), component);
|
||||
if (iter != components_.end())
|
||||
{
|
||||
component->DestroyComponent();
|
||||
components_.Remove(component);
|
||||
}
|
||||
RemoveComponent(component->GetName());
|
||||
}
|
||||
|
||||
void ComponentManager::RemoveComponents(const String& name)
|
||||
void ComponentManager::RemoveComponent(const String& name)
|
||||
{
|
||||
if (!components_.IsEmpty())
|
||||
{
|
||||
ComponentPtr next;
|
||||
for (auto component = components_.GetFirst(); component; component = next)
|
||||
{
|
||||
next = component->GetNext();
|
||||
size_t hash = std::hash<String>{}(name);
|
||||
RemoveComponent(hash);
|
||||
}
|
||||
|
||||
if (component->IsName(name))
|
||||
{
|
||||
component->DestroyComponent();
|
||||
components_.Remove(component);
|
||||
}
|
||||
void ComponentManager::RemoveComponent(size_t name_hash)
|
||||
{
|
||||
if (!components_.empty())
|
||||
{
|
||||
auto iter = components_.find(name_hash);
|
||||
if (iter != components_.end())
|
||||
{
|
||||
iter->second->DestroyComponent();
|
||||
components_.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,31 +110,28 @@ void ComponentManager::RemoveComponents(const String& name)
|
|||
void ComponentManager::RemoveAllComponents()
|
||||
{
|
||||
// Destroy all components
|
||||
if (!components_.IsEmpty())
|
||||
if (!components_.empty())
|
||||
{
|
||||
ComponentPtr next;
|
||||
for (auto component = components_.GetFirst(); component; component = next)
|
||||
for (auto& p : components_)
|
||||
{
|
||||
next = component->GetNext();
|
||||
|
||||
component->DestroyComponent();
|
||||
p.second->DestroyComponent();
|
||||
}
|
||||
}
|
||||
components_.Clear();
|
||||
components_.clear();
|
||||
}
|
||||
|
||||
void ComponentManager::Update(Duration dt)
|
||||
{
|
||||
if (!components_.IsEmpty())
|
||||
if (!components_.empty())
|
||||
{
|
||||
ComponentPtr next;
|
||||
for (auto component = components_.GetFirst(); component; component = next)
|
||||
if (!components_.empty())
|
||||
{
|
||||
next = component->GetNext();
|
||||
|
||||
if (component->IsEnable())
|
||||
for (auto& p : components_)
|
||||
{
|
||||
component->OnUpdate(dt);
|
||||
if (p.second->IsEnable())
|
||||
{
|
||||
p.second->OnUpdate(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -113,16 +139,16 @@ void ComponentManager::Update(Duration dt)
|
|||
|
||||
void ComponentManager::Render(RenderContext& ctx)
|
||||
{
|
||||
if (!components_.IsEmpty())
|
||||
if (!components_.empty())
|
||||
{
|
||||
ComponentPtr next;
|
||||
for (auto component = components_.GetFirst(); component; component = next)
|
||||
if (!components_.empty())
|
||||
{
|
||||
next = component->GetNext();
|
||||
|
||||
if (component->IsEnable())
|
||||
for (auto& p : components_)
|
||||
{
|
||||
component->OnRender(ctx);
|
||||
if (p.second->IsEnable())
|
||||
{
|
||||
p.second->OnRender(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,16 +156,16 @@ void ComponentManager::Render(RenderContext& ctx)
|
|||
|
||||
void ComponentManager::DispatchToComponents(Event* evt)
|
||||
{
|
||||
if (!components_.IsEmpty())
|
||||
if (!components_.empty())
|
||||
{
|
||||
ComponentPtr next;
|
||||
for (auto component = components_.GetFirst(); component; component = next)
|
||||
if (!components_.empty())
|
||||
{
|
||||
next = component->GetNext();
|
||||
|
||||
if (component->IsEnable())
|
||||
for (auto& p : components_)
|
||||
{
|
||||
component->HandleEvent(evt);
|
||||
if (p.second->IsEnable())
|
||||
{
|
||||
p.second->HandleEvent(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ namespace kiwano
|
|||
*/
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 组件列表
|
||||
typedef IntrusiveList<ComponentPtr> ComponentList;
|
||||
/// @brief 组件映射
|
||||
typedef UnorderedMap<size_t, ComponentPtr> ComponentMap;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
|
|
@ -47,12 +47,26 @@ public:
|
|||
Component* AddComponent(ComponentPtr component);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取所有组件
|
||||
ComponentList& GetAllComponents();
|
||||
/// @brief 添加组件
|
||||
/// @param index 索引值
|
||||
/// @param component 组件
|
||||
Component* AddComponent(size_t index, ComponentPtr component);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取组件
|
||||
Component* GetComponent(const String& name);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取组件
|
||||
Component* GetComponent(size_t name_hash);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取所有组件
|
||||
const ComponentList& GetAllComponents() const;
|
||||
ComponentMap& GetAllComponents();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取所有组件
|
||||
const ComponentMap& GetAllComponents() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除组件
|
||||
|
|
@ -61,7 +75,12 @@ public:
|
|||
/// \~chinese
|
||||
/// @brief 移除组件
|
||||
/// @param name 组件名称
|
||||
void RemoveComponents(const String& name);
|
||||
void RemoveComponent(const String& name);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除组件
|
||||
/// @param name_hash 组件名称hash值
|
||||
void RemoveComponent(size_t name_hash);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除所有组件
|
||||
|
|
@ -83,8 +102,8 @@ protected:
|
|||
ComponentManager(Actor* target);
|
||||
|
||||
private:
|
||||
Actor* target_;
|
||||
ComponentList components_;
|
||||
Actor* target_;
|
||||
ComponentMap components_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2016-2018 Kiwano - 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 <kiwano/core/Function.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
class Defer
|
||||
{
|
||||
public:
|
||||
Defer() = default;
|
||||
|
||||
Defer(const Function<void()>& func)
|
||||
: func_(func)
|
||||
{
|
||||
}
|
||||
|
||||
Defer(Defer&& other) noexcept
|
||||
: func_(other.func_)
|
||||
{
|
||||
other.func_ = nullptr;
|
||||
}
|
||||
|
||||
~Defer()
|
||||
{
|
||||
if (func_)
|
||||
func_();
|
||||
}
|
||||
|
||||
private:
|
||||
Defer(const Defer&) = delete;
|
||||
Defer& operator=(const Defer&) = delete;
|
||||
|
||||
Function<void()> func_;
|
||||
};
|
||||
|
||||
class __DeferHelper
|
||||
{
|
||||
public:
|
||||
Defer operator-(const Function<void()>& func) const
|
||||
{
|
||||
return Defer{ func };
|
||||
}
|
||||
};
|
||||
|
||||
#define KGE_DEFER auto __KGE_DEFER_VAR(__defer_line_, __LINE__, __) = ::kiwano::__DeferHelper() -
|
||||
#define __KGE_DEFER_VAR(a, b, c) __KGE_DEFER_TOKEN_CONNECT(a, b, c)
|
||||
#define __KGE_DEFER_TOKEN_CONNECT(a, b, c) a##b##c
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -19,12 +19,13 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
template <typename _Ty>
|
||||
struct Singleton
|
||||
class Singleton
|
||||
{
|
||||
protected:
|
||||
Singleton() = default;
|
||||
|
|
@ -32,29 +33,47 @@ protected:
|
|||
Singleton& operator=(const Singleton&) = delete;
|
||||
|
||||
private:
|
||||
struct ObjectCreator
|
||||
struct InstanceCreator
|
||||
{
|
||||
ObjectCreator()
|
||||
InstanceCreator()
|
||||
{
|
||||
(void)Singleton<_Ty>::GetInstance();
|
||||
(void)Singleton<_Ty>::GetInstancePtr();
|
||||
}
|
||||
|
||||
inline void Dummy() const {}
|
||||
};
|
||||
static ObjectCreator creator_;
|
||||
static InstanceCreator creator_;
|
||||
|
||||
public:
|
||||
using object_type = _Ty;
|
||||
|
||||
static std::unique_ptr<object_type> instance_ptr_;
|
||||
|
||||
static inline object_type& GetInstance()
|
||||
{
|
||||
static object_type instance;
|
||||
return *GetInstancePtr();
|
||||
}
|
||||
|
||||
static inline object_type* GetInstancePtr()
|
||||
{
|
||||
creator_.Dummy();
|
||||
return instance;
|
||||
if (!instance_ptr_)
|
||||
{
|
||||
instance_ptr_.reset(new object_type);
|
||||
}
|
||||
return instance_ptr_.get();
|
||||
}
|
||||
|
||||
static inline void DestroyInstance()
|
||||
{
|
||||
instance_ptr_.reset();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _Ty>
|
||||
typename Singleton<_Ty>::ObjectCreator Singleton<_Ty>::creator_;
|
||||
typename Singleton<_Ty>::InstanceCreator Singleton<_Ty>::creator_;
|
||||
|
||||
template <typename _Ty>
|
||||
typename std::unique_ptr<_Ty> Singleton<_Ty>::instance_ptr_;
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 判断事件类型
|
||||
/// @return 是否是指定事件类型
|
||||
/// @return 事件类型相同返回true,否则返回false
|
||||
template <typename _Ty>
|
||||
bool IsType() const;
|
||||
|
||||
|
|
@ -75,19 +75,20 @@ private:
|
|||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 事件特性:判断指定类型是否是事件
|
||||
/// @brief 事件特性:判断是否是事件
|
||||
template <typename _Ty>
|
||||
struct IsEvent : public std::bool_constant<std::is_base_of<Event, _Ty>::value || std::is_same<Event, _Ty>::value>
|
||||
struct IsBaseOfEvent : public std::bool_constant<std::is_base_of<Event, _Ty>::value || std::is_same<Event, _Ty>::value>
|
||||
{
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 事件特性:判断一个事件能否安全转换到另一事件类型
|
||||
template <typename _Ty, typename = typename std::enable_if<IsEvent<_Ty>::value, int>::type>
|
||||
struct IsEventType
|
||||
/// @brief 事件特性:判断事件类型是否相同
|
||||
template <typename _Ty>
|
||||
struct IsSameEventType
|
||||
{
|
||||
inline bool operator()(const Event* evt) const
|
||||
{
|
||||
static_assert(kiwano::IsBaseOfEvent<_Ty>::value, "_Ty is not an event type.");
|
||||
return evt->GetType() == KGE_EVENT(_Ty);
|
||||
}
|
||||
};
|
||||
|
|
@ -102,8 +103,8 @@ inline const EventType& Event::GetType() const
|
|||
template <typename _Ty>
|
||||
inline bool Event::IsType() const
|
||||
{
|
||||
static_assert(kiwano::IsEvent<_Ty>::value, "_Ty is not an event type.");
|
||||
return kiwano::IsEventType<_Ty>()(this);
|
||||
static_assert(kiwano::IsBaseOfEvent<_Ty>::value, "_Ty is not an event type.");
|
||||
return IsSameEventType<_Ty>()(this);
|
||||
}
|
||||
|
||||
template <typename _Ty>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public:
|
|||
template <typename _EventTy>
|
||||
EventListener* AddListener(EventListener::Callback callback)
|
||||
{
|
||||
static_assert(kiwano::IsEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
static_assert(kiwano::IsBaseOfEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
return AddListener(KGE_EVENT(_EventTy), callback);
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ public:
|
|||
template <typename _EventTy>
|
||||
EventListener* AddListener(const String& name, EventListener::Callback callback)
|
||||
{
|
||||
static_assert(kiwano::IsEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
static_assert(kiwano::IsBaseOfEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
return AddListener(name, KGE_EVENT(_EventTy), callback);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,4 +58,12 @@ EventListener::EventListener()
|
|||
|
||||
EventListener::~EventListener() {}
|
||||
|
||||
void EventListener::Receive(Event* evt)
|
||||
{
|
||||
if (ShouldHandle(evt) && callback_)
|
||||
{
|
||||
callback_(evt);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
template <typename _EventTy>
|
||||
static inline EventListenerPtr Create(const Callback& callback)
|
||||
{
|
||||
static_assert(kiwano::IsEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
static_assert(kiwano::IsBaseOfEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
return EventListener::Create(KGE_EVENT(_EventTy), callback);
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ public:
|
|||
template <typename _EventTy>
|
||||
static inline EventListenerPtr Create(const String& name, const Callback& callback)
|
||||
{
|
||||
static_assert(kiwano::IsEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
static_assert(kiwano::IsBaseOfEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
return EventListener::Create(name, KGE_EVENT(_EventTy), callback);
|
||||
}
|
||||
|
||||
|
|
@ -132,12 +132,17 @@ public:
|
|||
/// @brief 设置监听的事件类型
|
||||
void SetEventType(const EventType& type);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ÅжÏÊÇ·ñ´¦Àíʼþ
|
||||
virtual bool ShouldHandle(Event* evt) const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置监听的事件类型
|
||||
/// @tparam _EventTy 事件类型
|
||||
template <typename _EventTy, typename = typename std::enable_if<IsEvent<_EventTy>::value, int>::type>
|
||||
template <typename _EventTy>
|
||||
inline void SetEventType()
|
||||
{
|
||||
static_assert(kiwano::IsBaseOfEvent<_EventTy>::value, "_EventTy is not an event type.");
|
||||
SetEventType(KGE_EVENT(_EventTy));
|
||||
}
|
||||
|
||||
|
|
@ -208,13 +213,13 @@ inline void EventListener::SetEventType(const EventType& type)
|
|||
type_ = type;
|
||||
}
|
||||
|
||||
inline void EventListener::Receive(Event* evt)
|
||||
inline bool EventListener::ShouldHandle(Event* evt) const
|
||||
{
|
||||
KGE_ASSERT(evt != nullptr);
|
||||
|
||||
if (type_ == evt->GetType() && callback_)
|
||||
if (evt)
|
||||
{
|
||||
callback_(evt);
|
||||
return evt->GetType() == type_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -72,10 +72,8 @@ public:
|
|||
KeyCharEvent();
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
template <>
|
||||
struct IsEventType<KeyEvent>
|
||||
struct IsSameEventType<KeyEvent>
|
||||
{
|
||||
inline bool operator()(const Event* evt) const
|
||||
{
|
||||
|
|
@ -84,4 +82,6 @@ struct IsEventType<KeyEvent>
|
|||
}
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -113,10 +113,8 @@ public:
|
|||
MouseWheelEvent();
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
template <>
|
||||
struct IsEventType<MouseEvent>
|
||||
struct IsSameEventType<MouseEvent>
|
||||
{
|
||||
inline bool operator()(const Event* evt) const
|
||||
{
|
||||
|
|
@ -127,4 +125,6 @@ struct IsEventType<MouseEvent>
|
|||
}
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -93,10 +93,8 @@ public:
|
|||
WindowClosedEvent();
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
template <>
|
||||
struct IsEventType<WindowEvent>
|
||||
struct IsSameEventType<WindowEvent>
|
||||
{
|
||||
inline bool operator()(const Event* evt) const
|
||||
{
|
||||
|
|
@ -107,4 +105,6 @@ struct IsEventType<WindowEvent>
|
|||
}
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
//
|
||||
|
||||
#include <kiwano/core/Common.h>
|
||||
#include <kiwano/core/Defer.h>
|
||||
#include <kiwano/core/Resource.h>
|
||||
#include <kiwano/core/SmartPtr.hpp>
|
||||
#include <kiwano/core/Time.h>
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/platform/Application.h>
|
||||
#include <kiwano/utils/Logger.h>
|
||||
#include <kiwano/core/Defer.h>
|
||||
#include <kiwano/base/Director.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/TextureCache.h>
|
||||
#include <kiwano/utils/ResourceCache.h>
|
||||
#include <kiwano/utils/Logger.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -42,15 +43,15 @@ Application::Application()
|
|||
|
||||
Application::~Application()
|
||||
{
|
||||
this->Destroy();
|
||||
}
|
||||
|
||||
void Application::Run(RunnerPtr runner)
|
||||
{
|
||||
KGE_ASSERT(runner);
|
||||
runner_ = runner;
|
||||
running_ = true;
|
||||
running_ = true;
|
||||
is_paused_ = false;
|
||||
runner_ = runner;
|
||||
timer_ = Timer::Create();
|
||||
|
||||
// Initialize runner
|
||||
runner->InitSettings();
|
||||
|
|
@ -61,51 +62,43 @@ void Application::Run(RunnerPtr runner)
|
|||
c->SetupModule();
|
||||
}
|
||||
|
||||
// Ensure resources are destroyed before exiting
|
||||
KGE_DEFER[=]()
|
||||
{
|
||||
this->Destroy();
|
||||
};
|
||||
|
||||
// Everything is ready
|
||||
runner->OnReady();
|
||||
|
||||
// Update everything
|
||||
this->Update(0);
|
||||
|
||||
// Start the loop
|
||||
while (running_)
|
||||
{
|
||||
if (!frame_ticker_)
|
||||
{
|
||||
frame_ticker_ = Ticker::Create(0);
|
||||
}
|
||||
timer_->Tick();
|
||||
|
||||
if (frame_ticker_->Tick())
|
||||
{
|
||||
// Execute main loop
|
||||
if (!runner->MainLoop(frame_ticker_->GetDeltaTime()))
|
||||
running_ = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Releases CPU
|
||||
Duration total_dt = frame_ticker_->GetDeltaTime() + frame_ticker_->GetErrorTime();
|
||||
Duration sleep_dt = frame_ticker_->GetInterval() - total_dt;
|
||||
if (sleep_dt.Milliseconds() > 1LL)
|
||||
{
|
||||
sleep_dt.Sleep();
|
||||
}
|
||||
}
|
||||
// Execute main loop
|
||||
if (!runner->MainLoop(timer_->GetDeltaTime()))
|
||||
running_ = false;
|
||||
}
|
||||
|
||||
this->Destroy();
|
||||
}
|
||||
|
||||
void Application::Pause()
|
||||
{
|
||||
is_paused_ = true;
|
||||
|
||||
if (frame_ticker_)
|
||||
frame_ticker_->Pause();
|
||||
if (timer_)
|
||||
timer_->Pause();
|
||||
}
|
||||
|
||||
void Application::Resume()
|
||||
{
|
||||
is_paused_ = false;
|
||||
|
||||
if (frame_ticker_)
|
||||
frame_ticker_->Resume();
|
||||
if (timer_)
|
||||
timer_->Resume();
|
||||
}
|
||||
|
||||
void Application::Quit()
|
||||
|
|
@ -113,6 +106,12 @@ void Application::Quit()
|
|||
running_ = false;
|
||||
}
|
||||
|
||||
void Application::UpdateFrame(Duration dt)
|
||||
{
|
||||
this->Render();
|
||||
this->Update(dt);
|
||||
}
|
||||
|
||||
void Application::Destroy()
|
||||
{
|
||||
if (runner_)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include <kiwano/event/Event.h>
|
||||
#include <kiwano/platform/Runner.h>
|
||||
#include <kiwano/platform/Window.h>
|
||||
#include <kiwano/utils/Ticker.h>
|
||||
#include <kiwano/utils/Timer.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -103,18 +103,6 @@ public:
|
|||
*/
|
||||
WindowPtr GetWindow() const;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 获取帧报时器
|
||||
*/
|
||||
TickerPtr GetFrameTicker() const;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 设置帧报时器
|
||||
*/
|
||||
void SetFrameTicker(TickerPtr ticker);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 设置时间缩放因子
|
||||
|
|
@ -150,16 +138,10 @@ public:
|
|||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 更新所有模块
|
||||
* @brief 更新一帧
|
||||
* @param dt 时间间隔
|
||||
*/
|
||||
void Update(Duration dt);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 创建渲染上下文并渲染画面
|
||||
*/
|
||||
void Render();
|
||||
void UpdateFrame(Duration dt);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
|
|
@ -167,12 +149,26 @@ public:
|
|||
*/
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 更新所有模块
|
||||
* @param dt 时间间隔
|
||||
*/
|
||||
void Update(Duration dt);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 渲染画面
|
||||
*/
|
||||
void Render();
|
||||
|
||||
private:
|
||||
bool running_;
|
||||
bool is_paused_;
|
||||
float time_scale_;
|
||||
RunnerPtr runner_;
|
||||
TickerPtr frame_ticker_;
|
||||
TimerPtr timer_;
|
||||
List<Module*> modules_;
|
||||
std::mutex perform_mutex_;
|
||||
Queue<Function<void()>> functions_to_perform_;
|
||||
|
|
@ -185,18 +181,9 @@ inline RunnerPtr Application::GetRunner() const
|
|||
|
||||
inline WindowPtr Application::GetWindow() const
|
||||
{
|
||||
KGE_ASSERT(runner_);
|
||||
return runner_->GetWindow();
|
||||
}
|
||||
|
||||
inline TickerPtr Application::GetFrameTicker() const
|
||||
{
|
||||
return frame_ticker_;
|
||||
}
|
||||
|
||||
inline void Application::SetFrameTicker(TickerPtr ticker)
|
||||
{
|
||||
frame_ticker_ = ticker;
|
||||
if (runner_)
|
||||
return runner_->GetWindow();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline bool Application::IsPaused() const
|
||||
|
|
|
|||
|
|
@ -102,11 +102,11 @@ public:
|
|||
*/
|
||||
bool ExtractResourceToFile(const Resource& res, const String& dest_file_name) const;
|
||||
|
||||
~FileSystem();
|
||||
|
||||
private:
|
||||
FileSystem();
|
||||
|
||||
~FileSystem();
|
||||
|
||||
private:
|
||||
Vector<String> search_paths_;
|
||||
UnorderedMap<String, String> file_lookup_dict_;
|
||||
|
|
|
|||
|
|
@ -112,11 +112,11 @@ public:
|
|||
|
||||
void HandleEvent(Event* evt) override;
|
||||
|
||||
~Input();
|
||||
|
||||
private:
|
||||
Input();
|
||||
|
||||
~Input();
|
||||
|
||||
void UpdateKey(KeyCode key, bool down);
|
||||
|
||||
void UpdateButton(MouseButton btn, bool down);
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ void Runner::InitSettings()
|
|||
}
|
||||
|
||||
// Create game window
|
||||
WindowPtr window =
|
||||
Window::Create(settings_.title, settings_.width, settings_.height, settings_.icon, settings_.resizable);
|
||||
WindowPtr window = Window::Create(settings_.title, settings_.width, settings_.height, settings_.icon,
|
||||
settings_.resizable, settings_.fullscreen);
|
||||
SetWindow(window);
|
||||
|
||||
// Update renderer settings
|
||||
|
|
@ -101,6 +101,9 @@ void Runner::InitSettings()
|
|||
Director::GetInstance().ShowDebugInfo(true);
|
||||
Renderer::GetInstance().GetContext().SetCollectingStatus(true);
|
||||
}
|
||||
|
||||
// Create frame ticker
|
||||
frame_ticker_ = Ticker::Create(settings_.frame_interval, -1);
|
||||
}
|
||||
|
||||
bool Runner::MainLoop(Duration dt)
|
||||
|
|
@ -118,9 +121,6 @@ bool Runner::MainLoop(Duration dt)
|
|||
|
||||
Application& app = Application::GetInstance();
|
||||
|
||||
// Update modules before poll events
|
||||
app.Update(dt);
|
||||
|
||||
// Poll events
|
||||
main_window_->PumpEvents();
|
||||
while (EventPtr evt = main_window_->PollEvent())
|
||||
|
|
@ -128,12 +128,27 @@ bool Runner::MainLoop(Duration dt)
|
|||
app.DispatchEvent(evt.Get());
|
||||
}
|
||||
|
||||
app.Render();
|
||||
|
||||
if (app.IsPaused())
|
||||
// Update frame ticker
|
||||
if (frame_ticker_)
|
||||
{
|
||||
// Slow down when the application is paused
|
||||
Duration(5).Sleep();
|
||||
if (frame_ticker_->Tick(dt))
|
||||
{
|
||||
app.UpdateFrame(frame_ticker_->GetDeltaTime());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Releases CPU
|
||||
Duration total_dt = frame_ticker_->GetDeltaTime() + frame_ticker_->GetErrorTime();
|
||||
Duration sleep_dt = frame_ticker_->GetInterval() - total_dt;
|
||||
if (sleep_dt.Milliseconds() > 1LL)
|
||||
{
|
||||
sleep_dt.Sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UpdateFrame(dt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <kiwano/platform/Window.h>
|
||||
#include <kiwano/render/Color.h>
|
||||
#include <kiwano/render/Texture.h>
|
||||
#include <kiwano/utils/Ticker.h>
|
||||
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -38,14 +40,16 @@ KGE_DECLARE_SMART_PTR(Runner);
|
|||
*/
|
||||
struct Settings
|
||||
{
|
||||
uint32_t width; ///< 窗口宽度
|
||||
uint32_t height; ///< 窗口高度
|
||||
String title; ///< 窗口标题
|
||||
uint32_t icon; ///< 窗口图标
|
||||
bool resizable; ///< 窗口大小可调整
|
||||
Color bg_color; ///< 窗口背景色
|
||||
bool vsync_enabled; ///< 垂直同步
|
||||
bool debug_mode; ///< 调试模式
|
||||
uint32_t width; ///< 窗口宽度
|
||||
uint32_t height; ///< 窗口高度
|
||||
String title; ///< 窗口标题
|
||||
uint32_t icon; ///< 窗口图标
|
||||
bool resizable; ///< 窗口大小可调整
|
||||
bool fullscreen; ///< 窗口全屏
|
||||
Color bg_color; ///< 窗口背景色
|
||||
Duration frame_interval; ///< 帧间隔
|
||||
bool vsync_enabled; ///< 垂直同步
|
||||
bool debug_mode; ///< 调试模式
|
||||
|
||||
Settings()
|
||||
: width(800)
|
||||
|
|
@ -53,8 +57,10 @@ struct Settings
|
|||
, title("Kiwano")
|
||||
, icon()
|
||||
, resizable(false)
|
||||
, fullscreen(false)
|
||||
, bg_color(Color::Black)
|
||||
, vsync_enabled(true)
|
||||
, frame_interval(16)
|
||||
, vsync_enabled(false)
|
||||
, debug_mode(false)
|
||||
{
|
||||
}
|
||||
|
|
@ -118,6 +124,14 @@ public:
|
|||
/// @brief »ñÈ¡ÉèÖÃ
|
||||
Settings GetSettings() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取帧报时器
|
||||
TickerPtr GetFrameTicker() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置帧报时器
|
||||
void SetFrameTicker(TickerPtr ticker);
|
||||
|
||||
protected:
|
||||
/// \~chinese
|
||||
/// @brief ÐÞ¸ÄÉèÖÃ
|
||||
|
|
@ -131,6 +145,7 @@ private:
|
|||
private:
|
||||
Settings settings_;
|
||||
WindowPtr main_window_;
|
||||
TickerPtr frame_ticker_;
|
||||
};
|
||||
|
||||
inline void Runner::OnReady() {}
|
||||
|
|
@ -162,4 +177,14 @@ inline void Runner::SetSettings(Settings settings)
|
|||
settings_ = settings;
|
||||
}
|
||||
|
||||
inline TickerPtr Runner::GetFrameTicker() const
|
||||
{
|
||||
return frame_ticker_;
|
||||
}
|
||||
|
||||
inline void Runner::SetFrameTicker(TickerPtr ticker)
|
||||
{
|
||||
frame_ticker_ = ticker;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -71,6 +71,11 @@ uint32_t Window::GetHeight() const
|
|||
return height_;
|
||||
}
|
||||
|
||||
Resolution Window::GetCurrentResolution() const
|
||||
{
|
||||
return resolution_;
|
||||
}
|
||||
|
||||
WindowHandle Window::GetHandle() const
|
||||
{
|
||||
return handle_;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public:
|
|||
* @throw kiwano::SystemError 窗口创建失败时抛出
|
||||
*/
|
||||
static WindowPtr Create(const String& title, uint32_t width, uint32_t height, uint32_t icon = 0,
|
||||
bool resizable = false);
|
||||
bool resizable = false, bool fullscreen = false);
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
|
|
@ -110,6 +110,12 @@ public:
|
|||
*/
|
||||
uint32_t GetHeight() const;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 获取当前分辨率
|
||||
*/
|
||||
Resolution GetCurrentResolution() const;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 获取窗口句柄
|
||||
|
|
@ -214,6 +220,7 @@ protected:
|
|||
uint32_t min_height_;
|
||||
uint32_t max_width_;
|
||||
uint32_t max_height_;
|
||||
Resolution resolution_;
|
||||
WindowHandle handle_;
|
||||
String title_;
|
||||
std::queue<EventPtr> event_queue_;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include <kiwano/event/Events.h>
|
||||
#include <kiwano/platform/Application.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/DirectX/D3DDeviceResources.h>
|
||||
#include <Windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
||||
#include <imm.h> // ImmAssociateContext
|
||||
#pragma comment(lib, "imm32.lib")
|
||||
|
|
@ -49,7 +48,7 @@ public:
|
|||
|
||||
virtual ~WindowWin32Impl();
|
||||
|
||||
void Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable);
|
||||
void Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen);
|
||||
|
||||
void SetTitle(const String& title) override;
|
||||
|
||||
|
|
@ -69,6 +68,8 @@ public:
|
|||
|
||||
DWORD GetStyle() const;
|
||||
|
||||
void SetActive(bool active);
|
||||
|
||||
void UpdateCursor();
|
||||
|
||||
LRESULT MessageProc(HWND, UINT32, WPARAM, LPARAM);
|
||||
|
|
@ -86,12 +87,13 @@ private:
|
|||
std::array<KeyCode, 256> key_map_;
|
||||
};
|
||||
|
||||
WindowPtr Window::Create(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable)
|
||||
WindowPtr Window::Create(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable,
|
||||
bool fullscreen)
|
||||
{
|
||||
WindowWin32ImplPtr ptr = memory::New<WindowWin32Impl>();
|
||||
if (ptr)
|
||||
{
|
||||
ptr->Init(title, width, height, icon, resizable);
|
||||
ptr->Init(title, width, height, icon, resizable, fullscreen);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
|
@ -103,6 +105,7 @@ namespace kiwano
|
|||
|
||||
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
||||
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
|
||||
#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -202,7 +205,8 @@ WindowWin32Impl::~WindowWin32Impl()
|
|||
::timeEndPeriod(0);
|
||||
}
|
||||
|
||||
void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable)
|
||||
void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable,
|
||||
bool fullscreen)
|
||||
{
|
||||
HINSTANCE hinst = GetModuleHandle(nullptr);
|
||||
WNDCLASSEXA wcex = { 0 };
|
||||
|
|
@ -249,10 +253,13 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height,
|
|||
width = win_width;
|
||||
height = win_height;
|
||||
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
resizable_ = resizable;
|
||||
handle_ = ::CreateWindowExA(0, "KiwanoAppWnd", title.c_str(), GetStyle(), left, top, width, height, nullptr,
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
resizable_ = resizable;
|
||||
is_fullscreen_ = fullscreen;
|
||||
resolution_ = Resolution{ width_, height_, 0 };
|
||||
|
||||
handle_ = ::CreateWindowExA(0, "KiwanoAppWnd", title.c_str(), GetStyle(), left, top, width, height, nullptr,
|
||||
nullptr, hinst, nullptr);
|
||||
|
||||
if (handle_ == nullptr)
|
||||
|
|
@ -269,6 +276,19 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height,
|
|||
|
||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||
::UpdateWindow(handle_);
|
||||
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
MONITORINFOEXA info = GetMoniterInfoEx(handle_);
|
||||
int x = (int)info.rcMonitor.left;
|
||||
int y = (int)info.rcMonitor.top;
|
||||
int cx = (int)(info.rcMonitor.right - info.rcMonitor.left);
|
||||
int cy = (int)(info.rcMonitor.bottom - info.rcMonitor.top);
|
||||
|
||||
// Top the window
|
||||
::SetWindowPos(handle_, HWND_TOPMOST, x, y, cx, cy, SWP_NOACTIVATE);
|
||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWin32Impl::PumpEvents()
|
||||
|
|
@ -318,71 +338,78 @@ void WindowWin32Impl::SetCursor(CursorType cursor)
|
|||
|
||||
void WindowWin32Impl::SetResolution(uint32_t width, uint32_t height, bool fullscreen)
|
||||
{
|
||||
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
|
||||
|
||||
if (fullscreen)
|
||||
if (is_fullscreen_ != fullscreen)
|
||||
{
|
||||
HRESULT hr = d3d->ResizeTarget(width, height);
|
||||
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
|
||||
is_fullscreen_ = fullscreen;
|
||||
|
||||
hr = d3d->SetFullscreenState(fullscreen);
|
||||
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
|
||||
// Reset window style
|
||||
::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle());
|
||||
}
|
||||
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
MONITORINFOEXA info = GetMoniterInfoEx(handle_);
|
||||
int x = (int)info.rcMonitor.left;
|
||||
int y = (int)info.rcMonitor.top;
|
||||
int cx = (int)(info.rcMonitor.right - info.rcMonitor.left);
|
||||
int cy = (int)(info.rcMonitor.bottom - info.rcMonitor.top);
|
||||
|
||||
// Top the window
|
||||
::SetWindowPos(handle_, HWND_TOPMOST, x, y, cx, cy, SWP_NOACTIVATE);
|
||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
HRESULT hr = d3d->SetFullscreenState(fullscreen);
|
||||
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
|
||||
// Adjust the rect of client area
|
||||
RECT rc = { 0, 0, LONG(width), LONG(height) };
|
||||
::AdjustWindowRect(&rc, GetStyle(), false);
|
||||
|
||||
hr = d3d->ResizeTarget(width, height);
|
||||
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
|
||||
width = uint32_t(rc.right - rc.left);
|
||||
height = uint32_t(rc.bottom - rc.top);
|
||||
|
||||
MONITORINFOEXA info = GetMoniterInfoEx(handle_);
|
||||
uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left);
|
||||
uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top);
|
||||
int left = screenw > width ? ((screenw - width) / 2) : 0;
|
||||
int top = screenh > height ? ((screenh - height) / 2) : 0;
|
||||
|
||||
// Reset window style
|
||||
::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle());
|
||||
|
||||
// Unpin the window
|
||||
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, width, height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
|
||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
is_fullscreen_ = fullscreen;
|
||||
resolution_ = Resolution{ width, height, 0 };
|
||||
|
||||
// Resize render target
|
||||
Renderer::GetInstance().Resize(width, height);
|
||||
}
|
||||
|
||||
Vector<Resolution> WindowWin32Impl::GetResolutions()
|
||||
{
|
||||
if (resolutions_.empty())
|
||||
{
|
||||
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
|
||||
Set<String> resolution_list;
|
||||
|
||||
DXGI_MODE_DESC* mode_descs = nullptr;
|
||||
int mode_num = 0;
|
||||
DEVMODEA dmi;
|
||||
ZeroMemory(&dmi, sizeof(dmi));
|
||||
dmi.dmSize = sizeof(dmi);
|
||||
|
||||
HRESULT hr = d3d->GetDisplaySettings(&mode_descs, &mode_num);
|
||||
if (SUCCEEDED(hr))
|
||||
DWORD mode_count = 0;
|
||||
while (EnumDisplaySettingsA(device_name_.c_str(), mode_count++, &dmi) != 0)
|
||||
{
|
||||
std::unique_ptr<DXGI_MODE_DESC[]> mode_list(mode_descs);
|
||||
StringStream ss;
|
||||
ss << dmi.dmPelsWidth << 'x' << dmi.dmPelsHeight << ':' << dmi.dmDisplayFrequency;
|
||||
|
||||
if (mode_list)
|
||||
if (resolution_list.find(ss.str()) == resolution_list.end())
|
||||
{
|
||||
for (int i = 0; i < mode_num; i++)
|
||||
{
|
||||
Resolution res;
|
||||
res.width = mode_descs[i].Width;
|
||||
res.height = mode_descs[i].Height;
|
||||
res.refresh_rate = 0;
|
||||
|
||||
if (mode_descs[i].RefreshRate.Denominator > 0)
|
||||
{
|
||||
res.refresh_rate = mode_descs[i].RefreshRate.Numerator / mode_descs[i].RefreshRate.Denominator;
|
||||
}
|
||||
|
||||
if (!resolutions_.empty())
|
||||
{
|
||||
auto& back = resolutions_.back();
|
||||
if (back.width == res.width && back.height == res.height
|
||||
&& back.refresh_rate == res.refresh_rate)
|
||||
continue;
|
||||
}
|
||||
|
||||
resolutions_.push_back(res);
|
||||
}
|
||||
resolution_list.insert(ss.str());
|
||||
resolutions_.push_back(Resolution{ uint32_t(dmi.dmPelsWidth), uint32_t(dmi.dmPelsHeight),
|
||||
uint32_t(dmi.dmDisplayFrequency) });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_THROW_IF_FAILED(hr, "DXGI GetDisplaySettings failed!");
|
||||
ZeroMemory(&dmi, sizeof(dmi));
|
||||
}
|
||||
}
|
||||
return resolutions_;
|
||||
|
|
@ -390,7 +417,30 @@ Vector<Resolution> WindowWin32Impl::GetResolutions()
|
|||
|
||||
DWORD WindowWin32Impl::GetStyle() const
|
||||
{
|
||||
return (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));
|
||||
if (is_fullscreen_)
|
||||
return WINDOW_FULLSCREEN_STYLE;
|
||||
if (resizable_)
|
||||
return WINDOW_RESIZABLE_STYLE;
|
||||
return WINDOW_FIXED_STYLE;
|
||||
}
|
||||
|
||||
void WindowWin32Impl::SetActive(bool active)
|
||||
{
|
||||
if (!handle_)
|
||||
return;
|
||||
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
// Hide window when it is not active
|
||||
if (active)
|
||||
{
|
||||
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWin32Impl::UpdateCursor()
|
||||
|
|
@ -658,8 +708,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
{
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
// TODO restore to fullscreen mode
|
||||
// SetResolution();
|
||||
SetActive(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -668,8 +717,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
{
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
// TODO exit fullscreen mode
|
||||
// ::ShowWindow(handle_, SW_MINIMIZE);
|
||||
SetActive(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -695,18 +743,6 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
KGE_SYS_LOG("The display resolution has changed");
|
||||
|
||||
// Check fullscreen state
|
||||
auto d3d_res = graphics::directx::GetD3DDeviceResources();
|
||||
auto swap_chain = d3d_res->GetDXGISwapChain();
|
||||
if (swap_chain)
|
||||
{
|
||||
BOOL is_fullscreen = FALSE;
|
||||
if (SUCCEEDED(swap_chain->GetFullscreenState(&is_fullscreen, nullptr)))
|
||||
{
|
||||
is_fullscreen_ = !!is_fullscreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ inline bool SdkLayersAvailable()
|
|||
struct D3D10DeviceResources : public ID3D10DeviceResources
|
||||
{
|
||||
public:
|
||||
HRESULT Initialize(HWND hwnd) override;
|
||||
HRESULT Initialize(HWND hwnd, Size logical_size) override;
|
||||
|
||||
HRESULT Present(bool vsync) override;
|
||||
|
||||
|
|
@ -138,14 +138,10 @@ D3D10DeviceResources::~D3D10DeviceResources()
|
|||
DiscardResources();
|
||||
}
|
||||
|
||||
HRESULT D3D10DeviceResources::Initialize(HWND hwnd)
|
||||
HRESULT D3D10DeviceResources::Initialize(HWND hwnd, Size logical_size)
|
||||
{
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
|
||||
this->hwnd_ = hwnd;
|
||||
this->logical_size_.x = float(rc.right - rc.left);
|
||||
this->logical_size_.y = float(rc.bottom - rc.top);
|
||||
this->logical_size_ = logical_size;
|
||||
|
||||
HRESULT hr = this->CreateDeviceResources();
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ inline bool SdkLayersAvailable()
|
|||
struct D3D11DeviceResources : public ID3D11DeviceResources
|
||||
{
|
||||
public:
|
||||
HRESULT Initialize(HWND hwnd) override;
|
||||
HRESULT Initialize(HWND hwnd, Size logical_size) override;
|
||||
|
||||
HRESULT Present(bool vsync) override;
|
||||
|
||||
|
|
@ -133,14 +133,10 @@ D3D11DeviceResources::~D3D11DeviceResources()
|
|||
DiscardResources();
|
||||
}
|
||||
|
||||
HRESULT D3D11DeviceResources::Initialize(HWND hwnd)
|
||||
HRESULT D3D11DeviceResources::Initialize(HWND hwnd, Size logical_size)
|
||||
{
|
||||
RECT rc;
|
||||
::GetClientRect(hwnd, &rc);
|
||||
|
||||
this->hwnd_ = hwnd;
|
||||
this->logical_size_.x = float(rc.right - rc.left);
|
||||
this->logical_size_.y = float(rc.bottom - rc.top);
|
||||
this->logical_size_ = logical_size;
|
||||
|
||||
HRESULT hr = this->CreateDeviceResources();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d")
|
|||
ID3DDeviceResourcesBase : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT Initialize(HWND hwnd) = 0;
|
||||
virtual HRESULT Initialize(HWND hwnd, Size logical_size) = 0;
|
||||
|
||||
virtual HRESULT Present(bool vsync) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,17 +55,18 @@ void RendererImpl::MakeContextForWindow(WindowPtr window)
|
|||
|
||||
KGE_THROW_IF_FAILED(::CoInitialize(nullptr), "CoInitialize failed");
|
||||
|
||||
HWND target_window = window->GetHandle();
|
||||
output_size_ = window->GetSize();
|
||||
HWND target_window = window->GetHandle();
|
||||
Resolution resolution = window->GetCurrentResolution();
|
||||
HRESULT hr = target_window ? S_OK : E_FAIL;
|
||||
|
||||
HRESULT hr = target_window ? S_OK : E_FAIL;
|
||||
output_size_ = Size{ float(resolution.width), float(resolution.height) };
|
||||
|
||||
// Initialize Direct3D resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
auto d3d_res = graphics::directx::GetD3DDeviceResources();
|
||||
|
||||
hr = d3d_res->Initialize(target_window);
|
||||
hr = d3d_res->Initialize(target_window, output_size_);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
d3d_res->DiscardResources();
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ public:
|
|||
/// @brief 헌왕뻠닸
|
||||
void Clear();
|
||||
|
||||
virtual ~TextureCache();
|
||||
|
||||
private:
|
||||
TextureCache();
|
||||
|
||||
virtual ~TextureCache();
|
||||
|
||||
private:
|
||||
using TextureMap = UnorderedMap<size_t, TexturePtr>;
|
||||
TextureMap texture_cache_;
|
||||
|
|
|
|||
|
|
@ -126,11 +126,11 @@ public:
|
|||
/// @note 此操作会重定向输出流到标准输出流
|
||||
void ShowConsole(bool show);
|
||||
|
||||
~Logger();
|
||||
|
||||
private:
|
||||
Logger();
|
||||
|
||||
~Logger();
|
||||
|
||||
void Prepare(Level level, StringStream& sstream);
|
||||
|
||||
void Output(Level level, StringStream& sstream);
|
||||
|
|
|
|||
|
|
@ -88,11 +88,11 @@ public:
|
|||
/// @brief 清空所有资源
|
||||
void Clear();
|
||||
|
||||
virtual ~ResourceCache();
|
||||
|
||||
private:
|
||||
ResourceCache();
|
||||
|
||||
virtual ~ResourceCache();
|
||||
|
||||
private:
|
||||
UnorderedMap<String, ObjectBasePtr> object_cache_;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue