ソースを参照

Refactor AttributeAnimation, make IntVector2 and IntRect interpolatable.

aster2013 11 年 前
コミット
802af0c21b

+ 61 - 4
Source/Engine/Scene/AttributeAnimation.cpp

@@ -21,10 +21,12 @@
 //
 
 #include "Precompiled.h"
+#include "Animatable.h"
 #include "AttributeAnimation.h"
 #include "Context.h"
-#include "ObjectAnimation.h"
 #include "Deserializer.h"
+#include "Log.h"
+#include "ObjectAnimation.h"
 #include "Serializer.h"
 #include "XMLFile.h"
 
@@ -133,9 +135,8 @@ void AttributeAnimation::SetValueType(VariantType valueType)
         return;
 
     valueType_ = valueType;
-
-    isInterpolatable_ = (valueType_ == VAR_FLOAT) || (valueType_ == VAR_VECTOR2) || (valueType_ == VAR_VECTOR3) || 
-        (valueType_ == VAR_VECTOR4) || (valueType_ == VAR_QUATERNION) || (valueType_ == VAR_COLOR);
+    isInterpolatable_ = (valueType_ == VAR_FLOAT) || (valueType_ == VAR_VECTOR2) || (valueType_ == VAR_VECTOR3) || (valueType_ == VAR_VECTOR4) || 
+        (valueType_ == VAR_QUATERNION) || (valueType_ == VAR_COLOR) || (valueType_ == VAR_INTRECT) || (valueType_ == VAR_INTVECTOR2);
 
     keyFrames_.Clear();
     beginTime_ = M_INFINITY;
@@ -200,6 +201,21 @@ ObjectAnimation* AttributeAnimation::GetObjectAnimation() const
     return objectAnimation_;
 }
 
+void AttributeAnimation::UpdateAttributeValue(Animatable* animatable, const AttributeInfo& attributeInfo, float scaledTime) const
+{
+    unsigned index = 1;
+    for (; index < keyFrames_.Size(); ++index)
+    {
+        if (scaledTime < keyFrames_[index].time_)
+            break;
+    }
+
+    if (index >= keyFrames_.Size() || !isInterpolatable_)
+        animatable->OnSetAttribute(attributeInfo, keyFrames_[index - 1].value_);
+    else
+        animatable->OnSetAttribute(attributeInfo, LinearInterpolation(index - 1, index, scaledTime));
+}
+
 void AttributeAnimation::GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const
 {
     for (unsigned i = 0; i < eventFrames_.Size(); ++i)
@@ -213,4 +229,45 @@ void AttributeAnimation::GetEventFrames(float beginTime, float endTime, Vector<c
     }
 }
 
+Variant AttributeAnimation::LinearInterpolation(unsigned index1, unsigned index2, float scaledTime) const
+{
+    const AttributeKeyFrame& keyFrame1 = keyFrames_[index1];
+    const AttributeKeyFrame& keyFrame2 = keyFrames_[index2];
+
+    float t = (scaledTime - keyFrame1.time_) / (keyFrame2.time_ - keyFrame1.time_);
+
+    switch (valueType_)
+    {
+    case VAR_FLOAT:
+        return Lerp(keyFrame1.value_.GetFloat(), keyFrame2.value_.GetFloat(), t);
+    case VAR_VECTOR2:
+        return keyFrame1.value_.GetVector2().Lerp(keyFrame2.value_.GetVector2(), t);
+    case VAR_VECTOR3:
+        return keyFrame1.value_.GetVector3().Lerp(keyFrame2.value_.GetVector3(), t);
+    case VAR_VECTOR4:
+        return keyFrame1.value_.GetVector4().Lerp(keyFrame2.value_.GetVector4(), t);
+    case VAR_QUATERNION:
+        return keyFrame1.value_.GetQuaternion().Slerp(keyFrame2.value_.GetQuaternion(), t);
+    case VAR_COLOR:
+        return keyFrame1.value_.GetColor().Lerp(keyFrame2.value_.GetColor(), t);
+    case VAR_INTRECT:
+        {
+            float s = 1.0f - t;
+            const IntRect& r1 = keyFrame1.value_.GetIntRect();
+            const IntRect& r2 = keyFrame2.value_.GetIntRect();
+            return IntRect((int)(r1.left_ * s + r2.left_ * t), (int)(r1.top_ * s + r2.top_ * t), (int)(r1.right_ * s + r2.right_ * t), (int)(r1.bottom_ * s + r2.bottom_ * t));
+        }
+    case VAR_INTVECTOR2:
+        {
+            float s = 1.0f - t;
+            const IntVector2& v1 = keyFrame1.value_.GetIntVector2();
+            const IntVector2& v2 = keyFrame2.value_.GetIntVector2();
+            return IntVector2((int)(v1.x_ * s + v2.x_ * t), (int)(v1.y_ * s + v2.y_ * t));
+        }
+    }
+
+    LOGERROR("Invalid value type for linear interpolation");
+    return Variant::EMPTY;
+}
+
 }

+ 10 - 4
Source/Engine/Scene/AttributeAnimation.h

@@ -28,8 +28,10 @@
 namespace Urho3D
 {
 
+class Animatable;
 class ObjectAnimation;
 class XMLElement;
+struct AttributeInfo;
 
 /// Attribute key frame
 struct AttributeKeyFrame
@@ -77,29 +79,33 @@ public:
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     /// Set value type.
     void SetValueType(VariantType valueType);
+    
     /// Set key frame.
     bool SetKeyFrame(float time, const Variant& value);
     /// Set event frame.
     void SetEventFrame(float time, const StringHash& eventType, const VariantMap& eventData = VariantMap());
 
+    /// Return animation is valid.
+    bool IsValid() const { return keyFrames_.Size() > 1; }
     /// Return object animation.
     ObjectAnimation* GetObjectAnimation() const;
     /// Return value type.
     VariantType GetValueType() const { return valueType_; }
-    /// Is interpolatable.
-    bool IsInterpolatable() const { return isInterpolatable_; }
     /// Return begin time.
     float GetBeginTime() const { return beginTime_; }
     /// Return end time.
     float GetEndTime() const { return endTime_; }
-    /// Return all key frames.
-    const Vector<AttributeKeyFrame>& GetKeyFrames() const { return keyFrames_; }
+    /// Update object's attribute value.
+    void UpdateAttributeValue(Animatable* animatable, const AttributeInfo& attributeInfo, float scaledTime) const;
     /// Has event frames.
     bool HasEventFrames() const { return eventFrames_.Size() != 0; }
     /// Return all event frames between time.
     void GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const;
 
 protected:
+    /// Linear interpolation.
+    Variant LinearInterpolation(unsigned index1, unsigned index2, float scaledTime) const;
+
     /// Object animation.
     WeakPtr<ObjectAnimation> objectAnimation_;
     /// Value type.

+ 27 - 42
Source/Engine/Scene/AttributeAnimationInstance.cpp

@@ -60,29 +60,14 @@ bool AttributeAnimationInstance::Update(float timeStep)
     
     currentTime_ += timeStep * speed_;
     
-    const Vector<AttributeKeyFrame>& keyFrames = attributeAnimation_->GetKeyFrames();
-    if (keyFrames.Size() < 2)
+    if (!attributeAnimation_->IsValid())
         return true;
 
     bool finished = false;
+    // Calculate scale time by wrap mode
     float scaledTime = CalculateScaledTime(currentTime_, finished);
 
-    unsigned index = 1;
-    for (; index < keyFrames.Size(); ++index)
-    {
-        const AttributeKeyFrame& currKeyFrame = keyFrames[index];
-        if (scaledTime < currKeyFrame.time_)
-            break;
-    }
-
-    const AttributeKeyFrame& prevKeyFrame = keyFrames[index - 1];
-    if (index >= keyFrames.Size() || !attributeAnimation_->IsInterpolatable())
-        animatable_->OnSetAttribute(attributeInfo_, prevKeyFrame.value_);
-    else
-    {
-        const AttributeKeyFrame& currKeyFrame = keyFrames[index];
-        animatable_->OnSetAttribute(attributeInfo_, Interpolation(prevKeyFrame, currKeyFrame, scaledTime));
-    }
+    attributeAnimation_->UpdateAttributeValue(animatable_, attributeInfo_, scaledTime);
 
     if (attributeAnimation_->HasEventFrames())
     {
@@ -142,29 +127,29 @@ float AttributeAnimationInstance::CalculateScaledTime(float currentTime, bool& f
     return beginTime;
 }
 
-Variant AttributeAnimationInstance::Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const
-{
-    float factor = (scaledTime - prevKeyFrame.time_) / (currKeyFrame.time_ - prevKeyFrame.time_);
-
-    switch (attributeAnimation_->GetValueType())
-    {
-    case VAR_FLOAT:
-        return Lerp(prevKeyFrame.value_.GetFloat(), currKeyFrame.value_.GetFloat(), factor);
-    case VAR_VECTOR2:
-        return prevKeyFrame.value_.GetVector2().Lerp(currKeyFrame.value_.GetVector2(), factor);
-    case VAR_VECTOR3:
-        return prevKeyFrame.value_.GetVector3().Lerp(currKeyFrame.value_.GetVector3(), factor);
-    case VAR_VECTOR4:
-        return prevKeyFrame.value_.GetVector4().Lerp(currKeyFrame.value_.GetVector4(), factor);
-    case VAR_QUATERNION:
-        return prevKeyFrame.value_.GetQuaternion().Slerp(currKeyFrame.value_.GetQuaternion(), factor);
-    case VAR_COLOR:
-        return prevKeyFrame.value_.GetColor().Lerp(currKeyFrame.value_.GetColor(), factor);
-    }
-
-    LOGERROR("value type");
-
-    return Variant::EMPTY;
-}
+//Variant AttributeAnimationInstance::Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const
+//{
+//    float factor = (scaledTime - prevKeyFrame.time_) / (currKeyFrame.time_ - prevKeyFrame.time_);
+//
+//    switch (attributeAnimation_->GetValueType())
+//    {
+//    case VAR_FLOAT:
+//        return Lerp(prevKeyFrame.value_.GetFloat(), currKeyFrame.value_.GetFloat(), factor);
+//    case VAR_VECTOR2:
+//        return prevKeyFrame.value_.GetVector2().Lerp(currKeyFrame.value_.GetVector2(), factor);
+//    case VAR_VECTOR3:
+//        return prevKeyFrame.value_.GetVector3().Lerp(currKeyFrame.value_.GetVector3(), factor);
+//    case VAR_VECTOR4:
+//        return prevKeyFrame.value_.GetVector4().Lerp(currKeyFrame.value_.GetVector4(), factor);
+//    case VAR_QUATERNION:
+//        return prevKeyFrame.value_.GetQuaternion().Slerp(currKeyFrame.value_.GetQuaternion(), factor);
+//    case VAR_COLOR:
+//        return prevKeyFrame.value_.GetColor().Lerp(currKeyFrame.value_.GetColor(), factor);
+//    }
+//
+//    LOGERROR("value type");
+//
+//    return Variant::EMPTY;
+//}
 
 }

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

@@ -54,7 +54,7 @@ private:
     /// Calculate scaled time.
     float CalculateScaledTime(float currentTime, bool& finished) const;
     /// Interpolation.
-    Variant Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const;
+    // Variant Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const;
 
     /// Animatable.
     WeakPtr<Animatable> animatable_;