Fix regression by previous optimization for mDirtyFlags
[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 Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/update/nodes/node.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/internal/update/node-attachments/node-attachment.h>
22 #include <dali/internal/update/common/discard-queue.h>
23 #include <dali/internal/render/shaders/shader.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( Vector3::ZERO ),
48   mPosition( Vector3::ZERO ),
49   mRotation( Quaternion::IDENTITY ),
50   mScale( Vector3::ONE ),
51   mVisible( true ),
52   mColor( Color::WHITE ),
53   mWorldPosition( Vector3::ZERO ),
54   mWorldRotation( Quaternion::IDENTITY ),
55   mWorldScale( Vector3::ONE ),
56   mWorldMatrix( Matrix::IDENTITY ),
57   mWorldColor( Color::WHITE ),
58   mParent( NULL ),
59   mAppliedShader( NULL ),
60   mInheritedShader( NULL ),
61   mExclusiveRenderTask( NULL ),
62   mAttachment( NULL ),
63   mChildren(),
64   mGeometryScale( Vector3::ONE ),
65   mInitialVolume( Vector3::ONE ),
66   mDirtyFlags(AllFlags),
67   mIsRoot( false ),
68   mInheritShader( true ),
69   mInheritRotation( true ),
70   mInheritScale( true ),
71   mTransmitGeometryScaling( false ),
72   mInhibitLocalTransform( false ),
73   mIsActive( true ),
74   mDrawMode( DrawMode::NORMAL ),
75   mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
76   mColorMode( DEFAULT_COLOR_MODE )
77 {
78 }
79
80 Node::~Node()
81 {
82 }
83
84 void Node::OnDestroy()
85 {
86   // Node attachments should be notified about the disconnection.
87   if ( mAttachment )
88   {
89     mAttachment->OnDestroy();
90   }
91
92   // Animators, Constraints etc. should be disconnected from the child's properties.
93   PropertyOwner::DisconnectFromSceneGraph();
94 }
95
96 void Node::Attach( NodeAttachment& object )
97 {
98   DALI_ASSERT_DEBUG(!mAttachment);
99
100   object.SetParent(*this);
101
102   mAttachment = &object;
103   SetAllDirtyFlags();
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 )
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   mChildren.PushBack( childNode );
125 }
126
127 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
128 {
129   DALI_ASSERT_ALWAYS( this != &childNode );
130   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
131
132   // Find the childNode and remove it
133   Node* found( NULL );
134
135   const NodeIter endIter = mChildren.End();
136   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
137   {
138     Node* current = *iter;
139     if ( current == &childNode )
140     {
141       found = current;
142       mChildren.Erase( iter ); // order matters here
143       break; // iter is no longer valid
144     }
145   }
146   DALI_ASSERT_ALWAYS( NULL != found );
147
148   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
149 }
150
151 void Node::ApplyShader( Shader* shader )
152 {
153   DALI_ASSERT_DEBUG( shader && "null shader passed to node" );
154
155   mAppliedShader = shader;
156
157   SetDirtyFlag(ShaderFlag);
158 }
159
160 void Node::RemoveShader()
161 {
162   mAppliedShader = NULL; // Wait until InheritShader to grab default shader
163
164   SetDirtyFlag(ShaderFlag);
165 }
166
167 Shader* Node::GetAppliedShader() const
168 {
169   return mAppliedShader;
170 }
171
172 void Node::SetInheritedShader(Shader* shader)
173 {
174   mInheritedShader = shader;
175 }
176
177 Shader* Node::GetInheritedShader() const
178 {
179   return mInheritedShader;
180 }
181
182 void Node::InheritShader(Shader* defaultShader)
183 {
184   DALI_ASSERT_DEBUG(mParent != NULL);
185
186   // If we have a custom shader for this node, then use it
187   if ( mAppliedShader != NULL )
188   {
189     mInheritedShader = mAppliedShader;
190   }
191   else
192   {
193     // Otherwise we either inherit a shader, or fall-back to the default
194     if (mInheritShader)
195     {
196       mInheritedShader = mParent->GetInheritedShader();
197     }
198     else
199     {
200       mInheritedShader = defaultShader;
201     }
202   }
203   DALI_ASSERT_DEBUG( mInheritedShader != NULL );
204 }
205
206 int Node::GetDirtyFlags() const
207 {
208   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
209   int flags = mDirtyFlags;
210   const bool sizeFlag = mSize.IsClean();
211
212   if ( !(flags & TransformFlag) )
213   {
214     // Check whether the transform related properties have changed
215     if( !sizeFlag            ||
216         !mPosition.IsClean() ||
217         !mRotation.IsClean() ||
218         !mScale.IsClean()    ||
219         mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
220         mAnchorPoint.InputChanged() )
221     {
222       flags |= TransformFlag;
223     }
224   }
225
226   // Check whether the visible property has changed
227   if ( !mVisible.IsClean() )
228   {
229     flags |= VisibleFlag;
230   }
231
232   // Check whether the color property has changed
233   if ( !mColor.IsClean() )
234   {
235     flags |= ColorFlag;
236   }
237
238   // Check whether the size property has changed
239   if ( !sizeFlag )
240   {
241     flags |= SizeFlag;
242    }
243
244   return flags;
245 }
246
247 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
248 {
249   // clear dirty flags in parent origin & anchor point
250   mParentOrigin.Clear();
251   mAnchorPoint.Clear();
252   // Reset default properties
253   mSize.ResetToBaseValue( updateBufferIndex );
254   mPosition.ResetToBaseValue( updateBufferIndex );
255   mRotation.ResetToBaseValue( updateBufferIndex );
256   mScale.ResetToBaseValue( updateBufferIndex );
257   mVisible.ResetToBaseValue( updateBufferIndex );
258   mColor.ResetToBaseValue( updateBufferIndex );
259
260   mDirtyFlags = NothingFlag;
261 }
262
263 bool Node::IsFullyVisible( BufferIndex updateBufferIndex ) const
264 {
265   if( !IsVisible( updateBufferIndex ) )
266   {
267     return false;
268   }
269
270   Node* parent = mParent;
271
272   while( NULL != parent )
273   {
274     if( !parent->IsVisible( updateBufferIndex ) )
275     {
276       return false;
277     }
278
279     parent = parent->GetParent();
280   }
281
282   return true;
283 }
284
285 void Node::SetParent(Node& parentNode)
286 {
287   DALI_ASSERT_ALWAYS(this != &parentNode);
288   DALI_ASSERT_ALWAYS(!mIsRoot);
289   DALI_ASSERT_ALWAYS(mParent == NULL);
290
291   mParent = &parentNode;
292 }
293
294 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
295 {
296   DALI_ASSERT_ALWAYS(!mIsRoot);
297   DALI_ASSERT_ALWAYS(mParent != NULL);
298
299   const NodeIter endIter = mChildren.End();
300   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
301   {
302     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
303   }
304
305   // Animators, Constraints etc. should be disconnected from the child's properties.
306   PropertyOwner::DisconnectFromSceneGraph();
307
308   // Remove effects
309   mAppliedShader         = NULL;
310   mInheritedShader       = NULL;
311
312   // Remove back-pointer to parent
313   mParent = NULL;
314
315   // Remove all child pointers
316   mChildren.Clear();
317
318   // Move into disconnectedNodes
319   std::set<Node*>::size_type removed = connectedNodes.erase( this );
320   DALI_ASSERT_ALWAYS( removed );
321   disconnectedNodes.insert( this );
322 }
323
324 } // namespace SceneGraph
325
326 } // namespace Internal
327
328 } // namespace Dali