Append Stopped animation notify list at Update Animation time
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-manager.cpp
index 484687a..7a971f5 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.
@@ -224,6 +224,7 @@ struct UpdateManager::Impl
       (*iter)->OnDestroy();
       Node::Delete(*iter);
     }
+    nodeIdMap.clear();
 
     for(auto&& scene : scenes)
     {
@@ -275,6 +276,8 @@ struct UpdateManager::Impl
 
   Vector<Node*> nodes; ///< A container of all instantiated nodes
 
+  std::unordered_map<uint32_t, Node*> nodeIdMap; ///< A container of nodes map by id.
+
   Vector<Camera*> cameras; ///< A container of cameras. Note : these cameras are owned by Impl::nodes.
 
   OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
@@ -360,6 +363,10 @@ void UpdateManager::InstallRoot(OwnerPointer<Layer>& layer)
 
   rootLayer->AddInitializeResetter(*this);
 
+  // Do not allow to insert duplicated nodes.
+  // It could be happened if node id is overflowed.
+  DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rootLayer->GetId(), rootLayer}).second);
+
   mImpl->scenes.emplace_back(new Impl::SceneInfo(rootLayer));
 }
 
@@ -377,6 +384,8 @@ void UpdateManager::UninstallRoot(Layer* layer)
     }
   }
 
+  mImpl->nodeIdMap.erase(layer->GetId());
+
   mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), layer);
 
   // Notify the layer about impending destruction
@@ -396,7 +405,12 @@ void UpdateManager::AddNode(OwnerPointer<Node>& node)
     AddCamera(static_cast<Camera*>(rawNode));
   }
 
+  // Do not allow to insert duplicated nodes.
+  // It could be happened if node id is overflowed.
+  DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rawNode->GetId(), rawNode}).second);
+
   mImpl->nodes.PushBack(rawNode);
+
   rawNode->CreateTransform(&mImpl->transformManager);
 }
 
@@ -408,6 +422,7 @@ void UpdateManager::ConnectNode(Node* parent, Node* node)
 
   DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] ConnectNode\n", node);
 
+  parent->SetDirtyFlag(NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
   parent->ConnectChild(node);
 
   node->AddInitializeResetter(*this);
@@ -425,7 +440,7 @@ void UpdateManager::DisconnectNode(Node* node)
 
   Node* parent = node->GetParent();
   DALI_ASSERT_ALWAYS(nullptr != parent);
-  parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED); // make parent dirty so that render items dont get reused
+  parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED | NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
 
   parent->DisconnectChild(mSceneGraphBuffers.GetUpdateBufferIndex(), *node);
 
@@ -460,6 +475,8 @@ void UpdateManager::DestroyNode(Node* node)
     RemoveCamera(static_cast<Camera*>(node));
   }
 
+  mImpl->nodeIdMap.erase(node->GetId());
+
   mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
 
   // Notify the Node about impending destruction
@@ -573,12 +590,16 @@ void UpdateManager::StopAnimation(Animation* animation)
 
   bool animationFinished = animation->Stop(mSceneGraphBuffers.GetUpdateBufferIndex());
 
-  // Queue this animation into notify required animations. Since we need to send Finished signal
-  mImpl->notifyRequiredAnimations.PushBack(animation->GetNotifyId());
-
   mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
 }
 
+void UpdateManager::ClearAnimation(Animation* animation)
+{
+  DALI_ASSERT_DEBUG(animation && "NULL animation called to clear");
+
+  animation->ClearAnimator(mSceneGraphBuffers.GetUpdateBufferIndex());
+}
+
 void UpdateManager::RemoveAnimation(Animation* animation)
 {
   DALI_ASSERT_DEBUG(animation && "NULL animation called to remove");
@@ -802,7 +823,6 @@ bool UpdateManager::ProcessGestures(BufferIndex bufferIndex, uint32_t lastVSyncT
 bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
 {
   bool animationActive = false;
-  bool animationLooped = false;
 
   auto&& iter = mImpl->animations.Begin();
 
@@ -810,9 +830,9 @@ bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
   {
     Animation* animation             = *iter;
     bool       finished              = false;
-    bool       looped                = false;
+    bool       stopped               = false;
     bool       progressMarkerReached = false;
-    animation->Update(bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached);
+    animation->Update(bufferIndex, elapsedSeconds, stopped, finished, progressMarkerReached);
 
     animationActive = animationActive || animation->IsActive();
 
@@ -822,10 +842,9 @@ bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
     }
 
     mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
-    animationLooped                      = animationLooped || looped;
 
-    // queue the notification on finished or stoped or looped (to update loop count)
-    if(finished || looped)
+    // queue the notification on finished or stopped
+    if(finished || stopped)
     {
       mImpl->notifyRequiredAnimations.PushBack(animation->GetNotifyId());
     }
@@ -1223,7 +1242,7 @@ void UpdateManager::PostRender()
   // Reset dirty flag
   for(auto&& renderer : mImpl->renderers)
   {
-    renderer->ResetDirtyFlag();
+    renderer->SetUpdated(false);
   }
 
   for(auto&& shader : mImpl->shaders)
@@ -1298,6 +1317,17 @@ void UpdateManager::RequestRendering()
   mImpl->renderingRequired = true;
 }
 
+Node* UpdateManager::GetNodePointerById(uint32_t nodeId) const
+{
+  Node* foundNodePointer = nullptr;
+  auto  iter             = mImpl->nodeIdMap.find(nodeId);
+  if(iter != mImpl->nodeIdMap.end())
+  {
+    foundNodePointer = iter->second;
+  }
+  return foundNodePointer;
+}
+
 void UpdateManager::SetLayerDepths(const SortedLayerPointers& layers, const Layer* rootLayer)
 {
   for(auto&& scene : mImpl->scenes)
@@ -1315,9 +1345,13 @@ void UpdateManager::SetDepthIndices(OwnerPointer<NodeDepths>& nodeDepths)
   // note, this vector is already in depth order.
   // So if we reverse iterate, we can assume that
   // my descendant node's depth index are updated.
+
+  // And also, This API is the last flushed message.
+  // We can now setup the DESCENDENT_HIERARCHY_CHANGED flag here.
   for(auto rIter = nodeDepths->nodeDepths.rbegin(), rEndIter = nodeDepths->nodeDepths.rend(); rIter != rEndIter; rIter++)
   {
     auto* node = rIter->node;
+    node->PropagateDescendentFlags();
     node->SetDepthIndex(rIter->sortedDepth);
     if(node->IsChildrenReorderRequired())
     {