Sort Animator only if required. 38/289038/7
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 27 Feb 2023 13:09:34 +0000 (22:09 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 27 Feb 2023 16:48:00 +0000 (01:48 +0900)
Previously, we sort mConnectorTargetValues every Play() API.
Even if we don't need to sort it.

Now, make we sort that container only if last inserted value is bigger than
latest thing, and reset the flag if we sort.

Change-Id: Ia2ba07df3db5a2a0d6d89b0ef2854c5fc655fb2a
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali/internal/event/animation/animation-impl.cpp
dali/internal/event/animation/animation-impl.h
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/animation/scene-graph-animation.h

index 6fdf660..60e54f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -393,6 +393,7 @@ void Animation::Clear()
 
   // Reset the connector target values
   mConnectorTargetValues.clear();
+  mConnectorTargetValuesSortRequired = false;
 
   // Replace the old scene-object with a new one
   DestroySceneObject();
@@ -523,8 +524,8 @@ void Animation::AnimateBy(Property& target, Property::Value relativeValue, Alpha
       DALI_ASSERT_DEBUG(false && "Property  not supported");
     }
   }
-  // Store data to later notify the object that its property is being animated
-  mConnectorTargetValues.push_back({std::move(relativeValue), period, connectorIndex, Animation::BY});
+
+  AppendConnectorTargetValues({std::move(relativeValue), period, connectorIndex, Animation::BY});
 }
 
 void Animation::AnimateTo(Property& target, Property::Value destinationValue)
@@ -643,8 +644,8 @@ void Animation::AnimateTo(Property& target, Property::Value destinationValue, Al
       DALI_ASSERT_DEBUG(false && "Property  not supported");
     }
   }
-  // Store data to later notify the object that its property is being animated
-  mConnectorTargetValues.push_back({std::move(destinationValue), period, connectorIndex, Animation::TO});
+
+  AppendConnectorTargetValues({std::move(destinationValue), period, connectorIndex, Animation::TO});
 }
 
 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
@@ -695,8 +696,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
 
   ExtendDuration(period);
 
-  // Store data to later notify the object that its property is being animated
-  mConnectorTargetValues.push_back({keyFrames.GetLastKeyFrameValue(), period, mConnectors.Count(), BETWEEN});
+  AppendConnectorTargetValues({keyFrames.GetLastKeyFrameValue(), period, mConnectors.Count(), BETWEEN});
 
   // using destination type so component animation gets correct type
   switch(destinationType)
@@ -1058,9 +1058,12 @@ void Animation::NotifyObjects(Animation::Notify notifyValueType)
   {
     // Sort according to end time with earlier end times coming first, if the end time is the same, then the connectors are not moved
     // Only do this if we're using the target value
-    if(notifyValueType == Notify::USE_TARGET_VALUE)
+    if(mConnectorTargetValuesSortRequired && notifyValueType == Notify::USE_TARGET_VALUE)
     {
       std::stable_sort(mConnectorTargetValues.begin(), mConnectorTargetValues.end(), CompareConnectorEndTimes);
+
+      // Now mConnectorTargetValues sorted. Reset flag.
+      mConnectorTargetValuesSortRequired = false;
     }
 
     // Loop through all connector target values sorted by increasing end time
@@ -1093,6 +1096,22 @@ void Animation::SendFinalProgressNotificationMessage()
   }
 }
 
+void Animation::AppendConnectorTargetValues(ConnectorTargetValues&& connectorTargetValues)
+{
+  // Check whether we need to sort mConnectorTargetValues or not.
+  // Sort will be required only if new item is smaller than last value of container.
+  if(!mConnectorTargetValuesSortRequired && !mConnectorTargetValues.empty())
+  {
+    if(CompareConnectorEndTimes(connectorTargetValues, mConnectorTargetValues.back()))
+    {
+      mConnectorTargetValuesSortRequired = true;
+    }
+  }
+
+  // Store data to later notify the object that its property is being animated
+  mConnectorTargetValues.push_back(std::move(connectorTargetValues));
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 410929b..966638e 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ANIMATION_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -479,6 +479,24 @@ private:
     {
     }
 
+    // Move operations
+    ConnectorTargetValues(ConnectorTargetValues&& rhs) noexcept
+    : targetValue(std::move(rhs.targetValue)),
+      timePeriod(std::move(rhs.timePeriod)),
+      connectorIndex(rhs.connectorIndex),
+      animatorType(rhs.animatorType)
+    {
+    }
+
+    ConnectorTargetValues& operator=(ConnectorTargetValues&& rhs) noexcept
+    {
+      targetValue    = std::move(rhs.targetValue);
+      timePeriod     = std::move(rhs.timePeriod);
+      connectorIndex = rhs.connectorIndex;
+      animatorType   = rhs.animatorType;
+      return *this;
+    }
+
     Property::Value targetValue;
     TimePeriod      timePeriod{0.f};
     std::size_t     connectorIndex{0};
@@ -512,6 +530,13 @@ private:
    */
   void SendFinalProgressNotificationMessage();
 
+  /**
+   * @brief Append ConnectorTargetValues into the container.
+   *
+   * @param[in] connectorTargetValues moved ConnectorTargetValues that will be append end of container
+   */
+  void AppendConnectorTargetValues(ConnectorTargetValues&& connectorTargetValues);
+
 private:
   using AnimatorConnectorContainer     = OwnerContainer<AnimatorConnectorBase*>;
   using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
@@ -539,7 +564,8 @@ private:
   EndAction              mEndAction;
   EndAction              mDisconnectAction;
   Dali::Animation::State mState{Dali::Animation::STOPPED};
-  bool                   mAutoReverseEnabled{false}; ///< Flag to identify that the looping mode is auto reverse.
+  bool                   mAutoReverseEnabled{false};                ///< Flag to identify that the looping mode is auto reverse.
+  bool                   mConnectorTargetValuesSortRequired{false}; ///< Flag to whether we need to sort mConnectorTargetValues or not
 };
 
 } // namespace Internal
index 659547f..ec26435 100644 (file)
@@ -80,6 +80,7 @@ Animation::Animation(float durationSeconds, float speedFactor, const Vector2& pl
   mState(Stopped),
   mProgressReachedSignalRequired(false),
   mAutoReverseEnabled(false),
+  mAnimatorSortRequired(false),
   mIsActive{false}
 {
 }
@@ -151,8 +152,12 @@ void Animation::SetPlayRange(const Vector2& range)
 
 void Animation::Play()
 {
-  // Sort according to end time with earlier end times coming first, if the end time is the same, then the animators are not moved
-  std::stable_sort(mAnimators.Begin(), mAnimators.End(), CompareAnimatorEndTimes);
+  if(mAnimatorSortRequired)
+  {
+    // Sort according to end time with earlier end times coming first, if the end time is the same, then the animators are not moved
+    std::stable_sort(mAnimators.Begin(), mAnimators.End(), CompareAnimatorEndTimes);
+    mAnimatorSortRequired = false;
+  }
 
   mState = Playing;
 
@@ -299,6 +304,16 @@ void Animation::AddAnimator(OwnerPointer<AnimatorBase>& animator)
   animator->ConnectToSceneGraph();
   animator->SetDisconnectAction(mDisconnectAction);
 
+  // Check whether we need to sort mAnimators or not.
+  // Sort will be required only if new item is smaller than last value of container.
+  if(!mAnimatorSortRequired && !mAnimators.Empty())
+  {
+    if(CompareAnimatorEndTimes(animator.Get(), *(mAnimators.End() - 1u)))
+    {
+      mAnimatorSortRequired = true;
+    }
+  }
+
   mAnimators.PushBack(animator.Release());
 }
 
@@ -485,6 +500,10 @@ void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake, bool animati
   {
     //Remove animators whose PropertyOwner has been destroyed
     mAnimators.EraseIf([](auto& animator) { return animator->Orphan(); });
+
+    // Need to be re-sort if remained animators size is bigger than one.
+    // Note that if animator contains only zero or one items, It is already sorted case.
+    mAnimatorSortRequired = (mAnimators.Count() >= 2);
   }
 }
 
index 4119c15..6ae8fdd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -352,6 +352,7 @@ protected:
 
   bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit
   bool mAutoReverseEnabled;            // Flag to identify that the looping mode is auto reverse.
+  bool mAnimatorSortRequired;          // Flag to whether we need to sort animator or not.
   bool mIsActive[2];                   // Flag to indicate whether the animation is active in the current frame (which is double buffered)
 };