refactoring animation

This commit is contained in:
Nomango 2020-10-10 21:12:37 +08:00
parent f19d52b662
commit d9feebae31
41 changed files with 2348 additions and 2925 deletions

View File

@ -1,20 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\kiwano\2d\action\Action.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionDelay.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionGroup.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionScheduler.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionWalk.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\ActionTween.h" />
<ClInclude Include="..\..\src\kiwano\2d\action\Animation.h" />
<ClInclude Include="..\..\src\kiwano\2d\Actor.h" /> <ClInclude Include="..\..\src\kiwano\2d\Actor.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\Animation.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\Animation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\EaseFunc.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\DelayAnimation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\FrameAnimation.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\AnimationGroup.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\Interpolator.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\Animator.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\Key.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\FrameSequence.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\KeyFrame.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\TweenAnimation.h" /> <ClInclude Include="..\..\src\kiwano\2d\animation\TweenAnimation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\PathAnimation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\AnimationWrapper.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\CustomAnimation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\FrameAnimation.h" />
<ClInclude Include="..\..\src\kiwano\2d\animation\EaseFunc.h" />
<ClInclude Include="..\..\src\kiwano\2d\GifSprite.h" /> <ClInclude Include="..\..\src\kiwano\2d\GifSprite.h" />
<ClInclude Include="..\..\src\kiwano\base\component\Button.h" /> <ClInclude Include="..\..\src\kiwano\base\component\Button.h" />
<ClInclude Include="..\..\src\kiwano\base\component\Component.h" /> <ClInclude Include="..\..\src\kiwano\base\component\Component.h" />
@ -93,8 +92,6 @@
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" /> <ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" />
<ClInclude Include="..\..\src\kiwano\render\Font.h" /> <ClInclude Include="..\..\src\kiwano\render\Font.h" />
<ClInclude Include="..\..\src\kiwano\render\Frame.h" />
<ClInclude Include="..\..\src\kiwano\render\FrameSequence.h" />
<ClInclude Include="..\..\src\kiwano\render\NativeObject.h" /> <ClInclude Include="..\..\src\kiwano\render\NativeObject.h" />
<ClInclude Include="..\..\src\kiwano\render\Shape.h" /> <ClInclude Include="..\..\src\kiwano\render\Shape.h" />
<ClInclude Include="..\..\src\kiwano\render\ShapeMaker.h" /> <ClInclude Include="..\..\src\kiwano\render\ShapeMaker.h" />
@ -121,18 +118,18 @@
<ClInclude Include="..\..\src\kiwano\utils\Xml.h" /> <ClInclude Include="..\..\src\kiwano\utils\Xml.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\action\Action.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionDelay.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionGroup.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionScheduler.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionWalk.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\ActionTween.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\action\Animation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Actor.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\Actor.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\Animation.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\animation\Animation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\EaseFunc.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\animation\DelayAnimation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\FrameAnimation.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\animation\AnimationGroup.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\Animator.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\FrameSequence.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\KeyFrame.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\TweenAnimation.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\animation\TweenAnimation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\PathAnimation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\CustomAnimation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\FrameAnimation.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\animation\EaseFunc.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\DebugActor.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\DebugActor.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\ShapeActor.cpp" /> <ClCompile Include="..\..\src\kiwano\2d\ShapeActor.cpp" />
@ -179,8 +176,6 @@
<ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp" />
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp" /> <ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Font.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Font.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Frame.cpp" />
<ClCompile Include="..\..\src\kiwano\render\FrameSequence.cpp" />
<ClCompile Include="..\..\src\kiwano\render\NativeObject.cpp" /> <ClCompile Include="..\..\src\kiwano\render\NativeObject.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Shape.cpp" />
<ClCompile Include="..\..\src\kiwano\render\ShapeMaker.cpp" /> <ClCompile Include="..\..\src\kiwano\render\ShapeMaker.cpp" />

View File

@ -16,9 +16,6 @@
<Filter Include="core"> <Filter Include="core">
<UniqueIdentifier>{2e18d99a-e906-499a-9e29-4e0783202644}</UniqueIdentifier> <UniqueIdentifier>{2e18d99a-e906-499a-9e29-4e0783202644}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="2d\action">
<UniqueIdentifier>{9314f30d-5742-48b6-94e5-e3b4284106f6}</UniqueIdentifier>
</Filter>
<Filter Include="platform\win32"> <Filter Include="platform\win32">
<UniqueIdentifier>{e84dcf9a-e650-473e-8c9c-193804ab9e76}</UniqueIdentifier> <UniqueIdentifier>{e84dcf9a-e650-473e-8c9c-193804ab9e76}</UniqueIdentifier>
</Filter> </Filter>
@ -38,7 +35,7 @@
<UniqueIdentifier>{d15f4de1-7c2c-40d6-a3ce-68860b95a61e}</UniqueIdentifier> <UniqueIdentifier>{d15f4de1-7c2c-40d6-a3ce-68860b95a61e}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="2d\animation"> <Filter Include="2d\animation">
<UniqueIdentifier>{254c8f6b-8a27-4241-bae1-39cee771ccde}</UniqueIdentifier> <UniqueIdentifier>{9314f30d-5742-48b6-94e5-e3b4284106f6}</UniqueIdentifier>
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -75,15 +72,6 @@
<ClInclude Include="..\..\src\kiwano\2d\Stage.h"> <ClInclude Include="..\..\src\kiwano\2d\Stage.h">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\ActionGroup.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\ActionTween.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\Animation.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h"> <ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClInclude> </ClInclude>
@ -93,12 +81,6 @@
<ClInclude Include="..\..\src\kiwano\2d\ShapeActor.h"> <ClInclude Include="..\..\src\kiwano\2d\ShapeActor.h">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\ActionDelay.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\ActionWalk.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\utils\UserData.h"> <ClInclude Include="..\..\src\kiwano\utils\UserData.h">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClInclude> </ClInclude>
@ -258,12 +240,6 @@
<ClInclude Include="..\..\src\kiwano\core\Serializable.h"> <ClInclude Include="..\..\src\kiwano\core\Serializable.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\render\Frame.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\FrameSequence.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\utils\EventTicker.h"> <ClInclude Include="..\..\src\kiwano\utils\EventTicker.h">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClInclude> </ClInclude>
@ -285,9 +261,6 @@
<ClInclude Include="..\..\src\kiwano\utils\TaskScheduler.h"> <ClInclude Include="..\..\src\kiwano\utils\TaskScheduler.h">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\ActionScheduler.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResources.h"> <ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResources.h">
<Filter>render\DirectX</Filter> <Filter>render\DirectX</Filter>
</ClInclude> </ClInclude>
@ -345,9 +318,6 @@
<ClInclude Include="..\..\src\kiwano\core\Defer.h"> <ClInclude Include="..\..\src\kiwano\core\Defer.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\action\Action.h">
<Filter>2d\action</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\base\RefObject.h"> <ClInclude Include="..\..\src\kiwano\base\RefObject.h">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
@ -372,24 +342,42 @@
<ClInclude Include="..\..\src\kiwano\core\Value.h"> <ClInclude Include="..\..\src\kiwano\core\Value.h">
<Filter>core</Filter> <Filter>core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\Animation.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\EaseFunc.h"> <ClInclude Include="..\..\src\kiwano\2d\animation\EaseFunc.h">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\FrameAnimation.h"> <ClInclude Include="..\..\src\kiwano\2d\animation\FrameAnimation.h">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\Interpolator.h"> <ClInclude Include="..\..\src\kiwano\2d\animation\CustomAnimation.h">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\Key.h"> <ClInclude Include="..\..\src\kiwano\2d\animation\Animation.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\DelayAnimation.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\AnimationGroup.h">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\TweenAnimation.h"> <ClInclude Include="..\..\src\kiwano\2d\animation\TweenAnimation.h">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\PathAnimation.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\Animator.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\FrameSequence.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\KeyFrame.h">
<Filter>2d\animation</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\2d\animation\AnimationWrapper.h">
<Filter>2d\animation</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
@ -413,15 +401,6 @@
<ClCompile Include="..\..\src\kiwano\2d\Stage.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Stage.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\ActionGroup.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\ActionTween.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\Animation.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp"> <ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
@ -431,12 +410,6 @@
<ClCompile Include="..\..\src\kiwano\2d\ShapeActor.cpp"> <ClCompile Include="..\..\src\kiwano\2d\ShapeActor.cpp">
<Filter>2d</Filter> <Filter>2d</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\ActionDelay.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\ActionWalk.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\utils\UserData.cpp"> <ClCompile Include="..\..\src\kiwano\utils\UserData.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
@ -539,12 +512,6 @@
<ClCompile Include="..\..\src\kiwano\core\Allocator.cpp"> <ClCompile Include="..\..\src\kiwano\core\Allocator.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\render\Frame.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\FrameSequence.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\utils\EventTicker.cpp"> <ClCompile Include="..\..\src\kiwano\utils\EventTicker.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
@ -560,9 +527,6 @@
<ClCompile Include="..\..\src\kiwano\utils\TaskScheduler.cpp"> <ClCompile Include="..\..\src\kiwano\utils\TaskScheduler.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\ActionScheduler.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\utils\Logger.cpp"> <ClCompile Include="..\..\src\kiwano\utils\Logger.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
@ -608,9 +572,6 @@
<ClCompile Include="..\..\src\kiwano\utils\ConfigIni.cpp"> <ClCompile Include="..\..\src\kiwano\utils\ConfigIni.cpp">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\action\Action.cpp">
<Filter>2d\action</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\base\RefObject.cpp"> <ClCompile Include="..\..\src\kiwano\base\RefObject.cpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClCompile> </ClCompile>
@ -626,18 +587,39 @@
<ClCompile Include="..\..\src\kiwano\core\Duration.cpp"> <ClCompile Include="..\..\src\kiwano\core\Duration.cpp">
<Filter>core</Filter> <Filter>core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\Animation.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\EaseFunc.cpp"> <ClCompile Include="..\..\src\kiwano\2d\animation\EaseFunc.cpp">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\FrameAnimation.cpp"> <ClCompile Include="..\..\src\kiwano\2d\animation\FrameAnimation.cpp">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\CustomAnimation.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\Animation.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\DelayAnimation.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\AnimationGroup.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\TweenAnimation.cpp"> <ClCompile Include="..\..\src\kiwano\2d\animation\TweenAnimation.cpp">
<Filter>2d\animation</Filter> <Filter>2d\animation</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\PathAnimation.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\Animator.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\FrameSequence.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\2d\animation\KeyFrame.cpp">
<Filter>2d\animation</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="suppress_warning.ruleset" /> <None Include="suppress_warning.ruleset" />

View File

@ -70,7 +70,7 @@ Actor::~Actor()
void Actor::Update(Duration dt) void Actor::Update(Duration dt)
{ {
ActionScheduler::Update(this, dt); Animator::Update(this, dt);
TaskScheduler::Update(dt); TaskScheduler::Update(dt);
ComponentManager::Update(dt); ComponentManager::Update(dt);

View File

@ -25,7 +25,7 @@
#include <kiwano/base/component/ComponentManager.h> #include <kiwano/base/component/ComponentManager.h>
#include <kiwano/event/EventDispatcher.h> #include <kiwano/event/EventDispatcher.h>
#include <kiwano/utils/TaskScheduler.h> #include <kiwano/utils/TaskScheduler.h>
#include <kiwano/2d/action/ActionScheduler.h> #include <kiwano/2d/animation/Animator.h>
namespace kiwano namespace kiwano
{ {
@ -62,8 +62,8 @@ typedef IntrusiveList<ActorPtr> ActorList;
*/ */
class KGE_API Actor class KGE_API Actor
: public ObjectBase : public ObjectBase
, public Animator
, public TaskScheduler , public TaskScheduler
, public ActionScheduler
, public EventDispatcher , public EventDispatcher
, public ComponentManager , public ComponentManager
, protected IntrusiveListValue<ActorPtr> , protected IntrusiveListValue<ActorPtr>

View File

@ -20,7 +20,7 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/render/Frame.h> #include <kiwano/2d/animation/KeyFrame.h>
#include <kiwano/render/ShapeMaker.h> #include <kiwano/render/ShapeMaker.h>
#include <kiwano/render/RenderContext.h> #include <kiwano/render/RenderContext.h>
@ -150,17 +150,19 @@ public:
void FillRoundedRect(const Rect& rect, const Vec2& radius); void FillRoundedRect(const Rect& rect, const Vec2& radius);
/// \~chinese /// \~chinese
/// @brief 绘制图像帧 /// @brief 绘制纹理
/// @param frame 图像帧 /// @param texture 纹理
/// @param pos 绘制图像的位置 /// @param pos 绘制的目标位置
void DrawFrame(FramePtr frame, const Point& pos); /// @param crop_rect 纹理裁剪矩形
void DrawTexture(TexturePtr texture, const Point& pos, const Rect* crop_rect = nullptr);
/// \~chinese /// \~chinese
/// @brief 绘制图像帧 /// @brief 绘制纹理
/// @param frame 图像帧 /// @param texture 纹理
/// @param pos 绘制图像的位置 /// @param pos 绘制的目标位置
/// @param size 渲染的图像大小 /// @param size 绘制的目标大小
void DrawFrame(FramePtr frame, const Point& pos, const Size& size); /// @param crop_rect 纹理裁剪矩形
void DrawTexture(TexturePtr texture, const Point& pos, const Size& size, const Rect* crop_rect = nullptr);
/// \~chinese /// \~chinese
/// @brief 绘制文字布局 /// @brief 绘制文字布局
@ -381,22 +383,22 @@ inline void CanvasRenderContext::FillRoundedRect(const Rect& rect, const Vec2& r
ctx_->FillRoundedRectangle(rect, radius); ctx_->FillRoundedRectangle(rect, radius);
} }
inline void CanvasRenderContext::DrawFrame(FramePtr frame, const Point& pos) inline void CanvasRenderContext::DrawTexture(TexturePtr texture, const Point& pos, const Rect* crop_rect)
{ {
if (frame) if (texture)
{ {
Size frame_size = frame->GetSize(); this->DrawTexture(texture, pos, texture->GetSize(), crop_rect);
this->DrawFrame(frame, pos, frame_size);
} }
} }
inline void CanvasRenderContext::DrawFrame(FramePtr frame, const Point& pos, const Size& size) inline void CanvasRenderContext::DrawTexture(TexturePtr texture, const Point& pos, const Size& size,
const Rect* crop_rect)
{ {
KGE_ASSERT(ctx_); KGE_ASSERT(ctx_);
if (frame) if (texture)
{ {
ctx_->DrawFrame(frame, Rect(pos, size)); ctx_->DrawTexture(*texture, crop_rect, &Rect(pos, size));
} }
} }

View File

@ -130,7 +130,7 @@ private:
void ComposeNextFrame(); void ComposeNextFrame();
/// \~chinese /// \~chinese
/// @brief 解析当前图像 /// @brief 解析当前关键
void DisposeCurrentFrame(); void DisposeCurrentFrame();
/// \~chinese /// \~chinese
@ -138,11 +138,11 @@ private:
void OverlayNextFrame(); void OverlayNextFrame();
/// \~chinese /// \~chinese
/// @brief 保存合成后的图像 /// @brief 保存合成后的关键
void SaveComposedFrame(); void SaveComposedFrame();
/// \~chinese /// \~chinese
/// @brief 恢复已保存的图像 /// @brief 恢复已保存的关键
void RestoreSavedFrame(); void RestoreSavedFrame();
/// \~chinese /// \~chinese

View File

@ -36,9 +36,9 @@ Sprite::Sprite(const Resource& res)
Load(res); Load(res);
} }
Sprite::Sprite(FramePtr frame) Sprite::Sprite(TexturePtr texture)
{ {
SetFrame(frame); SetTexture(texture);
} }
Sprite::Sprite(const String& file_path, const Rect& crop_rect) Sprite::Sprite(const String& file_path, const Rect& crop_rect)
@ -53,110 +53,61 @@ Sprite::Sprite(const Resource& res, const Rect& crop_rect)
SetCropRect(crop_rect); SetCropRect(crop_rect);
} }
Sprite::Sprite(TexturePtr texture, const Rect& crop_rect)
{
SetTexture(texture);
SetCropRect(crop_rect);
}
Sprite::~Sprite() {} Sprite::~Sprite() {}
bool Sprite::Load(const String& file_path, bool autoresize) bool Sprite::Load(const String& file_path)
{ {
FramePtr frame = MakePtr<Frame>(file_path); TexturePtr texture = MakePtr<Texture>(file_path);
if (frame && frame->IsValid()) if (texture && texture->IsValid())
{ {
SetFrame(frame, autoresize); SetTexture(texture);
return true; return true;
} }
Fail("Sprite::Load failed"); Fail("Sprite::Load failed");
return false; return false;
} }
bool Sprite::Load(const Resource& res, bool autoresize) bool Sprite::Load(const Resource& res)
{ {
FramePtr frame = MakePtr<Frame>(res); TexturePtr texture = MakePtr<Texture>(res);
if (frame) if (texture && texture->IsValid())
{ {
SetFrame(frame, autoresize); SetTexture(texture);
return true; return true;
} }
Fail("Sprite::Load failed"); Fail("Sprite::Load failed");
return false; return false;
} }
float Sprite::GetSourceWidth() const void Sprite::SetTexture(TexturePtr texture)
{ {
if (frame_) texture_ = texture;
{
return frame_->GetSourceWidth();
}
return 0.0f;
}
float Sprite::GetSourceHeight() const Size texture_size;
if (texture_)
{ {
if (frame_) texture_size = texture_->GetSize();
{
return frame_->GetSourceHeight();
}
return 0.0f;
}
Size Sprite::GetSourceSize() const
{
if (frame_)
{
return frame_->GetSourceSize();
}
return Size();
}
Rect Sprite::GetCropRect() const
{
if (frame_)
{
return frame_->GetCropRect();
}
return Rect();
}
void Sprite::SetCropRect(const Rect& crop_rect)
{
if (frame_)
{
frame_->SetCropRect(crop_rect);
}
}
void Sprite::SetFrame(FramePtr frame, bool autoresize)
{
if (frame_ != frame)
{
frame_ = frame;
if (autoresize)
{
ResetSize();
}
}
}
void Sprite::ResetSize()
{
if (frame_)
{
SetSize(frame_->GetSize());
}
else
{
SetSize(Size());
} }
// ÖØÖòüô¾ØÐÎ
SetCropRect(Rect(Point(), texture_size));
} }
void Sprite::OnRender(RenderContext& ctx) void Sprite::OnRender(RenderContext& ctx)
{ {
if (frame_ && frame_->IsValid()) if (texture_ && texture_->IsValid())
{ {
ctx.DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds()); ctx.DrawTexture(*texture_, &crop_rect_, &GetBounds());
} }
} }
bool Sprite::CheckVisibility(RenderContext& ctx) const bool Sprite::CheckVisibility(RenderContext& ctx) const
{ {
return frame_ && frame_->IsValid() && Actor::CheckVisibility(ctx); return texture_ && texture_->IsValid() && Actor::CheckVisibility(ctx);
} }
} // namespace kiwano } // namespace kiwano

View File

@ -20,7 +20,7 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/render/Frame.h> #include <kiwano/2d/animation/KeyFrame.h>
namespace kiwano namespace kiwano
{ {
@ -53,8 +53,8 @@ public:
/// \~chinese /// \~chinese
/// @brief 创建精灵 /// @brief 创建精灵
/// @param frame 图像帧 /// @param texture 图像
Sprite(FramePtr frame); Sprite(TexturePtr texture);
/// \~chinese /// \~chinese
/// @brief 创建精灵 /// @brief 创建精灵
@ -68,61 +68,46 @@ public:
/// @param crop_rect 裁剪矩形 /// @param crop_rect 裁剪矩形
Sprite(const Resource& res, const Rect& crop_rect); Sprite(const Resource& res, const Rect& crop_rect);
/// \~chinese
/// @brief 创建精灵
/// @param texture 图像
/// @param crop_rect 裁剪矩形
Sprite(TexturePtr texture, const Rect& crop_rect);
virtual ~Sprite(); virtual ~Sprite();
/// \~chinese /// \~chinese
/// @brief 加载本地图片 /// @brief 加载本地图片并重置裁剪矩形
/// @param file_path 本地图片路径 /// @param file_path 本地图片路径
/// @param autoresize 是否自动调整自身大小为图像大小 bool Load(const String& file_path);
bool Load(const String& file_path, bool autoresize = true);
/// \~chinese /// \~chinese
/// @brief 加载图像资源 /// @brief 加载图像资源并重置裁剪矩形
/// @param res 图片资源 /// @param res 图片资源
/// @param autoresize 是否自动调整自身大小为图像大小 bool Load(const Resource& res);
bool Load(const Resource& res, bool autoresize = true);
/// \~chinese /// \~chinese
/// @brief 获取图像原宽度 /// @brief 获取图像
float GetSourceWidth() const; TexturePtr GetTexture() const;
/// \~chinese
/// @brief 获取图像原高度
float GetSourceHeight() const;
/// \~chinese
/// @brief 获取图像原大小
Size GetSourceSize() const;
/// \~chinese /// \~chinese
/// @brief 获取裁剪矩形 /// @brief 获取裁剪矩形
Rect GetCropRect() const; Rect GetCropRect() const;
/// \~chinese
/// @brief 设置图像并重置裁剪矩形
/// @param[in] texture 图像
void SetTexture(TexturePtr texture);
/// \~chinese /// \~chinese
/// @brief 使用矩形区域裁剪精灵 /// @brief 使用矩形区域裁剪精灵
/// @param crop_rect 裁剪矩形 /// @param crop_rect 裁剪矩形
void SetCropRect(const Rect& crop_rect); void SetCropRect(const Rect& crop_rect);
/// \~chinese /// \~chinese
/// @brief 获取帧图像 /// @brief 设置关键帧
FramePtr GetFrame() const; /// @param[in] frame 关键帧
void SetKeyFrame(KeyFramePtr frame);
/// \~chinese
/// @brief 设置图像帧
/// @param[in] frame 图像帧
/// @param autoresize 是否自动调整自身大小为图像大小
void SetFrame(FramePtr frame, bool autoresize = true);
/// \~chinese
/// @brief 重置精灵大小为图像帧大小
void ResetSize();
/// \~chinese
/// @brief 获取图像帧属性
inline Value<FramePtr, Function<void()>> FrameProperty()
{
return Value<FramePtr, Function<void()>>(frame_, Closure(this, &Sprite::ResetSize));
}
void OnRender(RenderContext& ctx) override; void OnRender(RenderContext& ctx) override;
@ -130,13 +115,35 @@ protected:
bool CheckVisibility(RenderContext& ctx) const override; bool CheckVisibility(RenderContext& ctx) const override;
private: private:
FramePtr frame_; TexturePtr texture_;
Rect crop_rect_;
}; };
/** @} */ /** @} */
inline FramePtr Sprite::GetFrame() const inline TexturePtr Sprite::GetTexture() const
{ {
return frame_; return texture_;
} }
inline Rect Sprite::GetCropRect() const
{
return crop_rect_;
}
inline void Sprite::SetCropRect(const Rect& crop_rect)
{
crop_rect_ = crop_rect;
SetSize(crop_rect.GetSize());
}
inline void Sprite::SetKeyFrame(KeyFramePtr frame)
{
if (frame)
{
SetTexture(frame->GetTexture());
SetCropRect(frame->GetCropRect());
}
}
} // namespace kiwano } // namespace kiwano

View File

@ -1,121 +0,0 @@
// 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/2d/Actor.h>
#include <kiwano/2d/action/Action.h>
namespace kiwano
{
ActionEntity::ActionEntity()
: running_(true)
, detach_target_(false)
, loops_done_(0)
, loops_(0)
, status_(Status::NotStarted)
{
}
ActionEntity::~ActionEntity() {}
void ActionEntity::Init(Actor* target) {}
void ActionEntity::Update(Actor* target, Duration dt)
{
Complete(target);
}
void ActionEntity::UpdateStep(Actor* target, Duration dt)
{
KGE_ASSERT(target != nullptr && "ActionEntity target should NOT be nullptr!");
elapsed_ += dt;
if (status_ == Status::NotStarted)
{
status_ = delay_.IsZero() ? Status::Started : Status::Delayed;
Init(target);
}
switch (status_)
{
case Status::Delayed:
if (elapsed_ >= delay_)
{
status_ = Status::Started;
}
break;
case Status::Started:
Update(target, dt);
break;
default:
break;
}
if (status_ == Status::Done)
{
if (cb_done_)
cb_done_(target);
if (detach_target_)
target->RemoveFromParent();
status_ = Status::Removeable;
}
}
void ActionEntity::Complete(Actor* target)
{
if (cb_loop_done_)
cb_loop_done_(target);
if (loops_ >= 0 && loops_done_ >= loops_)
{
Done();
}
else
{
Init(target); // reinit when a loop is done
}
++loops_done_;
}
void ActionEntity::Reset()
{
status_ = Status::NotStarted;
elapsed_ = 0;
loops_done_ = 0;
}
void ActionEntity::DoClone(ActionEntity* to) const
{
if (to)
{
to->SetDelay(this->GetDelay());
to->SetDoneCallback(this->GetDoneCallback());
to->SetLoopDoneCallback(this->GetLoopDoneCallback());
to->SetLoops(this->GetLoops());
to->SetName(this->GetName());
}
}
} // namespace kiwano

View File

@ -1,417 +0,0 @@
// 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/Common.h>
#include <kiwano/core/Cloneable.h>
#include <kiwano/base/ObjectBase.h>
#include <kiwano/core/Time.h>
#include <kiwano/core/IntrusiveList.h>
#include <kiwano/math/Math.h>
namespace kiwano
{
class Actor;
class ActionScheduler;
KGE_DECLARE_SMART_PTR(ActionEntity);
/**
* \~chinese
* \defgroup Actions
*/
/**
* \addtogroup Actions
* @{
*/
/// \~chinese
/// @brief 动画列表
typedef IntrusiveList<ActionEntityPtr> ActionList;
/// \~chinese
/// @brief 动画结束时的回调函数
typedef Function<void(Actor* /* target */)> ActionDoneCallback;
/// \~chinese
/// @brief 动画实体
class KGE_API ActionEntity
: public ObjectBase
, public Cloneable<ActionEntity>
, protected IntrusiveListValue<ActionEntityPtr>
{
friend class ActionScheduler;
friend class ActionGroupEntity;
friend IntrusiveList<ActionEntityPtr>;
public:
ActionEntity();
virtual ~ActionEntity();
/// \~chinese
/// @brief 继续动画
void Resume();
/// \~chinese
/// @brief 暂停动画
void Pause();
/// \~chinese
/// @brief 停止动画
void Stop();
/// \~chinese
/// @brief 设置动画延时
void SetDelay(Duration delay);
/// \~chinese
/// @brief 设置循环次数
/// @param loops 循环次数,-1 为永久循环
void SetLoops(int loops);
/// \~chinese
/// @brief 动画结束时移除目标角色
void RemoveTargetWhenDone();
/// \~chinese
/// @brief 设置动画结束时的回调函数
void SetDoneCallback(const ActionDoneCallback& cb);
/// \~chinese
/// @brief 设置动画循环结束时的回调函数
void SetLoopDoneCallback(const ActionDoneCallback& cb);
/// \~chinese
/// @brief 获取动画的倒转
virtual ActionEntity* Reverse() const = 0;
/// \~chinese
/// @brief 获取动画的运行状态
bool IsRunning() const;
/// \~chinese
/// @brief 获取动画的循环次数
int GetLoops() const;
/// \~chinese
/// @brief 获取动画的延时
Duration GetDelay() const;
/// \~chinese
/// @brief 获取动画结束时的回调函数
ActionDoneCallback GetDoneCallback() const;
/// \~chinese
/// @brief 获取动画循环结束时的回调函数
ActionDoneCallback GetLoopDoneCallback() const;
protected:
/// \~chinese
/// @brief 初始化动画
virtual void Init(Actor* target);
/// \~chinese
/// @brief 更新动画
virtual void Update(Actor* target, Duration dt);
/// \~chinese
/// @brief 更新一个时间步
void UpdateStep(Actor* target, Duration dt);
/// \~chinese
/// @brief 完成动画
void Complete(Actor* target);
/// \~chinese
/// @brief 重置动画
void Reset();
/// \~chinese
/// @brief 动画状态
enum class Status
{
NotStarted, ///< 未开始
Delayed, ///< 等待延时
Started, ///< 已开始
Done, ///< 已结束
Removeable ///< 可移除
};
/// \~chinese
/// @brief 获取动画状态
Status GetStatus() const;
/// \~chinese
/// @brief 获取消逝时间
Duration GetElapsed() const;
/// \~chinese
/// @brief 获取完成的循环次数
int GetLoopsDone() const;
/// \~chinese
/// @brief 结束动画
void Done();
/// \~chinese
/// @brief 是否已结束
bool IsDone() const;
/// \~chinese
/// @brief 是否可移除
bool IsRemoveable() const;
/// \~chinese
/// @brief 执行克隆
void DoClone(ActionEntity* to) const;
private:
Status status_;
bool running_;
bool detach_target_;
int loops_;
int loops_done_;
Duration delay_;
Duration elapsed_;
ActionDoneCallback cb_done_;
ActionDoneCallback cb_loop_done_;
};
/// \~chinese
/// @brief 动画
class KGE_API Action
{
public:
Action() = default;
inline Action(ActionEntityPtr ptr)
: ptr(ptr)
{
}
/// \~chinese
/// @brief 设置循环次数
inline Action& Loops(int loops)
{
if (ptr)
ptr->SetLoops(loops);
return (*this);
}
/// \~chinese
/// @brief 设置动画延迟
inline Action& Delay(Duration delay)
{
if (ptr)
ptr->SetDelay(delay);
return (*this);
}
/// \~chinese
/// @brief 设置动画结束回调函数
inline Action& DoneCallback(const ActionDoneCallback& cb)
{
if (ptr)
ptr->SetDoneCallback(cb);
return (*this);
}
/// \~chinese
/// @brief 设置动画循环结束时的回调函数
inline Action& LoopDoneCallback(const ActionDoneCallback& cb)
{
if (ptr)
ptr->SetLoopDoneCallback(cb);
return (*this);
}
/// \~chinese
/// @brief 动画结束时移除目标角色
inline Action& RemoveTargetWhenDone()
{
if (ptr)
ptr->RemoveTargetWhenDone();
return (*this);
}
/// \~chinese
/// @brief 设置名称
inline Action& Name(const String& name)
{
if (ptr)
ptr->SetName(name);
return (*this);
}
/// \~chinese
/// @brief 克隆动画
inline Action Clone() const
{
if (ptr)
return Action(ptr->Clone());
return Action();
}
/// \~chinese
/// @brief 获取反向动画
inline Action Reverse() const
{
if (ptr)
return Action(ptr->Reverse());
return Action();
}
/// \~chinese
/// @brief 获取指针
inline ActionEntity* Get() const
{
return const_cast<ActionEntity*>(ptr.Get());
}
/// \~chinese
/// @brief 设置动画实体
inline void SetEntity(ActionEntityPtr ptr)
{
this->ptr = ptr;
}
inline ActionEntity* operator->() const
{
return Get();
}
inline operator ActionEntity*() const
{
return Get();
}
inline operator ActionEntityPtr() const
{
return ptr;
}
inline operator bool() const
{
return ptr != nullptr;
}
protected:
ActionEntityPtr ptr;
};
/** @} */
inline void ActionEntity::Resume()
{
running_ = true;
}
inline void ActionEntity::Pause()
{
running_ = false;
}
inline void ActionEntity::Stop()
{
Done();
}
inline void ActionEntity::SetDelay(Duration delay)
{
delay_ = delay;
}
inline void ActionEntity::SetLoops(int loops)
{
loops_ = loops;
}
inline void ActionEntity::RemoveTargetWhenDone()
{
detach_target_ = true;
}
inline void ActionEntity::SetDoneCallback(const ActionDoneCallback& cb)
{
cb_done_ = cb;
}
inline void ActionEntity::SetLoopDoneCallback(const ActionDoneCallback& cb)
{
cb_loop_done_ = cb;
}
inline void ActionEntity::Done()
{
status_ = Status::Done;
}
inline ActionEntity::Status ActionEntity::GetStatus() const
{
return status_;
}
inline bool ActionEntity::IsRunning() const
{
return running_;
}
inline bool ActionEntity::IsDone() const
{
return status_ == Status::Done || status_ == Status::Removeable;
}
inline bool ActionEntity::IsRemoveable() const
{
return status_ == Status::Removeable;
}
inline int ActionEntity::GetLoops() const
{
return loops_;
}
inline Duration ActionEntity::GetDelay() const
{
return delay_;
}
inline Duration ActionEntity::GetElapsed() const
{
return elapsed_;
}
inline int ActionEntity::GetLoopsDone() const
{
return loops_done_;
}
inline ActionDoneCallback ActionEntity::GetDoneCallback() const
{
return cb_done_;
}
inline ActionDoneCallback ActionEntity::GetLoopDoneCallback() const
{
return cb_loop_done_;
}
} // namespace kiwano

View File

@ -1,528 +0,0 @@
// 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 <functional>
#include <kiwano/2d/Actor.h>
#include <kiwano/2d/action/ActionTween.h>
namespace kiwano
{
//-------------------------------------------------------
// Ease Functions
//-------------------------------------------------------
inline EaseFunc MakeEaseIn(float rate)
{
return std::bind(math::EaseIn, std::placeholders::_1, rate);
}
inline EaseFunc MakeEaseOut(float rate)
{
return std::bind(math::EaseOut, std::placeholders::_1, rate);
}
inline EaseFunc MakeEaseInOut(float rate)
{
return std::bind(math::EaseInOut, std::placeholders::_1, rate);
}
inline EaseFunc MakeEaseElasticIn(float period)
{
return std::bind(math::EaseElasticIn, std::placeholders::_1, period);
}
inline EaseFunc MakeEaseElasticOut(float period)
{
return std::bind(math::EaseElasticOut, std::placeholders::_1, period);
}
inline EaseFunc MakeEaseElasticInOut(float period)
{
return std::bind(math::EaseElasticInOut, std::placeholders::_1, period);
}
KGE_API EaseFunc Ease::Linear = math::Linear;
KGE_API EaseFunc Ease::EaseIn = MakeEaseIn(2.f);
KGE_API EaseFunc Ease::EaseOut = MakeEaseOut(2.f);
KGE_API EaseFunc Ease::EaseInOut = MakeEaseInOut(2.f);
KGE_API EaseFunc Ease::ExpoIn = math::EaseExponentialIn;
KGE_API EaseFunc Ease::ExpoOut = math::EaseExponentialOut;
KGE_API EaseFunc Ease::ExpoInOut = math::EaseExponentialInOut;
KGE_API EaseFunc Ease::BounceIn = math::EaseBounceIn;
KGE_API EaseFunc Ease::BounceOut = math::EaseBounceOut;
KGE_API EaseFunc Ease::BounceInOut = math::EaseBounceInOut;
KGE_API EaseFunc Ease::ElasticIn = MakeEaseElasticIn(0.3f);
KGE_API EaseFunc Ease::ElasticOut = MakeEaseElasticOut(0.3f);
KGE_API EaseFunc Ease::ElasticInOut = MakeEaseElasticInOut(0.3f);
KGE_API EaseFunc Ease::SineIn = math::EaseSineIn;
KGE_API EaseFunc Ease::SineOut = math::EaseSineOut;
KGE_API EaseFunc Ease::SineInOut = math::EaseSineInOut;
KGE_API EaseFunc Ease::BackIn = math::EaseBackIn;
KGE_API EaseFunc Ease::BackOut = math::EaseBackOut;
KGE_API EaseFunc Ease::BackInOut = math::EaseBackInOut;
KGE_API EaseFunc Ease::QuadIn = math::EaseQuadIn;
KGE_API EaseFunc Ease::QuadOut = math::EaseQuadOut;
KGE_API EaseFunc Ease::QuadInOut = math::EaseQuadInOut;
KGE_API EaseFunc Ease::CubicIn = math::EaseCubicIn;
KGE_API EaseFunc Ease::CubicOut = math::EaseCubicOut;
KGE_API EaseFunc Ease::CubicInOut = math::EaseCubicInOut;
KGE_API EaseFunc Ease::QuartIn = math::EaseQuartIn;
KGE_API EaseFunc Ease::QuartOut = math::EaseQuartOut;
KGE_API EaseFunc Ease::QuartInOut = math::EaseQuartInOut;
KGE_API EaseFunc Ease::QuintIn = math::EaseQuintIn;
KGE_API EaseFunc Ease::QuintOut = math::EaseQuintOut;
KGE_API EaseFunc Ease::QuintInOut = math::EaseQuintInOut;
//-------------------------------------------------------
// ActionTweenEntity
//-------------------------------------------------------
ActionTweenEntity::ActionTweenEntity()
: dur_()
, ease_func_(nullptr)
{
}
ActionTweenEntity::ActionTweenEntity(Duration duration)
: dur_(duration)
, ease_func_(nullptr)
{
}
void ActionTweenEntity::Update(Actor* target, Duration dt)
{
float percent;
if (dur_.IsZero())
{
percent = 1.f;
Complete(target);
}
else
{
Duration elapsed = GetElapsed() - GetDelay();
float loops_done = elapsed / dur_;
while (GetLoopsDone() < static_cast<int>(loops_done))
{
Complete(target); // loops_done_++
}
percent = (GetStatus() == Status::Done) ? 1.f : (loops_done - static_cast<float>(GetLoopsDone()));
}
if (ease_func_)
percent = ease_func_(percent);
UpdateTween(target, percent);
}
void ActionTweenEntity::DoClone(ActionTweenEntity* to) const
{
if (to)
{
ActionEntity::DoClone(to);
to->SetDuration(this->GetDuration());
to->SetEaseFunc(this->GetEaseFunc());
}
}
//-------------------------------------------------------
// Move Action
//-------------------------------------------------------
ActionMoveByEntity::ActionMoveByEntity(Duration duration, const Vec2& displacement)
: ActionTweenEntity(duration)
, displacement_(displacement)
{
}
void ActionMoveByEntity::Init(Actor* target)
{
if (target)
{
prev_pos_ = start_pos_ = target->GetPosition();
}
}
void ActionMoveByEntity::UpdateTween(Actor* target, float percent)
{
Point diff = target->GetPosition() - prev_pos_;
start_pos_ = start_pos_ + diff;
Point new_pos = start_pos_ + (displacement_ * percent);
target->SetPosition(new_pos);
prev_pos_ = new_pos;
}
ActionMoveByEntity* ActionMoveByEntity::Clone() const
{
ActionMoveByEntity* ptr = new ActionMoveByEntity(GetDuration(), displacement_);
DoClone(ptr);
return ptr;
}
ActionMoveByEntity* ActionMoveByEntity::Reverse() const
{
ActionMoveByEntity* ptr = new ActionMoveByEntity(GetDuration(), -displacement_);
DoClone(ptr);
return ptr;
}
ActionMoveToEntity::ActionMoveToEntity(Duration duration, const Point& distination)
: ActionMoveByEntity(duration, Vec2())
, distination_(distination)
{
}
ActionMoveToEntity* ActionMoveToEntity::Clone() const
{
ActionMoveToEntity* ptr = new ActionMoveToEntity(GetDuration(), distination_);
DoClone(ptr);
return ptr;
}
void ActionMoveToEntity::Init(Actor* target)
{
ActionMoveByEntity::Init(target);
displacement_ = distination_ - start_pos_;
}
//-------------------------------------------------------
// Jump Action
//-------------------------------------------------------
ActionJumpByEntity::ActionJumpByEntity(Duration duration, const Vec2& displacement, float height, int count)
: ActionTweenEntity(duration)
, height_(height)
, jump_count_(count)
, displacement_(displacement)
{
}
ActionJumpByEntity* ActionJumpByEntity::Clone() const
{
ActionJumpByEntity* ptr = new ActionJumpByEntity(GetDuration(), displacement_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
ActionJumpByEntity* ActionJumpByEntity::Reverse() const
{
ActionJumpByEntity* ptr = new ActionJumpByEntity(GetDuration(), -displacement_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
void ActionJumpByEntity::Init(Actor* target)
{
if (target)
{
prev_pos_ = start_pos_ = target->GetPosition();
}
}
void ActionJumpByEntity::UpdateTween(Actor* target, float percent)
{
float frac = fmod(percent * jump_count_, 1.f);
float x = displacement_.x * percent;
float y = height_ * 4 * frac * (1 - frac);
y += displacement_.y * percent;
Point diff = target->GetPosition() - prev_pos_;
start_pos_ = diff + start_pos_;
Point new_pos = start_pos_ + Point(x, y);
target->SetPosition(new_pos);
prev_pos_ = new_pos;
}
ActionJumpToEntity::ActionJumpToEntity(Duration duration, const Point& distination, float height, int count)
: ActionJumpByEntity(duration, Vec2(), height, count)
, distination_(distination)
{
}
ActionJumpToEntity* ActionJumpToEntity::Clone() const
{
ActionJumpToEntity* ptr = new ActionJumpToEntity(GetDuration(), distination_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
void ActionJumpToEntity::Init(Actor* target)
{
ActionJumpByEntity::Init(target);
displacement_ = distination_ - start_pos_;
}
//-------------------------------------------------------
// Scale Action
//-------------------------------------------------------
ActionScaleByEntity::ActionScaleByEntity(Duration duration, float scale_x, float scale_y)
: ActionTweenEntity(duration)
, delta_x_(scale_x)
, delta_y_(scale_y)
, start_scale_x_(0.f)
, start_scale_y_(0.f)
{
}
void ActionScaleByEntity::Init(Actor* target)
{
if (target)
{
start_scale_x_ = target->GetScaleX();
start_scale_y_ = target->GetScaleY();
}
}
void ActionScaleByEntity::UpdateTween(Actor* target, float percent)
{
target->SetScale(Vec2{ start_scale_x_ + delta_x_ * percent, start_scale_y_ + delta_y_ * percent });
}
ActionScaleByEntity* ActionScaleByEntity::Clone() const
{
ActionScaleByEntity* ptr = new ActionScaleByEntity(GetDuration(), delta_x_, delta_y_);
DoClone(ptr);
return ptr;
}
ActionScaleByEntity* ActionScaleByEntity::Reverse() const
{
ActionScaleByEntity* ptr = new ActionScaleByEntity(GetDuration(), -delta_x_, -delta_y_);
DoClone(ptr);
return ptr;
}
ActionScaleToEntity::ActionScaleToEntity(Duration duration, float scale_x, float scale_y)
: ActionScaleByEntity(duration, 0, 0)
, end_scale_x_(scale_x)
, end_scale_y_(scale_y)
{
}
ActionScaleToEntity* ActionScaleToEntity::Clone() const
{
ActionScaleToEntity* ptr = new ActionScaleToEntity(GetDuration(), end_scale_x_, end_scale_y_);
DoClone(ptr);
return ptr;
}
void ActionScaleToEntity::Init(Actor* target)
{
ActionScaleByEntity::Init(target);
delta_x_ = end_scale_x_ - start_scale_x_;
delta_y_ = end_scale_y_ - start_scale_y_;
}
//-------------------------------------------------------
// Opacity Action
//-------------------------------------------------------
ActionFadeToEntity::ActionFadeToEntity(Duration duration, float opacity)
: ActionTweenEntity(duration)
, delta_val_(0.0f)
, start_val_(0.f)
, end_val_(opacity)
{
}
void ActionFadeToEntity::Init(Actor* target)
{
if (target)
{
start_val_ = target->GetOpacity();
delta_val_ = end_val_ - start_val_;
}
}
void ActionFadeToEntity::UpdateTween(Actor* target, float percent)
{
target->SetOpacity(start_val_ + delta_val_ * percent);
}
ActionFadeToEntity* ActionFadeToEntity::Clone() const
{
ActionFadeToEntity* ptr = new ActionFadeToEntity(GetDuration(), end_val_);
DoClone(ptr);
return ptr;
}
//-------------------------------------------------------
// Rotate Action
//-------------------------------------------------------
ActionRotateByEntity::ActionRotateByEntity(Duration duration, float rotation)
: ActionTweenEntity(duration)
, delta_val_(rotation)
, start_val_(0.0f)
{
}
void ActionRotateByEntity::Init(Actor* target)
{
if (target)
{
start_val_ = target->GetRotation();
}
}
void ActionRotateByEntity::UpdateTween(Actor* target, float percent)
{
float rotation = start_val_ + delta_val_ * percent;
if (rotation > 360.f)
rotation -= 360.f;
target->SetRotation(rotation);
}
ActionRotateByEntity* ActionRotateByEntity::Clone() const
{
ActionRotateByEntity* ptr = new ActionRotateByEntity(GetDuration(), delta_val_);
DoClone(ptr);
return ptr;
}
ActionRotateByEntity* ActionRotateByEntity::Reverse() const
{
ActionRotateByEntity* ptr = new ActionRotateByEntity(GetDuration(), -delta_val_);
DoClone(ptr);
return ptr;
}
ActionRotateToEntity::ActionRotateToEntity(Duration duration, float rotation)
: ActionRotateByEntity(duration, 0)
, end_val_(rotation)
{
}
ActionRotateToEntity* ActionRotateToEntity::Clone() const
{
ActionRotateToEntity* ptr = new ActionRotateToEntity(GetDuration(), end_val_);
DoClone(ptr);
return ptr;
}
void ActionRotateToEntity::Init(Actor* target)
{
ActionRotateByEntity::Init(target);
delta_val_ = end_val_ - start_val_;
}
//-------------------------------------------------------
// ActionCustomEntity
//-------------------------------------------------------
ActionCustomEntity::ActionCustomEntity(Duration duration, ActionCustom::TweenFunc tween_func)
: ActionTweenEntity(duration)
, tween_func_(tween_func)
{
}
ActionCustomEntity* ActionCustomEntity::Clone() const
{
ActionCustomEntity* ptr = new ActionCustomEntity(GetDuration(), tween_func_);
DoClone(ptr);
return ptr;
}
void ActionCustomEntity::Init(Actor* target)
{
if (!tween_func_)
this->Done();
}
void ActionCustomEntity::UpdateTween(Actor* target, float percent)
{
if (tween_func_)
tween_func_(target, percent);
}
ActionMoveBy::ActionMoveBy(Duration duration, const Vec2& displacement)
{
SetEntity(MakePtr<ActionMoveByEntity>(duration, displacement));
}
ActionMoveTo::ActionMoveTo(Duration duration, const Point& distination)
{
SetEntity(MakePtr<ActionMoveToEntity>(duration, distination));
}
ActionJumpBy::ActionJumpBy(Duration duration, const Vec2& displacement, float height, int count)
{
SetEntity(MakePtr<ActionJumpByEntity>(duration, displacement, height, count));
}
ActionJumpTo::ActionJumpTo(Duration duration, const Point& distination, float height, int count)
{
SetEntity(MakePtr<ActionJumpToEntity>(duration, distination, height, count));
}
ActionScaleBy::ActionScaleBy(Duration duration, float scale_x, float scale_y)
{
SetEntity(MakePtr<ActionScaleByEntity>(duration, scale_x, scale_y));
}
ActionScaleBy::ActionScaleBy(Duration duration, Vec2 scale)
{
SetEntity(MakePtr<ActionScaleByEntity>(duration, scale.x, scale.y));
}
ActionScaleTo::ActionScaleTo(Duration duration, float scale_x, float scale_y)
{
SetEntity(MakePtr<ActionScaleToEntity>(duration, scale_x, scale_y));
}
ActionScaleTo::ActionScaleTo(Duration duration, Vec2 scale)
{
SetEntity(MakePtr<ActionScaleToEntity>(duration, scale.x, scale.y));
}
ActionFadeTo::ActionFadeTo(Duration duration, float opacity)
{
SetEntity(MakePtr<ActionFadeToEntity>(duration, opacity));
}
ActionFadeIn::ActionFadeIn(Duration duration)
{
SetEntity(MakePtr<ActionFadeToEntity>(duration, 1.0f));
}
ActionFadeOut::ActionFadeOut(Duration duration)
{
SetEntity(MakePtr<ActionFadeToEntity>(duration, 0.0f));
}
ActionRotateBy::ActionRotateBy(Duration duration, float rotation)
{
SetEntity(MakePtr<ActionRotateByEntity>(duration, rotation));
}
ActionRotateTo::ActionRotateTo(Duration duration, float rotation)
{
SetEntity(MakePtr<ActionRotateToEntity>(duration, rotation));
}
ActionCustom::ActionCustom(Duration duration, TweenFunc tween_func)
{
SetEntity(MakePtr<ActionCustomEntity>(duration, tween_func));
}
} // namespace kiwano

View File

@ -1,923 +0,0 @@
// 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/2d/action/Action.h>
#include <kiwano/utils/Logger.h>
namespace kiwano
{
/// \~chinese
/// @brief 缓动函数
using EaseFunc = Function<float(float)>;
/// \~chinese
/// @brief 缓动函数枚举
/// @details 查看 https://easings.net 获取更多信息
struct Ease
{
static KGE_API EaseFunc Linear; ///< 线性
static KGE_API EaseFunc EaseIn; ///< 由慢变快
static KGE_API EaseFunc EaseOut; ///< 由快变慢
static KGE_API EaseFunc EaseInOut; ///< 由慢变快, 再由快变慢
static KGE_API EaseFunc ExpoIn; ///< 由慢变极快
static KGE_API EaseFunc ExpoOut; ///< 由极快变慢
static KGE_API EaseFunc ExpoInOut; ///< 由慢至极快, 再由极快边慢
static KGE_API EaseFunc ElasticIn; ///< 自起点赋予弹性
static KGE_API EaseFunc ElasticOut; ///< 自终点赋予弹性
static KGE_API EaseFunc ElasticInOut; ///< 再起点和终点赋予弹性
static KGE_API EaseFunc BounceIn; ///< 自起点赋予反弹力
static KGE_API EaseFunc BounceOut; ///< 自终点赋予反弹力
static KGE_API EaseFunc BounceInOut; ///< 在起点和终点赋予反弹力
static KGE_API EaseFunc BackIn;
static KGE_API EaseFunc BackOut;
static KGE_API EaseFunc BackInOut;
static KGE_API EaseFunc QuadIn;
static KGE_API EaseFunc QuadOut;
static KGE_API EaseFunc QuadInOut;
static KGE_API EaseFunc CubicIn;
static KGE_API EaseFunc CubicOut;
static KGE_API EaseFunc CubicInOut;
static KGE_API EaseFunc QuartIn;
static KGE_API EaseFunc QuartOut;
static KGE_API EaseFunc QuartInOut;
static KGE_API EaseFunc QuintIn;
static KGE_API EaseFunc QuintOut;
static KGE_API EaseFunc QuintInOut;
static KGE_API EaseFunc SineIn;
static KGE_API EaseFunc SineOut;
static KGE_API EaseFunc SineInOut;
};
KGE_DECLARE_SMART_PTR(ActionTweenEntity);
KGE_DECLARE_SMART_PTR(ActionMoveByEntity);
KGE_DECLARE_SMART_PTR(ActionMoveToEntity);
KGE_DECLARE_SMART_PTR(ActionJumpByEntity);
KGE_DECLARE_SMART_PTR(ActionJumpToEntity);
KGE_DECLARE_SMART_PTR(ActionScaleByEntity);
KGE_DECLARE_SMART_PTR(ActionScaleToEntity);
KGE_DECLARE_SMART_PTR(ActionFadeToEntity);
KGE_DECLARE_SMART_PTR(ActionRotateByEntity);
KGE_DECLARE_SMART_PTR(ActionRotateToEntity);
KGE_DECLARE_SMART_PTR(ActionCustomEntity);
/**
* \addtogroup Actions
* @{
*/
/// \~chinese
/// @brief 补间动画实体
class KGE_API ActionTweenEntity : public ActionEntity
{
public:
/// \~chinese
/// @brief 获取动画时长
Duration GetDuration() const;
/// \~chinese
/// @brief 设置动画时长
void SetDuration(Duration duration);
/// \~chinese
/// @brief 获取动画速度缓动函数
const EaseFunc& GetEaseFunc() const;
/// \~chinese
/// @brief 设置动画速度缓动函数
void SetEaseFunc(const EaseFunc& func);
protected:
ActionTweenEntity();
/// \~chinese
/// @brief 补间动画
/// @param duration 动画时长
/// @param func 动画速度缓动函数
ActionTweenEntity(Duration duration);
void Update(Actor* target, Duration dt) override;
virtual void UpdateTween(Actor* target, float percent) = 0;
void DoClone(ActionTweenEntity* to) const;
private:
Duration dur_;
EaseFunc ease_func_;
};
/// \~chinese
/// @brief 补间动画
class ActionTween : public Action
{
public:
ActionTween() = default;
inline ActionTween(ActionTweenEntityPtr ptr)
{
SetEntity(ptr);
}
/// \~chinese
/// @brief 设置缓动函数
inline ActionTween& Ease(EaseFunc ease)
{
auto tween_ptr = Get();
if (tween_ptr)
tween_ptr->SetEaseFunc(ease);
return (*this);
}
/// \~chinese
/// @brief 获取指针
inline ActionTweenEntity* Get() const
{
return static_cast<ActionTweenEntity*>(Action::Get());
}
/// \~chinese
/// @brief 设置动画实体
inline void SetEntity(ActionTweenEntityPtr tween_ptr)
{
Action::SetEntity(tween_ptr.Get());
}
inline ActionTweenEntity* operator->() const
{
return Get();
}
};
/// \~chinese
/// @brief 相对位移动画
class KGE_API ActionMoveBy : public ActionTween
{
public:
/// \~chinese
/// @brief 创建相对位移动画
/// @param duration 动画时长
/// @param displacement 位移向量
ActionMoveBy(Duration duration, const Vec2& displacement);
};
/// \~chinese
/// @brief 相对位移动画实体
class KGE_API ActionMoveByEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建相对位移动画
/// @param duration 动画时长
/// @param displacement 位移向量
ActionMoveByEntity(Duration duration, const Vec2& displacement);
/// \~chinese
/// @brief 获取位移向量
Vec2 GetDisplacement() const;
/// \~chinese
/// @brief 设置位移向量
void SetDisplacement(const Vec2& displacement);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionMoveByEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionMoveByEntity* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
protected:
Point start_pos_;
Point prev_pos_;
Vec2 displacement_;
};
/// \~chinese
/// @brief 位移动画
class KGE_API ActionMoveTo : public ActionTween
{
public:
/// \~chinese
/// @brief 创建位移动画
/// @param duration 动画时长
/// @param distination 目的坐标
ActionMoveTo(Duration duration, const Point& distination);
};
/// \~chinese
/// @brief 位移动画实体
class KGE_API ActionMoveToEntity : public ActionMoveByEntity
{
public:
/// \~chinese
/// @brief 创建位移动画
/// @param duration 动画时长
/// @param distination 目的坐标
ActionMoveToEntity(Duration duration, const Point& distination);
/// \~chinese
/// @brief 获取目的坐标
Point GetDistination() const;
/// \~chinese
/// @brief 设置目的坐标
void SetDistination(const Point& distination);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionMoveToEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionMoveToEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionMoveToEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
Point distination_;
};
/// \~chinese
/// @brief 相对跳跃动画
class KGE_API ActionJumpBy : public ActionTween
{
public:
/// \~chinese
/// @brief 创建相对跳跃动画
/// @param duration 动画时长
/// @param displacement 跳跃位移向量
/// @param height 跳跃高度
/// @param count 跳跃次数
ActionJumpBy(Duration duration, const Vec2& displacement, float height, int count = 1);
};
/// \~chinese
/// @brief 相对跳跃动画实体
class KGE_API ActionJumpByEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建相对跳跃动画
/// @param duration 动画时长
/// @param displacement 跳跃位移向量
/// @param height 跳跃高度
/// @param count 跳跃次数
ActionJumpByEntity(Duration duration, const Vec2& displacement, float height, int count = 1);
/// \~chinese
/// @brief 获取跳跃位移
Vec2 GetDisplacement() const;
/// \~chinese
/// @brief 获取跳跃高度
float GetJumpHeight() const;
/// \~chinese
/// @brief 获取跳跃次数
int GetJumpCount() const;
/// \~chinese
/// @brief 设置跳跃位移
void SetDisplacement(const Vec2& displacement);
/// \~chinese
/// @brief 设置跳跃高度
void SetJumpHeight(float height);
/// \~chinese
/// @brief 设置跳跃次数
void SetJumpCount(int count);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionJumpByEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionJumpByEntity* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
protected:
float height_;
int jump_count_;
Point start_pos_;
Point displacement_;
Point prev_pos_;
};
/// \~chinese
/// @brief 跳跃动画
class KGE_API ActionJumpTo : public ActionTween
{
public:
/// \~chinese
/// @brief 创建跳跃动画
/// @param duration 动画时长
/// @param distination 目的坐标
/// @param height 跳跃高度
/// @param count 跳跃次数
ActionJumpTo(Duration duration, const Point& distination, float height, int count = 1);
};
/// \~chinese
/// @brief 跳跃动画实体
class KGE_API ActionJumpToEntity : public ActionJumpByEntity
{
public:
/// \~chinese
/// @brief 创建跳跃动画
/// @param duration 动画时长
/// @param distination 目的坐标
/// @param height 跳跃高度
/// @param count 跳跃次数
ActionJumpToEntity(Duration duration, const Point& distination, float height, int count = 1);
/// \~chinese
/// @brief 获取目的坐标
Point GetDistination() const;
/// \~chinese
/// @brief 设置目的坐标
void SetDistination(const Point& distination);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionJumpToEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionJumpToEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionJumpToEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
Point distination_;
};
/// \~chinese
/// @brief 相对缩放动画
class KGE_API ActionScaleBy : public ActionTween
{
public:
/// \~chinese
/// @brief 创建相对缩放动画
/// @param duration 动画时长
/// @param scale_x 横向缩放相对变化值
/// @param scale_y 纵向缩放相对变化值
ActionScaleBy(Duration duration, float scale_x, float scale_y);
/// \~chinese
/// @brief 创建相对缩放动画
/// @param duration 动画时长
/// @param scale 缩放相对变化值
ActionScaleBy(Duration duration, Vec2 scale);
};
/// \~chinese
/// @brief 相对缩放动画实体
class KGE_API ActionScaleByEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建相对缩放动画
/// @param duration 动画时长
/// @param scale_x 横向缩放相对变化值
/// @param scale_y 纵向缩放相对变化值
ActionScaleByEntity(Duration duration, float scale_x, float scale_y);
/// \~chinese
/// @brief 获取横向缩放相对变化值
float GetScaleX() const;
/// \~chinese
/// @brief 获取横向缩放相对变化值
float GetScaleY() const;
/// \~chinese
/// @brief 设置纵向缩放相对变化值
void SetScaleX(float scale_x);
/// \~chinese
/// @brief 设置纵向缩放相对变化值
void SetScaleY(float scale_y);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionScaleByEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionScaleByEntity* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
protected:
float start_scale_x_;
float start_scale_y_;
float delta_x_;
float delta_y_;
};
/// \~chinese
/// @brief 缩放动画
class KGE_API ActionScaleTo : public ActionTween
{
public:
/// \~chinese
/// @brief 创建缩放动画
/// @param duration 动画时长
/// @param scale_x 横向缩放目标值
/// @param scale_y 纵向缩放目标值
ActionScaleTo(Duration duration, float scale_x, float scale_y);
/// \~chinese
/// @brief 创建缩放动画
/// @param duration 动画时长
/// @param scale 缩放目标值
ActionScaleTo(Duration duration, Vec2 scale);
};
/// \~chinese
/// @brief 缩放动画实体
class KGE_API ActionScaleToEntity : public ActionScaleByEntity
{
public:
/// \~chinese
/// @brief 创建缩放动画
/// @param duration 动画时长
/// @param scale_x 横向缩放目标值
/// @param scale_y 纵向缩放目标值
ActionScaleToEntity(Duration duration, float scale_x, float scale_y);
/// \~chinese
/// @brief 获取横向缩放目标值
float GetTargetScaleX() const;
/// \~chinese
/// @brief 获取横向缩放目标值
float GetTargetScaleY() const;
/// \~chinese
/// @brief 设置纵向缩放目标值
void SetTargetScaleX(float scale_x);
/// \~chinese
/// @brief 设置纵向缩放目标值
void SetTargetScaleY(float scale_y);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionScaleToEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionScaleToEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionScaleToEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
float end_scale_x_;
float end_scale_y_;
};
/// \~chinese
/// @brief 透明度渐变动画
class KGE_API ActionFadeTo : public ActionTween
{
public:
/// \~chinese
/// @brief 创建透明度渐变动画
/// @param duration 动画时长
/// @param opacity 目标透明度
ActionFadeTo(Duration duration, float opacity);
};
/// \~chinese
/// @brief 淡入动画
class KGE_API ActionFadeIn : public ActionTween
{
public:
/// \~chinese
/// @brief 创建淡入动画
/// @param duration 动画时长
ActionFadeIn(Duration duration);
};
/// \~chinese
/// @brief 淡出动画
class KGE_API ActionFadeOut : public ActionTween
{
public:
/// \~chinese
/// @brief 创建淡出动画
/// @param duration 动画时长
ActionFadeOut(Duration duration);
};
/// \~chinese
/// @brief 透明度渐变动画实体
class KGE_API ActionFadeToEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建透明度渐变动画
/// @param duration 动画时长
/// @param opacity 目标透明度
ActionFadeToEntity(Duration duration, float opacity);
/// \~chinese
/// @brief 获取目标透明度
float GetTargetOpacity() const;
/// \~chinese
/// @brief 设置目标透明度
void SetTargetOpacity(float opacity);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionFadeToEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionFadeToEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionFadeToEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
private:
float start_val_;
float delta_val_;
float end_val_;
};
/// \~chinese
/// @brief 相对旋转动画
class KGE_API ActionRotateBy : public ActionTween
{
public:
/// \~chinese
/// @brief 创建相对旋转动画
/// @param duration 动画时长
/// @param rotation 角度相对变化值
ActionRotateBy(Duration duration, float rotation);
};
/// \~chinese
/// @brief 相对旋转动画实体
class KGE_API ActionRotateByEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建相对旋转动画
/// @param duration 动画时长
/// @param rotation 角度相对变化值
ActionRotateByEntity(Duration duration, float rotation);
/// \~chinese
/// @brief 获取角度相对变化值
float GetRotation() const;
/// \~chinese
/// @brief 设置角度相对变化值
void SetRotation(float rotation);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionRotateByEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionRotateByEntity* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
protected:
float start_val_;
float delta_val_;
};
/// \~chinese
/// @brief 旋转动画
class KGE_API ActionRotateTo : public ActionTween
{
public:
/// \~chinese
/// @brief 创建旋转动画
/// @param duration 动画时长
/// @param rotation 目标角度
ActionRotateTo(Duration duration, float rotation);
};
/// \~chinese
/// @brief 旋转动画实体
class KGE_API ActionRotateToEntity : public ActionRotateByEntity
{
public:
/// \~chinese
/// @brief 创建旋转动画
/// @param duration 动画时长
/// @param rotation 目标角度
ActionRotateToEntity(Duration duration, float rotation);
/// \~chinese
/// @brief 获取目标角度
float GetTargetRotation() const;
/// \~chinese
/// @brief 设置目标角度
void SetTargetRotation(float rotation);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionRotateToEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionRotateToEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionRotateToEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
float end_val_;
};
/// \~chinese
/// @brief 自定义动画
class KGE_API ActionCustom : public ActionTween
{
public:
/// \~chinese
/// @brief 动画回调函数
/// @details 在动画更新时回调该函数第一个参数是执行动画的目标第二个参数是动画进度0.0 - 1.0
using TweenFunc = Function<void(Actor* /* target */, float /* percent */)>;
/// \~chinese
/// @brief 创建自定义动画
/// @param duration 动画时长
/// @param tween_func 动画回调函数
ActionCustom(Duration duration, TweenFunc tween_func);
};
/// \~chinese
/// @brief 自定义动画实体
class KGE_API ActionCustomEntity : public ActionTweenEntity
{
public:
/// \~chinese
/// @brief 创建自定义动画
/// @param duration 动画时长
/// @param tween_func 动画回调函数
ActionCustomEntity(Duration duration, ActionCustom::TweenFunc tween_func);
/// \~chinese
/// @brief 获取动画回调函数
ActionCustom::TweenFunc GetTweenFunc() const;
/// \~chinese
/// @brief 设置动画回调函数
void SetTweenFunc(const ActionCustom::TweenFunc& tween_func);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ActionCustomEntity* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ActionCustomEntity* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ActionCustomEntity");
return nullptr;
}
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
private:
ActionCustom::TweenFunc tween_func_;
};
/** @} */
inline const EaseFunc& ActionTweenEntity::GetEaseFunc() const
{
return ease_func_;
}
inline Duration ActionTweenEntity::GetDuration() const
{
return dur_;
}
inline void ActionTweenEntity::SetDuration(Duration duration)
{
dur_ = duration;
}
inline void ActionTweenEntity::SetEaseFunc(const EaseFunc& func)
{
ease_func_ = func;
}
inline Vec2 ActionMoveByEntity::GetDisplacement() const
{
return displacement_;
}
inline void ActionMoveByEntity::SetDisplacement(const Vec2& displacement)
{
displacement_ = displacement;
}
inline Point ActionMoveToEntity::GetDistination() const
{
return distination_;
}
inline void ActionMoveToEntity::SetDistination(const Point& distination)
{
distination_ = distination;
}
inline Vec2 ActionJumpByEntity::GetDisplacement() const
{
return displacement_;
}
inline float ActionJumpByEntity::GetJumpHeight() const
{
return height_;
}
inline int ActionJumpByEntity::GetJumpCount() const
{
return jump_count_;
}
inline void ActionJumpByEntity::SetDisplacement(const Vec2& displacement)
{
displacement_ = displacement;
}
inline void ActionJumpByEntity::SetJumpHeight(float height)
{
height_ = height;
}
inline void ActionJumpByEntity::SetJumpCount(int count)
{
jump_count_ = count;
}
inline Point ActionJumpToEntity::GetDistination() const
{
return distination_;
}
inline void ActionJumpToEntity::SetDistination(const Point& distination)
{
distination_ = distination;
}
inline float ActionScaleByEntity::GetScaleX() const
{
return delta_x_;
}
inline float ActionScaleByEntity::GetScaleY() const
{
return delta_y_;
}
inline void ActionScaleByEntity::SetScaleX(float scale_x)
{
delta_x_ = scale_x;
}
inline void ActionScaleByEntity::SetScaleY(float scale_y)
{
delta_y_ = scale_y;
}
inline float ActionScaleToEntity::GetTargetScaleX() const
{
return end_scale_x_;
}
inline float ActionScaleToEntity::GetTargetScaleY() const
{
return end_scale_y_;
}
inline void ActionScaleToEntity::SetTargetScaleX(float scale_x)
{
end_scale_x_ = scale_x;
}
inline void ActionScaleToEntity::SetTargetScaleY(float scale_y)
{
end_scale_y_ = scale_y;
}
inline float ActionFadeToEntity::GetTargetOpacity() const
{
return end_val_;
}
inline void ActionFadeToEntity::SetTargetOpacity(float opacity)
{
end_val_ = opacity;
}
inline float ActionRotateByEntity::GetRotation() const
{
return delta_val_;
}
inline void ActionRotateByEntity::SetRotation(float rotation)
{
delta_val_ = rotation;
}
inline float ActionRotateToEntity::GetTargetRotation() const
{
return end_val_;
}
inline void ActionRotateToEntity::SetTargetRotation(float rotation)
{
end_val_ = rotation;
}
inline ActionCustom::TweenFunc ActionCustomEntity::GetTweenFunc() const
{
return tween_func_;
}
inline void ActionCustomEntity::SetTweenFunc(const ActionCustom::TweenFunc& tween_func)
{
tween_func_ = tween_func;
}
} // namespace kiwano

View File

@ -1,108 +0,0 @@
// 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/render/FrameSequence.h>
#include <kiwano/2d/Sprite.h>
#include <kiwano/2d/action/Animation.h>
namespace kiwano
{
Animation::Animation(Duration dur, FrameSequencePtr frame_seq)
{
SetEntity(MakePtr<AnimationEntity>(dur, frame_seq));
}
AnimationEntity::AnimationEntity()
: frame_seq_(nullptr)
{
}
AnimationEntity::AnimationEntity(Duration dur, FrameSequencePtr frame_seq)
: ActionTweenEntity(dur)
, frame_seq_(frame_seq)
{
}
AnimationEntity::~AnimationEntity() {}
FrameSequencePtr AnimationEntity::GetFrameSequence() const
{
return frame_seq_;
}
void AnimationEntity::SetFrameSequence(FrameSequencePtr frame_seq)
{
frame_seq_ = frame_seq;
}
void AnimationEntity::Init(Actor* target)
{
KGE_ASSERT(frame_seq_ && "AnimationEntity::Init() failed: FrameSequence is NULL!");
if (!frame_seq_ || frame_seq_->GetFrames().empty())
{
Done();
return;
}
auto sprite_target = dynamic_cast<Sprite*>(target);
KGE_ASSERT(sprite_target && "AnimationEntity only supports Sprites!");
if (sprite_target && frame_seq_)
{
sprite_target->SetFrame(frame_seq_->GetFrames()[0]);
}
}
void AnimationEntity::UpdateTween(Actor* target, float percent)
{
auto sprite_target = dynamic_cast<Sprite*>(target);
if (sprite_target && frame_seq_)
{
const auto& frames = frame_seq_->GetFrames();
auto size = frames.size();
auto index = std::min(static_cast<size_t>(math::Floor(size * percent)), size - 1);
sprite_target->SetFrame(frames[index]);
}
}
AnimationEntity* AnimationEntity::Clone() const
{
AnimationEntity* ptr = new AnimationEntity(GetDuration(), frame_seq_);
DoClone(ptr);
return ptr;
}
AnimationEntity* AnimationEntity::Reverse() const
{
AnimationEntity* ptr = new AnimationEntity(GetDuration(), nullptr);
DoClone(ptr);
if (frame_seq_)
{
FrameSequencePtr frames = frame_seq_->Reverse();
ptr->SetFrameSequence(frames);
}
return ptr;
}
} // namespace kiwano

View File

@ -18,9 +18,110 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Actor.h>
#include <kiwano/2d/animation/Animation.h> #include <kiwano/2d/animation/Animation.h>
namespace kiwano namespace kiwano
{ {
Animation::Animation()
: running_(true)
, detach_target_(false)
, loops_done_(0)
, loops_(0)
, status_(Status::NotStarted)
{
} }
Animation::~Animation() {}
void Animation::Init(Actor* target) {}
void Animation::Update(Actor* target, Duration dt)
{
Complete(target);
}
void Animation::UpdateStep(Actor* target, Duration dt)
{
KGE_ASSERT(target != nullptr && "Animation target should NOT be nullptr!");
elapsed_ += dt;
if (status_ == Status::NotStarted)
{
if (delay_.IsZero())
{
status_ = Status::Started;
EmitEvent(target, AnimationEvent::Started);
}
else
{
status_ = Status::Delayed;
}
Init(target);
}
switch (status_)
{
case Status::Delayed:
if (elapsed_ >= delay_)
{
status_ = Status::Started;
EmitEvent(target, AnimationEvent::Started);
}
break;
case Status::Started:
Update(target, dt);
break;
default:
break;
}
if (status_ == Status::Done)
{
EmitEvent(target, AnimationEvent::Done);
if (detach_target_)
target->RemoveFromParent();
status_ = Status::Removeable;
}
}
void Animation::Complete(Actor* target)
{
EmitEvent(target, AnimationEvent::LoopDone);
if (loops_ >= 0 && loops_done_ >= loops_)
{
Done();
}
else
{
Init(target); // reinit when a loop is done
}
++loops_done_;
}
void Animation::Reset()
{
status_ = Status::NotStarted;
elapsed_ = 0;
loops_done_ = 0;
}
void Animation::DoClone(Animation* to) const
{
if (to)
{
to->SetDelay(this->GetDelay());
to->SetHandler(this->GetHandler());
to->SetLoops(this->GetLoops());
to->SetName(this->GetName());
}
}
} // namespace kiwano

View File

@ -20,10 +20,291 @@
#pragma once #pragma once
#include <kiwano/core/Common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/Cloneable.h>
#include <kiwano/base/ObjectBase.h>
#include <kiwano/core/Time.h>
#include <kiwano/core/IntrusiveList.h>
#include <kiwano/math/Math.h>
namespace kiwano namespace kiwano
{ {
class Actor;
class Animator;
KGE_DECLARE_SMART_PTR(Animation);
KGE_DECLARE_SMART_PTR(AnimationEventHandler);
/**
* \~chinese
* \defgroup Animation
*/
/**
* \addtogroup Animation
* @{
*/
/// \~chinese
/// @brief 动画事件
enum class AnimationEvent
{
Started, ///< 动画开始
LoopDone, ///< 动画一次循环结束
Done, ///< 动画结束
Removed, ///< 动画被移除
};
/// \~chinese
/// @brief 动画事件处理器
class KGE_API AnimationEventHandler : public ObjectBase
{
public:
/// \~chinese
/// @brief 处理动画事件
/// @param anim 动画对象
/// @param target 执行动画的对象
/// @param evt 动画事件
virtual void Handle(Animation* anim, Actor* target, AnimationEvent evt) = 0;
};
/// \~chinese
/// @brief 动画列表
typedef IntrusiveList<AnimationPtr> AnimationList;
/// \~chinese
/// @brief 动画
class KGE_API Animation
: public ObjectBase
, public Cloneable<Animation>
, protected IntrusiveListValue<AnimationPtr>
{
friend class Animator;
friend class AnimationGroup;
friend IntrusiveList<AnimationPtr>;
public:
Animation();
virtual ~Animation();
/// \~chinese
/// @brief 继续动画
void Resume();
/// \~chinese
/// @brief 暂停动画
void Pause();
/// \~chinese
/// @brief 停止动画
void Stop();
/// \~chinese
/// @brief 设置动画延时
void SetDelay(Duration delay);
/// \~chinese
/// @brief 设置循环次数
/// @param loops 循环次数,-1 为永久循环
void SetLoops(int loops);
/// \~chinese
/// @brief 动画结束时移除目标角色
void RemoveTargetWhenDone();
/// \~chinese
/// @brief 获取动画的倒转
virtual Animation* Reverse() const = 0;
/// \~chinese
/// @brief 获取动画的运行状态
bool IsRunning() const;
/// \~chinese
/// @brief 获取动画的循环次数
int GetLoops() const;
/// \~chinese
/// @brief 获取动画的延时
Duration GetDelay() const;
/// \~chinese
/// @brief 设置动画事件处理
void SetHandler(AnimationEventHandlerPtr handler);
/// \~chinese
/// @brief 获取动画事件处理
AnimationEventHandlerPtr GetHandler() const;
protected:
/// \~chinese
/// @brief 初始化动画
virtual void Init(Actor* target);
/// \~chinese
/// @brief 更新动画
virtual void Update(Actor* target, Duration dt);
/// \~chinese
/// @brief 更新一个时间步
void UpdateStep(Actor* target, Duration dt);
/// \~chinese
/// @brief 完成动画
void Complete(Actor* target);
/// \~chinese
/// @brief 重置动画
void Reset();
/// \~chinese
/// @brief 动画状态
enum class Status
{
NotStarted, ///< 未开始
Delayed, ///< 等待延时
Started, ///< 已开始
Done, ///< 已结束
Removeable ///< 可移除
};
/// \~chinese
/// @brief 获取动画状态
Status GetStatus() const;
/// \~chinese
/// @brief 获取消逝时间
Duration GetElapsed() const;
/// \~chinese
/// @brief 获取完成的循环次数
int GetLoopsDone() const;
/// \~chinese
/// @brief 结束动画
void Done();
/// \~chinese
/// @brief 是否已结束
bool IsDone() const;
/// \~chinese
/// @brief 是否可移除
bool IsRemoveable() const;
/// \~chinese
/// @brief 发出动画事件
void EmitEvent(Actor* target, AnimationEvent evt);
/// \~chinese
/// @brief 执行克隆
void DoClone(Animation* to) const;
private:
Status status_;
bool running_;
bool detach_target_;
int loops_;
int loops_done_;
Duration delay_;
Duration elapsed_;
AnimationEventHandlerPtr handler_;
};
/** @} */
inline void Animation::Resume()
{
running_ = true;
} }
inline void Animation::Pause()
{
running_ = false;
}
inline void Animation::Stop()
{
Done();
}
inline void Animation::SetDelay(Duration delay)
{
delay_ = delay;
}
inline void Animation::SetLoops(int loops)
{
loops_ = loops;
}
inline void Animation::RemoveTargetWhenDone()
{
detach_target_ = true;
}
inline void Animation::Done()
{
status_ = Status::Done;
}
inline Animation::Status Animation::GetStatus() const
{
return status_;
}
inline bool Animation::IsRunning() const
{
return running_;
}
inline bool Animation::IsDone() const
{
return status_ == Status::Done || status_ == Status::Removeable;
}
inline bool Animation::IsRemoveable() const
{
return status_ == Status::Removeable;
}
inline void Animation::EmitEvent(Actor* target, AnimationEvent evt)
{
if (handler_)
{
handler_->Handle(this, target, evt);
}
}
inline int Animation::GetLoops() const
{
return loops_;
}
inline Duration Animation::GetDelay() const
{
return delay_;
}
inline void Animation::SetHandler(AnimationEventHandlerPtr handler)
{
handler_ = handler;
}
inline AnimationEventHandlerPtr Animation::GetHandler() const
{
return handler_;
}
inline Duration Animation::GetElapsed() const
{
return elapsed_;
}
inline int Animation::GetLoopsDone() const
{
return loops_done_;
}
} // namespace kiwano

View File

@ -18,52 +18,45 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Actor.h> #include <kiwano/2d/animation/AnimationGroup.h>
#include <kiwano/2d/action/ActionGroup.h>
#include <kiwano/utils/Logger.h>
namespace kiwano namespace kiwano
{ {
ActionGroup::ActionGroup(const Vector<ActionEntityPtr>& actions, bool parallel) AnimationGroup::AnimationGroup()
{
SetEntity(MakePtr<ActionGroupEntity>(actions, parallel));
}
ActionGroupEntity::ActionGroupEntity()
: parallel_(false) : parallel_(false)
{ {
} }
ActionGroupEntity::ActionGroupEntity(const Vector<ActionEntityPtr>& actions, bool parallel) AnimationGroup::AnimationGroup(const Vector<AnimationPtr>& animations, bool parallel)
: parallel_(parallel) : parallel_(parallel)
{ {
AddActions(actions); AddAnimation(animations);
} }
ActionGroupEntity::~ActionGroupEntity() {} AnimationGroup::~AnimationGroup() {}
void ActionGroupEntity::Init(Actor* target) void AnimationGroup::Init(Actor* target)
{ {
if (actions_.IsEmpty()) if (animations_.IsEmpty())
{ {
Done(); Done();
return; return;
} }
// reset all actions // reset all animations
for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext()) for (current_ = animations_.GetFirst(); current_; current_ = current_->GetNext())
{ {
current_->Reset(); current_->Reset();
} }
if (!parallel_) if (!parallel_)
{ {
current_ = actions_.GetFirst(); current_ = animations_.GetFirst();
} }
} }
void ActionGroupEntity::Update(Actor* target, Duration dt) void AnimationGroup::Update(Actor* target, Duration dt)
{ {
if (!parallel_) if (!parallel_)
{ {
@ -83,7 +76,7 @@ void ActionGroupEntity::Update(Actor* target, Duration dt)
else else
{ {
bool done = true; bool done = true;
for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext()) for (current_ = animations_.GetFirst(); current_; current_ = current_->GetNext())
{ {
if (!current_->IsDone()) if (!current_->IsDone())
{ {
@ -99,46 +92,46 @@ void ActionGroupEntity::Update(Actor* target, Duration dt)
} }
} }
void ActionGroupEntity::AddAction(ActionEntityPtr action) void AnimationGroup::AddAnimation(AnimationPtr animation)
{ {
if (action) if (animation)
{ {
actions_.PushBack(action); animations_.PushBack(animation);
} }
} }
void ActionGroupEntity::AddActions(const Vector<ActionEntityPtr>& actions) void AnimationGroup::AddAnimation(const Vector<AnimationPtr>& animations)
{ {
for (const auto& action : actions) for (const auto& animation : animations)
AddAction(action); AddAnimation(animation);
} }
ActionGroupEntity* ActionGroupEntity::Clone() const AnimationGroup* AnimationGroup::Clone() const
{ {
Vector<ActionEntityPtr> actions; Vector<AnimationPtr> animations;
if (!actions_.IsEmpty()) if (!animations_.IsEmpty())
{ {
for (auto action = actions_.GetFirst(); action; action = action->GetNext()) for (auto animation = animations_.GetFirst(); animation; animation = animation->GetNext())
{ {
actions.push_back(action->Clone()); animations.push_back(animation->Clone());
} }
} }
ActionGroupEntity* ptr = new ActionGroupEntity(actions, parallel_); AnimationGroup* ptr = new AnimationGroup(animations, parallel_);
DoClone(ptr); DoClone(ptr);
return ptr; return ptr;
} }
ActionGroupEntity* ActionGroupEntity::Reverse() const AnimationGroup* AnimationGroup::Reverse() const
{ {
Vector<ActionEntityPtr> actions; Vector<AnimationPtr> animations;
if (!actions_.IsEmpty()) if (!animations_.IsEmpty())
{ {
for (auto action = actions_.GetLast(); action; action = action->GetPrev()) for (auto animation = animations_.GetLast(); animation; animation = animation->GetPrev())
{ {
actions.push_back(action->Reverse()); animations.push_back(animation->Reverse());
} }
} }
ActionGroupEntity* ptr = new ActionGroupEntity(actions, parallel_); AnimationGroup* ptr = new AnimationGroup(animations, parallel_);
DoClone(ptr); DoClone(ptr);
return ptr; return ptr;
} }

View File

@ -19,65 +19,54 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/2d/action/Action.h> #include <kiwano/2d/animation/Animation.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ActionGroupEntity); KGE_DECLARE_SMART_PTR(AnimationGroup);
/** /**
* \addtogroup Actions * \addtogroup Animation
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 动画组合 /// @brief 动画组合
class KGE_API ActionGroup : public Action class KGE_API AnimationGroup : public Animation
{ {
public: public:
/// \~chinese AnimationGroup();
/// @brief 创建动画组合
/// @param actions 动画集合
/// @param parallel 同步执行
ActionGroup(const Vector<ActionEntityPtr>& actions, bool parallel = false);
};
/// \~chinese
/// @brief 动画组合实体
class KGE_API ActionGroupEntity : public ActionEntity
{
public:
ActionGroupEntity();
/// \~chinese /// \~chinese
/// @brief 创建动画组合 /// @brief 创建动画组合
/// @param actions 动画集合 /// @param animations ¶¯»­¼¯ºÏ
/// @param parallel 同步执行 /// @param parallel 同步执行
ActionGroupEntity(const Vector<ActionEntityPtr>& actions, bool parallel = false); AnimationGroup(const Vector<AnimationPtr>& animations, bool parallel = false);
virtual ~ActionGroupEntity(); virtual ~AnimationGroup();
/// \~chinese /// \~chinese
/// @brief 添加动画 /// @brief 添加动画
/// @param action 动画 /// @param animation ¶¯»­
void AddAction(ActionEntityPtr action); void AddAnimation(AnimationPtr animation);
/// \~chinese /// \~chinese
/// @brief 添加多个动画 /// @brief 添加多个动画
/// @param actions 动画集合 /// @param animations ¶¯»­¼¯ºÏ
void AddActions(const Vector<ActionEntityPtr>& actions); void AddAnimation(const Vector<AnimationPtr>& animations);
/// \~chinese /// \~chinese
/// @brief 获取所有动画 /// @brief 获取所有动画
const ActionList& GetActions() const; const AnimationList& GetAnimations() const;
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
ActionGroupEntity* Clone() const override; AnimationGroup* Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionGroupEntity* Reverse() const override; AnimationGroup* Reverse() const override;
protected: protected:
void Init(Actor* target) override; void Init(Actor* target) override;
@ -86,15 +75,15 @@ protected:
private: private:
bool parallel_; bool parallel_;
ActionEntityPtr current_; AnimationPtr current_;
ActionList actions_; AnimationList animations_;
}; };
/** @} */ /** @} */
inline const ActionList& ActionGroupEntity::GetActions() const inline const AnimationList& AnimationGroup::GetAnimations() const
{ {
return actions_; return animations_;
} }
} // namespace kiwano } // namespace kiwano

View File

@ -0,0 +1,311 @@
// Copyright (c) 2020-2021 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/2d/animation/Animation.h>
#include <kiwano/2d/animation/TweenAnimation.h>
#include <kiwano/2d/animation/PathAnimation.h>
#include <kiwano/2d/animation/DelayAnimation.h>
#include <kiwano/2d/animation/FrameAnimation.h>
#include <kiwano/2d/animation/CustomAnimation.h>
#include <kiwano/2d/animation/AnimationGroup.h>
namespace kiwano
{
/// \~chinese
/// @brief 动画包装器
class KGE_API AnimationWrapper
{
public:
AnimationWrapper() = default;
inline AnimationWrapper(AnimationPtr ptr)
: ptr(ptr)
{
}
/// \~chinese
/// @brief 设置循环次数
inline AnimationWrapper& Loops(int loops)
{
if (ptr)
ptr->SetLoops(loops);
return (*this);
}
/// \~chinese
/// @brief 设置动画延迟
inline AnimationWrapper& Delay(Duration delay)
{
if (ptr)
ptr->SetDelay(delay);
return (*this);
}
/// \~chinese
/// @brief 设置动画结束回调函数
inline AnimationWrapper& Handler(AnimationEventHandlerPtr handler)
{
if (ptr)
ptr->SetHandler(handler);
return (*this);
}
/// \~chinese
/// @brief 动画结束时移除目标角色
inline AnimationWrapper& RemoveTargetWhenDone()
{
if (ptr)
ptr->RemoveTargetWhenDone();
return (*this);
}
/// \~chinese
/// @brief 设置名称
inline AnimationWrapper& Name(const String& name)
{
if (ptr)
ptr->SetName(name);
return (*this);
}
/// \~chinese
/// @brief 设置缓动函数
inline AnimationWrapper& Ease(const EaseFunc& ease)
{
auto tween = dynamic_cast<TweenAnimation*>(ptr.Get());
if (tween)
{
tween->SetEaseFunc(ease);
}
return (*this);
}
/// \~chinese
/// @brief 克隆动画
inline AnimationWrapper Clone() const
{
if (ptr)
return AnimationWrapper(ptr->Clone());
return AnimationWrapper();
}
/// \~chinese
/// @brief 获取反向动画
inline AnimationWrapper Reverse() const
{
if (ptr)
return AnimationWrapper(ptr->Reverse());
return AnimationWrapper();
}
/// \~chinese
/// @brief 获取指针
inline Animation* Get() const
{
return const_cast<Animation*>(ptr.Get());
}
/// \~chinese
/// @brief 设置动画
inline void SetEntity(AnimationPtr ptr)
{
this->ptr = ptr;
}
inline Animation* operator->() const
{
return Get();
}
inline operator Animation*() const
{
return Get();
}
inline operator AnimationPtr() const
{
return ptr;
}
inline operator bool() const
{
return ptr != nullptr;
}
protected:
AnimationPtr ptr;
};
namespace animation
{
/// \~chinese
/// @brief 创建相对位移动画
/// @param duration 动画时长
/// @param displacement 位移向量
inline AnimationWrapper MoveBy(kiwano::Duration duration, const Vec2& displacement)
{
return AnimationWrapper(new MoveByAnimation(duration, displacement));
}
/// \~chinese
/// @brief 创建位移动画
/// @param duration 动画时长
/// @param distination 目的坐标
inline AnimationWrapper MoveTo(kiwano::Duration duration, const Point& distination)
{
return AnimationWrapper(new MoveToAnimation(duration, distination));
}
/// \~chinese
/// @brief 创建相对跳跃动画
/// @param duration 动画时长
/// @param displacement 跳跃位移向量
/// @param height 跳跃高度
/// @param count 跳跃次数
inline AnimationWrapper JumpBy(kiwano::Duration duration, const Vec2& displacement, float height, int count = 1)
{
return AnimationWrapper(new JumpByAnimation(duration, displacement, height, count));
}
/// \~chinese
/// @brief 创建跳跃动画
/// @param duration 动画时长
/// @param distination 目的坐标
/// @param height 跳跃高度
/// @param count 跳跃次数
inline AnimationWrapper JumpTo(kiwano::Duration duration, const Point& distination, float height, int count = 1)
{
return AnimationWrapper(new JumpToAnimation(duration, distination, height, count));
}
/// \~chinese
/// @brief 创建相对缩放动画
/// @param duration 动画时长
/// @param scale 缩放相对变化值
inline AnimationWrapper ScaleBy(kiwano::Duration duration, Vec2 scale)
{
return AnimationWrapper(new ScaleByAnimation(duration, scale));
}
/// \~chinese
/// @brief 创建缩放动画
/// @param duration 动画时长
/// @param scale 缩放目标值
inline AnimationWrapper ScaleTo(kiwano::Duration duration, Vec2 scale)
{
return AnimationWrapper(new ScaleToAnimation(duration, scale));
}
/// \~chinese
/// @brief 创建透明度渐变动画
/// @param duration 动画时长
/// @param opacity 目标透明度
inline AnimationWrapper FadeTo(kiwano::Duration duration, float opacity)
{
return AnimationWrapper(new FadeToAnimation(duration, opacity));
}
/// \~chinese
/// @brief 创建淡入动画
/// @param duration 动画时长
inline AnimationWrapper FadeIn(kiwano::Duration duration)
{
return AnimationWrapper(new FadeToAnimation(duration, 1.0f));
}
/// \~chinese
/// @brief 创建淡出动画
/// @param duration 动画时长
inline AnimationWrapper FadeOut(kiwano::Duration duration)
{
return AnimationWrapper(new FadeToAnimation(duration, 0.0f));
}
/// \~chinese
/// @brief 创建相对旋转动画
/// @param duration 动画时长
/// @param rotation 角度相对变化值
inline AnimationWrapper RotateBy(kiwano::Duration duration, float rotation)
{
return AnimationWrapper(new RotateByAnimation(duration, rotation));
}
/// \~chinese
/// @brief 创建旋转动画
/// @param duration 动画时长
/// @param rotation 目标角度
inline AnimationWrapper RotateTo(kiwano::Duration duration, float rotation)
{
return AnimationWrapper(new RotateToAnimation(duration, rotation));
}
/// \~chinese
/// @brief 创建自定义动画
/// @param duration 动画时长
/// @param tween_func 动画回调函数
inline AnimationWrapper Custom(kiwano::Duration duration, TweenFunc tween_func)
{
return AnimationWrapper(new CustomAnimation(duration, tween_func));
}
/// \~chinese
/// @brief 创建路径行走动画
/// @param duration 持续时长
/// @param path 路径形状
/// @param rotating 是否沿路径切线方向旋转
/// @param start 路径起点(百分比)
/// @param end 路径终点(百分比)
inline AnimationWrapper Path(kiwano::Duration duration, ShapePtr path, bool rotating = false, float start = 0.f,
float end = 1.f)
{
return AnimationWrapper(new PathAnimation(duration, path, rotating, start, end));
}
/// \~chinese
/// @brief 创建延时动画
/// @param delay 延时时长
inline AnimationWrapper Delay(kiwano::Duration delay)
{
return AnimationWrapper(new DelayAnimation(delay));
}
/// \~chinese
/// @brief 创建帧动画
/// @param duration 动画时长
/// @param frame_seq 序列帧
inline AnimationWrapper Frames(kiwano::Duration duration, FrameSequencePtr frame_seq)
{
return AnimationWrapper(new FrameAnimation(duration, frame_seq));
}
/// \~chinese
/// @brief 创建动画组合
/// @param actions 动画集合
/// @param parallel 同步执行
inline AnimationWrapper Group(const Vector<AnimationPtr>& animations, bool parallel = false)
{
return AnimationWrapper(new AnimationGroup(animations, parallel));
}
} // namespace animation
} // namespace kiwano

View File

@ -19,87 +19,87 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/action/ActionScheduler.h> #include <kiwano/2d/animation/Animator.h>
#include <kiwano/utils/Logger.h> #include <kiwano/utils/Logger.h>
namespace kiwano namespace kiwano
{ {
void ActionScheduler::Update(Actor* target, Duration dt) void Animator::Update(Actor* target, Duration dt)
{ {
if (actions_.IsEmpty() || !target) if (animations_.IsEmpty() || !target)
return; return;
ActionEntityPtr next; AnimationPtr next;
for (auto action = actions_.GetFirst(); action; action = next) for (auto animation = animations_.GetFirst(); animation; animation = next)
{ {
next = action->GetNext(); next = animation->GetNext();
if (action->IsRunning()) if (animation->IsRunning())
action->UpdateStep(target, dt); animation->UpdateStep(target, dt);
if (action->IsRemoveable()) if (animation->IsRemoveable())
actions_.Remove(action); animations_.Remove(animation);
} }
} }
ActionEntity* ActionScheduler::AddAction(ActionEntityPtr action) Animation* Animator::AddAnimation(AnimationPtr animation)
{ {
KGE_ASSERT(action && "AddAction failed, NULL pointer exception"); KGE_ASSERT(animation && "AddAnimation failed, NULL pointer exception");
if (action) if (animation)
{ {
actions_.PushBack(action); animations_.PushBack(animation);
} }
return action.Get(); return animation.Get();
} }
void ActionScheduler::ResumeAllActions() void Animator::ResumeAllAnimations()
{ {
if (actions_.IsEmpty()) if (animations_.IsEmpty())
return; return;
for (auto& action : actions_) for (auto& animation : animations_)
{ {
action->Resume(); animation->Resume();
} }
} }
void ActionScheduler::PauseAllActions() void Animator::PauseAllAnimations()
{ {
if (actions_.IsEmpty()) if (animations_.IsEmpty())
return; return;
for (auto& action : actions_) for (auto& animation : animations_)
{ {
action->Pause(); animation->Pause();
} }
} }
void ActionScheduler::StopAllActions() void Animator::StopAllAnimations()
{ {
if (actions_.IsEmpty()) if (animations_.IsEmpty())
return; return;
for (auto& action : actions_) for (auto& animation : animations_)
{ {
action->Stop(); animation->Stop();
} }
} }
ActionEntity* ActionScheduler::GetAction(const String& name) Animation* Animator::GetAnimation(const String& name)
{ {
if (actions_.IsEmpty()) if (animations_.IsEmpty())
return nullptr; return nullptr;
for (auto& action : actions_) for (auto& animation : animations_)
if (action->IsName(name)) if (animation->IsName(name))
return action.Get(); return animation.Get();
return nullptr; return nullptr;
} }
const ActionList& ActionScheduler::GetAllActions() const const AnimationList& Animator::GetAllAnimations() const
{ {
return actions_; return animations_;
} }
} // namespace kiwano } // namespace kiwano

View File

@ -19,13 +19,13 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/2d/action/Action.h> #include <kiwano/2d/animation/Animation.h>
namespace kiwano namespace kiwano
{ {
/** /**
* \addtogroup Actions * \addtogroup Animation
* @{ * @{
*/ */
@ -33,40 +33,47 @@ namespace kiwano
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API ActionScheduler class KGE_API Animator
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 添加动画 /// @brief 添加动画
ActionEntity* AddAction(ActionEntityPtr action); Animation* AddAnimation(AnimationPtr animation);
/// \~chinese
/// @brief ¿ªÊ¼¶¯»­
inline Animation* StartAnimation(AnimationPtr animation)
{
return AddAnimation(animation);
}
/// \~chinese /// \~chinese
/// @brief 继续所有暂停动画 /// @brief 继续所有暂停动画
void ResumeAllActions(); void ResumeAllAnimations();
/// \~chinese /// \~chinese
/// @brief 暂停所有动画 /// @brief 暂停所有动画
void PauseAllActions(); void PauseAllAnimations();
/// \~chinese /// \~chinese
/// @brief 停止所有动画 /// @brief 停止所有动画
void StopAllActions(); void StopAllAnimations();
/// \~chinese /// \~chinese
/// @brief 获取指定名称的动画 /// @brief 获取指定名称的动画
/// @param name 动画名称 /// @param name 动画名称
ActionEntity* GetAction(const String& name); Animation* GetAnimation(const String& name);
/// \~chinese /// \~chinese
/// @brief 获取所有动画 /// @brief 获取所有动画
const ActionList& GetAllActions() const; const AnimationList& GetAllAnimations() const;
/// \~chinese /// \~chinese
/// @brief 更新动画 /// @brief 更新动画
void Update(Actor* target, Duration dt); void Update(Actor* target, Duration dt);
private: private:
ActionList actions_; AnimationList animations_;
}; };
/** @} */ /** @} */

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019-2020 Kiwano - Nomango // Copyright (c) 2016-2018 Kiwano - Nomango
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -18,52 +18,34 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #include <kiwano/2d/animation/CustomAnimation.h>
#include <kiwano/2d/animation/Interpolator.h>
namespace kiwano namespace kiwano
{ {
template <typename _Ty, typename _NotifierTy> CustomAnimation::CustomAnimation(Duration duration, TweenFunc tween_func)
class KeyValue : TweenAnimation(duration)
{ , tween_func_(tween_func)
public:
typedef _Ty value_type;
typedef Value<_Ty, _NotifierTy> property_type;
inline KeyValue(const property_type& prop, value_type end_value)
: end_value_(end_value)
, prop_(prop)
, interpolator_()
{ {
} }
inline KeyValue(const property_type& prop, value_type end_value, const EaseFunc& ease_func) CustomAnimation* CustomAnimation::Clone() const
: end_value_(end_value)
, prop_(prop)
, interpolator_(ease_func)
{ {
CustomAnimation* ptr = new CustomAnimation(GetDuration(), tween_func_);
DoClone(ptr);
return ptr;
} }
inline property_type GetProperty() const void CustomAnimation::Init(Actor* target)
{ {
return prop_; if (!tween_func_)
this->Done();
} }
inline value_type GetEndValue() const void CustomAnimation::UpdateTween(Actor* target, float frac)
{ {
return end_value_; if (tween_func_)
tween_func_(target, frac);
} }
inline const Interpolator& GetInterpolator() const } // namespace kiwano
{
return interpolator_;
}
private:
property_type prop_;
value_type end_value_;
Interpolator interpolator_;
};
}

View File

@ -19,72 +19,75 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/render/FrameSequence.h> #include <kiwano/2d/animation/TweenAnimation.h>
#include <kiwano/2d/action/ActionTween.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(CustomAnimation);
KGE_DECLARE_SMART_PTR(AnimationEntity);
/** /**
* \addtogroup Actions * \addtogroup Animation
* @{ * @{
*/ */
/// \~chinese /// \~chinese
/// @brief 帧动画 /// @brief 补间动画回调函数
class KGE_API Animation : public ActionTween /// @details 在动画更新时回调该函数第一个参数是执行动画的目标第二个参数是动画进度0.0 - 1.0
using TweenFunc = Function<void(Actor* /* target */, float /* frac */)>;
/// \~chinese
/// @brief 自定义动画
class KGE_API CustomAnimation : public TweenAnimation
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 创建帧动画 /// @brief 创建自定义动画
/// @param dur 动画时长 /// @param duration 动画时长
/// @param frame_seq 序列帧 /// @param tween_func 动画回调函数
Animation(Duration dur, FrameSequencePtr frame_seq); CustomAnimation(Duration duration, TweenFunc tween_func);
};
/// \~chinese /// \~chinese
/// @brief 帧动画实体 /// @brief 获取动画回调函数
class KGE_API AnimationEntity : public ActionTweenEntity TweenFunc GetTweenFunc() const;
{
public:
AnimationEntity();
/// \~chinese /// \~chinese
/// @brief 创建帧动画 /// @brief 设置动画回调函数
/// @param dur 动画时长 void SetTweenFunc(const TweenFunc& tween_func);
/// @param frame_seq 序列帧
AnimationEntity(Duration dur, FrameSequencePtr frame_seq);
virtual ~AnimationEntity();
/// \~chinese
/// @brief 获取序列帧
FrameSequencePtr GetFrameSequence() const;
/// \~chinese
/// @brief 设置序列帧
/// @param[in] frame_seq 序列帧
void SetFrameSequence(FrameSequencePtr frame_seq);
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
AnimationEntity* Clone() const override; CustomAnimation* Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
AnimationEntity* Reverse() const override; CustomAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in CustomAnimation");
return nullptr;
}
protected: protected:
void Init(Actor* target) override; void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override; void UpdateTween(Actor* target, float frac) override;
private: private:
FrameSequencePtr frame_seq_; TweenFunc tween_func_;
}; };
/** @} */ /** @} */
inline TweenFunc CustomAnimation::GetTweenFunc() const
{
return tween_func_;
}
inline void CustomAnimation::SetTweenFunc(const TweenFunc& tween_func)
{
tween_func_ = tween_func;
}
} // namespace kiwano } // namespace kiwano

View File

@ -18,29 +18,24 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/action/ActionDelay.h> #include <kiwano/2d/animation/DelayAnimation.h>
namespace kiwano namespace kiwano
{ {
ActionDelay::ActionDelay(Duration delay) DelayAnimation::DelayAnimation(Duration delay)
{
SetEntity(MakePtr<ActionDelayEntity>(delay));
}
ActionDelayEntity::ActionDelayEntity(Duration delay)
{ {
this->SetDelay(delay); this->SetDelay(delay);
} }
ActionDelayEntity* ActionDelayEntity::Clone() const DelayAnimation* DelayAnimation::Clone() const
{ {
ActionDelayEntity* ptr = new ActionDelayEntity(GetDelay()); DelayAnimation* ptr = new DelayAnimation(GetDelay());
DoClone(ptr); DoClone(ptr);
return ptr; return ptr;
} }
ActionDelayEntity* ActionDelayEntity::Reverse() const DelayAnimation* DelayAnimation::Reverse() const
{ {
return Clone(); return Clone();
} }

View File

@ -19,46 +19,36 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/2d/action/Action.h> #include <kiwano/2d/animation/Animation.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ActionDelayEntity); KGE_DECLARE_SMART_PTR(DelayAnimation);
/** /**
* \addtogroup Actions * \addtogroup Animation
* @{ * @{
*/ */
/// \~chinese
/// @brief 延时动画
class KGE_API ActionDelay : public Action
{
public:
/// \~chinese
/// @brief 创建延时动画
/// @param delay 延时时长
ActionDelay(Duration delay);
};
/// \~chinese /// \~chinese
/// @brief 延时动画实体 /// @brief 延时动画
class KGE_API ActionDelayEntity : public ActionEntity class KGE_API DelayAnimation : public Animation
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 创建延时动画 /// @brief 创建延时动画
/// @param delay 延时时长 /// @param delay 延时时长
ActionDelayEntity(Duration delay); DelayAnimation(Duration delay);
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
ActionDelayEntity* Clone() const override; DelayAnimation* Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionDelayEntity* Reverse() const override; DelayAnimation* Reverse() const override;
}; };
/** @} */ /** @} */

View File

@ -18,9 +18,90 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/animation/Animation.h> #include <kiwano/2d/animation/FrameAnimation.h>
#include <kiwano/2d/Sprite.h>
namespace kiwano namespace kiwano
{ {
FrameAnimation::FrameAnimation()
: frame_seq_(nullptr)
{
} }
FrameAnimation::FrameAnimation(Duration dur, FrameSequencePtr frame_seq)
: TweenAnimation(dur)
, frame_seq_(frame_seq)
{
}
FrameAnimation::~FrameAnimation() {}
FrameSequencePtr FrameAnimation::GetFrameSequence() const
{
return frame_seq_;
}
void FrameAnimation::SetFrameSequence(FrameSequencePtr frame_seq)
{
frame_seq_ = frame_seq;
}
void FrameAnimation::Init(Actor* target)
{
KGE_ASSERT(frame_seq_ && "FrameAnimation::Init() failed: FrameSequence is NULL!");
if (!frame_seq_ || frame_seq_->GetFrames().empty())
{
Done();
return;
}
auto sprite_target = dynamic_cast<Sprite*>(target);
KGE_ASSERT(sprite_target && "FrameAnimation only supports Sprites!");
if (sprite_target && frame_seq_)
{
sprite_target->SetKeyFrame(frame_seq_->GetFrames()[0]);
current_index_ = 0;
}
}
void FrameAnimation::UpdateTween(Actor* target, float percent)
{
auto sprite_target = dynamic_cast<Sprite*>(target);
if (sprite_target && frame_seq_)
{
const auto& frames = frame_seq_->GetFrames();
auto size = frames.size();
auto index = std::min(static_cast<size_t>(math::Floor(size * percent)), size - 1);
if (index != current_index_)
{
current_index_ = index;
sprite_target->SetKeyFrame(frames[index]);
}
}
}
FrameAnimation* FrameAnimation::Clone() const
{
FrameAnimation* ptr = new FrameAnimation(GetDuration(), frame_seq_);
DoClone(ptr);
return ptr;
}
FrameAnimation* FrameAnimation::Reverse() const
{
FrameAnimation* ptr = new FrameAnimation(GetDuration(), nullptr);
DoClone(ptr);
if (frame_seq_)
{
FrameSequencePtr frames = frame_seq_->Reverse();
ptr->SetFrameSequence(frames);
}
return ptr;
}
} // namespace kiwano

View File

@ -19,11 +19,61 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/Common.h> #include <kiwano/2d/animation/TweenAnimation.h>
#include <kiwano/2d/animation/FrameSequence.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(FrameAnimation);
/**
* \addtogroup Animation
* @{
*/
} /// \~chinese
/// @brief 帧动画
class KGE_API FrameAnimation : public TweenAnimation
{
public:
FrameAnimation();
/// \~chinese
/// @brief 创建帧动画
/// @param dur 动画时长
/// @param frame_seq 序列帧
FrameAnimation(Duration dur, FrameSequencePtr frame_seq);
virtual ~FrameAnimation();
/// \~chinese
/// @brief 获取序列帧
FrameSequencePtr GetFrameSequence() const;
/// \~chinese
/// @brief 设置序列帧
/// @param[in] frame_seq 序列帧
void SetFrameSequence(FrameSequencePtr frame_seq);
/// \~chinese
/// @brief 获取该动画的拷贝对象
FrameAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
FrameAnimation* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float percent) override;
private:
size_t current_index_;
FrameSequencePtr frame_seq_;
};
/** @} */
} // namespace kiwano

View File

@ -18,28 +18,22 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/render/FrameSequence.h> #include <kiwano/2d/animation/FrameSequence.h>
#include <kiwano/utils/Logger.h> #include <kiwano/utils/Logger.h>
namespace kiwano namespace kiwano
{ {
FrameSequence::FrameSequence(const Vector<FramePtr>& frames)
{
AddFrames(frames);
}
FrameSequence::FrameSequence(FramePtr frame, int cols, int rows, int max_num, float padding_x,
float padding_y)
{
AddFrames(frame, cols, rows, max_num, padding_x, padding_y);
}
FrameSequence::FrameSequence() {} FrameSequence::FrameSequence() {}
FrameSequence::~FrameSequence() {} FrameSequence::~FrameSequence() {}
void FrameSequence::AddFrame(FramePtr frame) FrameSequence::FrameSequence(const Vector<KeyFramePtr>& frames)
{
AddFrames(frames);
}
void FrameSequence::AddFrame(KeyFramePtr frame)
{ {
if (frame) if (frame)
{ {
@ -51,7 +45,7 @@ void FrameSequence::AddFrame(FramePtr frame)
} }
} }
void FrameSequence::AddFrames(const Vector<FramePtr>& frames) void FrameSequence::AddFrames(const Vector<KeyFramePtr>& frames)
{ {
if (frames_.empty()) if (frames_.empty())
frames_ = frames; frames_ = frames;
@ -63,58 +57,13 @@ void FrameSequence::AddFrames(const Vector<FramePtr>& frames)
} }
} }
void FrameSequence::AddFrames(FramePtr frame, int cols, int rows, int max_num, float padding_x, float padding_y) KeyFramePtr FrameSequence::GetFrame(size_t index) const
{
if (cols <= 0 || rows <= 0 || max_num == 0)
return;
if (!frame)
return;
Rect src_rect = frame->GetCropRect();
float raw_width = src_rect.GetWidth();
float raw_height = src_rect.GetHeight();
float width = (raw_width - (cols - 1) * padding_x) / cols;
float height = (raw_height - (rows - 1) * padding_y) / rows;
Vector<FramePtr> frames;
frames.reserve((max_num > 0) ? max_num : (rows * cols));
int current_num = 0;
float dty = src_rect.GetTop();
for (int i = 0; i < rows; i++)
{
float dtx = src_rect.GetLeft();
for (int j = 0; j < cols; j++)
{
FramePtr ptr = MakePtr<Frame>();
if (ptr)
{
ptr->SetTexture(frame->GetTexture());
ptr->SetCropRect(Rect{ dtx, dty, dtx + width, dty + height });
frames.push_back(ptr);
++current_num;
}
dtx += (width + padding_x);
}
dty += (height + padding_y);
if (max_num > 0 && current_num == max_num)
break;
}
AddFrames(frames);
}
FramePtr FrameSequence::GetFrame(size_t index) const
{ {
KGE_ASSERT(index < frames_.size()); KGE_ASSERT(index < frames_.size());
return frames_[index]; return frames_[index];
} }
const Vector<FramePtr>& FrameSequence::GetFrames() const const Vector<KeyFramePtr>& FrameSequence::GetFrames() const
{ {
return frames_; return frames_;
} }
@ -147,4 +96,62 @@ FrameSequencePtr FrameSequence::Reverse() const
return frame_seq; return frame_seq;
} }
KeyFrameSpliter::KeyFrameSpliter(TexturePtr texture)
: texture(texture)
{
if (texture)
{
crop_rect = Rect(Point(), texture->GetSize());
}
}
KeyFrameSpliter::KeyFrameSpliter(TexturePtr texture, const Rect& crop_rect)
: texture(texture)
, crop_rect(crop_rect)
{
}
Vector<KeyFramePtr> KeyFrameSpliter::Split(int cols, int rows, int max_num, float padding_x, float padding_y)
{
if (cols <= 0 || rows <= 0 || max_num == 0)
return {};
if (!texture)
return {};
float raw_width = crop_rect.GetWidth();
float raw_height = crop_rect.GetHeight();
float width = (raw_width - (cols - 1) * padding_x) / cols;
float height = (raw_height - (rows - 1) * padding_y) / rows;
Vector<KeyFramePtr> frames;
frames.reserve((max_num > 0) ? max_num : (rows * cols));
int current_num = 0;
float dty = crop_rect.GetTop();
for (int i = 0; i < rows; i++)
{
float dtx = crop_rect.GetLeft();
for (int j = 0; j < cols; j++)
{
KeyFramePtr ptr = MakePtr<KeyFrame>();
if (ptr)
{
ptr->SetTexture(texture);
ptr->SetCropRect(Rect{ dtx, dty, dtx + width, dty + height });
frames.push_back(ptr);
++current_num;
}
dtx += (width + padding_x);
}
dty += (height + padding_y);
if (max_num > 0 && current_num == max_num)
break;
}
return frames;
}
} // namespace kiwano } // namespace kiwano

View File

@ -19,7 +19,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/render/Frame.h> #include <kiwano/2d/animation/KeyFrame.h>
#include <kiwano/core/Common.h> #include <kiwano/core/Common.h>
#include <kiwano/core/Time.h> #include <kiwano/core/Time.h>
@ -36,19 +36,8 @@ class KGE_API FrameSequence : public ObjectBase
public: public:
/// \~chinese /// \~chinese
/// @brief 创建序列帧 /// @brief 创建序列帧
/// @param frames 图像帧集合 /// @param frames 关键帧集合
FrameSequence(const Vector<FramePtr>& frames); FrameSequence(const Vector<KeyFramePtr>& frames);
/// \~chinese
/// @brief 按行列分割图像并创建序列帧
/// @param frame 图像帧
/// @param cols 列数
/// @param rows 行数
/// @param max_num 最大帧数量,设-1为将分割后的图像全部作为序列帧
/// @param padding_x X方向间隔
/// @param padding_y Y方向间隔
FrameSequence(FramePtr frame, int cols, int rows = 1, int max_num = -1, float padding_x = 0,
float padding_y = 0);
/// \~chinese /// \~chinese
/// @brief 构建空序列帧 /// @brief 构建空序列帧
@ -58,32 +47,22 @@ public:
/// \~chinese /// \~chinese
/// @brief 添加关键帧 /// @brief 添加关键帧
/// @param frame 图像 /// @param frame 关键
void AddFrame(FramePtr frame); void AddFrame(KeyFramePtr frame);
/// \~chinese /// \~chinese
/// @brief 添加多个关键帧 /// @brief 添加多个关键帧
/// @param frames 图像帧集合 /// @param frames 关键帧集合
void AddFrames(const Vector<FramePtr>& frames); void AddFrames(const Vector<KeyFramePtr>& frames);
/// \~chinese
/// @brief 按行列分割图像并添加序列帧
/// @param frame 图像帧
/// @param cols 列数
/// @param rows 行数
/// @param max_num 最大帧数量,设-1为将分割后的图像全部作为序列帧
/// @param padding_x X方向间隔
/// @param padding_y Y方向间隔
void AddFrames(FramePtr frame, int cols, int rows = 1, int max_num = -1, float padding_x = 0, float padding_y = 0);
/// \~chinese /// \~chinese
/// @brief 获取关键帧 /// @brief 获取关键帧
/// @param index 图像帧下标 /// @param index 关键帧下标
FramePtr GetFrame(size_t index) const; KeyFramePtr GetFrame(size_t index) const;
/// \~chinese /// \~chinese
/// @brief 获取所有关键帧 /// @brief 获取所有关键帧
const Vector<FramePtr>& GetFrames() const; const Vector<KeyFramePtr>& GetFrames() const;
/// \~chinese /// \~chinese
/// @brief 获取关键帧数量 /// @brief 获取关键帧数量
@ -98,6 +77,37 @@ public:
FrameSequencePtr Reverse() const; FrameSequencePtr Reverse() const;
private: private:
Vector<FramePtr> frames_; Vector<KeyFramePtr> frames_;
}; };
/// \~chinese
/// @brief 序列帧图像分割器
struct KGE_API KeyFrameSpliter
{
TexturePtr texture;
Rect crop_rect;
KeyFrameSpliter() = default;
/// \~chinese
/// @brief 创建序列帧图像分割器
/// @param texture 图像
KeyFrameSpliter(TexturePtr texture);
/// \~chinese
/// @brief 创建序列帧图像分割器
/// @param texture 图像
/// @param crop_rect 裁剪矩形
KeyFrameSpliter(TexturePtr texture, const Rect& crop_rect);
/// \~chinese
/// @brief 按行列分割图像并创建序列帧
/// @param cols 列数
/// @param rows 行数
/// @param max_num 最大帧数量,设-1为将分割后的图像全部作为序列帧
/// @param padding_x X方向间隔
/// @param padding_y Y方向间隔
Vector<KeyFramePtr> Split(int cols, int rows = 1, int max_num = -1, float padding_x = 0, float padding_y = 0);
};
} // namespace kiwano } // namespace kiwano

View File

@ -1,78 +0,0 @@
// Copyright (c) 2019-2020 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/Common.h>
#include <kiwano/math/Math.h>
#include <kiwano/2d/animation/EaseFunc.h>
namespace kiwano
{
#define KGE_INTERPOLATOR_NUMRIC_INTERPOLATE_IMPL(TYPE) \
inline TYPE Interpolate(TYPE start, TYPE end, float frac) \
{ \
return NumricInterpolate(start, end, Fraction(frac)); \
}
class KGE_API Interpolator
{
public:
inline Interpolator() {}
inline Interpolator(const EaseFunc& ease_func)
: ease_func_(ease_func)
{
}
KGE_INTERPOLATOR_NUMRIC_INTERPOLATE_IMPL(int)
KGE_INTERPOLATOR_NUMRIC_INTERPOLATE_IMPL(unsigned)
KGE_INTERPOLATOR_NUMRIC_INTERPOLATE_IMPL(float)
KGE_INTERPOLATOR_NUMRIC_INTERPOLATE_IMPL(double)
template <typename _Ty>
inline _Ty Interpolate(_Ty start, _Ty end, float frac)
{
if (NumricInterpolate(0, 1, Fraction(frac)) == 1)
return end;
return start;
}
private:
inline float Fraction(float frac)
{
if (ease_func_)
{
return ease_func_(frac);
}
return frac;
}
template <typename _Ty>
inline _Ty NumricInterpolate(_Ty start, _Ty end, float frac)
{
return start + static_cast<_Ty>(math::Floor(static_cast<float>(end - start) * frac));
}
private:
EaseFunc ease_func_;
};
}

View File

@ -18,29 +18,47 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/render/Frame.h> #include <kiwano/2d/animation/KeyFrame.h>
namespace kiwano namespace kiwano
{ {
Frame::Frame(const String& file_path) KeyFrame::KeyFrame() {}
KeyFrame::KeyFrame(const String& file_path)
{ {
Load(file_path); Load(file_path);
} }
Frame::Frame(const Resource& res) KeyFrame::KeyFrame(const Resource& res)
{ {
Load(res); Load(res);
} }
Frame::Frame(TexturePtr texture) KeyFrame::KeyFrame(TexturePtr texture)
{ {
SetTexture(texture); SetTexture(texture);
} }
Frame::Frame() {} KeyFrame::KeyFrame(const String& file_path, const Rect& crop_rect)
: KeyFrame(file_path)
{
SetCropRect(crop_rect);
}
bool Frame::Load(const String& file_path) KeyFrame::KeyFrame(const Resource& res, const Rect& crop_rect)
: KeyFrame(res)
{
SetCropRect(crop_rect);
}
KeyFrame::KeyFrame(TexturePtr texture, const Rect& crop_rect)
: KeyFrame(texture)
{
SetCropRect(crop_rect);
}
bool KeyFrame::Load(const String& file_path)
{ {
TexturePtr texture = Texture::Preload(file_path); TexturePtr texture = Texture::Preload(file_path);
if (texture->IsValid()) if (texture->IsValid())
@ -51,7 +69,7 @@ bool Frame::Load(const String& file_path)
return false; return false;
} }
bool Frame::Load(const Resource& res) bool KeyFrame::Load(const Resource& res)
{ {
TexturePtr texture = Texture::Preload(res); TexturePtr texture = Texture::Preload(res);
if (texture->IsValid()) if (texture->IsValid())
@ -62,7 +80,7 @@ bool Frame::Load(const Resource& res)
return false; return false;
} }
void Frame::SetCropRect(const Rect& crop_rect) void KeyFrame::SetCropRect(const Rect& crop_rect)
{ {
if (texture_->IsValid()) if (texture_->IsValid())
{ {
@ -74,7 +92,7 @@ void Frame::SetCropRect(const Rect& crop_rect)
} }
} }
void Frame::SetTexture(TexturePtr texture) void KeyFrame::SetTexture(TexturePtr texture)
{ {
texture_ = texture; texture_ = texture;
if (texture_->IsValid()) if (texture_->IsValid())

View File

@ -19,38 +19,53 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/base/ObjectBase.h>
#include <kiwano/render/Texture.h> #include <kiwano/render/Texture.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(Frame); KGE_DECLARE_SMART_PTR(KeyFrame);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API Frame : public ObjectBase class KGE_API KeyFrame : public ObjectBase
{ {
public: public:
KeyFrame();
/// \~chinese /// \~chinese
/// @brief 创建图像帧 /// @brief 创建关键
/// @param file_path 图像路径 /// @param file_path 图像路径
Frame(const String& file_path); KeyFrame(const String& file_path);
/// \~chinese /// \~chinese
/// @brief 创建图像 /// @brief 创建关键
/// @param res 图像资源 /// @param res 图像资源
Frame(const Resource& res); KeyFrame(const Resource& res);
/// \~chinese /// \~chinese
/// @brief 创建图像 /// @brief 创建关键
/// @param texture 纹理 /// @param texture 纹理
Frame(TexturePtr texture); KeyFrame(TexturePtr texture);
/// \~chinese /// \~chinese
/// @brief 构建空图像帧 /// @brief 创建关键帧
Frame(); /// @param file_path 图像路径
/// @param crop_rect 裁剪矩形
KeyFrame(const String& file_path, const Rect& crop_rect);
/// \~chinese
/// @brief 创建关键帧
/// @param res 图像资源
/// @param crop_rect 裁剪矩形
KeyFrame(const Resource& res, const Rect& crop_rect);
/// \~chinese
/// @brief 创建关键帧
/// @param texture 纹理
/// @param crop_rect 裁剪矩形
KeyFrame(TexturePtr texture, const Rect& crop_rect);
/// \~chinese /// \~chinese
/// @brief 加载图像 /// @brief 加载图像
@ -63,8 +78,12 @@ public:
bool Load(const Resource& res); bool Load(const Resource& res);
/// \~chinese /// \~chinese
/// @brief 裁剪图像帧为矩形 /// @brief 是否有效
/// @param crop_rect 裁剪矩形定义 bool IsValid() const;
/// \~chinese
/// @brief 裁剪关键帧为矩形
/// @param crop_rect 裁剪矩形
void SetCropRect(const Rect& crop_rect); void SetCropRect(const Rect& crop_rect);
/// \~chinese /// \~chinese
@ -72,42 +91,10 @@ public:
/// @param texture 纹理 /// @param texture 纹理
void SetTexture(TexturePtr texture); void SetTexture(TexturePtr texture);
/// \~chinese
/// @brief 是否有效
bool IsValid() const;
/// \~chinese
/// @brief 获取宽度
float GetWidth() const;
/// \~chinese
/// @brief 获取高度
float GetHeight() const;
/// \~chinese
/// @brief 获取大小
Size GetSize() const;
/// \~chinese
/// @brief 获取裁剪位置
Point GetCropPoint() const;
/// \~chinese /// \~chinese
/// @brief 获取裁剪矩形 /// @brief 获取裁剪矩形
const Rect& GetCropRect() const; const Rect& GetCropRect() const;
/// \~chinese
/// @brief 获取图像原宽度
float GetSourceWidth() const;
/// \~chinese
/// @brief 获取图像原高度
float GetSourceHeight() const;
/// \~chinese
/// @brief 获取图像原大小
Size GetSourceSize() const;
/// \~chinese /// \~chinese
/// @brief 获取纹理 /// @brief 获取纹理
TexturePtr GetTexture() const; TexturePtr GetTexture() const;
@ -117,64 +104,17 @@ private:
Rect crop_rect_; Rect crop_rect_;
}; };
inline bool Frame::IsValid() const inline bool KeyFrame::IsValid() const
{ {
return texture_ && texture_->IsValid(); return texture_ && texture_->IsValid();
} }
inline float Frame::GetWidth() const inline const Rect& KeyFrame::GetCropRect() const
{
return crop_rect_.GetWidth();
}
inline float Frame::GetHeight() const
{
return crop_rect_.GetHeight();
}
inline Size Frame::GetSize() const
{
return crop_rect_.GetSize();
}
inline Point Frame::GetCropPoint() const
{
return crop_rect_.GetLeftTop();
}
inline const Rect& Frame::GetCropRect() const
{ {
return crop_rect_; return crop_rect_;
} }
inline float Frame::GetSourceWidth() const inline TexturePtr KeyFrame::GetTexture() const
{
if (texture_)
{
return texture_->GetWidth();
}
return 0.0f;
}
inline float Frame::GetSourceHeight() const
{
if (texture_)
{
return texture_->GetHeight();
}
return 0.0f;
}
inline Size Frame::GetSourceSize() const
{
if (texture_)
{
return texture_->GetSize();
}
return Size();
}
inline TexturePtr Frame::GetTexture() const
{ {
return texture_; return texture_;
} }

View File

@ -18,19 +18,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/animation/PathAnimation.h>
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/action/ActionWalk.h>
namespace kiwano namespace kiwano
{ {
ActionWalk::ActionWalk(Duration duration, ShapePtr path, bool rotating, float start, float end) PathAnimation::PathAnimation(Duration duration, ShapePtr path, bool rotating, float start, float end)
{ : TweenAnimation(duration)
SetEntity(MakePtr<ActionWalkEntity>(duration, path, rotating, start, end));
}
ActionWalkEntity::ActionWalkEntity(Duration duration, ShapePtr path, bool rotating, float start, float end)
: ActionTweenEntity(duration)
, start_(start) , start_(start)
, end_(end) , end_(end)
, rotating_(rotating) , rotating_(rotating)
@ -39,21 +34,21 @@ ActionWalkEntity::ActionWalkEntity(Duration duration, ShapePtr path, bool rotati
{ {
} }
ActionWalkEntity* ActionWalkEntity::Clone() const PathAnimation* PathAnimation::Clone() const
{ {
ActionWalkEntity* ptr = new ActionWalkEntity(GetDuration(), path_, rotating_, start_, end_); PathAnimation* ptr = new PathAnimation(GetDuration(), path_, rotating_, start_, end_);
DoClone(ptr); DoClone(ptr);
return ptr; return ptr;
} }
ActionWalkEntity* ActionWalkEntity::Reverse() const PathAnimation* PathAnimation::Reverse() const
{ {
ActionWalkEntity* ptr = new ActionWalkEntity(GetDuration(), path_, rotating_, end_, start_); PathAnimation* ptr = new PathAnimation(GetDuration(), path_, rotating_, end_, start_);
DoClone(ptr); DoClone(ptr);
return ptr; return ptr;
} }
void ActionWalkEntity::Init(Actor* target) void PathAnimation::Init(Actor* target)
{ {
if (!path_ || !path_->IsValid()) if (!path_ || !path_->IsValid())
{ {
@ -65,7 +60,7 @@ void ActionWalkEntity::Init(Actor* target)
length_ = path_->GetLength(); length_ = path_->GetLength();
} }
void ActionWalkEntity::UpdateTween(Actor* target, float percent) void PathAnimation::UpdateTween(Actor* target, float percent)
{ {
float distance = length_ * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f); float distance = length_ * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f);

View File

@ -19,37 +19,22 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/2d/action/ActionTween.h> #include <kiwano/2d/animation/TweenAnimation.h>
#include <kiwano/render/Shape.h> #include <kiwano/render/Shape.h>
#include <kiwano/render/ShapeMaker.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(ActionWalkEntity); KGE_DECLARE_SMART_PTR(PathAnimation);
/** /**
* \addtogroup Actions * \addtogroup Animation
* @{ * @{
*/ */
/// \~chinese
/// @brief 路径行走动画
class KGE_API ActionWalk : public ActionTween
{
public:
/// \~chinese
/// @brief 创建路径行走动画
/// @param duration 持续时长
/// @param path 路径形状
/// @param rotating 是否沿路径切线方向旋转
/// @param start 路径起点(百分比)
/// @param end 路径终点(百分比)
ActionWalk(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f, float end = 1.f);
};
/// \~chinese /// \~chinese
/// @brief 路径行走动画实体 /// @brief ·¾¶ÐÐ×ß¶¯»­
class KGE_API ActionWalkEntity : public ActionTweenEntity class KGE_API PathAnimation : public TweenAnimation
{ {
public: public:
/// \~chinese /// \~chinese
@ -59,7 +44,7 @@ public:
/// @param rotating 是否沿路径切线方向旋转 /// @param rotating 是否沿路径切线方向旋转
/// @param start 路径起点(百分比) /// @param start 路径起点(百分比)
/// @param end 路径终点(百分比) /// @param end 路径终点(百分比)
ActionWalkEntity(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f, float end = 1.f); PathAnimation(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f, float end = 1.f);
/// \~chinese /// \~chinese
/// @brief 获取路线 /// @brief 获取路线
@ -95,11 +80,11 @@ public:
/// \~chinese /// \~chinese
/// @brief 获取该动画的拷贝对象 /// @brief 获取该动画的拷贝对象
ActionWalkEntity* Clone() const override; PathAnimation* Clone() const override;
/// \~chinese /// \~chinese
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionWalkEntity* Reverse() const override; PathAnimation* Reverse() const override;
protected: protected:
void Init(Actor* target) override; void Init(Actor* target) override;
@ -117,42 +102,42 @@ private:
/** @} */ /** @} */
inline ShapePtr ActionWalkEntity::GetPath() const inline ShapePtr PathAnimation::GetPath() const
{ {
return path_; return path_;
} }
inline bool ActionWalkEntity::IsRotating() const inline bool PathAnimation::IsRotating() const
{ {
return rotating_; return rotating_;
} }
inline float ActionWalkEntity::GetStartValue() const inline float PathAnimation::GetStartValue() const
{ {
return start_; return start_;
} }
inline float ActionWalkEntity::GetEndValue() const inline float PathAnimation::GetEndValue() const
{ {
return end_; return end_;
} }
inline void ActionWalkEntity::SetPath(ShapePtr path) inline void PathAnimation::SetPath(ShapePtr path)
{ {
path_ = path; path_ = path;
} }
inline void ActionWalkEntity::SetRotating(bool rotating) inline void PathAnimation::SetRotating(bool rotating)
{ {
rotating_ = rotating; rotating_ = rotating;
} }
inline void ActionWalkEntity::SetStartValue(float start) inline void PathAnimation::SetStartValue(float start)
{ {
start_ = start; start_ = start;
} }
inline void ActionWalkEntity::SetEndValue(float end) inline void PathAnimation::SetEndValue(float end)
{ {
end_ = end; end_ = end;
} }

View File

@ -18,9 +18,352 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include <kiwano/2d/animation/Animation.h> #include <kiwano/2d/Actor.h>
#include <kiwano/2d/animation/TweenAnimation.h>
namespace kiwano namespace kiwano
{ {
//-------------------------------------------------------
// TweenAnimation
//-------------------------------------------------------
TweenAnimation::TweenAnimation()
: dur_()
, ease_func_(nullptr)
{
} }
TweenAnimation::TweenAnimation(Duration duration)
: dur_(duration)
, ease_func_(nullptr)
{
}
float TweenAnimation::Interpolate(float frac)
{
if (ease_func_)
frac = ease_func_(frac);
return frac;
}
void TweenAnimation::Update(Actor* target, Duration dt)
{
float frac;
if (dur_.IsZero())
{
frac = 1.f;
Complete(target);
}
else
{
Duration elapsed = GetElapsed() - GetDelay();
float loops_done = elapsed / dur_;
while (GetLoopsDone() < static_cast<int>(loops_done))
{
Complete(target); // loops_done_++
}
frac = (GetStatus() == Status::Done) ? 1.f : (loops_done - static_cast<float>(GetLoopsDone()));
}
frac = Interpolate(frac);
UpdateTween(target, frac);
}
void TweenAnimation::DoClone(TweenAnimation* to) const
{
if (to)
{
Animation::DoClone(to);
to->SetDuration(this->GetDuration());
to->SetEaseFunc(this->GetEaseFunc());
}
}
//-------------------------------------------------------
// Move Animation
//-------------------------------------------------------
MoveByAnimation::MoveByAnimation(Duration duration, const Vec2& displacement)
: TweenAnimation(duration)
, displacement_(displacement)
{
}
void MoveByAnimation::Init(Actor* target)
{
if (target)
{
prev_pos_ = start_pos_ = target->GetPosition();
}
}
void MoveByAnimation::UpdateTween(Actor* target, float frac)
{
Point diff = target->GetPosition() - prev_pos_;
start_pos_ = start_pos_ + diff;
Point new_pos = start_pos_ + (displacement_ * frac);
target->SetPosition(new_pos);
prev_pos_ = new_pos;
}
MoveByAnimation* MoveByAnimation::Clone() const
{
MoveByAnimation* ptr = new MoveByAnimation(GetDuration(), displacement_);
DoClone(ptr);
return ptr;
}
MoveByAnimation* MoveByAnimation::Reverse() const
{
MoveByAnimation* ptr = new MoveByAnimation(GetDuration(), -displacement_);
DoClone(ptr);
return ptr;
}
MoveToAnimation::MoveToAnimation(Duration duration, const Point& distination)
: MoveByAnimation(duration, Vec2())
, distination_(distination)
{
}
MoveToAnimation* MoveToAnimation::Clone() const
{
MoveToAnimation* ptr = new MoveToAnimation(GetDuration(), distination_);
DoClone(ptr);
return ptr;
}
void MoveToAnimation::Init(Actor* target)
{
MoveByAnimation::Init(target);
displacement_ = distination_ - start_pos_;
}
//-------------------------------------------------------
// Jump Animation
//-------------------------------------------------------
JumpByAnimation::JumpByAnimation(Duration duration, const Vec2& displacement, float height, int count)
: TweenAnimation(duration)
, height_(height)
, jump_count_(count)
, displacement_(displacement)
{
}
JumpByAnimation* JumpByAnimation::Clone() const
{
JumpByAnimation* ptr = new JumpByAnimation(GetDuration(), displacement_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
JumpByAnimation* JumpByAnimation::Reverse() const
{
JumpByAnimation* ptr = new JumpByAnimation(GetDuration(), -displacement_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
void JumpByAnimation::Init(Actor* target)
{
if (target)
{
prev_pos_ = start_pos_ = target->GetPosition();
}
}
void JumpByAnimation::UpdateTween(Actor* target, float frac)
{
float f = ::fmod(frac * jump_count_, 1.f);
float x = displacement_.x * frac;
float y = height_ * 4 * f * (1 - f);
y += displacement_.y * frac;
Point diff = target->GetPosition() - prev_pos_;
start_pos_ = diff + start_pos_;
Point new_pos = start_pos_ + Point(x, y);
target->SetPosition(new_pos);
prev_pos_ = new_pos;
}
JumpToAnimation::JumpToAnimation(Duration duration, const Point& distination, float height, int count)
: JumpByAnimation(duration, Vec2(), height, count)
, distination_(distination)
{
}
JumpToAnimation* JumpToAnimation::Clone() const
{
JumpToAnimation* ptr = new JumpToAnimation(GetDuration(), distination_, height_, jump_count_);
DoClone(ptr);
return ptr;
}
void JumpToAnimation::Init(Actor* target)
{
JumpByAnimation::Init(target);
displacement_ = distination_ - start_pos_;
}
//-------------------------------------------------------
// Scale Animation
//-------------------------------------------------------
ScaleByAnimation::ScaleByAnimation(Duration duration, const Vec2& scale)
: TweenAnimation(duration)
, delta_(scale)
, start_val_()
{
}
void ScaleByAnimation::Init(Actor* target)
{
if (target)
{
start_val_ = target->GetScale();
}
}
void ScaleByAnimation::UpdateTween(Actor* target, float frac)
{
target->SetScale(Vec2{ start_val_.x + delta_.x * frac, start_val_.y + delta_.y * frac });
}
ScaleByAnimation* ScaleByAnimation::Clone() const
{
ScaleByAnimation* ptr = new ScaleByAnimation(GetDuration(), delta_);
DoClone(ptr);
return ptr;
}
ScaleByAnimation* ScaleByAnimation::Reverse() const
{
ScaleByAnimation* ptr = new ScaleByAnimation(GetDuration(), -delta_);
DoClone(ptr);
return ptr;
}
ScaleToAnimation::ScaleToAnimation(Duration duration, const Vec2& scale)
: ScaleByAnimation(duration, Vec2())
, end_val_(scale)
{
}
ScaleToAnimation* ScaleToAnimation::Clone() const
{
ScaleToAnimation* ptr = new ScaleToAnimation(GetDuration(), end_val_);
DoClone(ptr);
return ptr;
}
void ScaleToAnimation::Init(Actor* target)
{
ScaleByAnimation::Init(target);
delta_ = end_val_ - start_val_;
}
//-------------------------------------------------------
// Opacity Animation
//-------------------------------------------------------
FadeToAnimation::FadeToAnimation(Duration duration, float opacity)
: TweenAnimation(duration)
, delta_val_(0.0f)
, start_val_(0.f)
, end_val_(opacity)
{
}
void FadeToAnimation::Init(Actor* target)
{
if (target)
{
start_val_ = target->GetOpacity();
delta_val_ = end_val_ - start_val_;
}
}
void FadeToAnimation::UpdateTween(Actor* target, float frac)
{
target->SetOpacity(start_val_ + delta_val_ * frac);
}
FadeToAnimation* FadeToAnimation::Clone() const
{
FadeToAnimation* ptr = new FadeToAnimation(GetDuration(), end_val_);
DoClone(ptr);
return ptr;
}
//-------------------------------------------------------
// Rotate Animation
//-------------------------------------------------------
RotateByAnimation::RotateByAnimation(Duration duration, float rotation)
: TweenAnimation(duration)
, delta_val_(rotation)
, start_val_(0.0f)
{
}
void RotateByAnimation::Init(Actor* target)
{
if (target)
{
start_val_ = target->GetRotation();
}
}
void RotateByAnimation::UpdateTween(Actor* target, float frac)
{
float rotation = start_val_ + delta_val_ * frac;
if (rotation > 360.f)
rotation -= 360.f;
target->SetRotation(rotation);
}
RotateByAnimation* RotateByAnimation::Clone() const
{
RotateByAnimation* ptr = new RotateByAnimation(GetDuration(), delta_val_);
DoClone(ptr);
return ptr;
}
RotateByAnimation* RotateByAnimation::Reverse() const
{
RotateByAnimation* ptr = new RotateByAnimation(GetDuration(), -delta_val_);
DoClone(ptr);
return ptr;
}
RotateToAnimation::RotateToAnimation(Duration duration, float rotation)
: RotateByAnimation(duration, 0)
, end_val_(rotation)
{
}
RotateToAnimation* RotateToAnimation::Clone() const
{
RotateToAnimation* ptr = new RotateToAnimation(GetDuration(), end_val_);
DoClone(ptr);
return ptr;
}
void RotateToAnimation::Init(Actor* target)
{
RotateByAnimation::Init(target);
delta_val_ = end_val_ - start_val_;
}
} // namespace kiwano

View File

@ -19,11 +19,609 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/Common.h> #include <kiwano/2d/animation/Animation.h>
#include <kiwano/2d/animation/EaseFunc.h>
#include <kiwano/utils/Logger.h>
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(TweenAnimation);
KGE_DECLARE_SMART_PTR(MoveByAnimation);
KGE_DECLARE_SMART_PTR(MoveToAnimation);
KGE_DECLARE_SMART_PTR(JumpByAnimation);
KGE_DECLARE_SMART_PTR(JumpToAnimation);
KGE_DECLARE_SMART_PTR(ScaleByAnimation);
KGE_DECLARE_SMART_PTR(ScaleToAnimation);
KGE_DECLARE_SMART_PTR(FadeToAnimation);
KGE_DECLARE_SMART_PTR(RotateByAnimation);
KGE_DECLARE_SMART_PTR(RotateToAnimation);
/**
* \addtogroup Animation
* @{
*/
/// \~chinese
/// @brief 补间动画
class KGE_API TweenAnimation : public Animation
{
public:
/// \~chinese
/// @brief 获取动画时长
Duration GetDuration() const;
/// \~chinese
/// @brief 设置动画时长
void SetDuration(Duration duration);
/// \~chinese
/// @brief 获取动画速度缓动函数
const EaseFunc& GetEaseFunc() const;
/// \~chinese
/// @brief 设置动画速度缓动函数
void SetEaseFunc(const EaseFunc& func);
protected:
TweenAnimation();
TweenAnimation(Duration duration);
float Interpolate(float frac);
void Update(Actor* target, Duration dt) override;
virtual void UpdateTween(Actor* target, float frac) = 0;
void DoClone(TweenAnimation* to) const;
private:
Duration dur_;
EaseFunc ease_func_;
};
/// \~chinese
/// @brief 相对位移动画
class KGE_API MoveByAnimation : public TweenAnimation
{
public:
/// \~chinese
/// @brief 创建相对位移动画
/// @param duration 动画时长
/// @param displacement 位移向量
MoveByAnimation(Duration duration, const Vec2& displacement);
/// \~chinese
/// @brief 获取位移向量
Vec2 GetDisplacement() const;
/// \~chinese
/// @brief 设置位移向量
void SetDisplacement(const Vec2& displacement);
/// \~chinese
/// @brief 获取该动画的拷贝对象
MoveByAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
MoveByAnimation* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float frac) override;
protected:
Point start_pos_;
Point prev_pos_;
Vec2 displacement_;
};
/// \~chinese
/// @brief 位移动画
class KGE_API MoveToAnimation : public MoveByAnimation
{
public:
/// \~chinese
/// @brief 创建位移动画
/// @param duration 动画时长
/// @param distination 目的坐标
MoveToAnimation(Duration duration, const Point& distination);
/// \~chinese
/// @brief 获取目的坐标
Point GetDistination() const;
/// \~chinese
/// @brief 设置目的坐标
void SetDistination(const Point& distination);
/// \~chinese
/// @brief 获取该动画的拷贝对象
MoveToAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
MoveToAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in MoveToAnimation");
return nullptr;
} }
protected:
void Init(Actor* target) override;
private:
Point distination_;
};
/// \~chinese
/// @brief 相对跳跃动画
class KGE_API JumpByAnimation : public TweenAnimation
{
public:
/// \~chinese
/// @brief 创建相对跳跃动画
/// @param duration 动画时长
/// @param displacement 跳跃位移向量
/// @param height 跳跃高度
/// @param count 跳跃次数
JumpByAnimation(Duration duration, const Vec2& displacement, float height, int count = 1);
/// \~chinese
/// @brief 获取跳跃位移
Vec2 GetDisplacement() const;
/// \~chinese
/// @brief 获取跳跃高度
float GetJumpHeight() const;
/// \~chinese
/// @brief 获取跳跃次数
int GetJumpCount() const;
/// \~chinese
/// @brief 设置跳跃位移
void SetDisplacement(const Vec2& displacement);
/// \~chinese
/// @brief 设置跳跃高度
void SetJumpHeight(float height);
/// \~chinese
/// @brief 设置跳跃次数
void SetJumpCount(int count);
/// \~chinese
/// @brief 获取该动画的拷贝对象
JumpByAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
JumpByAnimation* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float frac) override;
protected:
float height_;
int jump_count_;
Point start_pos_;
Point displacement_;
Point prev_pos_;
};
/// \~chinese
/// @brief 跳跃动画
class KGE_API JumpToAnimation : public JumpByAnimation
{
public:
/// \~chinese
/// @brief 创建跳跃动画
/// @param duration 动画时长
/// @param distination 目的坐标
/// @param height 跳跃高度
/// @param count 跳跃次数
JumpToAnimation(Duration duration, const Point& distination, float height, int count = 1);
/// \~chinese
/// @brief 获取目的坐标
Point GetDistination() const;
/// \~chinese
/// @brief 设置目的坐标
void SetDistination(const Point& distination);
/// \~chinese
/// @brief 获取该动画的拷贝对象
JumpToAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
JumpToAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in JumpToAnimation");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
Point distination_;
};
/// \~chinese
/// @brief 相对缩放动画
class KGE_API ScaleByAnimation : public TweenAnimation
{
public:
/// \~chinese
/// @brief 创建相对缩放动画
/// @param duration 动画时长
/// @param scale 缩放相对变化值
ScaleByAnimation(Duration duration, const Vec2& scale);
/// \~chinese
/// @brief 获取横向缩放相对变化值
float GetScaleX() const;
/// \~chinese
/// @brief 获取横向缩放相对变化值
float GetScaleY() const;
/// \~chinese
/// @brief 设置纵向缩放相对变化值
void SetScaleX(float scale_x);
/// \~chinese
/// @brief 设置纵向缩放相对变化值
void SetScaleY(float scale_y);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ScaleByAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ScaleByAnimation* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float frac) override;
protected:
Vec2 start_val_;
Vec2 delta_;
};
/// \~chinese
/// @brief 缩放动画
class KGE_API ScaleToAnimation : public ScaleByAnimation
{
public:
/// \~chinese
/// @brief 创建缩放动画
/// @param duration 动画时长
/// @param scale 缩放目标值
ScaleToAnimation(Duration duration, const Vec2& scale);
/// \~chinese
/// @brief 获取横向缩放目标值
float GetTargetScaleX() const;
/// \~chinese
/// @brief 获取横向缩放目标值
float GetTargetScaleY() const;
/// \~chinese
/// @brief 设置纵向缩放目标值
void SetTargetScaleX(float scale_x);
/// \~chinese
/// @brief 设置纵向缩放目标值
void SetTargetScaleY(float scale_y);
/// \~chinese
/// @brief 获取该动画的拷贝对象
ScaleToAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
ScaleToAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in ScaleToAnimation");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
Vec2 end_val_;
};
/// \~chinese
/// @brief 透明度渐变动画
class KGE_API FadeToAnimation : public TweenAnimation
{
public:
/// \~chinese
/// @brief 创建透明度渐变动画
/// @param duration 动画时长
/// @param opacity 目标透明度
FadeToAnimation(Duration duration, float opacity);
/// \~chinese
/// @brief 获取目标透明度
float GetTargetOpacity() const;
/// \~chinese
/// @brief 设置目标透明度
void SetTargetOpacity(float opacity);
/// \~chinese
/// @brief 获取该动画的拷贝对象
FadeToAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
FadeToAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in FadeToAnimation");
return nullptr;
}
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float frac) override;
private:
float start_val_;
float delta_val_;
float end_val_;
};
/// \~chinese
/// @brief 相对旋转动画
class KGE_API RotateByAnimation : public TweenAnimation
{
public:
/// \~chinese
/// @brief 创建相对旋转动画
/// @param duration 动画时长
/// @param rotation 角度相对变化值
RotateByAnimation(Duration duration, float rotation);
/// \~chinese
/// @brief 获取角度相对变化值
float GetRotation() const;
/// \~chinese
/// @brief 设置角度相对变化值
void SetRotation(float rotation);
/// \~chinese
/// @brief 获取该动画的拷贝对象
RotateByAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
RotateByAnimation* Reverse() const override;
protected:
void Init(Actor* target) override;
void UpdateTween(Actor* target, float frac) override;
protected:
float start_val_;
float delta_val_;
};
/// \~chinese
/// @brief 旋转动画
class KGE_API RotateToAnimation : public RotateByAnimation
{
public:
/// \~chinese
/// @brief 创建旋转动画
/// @param duration 动画时长
/// @param rotation 目标角度
RotateToAnimation(Duration duration, float rotation);
/// \~chinese
/// @brief 获取目标角度
float GetTargetRotation() const;
/// \~chinese
/// @brief 设置目标角度
void SetTargetRotation(float rotation);
/// \~chinese
/// @brief 获取该动画的拷贝对象
RotateToAnimation* Clone() const override;
/// \~chinese
/// @brief 获取该动画的倒转
RotateToAnimation* Reverse() const override
{
KGE_ERRORF("Reverse() not supported in RotateToAnimation");
return nullptr;
}
protected:
void Init(Actor* target) override;
private:
float end_val_;
};
/** @} */
inline const EaseFunc& TweenAnimation::GetEaseFunc() const
{
return ease_func_;
}
inline Duration TweenAnimation::GetDuration() const
{
return dur_;
}
inline void TweenAnimation::SetDuration(Duration duration)
{
dur_ = duration;
}
inline void TweenAnimation::SetEaseFunc(const EaseFunc& func)
{
ease_func_ = func;
}
inline Vec2 MoveByAnimation::GetDisplacement() const
{
return displacement_;
}
inline void MoveByAnimation::SetDisplacement(const Vec2& displacement)
{
displacement_ = displacement;
}
inline Point MoveToAnimation::GetDistination() const
{
return distination_;
}
inline void MoveToAnimation::SetDistination(const Point& distination)
{
distination_ = distination;
}
inline Vec2 JumpByAnimation::GetDisplacement() const
{
return displacement_;
}
inline float JumpByAnimation::GetJumpHeight() const
{
return height_;
}
inline int JumpByAnimation::GetJumpCount() const
{
return jump_count_;
}
inline void JumpByAnimation::SetDisplacement(const Vec2& displacement)
{
displacement_ = displacement;
}
inline void JumpByAnimation::SetJumpHeight(float height)
{
height_ = height;
}
inline void JumpByAnimation::SetJumpCount(int count)
{
jump_count_ = count;
}
inline Point JumpToAnimation::GetDistination() const
{
return distination_;
}
inline void JumpToAnimation::SetDistination(const Point& distination)
{
distination_ = distination;
}
inline float ScaleByAnimation::GetScaleX() const
{
return delta_.x;
}
inline float ScaleByAnimation::GetScaleY() const
{
return delta_.y;
}
inline void ScaleByAnimation::SetScaleX(float scale_x)
{
delta_.x = scale_x;
}
inline void ScaleByAnimation::SetScaleY(float scale_y)
{
delta_.y = scale_y;
}
inline float ScaleToAnimation::GetTargetScaleX() const
{
return end_val_.x;
}
inline float ScaleToAnimation::GetTargetScaleY() const
{
return end_val_.y;
}
inline void ScaleToAnimation::SetTargetScaleX(float scale_x)
{
end_val_.x = scale_x;
}
inline void ScaleToAnimation::SetTargetScaleY(float scale_y)
{
end_val_.y = scale_y;
}
inline float FadeToAnimation::GetTargetOpacity() const
{
return end_val_;
}
inline void FadeToAnimation::SetTargetOpacity(float opacity)
{
end_val_ = opacity;
}
inline float RotateByAnimation::GetRotation() const
{
return delta_val_;
}
inline void RotateByAnimation::SetRotation(float rotation)
{
delta_val_ = rotation;
}
inline float RotateToAnimation::GetTargetRotation() const
{
return end_val_;
}
inline void RotateToAnimation::SetTargetRotation(float rotation)
{
end_val_ = rotation;
}
} // namespace kiwano

View File

@ -82,8 +82,6 @@
#include <kiwano/render/Shape.h> #include <kiwano/render/Shape.h>
#include <kiwano/render/ShapeMaker.h> #include <kiwano/render/ShapeMaker.h>
#include <kiwano/render/Texture.h> #include <kiwano/render/Texture.h>
#include <kiwano/render/Frame.h>
#include <kiwano/render/FrameSequence.h>
#include <kiwano/render/GifImage.h> #include <kiwano/render/GifImage.h>
#include <kiwano/render/Layer.h> #include <kiwano/render/Layer.h>
#include <kiwano/render/TextLayout.h> #include <kiwano/render/TextLayout.h>
@ -104,13 +102,21 @@
#include <kiwano/2d/Stage.h> #include <kiwano/2d/Stage.h>
#include <kiwano/2d/TextActor.h> #include <kiwano/2d/TextActor.h>
#include <kiwano/2d/Transition.h> #include <kiwano/2d/Transition.h>
#include <kiwano/2d/action/Action.h>
#include <kiwano/2d/action/ActionDelay.h> //
#include <kiwano/2d/action/ActionGroup.h> // animation
#include <kiwano/2d/action/ActionTween.h> //
#include <kiwano/2d/action/ActionWalk.h>
#include <kiwano/2d/action/Animation.h> #include <kiwano/2d/animation/Animation.h>
#include <kiwano/2d/action/ActionScheduler.h> #include <kiwano/2d/animation/DelayAnimation.h>
#include <kiwano/2d/animation/AnimationGroup.h>
#include <kiwano/2d/animation/TweenAnimation.h>
#include <kiwano/2d/animation/PathAnimation.h>
#include <kiwano/2d/animation/KeyFrame.h>
#include <kiwano/2d/animation/FrameSequence.h>
#include <kiwano/2d/animation/FrameAnimation.h>
#include <kiwano/2d/animation/Animator.h>
#include <kiwano/2d/animation/AnimationWrapper.h>
// //
// platform // platform

View File

@ -60,22 +60,6 @@ void RenderContext::EndDraw()
} }
} }
void RenderContext::DrawFrame(FramePtr frame, const Point& dest_pos)
{
if (frame)
{
this->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(dest_pos, frame->GetSize()));
}
}
void RenderContext::DrawFrame(FramePtr frame, const Rect& dest_rect)
{
if (frame)
{
this->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &dest_rect);
}
}
void RenderContext::SetGlobalTransform(const Matrix3x2* matrix) void RenderContext::SetGlobalTransform(const Matrix3x2* matrix)
{ {
if (matrix) if (matrix)

View File

@ -25,7 +25,6 @@
#include <kiwano/render/Layer.h> #include <kiwano/render/Layer.h>
#include <kiwano/render/TextLayout.h> #include <kiwano/render/TextLayout.h>
#include <kiwano/render/Texture.h> #include <kiwano/render/Texture.h>
#include <kiwano/render/Frame.h>
namespace kiwano namespace kiwano
{ {
@ -80,18 +79,6 @@ public:
virtual void DrawTexture(const Texture& texture, const Rect* src_rect = nullptr, virtual void DrawTexture(const Texture& texture, const Rect* src_rect = nullptr,
const Rect* dest_rect = nullptr) = 0; const Rect* dest_rect = nullptr) = 0;
/// \~chinese
/// @brief 绘制图像帧
/// @param frame 图像帧
/// @param dest_pos 绘制图像的位置
virtual void DrawFrame(FramePtr frame, const Point& dest_pos);
/// \~chinese
/// @brief 绘制图像帧
/// @param frame 图像帧
/// @param dest_rect 绘制的目标区域
virtual void DrawFrame(FramePtr frame, const Rect& dest_rect);
/// \~chinese /// \~chinese
/// @brief 绘制文本布局 /// @brief 绘制文本布局
/// @param layout 文本布局 /// @param layout 文本布局

View File

@ -104,8 +104,8 @@ public:
virtual void CreateGifImage(GifImage& gif, const Resource& resource) = 0; virtual void CreateGifImage(GifImage& gif, const Resource& resource) = 0;
/// \~chinese /// \~chinese
/// @brief ´´½¨GIFͼÏñÖ¡ÄÚ²¿×ÊÔ´ /// @brief 创建GIF关键帧内部资源
/// @param[out] frame GIFͼÏñÖ¡ /// @param[out] frame GIF关键帧
/// @param[in] gif GIF图像 /// @param[in] gif GIF图像
/// @param[in] frame_index 帧下标 /// @param[in] frame_index 帧下标
virtual void CreateGifImageFrame(GifImage::Frame& frame, const GifImage& gif, size_t frame_index) = 0; virtual void CreateGifImageFrame(GifImage::Frame& frame, const GifImage& gif, size_t frame_index) = 0;

View File

@ -20,10 +20,7 @@
#pragma once #pragma once
#include <kiwano/core/Resource.h> #include <kiwano/core/Resource.h>
#include <kiwano/render/Frame.h> #include <kiwano/base/ObjectBase.h>
#include <kiwano/render/FrameSequence.h>
#include <kiwano/render/Font.h>
#include <kiwano/render/GifImage.h>
namespace kiwano namespace kiwano
{ {

View File

@ -24,6 +24,11 @@
#include <kiwano/utils/ResourceLoader.h> #include <kiwano/utils/ResourceLoader.h>
#include <kiwano/utils/ResourceCache.h> #include <kiwano/utils/ResourceCache.h>
#include <kiwano/render/Font.h>
#include <kiwano/render/GifImage.h>
#include <kiwano/2d/animation/KeyFrame.h>
#include <kiwano/2d/animation/FrameSequence.h>
namespace kiwano namespace kiwano
{ {
namespace resource_cache_01 namespace resource_cache_01
@ -195,7 +200,7 @@ void LoadTexturesFromData(ResourceCache* cache, GlobalData* gdata, const String&
else if (!file.empty()) else if (!file.empty())
{ {
// Simple image // Simple image
FramePtr frame = MakePtr<Frame>(); KeyFramePtr frame = MakePtr<KeyFrame>();
if (frame && frame->Load(gdata->path + file)) if (frame && frame->Load(gdata->path + file))
{ {
cache->AddObject(id, frame); cache->AddObject(id, frame);
@ -212,11 +217,11 @@ void LoadTexturesFromData(ResourceCache* cache, GlobalData* gdata, const String&
return; return;
// Frames // Frames
Vector<FramePtr> frames; Vector<KeyFramePtr> frames;
frames.reserve(files.size()); frames.reserve(files.size());
for (const auto& file : files) for (const auto& file : files)
{ {
FramePtr frame = MakePtr<Frame>(); KeyFramePtr frame = MakePtr<KeyFrame>();
if (frame->Load(gdata->path + file)) if (frame->Load(gdata->path + file))
{ {
frames.push_back(frame); frames.push_back(frame);
@ -243,14 +248,17 @@ void LoadTexturesFromData(ResourceCache* cache, GlobalData* gdata, const String&
{ {
if (rows || cols) if (rows || cols)
{ {
// Frame slices // KeyFrame slices
FramePtr frame = MakePtr<Frame>(); TexturePtr texture = MakePtr<Texture>();
if (frame && frame->Load(gdata->path + file)) if (texture && texture->Load(gdata->path + file))
{ {
FrameSequencePtr frame_seq = MakePtr<FrameSequence>(); FrameSequencePtr frame_seq = MakePtr<FrameSequence>();
if (frame_seq) if (frame_seq)
{ {
frame_seq->AddFrames(frame, cols, rows, max_num, padding_x, padding_y); KeyFrameSpliter spliter(texture);
auto frames = spliter.Split(cols, rows, max_num, padding_x, padding_y);
frame_seq->AddFrames(frames);
cache->AddObject(id, frame_seq); cache->AddObject(id, frame_seq);
return; return;
} }
@ -259,7 +267,7 @@ void LoadTexturesFromData(ResourceCache* cache, GlobalData* gdata, const String&
else else
{ {
// Simple image // Simple image
FramePtr frame = MakePtr<Frame>(); KeyFramePtr frame = MakePtr<KeyFrame>();
if (frame && frame->Load(gdata->path + file)) if (frame && frame->Load(gdata->path + file))
{ {
cache->AddObject(id, frame); cache->AddObject(id, frame);