Keep node by id + Make SceneGraphTraveler don't travel anymore
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / scene-graph-traveler.cpp
1 /*
2  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/update/manager/scene-graph-traveler.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/update/manager/update-manager.h>
23 #include <dali/internal/update/nodes/node.h>
24
25 namespace Dali
26 {
27 namespace Internal
28 {
29 SceneGraphTraveler::SceneGraphTraveler(SceneGraph::UpdateManager& updateManager, SceneGraph::Node& rootNode)
30 : SceneGraphTravelerInterface(updateManager),
31   mRootNode(rootNode),
32   mInvalidated{false}
33 {
34   mRootNode.AddObserver(*this);
35   Clear();
36 }
37
38 SceneGraphTraveler::~SceneGraphTraveler()
39 {
40   if(!mInvalidated)
41   {
42     mRootNode.RemoveObserver(*this);
43   }
44 }
45
46 SceneGraph::Node* SceneGraphTraveler::FindNode(uint32_t id)
47 {
48   SceneGraph::Node* node = nullptr;
49
50   if(!mInvalidated)
51   {
52     // Find node in cached map
53     auto iter = mTravledNodeMap.find(id);
54     if(iter != mTravledNodeMap.end())
55     {
56       node = iter->second;
57     }
58     else
59     {
60       SceneGraph::Node* currentNode = mUpdateManager.GetNodePointerById(id);
61
62       bool isNodeUnderRootNode = false;
63
64       std::vector<std::pair<uint32_t, SceneGraph::Node*>> nodeStack;
65
66       SceneGraph::Node* iterateNode = currentNode;
67
68       while(iterateNode)
69       {
70         uint32_t iterateNodeId = iterateNode->GetId();
71
72         auto iter = mTravledNodeMap.find(iterateNodeId);
73         if(iter != mTravledNodeMap.end())
74         {
75           // iter->second could be nullptr if it was failed item before.
76           if(iter->second != nullptr)
77           {
78             isNodeUnderRootNode = true;
79           }
80           break;
81         }
82         nodeStack.push_back({iterateNodeId, iterateNode});
83
84         // Go to parent.
85         iterateNode = iterateNode->GetParent();
86       }
87
88       // Store current found result.
89       for(auto&& idPair : nodeStack)
90       {
91         mTravledNodeMap.insert({idPair.first, isNodeUnderRootNode ? idPair.second : nullptr});
92       }
93
94       if(isNodeUnderRootNode)
95       {
96         node = currentNode;
97       }
98     }
99   }
100
101   return node;
102 }
103
104 void SceneGraphTraveler::Clear()
105 {
106   mTravledNodeMap.clear();
107   mTravledNodeMap.rehash(0u); ///< Note : We have to reduce capacity of hash map. Without this line, clear() API will be slow downed.
108   if(!mInvalidated)
109   {
110     mTravledNodeMap.insert({mRootNode.GetId(), &mRootNode});
111   }
112 }
113
114 } // namespace Internal
115
116 } // namespace Dali