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