Removed sets of connected/disconnected nodes. Brought back a vector of sorted nodes...
[platform/core/uifw/dali-core.git] / dali / internal / update / nodes / node.cpp
1 /*
2  * Copyright (c) 2014 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/nodes/node.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/common/internal-constants.h>
23 #include <dali/internal/common/memory-pool-object-allocator.h>
24 #include <dali/internal/update/node-attachments/node-attachment.h>
25 #include <dali/internal/update/common/discard-queue.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/common/constants.h>
28
29 namespace //Unnamed namespace
30 {
31 //Memory pool used to allocate new nodes. Memory used by this pool will be released when shutting down DALi
32 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Node> gNodeMemoryPool;
33 }
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace SceneGraph
42 {
43
44 const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION );
45 const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
46
47 Node* Node::New()
48 {
49   return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node();
50 }
51
52 Node::Node()
53 : mParentOrigin( ParentOrigin::DEFAULT ),
54   mAnchorPoint( AnchorPoint::DEFAULT ),
55   mSize(),     // zero initialized by default
56   mPosition(), // zero initialized by default
57   mOrientation(), // initialized to identity by default
58   mScale( Vector3::ONE ),
59   mVisible( true ),
60   mColor( Color::WHITE ),
61   mWorldPosition(), // zero initialized by default
62   mWorldOrientation(), // initialized to identity by default
63   mWorldScale( Vector3::ONE ),
64   mWorldMatrix(),
65   mWorldColor( Color::WHITE ),
66   mParent( NULL ),
67   mExclusiveRenderTask( NULL ),
68   mAttachment( NULL ),
69   mChildren(),
70   mRegenerateUniformMap( 0 ),
71   mDepth(0u),
72   mDirtyFlags(AllFlags),
73   mIsRoot( false ),
74   mInheritOrientation( true ),
75   mInheritScale( true ),
76   mDrawMode( DrawMode::NORMAL ),
77   mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
78   mColorMode( DEFAULT_COLOR_MODE )
79 {
80   mUniformMapChanged[0] = 0u;
81   mUniformMapChanged[1] = 0u;
82 }
83
84 Node::~Node()
85 {
86 }
87
88 void Node::operator delete( void* ptr )
89 {
90   gNodeMemoryPool.FreeThreadSafe( static_cast<Node*>( ptr ) );
91 }
92
93 void Node::OnDestroy()
94 {
95   // Node attachments should be notified about the disconnection.
96   if ( mAttachment )
97   {
98     mAttachment->OnDestroy();
99   }
100
101   // Animators, Constraints etc. should be disconnected from the child's properties.
102   PropertyOwner::Destroy();
103 }
104
105 void Node::Attach( NodeAttachment& object )
106 {
107   DALI_ASSERT_DEBUG(!mAttachment);
108
109   object.SetParent(*this);
110
111   mAttachment = &object;
112   SetAllDirtyFlags();
113
114   mAttachment->ConnectedToSceneGraph();
115 }
116
117 void Node::SetRoot(bool isRoot)
118 {
119   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
120
121   mIsRoot = isRoot;
122 }
123
124 void Node::AddUniformMapping( UniformPropertyMapping* map )
125 {
126   PropertyOwner::AddUniformMapping( map );
127   mRegenerateUniformMap = 2;
128 }
129
130 void Node::RemoveUniformMapping( const std::string& uniformName )
131 {
132   PropertyOwner::RemoveUniformMapping( uniformName );
133   mRegenerateUniformMap = 2;
134 }
135
136 void Node::PrepareRender( BufferIndex bufferIndex )
137 {
138   if(mRegenerateUniformMap != 0 )
139   {
140     if( mRegenerateUniformMap == 2 )
141     {
142       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
143       localMap.Resize(0);
144
145       for( unsigned int i=0, count=mUniformMaps.Count(); i<count; ++i )
146       {
147         localMap.PushBack( &mUniformMaps[i] );
148       }
149     }
150     else if( mRegenerateUniformMap == 1 )
151     {
152       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
153       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-bufferIndex ];
154
155       localMap.Resize( oldMap.Count() );
156
157       unsigned int index=0;
158       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
159       {
160         localMap[index] = *iter;
161       }
162     }
163     --mRegenerateUniformMap;
164     mUniformMapChanged[bufferIndex] = 1u;
165   }
166 }
167
168 void Node::ConnectChild( Node* childNode )
169 {
170   DALI_ASSERT_ALWAYS( this != childNode );
171   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
172   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
173
174   childNode->SetParent( *this );
175
176   // Everything should be reinherited when reconnected to scene-graph
177   childNode->SetAllDirtyFlags();
178
179   // Add the node to the end of the child list.
180   mChildren.PushBack( childNode );
181
182   // Inform property observers of new connection
183   childNode->ConnectToSceneGraph();
184
185   // Inform child node attachment that the node has been added to the stage
186   if( childNode->mAttachment )
187   {
188     childNode->mAttachment->ConnectedToSceneGraph();
189   }
190 }
191
192 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode )
193 {
194   DALI_ASSERT_ALWAYS( this != &childNode );
195   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
196
197   // Find the childNode and remove it
198   Node* found( NULL );
199
200   const NodeIter endIter = mChildren.End();
201   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
202   {
203     Node* current = *iter;
204     if ( current == &childNode )
205     {
206       found = current;
207       mChildren.Erase( iter ); // order matters here
208       break; // iter is no longer valid
209     }
210   }
211   DALI_ASSERT_ALWAYS( NULL != found );
212
213   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
214 }
215
216 void Node::RemoveRenderer( Renderer* renderer )
217 {
218   unsigned int rendererCount( mRenderer.Size() );
219   for( unsigned int i(0); i<rendererCount; ++i )
220   {
221     if( mRenderer[i] == renderer )
222     {
223       mRenderer.Erase( mRenderer.Begin()+i);
224       return;
225     }
226   }
227 }
228
229 int Node::GetDirtyFlags() const
230 {
231   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
232   int flags = mDirtyFlags;
233   const bool sizeFlag = mSize.IsClean();
234
235   if ( !(flags & TransformFlag) )
236   {
237     // Check whether the transform related properties have changed
238     if( !sizeFlag            ||
239         !mPosition.IsClean() ||
240         !mOrientation.IsClean() ||
241         !mScale.IsClean()    ||
242         mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
243         mAnchorPoint.InputChanged() )
244     {
245       flags |= TransformFlag;
246     }
247   }
248
249   // Check whether the visible property has changed
250   if ( !mVisible.IsClean() )
251   {
252     flags |= VisibleFlag;
253   }
254
255   // Check whether the color property has changed
256   if ( !mColor.IsClean() )
257   {
258     flags |= ColorFlag;
259   }
260
261   // Check whether the size property has changed
262   if ( !sizeFlag )
263   {
264     flags |= SizeFlag;
265    }
266
267   return flags;
268 }
269
270 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
271 {
272   // clear dirty flags in parent origin & anchor point
273   mParentOrigin.Clear();
274   mAnchorPoint.Clear();
275   // Reset default properties
276   mSize.ResetToBaseValue( updateBufferIndex );
277   mPosition.ResetToBaseValue( updateBufferIndex );
278   mOrientation.ResetToBaseValue( updateBufferIndex );
279   mScale.ResetToBaseValue( updateBufferIndex );
280   mVisible.ResetToBaseValue( updateBufferIndex );
281   mColor.ResetToBaseValue( updateBufferIndex );
282
283   mDirtyFlags = NothingFlag;
284 }
285
286 void Node::SetParent(Node& parentNode)
287 {
288   DALI_ASSERT_ALWAYS(this != &parentNode);
289   DALI_ASSERT_ALWAYS(!mIsRoot);
290   DALI_ASSERT_ALWAYS(mParent == NULL);
291
292   mParent = &parentNode;
293   mDepth = mParent->GetDepth() + 1u;
294 }
295
296 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
297 {
298   DALI_ASSERT_ALWAYS(!mIsRoot);
299   DALI_ASSERT_ALWAYS(mParent != NULL);
300
301   const NodeIter endIter = mChildren.End();
302   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
303   {
304     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
305   }
306
307   // Animators, Constraints etc. should be disconnected from the child's properties.
308   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
309
310   // Remove back-pointer to parent
311   mParent = NULL;
312   mDepth = 0u;
313
314   // Remove all child pointers
315   mChildren.Clear();
316
317   // Inform child node attachment that the node has been removed from the stage
318   if( mAttachment )
319   {
320     mAttachment->DisconnectedFromSceneGraph();
321   }
322
323 }
324
325 } // namespace SceneGraph
326
327 } // namespace Internal
328
329 } // namespace Dali