Apply constraints when traversing the scene to update
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-algorithms.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/manager/update-algorithms.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/actors/draw-mode.h>
26 #include <dali/public-api/math/matrix.h>
27 #include <dali/public-api/math/vector3.h>
28 #include <dali/internal/update/resources/resource-manager.h>
29 #include <dali/internal/update/nodes/node.h>
30 #include <dali/internal/update/node-attachments/node-attachment.h>
31 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
32 #include <dali/internal/update/nodes/scene-graph-layer.h>
33 #include <dali/internal/render/renderers/render-renderer.h>
34
35 #include <dali/integration-api/debug.h>
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 namespace SceneGraph
44 {
45
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS");
48 #endif
49
50 /******************************************************************************
51  *********************** Apply Constraints ************************************
52  ******************************************************************************/
53
54
55 /**
56  * Constrain the local properties of the PropertyOwner.
57  * @param propertyOwner to constrain
58  * @param updateBufferIndex buffer index to use
59  * @return The number of constraints that are still being applied
60  */
61 void ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex )
62 {
63   ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints();
64
65   const ConstraintIter endIter = constraints.End();
66   for( ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter )
67   {
68     ConstraintBase& constraint = **iter;
69     constraint.Apply( updateBufferIndex );
70   }
71 }
72
73 /******************************************************************************
74  ************************** Update node hierarchy *****************************
75  ******************************************************************************/
76
77 inline void UpdateRootNodeOpacity( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
78 {
79   if ( nodeDirtyFlags & ColorFlag )
80   {
81     rootNode.SetWorldColor( rootNode.GetColor( updateBufferIndex ), updateBufferIndex );
82   }
83   else
84   {
85     // Copy previous value, in case it changed in the previous frame
86     rootNode.CopyPreviousWorldColor( updateBufferIndex );
87   }
88 }
89
90 inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
91 {
92   // If opacity needs to be recalculated
93   if ( nodeDirtyFlags & ColorFlag )
94   {
95     node.InheritWorldColor( updateBufferIndex );
96   }
97   else
98   {
99     // Copy inherited value, if changed in the previous frame
100     node.CopyPreviousWorldColor( updateBufferIndex );
101   }
102 }
103
104 inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
105 {
106   // If the transform values need to be reinherited
107   if ( nodeDirtyFlags & TransformFlag )
108   {
109     rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) );
110     rootNode.SetWorldOrientation( updateBufferIndex, rootNode.GetOrientation( updateBufferIndex ) );
111     rootNode.SetWorldScale   ( updateBufferIndex, rootNode.GetScale   ( updateBufferIndex ) );
112   }
113   else
114   {
115     // Copy previous value, in case they changed in the previous frame
116     rootNode.CopyPreviousWorldOrientation( updateBufferIndex );
117     rootNode.CopyPreviousWorldScale( updateBufferIndex );
118     rootNode.CopyPreviousWorldPosition( updateBufferIndex );
119   }
120 }
121
122 /**
123  * Updates transform values for the given node if the transform flag is dirty.
124   * Note that this will cause the size dirty flag to be set. This is why we pass
125  * the dirty flags in by reference.
126  * @param[in]     node The node to update
127  * @param[in,out] nodeDirtyFlags A reference to the dirty flags, these may be modified by this function
128  * @param[in]     updateBufferIndex The current index to use for this frame
129  */
130 inline void UpdateNodeTransformValues( Node& node, int& nodeDirtyFlags, BufferIndex updateBufferIndex )
131 {
132   // If the transform values need to be reinherited
133   if( nodeDirtyFlags & TransformFlag )
134   {
135     // With a non-central anchor-point, the world rotation and scale affects the world position.
136     // Therefore the world rotation & scale must be updated before the world position.
137     if( node.IsOrientationInherited() )
138     {
139       node.InheritWorldOrientation( updateBufferIndex );
140     }
141     else
142     {
143       node.SetWorldOrientation( updateBufferIndex, node.GetOrientation( updateBufferIndex ) );
144     }
145
146     if( node.IsScaleInherited() )
147     {
148       node.InheritWorldScale( updateBufferIndex );
149     }
150     else
151     {
152       node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) );
153     }
154
155     node.InheritWorldPosition( updateBufferIndex );
156   }
157   else
158   {
159     // Copy inherited values, if those changed in the previous frame
160     node.CopyPreviousWorldOrientation( updateBufferIndex );
161     node.CopyPreviousWorldScale( updateBufferIndex );
162     node.CopyPreviousWorldPosition( updateBufferIndex );
163   }
164 }
165
166 inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
167 {
168   // If world-matrix needs to be recalculated
169   if ( nodeDirtyFlags & TransformFlag )
170   {
171     node.SetWorldMatrix( updateBufferIndex,
172                          node.GetWorldScale(updateBufferIndex),
173                          node.GetWorldOrientation(updateBufferIndex),
174                          node.GetWorldPosition(updateBufferIndex) );
175   }
176   else
177   {
178     node.CopyPreviousWorldMatrix( updateBufferIndex );
179   }
180 }
181
182 /**
183  * This is called recursively for all children of the root Node
184  */
185 inline int UpdateNodesAndAttachments( Node& node,
186                                       int parentFlags,
187                                       BufferIndex updateBufferIndex,
188                                       ResourceManager& resourceManager,
189                                       RenderQueue& renderQueue,
190                                       Layer& currentLayer,
191                                       int inheritedDrawMode )
192 {
193   //Apply constraints to the node
194   ConstrainPropertyOwner( node, updateBufferIndex );
195
196   // Short-circuit for invisible nodes
197   if ( !node.IsVisible( updateBufferIndex ) )
198   {
199     return 0;
200   }
201
202   // If the node was not previously visible
203   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
204   if ( !node.IsVisible( previousBuffer ) )
205   {
206     // The node was skipped in the previous update; it must recalculate everything
207     node.SetAllDirtyFlags();
208   }
209
210   // Some dirty flags are inherited from parent
211   int nodeDirtyFlags( node.GetDirtyFlags() | ( parentFlags & InheritedDirtyFlags ) );
212
213   int cumulativeDirtyFlags = nodeDirtyFlags;
214
215   Layer* layer = &currentLayer;
216   Layer* nodeIsLayer( node.GetLayer() );
217   if( nodeIsLayer )
218   {
219     // all childs go to this layer
220     layer = nodeIsLayer;
221
222     // assume layer is clean to begin with
223     layer->SetReuseRenderers( updateBufferIndex, true );
224
225     // Layers do not inherit the DrawMode from their parents
226     inheritedDrawMode = DrawMode::NORMAL;
227   }
228   DALI_ASSERT_DEBUG( NULL != layer );
229
230   UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex );
231
232   // Note: nodeDirtyFlags are passed in by reference and may be modified by the following function
233   UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex );
234
235   // Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited.
236   inheritedDrawMode |= node.GetDrawMode();
237
238   if ( DALI_UNLIKELY( node.HasAttachment() ) )
239   {
240     //Apply constraints to the attachement
241     NodeAttachment& attachment = node.GetAttachment();
242     PropertyOwner* propertyOwner = dynamic_cast< PropertyOwner* >( &attachment );
243     if( propertyOwner != NULL )
244     {
245       ConstrainPropertyOwner( *propertyOwner, updateBufferIndex );
246     }
247
248     //Update the attachment
249     attachment.Update( updateBufferIndex, node, nodeDirtyFlags );
250   }
251   else if( node.IsObserved() || node.GetRendererCount() )
252   {
253     // This node is being used as a property input for an animation, constraint,
254     // camera or bone. Ensure it's matrix is updated
255     UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex );
256   }
257
258   node.PrepareRender( updateBufferIndex );
259
260
261   // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
262   // also if node has been deleted, dont reuse old render items
263   if( nodeDirtyFlags & RenderableUpdateFlags )
264   {
265     layer->SetReuseRenderers( updateBufferIndex, false );
266   }
267
268   // recurse children
269   NodeContainer& children = node.GetChildren();
270   const NodeIter endIter = children.End();
271   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
272   {
273     Node& child = **iter;
274     cumulativeDirtyFlags |=UpdateNodesAndAttachments( child,
275                                                       nodeDirtyFlags,
276                                                       updateBufferIndex,
277                                                       resourceManager,
278                                                       renderQueue,
279                                                       *layer,
280                                                       inheritedDrawMode );
281   }
282
283   return cumulativeDirtyFlags;
284 }
285
286 /**
287  * The root node is treated separately; it cannot inherit values since it has no parent
288  */
289 int UpdateNodesAndAttachments( Layer& rootNode,
290                                BufferIndex updateBufferIndex,
291                                ResourceManager& resourceManager,
292                                RenderQueue& renderQueue )
293 {
294   DALI_ASSERT_DEBUG( rootNode.IsRoot() );
295
296   // Short-circuit for invisible nodes
297   if ( DALI_UNLIKELY( !rootNode.IsVisible( updateBufferIndex ) ) ) // almost never ever true
298   {
299     return 0;
300   }
301
302   // If the root node was not previously visible
303   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
304   if ( DALI_UNLIKELY( !rootNode.IsVisible( previousBuffer ) ) ) // almost never ever true
305   {
306     // The node was skipped in the previous update; it must recalculate everything
307     rootNode.SetAllDirtyFlags();
308   }
309
310   int nodeDirtyFlags( rootNode.GetDirtyFlags() );
311
312   int cumulativeDirtyFlags = nodeDirtyFlags;
313
314   UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
315
316   UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
317
318   DrawMode::Type drawMode( rootNode.GetDrawMode() );
319
320   // recurse children
321   NodeContainer& children = rootNode.GetChildren();
322   const NodeIter endIter = children.End();
323   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
324   {
325     Node& child = **iter;
326     cumulativeDirtyFlags |= UpdateNodesAndAttachments( child,
327                                                        nodeDirtyFlags,
328                                                        updateBufferIndex,
329                                                        resourceManager,
330                                                        renderQueue,
331                                                        rootNode,
332                                                        drawMode );
333   }
334
335   return cumulativeDirtyFlags;
336 }
337
338 } // namespace SceneGraph
339
340 } // namespace Internal
341
342 } // namespace Dali