[dali_2.3.33] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / transform-manager.cpp
1 /*
2  * Copyright (c) 2024 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/transform-manager.h>
20
21 //EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <cstring>
24 #include <type_traits>
25
26 //INTERNAL INCLUDES
27 #include <dali/internal/common/math.h>
28 #include <dali/internal/common/matrix-utils.h>
29 #include <dali/internal/update/common/animatable-property.h> ///< for SET_FLAG and BAKE_FLAG
30 #include <dali/public-api/common/constants.h>
31
32 #include <dali/integration-api/debug.h>
33 #include <dali/integration-api/trace.h>
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace SceneGraph
40 {
41 namespace
42 {
43 //Default values for scale (1.0,1.0,1.0), orientation (Identity) and position (0.0,0.0,0.0)
44 static const float gDefaultTransformComponentAnimatableData[] = {1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
45
46 //Default values for anchor point (CENTER) and parent origin (TOP_LEFT)
47 static const float gDefaultTransformComponentStaticData[] = {0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, true};
48
49 static const uint32_t STATIC_COMPONENT_FLAG = 0x01; ///< Indicates that the value when we change static transform components, so need to update at least 1 frame.
50
51 static_assert(sizeof(gDefaultTransformComponentAnimatableData) == sizeof(TransformComponentAnimatable), "gDefaultTransformComponentAnimatableData should have the same number of floats as specified in TransformComponentAnimatable");
52 static_assert(sizeof(gDefaultTransformComponentStaticData) == sizeof(TransformComponentStatic), "gDefaultTransformComponentStaticData should have the same number of floats as specified in TransformComponentStatic");
53
54 /**
55  * @brief Calculates the center position for the transform component
56  * @param[out] centerPosition The calculated center-position of the transform component
57  * @param[in] transformComponentStatic A const reference to the static component transform struct
58  * @param[in] scale scale factor to be applied to the center position.
59  * @param[in] orientation orientation factor to be applied to the center position.
60  * @param[in] size The size of the current transform component
61  * @param[in] half Halfway point of the transform
62  * @param[in] topLeft The top-left coords of the transform
63  */
64 inline void CalculateCenterPosition(
65   Vector3&                        centerPosition,
66   const TransformComponentStatic& transformComponentStatic,
67   const Vector3&                  scale,
68   const Quaternion&               orientation,
69   const Vector3&                  size,
70   const Vector3&                  half,
71   const Vector3&                  topLeft)
72 {
73   // Calculate the center-point by applying the scale and rotation on the anchor point.
74   centerPosition = (half - transformComponentStatic.mAnchorPoint) * size * scale;
75   centerPosition *= orientation;
76
77   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
78   if(!transformComponentStatic.mPositionUsesAnchorPoint)
79   {
80     centerPosition -= (topLeft - transformComponentStatic.mAnchorPoint) * size;
81   }
82 }
83
84 // TODO : The name of trace marker is from VD specific.
85 // We might need to change it as DALI_TRACE_UPDATE_PROCESS.
86 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_COMBINED, false);
87 } // unnamed namespace
88
89 TransformManager::TransformManager()
90 : mComponentCount(0),
91   mReorder(false)
92 {
93 }
94
95 TransformManager::~TransformManager() = default;
96
97 TransformId TransformManager::CreateTransform()
98 {
99   //Get id for the new component
100   TransformId id = mIds.Add(mComponentCount);
101
102   if(mTxComponentAnimatable.Size() <= mComponentCount)
103   {
104     //Make room for another component
105     mTxComponentAnimatable.PushBack(TransformComponentAnimatable());
106     mTxComponentStatic.PushBack(TransformComponentStatic());
107     mInheritanceMode.PushBack(INHERIT_ALL);
108     mComponentId.PushBack(id);
109     mSize.PushBack(Vector3(0.0f, 0.0f, 0.0f));
110     mParent.PushBack(INVALID_TRANSFORM_ID);
111     mWorld.PushBack(Matrix::IDENTITY);
112     mLocal.PushBack(Matrix::IDENTITY);
113     mBoundingSpheres.PushBack(Vector4(0.0f, 0.0f, 0.0f, 0.0f));
114     mTxComponentAnimatableBaseValue.PushBack(TransformComponentAnimatable());
115     mSizeBase.PushBack(Vector3(0.0f, 0.0f, 0.0f));
116     mComponentDirty.PushBack(CLEAN_FLAG);
117     mLocalMatrixDirty.PushBack(false);
118   }
119   else
120   {
121     //Set default values
122     memcpy(&mTxComponentAnimatable[mComponentCount], &gDefaultTransformComponentAnimatableData, sizeof(TransformComponentAnimatable));
123     memcpy(&mTxComponentStatic[mComponentCount], &gDefaultTransformComponentStaticData, sizeof(TransformComponentStatic));
124     memcpy(&mTxComponentAnimatableBaseValue[mComponentCount], &gDefaultTransformComponentAnimatableData, sizeof(TransformComponentAnimatable));
125     mInheritanceMode[mComponentCount] = INHERIT_ALL;
126     mComponentId[mComponentCount]     = id;
127     mSize[mComponentCount]            = Vector3(0.0f, 0.0f, 0.0f);
128     mParent[mComponentCount]          = INVALID_TRANSFORM_ID;
129     mLocal[mComponentCount].SetIdentity();
130     mWorld[mComponentCount].SetIdentity();
131     mBoundingSpheres[mComponentCount]  = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
132     mSizeBase[mComponentCount]         = Vector3(0.0f, 0.0f, 0.0f);
133     mComponentDirty[mComponentCount]   = CLEAN_FLAG;
134     mLocalMatrixDirty[mComponentCount] = false;
135   }
136
137   mComponentCount++;
138   return id;
139 }
140
141 void TransformManager::RemoveTransform(TransformId id)
142 {
143   //Move the last element to the gap
144   mComponentCount--;
145   TransformId index                      = mIds[id];
146   mTxComponentAnimatable[index]          = mTxComponentAnimatable[mComponentCount];
147   mTxComponentStatic[index]              = mTxComponentStatic[mComponentCount];
148   mInheritanceMode[index]                = mInheritanceMode[mComponentCount];
149   mSize[index]                           = mSize[mComponentCount];
150   mParent[index]                         = mParent[mComponentCount];
151   mWorld[index]                          = mWorld[mComponentCount];
152   mLocal[index]                          = mLocal[mComponentCount];
153   mTxComponentAnimatableBaseValue[index] = mTxComponentAnimatableBaseValue[mComponentCount];
154   mSizeBase[index]                       = mSizeBase[mComponentCount];
155   mComponentDirty[index]                 = mComponentDirty[mComponentCount];
156   mLocalMatrixDirty[index]               = mLocalMatrixDirty[mComponentCount];
157   mBoundingSpheres[index]                = mBoundingSpheres[mComponentCount];
158
159   TransformId lastItemId = mComponentId[mComponentCount];
160   mIds[lastItemId]       = index;
161   mComponentId[index]    = lastItemId;
162   mIds.Remove(id);
163
164   mReorder = true;
165 }
166
167 void TransformManager::SetParent(TransformId id, TransformId parentId)
168 {
169   DALI_ASSERT_ALWAYS(id != parentId);
170
171   TransformId index = mIds[id];
172   mParent[index]    = parentId;
173   mComponentDirty[index] |= STATIC_COMPONENT_FLAG; ///< Need to calculate local matrix, at least 1 frame.
174
175   mReorder = true;
176 }
177
178 const Matrix& TransformManager::GetWorldMatrix(TransformId id) const
179 {
180   return mWorld[mIds[id]];
181 }
182
183 Matrix& TransformManager::GetWorldMatrix(TransformId id)
184 {
185   return mWorld[mIds[id]];
186 }
187
188 void TransformManager::SetInheritPosition(TransformId id, bool inherit)
189 {
190   TransformId index = mIds[id];
191   if(inherit)
192   {
193     mInheritanceMode[index] |= INHERIT_POSITION;
194   }
195   else
196   {
197     mInheritanceMode[index] &= ~INHERIT_POSITION;
198   }
199
200   mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
201 }
202
203 void TransformManager::SetInheritScale(TransformId id, bool inherit)
204 {
205   TransformId index = mIds[id];
206   if(inherit)
207   {
208     mInheritanceMode[index] |= INHERIT_SCALE;
209   }
210   else
211   {
212     mInheritanceMode[index] &= ~INHERIT_SCALE;
213   }
214
215   mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
216 }
217
218 void TransformManager::SetInheritOrientation(TransformId id, bool inherit)
219 {
220   TransformId index = mIds[id];
221   if(inherit)
222   {
223     mInheritanceMode[index] |= INHERIT_ORIENTATION;
224   }
225   else
226   {
227     mInheritanceMode[index] &= ~INHERIT_ORIENTATION;
228   }
229
230   mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
231 }
232
233 void TransformManager::ResetToBaseValue()
234 {
235   if(mComponentCount)
236   {
237     memcpy(&mTxComponentAnimatable[0], &mTxComponentAnimatableBaseValue[0], sizeof(TransformComponentAnimatable) * mComponentCount);
238     memcpy(&mSize[0], &mSizeBase[0], sizeof(Vector3) * mComponentCount);
239     memset(&mLocalMatrixDirty[0], false, sizeof(bool) * mComponentCount);
240   }
241 }
242
243 bool TransformManager::Update()
244 {
245   bool componentsChanged = false;
246
247   DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_TRANSFORM_UPDATE", [&](std::ostringstream& oss) {
248     oss << "[" << mComponentCount << "]";
249   });
250
251   if(mReorder)
252   {
253     DALI_TRACE_SCOPE(gTraceFilter, "DALI_TRANSFORM_REORDER");
254     //If some transform component has change its parent or has been removed since last update
255     //we need to reorder the vectors
256     ReorderComponents();
257     mReorder = false;
258   }
259
260   //Iterate through all components to compute its world matrix
261   Vector3       centerPosition;
262   Vector3       localPosition;
263   const Vector3 half(0.5f, 0.5f, 0.5f);
264   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
265   for(unsigned int i(0); i < mComponentCount; ++i)
266   {
267     if(DALI_LIKELY(mInheritanceMode[i] != DONT_INHERIT_TRANSFORM && mParent[i] != INVALID_TRANSFORM_ID))
268     {
269       const TransformId& parentIndex = mIds[mParent[i]];
270       if(DALI_LIKELY(mInheritanceMode[i] == INHERIT_ALL))
271       {
272         if(mComponentDirty[i] || mLocalMatrixDirty[parentIndex])
273         {
274           //Full transform inherited
275           mLocalMatrixDirty[i] = true;
276           CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
277           localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
278           mLocal[i].SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition);
279         }
280
281         //Update the world matrix
282         MatrixUtils::MultiplyTransformMatrix(mWorld[i], mLocal[i], mWorld[parentIndex]);
283       }
284       else
285       {
286         // Keep previous localMatrix for comparison.
287         Matrix previousLocalMatrix = mLocal[i];
288
289         // Get Parent information.
290         Vector3       parentPosition, parentScale;
291         Quaternion    parentOrientation;
292         const Matrix& parentMatrix = mWorld[parentIndex];
293         parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
294
295         // Compute intermediate Local information
296         CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
297         Vector3 intermediateLocalPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
298         Matrix  intermediateLocalMatrix;
299         intermediateLocalMatrix.SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, intermediateLocalPosition);
300
301         // Compute intermediate world information
302         Matrix intermediateWorldMatrix;
303         MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, mWorld[parentIndex]);
304
305         Vector3    intermediateWorldPosition, intermediateWorldScale;
306         Quaternion intermediateWorldOrientation;
307         intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
308
309         // Compute final world information
310         Vector3    finalWorldPosition    = intermediateWorldPosition;
311         Vector3    finalWorldScale       = intermediateWorldScale;
312         Quaternion finalWorldOrientation = intermediateWorldOrientation;
313         // worldScale includes the influence of local scale, local rotation, and parent scale.
314         // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
315         // If not, use local scale for the final world matrix.
316         if((mInheritanceMode[i] & INHERIT_SCALE) == 0)
317         {
318           finalWorldScale = mTxComponentAnimatable[i].mScale;
319         }
320
321         // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
322         // If not, use local orientation for the final world matrix.
323         if((mInheritanceMode[i] & INHERIT_ORIENTATION) == 0)
324         {
325           finalWorldOrientation = mTxComponentAnimatable[i].mOrientation;
326         }
327
328         // The final world position of this node is computed as a sum of
329         // parent origin position in world space and relative position of center from parent origin.
330         // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
331         Vector3 localCenterPosition;
332         CalculateCenterPosition(localCenterPosition, mTxComponentStatic[i], finalWorldScale, finalWorldOrientation, mSize[i], half, topLeft);
333         finalWorldPosition = mTxComponentAnimatable[i].mPosition * finalWorldScale;
334         finalWorldPosition *= finalWorldOrientation;
335         finalWorldPosition += localCenterPosition;
336         if((mInheritanceMode[i] & INHERIT_POSITION) != 0)
337         {
338           Vector4 parentOriginPosition((mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex]);
339           parentOriginPosition.w = 1.0f;
340           finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
341         }
342
343         mWorld[i].SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
344
345         Matrix inverseParentMatrix;
346         inverseParentMatrix.SetInverseTransformComponents(parentScale, parentOrientation, parentPosition);
347         mLocal[i] = inverseParentMatrix * mWorld[i];
348
349         mLocalMatrixDirty[i] = mComponentDirty[i] || (previousLocalMatrix != mLocal[i]);
350       }
351     }
352     else //Component has no parent or doesn't inherit transform
353     {
354       Matrix localMatrix = mLocal[i];
355       CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
356       localPosition = mTxComponentAnimatable[i].mPosition + centerPosition;
357       mLocal[i].SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition);
358       mWorld[i]            = mLocal[i];
359       mLocalMatrixDirty[i] = mComponentDirty[i] || (localMatrix != mLocal[i]);
360     }
361
362     //Update the bounding sphere
363     Vec3 centerToEdge = {mSize[i].Length() * 0.5f, 0.0f, 0.0f};
364     Vec3 centerToEdgeWorldSpace;
365     TransformVector3(centerToEdgeWorldSpace, mWorld[i].AsFloat(), centerToEdge);
366
367     mBoundingSpheres[i]   = mWorld[i].GetTranslation();
368     mBoundingSpheres[i].w = Length(centerToEdgeWorldSpace);
369
370     componentsChanged = componentsChanged || mComponentDirty[i];
371     mComponentDirty[i] >>= 1u; ///< age down.
372   }
373
374   DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_TRANSFORM_UPDATE", [&](std::ostringstream& oss) {
375     oss << "[componentsChanged:" << componentsChanged << "]";
376   });
377
378   return componentsChanged;
379 }
380
381 void TransformManager::SwapComponents(unsigned int i, unsigned int j)
382 {
383   std::swap(mTxComponentAnimatable[i], mTxComponentAnimatable[j]);
384   std::swap(mTxComponentStatic[i], mTxComponentStatic[j]);
385   std::swap(mInheritanceMode[i], mInheritanceMode[j]);
386   std::swap(mSize[i], mSize[j]);
387   std::swap(mParent[i], mParent[j]);
388   std::swap(mComponentId[i], mComponentId[j]);
389   std::swap(mTxComponentAnimatableBaseValue[i], mTxComponentAnimatableBaseValue[j]);
390   std::swap(mSizeBase[i], mSizeBase[j]);
391   std::swap(mLocal[i], mLocal[j]);
392   std::swap(mComponentDirty[i], mComponentDirty[j]);
393   std::swap(mBoundingSpheres[i], mBoundingSpheres[j]);
394   std::swap(mWorld[i], mWorld[j]);
395
396   mIds[mComponentId[i]] = i;
397   mIds[mComponentId[j]] = j;
398 }
399
400 void TransformManager::ReorderComponents()
401 {
402   mOrderedComponents.Resize(mComponentCount);
403
404   uint16_t    sceneId = 0u;
405   TransformId parentId;
406
407   // Create sceneId first
408   for(TransformId i = 0; i < mComponentCount; ++i)
409   {
410     mOrderedComponents[i].id    = mComponentId[i];
411     mOrderedComponents[i].level = 0u;
412
413     parentId = mParent[i];
414     if(parentId == INVALID_TRANSFORM_ID)
415     {
416       mOrderedComponents[i].sceneId = sceneId++;
417     }
418   }
419
420   // Propagate sceneId and level
421   for(TransformId i = 0; i < mComponentCount; ++i)
422   {
423     parentId = mParent[i];
424     while(parentId != INVALID_TRANSFORM_ID)
425     {
426       const uint32_t parentIndex = mIds[parentId];
427       ++mOrderedComponents[i].level;
428       mOrderedComponents[i].sceneId = mOrderedComponents[parentIndex].sceneId;
429       if(parentIndex < i)
430       {
431         // Parent information update done. We can reuse it.
432         mOrderedComponents[i].level += mOrderedComponents[parentIndex].level;
433         break;
434       }
435       else
436       {
437         parentId = mParent[parentIndex];
438       }
439     }
440   }
441
442   std::stable_sort(mOrderedComponents.Begin(), mOrderedComponents.End());
443   TransformId previousIndex = 0;
444   for(TransformId newIndex = 0; newIndex < mComponentCount - 1; ++newIndex)
445   {
446     previousIndex = mIds[mOrderedComponents[newIndex].id];
447     if(previousIndex != newIndex)
448     {
449       SwapComponents(previousIndex, newIndex);
450     }
451   }
452
453 #if defined(LOW_SPEC_MEMORY_MANAGEMENT_ENABLED)
454   // Since Resize() operation will make overhead when we create new Transform::Data, let we check shrink to fit trigger like this.
455   if(DALI_UNLIKELY(static_cast<decltype(mTxComponentAnimatable)::SizeType>(mComponentCount) * Dali::VectorBase::SHRINK_REQUIRED_RATIO < mTxComponentAnimatable.Capacity()))
456   {
457     // Reduce the capacity of vector.
458     // Note that reduce vector capacity will make performance down.
459     // Please do not doing this frequencly.
460
461     // NOTE : We cannot reduce FreeList type for now.
462
463     mTxComponentAnimatable.Resize(mComponentCount);
464     mTxComponentStatic.Resize(mComponentCount);
465     mInheritanceMode.Resize(mComponentCount);
466     mComponentId.Resize(mComponentCount);
467     mSize.Resize(mComponentCount);
468     mParent.Resize(mComponentCount);
469     mWorld.Resize(mComponentCount);
470     mLocal.Resize(mComponentCount);
471     mBoundingSpheres.Resize(mComponentCount);
472     mTxComponentAnimatableBaseValue.Resize(mComponentCount);
473     mSizeBase.Resize(mComponentCount);
474     mComponentDirty.Resize(mComponentCount);
475     mLocalMatrixDirty.Resize(mComponentCount);
476     mOrderedComponents.Resize(mComponentCount);
477
478     mTxComponentAnimatable.ShrinkToFit();
479     mTxComponentStatic.ShrinkToFit();
480     mInheritanceMode.ShrinkToFit();
481     mComponentId.ShrinkToFit();
482     mSize.ShrinkToFit();
483     mParent.ShrinkToFit();
484     mWorld.ShrinkToFit();
485     mLocal.ShrinkToFit();
486     mBoundingSpheres.ShrinkToFit();
487     mTxComponentAnimatableBaseValue.ShrinkToFit();
488     mSizeBase.ShrinkToFit();
489     mComponentDirty.ShrinkToFit();
490     mLocalMatrixDirty.ShrinkToFit();
491     mOrderedComponents.ShrinkToFit();
492   }
493 #endif
494 }
495
496 Vector3& TransformManager::GetVector3PropertyValue(TransformId id, TransformManagerProperty property)
497 {
498   switch(property)
499   {
500     case TRANSFORM_PROPERTY_POSITION:
501     {
502       TransformId index(mIds[id]);
503       return mTxComponentAnimatable[index].mPosition;
504     }
505     case TRANSFORM_PROPERTY_SCALE:
506     {
507       TransformId index(mIds[id]);
508       return mTxComponentAnimatable[index].mScale;
509     }
510     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
511     {
512       TransformId index(mIds[id]);
513       return mTxComponentStatic[index].mParentOrigin;
514     }
515     case TRANSFORM_PROPERTY_ANCHOR_POINT:
516     {
517       TransformId index(mIds[id]);
518       return mTxComponentStatic[index].mAnchorPoint;
519     }
520     case TRANSFORM_PROPERTY_SIZE:
521     {
522       TransformId index(mIds[id]);
523       return mSize[index];
524     }
525     default:
526     {
527       DALI_ASSERT_ALWAYS(false);
528       return mTxComponentAnimatable[mIds[id]].mPosition;
529     }
530   }
531 }
532
533 const Vector3& TransformManager::GetVector3PropertyValue(TransformId id, TransformManagerProperty property) const
534 {
535   switch(property)
536   {
537     case TRANSFORM_PROPERTY_POSITION:
538     {
539       return mTxComponentAnimatable[mIds[id]].mPosition;
540     }
541     case TRANSFORM_PROPERTY_SCALE:
542     {
543       return mTxComponentAnimatable[mIds[id]].mScale;
544     }
545     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
546     {
547       return mTxComponentStatic[mIds[id]].mParentOrigin;
548     }
549     case TRANSFORM_PROPERTY_ANCHOR_POINT:
550     {
551       return mTxComponentStatic[mIds[id]].mAnchorPoint;
552     }
553     case TRANSFORM_PROPERTY_SIZE:
554     {
555       return mSize[mIds[id]];
556     }
557     default:
558     {
559       DALI_ASSERT_ALWAYS(false);
560       return mTxComponentAnimatable[mIds[id]].mPosition;
561     }
562   }
563 }
564
565 const float& TransformManager::GetVector3PropertyComponentValue(TransformId id, TransformManagerProperty property, unsigned int component) const
566 {
567   switch(property)
568   {
569     case TRANSFORM_PROPERTY_POSITION:
570     {
571       return mTxComponentAnimatable[mIds[id]].mPosition[component];
572     }
573     case TRANSFORM_PROPERTY_SCALE:
574     {
575       return mTxComponentAnimatable[mIds[id]].mScale[component];
576     }
577     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
578     {
579       return mTxComponentStatic[mIds[id]].mParentOrigin[component];
580     }
581     case TRANSFORM_PROPERTY_ANCHOR_POINT:
582     {
583       return mTxComponentStatic[mIds[id]].mAnchorPoint[component];
584     }
585     case TRANSFORM_PROPERTY_SIZE:
586     {
587       return mSize[mIds[id]][component];
588     }
589     default:
590     {
591       DALI_ASSERT_ALWAYS(false);
592       return mTxComponentAnimatable[mIds[id]].mPosition[component];
593     }
594   }
595 }
596
597 void TransformManager::SetVector3PropertyValue(TransformId id, TransformManagerProperty property, const Vector3& value)
598 {
599   TransformId index(mIds[id]);
600
601   switch(property)
602   {
603     case TRANSFORM_PROPERTY_POSITION:
604     {
605       mComponentDirty[index]                  = SET_FLAG;
606       mTxComponentAnimatable[index].mPosition = value;
607       break;
608     }
609     case TRANSFORM_PROPERTY_SCALE:
610     {
611       mComponentDirty[index]               = SET_FLAG;
612       mTxComponentAnimatable[index].mScale = value;
613       break;
614     }
615     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
616     {
617       mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
618       mTxComponentStatic[index].mParentOrigin = value;
619       break;
620     }
621     case TRANSFORM_PROPERTY_ANCHOR_POINT:
622     {
623       mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
624       mTxComponentStatic[index].mAnchorPoint = value;
625       break;
626     }
627     case TRANSFORM_PROPERTY_SIZE:
628     {
629       mComponentDirty[index] = SET_FLAG;
630       mSize[index]           = value;
631       break;
632     }
633     default:
634     {
635       DALI_ASSERT_ALWAYS(false);
636     }
637   }
638 }
639
640 void TransformManager::SetVector3PropertyComponentValue(TransformId id, TransformManagerProperty property, float value, unsigned int component)
641 {
642   TransformId index(mIds[id]);
643
644   switch(property)
645   {
646     case TRANSFORM_PROPERTY_POSITION:
647     {
648       mComponentDirty[index]                             = SET_FLAG;
649       mTxComponentAnimatable[index].mPosition[component] = value;
650       break;
651     }
652     case TRANSFORM_PROPERTY_SCALE:
653     {
654       mComponentDirty[index]                          = SET_FLAG;
655       mTxComponentAnimatable[index].mScale[component] = value;
656       break;
657     }
658     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
659     {
660       mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
661       mTxComponentStatic[index].mParentOrigin[component] = value;
662       break;
663     }
664     case TRANSFORM_PROPERTY_ANCHOR_POINT:
665     {
666       mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
667       mTxComponentStatic[index].mAnchorPoint[component] = value;
668       break;
669     }
670     case TRANSFORM_PROPERTY_SIZE:
671     {
672       mComponentDirty[index]  = SET_FLAG;
673       mSize[index][component] = value;
674       break;
675     }
676     default:
677     {
678       DALI_ASSERT_ALWAYS(false);
679     }
680   }
681 }
682
683 void TransformManager::BakeVector3PropertyValue(TransformId id, TransformManagerProperty property, const Vector3& value)
684 {
685   TransformId index(mIds[id]);
686   mComponentDirty[index] |= BAKED_FLAG;
687
688   switch(property)
689   {
690     case TRANSFORM_PROPERTY_POSITION:
691     {
692       mTxComponentAnimatable[index].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = value;
693       break;
694     }
695     case TRANSFORM_PROPERTY_SCALE:
696     {
697       mTxComponentAnimatable[index].mScale = mTxComponentAnimatableBaseValue[index].mScale = value;
698       break;
699     }
700     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
701     {
702       mTxComponentStatic[index].mParentOrigin = value;
703       break;
704     }
705     case TRANSFORM_PROPERTY_ANCHOR_POINT:
706     {
707       mTxComponentStatic[index].mAnchorPoint = value;
708       break;
709     }
710     case TRANSFORM_PROPERTY_SIZE:
711     {
712       mSize[index] = mSizeBase[index] = value;
713       break;
714     }
715     default:
716     {
717       DALI_ASSERT_ALWAYS(false);
718     }
719   }
720 }
721
722 void TransformManager::BakeRelativeVector3PropertyValue(TransformId id, TransformManagerProperty property, const Vector3& value)
723 {
724   TransformId index(mIds[id]);
725   mComponentDirty[index] |= BAKED_FLAG;
726
727   switch(property)
728   {
729     case TRANSFORM_PROPERTY_POSITION:
730     {
731       mTxComponentAnimatable[index].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = mTxComponentAnimatable[index].mPosition + value;
732       break;
733     }
734     case TRANSFORM_PROPERTY_SCALE:
735     {
736       mTxComponentAnimatable[index].mScale = mTxComponentAnimatableBaseValue[index].mScale = mTxComponentAnimatable[index].mScale + value;
737       break;
738     }
739     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
740     {
741       mTxComponentStatic[index].mParentOrigin = mTxComponentStatic[index].mParentOrigin + value;
742       break;
743     }
744     case TRANSFORM_PROPERTY_ANCHOR_POINT:
745     {
746       mTxComponentStatic[index].mAnchorPoint = mTxComponentStatic[index].mAnchorPoint + value;
747       break;
748     }
749     case TRANSFORM_PROPERTY_SIZE:
750     {
751       mSize[index] = mSizeBase[index] = mSize[index] + value;
752       break;
753     }
754     default:
755     {
756       DALI_ASSERT_ALWAYS(false);
757     }
758   }
759 }
760
761 void TransformManager::BakeMultiplyVector3PropertyValue(TransformId id, TransformManagerProperty property, const Vector3& value)
762 {
763   TransformId index(mIds[id]);
764   mComponentDirty[index] |= BAKED_FLAG;
765
766   switch(property)
767   {
768     case TRANSFORM_PROPERTY_POSITION:
769     {
770       mTxComponentAnimatable[index].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = mTxComponentAnimatable[index].mPosition * value;
771       break;
772     }
773     case TRANSFORM_PROPERTY_SCALE:
774     {
775       mTxComponentAnimatable[index].mScale = mTxComponentAnimatableBaseValue[index].mScale = mTxComponentAnimatable[index].mScale * value;
776       break;
777     }
778     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
779     {
780       mTxComponentStatic[index].mParentOrigin = mTxComponentStatic[index].mParentOrigin * value;
781       break;
782     }
783     case TRANSFORM_PROPERTY_ANCHOR_POINT:
784     {
785       mTxComponentStatic[index].mAnchorPoint = mTxComponentStatic[index].mAnchorPoint * value;
786       break;
787     }
788     case TRANSFORM_PROPERTY_SIZE:
789     {
790       mSize[index] = mSizeBase[index] = mSize[index] * value;
791       break;
792     }
793     default:
794     {
795       DALI_ASSERT_ALWAYS(false);
796     }
797   }
798 }
799
800 void TransformManager::BakeVector3PropertyComponentValue(TransformId id, TransformManagerProperty property, float value, unsigned int component)
801 {
802   TransformId index(mIds[id]);
803   mComponentDirty[index] |= BAKED_FLAG;
804
805   switch(property)
806   {
807     case TRANSFORM_PROPERTY_POSITION:
808     {
809       mTxComponentAnimatable[index].mPosition[component] = mTxComponentAnimatableBaseValue[index].mPosition[component] = value;
810       break;
811     }
812     case TRANSFORM_PROPERTY_SCALE:
813     {
814       mTxComponentAnimatable[index].mScale[component] = mTxComponentAnimatableBaseValue[index].mScale[component] = value;
815       break;
816     }
817     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
818     {
819       mTxComponentStatic[index].mParentOrigin[component] = value;
820       break;
821     }
822     case TRANSFORM_PROPERTY_ANCHOR_POINT:
823     {
824       mTxComponentStatic[index].mAnchorPoint[component] = value;
825       break;
826     }
827     case TRANSFORM_PROPERTY_SIZE:
828     {
829       mSize[index][component] = mSizeBase[index][component] = value;
830       break;
831     }
832     default:
833     {
834       DALI_ASSERT_ALWAYS(false);
835     }
836   }
837 }
838
839 void TransformManager::BakeXVector3PropertyValue(TransformId id, TransformManagerProperty property, float value)
840 {
841   TransformId index(mIds[id]);
842   mComponentDirty[index] |= BAKED_FLAG;
843
844   switch(property)
845   {
846     case TRANSFORM_PROPERTY_POSITION:
847     {
848       mTxComponentAnimatable[index].mPosition.x = mTxComponentAnimatableBaseValue[index].mPosition.x = value;
849       break;
850     }
851     case TRANSFORM_PROPERTY_SCALE:
852     {
853       mTxComponentAnimatable[index].mScale.x = mTxComponentAnimatableBaseValue[index].mScale.x = value;
854       break;
855     }
856     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
857     {
858       mTxComponentStatic[index].mParentOrigin.x = value;
859       break;
860     }
861     case TRANSFORM_PROPERTY_ANCHOR_POINT:
862     {
863       mTxComponentStatic[index].mAnchorPoint.x = value;
864       break;
865     }
866     case TRANSFORM_PROPERTY_SIZE:
867     {
868       mSize[index].x = mSizeBase[index].x = value;
869       break;
870     }
871     default:
872     {
873       DALI_ASSERT_ALWAYS(false);
874     }
875   }
876 }
877
878 void TransformManager::BakeYVector3PropertyValue(TransformId id, TransformManagerProperty property, float value)
879 {
880   TransformId index(mIds[id]);
881   mComponentDirty[index] |= BAKED_FLAG;
882
883   switch(property)
884   {
885     case TRANSFORM_PROPERTY_POSITION:
886     {
887       mTxComponentAnimatable[index].mPosition.y = mTxComponentAnimatableBaseValue[index].mPosition.y = value;
888       break;
889     }
890     case TRANSFORM_PROPERTY_SCALE:
891     {
892       mTxComponentAnimatable[index].mScale.y = mTxComponentAnimatableBaseValue[index].mScale.y = value;
893       break;
894     }
895     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
896     {
897       mTxComponentStatic[index].mParentOrigin.y = value;
898       break;
899     }
900     case TRANSFORM_PROPERTY_ANCHOR_POINT:
901     {
902       mTxComponentStatic[index].mAnchorPoint.y = value;
903       break;
904     }
905     case TRANSFORM_PROPERTY_SIZE:
906     {
907       mSize[index].y = mSizeBase[index].y = value;
908       break;
909     }
910     default:
911     {
912       DALI_ASSERT_ALWAYS(false);
913     }
914   }
915 }
916
917 void TransformManager::BakeZVector3PropertyValue(TransformId id, TransformManagerProperty property, float value)
918 {
919   TransformId index(mIds[id]);
920   mComponentDirty[index] |= BAKED_FLAG;
921
922   switch(property)
923   {
924     case TRANSFORM_PROPERTY_POSITION:
925     {
926       mTxComponentAnimatable[index].mPosition.z = mTxComponentAnimatableBaseValue[index].mPosition.z = value;
927       break;
928     }
929     case TRANSFORM_PROPERTY_SCALE:
930     {
931       mTxComponentAnimatable[index].mScale.z = mTxComponentAnimatableBaseValue[index].mScale.z = value;
932       break;
933     }
934     case TRANSFORM_PROPERTY_PARENT_ORIGIN:
935     {
936       mTxComponentStatic[index].mParentOrigin.z = value;
937       break;
938     }
939     case TRANSFORM_PROPERTY_ANCHOR_POINT:
940     {
941       mTxComponentStatic[index].mAnchorPoint.z = value;
942       break;
943     }
944     case TRANSFORM_PROPERTY_SIZE:
945     {
946       mSize[index].z = mSizeBase[index].z = value;
947       break;
948     }
949     default:
950     {
951       DALI_ASSERT_ALWAYS(false);
952     }
953   }
954 }
955
956 Quaternion& TransformManager::GetQuaternionPropertyValue(TransformId id)
957 {
958   TransformId index(mIds[id]);
959   return mTxComponentAnimatable[index].mOrientation;
960 }
961
962 const Quaternion& TransformManager::GetQuaternionPropertyValue(TransformId id) const
963 {
964   return mTxComponentAnimatable[mIds[id]].mOrientation;
965 }
966
967 void TransformManager::SetQuaternionPropertyValue(TransformId id, const Quaternion& q)
968 {
969   TransformId index(mIds[id]);
970   mComponentDirty[index] = SET_FLAG;
971
972   mTxComponentAnimatable[index].mOrientation = q;
973 }
974
975 void TransformManager::BakeQuaternionPropertyValue(TransformId id, const Quaternion& q)
976 {
977   TransformId index(mIds[id]);
978   mComponentDirty[index] |= BAKED_FLAG;
979
980   mTxComponentAnimatable[index].mOrientation = mTxComponentAnimatableBaseValue[index].mOrientation = q;
981 }
982
983 void TransformManager::BakeRelativeQuaternionPropertyValue(TransformId id, const Quaternion& q)
984 {
985   TransformId index(mIds[id]);
986   mComponentDirty[index] |= BAKED_FLAG;
987
988   mTxComponentAnimatable[index].mOrientation = mTxComponentAnimatableBaseValue[index].mOrientation = mTxComponentAnimatable[index].mOrientation * q;
989 }
990
991 const Vector4& TransformManager::GetBoundingSphere(TransformId id) const
992 {
993   return mBoundingSpheres[mIds[id]];
994 }
995
996 void TransformManager::GetWorldMatrixAndSize(TransformId id, Matrix& worldMatrix, Vector3& size) const
997 {
998   TransformId index = mIds[id];
999   worldMatrix       = mWorld[index];
1000   size              = mSize[index];
1001 }
1002
1003 void TransformManager::SetPositionUsesAnchorPoint(TransformId id, bool value)
1004 {
1005   TransformId index(mIds[id]);
1006   mComponentDirty[index] |= STATIC_COMPONENT_FLAG;
1007
1008   mTxComponentStatic[index].mPositionUsesAnchorPoint = value;
1009 }
1010
1011 } //namespace SceneGraph
1012 } //namespace Internal
1013 } //namespace Dali