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