Add a node resetter that resets the animatable properties for two frames after node... 05/265205/4
authorRichard Huang <r.huang@samsung.com>
Tue, 12 Oct 2021 15:26:04 +0000 (16:26 +0100)
committerRichard <r.huang@samsung.com>
Thu, 18 Nov 2021 16:07:41 +0000 (16:07 +0000)
Change-Id: I3a64c3719107c231085a524b05c1302977ccde10

dali/internal/update/common/node-resetter.h [new file with mode: 0644]
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h

diff --git a/dali/internal/update/common/node-resetter.h b/dali/internal/update/common/node-resetter.h
new file mode 100644 (file)
index 0000000..7e73a6b
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
+#define DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLDUES
+#include <cstdint> // int8_t
+
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/property-component-accessor.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/nodes/node.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+/**
+ * Class to reset the node's properties to their base values. Used by UpdateManager
+ * to reset the node properties after the node is connected to the scene graph.
+ */
+class NodeResetter : public PropertyOwner::Observer
+{
+public:
+  /**
+   * New method.
+   * @param[in] node  The node
+   * @return the new node resetter
+   */
+  static NodeResetter* New(const Node& node)
+  {
+    return new NodeResetter(const_cast<Node*>(&node));
+  }
+
+  /**
+   * Virtual Destructor
+   */
+  ~NodeResetter() override
+  {
+    if(mNode != nullptr)
+    {
+      mNode->RemoveObserver(*this);
+    }
+  }
+
+  /**
+   * Initialize.
+   *
+   * Watches the node to track if it's disconnected or not.
+   */
+  void Initialize()
+  {
+    mNode->AddObserver(*this);
+  }
+
+  /**
+   * Reset the node properties to their base values if the node is still alive and on stage
+   * @param[in] updateBufferIndex the current buffer index
+   */
+  void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if(mNode != nullptr && mActive)
+    {
+      // Start aging the node properties.
+      // We need to reset the node properties for two frames to ensure both
+      // property values are set appropriately.
+      //      if(mDisconnected)
+      {
+        --mActive;
+      }
+
+      mNode->mVisible.ResetToBaseValue(updateBufferIndex);
+      mNode->mCulled.ResetToBaseValue(updateBufferIndex);
+      mNode->mColor.ResetToBaseValue(updateBufferIndex);
+      mNode->mUpdateSizeHint.ResetToBaseValue(updateBufferIndex);
+    }
+  };
+
+  /**
+   * Called when the node is connected to the scene graph.
+   *
+   * Note, this resetter object may be created after the node has been connected
+   * to the scene graph, so we track disconnection and re-connection instead of connection
+   *
+   * @param[in] owner The property owner
+   */
+  void PropertyOwnerConnected(PropertyOwner& owner) override
+  {
+    mDisconnected = false;
+    mActive       = ACTIVE;
+  }
+
+  /**
+   * Called when mPropertyOwner is disconnected from the scene graph.
+   * @param[in] bufferIndex the current buffer index
+   * @param[in] owner The property owner
+   */
+  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
+  {
+    mDisconnected = true;
+  }
+
+  /**
+   * Called shortly before the propertyOwner is destroyed
+   * @param[in] owner The property owner
+   */
+  void PropertyOwnerDestroyed(PropertyOwner& owner) override
+  {
+    mDisconnected = true;
+    mNode         = nullptr;
+
+    // Don't need to wait another frame as the properties are being destroyed
+    mActive = STOPPED;
+  }
+
+  /**
+   * Determine if the node resetter has finished.
+   *
+   * @return true if the node resetter has finished.
+   */
+  virtual bool IsFinished()
+  {
+    return mActive <= STOPPED;
+  }
+
+protected:
+  enum
+  {
+    STOPPED = 0,
+    AGING   = 1,
+    ACTIVE  = 2,
+  };
+
+  /**
+   * Constructor
+   *
+   * @param[in] node The node storing the base properties
+   */
+  NodeResetter(Node* node)
+  : mNode(node),
+    mActive(ACTIVE),
+    mDisconnected(false)
+  {
+  }
+
+  Node*  mNode;         ///< The node that owns the properties
+  int8_t mActive;       ///< 2 if active, 1 if aging, 0 if stopped
+  bool   mDisconnected; ///< True if the node has been disconnected
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
index 7f8eca8..86db620 100644 (file)
@@ -268,6 +268,7 @@ struct UpdateManager::Impl
   OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
 
   OwnerContainer<PropertyResetterBase*> propertyResetters;     ///< A container of property resetters
+  OwnerContainer<NodeResetter*>         nodeResetters;         ///< A container of node resetters
   OwnerContainer<Animation*>            animations;            ///< A container of owned animations
   PropertyNotificationContainer         propertyNotifications; ///< A container of owner property notifications.
   OwnerContainer<Renderer*>             renderers;             ///< A container of owned renderers
@@ -340,6 +341,9 @@ void UpdateManager::InstallRoot(OwnerPointer<Layer>& layer)
   rootLayer->CreateTransform(&mImpl->transformManager);
   rootLayer->SetRoot(true);
 
+  OwnerPointer<SceneGraph::NodeResetter> nodeResetter = SceneGraph::NodeResetter::New(*rootLayer);
+  AddNodeResetter(nodeResetter);
+
   mImpl->scenes.emplace_back(new Impl::SceneInfo(rootLayer));
 }
 
@@ -384,6 +388,9 @@ void UpdateManager::ConnectNode(Node* parent, Node* node)
 
   parent->ConnectChild(node);
 
+  OwnerPointer<SceneGraph::NodeResetter> nodeResetter = SceneGraph::NodeResetter::New(*node);
+  AddNodeResetter(nodeResetter);
+
   // Inform the frame-callback-processor, if set, about the node-hierarchy changing
   if(mImpl->frameCallbackProcessor)
   {
@@ -555,6 +562,12 @@ void UpdateManager::AddPropertyResetter(OwnerPointer<PropertyResetterBase>& prop
   mImpl->propertyResetters.PushBack(propertyResetter.Release());
 }
 
+void UpdateManager::AddNodeResetter(OwnerPointer<NodeResetter>& nodeResetter)
+{
+  nodeResetter->Initialize();
+  mImpl->nodeResetters.PushBack(nodeResetter.Release());
+}
+
 void UpdateManager::AddPropertyNotification(OwnerPointer<PropertyNotification>& propertyNotification)
 {
   mImpl->propertyNotifications.PushBack(propertyNotification.Release());
@@ -659,19 +672,36 @@ void UpdateManager::ResetProperties(BufferIndex bufferIndex)
   // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
   mImpl->animationFinishedDuringUpdate = false;
 
+  // Reset node properties
+  std::vector<NodeResetter*> nodeResetterToDelete;
+  for(auto&& element : mImpl->nodeResetters)
+  {
+    element->ResetToBaseValue(bufferIndex);
+    if(element->IsFinished())
+    {
+      nodeResetterToDelete.push_back(element);
+    }
+  }
+
+  // If a node resetter is no longer required, delete it.
+  for(auto&& elementPtr : nodeResetterToDelete)
+  {
+    mImpl->nodeResetters.EraseObject(elementPtr);
+  }
+
   // Reset all animating / constrained properties
-  std::vector<PropertyResetterBase*> toDelete;
+  std::vector<PropertyResetterBase*> propertyResettertoDelete;
   for(auto&& element : mImpl->propertyResetters)
   {
     element->ResetToBaseValue(bufferIndex);
     if(element->IsFinished())
     {
-      toDelete.push_back(element);
+      propertyResettertoDelete.push_back(element);
     }
   }
 
-  // If a resetter is no longer required (the animator or constraint has been removed), delete it.
-  for(auto&& elementPtr : toDelete)
+  // If a property resetter is no longer required (the animator or constraint has been removed), delete it.
+  for(auto&& elementPtr : propertyResettertoDelete)
   {
     mImpl->propertyResetters.EraseObject(elementPtr);
   }
index 8a8b2b3..da66ea4 100644 (file)
@@ -33,6 +33,7 @@
 #include <dali/internal/render/renderers/render-vertex-buffer.h>
 #include <dali/internal/render/shaders/render-shader.h> // for OwnerPointer< Shader >
 #include <dali/internal/update/animation/scene-graph-animation.h>
+#include <dali/internal/update/common/node-resetter.h>
 #include <dali/internal/update/common/property-resetter.h>
 #include <dali/internal/update/common/scene-graph-buffers.h>
 #include <dali/internal/update/common/scene-graph-property-notification.h>
@@ -259,6 +260,13 @@ public:
    */
   void AddPropertyResetter(OwnerPointer<PropertyResetterBase>& propertyResetter);
 
+  /**
+   * Add a node resetter. UpdateManager takes ownership of the object.
+   * It will be killed by UpdateManager when the node is disconnected from the scene graph;
+   * or when the node is destroyed.
+   */
+  void AddNodeResetter(OwnerPointer<NodeResetter>& nodeResetter);
+
   // Property Notification
 
   /**