Browse Source

Add bone animation support.

aster2013 11 years ago
parent
commit
2bee9a334f

+ 36 - 18
Source/Engine/Urho2D/AnimatedSprite2D.cpp

@@ -186,8 +186,9 @@ void AnimatedSprite2D::OnWorldBoundingBoxUpdate()
 
     for (unsigned i = 0; i < objectNodes_.Size(); ++i)
     {
-        StaticSprite2D* ss = objectNodes_[i]->GetComponent<StaticSprite2D>();
-        worldBoundingBox_.Merge(ss->GetWorldBoundingBox());
+        StaticSprite2D* staticSprite = objectNodes_[i]->GetComponent<StaticSprite2D>();
+        if (staticSprite)
+            worldBoundingBox_.Merge(staticSprite->GetWorldBoundingBox());
     }
 
     boundingBox_ = worldBoundingBox_.Transformed(node_->GetWorldTransform().Inverse());
@@ -219,14 +220,29 @@ void AnimatedSprite2D::SetAnimation(Animation2D* animation)
 
     animationTime_ = 0.0f;
 
-    for (unsigned i = 0; i < animation_->GetTimelines().Size(); ++i)
+    const MainlineKey& mainlineKey = animation_->GetMainlineKeys().Front();
+    for (unsigned i = 0; i < animation_->GetNumTimelines(); ++i)
     {
-        SharedPtr<Node> objectNode(GetNode()->CreateChild(animation_->GetTimelines()[i].name_));
+        const Timeline& timeline = animation_->GetTimeline(i);
 
-        StaticSprite2D* staticSprite = objectNode->CreateComponent<StaticSprite2D>();
-        staticSprite->SetLayer(layer_);
-        staticSprite->SetBlendMode(blendMode_);
-        staticSprite->SetUseHotSpot(true);
+        SharedPtr<Node> objectNode;
+        const ObjectRef* objectRef = mainlineKey.GetObjectRef(i);
+        if (!objectRef || objectRef->parent_ == -1)
+            objectNode = GetNode()->CreateChild(timeline.name_);
+        else
+        {
+            assert(objectRef->parent_ < (int)objectNodes_.Size());
+            SharedPtr<Node> parentNode = objectNodes_[objectRef->parent_];
+            objectNode = parentNode->CreateChild(timeline.name_);
+        }
+
+        if (!timeline.isBone_)
+        {
+            StaticSprite2D* staticSprite = objectNode->CreateComponent<StaticSprite2D>();
+            staticSprite->SetLayer(layer_);
+            staticSprite->SetBlendMode(blendMode_);
+            staticSprite->SetUseHotSpot(true);
+        }
 
         objectNodes_.Push(objectNode);        
     }
@@ -269,8 +285,7 @@ void AnimatedSprite2D::UpdateAnimation(float timeStep)
     if (!mainlineKey)
         mainlineKey = &mainlineKeys.Back();
 
-    const Vector<Timeline>& timelines = animation_->GetTimelines();
-    for (unsigned i = 0; i < timelines.Size(); ++i)
+    for (unsigned i = 0; i < animation_->GetNumTimelines(); ++i)
     {
         Node* objectNode = objectNodes_[i];
 
@@ -281,10 +296,8 @@ void AnimatedSprite2D::UpdateAnimation(float timeStep)
         {
             objectNode->SetEnabled(true);
 
-            StaticSprite2D* staticSprite = objectNode->GetComponent<StaticSprite2D>();
-            staticSprite->SetOrderInLayer(orderInLayer_ + objectRef->zIndex_);
-
-            const Vector<ObjectKey>& objectKeys = timelines[i].objectKeys_;
+            const Timeline& timeline = animation_->GetTimeline(i);
+            const Vector<ObjectKey>& objectKeys = timeline.objectKeys_;
             for (unsigned j = 0; j < objectKeys.Size() - 1; ++j)
             {
                 if (time <= objectKeys[j + 1].time_)
@@ -310,10 +323,15 @@ void AnimatedSprite2D::UpdateAnimation(float timeStep)
 
                     objectNode->SetScale(currKey.scale_.Lerp(nextKey.scale_, t));
 
-                    staticSprite->SetSprite(currKey.sprite_);
-                    staticSprite->SetHotSpot(currKey.hotSpot_.Lerp(nextKey.hotSpot_, t));
-                    float alpha_ = Lerp(currKey.alpha_, nextKey.alpha_, t);
-                    staticSprite->SetColor(Color(1.0f, 1.0f, 1.0f, alpha_));
+                    if (!timeline.isBone_)
+                    {
+                        StaticSprite2D* staticSprite = objectNode->GetComponent<StaticSprite2D>();
+                        staticSprite->SetOrderInLayer(orderInLayer_ + objectRef->zIndex_);
+                        staticSprite->SetSprite(currKey.sprite_);
+                        staticSprite->SetHotSpot(currKey.hotSpot_.Lerp(nextKey.hotSpot_, t));
+                        float alpha_ = Lerp(currKey.alpha_, nextKey.alpha_, t);
+                        staticSprite->SetColor(Color(1.0f, 1.0f, 1.0f, alpha_));
+                    }
 
                     break;
                 }

+ 8 - 4
Source/Engine/Urho2D/Animation2D.cpp

@@ -30,7 +30,9 @@
 namespace Urho3D
 {
 
-ObjectRef::ObjectRef() : 
+ObjectRef::ObjectRef() :
+    isBone_(false),
+    parent_(-1),
     timeline_(0),
     key_(0),
     zIndex_(0)
@@ -54,14 +56,16 @@ const ObjectRef* MainlineKey::GetObjectRef(int timeline) const
 
 ObjectKey::ObjectKey() :
     time_(0.0f),
-    hotSpot_(0.0f, 1.0f),
-    scale_(Vector2::ONE), 
     spin_(1),
+    angle_(0.0f),
+    scale_(Vector2::ONE), 
+    hotSpot_(0.0f, 1.0f),
     alpha_(1.0f)
 {
 }
 
-Timeline::Timeline()
+Timeline::Timeline() :
+    isBone_(false)
 {
 }
 

+ 22 - 11
Source/Engine/Urho2D/Animation2D.h

@@ -29,15 +29,19 @@
 namespace Urho3D
 {
 
-class Sprite2D;
 class AnimationSet2D;
+class Sprite2D;
 
 /// Object reference.
 struct ObjectRef
 {
     /// Construct.
     ObjectRef();
-
+    
+    /// Is bone.
+    bool isBone_;
+    /// Parent.
+    int parent_;
     /// Timeline.
     int timeline_;
     /// Key index.
@@ -57,7 +61,6 @@ public:
     float time_;
     /// Object references.
     Vector<ObjectRef> objectRefs_;
-
     /// Return object reference by timeline.
     const ObjectRef* GetObjectRef(int timeline) const;
 };
@@ -70,18 +73,20 @@ struct ObjectKey
 
     /// Time.
     float time_;
-    /// Sprite.
-    SharedPtr<Sprite2D> sprite_;
-    /// Position.
-    Vector2 position_;
-    /// Hot spot (pivot).
-    Vector2 hotSpot_;
-    /// Scale.
-    Vector2 scale_;
     /// Spin direction.
     int spin_;
+
+    /// Position.
+    Vector2 position_;
     /// Angle.
     float angle_;
+    /// Scale.
+    Vector2 scale_;
+
+    /// Sprite.
+    SharedPtr<Sprite2D> sprite_;
+    /// Hot spot (pivot).
+    Vector2 hotSpot_;
     /// Alpha.
     float alpha_;
 };
@@ -94,6 +99,8 @@ struct Timeline
 
     /// Name.
     String name_;
+    /// Is sprite.
+    bool isSprite_;
     /// Object keys.
     Vector<ObjectKey> objectKeys_;
 };
@@ -128,6 +135,10 @@ public:
     bool IsLooped() const { return looped_; }
     /// Return all mainline keys.
     const Vector<MainlineKey>& GetMainlineKeys() const { return mainlineKeys_; }
+    /// Return number of timelines.
+    unsigned GetNumTimelines() const { return timelines_.Size();}
+    /// Return timeline by index.
+    const Timeline& GetTimeline(unsigned index) const { return timelines_[index]; }
     /// Return all timelines.
     const Vector<Timeline>& GetTimelines() const { return timelines_; }
 

+ 53 - 37
Source/Engine/Urho2D/AnimationSet2D.cpp

@@ -174,15 +174,25 @@ bool AnimationSet2D::LoadAnimation(const XMLElement& animationElem)
         MainlineKey mainlineKey;
         mainlineKey.time_ = keyElem.GetFloat("time") * 0.001f;
 
-        // Just support object ref now
-        for (XMLElement objectRefElem = keyElem.GetChild("object_ref"); objectRefElem; objectRefElem = objectRefElem.GetNext("object_ref"))
+        for (XMLElement refElem = keyElem.GetChild(); refElem; refElem = refElem.GetNext())
         {
-            ObjectRef objectRef;
-            objectRef.timeline_ = objectRefElem.GetInt("timeline");
-            objectRef.key_ = objectRefElem.GetInt("key");
-            objectRef.zIndex_ = objectRefElem.GetInt("z_index");
+            ObjectRef ref;
+            
+            if (refElem.GetName() == "bone_ref")
+                ref.isBone_ = true;
+            else
+                ref.isBone_ = false;
+
+            if (refElem.HasAttribute("parent"))
+                ref.parent_ = refElem.GetInt("parent");
+
+            ref.timeline_ = refElem.GetInt("timeline");
+            ref.key_ = refElem.GetInt("key");
 
-            mainlineKey.objectRefs_.Push(objectRef);
+            if (refElem.GetName() == "object_ref")
+                ref.zIndex_ = refElem.GetInt("z_index");
+
+            mainlineKey.objectRefs_.Push(ref);
         }
 
         animation->AddMainlineKey(mainlineKey);
@@ -193,6 +203,10 @@ bool AnimationSet2D::LoadAnimation(const XMLElement& animationElem)
     {
         Timeline timeline;
         timeline.name_ = timelineElem.GetAttribute("name");
+        if (timelineElem.GetAttribute("object_type") == "bone")
+            timeline.isBone_ = true;
+        else
+            timeline.isBone_ = false;
 
         for (XMLElement keyElem = timelineElem.GetChild("key"); keyElem; keyElem = keyElem.GetNext("key"))
         {
@@ -202,40 +216,42 @@ bool AnimationSet2D::LoadAnimation(const XMLElement& animationElem)
             if (keyElem.HasAttribute("spin"))
                 objectKey.spin_ = keyElem.GetInt("spin");
 
-            XMLElement objectElem = keyElem.GetChild("object");          
+            XMLElement childElem = keyElem.GetChild();
+            objectKey.position_.x_ = childElem.GetFloat("x") * PIXEL_SIZE;
+            objectKey.position_.y_ = childElem.GetFloat("y") * PIXEL_SIZE;
             
-            int folder = objectElem.GetUInt("folder");
-            int file = objectElem.GetUInt("file");
-            objectKey.sprite_ = GetSprite(folder, file);
-            if (!objectKey.sprite_)
-            {
-                LOGERROR("Could not find sprite");
-                return false;
-            }
+            objectKey.angle_= childElem.GetFloat("angle");
 
-            objectKey.position_.x_ = objectElem.GetFloat("x") * PIXEL_SIZE;
-            objectKey.position_.y_ = objectElem.GetFloat("y") * PIXEL_SIZE;
-            
-            if (objectElem.HasAttribute("pivot_x"))
-                objectKey.hotSpot_.x_ = objectElem.GetFloat("pivot_x");
-            else
-                objectKey.hotSpot_.x_ = objectKey.sprite_->GetHotSpot().x_;
-
-            if (objectElem.HasAttribute("pivot_y"))
-                objectKey.hotSpot_.y_ = objectElem.GetFloat("pivot_y");
-            else
-                objectKey.hotSpot_.y_ = objectKey.sprite_->GetHotSpot().y_;
+            if (childElem.HasAttribute("scale_x"))
+                objectKey.scale_.x_ = childElem.GetFloat("scale_x");
 
-            if (objectElem.HasAttribute("scale_x"))
-                objectKey.scale_.x_ = objectElem.GetFloat("scale_x");
+            if (childElem.HasAttribute("scale_y"))
+                objectKey.scale_.y_ = childElem.GetFloat("scale_y");
 
-            if (objectElem.HasAttribute("scale_y"))
-                objectKey.scale_.y_ = objectElem.GetFloat("scale_y");
-
-            objectKey.angle_= objectElem.GetFloat("angle");
-                
-            if (objectElem.HasAttribute("a"))
-                objectKey.alpha_ = objectElem.GetFloat("a");
+            if (!timeline.isBone_)
+            {
+                int folder = childElem.GetUInt("folder");
+                int file = childElem.GetUInt("file");
+                objectKey.sprite_ = GetSprite(folder, file);
+                if (!objectKey.sprite_)
+                {
+                    LOGERROR("Could not find sprite");
+                    return false;
+                }
+
+                if (childElem.HasAttribute("pivot_x"))
+                    objectKey.hotSpot_.x_ = childElem.GetFloat("pivot_x");
+                else
+                    objectKey.hotSpot_.x_ = objectKey.sprite_->GetHotSpot().x_;
+
+                if (childElem.HasAttribute("pivot_y"))
+                    objectKey.hotSpot_.y_ = childElem.GetFloat("pivot_y");
+                else
+                    objectKey.hotSpot_.y_ = objectKey.sprite_->GetHotSpot().y_;
+
+                if (childElem.HasAttribute("a"))
+                    objectKey.alpha_ = childElem.GetFloat("a");
+            }
 
             timeline.objectKeys_.Push(objectKey);
         }