Added sibling order property to Actor
[platform/core/uifw/dali-core.git] / dali / internal / update / nodes / node.cpp
1 /*
2  * Copyright (c) 2016 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/common/discard-queue.h>
25 #include <dali/internal/update/manager/geometry-batcher.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 : mTransformManager( NULL ),
54   mTransformId( INVALID_TRANSFORM_ID ),
55   mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ),
56   mAnchorPoint( TRANSFORM_PROPERTY_ANCHOR_POINT ),
57   mSize( TRANSFORM_PROPERTY_SIZE ),                                               // Zero initialized by default
58   mPosition( TRANSFORM_PROPERTY_POSITION ),                                       // Zero initialized by default
59   mOrientation(),                                                                 // Initialized to identity by default
60   mScale( TRANSFORM_PROPERTY_SCALE ),
61   mVisible( true ),
62   mColor( Color::WHITE ),
63   mWorldPosition( TRANSFORM_PROPERTY_WORLD_POSITION, Vector3( 0.0f,0.0f,0.0f ) ), // Zero initialized by default
64   mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3( 1.0f,1.0f,1.0f ) ),
65   mWorldOrientation(),                                                            // Initialized to identity by default
66   mWorldMatrix(),
67   mWorldColor( Color::WHITE ),
68   mGeometryBatcher( NULL ),
69   mBatchIndex( BATCH_NULL_HANDLE ),
70   mClippingSortModifier( 0u ),
71   mIsBatchParent( false ),
72   mParent( NULL ),
73   mBatchParent( NULL ),
74   mExclusiveRenderTask( NULL ),
75   mChildren(),
76   mClippingDepth( 0u ),
77   mDepthIndex( 0u ),
78   mRegenerateUniformMap( 0 ),
79   mDirtyFlags( AllFlags ),
80   mDrawMode( DrawMode::NORMAL ),
81   mColorMode( DEFAULT_COLOR_MODE ),
82   mClippingMode( ClippingMode::DISABLED ),
83   mIsRoot( false )
84 {
85   mUniformMapChanged[0] = 0u;
86   mUniformMapChanged[1] = 0u;
87 }
88
89 Node::~Node()
90 {
91   if( mTransformId != INVALID_TRANSFORM_ID )
92   {
93     mTransformManager->RemoveTransform(mTransformId);
94   }
95 }
96
97 void Node::operator delete( void* ptr )
98 {
99   gNodeMemoryPool.FreeThreadSafe( static_cast<Node*>( ptr ) );
100 }
101
102 void Node::OnDestroy()
103 {
104   // Animators, Constraints etc. should be disconnected from the child's properties.
105   PropertyOwner::Destroy();
106 }
107
108 void Node::CreateTransform( SceneGraph::TransformManager* transformManager )
109 {
110   //Create a new transform
111   mTransformManager = transformManager;
112   mTransformId = transformManager->CreateTransform();
113
114   //Initialize all the animatable properties
115   mPosition.Initialize( transformManager, mTransformId );
116   mScale.Initialize( transformManager, mTransformId );
117   mOrientation.Initialize( transformManager, mTransformId );
118   mSize.Initialize( transformManager, mTransformId );
119   mParentOrigin.Initialize( transformManager, mTransformId );
120   mAnchorPoint.Initialize( transformManager, mTransformId );
121
122   //Initialize all the input properties
123   mWorldPosition.Initialize( transformManager, mTransformId );
124   mWorldScale.Initialize( transformManager, mTransformId );
125   mWorldOrientation.Initialize( transformManager, mTransformId );
126   mWorldMatrix.Initialize( transformManager, mTransformId );
127 }
128
129 void Node::SetRoot(bool isRoot)
130 {
131   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
132
133   mIsRoot = isRoot;
134 }
135
136 void Node::AddUniformMapping( UniformPropertyMapping* map )
137 {
138   PropertyOwner::AddUniformMapping( map );
139   mRegenerateUniformMap = 2;
140 }
141
142 void Node::RemoveUniformMapping( const std::string& uniformName )
143 {
144   PropertyOwner::RemoveUniformMapping( uniformName );
145   mRegenerateUniformMap = 2;
146 }
147
148 void Node::PrepareRender( BufferIndex bufferIndex )
149 {
150   if(mRegenerateUniformMap != 0 )
151   {
152     if( mRegenerateUniformMap == 2 )
153     {
154       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
155       localMap.Resize(0);
156
157       for( unsigned int i=0, count=mUniformMaps.Count(); i<count; ++i )
158       {
159         localMap.PushBack( &mUniformMaps[i] );
160       }
161     }
162     else if( mRegenerateUniformMap == 1 )
163     {
164       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
165       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-bufferIndex ];
166
167       localMap.Resize( oldMap.Count() );
168
169       unsigned int index=0;
170       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
171       {
172         localMap[index] = *iter;
173       }
174     }
175     --mRegenerateUniformMap;
176     mUniformMapChanged[bufferIndex] = 1u;
177   }
178 }
179
180 void Node::ConnectChild( Node* childNode )
181 {
182   DALI_ASSERT_ALWAYS( this != childNode );
183   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
184   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
185
186   childNode->SetParent( *this );
187
188   // Everything should be reinherited when reconnected to scene-graph
189   childNode->SetAllDirtyFlags();
190
191   // Add the node to the end of the child list.
192   mChildren.PushBack( childNode );
193
194   // Inform property observers of new connection
195   childNode->ConnectToSceneGraph();
196 }
197
198 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode )
199 {
200   DALI_ASSERT_ALWAYS( this != &childNode );
201   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
202
203   // Find the childNode and remove it
204   Node* found( NULL );
205
206   const NodeIter endIter = mChildren.End();
207   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
208   {
209     Node* current = *iter;
210     if ( current == &childNode )
211     {
212       found = current;
213       mChildren.Erase( iter ); // order matters here
214       break; // iter is no longer valid
215     }
216   }
217   DALI_ASSERT_ALWAYS( NULL != found );
218
219   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
220 }
221
222 void Node::AddRenderer( Renderer* renderer )
223 {
224   // Check that it has not been already added.
225   unsigned int rendererCount( mRenderer.Size() );
226   for( unsigned int i(0); i < rendererCount; ++i )
227   {
228     if( mRenderer[i] == renderer )
229     {
230       // Renderer is already in the list.
231       return;
232     }
233   }
234
235   // If it is the first renderer added, make sure the world transform will be calculated
236   // in the next update as world transform is not computed if node has no renderers.
237   if( rendererCount == 0 )
238   {
239     mDirtyFlags |= TransformFlag;
240   }
241
242   mRenderer.PushBack( renderer );
243
244   // Tell geometry batcher if should batch the child
245   if( mRenderer.Size() == 1 && mRenderer[0]->mBatchingEnabled )
246   {
247     mGeometryBatcher->AddNode( this );
248   }
249 }
250
251 void Node::RemoveRenderer( Renderer* renderer )
252 {
253   unsigned int rendererCount( mRenderer.Size() );
254   for( unsigned int i(0); i<rendererCount; ++i )
255   {
256     if( mRenderer[i] == renderer )
257     {
258       mRenderer.Erase( mRenderer.Begin()+i);
259       return;
260     }
261   }
262 }
263
264 int Node::GetDirtyFlags() const
265 {
266   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
267   int flags = mDirtyFlags;
268
269   // Check whether the visible property has changed
270   if ( !mVisible.IsClean() )
271   {
272     flags |= VisibleFlag;
273   }
274
275   // Check whether the color property has changed
276   if ( !mColor.IsClean() )
277   {
278     flags |= ColorFlag;
279   }
280
281   return flags;
282 }
283
284 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
285 {
286   mVisible.ResetToBaseValue( updateBufferIndex );
287   mColor.ResetToBaseValue( updateBufferIndex );
288
289   mDirtyFlags = NothingFlag;
290 }
291
292 void Node::SetParent( Node& parentNode )
293 {
294   DALI_ASSERT_ALWAYS(this != &parentNode);
295   DALI_ASSERT_ALWAYS(!mIsRoot);
296   DALI_ASSERT_ALWAYS(mParent == NULL);
297
298   mParent = &parentNode;
299
300   if( mTransformId != INVALID_TRANSFORM_ID )
301   {
302     mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
303   }
304 }
305
306 void Node::SetBatchParent( Node* batchParentNode )
307 {
308   DALI_ASSERT_ALWAYS(!mIsRoot);
309   mBatchParent = batchParentNode;
310 }
311
312 void Node::SetIsBatchParent( bool enabled )
313 {
314   if( mIsBatchParent != enabled )
315   {
316     mIsBatchParent = enabled;
317
318     if( enabled )
319     {
320       mGeometryBatcher->AddBatchParent( this );
321     }
322     else
323     {
324       mGeometryBatcher->RemoveBatchParent( this );
325     }
326   }
327 }
328
329 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
330 {
331   DALI_ASSERT_ALWAYS(!mIsRoot);
332   DALI_ASSERT_ALWAYS(mParent != NULL);
333
334   const NodeIter endIter = mChildren.End();
335   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
336   {
337     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
338   }
339
340   // Animators, Constraints etc. should be disconnected from the child's properties.
341   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
342
343   // Remove back-pointer to parent
344   mParent = NULL;
345
346   // Remove all child pointers
347   mChildren.Clear();
348
349   if( mTransformId != INVALID_TRANSFORM_ID )
350   {
351     mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
352   }
353 }
354
355 } // namespace SceneGraph
356
357 } // namespace Internal
358
359 } // namespace Dali