Do not re-create SG::Animation when we call Clear to empty animation + Clear reset... 38/305938/8
authorEunki Hong <eunkiki.hong@samsung.com>
Wed, 14 Feb 2024 02:51:16 +0000 (11:51 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Fri, 16 Feb 2024 12:02:02 +0000 (12:02 +0000)
Since we always destroy & create scene obeject whenever we call Clear(),
It will be make some useless memory increasement when user call
Clear() infinitely.

To avoid this cases, let we re-create that object only if we call Play() before
or at least 1 animator exist.

And also, make Clear() API reset some sensitive values, like CurrentLoop and State.

Change-Id: I7f79b5e8e2bf822f01f094e4023e90e5f0922faa
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-Animation.cpp
dali/internal/event/animation/animation-impl.cpp

index a4cfd8d..00847a6 100644 (file)
@@ -3406,6 +3406,103 @@ int UtcDaliAnimationClearP(void)
   END_TEST;
 }
 
+int UtcDaliAnimationEmptyAnimator(void)
+{
+  // Clear and play the empty animation, and get the state values.
+  TestApplication application;
+
+  float     durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.SetLoopCount(3);
+
+  bool                 signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  try
+  {
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+    application.SendNotification();
+    application.Render();
+
+    animation.Play();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+    application.SendNotification();
+    application.Render(1500 /* 150% of loop. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(1400 /* 290% of loop. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 2, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(100 + 1100 /* 300% of loop. and extra 110%. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 3, TEST_LOCATION);
+
+    // Check wether empty animation also call finished signal.
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    animation.Play();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    //DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION); ///< TODO : We'd better change the policy of GetCurrentLoop result
+    application.SendNotification();
+    application.Render(1500 /* 150% of loop. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    animation.Clear();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(1000);
+    application.Render(1000);
+    application.Render(1100 /* Over the loop count */);
+    application.SendNotification(); // Notification trigger.
+
+    // Check animation completed signal not recieved even of
+    finishCheck.CheckSignalNotReceived();
+
+    // Call clear again already cleared cases.
+    animation.Clear();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(1000);
+    application.Render(1000);
+    application.Render(1100 /* Over the loop count */);
+    application.SendNotification(); // Notification trigger.
+
+    // Check animation completed signal not recieved even of
+    finishCheck.CheckSignalNotReceived();
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK(false); // Should not get here
+  }
+
+  END_TEST;
+}
+
 int UtcDaliAnimationFinishedSignalP(void)
 {
   TestApplication application;
index f182e9e..b9a4de4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -389,6 +389,13 @@ void Animation::Clear()
 {
   DALI_ASSERT_DEBUG(mAnimation);
 
+  // Recreate scene-object only if animation play now, or connector connected at least 1 times.
+  if(mConnectors.Count() == 0u && mState == Dali::Animation::STOPPED)
+  {
+    // Animation is empty. Fast-out
+    return;
+  }
+
   // Only notify the objects with the current values if the end action is set to BAKE
   if(mEndAction == EndAction::BAKE && mState != Dali::Animation::STOPPED)
   {
@@ -406,8 +413,10 @@ void Animation::Clear()
   DestroySceneObject();
   CreateSceneObject();
 
-  // Reset the notification count, since the new scene-object has never been played
+  // Reset the notification count and relative values, since the new scene-object has never been played
   mNotificationCount = 0;
+  mCurrentLoop       = 0;
+  mState             = Dali::Animation::STOPPED;
 
   // Update the current playlist
   mPlaylist.OnClear(*this);