소스 검색

Minor refactoring on attribute animation classes.

Yao Wei Tjong 姚伟忠 11 년 전
부모
커밋
57d6c7827b

+ 2 - 27
Source/Engine/Scene/Animatable.cpp

@@ -130,11 +130,6 @@ bool Animatable::SaveXML(XMLElement& dest) const
     return true;
 }
 
-void Animatable::SetAnimationEnabled(bool animationEnabled)
-{
-    animationEnabled_ = animationEnabled;
-}
-
 void Animatable::SetObjectAnimation(ObjectAnimation* objectAnimation)
 {
     if (objectAnimation == objectAnimation_)
@@ -200,17 +195,7 @@ void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* a
 
         // Add network attribute to set
         if (attributeInfo->mode_ & AM_NET)
-        {
-            const Vector<AttributeInfo>* networkAttributes = GetNetworkAttributes();
-            for (Vector<AttributeInfo>::ConstIterator i = networkAttributes->Begin(); i != networkAttributes->End(); ++i)
-            {
-                if (name == (*i).name_)
-                {
-                    animatedNetworkAttributes_.Insert(&(*i));
-                    break;
-                }
-            }
-        }
+            animatedNetworkAttributes_.Insert(attributeInfo);
 
         attributeAnimationInstances_[name] = new AttributeAnimationInstance(this, *attributeInfo, attributeAnimation, wrapMode, speed);
 
@@ -224,17 +209,7 @@ void Animatable::SetAttributeAnimation(const String& name, AttributeAnimation* a
 
         // Remove network attribute from set
         if (currentInstance->GetAttributeInfo().mode_ & AM_NET)
-        {
-            const Vector<AttributeInfo>* networkAttributes = GetNetworkAttributes();
-            for (Vector<AttributeInfo>::ConstIterator i = networkAttributes->Begin(); i != networkAttributes->End(); ++i)
-            {
-                if (name == (*i).name_)
-                {
-                    animatedNetworkAttributes_.Erase(&(*i));
-                    break;
-                }
-            }
-        }
+            animatedNetworkAttributes_.Erase(&currentInstance->GetAttributeInfo());
 
         attributeAnimationInstances_.Erase(name);
         OnAttributeAnimationRemoved();

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

@@ -52,7 +52,7 @@ public:
     virtual bool SaveXML(XMLElement& dest) const;
 
     /// Set animation enabled.
-    void SetAnimationEnabled(bool enable);
+    void SetAnimationEnabled(bool enable) { animationEnabled_ = enable; }
     /// Set object animation.
     void SetObjectAnimation(ObjectAnimation* objectAnimation);
     /// Set attribute animation.

+ 34 - 33
Source/Engine/Scene/AttributeAnimation.cpp

@@ -47,7 +47,7 @@ AttributeAnimation::AttributeAnimation(Context* context) :
     interpolationMethod_(IM_LINEAR),
     splineTension_(0.5f),
     valueType_(VAR_NONE),
-    isInterpolatable_(false),
+    interpolatable_(false),
     beginTime_(M_INFINITY),
     endTime_(-M_INFINITY),
     splineTangentsDirty_(false)
@@ -103,14 +103,14 @@ bool AttributeAnimation::LoadXML(const XMLElement& source)
     if (interpolationMethod_ == IM_SPLINE)
         splineTension_ = source.GetFloat("splinetension");
 
-    XMLElement keyFrameEleme = source.GetChild("keyframe");
-    while (keyFrameEleme)
+    XMLElement keyFrameElem = source.GetChild("keyframe");
+    while (keyFrameElem)
     {
-        float time = keyFrameEleme.GetFloat("time");
-        Variant value = keyFrameEleme.GetVariant();
+        float time = keyFrameElem.GetFloat("time");
+        Variant value = keyFrameElem.GetVariant();
         SetKeyFrame(time, value);
 
-        keyFrameEleme = keyFrameEleme.GetNext("keyframe");
+        keyFrameElem = keyFrameElem.GetNext("keyframe");
     }
 
     XMLElement eventFrameElem = source.GetChild("eventframe");
@@ -153,32 +153,33 @@ bool AttributeAnimation::SaveXML(XMLElement& dest) const
     return true;
 }
 
-void AttributeAnimation::SetObjectAnimation(ObjectAnimation* objectAnimation)
-{
-    objectAnimation_ = objectAnimation;
-}
-
 void AttributeAnimation::SetValueType(VariantType valueType)
 {
     if (valueType == valueType_)
         return;
 
     valueType_ = valueType;
-    isInterpolatable_ = (valueType_ == VAR_FLOAT) || (valueType_ == VAR_VECTOR2) || (valueType_ == VAR_VECTOR3) || (valueType_ == VAR_VECTOR4) || 
+    interpolatable_ = (valueType_ == VAR_FLOAT) || (valueType_ == VAR_VECTOR2) || (valueType_ == VAR_VECTOR3) || (valueType_ == VAR_VECTOR4) ||
         (valueType_ == VAR_QUATERNION) || (valueType_ == VAR_COLOR);
 
     if ((valueType_ == VAR_INTRECT) || (valueType_ == VAR_INTVECTOR2))
     {
-        isInterpolatable_ = true;
+        interpolatable_ = true;
         // Force linear interpolation for IntRect and IntVector2
         interpolationMethod_ = IM_LINEAR;
     }
 
     keyFrames_.Clear();
+    eventFrames_.Clear();
     beginTime_ = M_INFINITY;
     endTime_ = -M_INFINITY;
 }
 
+void AttributeAnimation::SetObjectAnimation(ObjectAnimation* objectAnimation)
+{
+    objectAnimation_ = objectAnimation;
+}
+
 void AttributeAnimation::SetInterpolationMethod(InterpMethod method)
 {
     if (method == interpolationMethod_)
@@ -205,19 +206,19 @@ bool AttributeAnimation::SetKeyFrame(float time, const Variant& value)
     else if (value.GetType() != valueType_)
         return false;
 
-    beginTime_ = Min(time, beginTime_);
-    endTime_ = Max(time, endTime_);
-
     AttributeKeyFrame keyFrame;
     keyFrame.time_ = time;
     keyFrame.value_ = value;
 
-    if (keyFrames_.Empty() || time >= keyFrames_.Back().time_)
+    if (keyFrames_.Empty() || time > keyFrames_.Back().time_)
         keyFrames_.Push(keyFrame);
     else
     {
         for (unsigned i = 0; i < keyFrames_.Size(); ++i)
         {
+            // Guard against interpolation error caused by division by error due to 0 delta time between two key frames
+            if (time == keyFrames_[i].time_)
+                return false;
             if (time < keyFrames_[i].time_)
             {
                 keyFrames_.Insert(i, keyFrame);
@@ -226,6 +227,8 @@ bool AttributeAnimation::SetKeyFrame(float time, const Variant& value)
         }
     }
 
+    beginTime_ = Min(time, beginTime_);
+    endTime_ = Max(time, endTime_);
     splineTangentsDirty_ = true;
 
     return true;
@@ -258,11 +261,6 @@ bool AttributeAnimation::IsValid() const
     return (interpolationMethod_ == IM_LINEAR && keyFrames_.Size() > 1) || (interpolationMethod_ == IM_SPLINE && keyFrames_.Size() > 2);
 }
 
-ObjectAnimation* AttributeAnimation::GetObjectAnimation() const
-{
-    return objectAnimation_;
-}
-
 void AttributeAnimation::UpdateAttributeValue(Animatable* animatable, const AttributeInfo& attributeInfo, float scaledTime)
 {
     unsigned index = 1;
@@ -272,7 +270,7 @@ void AttributeAnimation::UpdateAttributeValue(Animatable* animatable, const Attr
             break;
     }
 
-    if (index >= keyFrames_.Size() || !isInterpolatable_)
+    if (index >= keyFrames_.Size() || !interpolatable_)
         animatable->OnSetAttribute(attributeInfo, keyFrames_[index - 1].value_);
     else
     {
@@ -283,7 +281,7 @@ void AttributeAnimation::UpdateAttributeValue(Animatable* animatable, const Attr
     }
 }
 
-void AttributeAnimation::GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const
+void AttributeAnimation::GetEventFrames(float beginTime, float endTime, PODVector<const AttributeEventFrame*>& eventFrames) const
 {
     for (unsigned i = 0; i < eventFrames_.Size(); ++i)
     {
@@ -340,10 +338,11 @@ Variant AttributeAnimation::LinearInterpolation(unsigned index1, unsigned index2
             const IntVector2& v2 = value2.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;
+    default:
+        LOGERROR("Invalid value type for linear interpolation");
+        return Variant::EMPTY;
+    }
 }
 
 Variant AttributeAnimation::SplineInterpolation(unsigned index1, unsigned index2, float scaledTime)
@@ -388,10 +387,11 @@ Variant AttributeAnimation::SplineInterpolation(unsigned index1, unsigned index2
 
     case VAR_COLOR:
         return v1.GetColor() * h1 + v2.GetColor() * h2 + t1.GetColor() * h3 + t2.GetColor() * h4;
-    }
 
-    LOGERROR("Invalid value type for spline interpolation");
-    return Variant::EMPTY;
+    default:
+        LOGERROR("Invalid value type for spline interpolation");
+        return Variant::EMPTY;
+    }
 }
 
 void AttributeAnimation::UpdateSplineTangents()
@@ -437,10 +437,11 @@ Variant AttributeAnimation::SubstractAndMultiply(const Variant& value1, const Va
 
     case VAR_COLOR:
         return (value1.GetColor() - value2.GetColor()) * t;
+
+    default:
+        LOGERROR("Invalid value type for spline interpolation's substract and multiply operation");
+        return Variant::EMPTY;
     }
-    
-    LOGERROR("Invalid value type for spline interpolation");
-    return Variant::EMPTY;
 }
 
 }

+ 8 - 8
Source/Engine/Scene/AttributeAnimation.h

@@ -42,7 +42,7 @@ enum InterpMethod
     IM_SPLINE,
 };
 
-/// Attribute key frame
+/// Attribute key frame.
 struct AttributeKeyFrame
 {
     /// Time.
@@ -101,7 +101,7 @@ public:
     /// Return animation is valid.
     bool IsValid() const;
     /// Return object animation.
-    ObjectAnimation* GetObjectAnimation() const;
+    ObjectAnimation* GetObjectAnimation() const { return objectAnimation_; }
     /// Return interpolation method.
     InterpMethod GetInterpolationMethod() const { return interpolationMethod_; }
     /// Return spline tension.
@@ -115,9 +115,9 @@ public:
     /// Update object's attribute value.
     void UpdateAttributeValue(Animatable* animatable, const AttributeInfo& attributeInfo, float scaledTime);
     /// Has event frames.
-    bool HasEventFrames() const { return eventFrames_.Size() != 0; }
+    bool HasEventFrames() const { return !eventFrames_.Empty(); }
     /// Return all event frames between time.
-    void GetEventFrames(float beginTime, float endTime, Vector<const AttributeEventFrame*>& eventFrames) const;
+    void GetEventFrames(float beginTime, float endTime, PODVector<const AttributeEventFrame*>& eventFrames) const;
 
 protected:
     /// Linear interpolation.
@@ -137,20 +137,20 @@ protected:
     float splineTension_;
     /// Value type.
     VariantType valueType_;
-    /// Is interpolatable.
-    bool isInterpolatable_;
+    /// Interpolatable flag.
+    bool interpolatable_;
     /// Begin time.
     float beginTime_;
     /// End time.
     float endTime_;
     /// Key frames.
-    Vector<AttributeKeyFrame> keyFrames_;
+    PODVector<AttributeKeyFrame> keyFrames_;
     /// Spline tangents.
     VariantVector splineTangents_;
     /// Spline tangents dirty.
     bool splineTangentsDirty_;
     /// Event frames.
-    Vector<AttributeEventFrame> eventFrames_;
+    PODVector<AttributeEventFrame> eventFrames_;
 };
 
 }

+ 0 - 5
Source/Engine/Scene/AttributeAnimationInfo.cpp

@@ -48,9 +48,4 @@ AttributeAnimationInfo::~AttributeAnimationInfo()
 {
 }
 
-AttributeAnimation* AttributeAnimationInfo::GetAttributeAnimation() const
-{
-    return attributeAnimation_;
 }
-
-}

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

@@ -47,7 +47,7 @@ public:
     void SetSpeed(float speed) { speed_ = speed; }
 
     /// Return attribute animation.
-    AttributeAnimation* GetAttributeAnimation() const;
+    AttributeAnimation* GetAttributeAnimation() const { return attributeAnimation_; }
     /// Return wrap mode.
     WrapMode GetWrapMode() const { return wrapMode_; }
     /// Return speed.

+ 7 - 34
Source/Engine/Scene/AttributeAnimationInstance.cpp

@@ -71,7 +71,7 @@ bool AttributeAnimationInstance::Update(float timeStep)
 
     if (attributeAnimation_->HasEventFrames())
     {
-        Vector<const AttributeEventFrame*> eventFrames;
+        PODVector<const AttributeEventFrame*> eventFrames;
         switch (wrapMode_)
         {
         case WM_LOOP:
@@ -99,11 +99,6 @@ bool AttributeAnimationInstance::Update(float timeStep)
     return finished;
 }
 
-Animatable* AttributeAnimationInstance::GetAnimatable() const
-{
-    return animatable_;
-}
-
 float AttributeAnimationInstance::CalculateScaledTime(float currentTime, bool& finished) const
 {
     float beginTime = attributeAnimation_->GetBeginTime();
@@ -119,37 +114,15 @@ float AttributeAnimationInstance::CalculateScaledTime(float currentTime, bool& f
 
     case WM_ONCE:
         finished = (currentTime >= endTime);
+        // Fallthrough
 
     case WM_CLAMP:
         return Clamp(currentTime, beginTime, endTime);
-    }
 
-    return beginTime;
+    default:
+        LOGERROR("Unsupported attribute animation wrap mode");
+        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;
-//}
-
-}
+}

+ 3 - 5
Source/Engine/Scene/AttributeAnimationInstance.h

@@ -35,16 +35,16 @@ class URHO3D_API AttributeAnimationInstance : public AttributeAnimationInfo
 public:
     /// Construct.
     AttributeAnimationInstance(Animatable* animatable, const AttributeInfo& attributeInfo, AttributeAnimation* attributeAnimation, WrapMode wrapMode, float speed);
-    /// Construct.
+    /// Copy construct.
     AttributeAnimationInstance(const AttributeAnimationInstance& other);
     /// Destruct.
     ~AttributeAnimationInstance();
 
-    /// Update (if animaiton finished return true).
+    /// Update. Return true when the animation is finished.
     bool Update(float timeStep);
 
     /// Return animatable.
-    Animatable* GetAnimatable() const;
+    Animatable* GetAnimatable() const { return animatable_; }
     /// Return attribute infomation.
     const AttributeInfo& GetAttributeInfo() const { return attributeInfo_; }
     /// Return current time.
@@ -53,8 +53,6 @@ public:
 private:
     /// Calculate scaled time.
     float CalculateScaledTime(float currentTime, bool& finished) const;
-    /// Interpolation.
-    // Variant Interpolation(const AttributeKeyFrame& prevKeyFrame, const AttributeKeyFrame& currKeyFrame, float scaledTime) const;
 
     /// Animatable.
     WeakPtr<Animatable> animatable_;

+ 7 - 2
Source/Engine/Scene/ObjectAnimation.cpp

@@ -32,7 +32,7 @@
 namespace Urho3D
 {
 
-const char* wrapModeNames[] = 
+const char* wrapModeNames[] =
 {
     "Loop",
     "Once",
@@ -137,7 +137,12 @@ void ObjectAnimation::AddAttributeAnimation(const String& name, AttributeAnimati
 
 void ObjectAnimation::RemoveAttributeAnimation(const String& name)
 {
-    RemoveAttributeAnimation(GetAttributeAnimation(name));
+    HashMap<String, SharedPtr<AttributeAnimationInfo> >::Iterator i = attributeAnimationInfos_.Find(name);
+    if (i != attributeAnimationInfos_.End())
+    {
+        i->second_->GetAttributeAnimation()->SetObjectAnimation(0);
+        attributeAnimationInfos_.Erase(i);
+    }
 }
 
 void ObjectAnimation::RemoveAttributeAnimation(AttributeAnimation* attributeAnimation)

+ 10 - 10
Source/Engine/Script/APITemplates.h

@@ -453,16 +453,16 @@ template <class T> void RegisterAnimatable(asIScriptEngine* engine, const char*
     RegisterSerializable<T>(engine, className);
     RegisterSubclass<Animatable, T>(engine, "Animatable", className);
 
-    engine->RegisterObjectMethod(className, "void set_animationEnabled(bool)", asMETHODPR(T, SetAnimationEnabled, (bool), void), 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, "ObjectAnimation@+ get_objectAnimation() const", asMETHODPR(T, GetObjectAnimation, () const, ObjectAnimation*), 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, "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, "float GetAttributeAnimationSpeed(const String&in) const", asMETHODPR(T, GetAttributeAnimationSpeed, (const String&) const, float), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_animationEnabled(bool)", asMETHOD(T, SetAnimationEnabled), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_animationEnabled() const", asMETHOD(T, GetAnimationEnabled), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_objectAnimation(ObjectAnimation@+)", asMETHOD(T, SetObjectAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "ObjectAnimation@+ get_objectAnimation() const", asMETHOD(T, GetObjectAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void SetAttributeAnimation(const String&in, AttributeAnimation@+, WrapMode wrapMode=WM_LOOP, float speed=1.0f)", asMETHOD(T, SetAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHOD(T, GetAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void SetAttributeAnimationWrapMode(const String&in, WrapMode)", asMETHOD(T, SetAttributeAnimationWrapMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "WrapMode GetAttributeAnimationWrapMode(const String&in) const", asMETHOD(T, GetAttributeAnimationWrapMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void SetAttributeAnimationSpeed(const String&in, float)", asMETHOD(T, SetAttributeAnimationSpeed), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "float GetAttributeAnimationSpeed(const String&in) const", asMETHOD(T, GetAttributeAnimationSpeed), asCALL_THISCALL);
 }
 
 /// Template function for registering a class derived from Component.

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

@@ -48,8 +48,8 @@ static void RegisterAttributeAnimation(asIScriptEngine* engine)
     engine->RegisterObjectMethod("AttributeAnimation", "float get_splineTension() const", asMETHOD(AttributeAnimation, GetSplineTension), 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", "void SetKeyFrame(float, const Variant&)", asMETHOD(AttributeAnimation, SetKeyFrame), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AttributeAnimation", "void SetEventFrame(float, const String&, const Variant&)", asMETHOD(AttributeAnimation, SetEventFrame), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AttributeAnimation", "void SetKeyFrame(float, const Variant&in)", asMETHOD(AttributeAnimation, SetKeyFrame), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AttributeAnimation", "void SetEventFrame(float, const String&in, const Variant&in)", asMETHOD(AttributeAnimation, SetEventFrame), asCALL_THISCALL);
 }
 
 static void RegisterObjectAnimation(asIScriptEngine* engine)
@@ -60,12 +60,15 @@ static void RegisterObjectAnimation(asIScriptEngine* engine)
     engine->RegisterEnumValue("WrapMode", "WM_CLAMP", WM_CLAMP);
 
     RegisterResource<ObjectAnimation>(engine, "ObjectAnimation");
-    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 AddAttributeAnimation(const String&in, AttributeAnimation@+, WrapMode wrapMode=WM_LOOP, float speed=1.0f)", asMETHOD(ObjectAnimation, AddAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "void RemoveAttributeAnimation(const String&in)", asMETHODPR(ObjectAnimation, RemoveAttributeAnimation, (const String&), 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", "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", "AttributeAnimation@+ GetAttributeAnimation(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "WrapMode GetAttributeAnimationWrapMode(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimationWrapMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "float GetAttributeAnimationSpeed(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimationSpeed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "Variant get_attributeAnimations(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "Variant get_wrapModes(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimationWrapMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ObjectAnimation", "Variant get_speeds(const String&in) const", asMETHOD(ObjectAnimation, GetAttributeAnimationSpeed), asCALL_THISCALL);
 }
 
 static void RegisterSerializable(asIScriptEngine* engine)