فهرست منبع

Fix event frame not expanding the ValueAnimation's time range properly. Fix removing an animating object during an event frame causing crash. Thanks to vudugun for noticing (forum thread http://urho3d.prophpbb.com/topic2464.html)

Lasse Öörni 9 سال پیش
والد
کامیت
9a5d9af6b7
3فایلهای تغییر یافته به همراه25 افزوده شده و 3 حذف شده
  1. 9 1
      Source/Urho3D/Scene/Animatable.cpp
  2. 3 0
      Source/Urho3D/Scene/ValueAnimation.cpp
  3. 13 2
      Source/Urho3D/Scene/ValueAnimationInfo.cpp

+ 9 - 1
Source/Urho3D/Scene/Animatable.cpp

@@ -517,11 +517,19 @@ void Animatable::UpdateAttributeAnimations(float timeStep)
     if (!animationEnabled_)
         return;
 
+    // Keep weak pointer to self to check for destruction caused by event handling
+    WeakPtr<Animatable> self(this);
+
     Vector<String> finishedNames;
     for (HashMap<String, SharedPtr<AttributeAnimationInfo> >::ConstIterator i = attributeAnimationInfos_.Begin();
          i != attributeAnimationInfos_.End(); ++i)
     {
-        if (i->second_->Update(timeStep))
+        bool finished = i->second_->Update(timeStep);
+        // If self deleted as a result of an event sent during animation playback, nothing more to do
+        if (self.Expired())
+            return;
+
+        if (finished)
             finishedNames.Push(i->second_->GetAttributeInfo().name_);
     }
 

+ 3 - 0
Source/Urho3D/Scene/ValueAnimation.cpp

@@ -328,6 +328,9 @@ void ValueAnimation::SetEventFrame(float time, const StringHash& eventType, cons
             }
         }
     }
+
+    beginTime_ = Min(time, beginTime_);
+    endTime_ = Max(time, endTime_);
 }
 
 bool ValueAnimation::IsValid() const

+ 13 - 2
Source/Urho3D/Scene/ValueAnimationInfo.cpp

@@ -98,8 +98,19 @@ bool ValueAnimationInfo::SetTime(float time)
         PODVector<const VAnimEventFrame*> eventFrames;
         GetEventFrames(lastScaledTime_, scaledTime, eventFrames);
 
-        for (unsigned i = 0; i < eventFrames.Size(); ++i)
-            target_->SendEvent(eventFrames[i]->eventType_, const_cast<VariantMap&>(eventFrames[i]->eventData_));
+        if (eventFrames.Size())
+        {
+            // Make a copy of the target weakptr, since if it expires, the AnimationInfo is deleted as well, in which case the
+            // member variable cannot be accessed
+            WeakPtr<Object> targetWeak(target_);
+
+            for (unsigned i = 0; i < eventFrames.Size(); ++i)
+                target_->SendEvent(eventFrames[i]->eventType_, const_cast<VariantMap&>(eventFrames[i]->eventData_));
+
+            // Break immediately if target expired due to event
+            if (targetWeak.Expired())
+                return true;
+        }
     }
 
     lastScaledTime_ = scaledTime;