/*
- * 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.
(*iter)->OnDestroy();
Node::Delete(*iter);
}
+ nodeIdMap.clear();
for(auto&& scene : scenes)
{
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)
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));
}
}
}
+ mImpl->nodeIdMap.erase(layer->GetId());
+
mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), layer);
// Notify the layer about impending destruction
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);
}
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);
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);
RemoveCamera(static_cast<Camera*>(node));
}
+ mImpl->nodeIdMap.erase(node->GetId());
+
mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
// Notify the Node about impending destruction
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");
bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
{
bool animationActive = false;
- bool animationLooped = false;
auto&& iter = mImpl->animations.Begin();
{
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();
}
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());
}
// Reset dirty flag
for(auto&& renderer : mImpl->renderers)
{
- renderer->ResetDirtyFlag();
+ renderer->SetUpdated(false);
}
for(auto&& shader : mImpl->shaders)
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)
// 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())
{