8f42ed360dce79c2bdb3504b73148752c2ed072d
[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/update/node-attachments/node-attachment.h>
23 #include <dali/internal/update/common/discard-queue.h>
24 #include <dali/public-api/common/dali-common.h>
25 #include <dali/public-api/common/constants.h>
26 #include <dali/internal/common/internal-constants.h>
27
28 namespace Dali
29 {
30
31 namespace Internal
32 {
33
34 namespace SceneGraph
35 {
36
37 const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION );
38 const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
39
40 Node* Node::New()
41 {
42   return new Node();
43 }
44
45 Node::Node()
46 : mParentOrigin( ParentOrigin::DEFAULT ),
47   mAnchorPoint( AnchorPoint::DEFAULT ),
48   mSize(),     // zero initialized by default
49   mPosition(), // zero initialized by default
50   mOrientation(), // initialized to identity by default
51   mScale( Vector3::ONE ),
52   mVisible( true ),
53   mColor( Color::WHITE ),
54   mWorldPosition(), // zero initialized by default
55   mWorldOrientation(), // initialized to identity by default
56   mWorldScale( Vector3::ONE ),
57   mWorldMatrix(),
58   mWorldColor( Color::WHITE ),
59   mParent( NULL ),
60   mExclusiveRenderTask( NULL ),
61   mAttachment( NULL ),
62   mChildren(),
63   mRegenerateUniformMap( 0 ),
64   mDepth(0u),
65   mDirtyFlags(AllFlags),
66   mIsRoot( false ),
67   mInheritOrientation( true ),
68   mInheritScale( true ),
69   mInhibitLocalTransform( false ),
70   mIsActive( true ),
71   mDrawMode( DrawMode::NORMAL ),
72   mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
73   mColorMode( DEFAULT_COLOR_MODE )
74 {
75   mUniformMapChanged[0] = 0u;
76   mUniformMapChanged[1] = 0u;
77 }
78
79 Node::~Node()
80 {
81 }
82
83 void Node::OnDestroy()
84 {
85   // Node attachments should be notified about the disconnection.
86   if ( mAttachment )
87   {
88     mAttachment->OnDestroy();
89   }
90
91   // Animators, Constraints etc. should be disconnected from the child's properties.
92   PropertyOwner::Destroy();
93 }
94
95 void Node::Attach( NodeAttachment& object )
96 {
97   DALI_ASSERT_DEBUG(!mAttachment);
98
99   object.SetParent(*this);
100
101   mAttachment = &object;
102   SetAllDirtyFlags();
103
104   if( mIsActive )
105   {
106     mAttachment->ConnectedToSceneGraph();
107   }
108 }
109
110 void Node::SetRoot(bool isRoot)
111 {
112   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
113
114   mIsRoot = isRoot;
115 }
116
117 bool Node::ResolveVisibility( BufferIndex updateBufferIndex )
118 {
119   bool result = false;
120   const Vector4& color = GetWorldColor( updateBufferIndex );
121   if( color.a > FULLY_TRANSPARENT )               // not fully transparent
122   {
123     const float MAX_NODE_SIZE = float(1u<<30);
124     const Vector3& size = GetSize( updateBufferIndex );
125     if( ( size.width > Math::MACHINE_EPSILON_1000 ) &&  // width is greater than a very small number
126         ( size.height > Math::MACHINE_EPSILON_1000 ) )  // height is greater than a very small number
127     {
128       if( ( size.width < MAX_NODE_SIZE ) &&             // width is smaller than the maximum allowed size
129           ( size.height < MAX_NODE_SIZE ) )             // height is smaller than the maximum allowed size
130       {
131         result = true;
132       }
133       else
134       {
135         DALI_LOG_ERROR("Actor size should not be bigger than %f.\n", MAX_NODE_SIZE );
136         DALI_LOG_ACTOR_TREE( mParent );
137       }
138     }
139   }
140   return result;
141 }
142
143 void Node::AddUniformMapping( UniformPropertyMapping* map )
144 {
145   PropertyOwner::AddUniformMapping( map );
146   mRegenerateUniformMap = 2;
147 }
148
149 void Node::RemoveUniformMapping( const std::string& uniformName )
150 {
151   PropertyOwner::RemoveUniformMapping( uniformName );
152   mRegenerateUniformMap = 2;
153 }
154
155 void Node::PrepareRender( BufferIndex bufferIndex )
156 {
157   if(mRegenerateUniformMap != 0 )
158   {
159     if( mRegenerateUniformMap == 2 )
160     {
161       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
162       localMap.Resize(0);
163
164       for( unsigned int i=0, count=mUniformMaps.Count(); i<count; ++i )
165       {
166         localMap.PushBack( &mUniformMaps[i] );
167       }
168     }
169     else if( mRegenerateUniformMap == 1 )
170     {
171       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
172       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-bufferIndex ];
173
174       localMap.Resize( oldMap.Count() );
175
176       unsigned int index=0;
177       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
178       {
179         localMap[index] = *iter;
180       }
181     }
182     --mRegenerateUniformMap;
183     mUniformMapChanged[bufferIndex] = 1u;
184   }
185 }
186
187 void Node::ConnectChild( Node* childNode )
188 {
189   DALI_ASSERT_ALWAYS( this != childNode );
190   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
191   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
192
193   childNode->SetParent( *this );
194
195   // Everything should be reinherited when reconnected to scene-graph
196   childNode->SetAllDirtyFlags();
197
198   // Add the node to the end of the child list.
199   mChildren.PushBack( childNode );
200
201   // Inform property observers of new connection
202   childNode->ConnectToSceneGraph();
203
204   // Inform child node attachment that the node has been added to the stage
205   if( childNode->mAttachment )
206   {
207     childNode->mAttachment->ConnectedToSceneGraph();
208   }
209 }
210
211 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
212 {
213   DALI_ASSERT_ALWAYS( this != &childNode );
214   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
215
216   // Find the childNode and remove it
217   Node* found( NULL );
218
219   const NodeIter endIter = mChildren.End();
220   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
221   {
222     Node* current = *iter;
223     if ( current == &childNode )
224     {
225       found = current;
226       mChildren.Erase( iter ); // order matters here
227       break; // iter is no longer valid
228     }
229   }
230   DALI_ASSERT_ALWAYS( NULL != found );
231
232   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
233 }
234
235 void Node::RemoveRenderer( Renderer* renderer )
236 {
237   unsigned int rendererCount( mRenderer.Size() );
238   for( unsigned int i(0); i<rendererCount; ++i )
239   {
240     if( mRenderer[i] == renderer )
241     {
242       mRenderer.Erase( mRenderer.Begin()+i);
243       return;
244     }
245   }
246 }
247
248 int Node::GetDirtyFlags() const
249 {
250   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
251   int flags = mDirtyFlags;
252   const bool sizeFlag = mSize.IsClean();
253
254   if ( !(flags & TransformFlag) )
255   {
256     // Check whether the transform related properties have changed
257     if( !sizeFlag            ||
258         !mPosition.IsClean() ||
259         !mOrientation.IsClean() ||
260         !mScale.IsClean()    ||
261         mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
262         mAnchorPoint.InputChanged() )
263     {
264       flags |= TransformFlag;
265     }
266   }
267
268   // Check whether the visible property has changed
269   if ( !mVisible.IsClean() )
270   {
271     flags |= VisibleFlag;
272   }
273
274   // Check whether the color property has changed
275   if ( !mColor.IsClean() )
276   {
277     flags |= ColorFlag;
278   }
279
280   // Check whether the size property has changed
281   if ( !sizeFlag )
282   {
283     flags |= SizeFlag;
284    }
285
286   return flags;
287 }
288
289 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
290 {
291   // clear dirty flags in parent origin & anchor point
292   mParentOrigin.Clear();
293   mAnchorPoint.Clear();
294   // Reset default properties
295   mSize.ResetToBaseValue( updateBufferIndex );
296   mPosition.ResetToBaseValue( updateBufferIndex );
297   mOrientation.ResetToBaseValue( updateBufferIndex );
298   mScale.ResetToBaseValue( updateBufferIndex );
299   mVisible.ResetToBaseValue( updateBufferIndex );
300   mColor.ResetToBaseValue( updateBufferIndex );
301
302   mDirtyFlags = NothingFlag;
303 }
304
305 bool Node::IsFullyVisible( BufferIndex updateBufferIndex ) const
306 {
307   if( !IsVisible( updateBufferIndex ) )
308   {
309     return false;
310   }
311
312   Node* parent = mParent;
313
314   while( NULL != parent )
315   {
316     if( !parent->IsVisible( updateBufferIndex ) )
317     {
318       return false;
319     }
320
321     parent = parent->GetParent();
322   }
323
324   return true;
325 }
326
327 void Node::SetParent(Node& parentNode)
328 {
329   DALI_ASSERT_ALWAYS(this != &parentNode);
330   DALI_ASSERT_ALWAYS(!mIsRoot);
331   DALI_ASSERT_ALWAYS(mParent == NULL);
332
333   mParent = &parentNode;
334   mDepth = mParent->GetDepth() + 1u;
335 }
336
337 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
338 {
339   DALI_ASSERT_ALWAYS(!mIsRoot);
340   DALI_ASSERT_ALWAYS(mParent != NULL);
341
342   const NodeIter endIter = mChildren.End();
343   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
344   {
345     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
346   }
347
348   // Animators, Constraints etc. should be disconnected from the child's properties.
349   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
350
351   // Remove back-pointer to parent
352   mParent = NULL;
353   mDepth = 0u;
354
355   // Remove all child pointers
356   mChildren.Clear();
357
358   // Inform child node attachment that the node has been removed from the stage
359   if( mAttachment )
360   {
361     mAttachment->DisconnectedFromSceneGraph();
362   }
363
364   // Move into disconnectedNodes
365   std::set<Node*>::size_type removed = connectedNodes.erase( this );
366   DALI_ASSERT_ALWAYS( removed );
367   disconnectedNodes.insert( this );
368 }
369
370 } // namespace SceneGraph
371
372 } // namespace Internal
373
374 } // namespace Dali