Ensure resetters reset both values when a property-owner is disconnected 68/192368/3
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 2 Nov 2018 17:55:29 +0000 (17:55 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Mon, 5 Nov 2018 12:33:48 +0000 (12:33 +0000)
Change-Id: Iaf3e077b8e62d149900abb4ca719efe4326fa598

automated-tests/src/dali/utc-Dali-Constraint.cpp
dali/internal/update/common/property-resetter.h

index 814c453..f8f8ac5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -1237,3 +1237,124 @@ int UtcDaliConstraintTestPropertyTypesP(void)
 
 ///////////////////////////////////////////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+void SetHalfOpacity( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.a = 0.5f;
+}
+} // unnamed namespace
+
+int UtcDaliConstraintEnsureResetterAppliedOnStageRemoval(void)
+{
+  // Ensure BOTH double-buffered values of our color property is reset when a constraint is applied to it.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Check initial value is fully opaque
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Create a constraint whose value is discarded when it is removed
+  Constraint constraint = Constraint::New< Vector4 >( actor, Actor::Property::COLOR, SetHalfOpacity );
+  constraint.SetRemoveAction( Constraint::RemoveAction::Discard );
+  constraint.Apply();
+
+  // Check value after one render, it should be constrained
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  // Render another frame, ensure the other value has also been updated
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  // Remove the actor from the stage and delete the constraint
+  actor.Unparent();
+  constraint.Remove();
+  constraint.Reset();
+
+  // Check value while off-stage, it should be fully opaque
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Add the actor back to the stage and check the value, it should be fully opaque again
+  Stage::GetCurrent().Add( actor );
+
+  // Check value when back on-stage, it should be fully opaque as the constraint is no longer applied to it.
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Render for another frame to ensure both buffers have the correct value
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintOnActorAddedAndRemoved(void)
+{
+  // Ensure adding and removing an actor from stage with a constraint still has it applied when it is re-added back to the stage
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Check initial value is fully opaque
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Create a constraint whose value is discarded when it is removed
+  Constraint constraint = Constraint::New< Vector4 >( actor, Actor::Property::COLOR, SetHalfOpacity );
+  constraint.SetRemoveAction( Constraint::RemoveAction::Discard );
+  constraint.Apply();
+
+  // Check value after one render, it should be constrained
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  // Render another frame, ensure the other value has also been updated
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  // Remove the actor from the stage
+  actor.Unparent();
+
+  // Check value while off-stage, the constraint is no longer being applied as it's off-stage
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Check the other buffer, the constraint should not be applied to this either.
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 1.0f, TEST_LOCATION );
+
+  // Add the actor back to the stage and check the value, the constraint should have been re-applied
+  Stage::GetCurrent().Add( actor );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  // Render for another frame to ensure both buffers have the correct value
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.5f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
index c28322f..305fb14 100644 (file)
@@ -17,6 +17,9 @@
  * limitations under the License.
  */
 
+// EXTERNAL INCLDUES
+#include <cstdint> // int8_t
+
 #include <dali/internal/update/animation/scene-graph-animator.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
 #include <dali/internal/update/animation/property-accessor.h>
@@ -66,8 +69,16 @@ public:
    */
   void ResetToBaseValue( BufferIndex updateBufferIndex )
   {
-    if( mPropertyOwner != nullptr && !mDisconnected )
+    if( mPropertyOwner != nullptr && mActive )
     {
+      // If property-owner has disconnected, start aging.
+      // We need to reset the property for two frames after disconnection to ensure both
+      // property values are set appropriately.
+      if( mDisconnected )
+      {
+        --mActive;
+      }
+
       mBaseProperty->ResetToBaseValue( updateBufferIndex );
     }
   };
@@ -83,6 +94,7 @@ public:
   virtual void PropertyOwnerConnected( PropertyOwner& owner ) override
   {
     mDisconnected = false;
+    mActive = ACTIVE;
   }
 
   /**
@@ -105,7 +117,8 @@ public:
     mPropertyOwner = nullptr;
 
     // Don't need to wait another frame as the property is being destroyed
-    mRunning = 0;
+    mActive = STOPPED;
+    mRunning = STOPPED;
   }
 
   /**
@@ -119,16 +132,23 @@ public:
    */
   virtual bool IsFinished()
   {
-    bool finished = mRunning <= 0;
-    if( mRunning == 1 )
+    bool finished = mRunning <= STOPPED;
+    if( mRunning == AGING )
     {
-      mRunning = 0;
+      mRunning = STOPPED;
     }
     return finished;
   }
 
 protected:
 
+  enum
+  {
+    STOPPED = 0,
+    AGING   = 1,
+    ACTIVE  = 2,
+  };
+
   /**
    * Constructor
    *
@@ -139,14 +159,16 @@ protected:
                         PropertyBase* baseProperty )
   : mPropertyOwner( propertyOwner ),
     mBaseProperty( baseProperty ),
-    mRunning( 2 ),
+    mRunning( ACTIVE ),
+    mActive( ACTIVE ),
     mDisconnected( false )
   {
   }
 
   PropertyOwner* mPropertyOwner; ///< The property owner
   PropertyBase* mBaseProperty;   ///< The base property being animated or constrained
-  int mRunning;                  ///< 2 if running, 1 if aging, 0 if stopped
+  int8_t mRunning;                  ///< Used to determine if we should finish or not, 2 if running, 1 if aging, 0 if stopped
+  int8_t mActive;                   ///< 2 if active, 1 if aging, 0 if stopped
   bool mDisconnected;            ///< True if the property owner has been disconnected
 };