73b52ee3a20957831c1de1a04d81539f2c07941c
[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   mRegenerateUniformMap( 0 ),
78   mDepth( 0u ),
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   mDepth = mParent->GetDepth() + 1u;
300
301   if( mTransformId != INVALID_TRANSFORM_ID )
302   {
303     mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
304   }
305 }
306
307 void Node::SetBatchParent( Node* batchParentNode )
308 {
309   DALI_ASSERT_ALWAYS(!mIsRoot);
310   mBatchParent = batchParentNode;
311 }
312
313 void Node::SetIsBatchParent( bool enabled )
314 {
315   if( mIsBatchParent != enabled )
316   {
317     mIsBatchParent = enabled;
318
319     if( enabled )
320     {
321       mGeometryBatcher->AddBatchParent( this );
322     }
323     else
324     {
325       mGeometryBatcher->RemoveBatchParent( this );
326     }
327   }
328 }
329
330 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
331 {
332   DALI_ASSERT_ALWAYS(!mIsRoot);
333   DALI_ASSERT_ALWAYS(mParent != NULL);
334
335   const NodeIter endIter = mChildren.End();
336   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
337   {
338     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
339   }
340
341   // Animators, Constraints etc. should be disconnected from the child's properties.
342   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
343
344   // Remove back-pointer to parent
345   mParent = NULL;
346   mDepth = 0u;
347
348   // Remove all child pointers
349   mChildren.Clear();
350
351   if( mTransformId != INVALID_TRANSFORM_ID )
352   {
353     mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
354   }
355 }
356
357 } // namespace SceneGraph
358
359 } // namespace Internal
360
361 } // namespace Dali