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