Browse Source

Move wrap mode out of AttributeAnimation.

Aster Jian 11 years ago
parent
commit
caf6f1b35a

+ 5 - 1
Source/Engine/LuaScript/pkgs/Scene/Animatable.pkg

@@ -1,15 +1,19 @@
 $#include "Animatable.h"
 $#include "Animatable.h"
 
 
+enum WrapMode{};
+
 class Animatable : Serializable
 class Animatable : Serializable
 {
 {
     void SetAnimationEnabled(bool enable);
     void SetAnimationEnabled(bool enable);
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
-    void SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, float speed = 1.0f);
+    void SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
+    void SetAttributeAnimationWrapMode(const String& name, WrapMode wrapMode);
     void SetAttributeAnimationSpeed(const String& name, float speed);
     void SetAttributeAnimationSpeed(const String& name, float speed);
 
 
     bool GetAnimationEnabled() const;
     bool GetAnimationEnabled() const;
     ObjectAnimation* GetObjectAnimation() const;
     ObjectAnimation* GetObjectAnimation() const;
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
+    WrapMode GetAttributeAnimationWrapMode(const String& name) const;
     float GetAttributeAnimationSpeed(const String& name) const;
     float GetAttributeAnimationSpeed(const String& name) const;
     
     
     tolua_property__get_set bool animationEnabled;
     tolua_property__get_set bool animationEnabled;

+ 0 - 10
Source/Engine/LuaScript/pkgs/Scene/AttributeAnimation.pkg

@@ -1,26 +1,16 @@
 $#include "AttributeAnimation.h"
 $#include "AttributeAnimation.h"
 
 
-enum WrapMode
-{
-    WM_LOOP = 0,
-    WM_ONCE,
-    WM_CLAMP,
-};
-
 class AttributeAnimation : public Resource
 class AttributeAnimation : public Resource
 {
 {
     AttributeAnimation();
     AttributeAnimation();
     virtual ~AttributeAnimation();
     virtual ~AttributeAnimation();
     
     
-    void SetWrapMode(WrapMode wrapMode);
     void SetValueType(VariantType valueType);
     void SetValueType(VariantType valueType);
     bool SetKeyFrame(float time, const Variant& value);
     bool SetKeyFrame(float time, const Variant& value);
     void SetEventFrame(float time, const StringHash& eventType, const VariantMap& eventData = VariantMap());
     void SetEventFrame(float time, const StringHash& eventType, const VariantMap& eventData = VariantMap());
     
     
-    WrapMode GetWrapMode() const;
     VariantType GetValueType() const;
     VariantType GetValueType() const;
 
 
-    tolua_property__get_set WrapMode wrapMode;
     tolua_property__get_set VariantType valueType;
     tolua_property__get_set VariantType valueType;
 };
 };
 
 

+ 9 - 1
Source/Engine/LuaScript/pkgs/Scene/ObjectAnimation.pkg

@@ -1,14 +1,22 @@
 $#include "ObjectAnimation.h"
 $#include "ObjectAnimation.h"
 
 
+enum WrapMode
+{
+    WM_LOOP = 0,
+    WM_ONCE,
+    WM_CLAMP,
+};
+
 class ObjectAnimation : Resource
 class ObjectAnimation : Resource
 {
 {
     ObjectAnimation();
     ObjectAnimation();
     virtual ~ObjectAnimation();
     virtual ~ObjectAnimation();
     
     
-    void AddAttributeAnimation(const String name, AttributeAnimation* attributeAnimation, float speed = 1.0f);
+    void AddAttributeAnimation(const String name, AttributeAnimation* attributeAnimation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
     void RemoveAttributeAnimation(const String name);
     void RemoveAttributeAnimation(const String name);
     void RemoveAttributeAnimation(AttributeAnimation* attributeAnimation);
     void RemoveAttributeAnimation(AttributeAnimation* attributeAnimation);
     AttributeAnimation* GetAttributeAnimation(const String name) const;
     AttributeAnimation* GetAttributeAnimation(const String name) const;
+    WrapMode GetAttributeAnimationWrapMode(const String name) const;
     float GetAttributeAnimationSpeed(const String name) const;
     float GetAttributeAnimationSpeed(const String name) const;
 };
 };
 
 

+ 32 - 4
Source/Engine/Scene/Animatable.cpp

@@ -35,6 +35,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+extern const char* wrapModeNames[];
+
 Animatable::Animatable(Context* context) :
 Animatable::Animatable(Context* context) :
     Serializable(context),
     Serializable(context),
     animationEnabled_(true)
     animationEnabled_(true)
@@ -76,8 +78,19 @@ bool Animatable::LoadXML(const XMLElement& source, bool setInstanceDefault)
         if (!attributeAnimation->LoadXML(elem))
         if (!attributeAnimation->LoadXML(elem))
             return false;
             return false;
 
 
+        String wrapModeString = source.GetAttribute("wrapMode");
+        WrapMode wrapMode = WM_LOOP;
+        for (int i = 0; i <= WM_CLAMP; ++i)
+        {
+            if (wrapModeString == wrapModeNames[i])
+            {
+                wrapMode = (WrapMode)i;
+                break;
+            }
+        }
+
         float speed = elem.GetFloat("speed");
         float speed = elem.GetFloat("speed");
-        SetAttributeAnimation(name, attributeAnimation, speed);
+        SetAttributeAnimation(name, attributeAnimation, wrapMode, speed);
 
 
         elem = elem.GetNext("attributeAnimation");
         elem = elem.GetNext("attributeAnimation");
     }
     }
@@ -110,6 +123,7 @@ bool Animatable::SaveXML(XMLElement& dest) const
         if (!attributeAnimation->SaveXML(elem))
         if (!attributeAnimation->SaveXML(elem))
             return false;
             return false;
 
 
+        elem.SetAttribute("wrapMode", wrapModeNames[i->second_->GetWrapMode()]);
         elem.SetFloat("speed", i->second_->GetSpeed());
         elem.SetFloat("speed", i->second_->GetSpeed());
     }
     }
 
 
@@ -135,7 +149,7 @@ void Animatable::SetObjectAnimation(ObjectAnimation* objectAnimation)
         OnObjectAnimationAdded(objectAnimation_);
         OnObjectAnimationAdded(objectAnimation_);
 }
 }
 
 
-void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, float speed)
+void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, WrapMode wrapMode, float speed)
 {
 {
     AttributeAnimationInstance* currentInstance = GetAttributeAnimationInstance(name);
     AttributeAnimationInstance* currentInstance = GetAttributeAnimationInstance(name);
 
 
@@ -143,6 +157,7 @@ void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* a
     {
     {
         if (currentInstance && attributeAnimation == currentInstance->GetAttributeAnimation())
         if (currentInstance && attributeAnimation == currentInstance->GetAttributeAnimation())
         {
         {
+            currentInstance->SetWrapMode(wrapMode);
             currentInstance->SetSpeed(speed);
             currentInstance->SetSpeed(speed);
             return;
             return;
         }
         }
@@ -197,7 +212,7 @@ void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* a
             }
             }
         }
         }
 
 
-        attributeAnimationInstances_[name] = new AttributeAnimationInstance(this, *attributeInfo, attributeAnimation, speed);
+        attributeAnimationInstances_[name] = new AttributeAnimationInstance(this, *attributeInfo, attributeAnimation, wrapMode, speed);
 
 
         if (!currentInstance)
         if (!currentInstance)
             OnAttributeAnimationAdded();
             OnAttributeAnimationAdded();
@@ -226,6 +241,13 @@ void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* a
     }
     }
 }
 }
 
 
+void Animatable::SetAttributeAnimationWrapMode(const String& name, WrapMode wrapMode)
+{
+    AttributeAnimationInstance* currentInstance = GetAttributeAnimationInstance(name);
+    if (currentInstance)
+        currentInstance->SetWrapMode(wrapMode);
+}
+
 void Animatable::SetAttributeAnimationSpeed(const String& name, float speed)
 void Animatable::SetAttributeAnimationSpeed(const String& name, float speed)
 {
 {
     AttributeAnimationInstance* currentInstance = GetAttributeAnimationInstance(name);
     AttributeAnimationInstance* currentInstance = GetAttributeAnimationInstance(name);
@@ -244,6 +266,12 @@ AttributeAnimation* Animatable::GetAttributeAnimation(const String& name) const
     return instance ? instance->GetAttributeAnimation() : 0;
     return instance ? instance->GetAttributeAnimation() : 0;
 }
 }
 
 
+WrapMode Animatable::GetAttributeAnimationWrapMode(const String& name) const
+{
+    const AttributeAnimationInstance* instance = GetAttributeAnimationInstance(name);
+    return instance ? instance->GetWrapMode() : WM_LOOP;
+}
+
 float Animatable::GetAttributeAnimationSpeed(const String& name) const
 float Animatable::GetAttributeAnimationSpeed(const String& name) const
 {
 {
     const AttributeAnimationInstance* instance = GetAttributeAnimationInstance(name);
     const AttributeAnimationInstance* instance = GetAttributeAnimationInstance(name);
@@ -272,7 +300,7 @@ void Animatable::OnObjectAnimationAdded(ObjectAnimation* objectAnimation)
     // Set all attribute animations from the object animation
     // Set all attribute animations from the object animation
     HashMap<String, SharedPtr<AttributeAnimation> > attributeAnimations = objectAnimation->GetAttributeAnimations();
     HashMap<String, SharedPtr<AttributeAnimation> > attributeAnimations = objectAnimation->GetAttributeAnimations();
     for (HashMap<String, SharedPtr<AttributeAnimation> >::Iterator i = attributeAnimations.Begin(); i != attributeAnimations.End(); ++i)
     for (HashMap<String, SharedPtr<AttributeAnimation> >::Iterator i = attributeAnimations.Begin(); i != attributeAnimations.End(); ++i)
-        SetAttributeAnimation(i->first_, i->second_, objectAnimation->GetAttributeAnimationSpeed(i->first_));
+        SetAttributeAnimation(i->first_, i->second_, objectAnimation->GetAttributeAnimationWrapMode(i->first_), objectAnimation->GetAttributeAnimationSpeed(i->first_));
 }
 }
 
 
 void Animatable::OnObjectAnimationRemoved(ObjectAnimation* objectAnimation)
 void Animatable::OnObjectAnimationRemoved(ObjectAnimation* objectAnimation)

+ 6 - 1
Source/Engine/Scene/Animatable.h

@@ -24,6 +24,7 @@
 
 
 #include "HashSet.h"
 #include "HashSet.h"
 #include "Serializable.h"
 #include "Serializable.h"
+#include "ObjectAnimation.h"
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
@@ -55,7 +56,9 @@ public:
     /// Set object animation.
     /// Set object animation.
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     /// Set attribute animation.
     /// Set attribute animation.
-    void SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, float speed = 1.0f);
+    void SetAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
+    /// Set attribute animation wrap mode.
+    void SetAttributeAnimationWrapMode(const String& name, WrapMode wrapMode);
     /// Set attribute animation speed.
     /// Set attribute animation speed.
     void SetAttributeAnimationSpeed(const String& name, float speed);
     void SetAttributeAnimationSpeed(const String& name, float speed);
 
 
@@ -65,6 +68,8 @@ public:
     ObjectAnimation* GetObjectAnimation() const;
     ObjectAnimation* GetObjectAnimation() const;
     /// Return attribute animation.
     /// Return attribute animation.
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
+    /// Return attribute animation wrap mode.
+    WrapMode GetAttributeAnimationWrapMode(const String& name) const;
     /// Return attribute animation speed.
     /// Return attribute animation speed.
     float GetAttributeAnimationSpeed(const String& name) const;
     float GetAttributeAnimationSpeed(const String& name) const;
 
 

+ 0 - 46
Source/Engine/Scene/AttributeAnimation.cpp

@@ -33,17 +33,8 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-const char* wrapModeNames[] = 
-{
-    "Loop",
-    "Once",
-    "Clamp",
-    0
-};
-
 AttributeAnimation::AttributeAnimation(Context* context) :
 AttributeAnimation::AttributeAnimation(Context* context) :
     Resource(context),
     Resource(context),
-    wrapMode_(WM_LOOP),
     valueType_(VAR_NONE),
     valueType_(VAR_NONE),
     isInterpolatable_(false),
     isInterpolatable_(false),
     beginTime_(M_INFINITY),
     beginTime_(M_INFINITY),
@@ -85,17 +76,6 @@ bool AttributeAnimation::LoadXML(const XMLElement& source)
     valueType_ = VAR_NONE;
     valueType_ = VAR_NONE;
     eventFrames_.Clear();
     eventFrames_.Clear();
 
 
-    String wrapModeString = source.GetAttribute("wrapMode");
-    wrapMode_ = WM_LOOP;
-    for (int i = 0; i <= WM_CLAMP; ++i)
-    {
-        if (wrapModeString == wrapModeNames[i])
-        {
-            wrapMode_ = (WrapMode)i;
-            break;
-        }
-    }
-
     SetValueType(Variant::GetTypeFromName(source.GetAttribute("valueType")));
     SetValueType(Variant::GetTypeFromName(source.GetAttribute("valueType")));
 
 
     XMLElement keyFrameEleme = source.GetChild("keyFrame");
     XMLElement keyFrameEleme = source.GetChild("keyFrame");
@@ -124,7 +104,6 @@ bool AttributeAnimation::LoadXML(const XMLElement& source)
 
 
 bool AttributeAnimation::SaveXML(XMLElement& dest) const
 bool AttributeAnimation::SaveXML(XMLElement& dest) const
 {
 {
-    dest.SetAttribute("wrapMode", wrapModeNames[wrapMode_]);
     dest.SetAttribute("valueType", Variant::GetTypeName(valueType_));
     dest.SetAttribute("valueType", Variant::GetTypeName(valueType_));
 
 
     for (unsigned i = 0; i < keyFrames_.Size(); ++i)
     for (unsigned i = 0; i < keyFrames_.Size(); ++i)
@@ -152,11 +131,6 @@ void AttributeAnimation::SetObjectAnimation(ObjectAnimation* objectAnimation)
     objectAnimation_ = objectAnimation;
     objectAnimation_ = objectAnimation;
 }
 }
 
 
-void AttributeAnimation::SetWrapMode(WrapMode wrapMode)
-{
-    wrapMode_ = wrapMode;
-}
-
 void AttributeAnimation::SetValueType(VariantType valueType)
 void AttributeAnimation::SetValueType(VariantType valueType)
 {
 {
     if (valueType == valueType_)
     if (valueType == valueType_)
@@ -230,26 +204,6 @@ ObjectAnimation* AttributeAnimation::GetObjectAnimation() const
     return objectAnimation_;
     return objectAnimation_;
 }
 }
 
 
-float AttributeAnimation::CalculateScaledTime(float currentTime, bool& finished) const
-{
-    switch (wrapMode_)
-    {
-    case WM_LOOP:
-        {
-            float span = endTime_ - beginTime_;
-            return beginTime_ + fmodf(currentTime - beginTime_, span);
-        }
-
-    case WM_ONCE:
-        finished = (currentTime >= endTime_);
-
-    case WM_CLAMP:
-        return Clamp(currentTime, beginTime_, endTime_);
-    }
-
-    return beginTime_;
-}
-
 void AttributeAnimation::GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const
 void AttributeAnimation::GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const
 {
 {
     for (unsigned i = 0; i < eventFrames_.Size(); ++i)
     for (unsigned i = 0; i < eventFrames_.Size(); ++i)

+ 1 - 21
Source/Engine/Scene/AttributeAnimation.h

@@ -31,17 +31,6 @@ namespace Urho3D
 class ObjectAnimation;
 class ObjectAnimation;
 class XMLElement;
 class XMLElement;
 
 
-/// Animation wrap mode.
-enum WrapMode
-{
-    /// Loop mode.
-    WM_LOOP = 0,
-    /// Play once then remove.
-    WM_ONCE,
-    /// Clamp mode.
-    WM_CLAMP,
-};
-
 /// Attribute key frame
 /// Attribute key frame
 struct AttributeKeyFrame
 struct AttributeKeyFrame
 {
 {
@@ -74,7 +63,7 @@ public:
     virtual ~AttributeAnimation();
     virtual ~AttributeAnimation();
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
-    
+
     /// Load resource. Return true if successful.
     /// Load resource. Return true if successful.
     virtual bool Load(Deserializer& source);
     virtual bool Load(Deserializer& source);
     /// Save resource. Return true if successful.
     /// Save resource. Return true if successful.
@@ -86,8 +75,6 @@ public:
 
 
     /// Set object animation.
     /// Set object animation.
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
-    /// Set wrap mode.
-    void SetWrapMode(WrapMode warpMode);
     /// Set value type.
     /// Set value type.
     void SetValueType(VariantType valueType);
     void SetValueType(VariantType valueType);
     /// Set key frame.
     /// Set key frame.
@@ -97,8 +84,6 @@ public:
 
 
     /// Return object animation.
     /// Return object animation.
     ObjectAnimation* GetObjectAnimation() const;
     ObjectAnimation* GetObjectAnimation() const;
-    /// Return wrap mode.
-    WrapMode GetWrapMode() const { return wrapMode_; }
     /// Return value type.
     /// Return value type.
     VariantType GetValueType() const { return valueType_; }
     VariantType GetValueType() const { return valueType_; }
     /// Is interpolatable.
     /// Is interpolatable.
@@ -107,8 +92,6 @@ public:
     float GetBeginTime() const { return beginTime_; }
     float GetBeginTime() const { return beginTime_; }
     /// Return end time.
     /// Return end time.
     float GetEndTime() const { return endTime_; }
     float GetEndTime() const { return endTime_; }
-    /// Calculate scaled time.
-    float CalculateScaledTime(float currentTime, bool& finished) const;
     /// Return all key frames.
     /// Return all key frames.
     const Vector<AttributeKeyFrame>& GetKeyFrames() const { return keyFrames_; }
     const Vector<AttributeKeyFrame>& GetKeyFrames() const { return keyFrames_; }
     /// Has event frames.
     /// Has event frames.
@@ -117,11 +100,8 @@ public:
     void GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const;
     void GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const;
 
 
 protected:
 protected:
-
     /// Object animation.
     /// Object animation.
     WeakPtr<ObjectAnimation> objectAnimation_;
     WeakPtr<ObjectAnimation> objectAnimation_;
-    /// Wrap mode.
-    WrapMode wrapMode_;
     /// Value type.
     /// Value type.
     VariantType valueType_;
     VariantType valueType_;
     /// Is interpolatable.
     /// Is interpolatable.

+ 28 - 3
Source/Engine/Scene/AttributeAnimationInstance.cpp

@@ -31,10 +31,11 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-AttributeAnimationInstance::AttributeAnimationInstance(Animatable* animatable, const AttributeInfo& attributeInfo, AttributeAnimation* attributeAnimation, float speed) :
+AttributeAnimationInstance::AttributeAnimationInstance(Animatable* animatable, const AttributeInfo& attributeInfo, AttributeAnimation* attributeAnimation, WrapMode wrapMode, float speed) :
     animatable_(animatable),
     animatable_(animatable),
     attributeInfo_(attributeInfo),
     attributeInfo_(attributeInfo),
     attributeAnimation_(attributeAnimation),
     attributeAnimation_(attributeAnimation),
+    wrapMode_(wrapMode),
     speed_(speed),
     speed_(speed),
     currentTime_(0.0f),
     currentTime_(0.0f),
     lastScaledTime_(0.0f)
     lastScaledTime_(0.0f)
@@ -46,6 +47,7 @@ AttributeAnimationInstance::AttributeAnimationInstance(const AttributeAnimationI
     animatable_(other.animatable_),
     animatable_(other.animatable_),
     attributeInfo_(other.attributeInfo_),
     attributeInfo_(other.attributeInfo_),
     attributeAnimation_(other.attributeAnimation_),
     attributeAnimation_(other.attributeAnimation_),
+    wrapMode_(other.wrapMode_),
     speed_(other.speed_),
     speed_(other.speed_),
     currentTime_(0.0f),
     currentTime_(0.0f),
     lastScaledTime_(0.0f)
     lastScaledTime_(0.0f)
@@ -68,7 +70,7 @@ bool AttributeAnimationInstance::Update(float timeStep)
         return true;
         return true;
 
 
     bool finished = false;
     bool finished = false;
-    float scaledTime = attributeAnimation_->CalculateScaledTime(currentTime_, finished);
+    float scaledTime = CalculateScaledTime(currentTime_, finished);
 
 
     for (unsigned i = 1; i < keyFrames.Size(); ++i)
     for (unsigned i = 1; i < keyFrames.Size(); ++i)
     {
     {
@@ -87,7 +89,7 @@ bool AttributeAnimationInstance::Update(float timeStep)
     if (attributeAnimation_->HasEventFrames())
     if (attributeAnimation_->HasEventFrames())
     {
     {
         Vector<const AttributeEventFrame*> eventFrames;
         Vector<const AttributeEventFrame*> eventFrames;
-        switch (attributeAnimation_->GetWrapMode())
+        switch (wrapMode_)
         {
         {
         case WM_LOOP:
         case WM_LOOP:
             if (lastScaledTime_ < scaledTime)
             if (lastScaledTime_ < scaledTime)
@@ -124,6 +126,29 @@ AttributeAnimation* AttributeAnimationInstance::GetAttributeAnimation() const
     return attributeAnimation_;
     return attributeAnimation_;
 }
 }
 
 
+float AttributeAnimationInstance::CalculateScaledTime(float currentTime, bool& finished) const
+{
+    float beginTime = attributeAnimation_->GetBeginTime();
+    float endTime = attributeAnimation_->GetEndTime();
+
+    switch (wrapMode_)
+    {
+    case WM_LOOP:
+        {
+            float span = endTime - beginTime;
+            return beginTime + fmodf(currentTime - beginTime, span);
+        }
+
+    case WM_ONCE:
+        finished = (currentTime >= endTime);
+
+    case WM_CLAMP:
+        return Clamp(currentTime, beginTime, endTime);
+    }
+
+    return beginTime;
+}
+
 Variant AttributeAnimationInstance::Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const
 Variant AttributeAnimationInstance::Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const
 {
 {
     float factor = (scaledTime - prevKeyFrame.time_) / (currKeyFrame.time_ - prevKeyFrame.time_);
     float factor = (scaledTime - prevKeyFrame.time_) / (currKeyFrame.time_ - prevKeyFrame.time_);

+ 10 - 1
Source/Engine/Scene/AttributeAnimationInstance.h

@@ -23,6 +23,7 @@
 #pragma once
 #pragma once
 
 
 #include "RefCounted.h"
 #include "RefCounted.h"
+#include "ObjectAnimation.h"
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
@@ -36,7 +37,7 @@ class URHO3D_API AttributeAnimationInstance : public RefCounted
 {
 {
 public:
 public:
     /// Construct.
     /// Construct.
-    AttributeAnimationInstance(Animatable* animatable, const AttributeInfo& attributeInfo, AttributeAnimation* attributeAnimation, float speed);
+    AttributeAnimationInstance(Animatable* animatable, const AttributeInfo& attributeInfo, AttributeAnimation* attributeAnimation, WrapMode wrapMode, float speed);
     /// Construct.
     /// Construct.
     AttributeAnimationInstance(const AttributeAnimationInstance& other);
     AttributeAnimationInstance(const AttributeAnimationInstance& other);
     /// Destruct.
     /// Destruct.
@@ -44,6 +45,8 @@ public:
 
 
     /// Update (if animaiton finished return true).
     /// Update (if animaiton finished return true).
     bool Update(float timeStep);
     bool Update(float timeStep);
+    /// Set wrap mode.
+    void SetWrapMode(WrapMode wrapMode) { wrapMode_ = wrapMode; }
     /// Set speed.
     /// Set speed.
     void SetSpeed(float speed) { speed_ = speed; }
     void SetSpeed(float speed) { speed_ = speed; }
     /// Return animatable.
     /// Return animatable.
@@ -52,12 +55,16 @@ public:
     const AttributeInfo& GetAttributeInfo() const { return attributeInfo_; }
     const AttributeInfo& GetAttributeInfo() const { return attributeInfo_; }
     /// Return attribute animation.
     /// Return attribute animation.
     AttributeAnimation* GetAttributeAnimation() const;
     AttributeAnimation* GetAttributeAnimation() const;
+    /// Return wrap mode.
+    WrapMode GetWrapMode() const { return wrapMode_; }
     /// Return speed.
     /// Return speed.
     float GetSpeed() const { return speed_; }
     float GetSpeed() const { return speed_; }
     /// Return current time.
     /// Return current time.
     float GetCurrentTime() const { return currentTime_; }
     float GetCurrentTime() const { return currentTime_; }
 
 
 protected:
 protected:
+    /// Calculate scaled time.
+    float CalculateScaledTime(float currentTime, bool& finished) const;
     /// Interpolation.
     /// Interpolation.
     Variant Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const;
     Variant Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const;
 
 
@@ -67,6 +74,8 @@ protected:
     const AttributeInfo& attributeInfo_;
     const AttributeInfo& attributeInfo_;
     /// Attribute animation.
     /// Attribute animation.
     SharedPtr<AttributeAnimation> attributeAnimation_;
     SharedPtr<AttributeAnimation> attributeAnimation_;
+    /// Wrap mode.
+    WrapMode wrapMode_;
     /// Speed.
     /// Speed.
     float speed_;
     float speed_;
     /// Current time.
     /// Current time.

+ 35 - 3
Source/Engine/Scene/ObjectAnimation.cpp

@@ -31,6 +31,14 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* wrapModeNames[] = 
+{
+    "Loop",
+    "Once",
+    "Clamp",
+    0
+};
+
 ObjectAnimation::ObjectAnimation(Context* context) :
 ObjectAnimation::ObjectAnimation(Context* context) :
     Resource(context)
     Resource(context)
 {
 {
@@ -74,13 +82,24 @@ bool ObjectAnimation::LoadXML(const XMLElement& source)
     while (animElem)
     while (animElem)
     {
     {
         String name = animElem.GetAttribute("name");
         String name = animElem.GetAttribute("name");
-
+        
         SharedPtr<AttributeAnimation> animation(new AttributeAnimation(context_));
         SharedPtr<AttributeAnimation> animation(new AttributeAnimation(context_));
         if (!animation->LoadXML(animElem))
         if (!animation->LoadXML(animElem))
             return false;
             return false;
 
 
+        String wrapModeString = source.GetAttribute("wrapMode");
+        WrapMode wrapMode = WM_LOOP;
+        for (int i = 0; i <= WM_CLAMP; ++i)
+        {
+            if (wrapModeString == wrapModeNames[i])
+            {
+                wrapMode = (WrapMode)i;
+                break;
+            }
+        }
+
         float speed = animElem.GetFloat("speed");
         float speed = animElem.GetFloat("speed");
-        AddAttributeAnimation(name, animation, speed);
+        AddAttributeAnimation(name, animation, wrapMode, speed);
 
 
         animElem = animElem.GetNext("attributeAnimation");
         animElem = animElem.GetNext("attributeAnimation");
     }
     }
@@ -98,19 +117,21 @@ bool ObjectAnimation::SaveXML(XMLElement& dest) const
         if (!i->second_->SaveXML(animElem))
         if (!i->second_->SaveXML(animElem))
             return false;
             return false;
 
 
+        animElem.SetAttribute("wrapMode", wrapModeNames[GetAttributeAnimationWrapMode(i->first_)]);
         animElem.SetFloat("speed", GetAttributeAnimationSpeed(i->first_));
         animElem.SetFloat("speed", GetAttributeAnimationSpeed(i->first_));
     }
     }
 
 
     return true;
     return true;
 }
 }
 
 
-void ObjectAnimation::AddAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, float speed)
+void ObjectAnimation::AddAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, WrapMode wrapMode, float speed)
 {
 {
     if (!attributeAnimation)
     if (!attributeAnimation)
         return;
         return;
 
 
     attributeAnimation->SetObjectAnimation(this);
     attributeAnimation->SetObjectAnimation(this);
     attributeAnimations_[name] = attributeAnimation;
     attributeAnimations_[name] = attributeAnimation;
+    attributeAnimationWrapModes_[name] = wrapMode;
     attributeAnimationSpeeds_[name] = speed;
     attributeAnimationSpeeds_[name] = speed;
 }
 }
 
 
@@ -138,7 +159,10 @@ void ObjectAnimation::RemoveAttributeAnimation(AttributeAnimation* attributeAnim
     }
     }
 
 
     if (!name.Empty())
     if (!name.Empty())
+    {
+        attributeAnimationWrapModes_.Erase(name);
         attributeAnimationSpeeds_.Erase(name);
         attributeAnimationSpeeds_.Erase(name);
+    }
 }
 }
 
 
 AttributeAnimation* ObjectAnimation::GetAttributeAnimation(const String& name) const
 AttributeAnimation* ObjectAnimation::GetAttributeAnimation(const String& name) const
@@ -149,6 +173,14 @@ AttributeAnimation* ObjectAnimation::GetAttributeAnimation(const String& name) c
     return 0;
     return 0;
 }
 }
 
 
+WrapMode ObjectAnimation::GetAttributeAnimationWrapMode(const String& name) const
+{
+    HashMap<String, WrapMode>::ConstIterator i = attributeAnimationWrapModes_.Find(name);
+    if (i != attributeAnimationWrapModes_.End())
+        return i->second_;
+    return WM_LOOP;
+}
+
 float ObjectAnimation::GetAttributeAnimationSpeed(const String& name) const
 float ObjectAnimation::GetAttributeAnimationSpeed(const String& name) const
 {
 {
     HashMap<String, float>::ConstIterator i = attributeAnimationSpeeds_.Find(name);
     HashMap<String, float>::ConstIterator i = attributeAnimationSpeeds_.Find(name);

+ 16 - 1
Source/Engine/Scene/ObjectAnimation.h

@@ -29,6 +29,17 @@ namespace Urho3D
 
 
 class AttributeAnimation;
 class AttributeAnimation;
 
 
+/// Animation wrap mode.
+enum WrapMode
+{
+    /// Loop mode.
+    WM_LOOP = 0,
+    /// Play once then remove.
+    WM_ONCE,
+    /// Clamp mode.
+    WM_CLAMP,
+};
+
 /// Object animation class.
 /// Object animation class.
 class URHO3D_API ObjectAnimation : public Resource
 class URHO3D_API ObjectAnimation : public Resource
 {
 {
@@ -52,7 +63,7 @@ public:
     bool SaveXML(XMLElement& dest) const;
     bool SaveXML(XMLElement& dest) const;
 
 
     /// Add attribute animation.
     /// Add attribute animation.
-    void AddAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, float speed = 1.0f);
+    void AddAttributeAnimation(const String& name, AttributeAnimation* attributeAnimation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
     /// Remove attribute animation.
     /// Remove attribute animation.
     void RemoveAttributeAnimation(const String& name);
     void RemoveAttributeAnimation(const String& name);
     /// Remove attribute animation.
     /// Remove attribute animation.
@@ -60,6 +71,8 @@ public:
 
 
     /// Return attribute animation by name.
     /// Return attribute animation by name.
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
     AttributeAnimation* GetAttributeAnimation(const String& name) const;
+    /// Return attribute animation wrap mode by name.
+    WrapMode GetAttributeAnimationWrapMode(const String& name) const;
     /// Return attribute animation speed by name.
     /// Return attribute animation speed by name.
     float GetAttributeAnimationSpeed(const String& name) const;
     float GetAttributeAnimationSpeed(const String& name) const;
     /// Return all attribute animations.
     /// Return all attribute animations.
@@ -68,6 +81,8 @@ public:
 private:
 private:
     /// Name to attribute animation mapping.
     /// Name to attribute animation mapping.
     HashMap<String, SharedPtr<AttributeAnimation> > attributeAnimations_;
     HashMap<String, SharedPtr<AttributeAnimation> > attributeAnimations_;
+    /// Name to attribute animation wrap mode mapping.
+    HashMap<String, WrapMode> attributeAnimationWrapModes_;
     /// Name to attribute animation speed mapping.
     /// Name to attribute animation speed mapping.
     HashMap<String, float> attributeAnimationSpeeds_;
     HashMap<String, float> attributeAnimationSpeeds_;
 };
 };

+ 3 - 1
Source/Engine/Script/APITemplates.h

@@ -457,8 +457,10 @@ template <class T> void RegisterAnimatable(asIScriptEngine* engine, const char*
     engine->RegisterObjectMethod(className, "bool get_animationEnabled() const", asMETHODPR(T, GetAnimationEnabled, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_animationEnabled() const", asMETHODPR(T, GetAnimationEnabled, () const, bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_objectAnimation(ObjectAnimation@+)", asMETHODPR(T, SetObjectAnimation, (ObjectAnimation*), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_objectAnimation(ObjectAnimation@+)", asMETHODPR(T, SetObjectAnimation, (ObjectAnimation*), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "ObjectAnimation@+ get_objectAnimation() const", asMETHODPR(T, GetObjectAnimation, () const, ObjectAnimation*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "ObjectAnimation@+ get_objectAnimation() const", asMETHODPR(T, GetObjectAnimation, () const, ObjectAnimation*), asCALL_THISCALL);
-    engine->RegisterObjectMethod(className, "void SetAttributeAnimation(const String&in, AttributeAnimation@+, float speed=1.0f)", asMETHODPR(T, SetAttributeAnimation, (const String&, AttributeAnimation*, float), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void SetAttributeAnimation(const String&in, AttributeAnimation@+, WrapMode wrapMode=WM_LOOP, float speed=1.0f)", asMETHODPR(T, SetAttributeAnimation, (const String&, AttributeAnimation*, WrapMode, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHODPR(T, GetAttributeAnimation, (const String&) const, AttributeAnimation*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHODPR(T, GetAttributeAnimation, (const String&) const, AttributeAnimation*), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void SetAttributeAnimationWrapMode(const String&in, WrapMode)", asMETHODPR(T, SetAttributeAnimationWrapMode, (const String&, WrapMode), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "WrapMode GetAttributeAnimationWrapMode(const String&in) const", asMETHODPR(T, GetAttributeAnimationWrapMode, (const String&) const, WrapMode), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetAttributeAnimationSpeed(const String&in, float)", asMETHODPR(T, SetAttributeAnimationSpeed, (const String&, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetAttributeAnimationSpeed(const String&in, float)", asMETHODPR(T, SetAttributeAnimationSpeed, (const String&, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "float GetAttributeAnimationSpeed(const String&in) const", asMETHODPR(T, GetAttributeAnimationSpeed, (const String&) const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "float GetAttributeAnimationSpeed(const String&in) const", asMETHODPR(T, GetAttributeAnimationSpeed, (const String&) const, float), asCALL_THISCALL);
 }
 }

+ 7 - 8
Source/Engine/Script/SceneAPI.cpp

@@ -37,14 +37,7 @@ namespace Urho3D
 
 
 static void RegisterAttributeAnimation(asIScriptEngine* engine)
 static void RegisterAttributeAnimation(asIScriptEngine* engine)
 {
 {
-    engine->RegisterEnum("WrapMode");
-    engine->RegisterEnumValue("WrapMode", "WM_LOOP", WM_LOOP);
-    engine->RegisterEnumValue("WrapMode", "WM_ONCE", WM_ONCE);
-    engine->RegisterEnumValue("WrapMode", "WM_CLAMP", WM_CLAMP);
-
     RegisterResource<AttributeAnimation>(engine, "AttributeAnimation");
     RegisterResource<AttributeAnimation>(engine, "AttributeAnimation");
-    engine->RegisterObjectMethod("AttributeAnimation", "void set_wrapMode(WrapMode)", asMETHOD(AttributeAnimation, SetWrapMode), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AttributeAnimation", "WrapMode get_wrapMode() const", asMETHOD(AttributeAnimation, GetWrapMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "void set_valueType(VariantType)", asMETHOD(AttributeAnimation, SetValueType), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "void set_valueType(VariantType)", asMETHOD(AttributeAnimation, SetValueType), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "VariantType get_valueType() const", asMETHOD(AttributeAnimation, GetValueType), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "VariantType get_valueType() const", asMETHOD(AttributeAnimation, GetValueType), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "void SetKeyFrame(float, const Variant&)", asMETHOD(AttributeAnimation, SetKeyFrame), asCALL_THISCALL);
     engine->RegisterObjectMethod("AttributeAnimation", "void SetKeyFrame(float, const Variant&)", asMETHOD(AttributeAnimation, SetKeyFrame), asCALL_THISCALL);
@@ -53,11 +46,17 @@ static void RegisterAttributeAnimation(asIScriptEngine* engine)
 
 
 static void RegisterObjectAnimation(asIScriptEngine* engine)
 static void RegisterObjectAnimation(asIScriptEngine* engine)
 {
 {
+    engine->RegisterEnum("WrapMode");
+    engine->RegisterEnumValue("WrapMode", "WM_LOOP", WM_LOOP);
+    engine->RegisterEnumValue("WrapMode", "WM_ONCE", WM_ONCE);
+    engine->RegisterEnumValue("WrapMode", "WM_CLAMP", WM_CLAMP);
+
     RegisterResource<ObjectAnimation>(engine, "ObjectAnimation");
     RegisterResource<ObjectAnimation>(engine, "ObjectAnimation");
-    engine->RegisterObjectMethod("ObjectAnimation", "void AddAttributeAnimation(const String&, AttributeAnimation@+, float speed=1.0f)", asMETHOD(ObjectAnimation, AddAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "void AddAttributeAnimation(const String&, AttributeAnimation@+, WrapMode wrapMode=WM_LOOP, float speed=1.0f)", asMETHOD(ObjectAnimation, AddAttributeAnimation), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "void RemoveAttributeAnimation(const String&)", asMETHODPR(ObjectAnimation, RemoveAttributeAnimation, (const String&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "void RemoveAttributeAnimation(const String&)", asMETHODPR(ObjectAnimation, RemoveAttributeAnimation, (const String&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "void RemoveAttributeAnimation(AttributeAnimation@+)", asMETHODPR(ObjectAnimation, RemoveAttributeAnimation, (AttributeAnimation*), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "void RemoveAttributeAnimation(AttributeAnimation@+)", asMETHODPR(ObjectAnimation, RemoveAttributeAnimation, (AttributeAnimation*), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHODPR(ObjectAnimation, GetAttributeAnimation, (const String&) const, AttributeAnimation*), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHODPR(ObjectAnimation, GetAttributeAnimation, (const String&) const, AttributeAnimation*), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "WrapMode GetAttributeAnimationWrapMode(const String&in) const", asMETHODPR(ObjectAnimation, GetAttributeAnimationWrapMode, (const String&) const, WrapMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "float GetAttributeAnimationSpeed(const String&in) const", asMETHODPR(ObjectAnimation, GetAttributeAnimationSpeed, (const String&) const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod("ObjectAnimation", "float GetAttributeAnimationSpeed(const String&in) const", asMETHODPR(ObjectAnimation, GetAttributeAnimationSpeed, (const String&) const, float), asCALL_THISCALL);
 }
 }