Changed draw ordering to take into account the depth of the node in the hierarchy
[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
27 namespace Dali
28 {
29
30 namespace Internal
31 {
32
33 namespace SceneGraph
34 {
35
36 const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION );
37 const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
38
39 Node* Node::New()
40 {
41   return new Node();
42 }
43
44 Node::Node()
45 : mParentOrigin( ParentOrigin::DEFAULT ),
46   mAnchorPoint( AnchorPoint::DEFAULT ),
47   mSize(),     // zero initialized by default
48   mPosition(), // zero initialized by default
49   mOrientation(), // initialized to identity by default
50   mScale( Vector3::ONE ),
51   mVisible( true ),
52   mColor( Color::WHITE ),
53   mWorldPosition(), // zero initialized by default
54   mWorldOrientation(), // initialized to identity by default
55   mWorldScale( Vector3::ONE ),
56   mWorldMatrix(),
57   mWorldColor( Color::WHITE ),
58   mParent( NULL ),
59   mExclusiveRenderTask( NULL ),
60   mAttachment( NULL ),
61   mChildren(),
62   mDepth(0u),
63   mDirtyFlags(AllFlags),
64   mIsRoot( false ),
65   mInheritOrientation( true ),
66   mInheritScale( true ),
67   mInhibitLocalTransform( false ),
68   mIsActive( true ),
69   mDrawMode( DrawMode::NORMAL ),
70   mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
71   mColorMode( DEFAULT_COLOR_MODE )
72 {
73 }
74
75 Node::~Node()
76 {
77 }
78
79 void Node::OnDestroy()
80 {
81   // Node attachments should be notified about the disconnection.
82   if ( mAttachment )
83   {
84     mAttachment->OnDestroy();
85   }
86
87   // Animators, Constraints etc. should be disconnected from the child's properties.
88   PropertyOwner::Destroy();
89 }
90
91 void Node::Attach( NodeAttachment& object )
92 {
93   DALI_ASSERT_DEBUG(!mAttachment);
94
95   object.SetParent(*this);
96
97   mAttachment = &object;
98   SetAllDirtyFlags();
99
100   if( mIsActive )
101   {
102     mAttachment->ConnectedToSceneGraph();
103   }
104 }
105
106 void Node::SetRoot(bool isRoot)
107 {
108   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
109
110   mIsRoot = isRoot;
111 }
112
113 void Node::ConnectChild( Node* childNode, int index )
114 {
115   DALI_ASSERT_ALWAYS( this != childNode );
116   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
117   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
118
119   childNode->SetParent( *this );
120
121   // Everything should be reinherited when reconnected to scene-graph
122   childNode->SetAllDirtyFlags();
123
124   if (index == -1)
125   {
126     mChildren.PushBack( childNode );
127   }
128   else
129   {
130     mChildren.Insert(mChildren.Begin()+index, childNode);
131   }
132
133   // Inform property observers of new connection
134   childNode->ConnectToSceneGraph();
135
136   // Inform child node attachment that the node has been added to the stage
137   if( childNode->mAttachment )
138   {
139     childNode->mAttachment->ConnectedToSceneGraph();
140   }
141 }
142
143 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
144 {
145   DALI_ASSERT_ALWAYS( this != &childNode );
146   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
147
148   // Find the childNode and remove it
149   Node* found( NULL );
150
151   const NodeIter endIter = mChildren.End();
152   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
153   {
154     Node* current = *iter;
155     if ( current == &childNode )
156     {
157       found = current;
158       mChildren.Erase( iter ); // order matters here
159       break; // iter is no longer valid
160     }
161   }
162   DALI_ASSERT_ALWAYS( NULL != found );
163
164   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
165 }
166
167 int Node::GetDirtyFlags() const
168 {
169   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
170   int flags = mDirtyFlags;
171   const bool sizeFlag = mSize.IsClean();
172
173   if ( !(flags & TransformFlag) )
174   {
175     // Check whether the transform related properties have changed
176     if( !sizeFlag            ||
177         !mPosition.IsClean() ||
178         !mOrientation.IsClean() ||
179         !mScale.IsClean()    ||
180         mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
181         mAnchorPoint.InputChanged() )
182     {
183       flags |= TransformFlag;
184     }
185   }
186
187   // Check whether the visible property has changed
188   if ( !mVisible.IsClean() )
189   {
190     flags |= VisibleFlag;
191   }
192
193   // Check whether the color property has changed
194   if ( !mColor.IsClean() )
195   {
196     flags |= ColorFlag;
197   }
198
199   // Check whether the size property has changed
200   if ( !sizeFlag )
201   {
202     flags |= SizeFlag;
203    }
204
205   return flags;
206 }
207
208 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
209 {
210   // clear dirty flags in parent origin & anchor point
211   mParentOrigin.Clear();
212   mAnchorPoint.Clear();
213   // Reset default properties
214   mSize.ResetToBaseValue( updateBufferIndex );
215   mPosition.ResetToBaseValue( updateBufferIndex );
216   mOrientation.ResetToBaseValue( updateBufferIndex );
217   mScale.ResetToBaseValue( updateBufferIndex );
218   mVisible.ResetToBaseValue( updateBufferIndex );
219   mColor.ResetToBaseValue( updateBufferIndex );
220
221   mDirtyFlags = NothingFlag;
222 }
223
224 bool Node::IsFullyVisible( BufferIndex updateBufferIndex ) const
225 {
226   if( !IsVisible( updateBufferIndex ) )
227   {
228     return false;
229   }
230
231   Node* parent = mParent;
232
233   while( NULL != parent )
234   {
235     if( !parent->IsVisible( updateBufferIndex ) )
236     {
237       return false;
238     }
239
240     parent = parent->GetParent();
241   }
242
243   return true;
244 }
245
246 void Node::SetParent(Node& parentNode)
247 {
248   DALI_ASSERT_ALWAYS(this != &parentNode);
249   DALI_ASSERT_ALWAYS(!mIsRoot);
250   DALI_ASSERT_ALWAYS(mParent == NULL);
251
252   mParent = &parentNode;
253   mDepth = mParent->GetDepth() + 1u;
254 }
255
256 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
257 {
258   DALI_ASSERT_ALWAYS(!mIsRoot);
259   DALI_ASSERT_ALWAYS(mParent != NULL);
260
261   const NodeIter endIter = mChildren.End();
262   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
263   {
264     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
265   }
266
267   // Animators, Constraints etc. should be disconnected from the child's properties.
268   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
269
270   // Remove back-pointer to parent
271   mParent = NULL;
272   mDepth = 0u;
273
274   // Remove all child pointers
275   mChildren.Clear();
276
277   // Inform child node attachment that the node has been removed from the stage
278   if( mAttachment )
279   {
280     mAttachment->DisconnectedFromSceneGraph();
281   }
282
283   // Move into disconnectedNodes
284   std::set<Node*>::size_type removed = connectedNodes.erase( this );
285   DALI_ASSERT_ALWAYS( removed );
286   disconnectedNodes.insert( this );
287 }
288
289 } // namespace SceneGraph
290
291 } // namespace Internal
292
293 } // namespace Dali