--- /dev/null
+#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
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
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));
}
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)
{
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());
// 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);
}