Bläddra i källkod

Make object animation can set child and component's attribute animation.

Aster@中国上海 11 år sedan
förälder
incheckning
cd42bc6f3f

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

@@ -287,6 +287,11 @@ ResourceRef Animatable::GetObjectAnimationAttr() const
     return GetResourceRef(objectAnimation_, ObjectAnimation::GetTypeStatic());
 }
 
+void Animatable::SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed)
+{
+    SetAttributeAnimation(name, attributeAnimation, wrapMode, speed);
+}
+
 void Animatable::OnObjectAnimationAdded(ObjectAnimation* objectAnimation)
 {
     if (!objectAnimation)
@@ -298,7 +303,7 @@ void Animatable::OnObjectAnimationAdded(ObjectAnimation* objectAnimation)
     {
         const String& name = i->first_;
         ValueAnimationInfo* info = i->second_;
-        SetAttributeAnimation(name, info->GetAnimation(), info->GetWrapMode(), info->GetSpeed());
+        SetObjectAttributeAnimation(name, info->GetAnimation(), info->GetWrapMode(), info->GetSpeed());
     }
 }
 
@@ -316,7 +321,7 @@ void Animatable::OnObjectAnimationRemoved(ObjectAnimation* objectAnimation)
     }
 
     for (unsigned int i = 0; i < names.Size(); ++i)
-        SetAttributeAnimation(names[i], 0);
+        SetObjectAttributeAnimation(names[i], 0, WM_LOOP, 1.0f);
 }
 
 void Animatable::UpdateAttributeAnimations(float timeStep)

+ 2 - 0
Source/Engine/Scene/Animatable.h

@@ -107,6 +107,8 @@ protected:
     virtual void OnAttributeAnimationAdded() = 0;
     /// Handle attribute animation removed.
     virtual void OnAttributeAnimationRemoved() = 0;
+    /// Set object attribute animation internal.
+    virtual void SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed);
     /// Handle object animation added.
     void OnObjectAnimationAdded(ObjectAnimation* objectAnimation);
     /// Handle object animation removed.

+ 67 - 1
Source/Engine/Scene/Node.cpp

@@ -1,4 +1,4 @@
-//
+//
 // Copyright (c) 2008-2014 the Urho3D project.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1515,6 +1515,72 @@ void Node::OnAttributeAnimationRemoved()
         UnsubscribeFromEvent(GetScene(), E_ATTRIBUTEANIMATIONUPDATE);
 }
 
+void Node::SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed)
+{
+    Vector<String> names = name.Split('/');
+    // Only attribute name
+    if (names.Size() == 1)
+        SetAttributeAnimation(name, attributeAnimation, wrapMode, speed);
+    else
+    {
+        // Name must in following format: "#0/#1/@component#0/attribute"
+        Node* node = this;
+        unsigned i = 0;
+        for (; i < names.Size() - 1; ++i)
+        {
+            if (names[i].Front() != '#')
+                break;
+
+            unsigned index = ToInt(names[i].Substring(1, -1));
+            node = node->GetChild(index);
+            if (!node)
+            {
+                LOGERROR("Could not find node by name " + name);
+                return;
+            }
+        }
+        
+        if (i == names.Size() - 1)
+        {
+            node->SetAttributeAnimation(names.Back(), attributeAnimation, wrapMode, speed);
+            return;
+        }
+
+        if (i != names.Size() - 2 || names[i].Front() != '@')
+        {
+            LOGERROR("Invalid name " + name);
+            return;
+        }
+
+        String componentName = names[i].Substring(1, names[i].Length() - 1);
+        Vector<String> componentNames = componentName.Split('#');
+        if (componentNames.Size() == 1)
+        {
+            Component* component = node->GetComponent(StringHash(componentNames.Front()));
+            if (!component)
+            {
+                LOGERROR("Could not find component by name " + name);
+                return;
+            }
+
+            component->SetAttributeAnimation(names.Back(), attributeAnimation, wrapMode, speed);
+        }
+        else
+        {
+            unsigned index = ToInt(componentNames[1]);
+            PODVector<Component*> components;
+            node->GetComponents(components, StringHash(componentNames.Front()));
+            if (index >= components.Size())
+            {
+                LOGERROR("Could not find component by name " + name);
+                return;
+            }
+
+            components[index]->SetAttributeAnimation(names.Back(), attributeAnimation, wrapMode, speed);
+        }
+    }
+}
+
 Component* Node::SafeCreateComponent(const String& typeName, StringHash type, CreateMode mode, unsigned id)
 {
     // First check if factory for type exists

+ 2 - 0
Source/Engine/Scene/Node.h

@@ -455,6 +455,8 @@ protected:
     virtual void OnAttributeAnimationAdded();
     /// Handle attribute animation removed.
     virtual void OnAttributeAnimationRemoved();
+    /// Set object attribute animation internal.
+    virtual void SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed);
 
     /// Network update queued flag.
     bool networkUpdate_;

+ 2 - 2
Source/Engine/Scene/ObjectAnimation.h

@@ -54,9 +54,9 @@ public:
     /// Save as XML data. Return true if successful.
     bool SaveXML(XMLElement& dest) const;
 
-    /// Add attribute animation.
+    /// Add attribute animation, attribute name can in following format: "attribute" or "#0/#1/attribute" or ""#0/#1/@component#1/attribute.
     void AddAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
-    /// Remove attribute animation.
+    /// Remove attribute animation, attribute name can in following format: "attribute" or "#0/#1/attribute" or ""#0/#1/@component#1/attribute.
     void RemoveAttributeAnimation(const String& name);
     /// Remove attribute animation.
     void RemoveAttributeAnimation(ValueAnimation* attributeAnimation);

+ 31 - 0
Source/Engine/UI/UIElement.cpp

@@ -1594,6 +1594,37 @@ void UIElement::OnAttributeAnimationRemoved()
         UnsubscribeFromEvent(E_POSTUPDATE);
 }
 
+void UIElement::SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed)
+{
+    Vector<String> names = name.Split('/');
+    // Only attribute name
+    if (names.Size() == 1)
+        SetAttributeAnimation(name, attributeAnimation, wrapMode, speed);
+    else
+    {
+        // Name must in following format: "#0/#1/attribute"
+        UIElement* element = this;
+        for (unsigned i = 0; i < names.Size() - 1; ++i)
+        {
+            if (names[i].Front() != '#')
+            {
+                LOGERROR("Invalid name " + name);
+                return;
+            }
+
+            unsigned index = ToInt(names[i].Substring(1, names[i].Length() - 1));
+            element = element->GetChild(index);
+            if (!element)
+            {
+                LOGERROR("Could not find element by name " + name);
+                return;
+            }
+        }
+
+        element->SetAttributeAnimation(names.Back(), attributeAnimation, wrapMode, speed);
+    }
+}
+
 void UIElement::MarkDirty()
 {
     positionDirty_ = true;

+ 2 - 0
Source/Engine/UI/UIElement.h

@@ -472,6 +472,8 @@ protected:
     virtual void OnAttributeAnimationAdded();
     /// Handle attribute animation removed.
     virtual void OnAttributeAnimationRemoved();
+    /// Set object attribute animation internal.
+    virtual void SetObjectAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed);
     /// Mark screen position as needing an update.
     void MarkDirty();
     /// Remove child XML element by matching attribute name.