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