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