Browse Source

Add Animation2D and AnimatedSprite2D.

aster2013 11 years ago
parent
commit
a6f18c41ea

+ 172 - 0
Source/Engine/Urho2D/AnimatedSprite2D.cpp

@@ -0,0 +1,172 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// 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 "Precompiled.h"
+#include "Animation2D.h"
+#include "AnimatedSprite2D.h"
+#include "Context.h"
+#include "SceneEvents.h"
+#include "Sprite2D.h"
+#include "Scene.h"
+#include "Texture2D.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+extern const char* URHO2D_CATEGORY;
+
+const char* cycleModeNames[] = 
+{
+    "Loop",
+    "Clamp",
+    "Pingpong",
+    0
+};
+
+template<> CycleMode Variant::Get<CycleMode>() const
+{
+    return (CycleMode)GetInt();
+}
+
+AnimatedSprite2D::AnimatedSprite2D(Context* context) : StaticSprite2D(context),
+    speed_(1.0f), 
+    cycleMode_(CM_LOOP),
+    animationTime_(0.0f), 
+    animationTotalTime_(1.0f)
+{
+}
+
+AnimatedSprite2D::~AnimatedSprite2D()
+{
+}
+
+void AnimatedSprite2D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<AnimatedSprite2D>(URHO2D_CATEGORY);
+    ACCESSOR_ATTRIBUTE(AnimatedSprite2D, VAR_FLOAT, "Speed", GetSpeed, SetSpeed, float, 1.0f, AM_DEFAULT);
+    ENUM_ACCESSOR_ATTRIBUTE(AnimatedSprite2D, "Cycle Mode", GetCycleMode, SetCycleMode, CycleMode, cycleModeNames, 0, AM_FILE);
+    COPY_BASE_ATTRIBUTES(AnimatedSprite2D, StaticSprite2D);
+}
+
+void AnimatedSprite2D::OnSetEnabled()
+{
+    StaticSprite2D::OnSetEnabled();
+
+    Scene* scene = GetScene();
+    if (scene)
+    {
+        if (IsEnabledEffective())
+            SubscribeToEvent(scene, E_SCENEPOSTUPDATE, HANDLER(AnimatedSprite2D, HandleScenePostUpdate));
+        else
+            UnsubscribeFromEvent(scene, E_SCENEPOSTUPDATE);
+    }
+}
+
+void AnimatedSprite2D::SetSpeed(float speed)
+{
+    speed_ = speed;
+}
+
+void AnimatedSprite2D::SetCycleMode(CycleMode cycleMode)
+{
+    cycleMode_ = cycleMode;
+}
+
+void AnimatedSprite2D::SetAnimation(Animation2D* animation, float startTime)
+{
+    animationTime_ = startTime;
+
+    if (animation_ == animation)
+        return;
+
+    if (animation_)
+        SetSprite(0);
+
+    animation_ = animation;
+
+    if (animation_)
+    {
+        const KeyFrame2D* keyFrame = animation_->GetKeyFrameByIndex(0);
+        if (keyFrame)
+            SetSprite(keyFrame->sprite_);
+
+        animationTotalTime_ = animation_->GetTotalTime();
+    }
+}
+
+Animation2D* AnimatedSprite2D::GetAnimation() const
+{
+    return animation_;
+}
+
+void AnimatedSprite2D::OnNodeSet(Node* node)
+{
+    StaticSprite2D::OnNodeSet(node);
+
+    if (node)
+    {
+        Scene* scene = GetScene();
+        if (scene && IsEnabledEffective())
+            SubscribeToEvent(scene, E_SCENEPOSTUPDATE, HANDLER(AnimatedSprite2D, HandleScenePostUpdate));
+    }
+}
+
+void AnimatedSprite2D::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
+{
+    using namespace ScenePostUpdate;
+    float timeStep = eventData[P_TIMESTEP].GetFloat();
+    animationTime_ += timeStep * speed_;
+
+    if (!animation_)
+        return;
+
+    float time;
+
+    switch (cycleMode_)
+    {
+    case CM_LOOP:
+        time = fmodf(animationTime_, animationTotalTime_);
+        break;
+
+    case CM_CLAMP:
+        time = Clamp(animationTime_, 0.0f, animationTotalTime_);
+        break;
+
+    case CM_PINGPONG:
+        {
+            float doubleTotalTime = animationTotalTime_ * 2.0f;
+            float fract = fmodf(animationTime_, doubleTotalTime);
+            time = (fract < animationTotalTime_) ? fract : doubleTotalTime - fract;
+        }
+        break;
+    }
+
+    const KeyFrame2D* keyFrame = animation_->GetKeyFrameByTime(time);
+    if (GetSprite() != keyFrame->sprite_)
+        SetSprite(keyFrame->sprite_);
+
+    MarkForUpdate();
+}
+
+}

+ 92 - 0
Source/Engine/Urho2D/AnimatedSprite2D.h

@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// 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 "StaticSprite2D.h"
+
+namespace Urho3D
+{
+
+class Animation2D;
+
+/// Cycle mode.
+enum CycleMode
+{
+    /// Loop mode.
+    CM_LOOP = 0,
+    /// Clamp mode.
+    CM_CLAMP,
+    /// Pingpong Mode.
+    CM_PINGPONG,
+};
+
+/// Static sprite component.
+class URHO3D_API AnimatedSprite2D : public StaticSprite2D
+{
+    OBJECT(AnimatedSprite2D);
+
+public:
+    /// Construct.
+    AnimatedSprite2D(Context* context);
+    /// Destruct.
+    ~AnimatedSprite2D();
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+    /// Handle enabled/disabled state change.
+    virtual void OnSetEnabled();
+
+    /// Set speed.
+    void SetSpeed(float speed);
+    /// Set cycle mode.
+    void SetCycleMode(CycleMode cycleMode);
+    /// Set animation.
+    void SetAnimation(Animation2D* animation, float startTime = 0.0f);
+
+    /// Return speed.
+    float GetSpeed() const { return speed_; }
+    /// Return cycle mode.
+    CycleMode GetCycleMode() const { return cycleMode_; }
+    /// Return Animation.
+    Animation2D* GetAnimation() const;
+
+protected:
+    /// Handle node being assigned.
+    virtual void OnNodeSet(Node* node);
+    /// Handle scene post update.
+    void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
+
+    /// Speed.
+    float speed_;
+    /// Cycle mode.
+    CycleMode cycleMode_;
+    /// Animation.
+    SharedPtr<Animation2D> animation_;
+    /// Animation time.
+    float animationTime_;
+    /// Animation total time.
+    float animationTotalTime_;
+};
+
+}
+

+ 167 - 0
Source/Engine/Urho2D/Animation2D.cpp

@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// 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 "Precompiled.h"
+#include "Animation2D.h"
+#include "Context.h"
+#include "Deserializer.h"
+#include "Log.h"
+#include "ResourceCache.h"
+#include "Serializer.h"
+#include "Sprite2D.h"
+#include "SpriteSheet2D.h"
+#include "XMLFile.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+Animation2D::Animation2D(Context* context) : Resource(context)
+{
+
+}
+
+Animation2D::~Animation2D()
+{
+
+}
+
+void Animation2D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<Animation2D>();
+}
+
+bool Animation2D::Load(Deserializer& source)
+{
+    keyFrames_.Clear();
+    keyFrameTimes_.Clear();
+
+    SharedPtr<XMLFile> xmlFile(new XMLFile(context_));
+    if(!xmlFile->Load(source))
+    {
+        LOGERROR("Could not load animation");
+        return false;
+    }
+
+    SetMemoryUse(source.GetSize());
+
+    XMLElement rootElem = xmlFile->GetRoot("Animaiton");
+    if (!rootElem)
+    {
+        LOGERROR("Invalid animation");
+        return false;
+    }
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    XMLElement keyFrameElem = rootElem.GetChild("KeyFrame");
+    if (!keyFrameElem)
+    {
+        LOGERROR("Could not found key frame");
+        return false;
+    }
+    
+    float totalTime = 0.0f;
+
+    while (keyFrameElem)
+    {
+        KeyFrame2D keyFrame;
+        keyFrame.duration_ = keyFrameElem.GetFloat("duration");
+
+        Vector<String> names = keyFrameElem.GetAttribute("sprite").Split('@');
+        if (names.Size() == 1)
+        {
+            Sprite2D* sprite = cache->GetResource<Sprite2D>(names[0]);
+            if (!sprite)
+            {
+                LOGERROR("Could not get sprite");
+                return false;
+            }
+
+            keyFrame.sprite_ = sprite;
+        }
+        else
+        {
+            SpriteSheet2D* spriteSheet = cache->GetResource<SpriteSheet2D>(names[0]);
+            if (!spriteSheet)
+            {
+                LOGERROR("Could not get sprite speet");
+                return false;
+            }
+
+            Sprite2D* sprite = spriteSheet->GetSprite(names[1]);
+            if (!sprite)
+            {
+                LOGERROR("Could not get sprite");
+                return false;
+            }
+
+            keyFrame.sprite_ = sprite;
+        }
+
+        keyFrames_.Push(keyFrame);
+
+        totalTime += keyFrame.duration_;
+        keyFrameTimes_.Push(totalTime);
+
+        keyFrameElem = keyFrameElem.GetNext("KeyFrame");
+    }
+
+    return true;
+}
+
+bool Animation2D::Save(Serializer& dest) const
+{
+    return false;
+}
+
+float Animation2D::GetTotalTime() const
+{
+    return keyFrameTimes_.Empty() ? 0.0f : keyFrameTimes_.Back();
+}
+
+unsigned Animation2D::GetNumKeyFrames() const
+{
+    return keyFrames_.Size();
+}
+
+const KeyFrame2D* Animation2D::GetKeyFrameByTime(float time) const
+{
+    if (time < 0.0f)
+        return 0;
+
+    for (unsigned i = 0; i < keyFrameTimes_.Size(); ++i)
+    {
+        if (time < keyFrameTimes_[i])
+            return &keyFrames_[i];
+    }
+
+    return 0;
+}
+
+const KeyFrame2D* Animation2D::GetKeyFrameByIndex(unsigned index) const
+{
+    return index < keyFrames_.Size() ? &keyFrames_[index] : 0;
+}
+
+}

+ 75 - 0
Source/Engine/Urho2D/Animation2D.h

@@ -0,0 +1,75 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// 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 "Resource.h"
+
+namespace Urho3D
+{
+
+class Sprite2D;
+
+/// 2D animation key frame.
+struct KeyFrame2D
+{
+    /// duration_;
+    float duration_;
+    /// Sprite.
+    SharedPtr<Sprite2D> sprite_;
+};
+
+/// 2D animation.
+class URHO3D_API Animation2D : public Resource
+{
+    OBJECT(Animation2D);
+
+public:
+    /// Construct.
+    Animation2D(Context* context);
+    /// Destruct.
+    virtual ~Animation2D();
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+    /// Load resource. Return true if successful.
+    virtual bool Load(Deserializer& source);
+    /// Save resource. Return true if successful.
+    virtual bool Save(Serializer& dest) const;
+
+    /// Return total time.
+    float GetTotalTime() const;
+    /// Return num key frame.
+    unsigned GetNumKeyFrames() const;
+    /// Return key frame by time.
+    const KeyFrame2D* GetKeyFrameByTime(float time) const;
+    /// Return key frame by index.
+    const KeyFrame2D* GetKeyFrameByIndex(unsigned index) const;
+    
+private:
+    /// Key frames.
+    Vector<KeyFrame2D> keyFrames_;
+    /// Key frame times.
+    PODVector<float> keyFrameTimes_;
+};
+
+}

+ 10 - 6
Source/Engine/Urho2D/Urho2D.cpp

@@ -21,12 +21,14 @@
 //
 
 #include "Precompiled.h"
+#include "AnimatedSprite2D.h"
+#include "Animation2D.h"
+#include "Drawable2D.h"
+#include "ParticleEmitter2D.h"
+#include "ParticleModel2D.h"
 #include "Sprite2D.h"
 #include "SpriteSheet2D.h"
-#include "Drawable2D.h"
 #include "StaticSprite2D.h"
-#include "ParticleModel2D.h"
-#include "ParticleEmitter2D.h"
 
 #include "DebugNew.h"
 
@@ -37,12 +39,14 @@ const char* URHO2D_CATEGORY = "Urho2D";
 
 void RegisterUrho2DLibrary(Context* context)
 {
+    AnimatedSprite2D::RegisterObject(context);
+    Animation2D::RegisterObject(context);
+    Drawable2D::RegisterObject(context);
+    ParticleEmitter2D::RegisterObject(context);
+    ParticleModel2D::RegisterObject(context);
     Sprite2D::RegisterObject(context);
     SpriteSheet2D::RegisterObject(context);
-    Drawable2D::RegisterObject(context);
     StaticSprite2D::RegisterObject(context);
-    ParticleModel2D::RegisterObject(context);
-    ParticleEmitter2D::RegisterObject(context);
 }
 
 }