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