Data oriented transform manager 01/58001/49
authorFerran Sole <ferran.sole@samsung.com>
Tue, 26 Jan 2016 15:40:49 +0000 (15:40 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Thu, 17 Mar 2016 17:44:20 +0000 (17:44 +0000)
Added a transform manager which computes the local to world transformations
of all the nodes in the scene. All the transformation data is stored contiguously
in memory which minimizes cache misses during updates.

Change-Id: I95caa2ffafc1ba1b7a83b6cbaf4ad6d9f0fd54fe

31 files changed:
automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-CameraActor.cpp
dali/internal/common/core-impl.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/camera-actor-impl.cpp
dali/internal/event/animation/animator-connector.h
dali/internal/event/animation/constraint-impl.h
dali/internal/event/common/property-input-impl.h
dali/internal/file.list
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-item.h
dali/internal/render/data-providers/node-data-provider.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/update/animation/property-accessor.h
dali/internal/update/animation/scene-graph-animator.h
dali/internal/update/manager/free-list.h [new file with mode: 0644]
dali/internal/update/manager/prepare-render-instructions.cpp
dali/internal/update/manager/transform-manager-property.h [new file with mode: 0644]
dali/internal/update/manager/transform-manager.cpp [new file with mode: 0644]
dali/internal/update/manager/transform-manager.h [new file with mode: 0644]
dali/internal/update/manager/update-algorithms.cpp
dali/internal/update/manager/update-manager.cpp
dali/internal/update/node-attachments/node-attachment.h
dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp
dali/internal/update/node-attachments/scene-graph-camera-attachment.h
dali/internal/update/nodes/node-messages.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/render-tasks/scene-graph-render-task.cpp

index bccd367..1761530 100644 (file)
@@ -165,16 +165,8 @@ int UtcFrustumLeftCullP(void)
   float offset = -0.01f;
   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_RIGHT );
 
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
   Vector2 stageSize = Stage::GetCurrent().GetSize();
-
   meshActor.SetParentOrigin( Vector3( -radius / stageSize.width + offset, 0.5f, 0.5f ) );
   meshActor.SetAnchorPoint( AnchorPoint::CENTER );
 
@@ -217,13 +209,6 @@ int UtcFrustumRightCullP(void)
   float offset = 1.01f;
   Actor meshActor = CreateMeshActorToStage( application, Vector3( offset, 0.5f, 0.5f ), AnchorPoint::CENTER_LEFT );
 
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
   Vector2 stageSize = Stage::GetCurrent().GetSize();
 
@@ -269,13 +254,6 @@ int UtcFrustumTopCullP(void)
   float offset = -0.01f;
   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::BOTTOM_CENTER );
 
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
   Vector2 stageSize = Stage::GetCurrent().GetSize();
 
@@ -322,13 +300,6 @@ int UtcFrustumBottomCullP(void)
   float offset = 1.01f;
   Actor meshActor = CreateMeshActorToStage( application, Vector3( 0.5f, offset, 0.5f ), AnchorPoint::TOP_CENTER );
 
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
   Vector2 stageSize = Stage::GetCurrent().GetSize();
 
@@ -378,18 +349,7 @@ int UtcFrustumNearCullP(void)
   Vector3 meshPosition = meshActor.GetCurrentPosition();
 
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
-  float offset = ( meshActor.GetTargetSize().z + radius ) * 0.5f; //midpoint between AABB and sphere
-  meshPosition.z = cameraDepth - nearPlane +  offset;
-  meshActor.SetPosition( meshPosition );
-
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
-  offset = radius + 0.1f;
+  float offset = radius + 0.1f;
   meshPosition.z = cameraDepth - nearPlane + offset;
   meshActor.SetPosition( meshPosition );
 
@@ -443,19 +403,7 @@ int UtcFrustumFarCullP(void)
   Vector3 meshPosition = meshActor.GetCurrentPosition();
 
   float radius = meshActor.GetTargetSize().Length() * 0.5f;
-  float offset = ( meshActor.GetTargetSize().z + radius ) * 0.5f; //midpoint between AABB and sphere
-
-  meshPosition.z = cameraDepth - farPlane - offset;
-  meshActor.SetPosition( meshPosition );
-
-  drawTrace.Reset();
-  application.SendNotification();
-  application.Render( 16 );
-
-  // This will be box culled
-  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
-
-  offset = radius + 0.1f;
+  float offset = radius + 0.1f;
   meshPosition.z = cameraDepth - farPlane - offset;
   meshActor.SetPosition( meshPosition );
 
index 1de3046..081c878 100644 (file)
@@ -1073,7 +1073,7 @@ int UtcDaliActorInheritPosition(void)
   DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
   DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
 
-  // first test default, which is INHERIT_PARENT_POSITION
+  // first test default, which is to inherit position
   DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::INHERIT_PARENT_POSITION, TEST_LOCATION );
   application.SendNotification();
   application.Render(0); // should only really call Update as Render is not required to update scene
@@ -1082,27 +1082,10 @@ int UtcDaliActorInheritPosition(void)
   DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
   DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childPosition, TEST_LOCATION );
 
-  // Change inheritance mode to use parent
-  child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION, TEST_LOCATION );
-  application.SendNotification();
-  application.Render(0); // should only really call Update as Render is not required to update scene
-  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION );
-  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
 
-  // Change inheritance mode to use parent + offset
-  child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+  //Change child position
   Vector3 childOffset( -1.0f, 1.0f, 0.0f );
   child.SetPosition( childOffset );
-  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION, TEST_LOCATION );
-  application.SendNotification();
-  application.Render(0); // should only really call Update as Render is not required to update scene
-  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentPosition(), childOffset, TEST_LOCATION );
-  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childOffset, TEST_LOCATION );
 
   // Change inheritance mode to not inherit
   child.SetPositionInheritanceMode( Dali::DONT_INHERIT_POSITION );
@@ -1728,6 +1711,9 @@ int UtcDaliActorScreenToLocal(void)
   float localX;
   float localY;
 
+  application.SendNotification();
+  application.Render();
+
   DALI_TEST_CHECK( actor.ScreenToLocal(localX, localY, 50.0f, 50.0f) );
 
   DALI_TEST_EQUALS(localX, 40.0f, 0.01f, TEST_LOCATION);
@@ -2296,10 +2282,6 @@ int UtcDaliActorGetCurrentWorldMatrix(void)
   child.SetScale( childScale );
   parent.Add( child );
 
-  // The actors should not have a world matrix yet
-  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
-
   app.SendNotification();
   app.Render(0);
   app.Render();
@@ -2308,12 +2290,12 @@ int UtcDaliActorGetCurrentWorldMatrix(void)
   Matrix parentMatrix(false);
   parentMatrix.SetTransformComponents(parentScale, parentRotation, parentPosition);
 
-  Vector3 childWorldPosition = parentPosition + parentRotation * parentScale * childPosition;
-  Quaternion childWorldRotation = parentRotation * childRotation;
-  Vector3 childWorldScale = parentScale * childScale;
+  Matrix childMatrix(false);
+  childMatrix.SetTransformComponents( childScale, childRotation, childPosition );
 
+  //Child matrix should be the composition of child and parent
   Matrix childWorldMatrix(false);
-  childWorldMatrix.SetTransformComponents(childWorldScale, childWorldRotation, childWorldPosition);
+  Matrix::Multiply( childWorldMatrix, childMatrix, parentMatrix);
 
   DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), parentMatrix, 0.001, TEST_LOCATION );
   DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), childWorldMatrix, 0.001, TEST_LOCATION );
@@ -2347,10 +2329,6 @@ int UtcDaliActorConstrainedToWorldMatrix(void)
 
   Stage::GetCurrent().Add( child );
 
-  // The actors should not have a world matrix yet
-  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
-  DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
-
   app.SendNotification();
   app.Render(0);
   app.Render();
index 5e92e44..5100ac0 100644 (file)
@@ -1207,6 +1207,9 @@ int UtcDaliCameraActorDefaultProperties(void)
   tet_infoline( "Testing Dali::CameraActor DefaultProperties" );
 
   CameraActor actor = CameraActor::New();
+  Stage stage = Stage::GetCurrent();
+  stage.Add(actor);
+  stage.GetRenderTaskList().GetTask(0).SetCameraActor( actor );
 
   actor.SetAspectRatio( TEST_ASPECT_RATIO );
   Stage::GetCurrent().Add( actor );
@@ -1469,6 +1472,7 @@ int UtcDaliCameraActorCheckLookAtAndFreeLookViews02(void)
   stage.Add( target );
   stage.Add( freeLookCameraActor );
   stage.Add( lookAtCameraActor );
+  stage.GetRenderTaskList().GetTask(0).SetCameraActor( freeLookCameraActor );
 
   // Create an arbitrary vector
   for( float x=-1.0f; x<=1.0f; x+=0.1f )
@@ -1489,20 +1493,17 @@ int UtcDaliCameraActorCheckLookAtAndFreeLookViews02(void)
         application.SendNotification();
         application.Render();
         Matrix freeLookViewMatrix;
-        Matrix lookAtViewMatrix;
         freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix );
-        lookAtCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( lookAtViewMatrix );
 
         Matrix freeLookWorld = freeLookCameraActor.GetCurrentWorldMatrix();
 
         Matrix freeLookTest( false );
         Matrix::Multiply( freeLookTest, freeLookViewMatrix, freeLookWorld );
         DALI_TEST_EQUALS( freeLookTest, Matrix::IDENTITY, 0.01f, TEST_LOCATION );
-
-        DALI_TEST_EQUALS( freeLookViewMatrix, lookAtViewMatrix, 0.01, TEST_LOCATION );
       }
     }
   }
+
   END_TEST;
 }
 
@@ -1526,6 +1527,7 @@ int UtcDaliCameraActorCheckLookAtAndFreeLookViews03(void)
   Actor cameraAnchor = Actor::New();
   cameraAnchor.Add( freeLookCameraActor );
   stage.Add( cameraAnchor );
+  stage.GetRenderTaskList().GetTask(0).SetCameraActor( freeLookCameraActor );
 
   for( float angle = 1.0f; angle <= 180.0f; angle += 1.0f )
   {
index efd603d..fbd547e 100644 (file)
@@ -204,10 +204,10 @@ Core::~Core()
   delete mShaderFactory;
   delete mResourceClient;
   delete mResourceManager;
+  delete mDiscardQueue;
   delete mUpdateManager;
   delete mTouchResampler;
   delete mRenderManager;
-  delete mDiscardQueue;
   delete mTextureUploadedQueue;
 }
 
index 932c872..b7b8f74 100644 (file)
@@ -660,7 +660,7 @@ void Actor::SetPosition( const Vector3& position )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
   }
 }
 
@@ -671,7 +671,7 @@ void Actor::SetX( float x )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
   }
 }
 
@@ -682,7 +682,7 @@ void Actor::SetY( float y )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
   }
 }
 
@@ -693,7 +693,7 @@ void Actor::SetZ( float z )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
   }
 }
 
@@ -704,7 +704,7 @@ void Actor::TranslateBy( const Vector3& distance )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
   }
 }
 
@@ -754,9 +754,10 @@ PositionInheritanceMode Actor::GetPositionInheritanceMode() const
 
 void Actor::SetInheritPosition( bool inherit )
 {
-  mInheritPosition = inherit;
-  if( NULL != mNode )
+  if( mInheritPosition != inherit && NULL != mNode )
   {
+    // non animateable so keep local copy
+    mInheritPosition = inherit;
     SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
   }
 }
@@ -781,7 +782,7 @@ void Actor::SetOrientation( const Quaternion& orientation )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
+    SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
   }
 }
 
@@ -790,7 +791,7 @@ void Actor::RotateBy( const Radian& angle, const Vector3& axis )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
+    SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
   }
 }
 
@@ -799,7 +800,7 @@ void Actor::RotateBy( const Quaternion& relativeRotation )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
+    SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
   }
 }
 
@@ -840,7 +841,7 @@ void Actor::SetScale( const Vector3& scale )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
   }
 }
 
@@ -849,7 +850,7 @@ void Actor::SetScaleX( float x )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
   }
 }
 
@@ -858,7 +859,7 @@ void Actor::SetScaleY( float y )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
   }
 }
 
@@ -867,7 +868,7 @@ void Actor::SetScaleZ( float z )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
   }
 }
 
@@ -876,7 +877,7 @@ void Actor::ScaleBy(const Vector3& relativeScale)
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
   }
 }
 
@@ -904,10 +905,11 @@ const Vector3& Actor::GetCurrentWorldScale() const
 
 void Actor::SetInheritScale( bool inherit )
 {
-  // non animateable so keep local copy
-  mInheritScale = inherit;
-  if( NULL != mNode )
+
+  if( mInheritScale != inherit && NULL != mNode )
   {
+    // non animateable so keep local copy
+    mInheritScale = inherit;
     // mNode is being used in a separate thread; queue a message to set the value
     SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
   }
@@ -922,14 +924,7 @@ Matrix Actor::GetCurrentWorldMatrix() const
 {
   if( NULL != mNode )
   {
-    // World matrix is no longer updated unless there is something observing the node.
-    // Need to calculate it from node's world position, orientation and scale:
-    BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
-    Matrix worldMatrix(false);
-    worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
-                                        mNode->GetWorldOrientation( updateBufferIndex ),
-                                        mNode->GetWorldPosition( updateBufferIndex ) );
-    return worldMatrix;
+    return mNode->GetWorldMatrix(0);
   }
 
   return Matrix::IDENTITY;
@@ -1034,10 +1029,10 @@ const Vector4& Actor::GetCurrentColor() const
 
 void Actor::SetInheritOrientation( bool inherit )
 {
-  // non animateable so keep local copy
-  mInheritOrientation = inherit;
-  if( NULL != mNode )
+  if( mInheritOrientation != inherit && NULL != mNode)
   {
+    // non animateable so keep local copy
+    mInheritOrientation = inherit;
     // mNode is being used in a separate thread; queue a message to set the value
     SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
   }
@@ -1128,7 +1123,7 @@ void Actor::SetSizeInternal( const Vector3& size )
     mTargetSize = size;
 
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
 
     // Notification for derived classes
     mInsideOnSizeSet = true;
@@ -1197,7 +1192,7 @@ void Actor::SetWidth( float width )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
   }
 }
 
@@ -1208,7 +1203,7 @@ void Actor::SetHeight( float height )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
   }
 }
 
@@ -1219,7 +1214,7 @@ void Actor::SetDepth( float depth )
   if( NULL != mNode )
   {
     // mNode is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
   }
 }
 
@@ -1556,13 +1551,9 @@ bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMat
     return false;
   }
 
-  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
-
-  // Calculate the ModelView matrix
-  Matrix modelView( false/*don't init*/);
-  // need to use the components as world matrix is only updated for actors that need it
-  modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
-  Matrix::Multiply( modelView, modelView, viewMatrix );
+  // Get the ModelView matrix
+  Matrix modelView;
+  Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
 
   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
   Matrix invertedMvp( false/*don't init*/);
@@ -1707,8 +1698,8 @@ bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vecto
     Matrix invModelMatrix( false/*don't init*/);
 
     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
-    // need to use the components as world matrix is only updated for actors that need it
-    invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
+    invModelMatrix = mNode->GetWorldMatrix(0);
+    invModelMatrix.Invert();
 
     Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
     Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
index 20e695e..18e8676 100644 (file)
@@ -337,7 +337,7 @@ bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates,
   {
     // Build a picking ray in the world reference system.
     // ray starts from the camera world position
-    rayOrigin = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
+    rayOrigin = mNode->GetWorldMatrix(0).GetTranslation();
     rayOrigin.w = 1.0f;
 
     // Transform the touch point from the screen coordinate system to the world coordinates system.
index 9440f91..e06225d 100644 (file)
@@ -195,149 +195,186 @@ private:
       //Cast to AnimatableProperty
       const PropertyInterfaceType* animatableProperty = dynamic_cast< const PropertyInterfaceType* >( baseProperty );
 
-      //Dynamic cast will fail if BaseProperty is not an AnimatableProperty
-      DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+      if( animatableProperty == NULL )
+      {
+        if( baseProperty->IsTransformManagerProperty() )
+        {
+          mAnimator = SceneGraph::AnimatorTransformProperty< PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+        }
+        else
+        {
+          DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+        }
 
-      //Create the animator
-      mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+      }
+      else
+      {
+        //Create the animator
+        mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+      }
 
     }
     else
     {
-      ///Animating a component of the property
-      if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() )
       {
-        // Animate float component of Vector2 property
-
-        // Cast to AnimatableProperty of type Vector2
-        const SceneGraph::AnimatableProperty<Vector2>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector2>* >( baseProperty );
+        ///Animating a component of the property
+        if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() )
+        {
+          // Animate float component of Vector2 property
 
-        //Dynamic cast will fail if BaseProperty is not a Vector2 AnimatableProperty
-        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+          // Cast to AnimatableProperty of type Vector2
+          const SceneGraph::AnimatableProperty<Vector2>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector2>* >( baseProperty );
+          DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
 
-        switch( mComponentIndex )
-        {
-          case 0:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector2> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 1:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector2> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          default:
+          switch( mComponentIndex )
           {
-            break;
+            case 0:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector2> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+            case 1:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector2> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+            default:
+            {
+              break;
+            }
           }
         }
-      }
-      else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() )
-      {
-        // Animate float component of Vector3 property
-
-        // Cast to AnimatableProperty of type Vector3
-        const SceneGraph::AnimatableProperty<Vector3>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector3>* >( baseProperty );
-
-        //Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
-        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
 
-        switch( mComponentIndex )
+        else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() )
         {
-          case 0:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector3> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 1:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector3> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 2:
+          // Animate float component of Vector3 property
+          // Cast to AnimatableProperty of type Vector3
+          const SceneGraph::AnimatableProperty<Vector3>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector3>* >( baseProperty );
+
+          if( animatableProperty == NULL )
           {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector3> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
+            if( baseProperty->IsTransformManagerProperty() )
+            {
+              if( mComponentIndex == 0 )
+              {
+                mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,0> >::New( *propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+              }
+              else if( mComponentIndex == 1 )
+              {
+                mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,1> >::New( *propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+              }
+              else if( mComponentIndex == 2 )
+              {
+                mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,2> >::New( *propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+              }
+            }
+            else
+            {
+              DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+            }
           }
-          default:
+          else
           {
-            break;
+            //Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
+            DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+
+            switch( mComponentIndex )
+            {
+              case 0:
+              {
+                mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector3> >::New( *propertyOwner,
+                                                                                                     *animatableProperty,
+                                                                                                     mAnimatorFunction,
+                                                                                                     mAlphaFunction,
+                                                                                                     mTimePeriod );
+                break;
+              }
+              case 1:
+              {
+                mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector3> >::New( *propertyOwner,
+                                                                                                     *animatableProperty,
+                                                                                                     mAnimatorFunction,
+                                                                                                     mAlphaFunction,
+                                                                                                     mTimePeriod );
+                break;
+              }
+              case 2:
+              {
+                mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector3> >::New( *propertyOwner,
+                                                                                                     *animatableProperty,
+                                                                                                     mAnimatorFunction,
+                                                                                                     mAlphaFunction,
+                                                                                                     mTimePeriod );
+                break;
+              }
+              default:
+              {
+                break;
+              }
+            }
           }
         }
-      }
-      else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() )
-      {
-        // Animate float component of Vector4 property
-
-        // Cast to AnimatableProperty of type Vector4
-        const SceneGraph::AnimatableProperty<Vector4>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector4>* >( baseProperty );
+        else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() )
+        {
+          // Animate float component of Vector4 property
 
-        //Dynamic cast will fail if BaseProperty is not a Vector4 AnimatableProperty
-        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+          // Cast to AnimatableProperty of type Vector4
+          const SceneGraph::AnimatableProperty<Vector4>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector4>* >( baseProperty );
 
-        switch( mComponentIndex )
-        {
-          case 0:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector4> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 1:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector4> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 2:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector4> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
-          case 3:
-          {
-            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorW<Vector4> >::New( *propertyOwner,
-                                                                                                 *animatableProperty,
-                                                                                                 mAnimatorFunction,
-                                                                                                 mAlphaFunction,
-                                                                                                 mTimePeriod );
-            break;
-          }
+          //Dynamic cast will fail if BaseProperty is not a Vector4 AnimatableProperty
+          DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
 
-          default:
+          switch( mComponentIndex )
           {
-            break;
+            case 0:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector4> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+            case 1:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector4> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+            case 2:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector4> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+            case 3:
+            {
+              mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorW<Vector4> >::New( *propertyOwner,
+                                                                                                   *animatableProperty,
+                                                                                                   mAnimatorFunction,
+                                                                                                   mAlphaFunction,
+                                                                                                   mTimePeriod );
+              break;
+            }
+
+            default:
+            {
+              break;
+            }
           }
         }
       }
index 45d17ab..cb671d6 100644 (file)
@@ -66,6 +66,7 @@ public:
   typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
   typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
   typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
+  typedef const SceneGraph::TransformManagerPropertyHandler<PropertyType> TransformManagerProperty;
 
   /**
    * Construct a new constraint.
@@ -169,18 +170,36 @@ private:
       // The targetProperty should exist, when targetObject exists
       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
 
-      // Connect the constraint
-      SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
-                                                                                     propertyOwners,
-                                                                                     func );
-      DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
-      sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+      if( targetProperty->IsTransformManagerProperty() )  //It is a property managed by the transform manager
+      {
+        // Connect the constraint
+        SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraph::Constraint<PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
+                                                                                      propertyOwners,
+                                                                                      func );
+        DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+        sceneGraphConstraint->SetRemoveAction( mRemoveAction );
 
-      // object is being used in a separate thread; queue a message to apply the constraint
-      ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+        // object is being used in a separate thread; queue a message to apply the constraint
+        ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
 
-      // Keep a raw-pointer to the scene-graph constraint
-      mSceneGraphConstraint = sceneGraphConstraint;
+        // Keep a raw-pointer to the scene-graph constraint
+        mSceneGraphConstraint = sceneGraphConstraint;
+      }
+      else  //SceneGraph property
+      {
+        // Connect the constraint
+        SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
+                                                                                      propertyOwners,
+                                                                                      func );
+        DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+        sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+        // object is being used in a separate thread; queue a message to apply the constraint
+        ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+        // Keep a raw-pointer to the scene-graph constraint
+        mSceneGraphConstraint = sceneGraphConstraint;
+      }
     }
   }
 
@@ -424,21 +443,41 @@ private:
         else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
         {
           // Constrain float component of Vector3 property
-
-          if ( 0 == componentIndex )
+          if( targetProperty->IsTransformManagerProperty() )
           {
-            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            if ( 0 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 1 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 2 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
           }
-          else if ( 1 == componentIndex )
+          else
           {
-            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
-          }
-          else if ( 2 == componentIndex )
-          {
-            typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            if ( 0 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 1 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 2 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
           }
         }
         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
index 970f18b..ff4604d 100644 (file)
@@ -307,6 +307,16 @@ public:
   }
 
   /**
+   * Query whether the property belongs to the
+   * transform manager or not.
+   * @return True if it is a transform manager property, false otherwise
+   */
+  virtual bool IsTransformManagerProperty() const
+  {
+    return false;
+  }
+
+  /**
    * Print the property value using a stream.
    * @param[in] debugStream The output stream.
    * @param[in] bufferIndex The buffer to read from.
index 9ba29c9..d459b62 100644 (file)
@@ -143,6 +143,7 @@ internal_src_files = \
   $(internal_src_dir)/update/touch/touch-resampler.cpp \
   $(internal_src_dir)/update/manager/prepare-render-instructions.cpp \
   $(internal_src_dir)/update/manager/process-render-tasks.cpp \
+  $(internal_src_dir)/update/manager/transform-manager.cpp \
   $(internal_src_dir)/update/manager/update-algorithms.cpp \
   $(internal_src_dir)/update/manager/update-manager.cpp \
   $(internal_src_dir)/update/manager/update-manager-debug.cpp \
index c31e084..abdfdd7 100644 (file)
@@ -138,7 +138,7 @@ inline void ProcessRenderList(
       //Enable depth writes if depth buffer is enabled and item is opaque
       context.DepthMask( depthBufferEnabled && ( item.IsOpaque() || item.GetRenderer().RequiresDepthTest() ) );
 
-      item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, !item.IsOpaque() );
+      item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() );
     }
   }
   else
@@ -149,7 +149,7 @@ inline void ProcessRenderList(
       const RenderItem& item = renderList.GetItem( index );
       DALI_PRINT_RENDER_ITEM( item );
 
-      item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, !item.IsOpaque() );
+      item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() );
     }
 
   }
index b25c9e5..85c6fb9 100644 (file)
@@ -136,6 +136,24 @@ public:
     return mIsOpaque;
   }
 
+  /**
+   * Sets the size of the render item
+   * @param[in] size The size of the render item
+   */
+  void SetSize( const Vector3& size)
+  {
+    mSize = size;
+  }
+
+  /**
+   * Retrives the size of the render item
+   * @return The size of the render item
+   */
+  const Vector3& GetSize() const
+  {
+    return mSize;
+  }
+
 private:
 
   /**
@@ -148,6 +166,7 @@ private:
   RenderItem& operator = ( const RenderItem& item );
 
   Matrix            mModelViewMatrix;
+  Vector3           mSize;
   Render::Renderer* mRenderer;
   Node*             mNode;
   int               mDepthIndex;
index ab4dfbf..0a40075 100644 (file)
@@ -55,12 +55,6 @@ public:
   virtual const Vector4& GetRenderColor( unsigned int bufferId ) const = 0;
 
   /**
-   * @param[in] bufferIndex The buffer index to use
-   * @return the actor size
-   */
-  virtual const Vector3& GetRenderSize( unsigned int bufferIndex ) const = 0;
-
-  /**
    * @copydoc Dali::Internal::SceneGraph::UniformMapDataProvider::GetUniformMapChanged()
    */
   virtual bool GetUniformMapChanged( BufferIndex bufferIndex ) const = 0;
index 99c7999..2a93574 100644 (file)
@@ -217,7 +217,7 @@ void Renderer::GlCleanup()
 {
 }
 
-void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, Program& program )
+void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
 {
   // Check if the map has changed
   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
@@ -278,7 +278,6 @@ void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataP
   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
   if( -1 != sizeLoc )
   {
-    Vector3 size = node.GetRenderSize( bufferIndex );
     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
   }
 }
@@ -440,6 +439,7 @@ void Renderer::Render( Context& context,
                        const Matrix& modelViewMatrix,
                        const Matrix& viewMatrix,
                        const Matrix& projectionMatrix,
+                       const Vector3& size,
                        bool blend )
 {
   // Get the program to use:
@@ -487,7 +487,7 @@ void Renderer::Render( Context& context,
       }
     }
 
-    SetUniforms( bufferIndex, node, *program );
+  SetUniforms( bufferIndex, node, size, *program );
 
     if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
     {
index 18ccc0c..2a86c5b 100644 (file)
@@ -185,6 +185,7 @@ public:
                const Matrix& modelViewMatrix,
                const Matrix& viewMatrix,
                const Matrix& projectionMatrix,
+               const Vector3& size,
                bool blend);
 
   /**
@@ -214,10 +215,12 @@ private:
 
   /**
    * Set the uniforms from properties according to the uniform map
+   * @param[in] bufferIndex The index of the previous update buffer.
    * @param[in] node The node using the renderer
+   * @param[in] size The size of the renderer
    * @param[in] program The shader program on which to set the uniforms.
    */
-  void SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, Program& program );
+  void SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program );
 
   /**
    * Set the program uniform in the map from the mapped property
index 7769f06..31364cd 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 #include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/manager/transform-manager-property.h>
 
 namespace Dali
 {
@@ -120,6 +121,191 @@ private:
   SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
 };
 
+
+
+/**
+ * A wrapper class for getting/setting a property.
+ * Animators use this instead of accessing properties directly.
+ */
+template <typename T>
+class TransformManagerPropertyAccessor
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property to access.
+   */
+  TransformManagerPropertyAccessor( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::TransformManagerPropertyHandler<T>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyAccessor is not suitable as a base class.
+   */
+  ~TransformManagerPropertyAccessor()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyAccessor is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   * @return The value of the property
+   */
+  const T& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, const T& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Set() mProperty was NULL" );
+    mProperty->Set( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, const T& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Bake() mProperty was NULL" );
+    mProperty->Bake( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  TransformManagerPropertyAccessor(const TransformManagerPropertyAccessor& property);
+
+  // Undefined
+  TransformManagerPropertyAccessor& operator=(const TransformManagerPropertyAccessor& rhs);
+
+private:
+
+  SceneGraph::TransformManagerPropertyHandler<T>* mProperty; ///< The real property
+};
+
+
+template <typename T, unsigned int COMPONENT>
+class TransformManagerPropertyComponentAccessor
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property to access.
+   */
+  TransformManagerPropertyComponentAccessor( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::TransformManagerPropertyHandler<T>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyAccessor is not suitable as a base class.
+   */
+  ~TransformManagerPropertyComponentAccessor()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyAccessor is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   * @return The value of the component of the property
+   */
+  const float& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Get() mProperty was NULL" );
+    return mProperty->GetFloatComponent( COMPONENT );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, const float& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Set() mProperty was NULL" );
+    mProperty->SetFloatComponent( value, COMPONENT );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, const float& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Bake() mProperty was NULL" );
+    mProperty->BakeFloatComponent( value, COMPONENT );
+  }
+
+private:
+
+  // Undefined
+  TransformManagerPropertyComponentAccessor(const TransformManagerPropertyComponentAccessor& property);
+
+  // Undefined
+  TransformManagerPropertyComponentAccessor& operator=(const TransformManagerPropertyComponentAccessor& rhs);
+
+private:
+
+  SceneGraph::TransformManagerPropertyHandler<T>* mProperty; ///< The real property
+};
+
 } // namespace Internal
 
 } // namespace Dali
index 486d2de..b3694b7 100644 (file)
@@ -31,6 +31,8 @@
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/math/quaternion.h>
 #include <dali/public-api/math/radian.h>
+#include <dali/internal/update/animation/property-accessor.h>
+
 
 namespace Dali
 {
@@ -411,10 +413,7 @@ public:
       mPropertyOwner->RemoveObserver(*this);
     }
 
-    if( mAnimatorFunction )
-    {
-      delete mAnimatorFunction;
-    }
+    delete mAnimatorFunction;
   }
 
   /**
@@ -456,8 +455,6 @@ public:
   virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
   {
     mPropertyOwner = NULL;
-    mPropertyAccessor.Reset();
-    mEnabled = false;
   }
 
   /**
@@ -522,6 +519,161 @@ protected:
   float mCurrentProgress;
 };
 
+
+
+/**
+ * An animator for a specific property type PropertyType.
+ */
+template <typename T, typename PropertyAccessorType>
+class AnimatorTransformProperty : public AnimatorBase, public PropertyOwner::Observer
+{
+public:
+
+  /**
+   * Construct a new property animator.
+   * @param[in] property The animatable property; only valid while the Animator is attached.
+   * @param[in] animatorFunction The function used to animate the property.
+   * @param[in] alphaFunction The alpha function to apply.
+   * @param[in] timePeriod The time period of this animation.
+   * @return A newly allocated animator.
+   */
+  static AnimatorBase* New( const PropertyOwner& propertyOwner,
+                            const PropertyBase& property,
+                            AnimatorFunctionBase* animatorFunction,
+                            AlphaFunction alphaFunction,
+                            const TimePeriod& timePeriod )
+  {
+
+    // The property was const in the actor-thread, but animators are used in the scene-graph thread.
+    AnimatorTransformProperty* animator = new AnimatorTransformProperty( const_cast<PropertyOwner*>( &propertyOwner ),
+                                               const_cast<PropertyBase*>( &property ),
+                                               animatorFunction );
+
+    animator->SetAlphaFunction( alphaFunction );
+    animator->SetInitialDelay( timePeriod.delaySeconds );
+    animator->SetDuration( timePeriod.durationSeconds );
+
+    return animator;
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatorTransformProperty()
+  {
+    if (mPropertyOwner && mConnectedToSceneGraph)
+    {
+      mPropertyOwner->RemoveObserver(*this);
+    }
+
+    delete mAnimatorFunction;
+  }
+
+  /**
+   * Called when Animator is added to the scene-graph in update-thread.
+   */
+  virtual void ConnectToSceneGraph()
+  {
+    mConnectedToSceneGraph = true;
+    mPropertyOwner->AddObserver(*this);
+  }
+
+  /**
+   * Called when mPropertyOwner is connected to the scene graph.
+   */
+  virtual void PropertyOwnerConnected( PropertyOwner& owner )
+  {
+    mEnabled = true;
+  }
+
+  /**
+   * Called when mPropertyOwner is disconnected from the scene graph.
+   */
+  virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
+  {
+    // If we are active, then bake the value if required
+    if ( mActive && mDisconnectAction != Dali::Animation::Discard )
+    {
+      // Bake to target-value if BakeFinal, otherwise bake current value
+      Update( bufferIndex, ( mDisconnectAction == Dali::Animation::Bake ? mCurrentProgress : 1.0f ), true );
+    }
+
+    mActive = false;
+    mEnabled = false;
+  }
+
+  /**
+   * Called shortly before mPropertyOwner is destroyed
+   */
+  virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
+  {
+    mPropertyOwner = NULL;
+  }
+
+  /**
+   * From AnimatorBase.
+   */
+  virtual void Update( BufferIndex bufferIndex, float progress, bool bake )
+  {
+    float alpha = ApplyAlphaFunction(progress);
+
+    const T& current = mPropertyAccessor.Get( bufferIndex );
+
+    const T result = (*mAnimatorFunction)( alpha, current );
+
+
+    if ( bake )
+    {
+      mPropertyAccessor.Bake( bufferIndex, result );
+    }
+    else
+    {
+      mPropertyAccessor.Set( bufferIndex, result );
+    }
+
+    mCurrentProgress = progress;
+  }
+
+  /**
+   * From AnimatorBase.
+   */
+  virtual bool Orphan()
+  {
+    return (mPropertyOwner == NULL);
+  }
+
+private:
+
+  /**
+   * Private constructor; see also Animator::New().
+   */
+  AnimatorTransformProperty( PropertyOwner* propertyOwner,
+            PropertyBase* property,
+            AnimatorFunctionBase* animatorFunction )
+  : mPropertyOwner( propertyOwner ),
+    mPropertyAccessor( property ),
+    mAnimatorFunction( animatorFunction ),
+    mCurrentProgress( 0.0f )
+  {
+    // WARNING - this object is created in the event-thread
+    // The scene-graph mPropertyOwner object cannot be observed here
+  }
+
+  // Undefined
+  AnimatorTransformProperty( const AnimatorTransformProperty& );
+
+  // Undefined
+  AnimatorTransformProperty& operator=( const AnimatorTransformProperty& );
+
+protected:
+
+  PropertyOwner* mPropertyOwner;
+  PropertyAccessorType mPropertyAccessor;
+
+  AnimatorFunctionBase* mAnimatorFunction;
+  float mCurrentProgress;
+};
+
 } // namespace SceneGraph
 
 /*
@@ -1022,7 +1174,6 @@ struct PathRotationFunctor : public AnimatorFunctionBase
   Vector3 mForward;
 };
 
-
 } // namespace Internal
 
 } // namespace Dali
diff --git a/dali/internal/update/manager/free-list.h b/dali/internal/update/manager/free-list.h
new file mode 100644 (file)
index 0000000..f195955
--- /dev/null
@@ -0,0 +1,121 @@
+
+#ifndef FREE_LIST_H_
+#define FREE_LIST_H_
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * FreeList operates by connecting unused elements of a vector together in a linked list using the
+ * value of each unused cell as a pointer to the next. When a new element is added, it will be added
+ * to the first free index of the vector and the new free index will be the value which was on that
+ * cell
+ */
+struct FreeList
+{
+  /**
+   * Constructor
+   */
+  FreeList()
+  :mData(),
+   mFirstFreeIndex(0)
+  {}
+
+  /**
+   * Destructor
+   */
+  ~FreeList()
+  {}
+
+  /**
+   * Adds a new item to the list. If there is no more space in the vector it will
+   * allocate more space, otherwise, it will use the first free cell to store the
+   * new value and will update the first free index.
+   *
+   * @param[in] value The value to add
+   * @return The index where the value has been added
+   */
+  unsigned int Add( unsigned int value )
+  {
+    if( mData.Empty() || mFirstFreeIndex == mData.Size() )
+    {
+      //Make room for another item
+      size_t size = mData.Size();
+      mData.PushBack( size+1 );
+      mFirstFreeIndex = size;
+    }
+
+    //Update first free index
+    unsigned int index = mFirstFreeIndex;
+    mFirstFreeIndex = mData[mFirstFreeIndex];
+
+    mData[index] = value;
+    return index;
+  }
+
+  /**
+   * Removes the item at position "index" from the list and
+   * updates the first free index
+   *
+   * @param[in] index The index of the element to remove
+   */
+  void Remove( unsigned int index )
+  {
+    mData[index] = mFirstFreeIndex;
+    mFirstFreeIndex = index;
+  }
+
+  /**
+   * Subscript operator.
+   *
+   * @param[in]  index Index of the element.
+   * @return Reference to the element for given index.
+   */
+  unsigned int& operator[]( unsigned int index )
+  {
+    return mData[index];
+  }
+
+  /**
+   * Subscript operator (const).
+   *
+   * @param[in]  index Index of the element.
+   * @return Reference to the element for given index.
+   */
+  unsigned int operator[]( unsigned int index ) const
+  {
+    return mData[index];
+  }
+
+private:
+  Dali::Vector<unsigned int> mData; ///< data
+  unsigned int mFirstFreeIndex;     ///< Index where a new element will be added
+};
+
+}
+}
+
+#endif /* FREE_LIST_H_ */
index 8a6a594..72ec1ac 100644 (file)
@@ -73,31 +73,14 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
   bool inside( true );
 
   const Matrix& worldMatrix = renderable.mNode->GetWorldMatrix( updateBufferIndex );
+  const Vector3& size = renderable.mNode->GetSize( updateBufferIndex );
   if ( cull && renderable.mRenderer->GetMaterial().GetShader()->GeometryHintEnabled( Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) )
   {
-    const Vector3& scale = renderable.mNode->GetWorldScale( updateBufferIndex );
-    const Vector3& halfSize = renderable.mNode->GetSize( updateBufferIndex ) * scale * 0.5f;
-    float radius( halfSize.Length() );
+    const Vector3& position = worldMatrix.GetTranslation3();
+    float radius( size.Length() * 0.5f );
 
-    if( radius > Math::MACHINE_EPSILON_1000 )
-    {
-      const Vector3& position = worldMatrix.GetTranslation3();
-      const Quaternion& rotation = renderable.mNode->GetWorldOrientation( updateBufferIndex );
-      bool axisAligned = rotation.IsIdentity();
-
-      if( axisAligned )
-      {
-        inside = cameraAttachment.CheckAABBInFrustum( updateBufferIndex, position, halfSize );
-      }
-      else
-      {
-        inside = cameraAttachment.CheckSphereInFrustum( updateBufferIndex, position, halfSize.Length() );
-      }
-    }
-    else
-    {
-      inside = false;
-    }
+    inside = (radius > Math::MACHINE_EPSILON_1000) &&
+        (cameraAttachment.CheckSphereInFrustum( updateBufferIndex, position, radius ) );
   }
 
   if ( inside )
@@ -121,6 +104,7 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
       }
       // save MV matrix onto the item
       Matrix::Multiply( item.GetModelViewMatrix(), worldMatrix, viewMatrix );
+      item.SetSize( size );
     }
   }
 }
diff --git a/dali/internal/update/manager/transform-manager-property.h b/dali/internal/update/manager/transform-manager-property.h
new file mode 100644 (file)
index 0000000..56f24cf
--- /dev/null
@@ -0,0 +1,744 @@
+#ifndef TRANSFORM_MANAGER_PROPERTY_H_
+#define TRANSFORM_MANAGER_PROPERTY_H_
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/update/manager/transform-manager.h>
+#include <dali/internal/update/common/animatable-property.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+template <typename T>
+struct TransformManagerPropertyHandler : public AnimatablePropertyBase
+{
+  /**
+   * Constructor
+   */
+  TransformManagerPropertyHandler()
+  :mTxManager(0),
+   mId( INVALID_TRANSFORM_ID )
+  {}
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const = 0;
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  virtual T& Get(size_t bufferIndex) = 0;
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  virtual const T& Get(size_t bufferIndex) const = 0;
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const{ return Vector3::ZERO; }
+
+  /**
+   * Retrieve a component of property
+   * @param[in] component The component of the property
+   */
+  virtual const float& GetFloatComponent(unsigned int component)=0;
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex Not used
+   * @param[in] value The new property value.
+   */
+  virtual void Set(BufferIndex bufferIndex, const T& value) = 0;
+
+  /**
+   * Change a component of property
+   * @param[in] value The new value of the component
+   * @param[in] component The component of the property
+   */
+  virtual void SetFloatComponent( float value, unsigned int component){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::Bake()
+   */
+  virtual void Bake(BufferIndex bufferIndex, const T& value) = 0;
+
+  /**
+   * Bake a component of a property
+   * @param[in] value The new value of the component
+   * @param[in] component The component of the property
+   */
+  virtual void BakeFloatComponent( float value, unsigned int component){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::BakeX()
+   */
+  virtual void BakeX(BufferIndex bufferIndex, float value){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::BakeY()
+   */
+  virtual void BakeY(BufferIndex bufferIndex, float value){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::BakeZ()
+   */
+  virtual void BakeZ(BufferIndex bufferIndex, float value){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::BakeRelative()
+   */
+  virtual void BakeRelative(BufferIndex bufferIndex, const T& value) = 0;
+
+  /**
+   * @copydoc Dali::AnimatableProperty::BakeRelativeMultiply()
+   */
+  virtual void BakeRelativeMultiply(BufferIndex bufferIndex, const T& value){};
+
+  /**
+   * @copydoc Dali::AnimatableProperty::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex){}
+
+  /**
+   * @copydoc Dali::AnimatableProperty::IsClean()
+   */
+  virtual bool IsClean() const{ return false; }
+
+  /**
+   * Initializes the property
+   * @param[in] transformManager Pointer to the transform manager
+   * @param[in] Id of the transformation the property is associated with
+   */
+  void Initialize( TransformManager* transformManager, TransformId id )
+  {
+    mTxManager = transformManager;
+    mId = id;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::IsTransformManagerProperty()
+   */
+  virtual bool IsTransformManagerProperty() const
+  {
+    return true;
+  }
+
+  TransformManager* mTxManager;
+  TransformId mId;
+};
+
+struct TransformManagerPropertyVector3 : public TransformManagerPropertyHandler<Vector3>
+{
+
+  TransformManagerPropertyVector3(TransformManagerProperty property)
+  :TransformManagerPropertyHandler(),
+   mProperty( property )
+  {}
+
+  Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  Vector3& Get(size_t bufferIndex)
+  {
+    return mTxManager->GetVector3PropertyValue( mId, mProperty );
+  }
+
+  const Vector3& Get(size_t bufferIndex) const
+  {
+    return mTxManager->GetVector3PropertyValue( mId, mProperty );
+  }
+
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return Get(bufferIndex);
+  }
+
+  const float& GetFloatComponent( unsigned int component )
+  {
+    return mTxManager->GetVector3PropertyComponentValue( mId, mProperty, component );
+  }
+
+  void Set(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mTxManager->SetVector3PropertyValue( mId, mProperty, value );
+  }
+
+  void SetComponent(BufferIndex bufferIndex, float value, unsigned int component)
+  {
+    mTxManager->SetVector3PropertyComponentValue( mId, mProperty, value, component);
+  }
+
+  void BakeComponent(BufferIndex bufferIndex, float value, unsigned int component)
+  {
+    mTxManager->BakeVector3PropertyComponentValue( mId, mProperty, value, component);
+  }
+
+  void Bake(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mTxManager->BakeVector3PropertyValue(mId, mProperty, value );
+  }
+
+  void BakeX(BufferIndex bufferIndex, float value)
+  {
+    mTxManager->BakeXVector3PropertyValue(mId, mProperty, value );
+  }
+
+  void BakeY(BufferIndex bufferIndex, float value)
+  {
+    mTxManager->BakeYVector3PropertyValue(mId, mProperty, value );
+  }
+
+  void BakeZ(BufferIndex bufferIndex, float value)
+  {
+    mTxManager->BakeZVector3PropertyValue(mId, mProperty, value );
+  }
+
+  void SetFloatComponent( float value, unsigned int component)
+  {
+    mTxManager->SetVector3PropertyComponentValue( mId, mProperty, value, component);
+  }
+
+  void BakeFloatComponent( float value, unsigned int component )
+  {
+    mTxManager->BakeVector3PropertyComponentValue( mId, mProperty, value, component);
+  }
+
+  void BakeRelative(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mTxManager->BakeRelativeVector3PropertyValue(mId, mProperty, value );
+  }
+
+  void BakeRelativeMultiply(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mTxManager->BakeMultiplyVector3PropertyValue(mId, mProperty, value );
+  }
+
+  TransformManagerProperty mProperty;
+};
+
+class TransformManagerPropertyQuaternion : public TransformManagerPropertyHandler<Quaternion>
+{
+public:
+
+  TransformManagerPropertyQuaternion()
+  :TransformManagerPropertyHandler()
+  {}
+
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Quaternion>();
+  }
+
+  Quaternion& Get(size_t bufferIndex)
+  {
+    return mTxManager->GetQuaternionPropertyValue( mId );
+  }
+
+  const Quaternion& Get(size_t bufferIndex) const
+  {
+    return mTxManager->GetQuaternionPropertyValue( mId );
+  }
+
+  const float& GetFloatComponent( unsigned int component)
+  {
+    return mTxManager->GetQuaternionPropertyValue( mId ).mVector[component];
+  }
+
+  void Set(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    return mTxManager->SetQuaternionPropertyValue( mId, value );
+  }
+
+  void Bake(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    return mTxManager->BakeQuaternionPropertyValue( mId, value );
+  }
+
+  void BakeRelative(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    return mTxManager->BakeRelativeQuaternionPropertyValue( mId, value );
+  }
+};
+
+/**
+ * A Vector3 property used as input.
+ */
+class TransformManagerVector3Input : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an TransformManagerVector3Input
+   */
+  TransformManagerVector3Input( TransformManagerProperty property, const Vector3& initialValue )
+  :mTxManager(0),
+   mId(INVALID_TRANSFORM_ID),
+   mProperty(property),
+   mValue(initialValue)
+  {}
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~TransformManagerVector3Input()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return true;
+  }
+
+  /**
+   * Helper function to get the transform components out of the world matrix.
+   * It stores the value in the mValue member variable
+   */
+  void ComputeTransformComponent() const
+  {
+    if( mTxManager )
+    {
+      const Matrix& worldMatrix = mTxManager->GetWorldMatrix(mId);
+
+      if( mProperty == TRANSFORM_PROPERTY_WORLD_POSITION )
+      {
+        mValue = worldMatrix.GetTranslation3();
+      }
+      else if( mProperty == TRANSFORM_PROPERTY_WORLD_SCALE )
+      {
+        Vector3 position;
+        Quaternion orientation;
+        worldMatrix.GetTransformComponents(position, orientation, mValue);
+      }
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputVector3()
+   */
+  virtual const Vector3& GetConstraintInputVector3( BufferIndex bufferIndex ) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Vector3& Get(size_t bufferIndex)
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Vector3& Get(size_t bufferIndex) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector3& operator[](size_t bufferIndex) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * Initializes the property
+   * @param[in] transformManager Pointer to the transform manager
+   * @param[in] Id of the transformation the property is associated with
+   */
+  void Initialize( TransformManager* transformManager, TransformId id )
+  {
+    mTxManager = transformManager;
+    mId = id;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::IsTransformManagerProperty()
+   */
+  virtual bool IsTransformManagerProperty() const
+  {
+    return true;
+  }
+
+private:
+
+  // Undefined
+  TransformManagerVector3Input(const TransformManagerVector3Input& property);
+
+  // Undefined
+  TransformManagerVector3Input& operator=(const TransformManagerVector3Input& rhs);
+
+public:
+
+  TransformManager* mTxManager;
+  TransformId mId;
+  TransformManagerProperty mProperty;
+  mutable Vector3 mValue;
+};
+
+/**
+ * A Quaternion property used as input.
+ */
+class TransformManagerQuaternionInput : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Constructor
+   */
+  TransformManagerQuaternionInput()
+  :mTxManager(0),
+   mId(INVALID_TRANSFORM_ID),
+   mValue(1.0f,0.0f,0.0f,0.0f)
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~TransformManagerQuaternionInput()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Quaternion>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return true;
+  }
+
+  /**
+   * Helper function to get the orientation out of the world matrix.
+   * It stores the result in the mValue member variable
+   */
+  void ComputeTransformComponent() const
+  {
+    if( mTxManager )
+    {
+      const Matrix& worldMatrix = mTxManager->GetWorldMatrix(mId);
+      Vector3 position, scale;
+      worldMatrix.GetTransformComponents(position, mValue, scale);
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputQuaternion()
+   */
+  virtual const Quaternion& GetConstraintInputQuaternion( BufferIndex bufferIndex ) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Quaternion& Get(size_t bufferIndex)
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Quaternion& Get(size_t bufferIndex) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Quaternion& operator[](size_t bufferIndex) const
+  {
+    ComputeTransformComponent();
+    return mValue;
+  }
+
+  /**
+   * Initializes the property
+   * @param[in] transformManager Pointer to the transform manager
+   * @param[in] Id of the transformation the property is associated with
+   */
+  void Initialize( TransformManager* transformManager, TransformId id )
+  {
+    mTxManager = transformManager;
+    mId = id;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::IsTransformManagerProperty()
+   */
+  virtual bool IsTransformManagerProperty() const
+  {
+    return true;
+  }
+
+private:
+
+  // Undefined
+  TransformManagerQuaternionInput(const TransformManagerQuaternionInput& property);
+
+  // Undefined
+  TransformManagerQuaternionInput& operator=(const TransformManagerQuaternionInput& rhs);
+
+public:
+
+  TransformManager* mTxManager;
+  TransformId mId;
+  mutable Quaternion mValue;
+};
+
+/**
+ * A Matrix property used as input.
+ */
+class TransformManagerMatrixInput : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Constructor
+   */
+  TransformManagerMatrixInput()
+  :mTxManager(0),
+   mId(INVALID_TRANSFORM_ID)
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~TransformManagerMatrixInput()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetMatrix()
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    if( mTxManager )
+    {
+      return mTxManager->GetWorldMatrix(mId);
+    }
+
+    return Matrix::IDENTITY;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputMatrix()
+   */
+  virtual const Matrix& GetConstraintInputMatrix( BufferIndex bufferIndex ) const
+  {
+    if( mTxManager )
+    {
+      return mTxManager->GetWorldMatrix(mId);
+    }
+
+    return Matrix::IDENTITY;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Matrix& Get(size_t bufferIndex)
+  {
+    DALI_ASSERT_ALWAYS( mTxManager != 0 );
+    return mTxManager->GetWorldMatrix(mId);
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Matrix& Get(size_t bufferIndex) const
+  {
+    return GetMatrix(bufferIndex);
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix& operator[](size_t bufferIndex) const
+  {
+    return GetMatrix(bufferIndex);
+  }
+
+  void Initialize( TransformManager* transformManager, TransformId id )
+  {
+    mTxManager = transformManager;
+    mId = id;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::IsTransformManagerProperty()
+   */
+  virtual bool IsTransformManagerProperty() const
+  {
+    return true;
+  }
+
+private:
+
+  // Undefined
+  TransformManagerMatrixInput(const TransformManagerMatrixInput& property);
+
+  // Undefined
+  TransformManagerMatrixInput& operator=(const TransformManagerMatrixInput& rhs);
+
+public:
+
+  TransformManager* mTxManager;
+  TransformId mId;
+};
+
+
+} //namespace SceneGraph
+} //namespace Internal
+} //namespace Dali
+
+#endif // TRANSFORM_MANAGER_PROPERTY_H_
diff --git a/dali/internal/update/manager/transform-manager.cpp b/dali/internal/update/manager/transform-manager.cpp
new file mode 100644 (file)
index 0000000..4d76f33
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/transform-manager.h>
+
+//EXTERNAL INCLUDES
+#include <algorithm>
+#include <cstring>
+
+//INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/compile-time-assert.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+//Default values for scale (1.0,1.0,1.0), orientation (Identity) and position (0.0,0.0,0.0)
+static const float gDefaultTransformComponentAnimatableData[] = { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
+
+//Default values for anchor point (CENTER) and parent origin (TOP_LEFT)
+static const float gDefaultTransformComponentStaticData[] = { 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f };
+
+DALI_COMPILE_TIME_ASSERT( sizeof(gDefaultTransformComponentAnimatableData) == sizeof(TransformComponentAnimatable) );
+DALI_COMPILE_TIME_ASSERT( sizeof(gDefaultTransformComponentStaticData) == sizeof(TransformComponentStatic) );
+}
+
+TransformManager::TransformManager()
+:mComponentCount(0),
+ mReorder(false)
+{}
+
+TransformManager::~TransformManager()
+{}
+
+TransformId TransformManager::CreateTransform()
+{
+  //Get id for the new component
+  TransformId id = mIds.Add(mComponentCount);
+
+  if( mTxComponentAnimatable.Size() <= mComponentCount )
+  {
+    //Make room for another component
+    mTxComponentAnimatable.PushBack(TransformComponentAnimatable());
+    mTxComponentStatic.PushBack(TransformComponentStatic());
+    mInheritanceMode.PushBack(INHERIT_ALL);
+    mComponentId.PushBack(id);
+    mSize.PushBack(Vector3(0.0f,0.0f,0.0f));
+    mParent.PushBack(INVALID_TRANSFORM_ID);
+    mWorld.PushBack(Matrix::IDENTITY);
+    mLocal.PushBack(Matrix::IDENTITY);
+    mTxComponentAnimatableBaseValue.PushBack(TransformComponentAnimatable());
+    mSizeBase.PushBack(Vector3(0.0f,0.0f,0.0f));
+    mComponentDirty.PushBack(false);
+    mLocalMatrixDirty.PushBack(false);
+  }
+  else
+  {
+    //Set default values
+    memcpy( &mTxComponentAnimatable[mComponentCount], &gDefaultTransformComponentAnimatableData, sizeof( TransformComponentAnimatable ) );
+    memcpy( &mTxComponentStatic[mComponentCount], &gDefaultTransformComponentStaticData, sizeof( TransformComponentStatic ) );
+    memcpy( &mTxComponentAnimatableBaseValue[mComponentCount], &gDefaultTransformComponentAnimatableData, sizeof( TransformComponentAnimatable ) );
+    mInheritanceMode[mComponentCount] = INHERIT_ALL;
+    mComponentId[mComponentCount] = id;
+    mSize[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
+    mParent[mComponentCount] = INVALID_TRANSFORM_ID;
+    mLocal[mComponentCount].SetIdentity();
+    mWorld[mComponentCount].SetIdentity();
+    mSizeBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
+    mComponentDirty[mComponentCount] = false;
+    mLocalMatrixDirty[mComponentCount] = false;
+  }
+
+  mComponentCount++;
+  return id;
+}
+
+void TransformManager::RemoveTransform(TransformId id)
+{
+  //Move the last element to the gap
+  mComponentCount--;
+  unsigned int index = mIds[id];
+  mTxComponentAnimatable[index] = mTxComponentAnimatable[mComponentCount];
+  mTxComponentStatic[index] = mTxComponentStatic[mComponentCount];
+  mInheritanceMode[index] = mInheritanceMode[mComponentCount];
+  mSize[index] = mSize[mComponentCount];
+  mParent[index] = mParent[mComponentCount];
+  mWorld[index] = mWorld[mComponentCount];
+  mLocal[index] = mLocal[mComponentCount];
+  mTxComponentAnimatableBaseValue[index] = mTxComponentAnimatableBaseValue[mComponentCount];
+  mSizeBase[index] = mSizeBase[mComponentCount];
+  mComponentDirty[index] = mComponentDirty[mComponentCount];
+  mLocalMatrixDirty[index] = mLocalMatrixDirty[mComponentCount];
+
+  TransformId lastItemId = mComponentId[mComponentCount];
+  mIds[ lastItemId ] = index;
+  mComponentId[index] = lastItemId;
+  mIds.Remove( id );
+
+  mReorder = true;
+}
+
+void TransformManager::SetParent( TransformId id, TransformId parentId )
+{
+  DALI_ASSERT_ALWAYS( id != parentId );
+  mParent[ mIds[id] ] = parentId;
+  mReorder = true;
+}
+
+const Matrix& TransformManager::GetWorldMatrix( TransformId id ) const
+{
+  return mWorld[ mIds[id] ];
+}
+
+Matrix& TransformManager::GetWorldMatrix( TransformId id )
+{
+  return mWorld[ mIds[id] ];
+}
+
+void TransformManager::SetInheritPosition( TransformId id, bool inherit )
+{
+  unsigned int index = mIds[id];
+  if( inherit )
+  {
+    mInheritanceMode[ index ] |= INHERIT_POSITION;
+  }
+  else
+  {
+    mInheritanceMode[ index ] &= ~INHERIT_POSITION;
+  }
+
+  mComponentDirty[index] = true;
+}
+
+void TransformManager::SetInheritScale( TransformId id, bool inherit )
+{
+  unsigned int index = mIds[id];
+  if( inherit )
+  {
+    mInheritanceMode[ index ] |= INHERIT_SCALE;
+  }
+  else
+  {
+    mInheritanceMode[ index ] &= ~INHERIT_SCALE;
+  }
+
+  mComponentDirty[index] = true;
+}
+
+void TransformManager::SetInheritOrientation( TransformId id, bool inherit )
+{
+  unsigned int index = mIds[id];
+  if( inherit )
+  {
+    mInheritanceMode[ index ] |= INHERIT_ORIENTATION;
+  }
+  else
+  {
+    mInheritanceMode[ index ] &= ~INHERIT_ORIENTATION;
+  }
+
+  mComponentDirty[index] = true;
+}
+
+void TransformManager::ResetToBaseValue()
+{
+  if( mComponentCount )
+  {
+    memcpy( &mTxComponentAnimatable[0], &mTxComponentAnimatableBaseValue[0], sizeof(TransformComponentAnimatable)*mComponentCount );
+    memcpy( &mSize[0], &mSizeBase[0], sizeof(Vector3)*mComponentCount );
+    memset( &mLocalMatrixDirty[0], false, sizeof(bool)*mComponentCount );
+  }
+}
+
+void TransformManager::Update()
+{
+  if( mReorder )
+  {
+    //If some transform component has change its parent or has been removed since last update
+    //we need to reorder the vectors
+    ReorderComponents();
+    mReorder = false;
+  }
+
+  //Iterate through all components to compute its world matrix
+  Vector3 anchorPosition;
+  Vector3 localPosition;
+  Vector3 half( 0.5f,0.5f,0.5f );
+  for( unsigned int i(0); i<mComponentCount; ++i )
+  {
+    if( DALI_LIKELY( mInheritanceMode[i] != DONT_INHERIT_TRANSFORM && mParent[i] != INVALID_TRANSFORM_ID ) )
+    {
+      const unsigned int& parentIndex = mIds[mParent[i] ];
+      if( DALI_LIKELY( mInheritanceMode[i] == INHERIT_ALL ) )
+      {
+        if( mComponentDirty[i] || mLocalMatrixDirty[parentIndex])
+        {
+          //Full transform inherited
+          mComponentDirty[i] = false;
+          mLocalMatrixDirty[i] = true;
+
+          anchorPosition = ( half - mTxComponentStatic[i].mAnchorPoint ) * mSize[i] * mTxComponentAnimatable[i].mScale;
+          anchorPosition *= mTxComponentAnimatable[i].mOrientation;
+          localPosition = mTxComponentAnimatable[i].mPosition + anchorPosition + ( mTxComponentStatic[i].mParentOrigin - half ) *  mSize[parentIndex];
+          mLocal[i].SetTransformComponents( mTxComponentAnimatable[i].mScale,mTxComponentAnimatable[i].mOrientation, localPosition );
+        }
+
+        Matrix::Multiply( mWorld[i], mLocal[i], mWorld[parentIndex]);
+      }
+      else
+      {
+        //Some components are not inherited
+        Vector3 parentPosition, parentScale;
+        Quaternion parentOrientation;
+        const Matrix& parentMatrix = mWorld[parentIndex];
+        parentMatrix.GetTransformComponents( parentPosition, parentOrientation, parentScale );
+
+        Vector3 localScale = mTxComponentAnimatable[i].mScale;
+        if( (mInheritanceMode[i] & INHERIT_SCALE) == 0 )
+        {
+          //Don't inherit scale
+          localScale /= parentScale;
+        }
+
+        Quaternion localOrientation( mTxComponentAnimatable[i].mOrientation );
+        if( (mInheritanceMode[i] & INHERIT_ORIENTATION) == 0 )
+        {
+          //Don't inherit orientation
+          parentOrientation.Invert();
+          localOrientation = parentOrientation * mTxComponentAnimatable[i].mOrientation;
+        }
+
+        if( (mInheritanceMode[i] & INHERIT_POSITION) == 0 )
+        {
+          //Don't inherit position
+          mLocal[i].SetTransformComponents( localScale, localOrientation, Vector3::ZERO );
+          Matrix::Multiply( mWorld[i], mLocal[i], parentMatrix );
+          mWorld[i].SetTranslation( mTxComponentAnimatable[i].mPosition);
+        }
+        else
+        {
+          anchorPosition = ( half - mTxComponentStatic[i].mAnchorPoint ) * mSize[i] * mTxComponentAnimatable[i].mScale;
+          anchorPosition *= mTxComponentAnimatable[i].mOrientation;
+          localPosition = mTxComponentAnimatable[i].mPosition + anchorPosition + ( mTxComponentStatic[i].mParentOrigin - half ) *  mSize[parentIndex];
+          mLocal[i].SetTransformComponents( localScale, localOrientation, localPosition );
+          Matrix::Multiply( mWorld[i], mLocal[i], parentMatrix );
+        }
+      }
+    }
+    else  //Component has no parent or doesn't inherit transform
+    {
+      anchorPosition = ( half - mTxComponentStatic[i].mAnchorPoint ) * mSize[i] * mTxComponentAnimatable[i].mScale;
+      anchorPosition *= mTxComponentAnimatable[i].mOrientation;
+      localPosition = mTxComponentAnimatable[i].mPosition + anchorPosition;
+      mWorld[i].SetTransformComponents( mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition );
+    }
+  }
+}
+
+void TransformManager::SwapComponents( unsigned int i, unsigned int j )
+{
+  std::swap( mTxComponentAnimatable[i], mTxComponentAnimatable[j] );
+  std::swap( mTxComponentStatic[i], mTxComponentStatic[j] );
+  std::swap( mInheritanceMode[i], mInheritanceMode[j] );
+  std::swap( mSize[i], mSize[j] );
+  std::swap( mParent[i], mParent[j] );
+  std::swap( mComponentId[i], mComponentId[j] );
+  std::swap( mTxComponentAnimatableBaseValue[i], mTxComponentAnimatableBaseValue[j] );
+  std::swap( mSizeBase[i], mSizeBase[j] );
+  std::swap( mLocal[i], mLocal[j] );
+  std::swap( mComponentDirty[i], mComponentDirty[j] );
+
+  mIds[ mComponentId[i] ] = i;
+  mIds[ mComponentId[j] ] = j;
+}
+
+void TransformManager::ReorderComponents()
+{
+  mOrderedComponents.Resize(mComponentCount);
+
+  TransformId parentId;
+  for( size_t i(0); i<mComponentCount; ++i )
+  {
+    mOrderedComponents[i].id = mComponentId[i];
+    mOrderedComponents[i].level = 0u;
+
+    parentId = mParent[i];
+    while( parentId != INVALID_TRANSFORM_ID )
+    {
+      mOrderedComponents[i].level++;
+      parentId = mParent[ mIds[parentId] ];
+    }
+  }
+
+  std::sort( mOrderedComponents.Begin(), mOrderedComponents.End());
+  for( size_t i(0); i<mComponentCount-1; ++i )
+  {
+    SwapComponents( mIds[mOrderedComponents[i].id], i);
+  }
+}
+
+Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformManagerProperty property )
+{
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      unsigned int index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mTxComponentAnimatable[ index ].mPosition;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      unsigned int index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mTxComponentAnimatable[ index ].mScale;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      unsigned int index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mTxComponentStatic[ index ].mParentOrigin;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      unsigned int index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mTxComponentStatic[ index ].mAnchorPoint;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      unsigned int index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mSize[ index ];
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+      return mTxComponentAnimatable[ mIds[id] ].mPosition;
+    }
+  }
+}
+
+const Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformManagerProperty property ) const
+{
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      return mTxComponentAnimatable[ mIds[id] ].mPosition;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      return mTxComponentAnimatable[ mIds[id] ].mScale;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      return mTxComponentStatic[ mIds[id] ].mParentOrigin;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      return mTxComponentStatic[ mIds[id] ].mAnchorPoint;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      return mSize[ mIds[id] ];
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+      return mTxComponentAnimatable[ mIds[id] ].mPosition;
+    }
+  }
+}
+
+const float& TransformManager::GetVector3PropertyComponentValue(TransformId id, TransformManagerProperty property, unsigned int component ) const
+{
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      return mTxComponentAnimatable[ mIds[id] ].mPosition[component];
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      return mTxComponentAnimatable[ mIds[id] ].mScale[component];
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      return mTxComponentStatic[ mIds[id] ].mParentOrigin[component];
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      return mTxComponentStatic[ mIds[id] ].mAnchorPoint[component];
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      return mSize[ mIds[id] ][component];
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+      return mTxComponentAnimatable[ mIds[id] ].mPosition[component];
+    }
+  }
+}
+
+void TransformManager::SetVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ] = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::SetVector3PropertyComponentValue( TransformId id, TransformManagerProperty property, float value, unsigned int component )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ][component] = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale = mTxComponentAnimatableBaseValue[index].mScale = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ] = mSizeBase[index] = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeRelativeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = mTxComponentAnimatable[ index ].mPosition + value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale = mTxComponentAnimatableBaseValue[index].mScale = mTxComponentAnimatable[ index ].mScale + value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin = mTxComponentStatic[ index ].mParentOrigin + value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint = mTxComponentStatic[ index ].mAnchorPoint + value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ] = mSizeBase[index] = mSize[ index ] + value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeMultiplyVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition = mTxComponentAnimatableBaseValue[index].mPosition = mTxComponentAnimatable[ index ].mPosition * value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale = mTxComponentAnimatableBaseValue[index].mScale = mTxComponentAnimatable[ index ].mScale * value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin = mTxComponentStatic[ index ].mParentOrigin * value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint = mTxComponentStatic[ index ].mAnchorPoint * value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ] = mSizeBase[index] = mSize[ index ] * value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeVector3PropertyComponentValue( TransformId id, TransformManagerProperty property, float value, unsigned int component )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition[component] = mTxComponentAnimatableBaseValue[index].mPosition[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale[component] = mTxComponentAnimatableBaseValue[index].mScale[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint[component] = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ][component] = mSizeBase[index][component] = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeXVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition.x = mTxComponentAnimatableBaseValue[index].mPosition.x = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale.x = mTxComponentAnimatableBaseValue[index].mScale.x = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin.x = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint.x = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ].x = mSizeBase[index].x = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeYVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition.y = mTxComponentAnimatableBaseValue[index].mPosition.y = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale.y = mTxComponentAnimatableBaseValue[index].mScale.y = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin.y = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint.y = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ].y = mSizeBase[index].y = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+
+  switch( property )
+  {
+    case TRANSFORM_PROPERTY_POSITION:
+    {
+      mTxComponentAnimatable[ index ].mPosition.z = mTxComponentAnimatableBaseValue[index].mPosition.z = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SCALE:
+    {
+      mTxComponentAnimatable[ index ].mScale.z = mTxComponentAnimatableBaseValue[index].mScale.z = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_PARENT_ORIGIN:
+    {
+      mTxComponentStatic[ index ].mParentOrigin.z = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_ANCHOR_POINT:
+    {
+      mTxComponentStatic[ index ].mAnchorPoint.z = value;
+      break;
+    }
+    case TRANSFORM_PROPERTY_SIZE:
+    {
+      mSize[ index ].z = mSizeBase[index].z = value;
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false);
+    }
+  }
+}
+
+Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id )
+{
+  unsigned int index( mIds[id] );
+  mComponentDirty[ index ] = true;
+  return mTxComponentAnimatable[ index ].mOrientation;
+}
+
+const Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id ) const
+{
+  return mTxComponentAnimatable[ mIds[id] ].mOrientation;
+}
+
+void TransformManager::SetQuaternionPropertyValue( TransformId id, const Quaternion& q )
+{
+  unsigned int index( mIds[id] );
+  mTxComponentAnimatable[ index ].mOrientation = q;
+  mComponentDirty[ index ] = true;
+}
+
+void TransformManager::BakeQuaternionPropertyValue( TransformId id, const Quaternion& q )
+{
+  unsigned int index( mIds[id] );
+  mTxComponentAnimatable[ index ].mOrientation = mTxComponentAnimatableBaseValue[index].mOrientation = q;
+  mComponentDirty[ index ] = true;
+}
+
+void TransformManager::BakeRelativeQuaternionPropertyValue( TransformId id, const Quaternion& q )
+{
+  unsigned int index( mIds[id] );
+  mTxComponentAnimatable[ index ].mOrientation = mTxComponentAnimatableBaseValue[index].mOrientation = mTxComponentAnimatable[ index ].mOrientation * q;
+  mComponentDirty[ index ] = true;
+}
+
+} //namespace SceneGraph
+} //namespace Internal
+} //namespace Dali
diff --git a/dali/internal/update/manager/transform-manager.h b/dali/internal/update/manager/transform-manager.h
new file mode 100644 (file)
index 0000000..445b103
--- /dev/null
@@ -0,0 +1,378 @@
+
+#ifndef TRANSFORM_MANAGER_H_
+#define TRANSFORM_MANAGER_H_
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/internal/update/manager/free-list.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Struct to store the animatable part of a component (Scale, orientation and position)
+ */
+struct TransformComponentAnimatable
+{
+  TransformComponentAnimatable()
+  :mScale(1.0f,1.0f,1.0f),
+   mOrientation(1.0f,0.0f,0.0f,0.0f),
+   mPosition(0.0f,0.0f,0.0f)
+  {}
+
+  Vector3 mScale;
+  Quaternion mOrientation;
+  Vector3 mPosition;
+};
+
+/**
+ * Struct to store the non-animatable part of a component (AnchorPoint and ParentOrigin)
+ */
+struct TransformComponentStatic
+{
+  TransformComponentStatic()
+  :mAnchorPoint(0.5f,0.5f,0.5f),
+   mParentOrigin(0.0f,0.0f,0.5f)
+  {}
+
+  Vector3 mAnchorPoint;
+  Vector3 mParentOrigin;
+};
+
+enum InheritanceMode
+{
+  DONT_INHERIT_TRANSFORM  = 0,
+  INHERIT_POSITION        = 1,
+  INHERIT_SCALE           = 2,
+  INHERIT_ORIENTATION     = 4,
+  INHERIT_ALL             = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
+};
+
+enum TransformManagerProperty
+{
+  TRANSFORM_PROPERTY_POSITION = 0,
+  TRANSFORM_PROPERTY_SCALE,
+  TRANSFORM_PROPERTY_ANCHOR_POINT,
+  TRANSFORM_PROPERTY_PARENT_ORIGIN,
+  TRANSFORM_PROPERTY_SIZE,
+  TRANSFORM_PROPERTY_WORLD_POSITION,
+  TRANSFORM_PROPERTY_WORLD_SCALE,
+  TRANSFORM_PROPERTY_WORLD_ORIENTATION,
+  TRANSFORM_PROPERTY_WORLD_MATRIX,
+  TRANSFORM_PROPERTY_COUNT,
+};
+
+typedef unsigned int TransformId;
+static const TransformId INVALID_TRANSFORM_ID = -1;
+
+} //SceneGraph
+} //Internal
+
+// Allow TransformComponentAnimatable to be treated as a POD type
+template <> struct TypeTraits< Dali::Internal::SceneGraph::TransformComponentAnimatable >: public Dali::BasicTypes< Dali::Internal::SceneGraph::TransformComponentAnimatable > { enum { IS_TRIVIAL_TYPE = true }; };
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Transform manager computes the local to world transformations
+ * of all the nodes in the scene. All the transformation data is stored contiguously
+ * in memory which minimizes cache misses during updates
+ */
+class TransformManager
+{
+public:
+
+  /**
+   * Default constructor
+   */
+  TransformManager();
+
+  /**
+   * Class destructor
+   */
+  ~TransformManager();
+
+  /**
+   * Add a new transform component to the manager
+   * @return A TransformId used to access the component
+   */
+  TransformId CreateTransform();
+
+  /**
+   * Removes an existing transform component
+   * @param[in] id Id of the transform to remove
+   */
+  void RemoveTransform(TransformId id);
+
+  /**
+   * Sets the parent transform of an existing component
+   * @param[in] id Id of the transform
+   * @param[in] parentId Id of the new parent
+   */
+  void SetParent( TransformId id, TransformId parentId );
+
+  /**
+   * Gets the world transform matrix of an exisiting transform component
+   * @param[in] id Id of the transform component
+   * @return The local to world transformation matrix of the component
+   */
+  const Matrix& GetWorldMatrix( TransformId id ) const;
+
+  /**
+   * Gets the world transform matrix of an exisiting transform component
+   * @param[in] id Id of the transform component
+   * @return The local to world transformation matrix of the component
+   */
+  Matrix& GetWorldMatrix( TransformId id );
+
+  /**
+   * Checks if the local transform was updated in the last Update
+   * @param[in] id Id of the transform
+   * @return true if local matrix changed in the last update, false otherwise
+   */
+  bool IsLocalMatrixDirty( TransformId id ) const
+  {
+    return mLocalMatrixDirty[mIds[id]];
+  }
+
+  /**
+   * Sets position inheritance mode.
+   * @param[in] id Id of the transform
+   * @param[in] inherit True if position is inherited from parent, false otherwise
+   */
+  void SetInheritPosition( TransformId id, bool inherit );
+
+  /**
+   * Sets scale inheritance mode.
+   * @param[in] id Id of the transform
+   * @param[in] inherit True if scale is inherited from parent, false otherwise
+   */
+  void SetInheritScale( TransformId id, bool inherit );
+
+  /**
+   * Sets orientation inheritance mode.
+   * @param[in] id Id of the transform
+   * @param[in] inherit True if orientation is inherited from parent, false otherwise
+   */
+  void SetInheritOrientation( TransformId id, bool inherit );
+
+  /**
+   * Recomputes all world transform matrices
+   */
+  void Update();
+
+  /**
+   * Resets all the animatable properties to its base value
+   */
+  void ResetToBaseValue();
+
+  /**
+   * Get the value of a Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   */
+  Vector3& GetVector3PropertyValue( TransformId id, TransformManagerProperty property );
+
+  /**
+   * Get the value of a Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   */
+  const Vector3& GetVector3PropertyValue( TransformId id, TransformManagerProperty property ) const;
+
+  /**
+   * Get the value of a component of Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * param[in] component The component (0,1,2)
+   */
+  const float& GetVector3PropertyComponentValue(TransformId id, TransformManagerProperty property, unsigned int component ) const;
+
+  /**
+   * Set the value of a Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void SetVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value );
+
+  /**
+   * Set the value of a component of a Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   * param[in] component The component (0,1,2)
+   */
+  void SetVector3PropertyComponentValue( TransformId id, TransformManagerProperty property, float value, unsigned int component );
+
+  /**
+   * Bakes the value of a Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value );
+
+  /**
+   * Bakes the value of a Vector3 property relative to the current value
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeRelativeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value );
+
+  /**
+   * Bakes the value of a Vector3 property by multiplying the current value and the new value
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeMultiplyVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value );
+
+  /**
+   * Bakes the value of a component of Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeVector3PropertyComponentValue( TransformId id, TransformManagerProperty property, float value, unsigned int component );
+
+  /**
+   * Bakes the value of the x component of Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeXVector3PropertyValue( TransformId id, TransformManagerProperty property, float value );
+
+  /**
+   * Bakes the value of the y component of Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeYVector3PropertyValue( TransformId id, TransformManagerProperty property, float value );
+
+  /**
+   * Bakes the value of the z component of Vector3 property
+   * @param[in] id Id of the transform component
+   * @param[in] property The property
+   * @param[in] value The new value
+   */
+  void BakeZVector3PropertyValue( TransformId id, TransformManagerProperty property, float value );
+
+  /**
+   * Get the value of a quaternion property
+   * @param[in] id Id of the transform component
+   */
+  Quaternion& GetQuaternionPropertyValue( TransformId id );
+
+  /**
+   * Get the value of a quaternion property
+   * @param[in] id Id of the transform component
+   */
+  const Quaternion& GetQuaternionPropertyValue( TransformId id ) const;
+
+  /**
+   * Set the value of a quaternion property
+   * @param[in] id Id of the transform component
+   * @param[in] q The new value
+   */
+  void SetQuaternionPropertyValue( TransformId id, const Quaternion& q );
+
+  /**
+   * Bake the value of a quaternion property
+   * @param[in] id Id of the transform component
+   * @param[in] q The new value
+   */
+  void BakeQuaternionPropertyValue( TransformId id, const Quaternion& q );
+
+  /**
+   * Bake the value of a quaternion property relative to its current value
+   * @param[in] id Id of the transform component
+   * @param[in] q The new value
+   */
+  void BakeRelativeQuaternionPropertyValue( TransformId id, const Quaternion& q );
+
+private:
+
+  //Helper struct to order components
+  struct SOrderItem
+  {
+    bool operator<(const SOrderItem& item) const {return level < item.level;}
+
+    TransformId  id;
+    unsigned int level;
+  };
+
+  /**
+   * Swaps two components in the vectors
+   * @param[in] i Index of a component
+   * @param[in] j Index of a component
+   */
+  void SwapComponents( unsigned int i, unsigned int j );
+
+  /**
+   * Reorders components in hierarchical order so update can iterate sequentially
+   * updating the world transforms
+   */
+  void ReorderComponents();
+
+  unsigned int mComponentCount;                                ///< Total number of components
+  FreeList mIds;                                               ///< FreeList of Ids
+  Vector<TransformComponentAnimatable> mTxComponentAnimatable; ///< Animatable part of the components
+  Vector<TransformComponentStatic> mTxComponentStatic;         ///< Static part of the components
+  Vector<unsigned int> mInheritanceMode;                       ///< Inheritance mode of the components
+  Vector<TransformId> mComponentId;                            ///< Ids of the components
+  Vector<Vector3> mSize;                                       ///< Size of the components
+  Vector<TransformId> mParent;                                 ///< Parent of the components
+  Vector<Matrix> mWorld;                                       ///< Local to world transform of the components
+  Vector<Matrix> mLocal;                                       ///< Local to parent space transform of the components
+  Vector<TransformComponentAnimatable> mTxComponentAnimatableBaseValue;  ///< Base values for the animatable part of the components
+  Vector<Vector3> mSizeBase;                                             ///< Base value for the size of the components
+  Vector<bool> mComponentDirty;    ///< 1u if some of the parts of the component has changed in this frame, 0 otherwise
+  Vector<bool> mLocalMatrixDirty;  ///< 1u if the local matrix has been updated in this frame, 0 otherwise
+  Vector<SOrderItem> mOrderedComponents;   ///< Used to reorder components when hierarchy changes
+  bool mReorder;                           ///< Flag to determine if the components have to reordered in the next Update
+
+};
+
+} //namespace SceneGraph
+
+} //namespace Internal
+
+
+} //namespace Dali
+
+
+#endif /* TRANSFORM_MANAGER_H_ */
index 6e8c76c..e5dbb4e 100644 (file)
@@ -101,84 +101,6 @@ inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updat
   }
 }
 
-inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
-{
-  // If the transform values need to be reinherited
-  if ( nodeDirtyFlags & TransformFlag )
-  {
-    rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) );
-    rootNode.SetWorldOrientation( updateBufferIndex, rootNode.GetOrientation( updateBufferIndex ) );
-    rootNode.SetWorldScale   ( updateBufferIndex, rootNode.GetScale   ( updateBufferIndex ) );
-  }
-  else
-  {
-    // Copy previous value, in case they changed in the previous frame
-    rootNode.CopyPreviousWorldOrientation( updateBufferIndex );
-    rootNode.CopyPreviousWorldScale( updateBufferIndex );
-    rootNode.CopyPreviousWorldPosition( updateBufferIndex );
-  }
-}
-
-/**
- * Updates transform values for the given node if the transform flag is dirty.
-  * Note that this will cause the size dirty flag to be set. This is why we pass
- * the dirty flags in by reference.
- * @param[in]     node The node to update
- * @param[in,out] nodeDirtyFlags A reference to the dirty flags, these may be modified by this function
- * @param[in]     updateBufferIndex The current index to use for this frame
- */
-inline void UpdateNodeTransformValues( Node& node, int& nodeDirtyFlags, BufferIndex updateBufferIndex )
-{
-  // If the transform values need to be reinherited
-  if( nodeDirtyFlags & TransformFlag )
-  {
-    // With a non-central anchor-point, the world rotation and scale affects the world position.
-    // Therefore the world rotation & scale must be updated before the world position.
-    if( node.IsOrientationInherited() )
-    {
-      node.InheritWorldOrientation( updateBufferIndex );
-    }
-    else
-    {
-      node.SetWorldOrientation( updateBufferIndex, node.GetOrientation( updateBufferIndex ) );
-    }
-
-    if( node.IsScaleInherited() )
-    {
-      node.InheritWorldScale( updateBufferIndex );
-    }
-    else
-    {
-      node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) );
-    }
-
-    node.InheritWorldPosition( updateBufferIndex );
-  }
-  else
-  {
-    // Copy inherited values, if those changed in the previous frame
-    node.CopyPreviousWorldOrientation( updateBufferIndex );
-    node.CopyPreviousWorldScale( updateBufferIndex );
-    node.CopyPreviousWorldPosition( updateBufferIndex );
-  }
-}
-
-inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
-{
-  // If world-matrix needs to be recalculated
-  if ( nodeDirtyFlags & TransformFlag )
-  {
-    node.SetWorldMatrix( updateBufferIndex,
-                         node.GetWorldScale(updateBufferIndex),
-                         node.GetWorldOrientation(updateBufferIndex),
-                         node.GetWorldPosition(updateBufferIndex) );
-  }
-  else
-  {
-    node.CopyPreviousWorldMatrix( updateBufferIndex );
-  }
-}
-
 /**
  * This is called recursively for all children of the root Node
  */
@@ -229,35 +151,11 @@ inline int UpdateNodesAndAttachments( Node& node,
 
   UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex );
 
-  // Note: nodeDirtyFlags are passed in by reference and may be modified by the following function
-  UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex );
-
   // Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited.
   inheritedDrawMode |= node.GetDrawMode();
 
-  if ( DALI_UNLIKELY( node.HasAttachment() ) )
-  {
-    //Apply constraints to the attachement
-    NodeAttachment& attachment = node.GetAttachment();
-    PropertyOwner* propertyOwner = dynamic_cast< PropertyOwner* >( &attachment );
-    if( propertyOwner != NULL )
-    {
-      ConstrainPropertyOwner( *propertyOwner, updateBufferIndex );
-    }
-
-    //Update the attachment
-    attachment.Update( updateBufferIndex, node, nodeDirtyFlags );
-  }
-  else if( node.IsObserved() || node.GetRendererCount() )
-  {
-    // This node is being used as a property input for an animation, constraint,
-    // camera or bone. Ensure it's matrix is updated
-    UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex );
-  }
-
   node.PrepareRender( updateBufferIndex );
 
-
   // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
   // also if node has been deleted, dont reuse old render items
   if( nodeDirtyFlags & RenderableUpdateFlags )
@@ -313,8 +211,6 @@ int UpdateNodesAndAttachments( Layer& rootNode,
 
   UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
 
-  UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
-
   DrawMode::Type drawMode( rootNode.GetDrawMode() );
 
   // recurse children
index 8a36580..3d4fd3f 100644 (file)
@@ -49,6 +49,7 @@
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/manager/update-algorithms.h>
 #include <dali/internal/update/manager/update-manager-debug.h>
+#include <dali/internal/update/manager/transform-manager.h>
 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
 #include <dali/internal/update/nodes/node.h>
 #include <dali/internal/update/nodes/scene-graph-layer.h>
@@ -130,9 +131,9 @@ struct UpdateManager::Impl
         TextureCache& textureCache,
         TouchResampler& touchResampler,
         SceneGraphBuffers& sceneGraphBuffers )
-  :
-    renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
+  : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
     notificationManager( notificationManager ),
+    transformManager(),
     animationFinishedNotifier( animationFinishedNotifier ),
     propertyNotifier( propertyNotifier ),
     shaderSaver( NULL ),
@@ -219,6 +220,7 @@ struct UpdateManager::Impl
   SceneGraphBuffers                   sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
   RenderMessageDispatcher             renderMessageDispatcher;       ///< Used for passing messages to the render-thread
   NotificationManager&                notificationManager;           ///< Queues notification messages for the event-thread.
+  TransformManager                    transformManager;              ///< Used to update the transformation matrices of the nodes
   CompleteNotificationInterface&      animationFinishedNotifier;     ///< Provides notification to applications when animations are finished.
   PropertyNotifier&                   propertyNotifier;              ///< Provides notification to applications when properties are modified.
   ShaderSaver*                        shaderSaver;                   ///< Saves shader binaries.
@@ -314,11 +316,13 @@ void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
   {
     DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
     mImpl->root = layer;
+    mImpl->root->CreateTransform( &mImpl->transformManager);
   }
   else
   {
     DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
     mImpl->systemLevelRoot = layer;
+    mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager);
   }
 
   layer->SetRoot(true);
@@ -336,6 +340,7 @@ void UpdateManager::AddNode( Node* node )
     if(node > (*iter))
     {
       mImpl->nodes.Insert((iter+1), node);
+      node->CreateTransform( &mImpl->transformManager);
       break;
     }
   }
@@ -916,6 +921,7 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
   {
     //Reset properties from the previous update
     ResetProperties( bufferIndex );
+    mImpl->transformManager.ResetToBaseValue();
   }
 
   //Process the queued scene messages
@@ -964,6 +970,9 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
     //Update renderers and apply constraints
     UpdateRenderers( bufferIndex );
 
+    //Update the trnasformations of all the nodes
+    mImpl->transformManager.Update();
+
     //Process Property Notifications
     ProcessPropertyNotifications( bufferIndex );
 
index f8afeae..ad151ae 100644 (file)
@@ -101,17 +101,6 @@ public:
     return *mParent;
   }
 
-  // Update methods
-
-  /**
-   * Called when the attachment or it's owning node is flagged as dirty during scene graph updates.
-   * Allows derived classes to perform extra processing
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] owningNode The attachment's owning node
-   * @param[in] nodeDirtyFlags of the owning node
-   */
-  virtual void Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags ) {}
-
 protected:
 
   /**
index f4f9a81..7078ddf 100644 (file)
@@ -304,14 +304,14 @@ const PropertyInputImpl* CameraAttachment::GetViewMatrix() const
   return &mViewMatrix;
 }
 
-void CameraAttachment::Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags )
+void CameraAttachment::Update( BufferIndex updateBufferIndex, const Node& owningNode )
 {
   // if owning node has changes in world position we need to update camera for next 2 frames
-  if( nodeDirtyFlags & TransformFlag )
+  if( owningNode.IsLocalMatrixDirty() )
   {
     mUpdateViewFlag = UPDATE_COUNT;
   }
-  if( nodeDirtyFlags & VisibleFlag )
+  if( owningNode.GetDirtyFlags() & VisibleFlag )
   {
     // If the visibility changes, the projection matrix needs to be re-calculated.
     // It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
@@ -366,17 +366,21 @@ unsigned int CameraAttachment::UpdateViewMatrix( BufferIndex updateBufferIndex,
         case Dali::Camera::FREE_LOOK:
           {
           Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
-          viewMatrix.SetInverseTransformComponents( Vector3::ONE, owningNode.GetWorldOrientation( updateBufferIndex ),
-                                                    owningNode.GetWorldPosition( updateBufferIndex ) );
+          viewMatrix = owningNode.GetWorldMatrix(updateBufferIndex);
+          viewMatrix.Invert();
           mViewMatrix.SetDirty( updateBufferIndex );
           break;
         }
           // camera orientation constrained to look at a target
         case Dali::Camera::LOOK_AT_TARGET:
           {
+          const Matrix& owningNodeMatrix( owningNode.GetWorldMatrix(updateBufferIndex) );
+          Vector3 position, scale;
+          Quaternion orientation;
+          owningNodeMatrix.GetTransformComponents( position, orientation, scale );
           Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
-          LookAt( viewMatrix, owningNode.GetWorldPosition( updateBufferIndex ), mTargetPosition,
-                  owningNode.GetWorldOrientation( updateBufferIndex ).Rotate( Vector3::YAXIS ) );
+          LookAt( viewMatrix, position, mTargetPosition,
+                  orientation.Rotate( Vector3::YAXIS ) );
           mViewMatrix.SetDirty( updateBufferIndex );
           break;
         }
index 48b5cbb..949e9ea 100644 (file)
@@ -244,7 +244,15 @@ public:
   /**
    * @copydoc NodeAttachment::Update
    */
-  virtual void Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags );
+  virtual void Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags ){};
+
+  /**
+   * Updates view and projection matrices.
+   * Called by the render task using the camera attachment
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @param[in] owningNode The node that owns the camera
+   */
+  void Update( BufferIndex updateBufferIndex, const Node& owningNode );
 
   /**
    * @return true if the view matrix of camera is updated this or the previous frame
index c11cc6c..af3cf6d 100644 (file)
@@ -222,6 +222,164 @@ private:
   float mParam;
 };
 
+
+template <typename P>
+class NodeTransformPropertyMessage : public NodePropertyMessageBase
+{
+public:
+
+  typedef void(TransformManagerPropertyHandler<P>::*MemberFunction)( BufferIndex, const P& );
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const Node* node,
+                    const TransformManagerPropertyHandler<P>* property,
+                    MemberFunction member,
+                    const P& value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( NodeTransformPropertyMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) NodeTransformPropertyMessage( eventThreadServices.GetUpdateManager(), node, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodeTransformPropertyMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] updateManager The update-manager.
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  NodeTransformPropertyMessage( UpdateManager& updateManager,
+                       const Node* node,
+                       const TransformManagerPropertyHandler<P>* property,
+                       MemberFunction member,
+                       const P& value )
+  : NodePropertyMessageBase( updateManager ),
+    mNode( const_cast< Node* >( node ) ),
+    mProperty( const_cast< TransformManagerPropertyHandler<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+
+  Node* mNode;
+  TransformManagerPropertyHandler<P>* mProperty;
+  MemberFunction mMemberFunction;
+  P mParam;
+};
+
+
+template <typename P>
+class NodeTransformComponentMessage : public NodePropertyMessageBase
+{
+public:
+
+  typedef void(TransformManagerPropertyHandler<P>::*MemberFunction)( BufferIndex, float );
+
+  /**
+   * Send a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const Node* node,
+                    const TransformManagerPropertyHandler<P>* property,
+                    MemberFunction member,
+                    float value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( NodeTransformComponentMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) NodeTransformComponentMessage( eventThreadServices.GetUpdateManager(), node, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodeTransformComponentMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] updateManager The update-manager.
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+  */
+  NodeTransformComponentMessage( UpdateManager& updateManager,
+                                const Node* node,
+                                const TransformManagerPropertyHandler<P>* property,
+                                MemberFunction member,
+                                float value )
+  : NodePropertyMessageBase( updateManager ),
+    mNode( const_cast< Node* >( node ) ),
+    mProperty( const_cast< TransformManagerPropertyHandler<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+
+  Node* mNode;
+  TransformManagerPropertyHandler<P>* mProperty;
+  MemberFunction mMemberFunction;
+  float mParam;
+};
+
 } // namespace SceneGraph
 
 } // namespace Internal
index 52fad10..e1d5847 100644 (file)
@@ -50,17 +50,19 @@ Node* Node::New()
 }
 
 Node::Node()
-: mParentOrigin( ParentOrigin::DEFAULT ),
-  mAnchorPoint( AnchorPoint::DEFAULT ),
-  mSize(),     // zero initialized by default
-  mPosition(), // zero initialized by default
+: mTransformManager(0),
+  mTransformId( INVALID_TRANSFORM_ID ),
+  mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ),
+  mAnchorPoint( TRANSFORM_PROPERTY_ANCHOR_POINT ),
+  mSize(TRANSFORM_PROPERTY_SIZE),     // zero initialized by default
+  mPosition(TRANSFORM_PROPERTY_POSITION), // zero initialized by default
   mOrientation(), // initialized to identity by default
-  mScale( Vector3::ONE ),
+  mScale( TRANSFORM_PROPERTY_SCALE ),
   mVisible( true ),
   mColor( Color::WHITE ),
-  mWorldPosition(), // zero initialized by default
+  mWorldPosition(TRANSFORM_PROPERTY_WORLD_POSITION, Vector3(0.0f,0.0f,0.0f)), // zero initialized by default
+  mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3(1.0f,1.0f,1.0f) ),
   mWorldOrientation(), // initialized to identity by default
-  mWorldScale( Vector3::ONE ),
   mWorldMatrix(),
   mWorldColor( Color::WHITE ),
   mParent( NULL ),
@@ -71,11 +73,7 @@ Node::Node()
   mDepth(0u),
   mDirtyFlags(AllFlags),
   mIsRoot( false ),
-  mInheritPosition( true ),
-  mInheritOrientation( true ),
-  mInheritScale( true ),
   mDrawMode( DrawMode::NORMAL ),
-  mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
   mColorMode( DEFAULT_COLOR_MODE )
 {
   mUniformMapChanged[0] = 0u;
@@ -84,6 +82,10 @@ Node::Node()
 
 Node::~Node()
 {
+  if( mTransformId != INVALID_TRANSFORM_ID )
+  {
+    mTransformManager->RemoveTransform(mTransformId);
+  }
 }
 
 void Node::operator delete( void* ptr )
@@ -103,6 +105,27 @@ void Node::OnDestroy()
   PropertyOwner::Destroy();
 }
 
+void Node::CreateTransform( SceneGraph::TransformManager* transformManager )
+{
+  //Create a new transform
+  mTransformManager = transformManager;
+  mTransformId = transformManager->CreateTransform();
+
+  //Initialize all the animatable properties
+  mPosition.Initialize( transformManager, mTransformId );
+  mScale.Initialize( transformManager, mTransformId );
+  mOrientation.Initialize( transformManager, mTransformId );
+  mSize.Initialize( transformManager, mTransformId );
+  mParentOrigin.Initialize( transformManager, mTransformId );
+  mAnchorPoint.Initialize( transformManager, mTransformId );
+
+  //Initialize all the input properties
+  mWorldPosition.Initialize( transformManager, mTransformId );
+  mWorldScale.Initialize( transformManager, mTransformId );
+  mWorldOrientation.Initialize( transformManager, mTransformId );
+  mWorldMatrix.Initialize( transformManager, mTransformId );
+}
+
 void Node::Attach( NodeAttachment& object )
 {
   DALI_ASSERT_DEBUG(!mAttachment);
@@ -231,21 +254,6 @@ int Node::GetDirtyFlags() const
 {
   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
   int flags = mDirtyFlags;
-  const bool sizeFlag = mSize.IsClean();
-
-  if ( !(flags & TransformFlag) )
-  {
-    // Check whether the transform related properties have changed
-    if( !sizeFlag            ||
-        !mPosition.IsClean() ||
-        !mOrientation.IsClean() ||
-        !mScale.IsClean()    ||
-        mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
-        mAnchorPoint.InputChanged() )
-    {
-      flags |= TransformFlag;
-    }
-  }
 
   // Check whether the visible property has changed
   if ( !mVisible.IsClean() )
@@ -259,25 +267,11 @@ int Node::GetDirtyFlags() const
     flags |= ColorFlag;
   }
 
-  // Check whether the size property has changed
-  if ( !sizeFlag )
-  {
-    flags |= SizeFlag;
-   }
-
   return flags;
 }
 
 void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
 {
-  // clear dirty flags in parent origin & anchor point
-  mParentOrigin.Clear();
-  mAnchorPoint.Clear();
-  // Reset default properties
-  mSize.ResetToBaseValue( updateBufferIndex );
-  mPosition.ResetToBaseValue( updateBufferIndex );
-  mOrientation.ResetToBaseValue( updateBufferIndex );
-  mScale.ResetToBaseValue( updateBufferIndex );
   mVisible.ResetToBaseValue( updateBufferIndex );
   mColor.ResetToBaseValue( updateBufferIndex );
 
@@ -292,6 +286,11 @@ void Node::SetParent(Node& parentNode)
 
   mParent = &parentNode;
   mDepth = mParent->GetDepth() + 1u;
+
+  if( mTransformId != INVALID_TRANSFORM_ID )
+  {
+    mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
+  }
 }
 
 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
@@ -321,6 +320,10 @@ void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
     mAttachment->DisconnectedFromSceneGraph();
   }
 
+  if( mTransformId != INVALID_TRANSFORM_ID )
+  {
+    mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
+  }
 }
 
 } // namespace SceneGraph
index 7e24335..e12c5ad 100644 (file)
 #include <dali/public-api/math/quaternion.h>
 #include <dali/public-api/math/math-utils.h>
 #include <dali/public-api/math/vector3.h>
+#include <dali/integration-api/debug.h>
 #include <dali/internal/common/message.h>
 #include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/render/data-providers/node-data-provider.h>
 #include <dali/internal/update/common/animatable-property.h>
 #include <dali/internal/update/common/property-owner.h>
 #include <dali/internal/update/common/property-vector3.h>
 #include <dali/internal/update/common/scene-graph-buffers.h>
 #include <dali/internal/update/common/inherited-property.h>
-#include <dali/integration-api/debug.h>
+#include <dali/internal/update/manager/transform-manager.h>
+#include <dali/internal/update/manager/transform-manager-property.h>
 #include <dali/internal/update/nodes/node-declarations.h>
 #include <dali/internal/update/node-attachments/node-attachment-declarations.h>
-#include <dali/internal/render/data-providers/node-data-provider.h>
 #include <dali/internal/update/rendering/scene-graph-renderer.h>
 
 namespace Dali
@@ -333,7 +335,7 @@ public:
    */
   const Vector3& GetParentOrigin() const
   {
-    return mParentOrigin.mValue;
+    return mParentOrigin.Get(0);
   }
 
   /**
@@ -342,8 +344,7 @@ public:
    */
   void SetParentOrigin(const Vector3& origin)
   {
-    mParentOrigin.mValue = origin;
-    mParentOrigin.OnSet();
+    mParentOrigin.Set(0,origin );
   }
 
   /**
@@ -352,7 +353,7 @@ public:
    */
   const Vector3& GetAnchorPoint() const
   {
-    return mAnchorPoint.mValue;
+    return mAnchorPoint.Get(0);
   }
 
   /**
@@ -361,8 +362,7 @@ public:
    */
   void SetAnchorPoint(const Vector3& anchor)
   {
-    mAnchorPoint.mValue = anchor;
-    mAnchorPoint.OnSet();
+    mAnchorPoint.Set(0, anchor );
   }
 
   /**
@@ -372,128 +372,12 @@ public:
    */
   const Vector3& GetPosition(BufferIndex bufferIndex) const
   {
-    return mPosition[bufferIndex];
-  }
-
-  /**
-   * Sets both the local & base positions of the node.
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] position The new local & base position.
-   */
-  void BakePosition(BufferIndex updateBufferIndex, const Vector3& position)
-  {
-    mPosition.Bake( updateBufferIndex, position );
-  }
-
-  /**
-   * Sets the world of the node derived from the position of all its parents.
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] position The world position.
-   */
-  void SetWorldPosition( BufferIndex updateBufferIndex, const Vector3& position )
-  {
-    mWorldPosition.Set( updateBufferIndex, position );
-  }
-
-  /**
-   * Sets the position of the node derived from the position of all its parents.
-   * This method should only be called when the parent's world position is up-to-date.
-   * With a non-central anchor-point, the local orientation and scale affects the world position.
-   * Therefore the world orientation & scale must be updated before the world position.
-   * @pre The node has a parent.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void InheritWorldPosition(BufferIndex updateBufferIndex)
-  {
-    DALI_ASSERT_DEBUG(mParent != NULL);
-
-    switch( mPositionInheritanceMode )
+    if( mTransformId != INVALID_TRANSFORM_ID )
     {
-      case INHERIT_PARENT_POSITION  : ///@see Dali::PositionInheritanceMode for how these modes are expected to work
-      {
-        Vector3 finalPosition(-0.5f, -0.5f, -0.5f);
-
-        finalPosition += mParentOrigin.mValue;
-        finalPosition *= mParent->GetSize(updateBufferIndex);
-        finalPosition += mPosition[updateBufferIndex];
-        finalPosition *= mParent->GetWorldScale(updateBufferIndex);
-        const Quaternion& parentWorldOrientation = mParent->GetWorldOrientation(updateBufferIndex);
-        if(!parentWorldOrientation.IsIdentity())
-        {
-          finalPosition *= parentWorldOrientation;
-        }
-
-        // check if a node needs to be offsetted locally (only applies when AnchorPoint is not central)
-        // dont use operator== as that does a slower comparison (and involves function calls)
-        Vector3 localOffset(0.5f, 0.5f, 0.5f);    // AnchorPoint::CENTER
-        localOffset -= mAnchorPoint.mValue;
-
-        if( ( fabsf( localOffset.x ) >= Math::MACHINE_EPSILON_0 ) ||
-            ( fabsf( localOffset.y ) >= Math::MACHINE_EPSILON_0 ) ||
-            ( fabsf( localOffset.z ) >= Math::MACHINE_EPSILON_0 ) )
-        {
-          localOffset *= mSize[updateBufferIndex];
-
-          Vector3 scale = mWorldScale[updateBufferIndex];
-
-          // Pick up sign of local scale
-          if (mScale[updateBufferIndex].x < 0.0f)
-          {
-            scale.x = -scale.x;
-          }
-          if (mScale[updateBufferIndex].y < 0.0f)
-          {
-            scale.y = -scale.y;
-          }
-          if (mScale[updateBufferIndex].z < 0.0f)
-          {
-            scale.z = -scale.z;
-          }
-
-          // If the anchor-point is not central, then position is affected by the local orientation & scale
-          localOffset *= scale;
-          const Quaternion& localWorldOrientation = mWorldOrientation[updateBufferIndex];
-          if(!localWorldOrientation.IsIdentity())
-          {
-            localOffset *= localWorldOrientation;
-          }
-          finalPosition += localOffset;
-        }
-
-        finalPosition += mParent->GetWorldPosition(updateBufferIndex);
-        mWorldPosition.Set( updateBufferIndex, finalPosition );
-        break;
-      }
-      case USE_PARENT_POSITION_PLUS_LOCAL_POSITION :
-      {
-        // copy parents position plus local transform
-        mWorldPosition.Set( updateBufferIndex, mParent->GetWorldPosition(updateBufferIndex) + mPosition[updateBufferIndex] );
-        break;
-      }
-      case USE_PARENT_POSITION :
-      {
-        // copy parents position
-        mWorldPosition.Set( updateBufferIndex, mParent->GetWorldPosition(updateBufferIndex) );
-        break;
-      }
-      case DONT_INHERIT_POSITION :
-      {
-        // use local position as world position
-        mWorldPosition.Set( updateBufferIndex, mPosition[updateBufferIndex] );
-        break;
-      }
+      return mPosition.Get(bufferIndex);
     }
-  }
 
-  /**
-   * Copies the previous inherited position, if this changed in the previous frame.
-   * This method should be called instead of InheritWorldPosition i.e. if the inherited position
-   * does not need to be recalculated in the current frame.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void CopyPreviousWorldPosition( BufferIndex updateBufferIndex )
-  {
-    mWorldPosition.CopyPrevious( updateBufferIndex );
+    return Vector3::ZERO;
   }
 
   /**
@@ -502,7 +386,7 @@ public:
    */
   const Vector3& GetWorldPosition( BufferIndex bufferIndex ) const
   {
-    return mWorldPosition[bufferIndex];
+    return mWorldPosition.Get(bufferIndex);
   }
 
   /**
@@ -511,11 +395,9 @@ public:
    */
   void SetInheritPosition(bool inherit)
   {
-    if (inherit != mInheritPosition)
+    if( mTransformId != INVALID_TRANSFORM_ID )
     {
-      mInheritPosition = inherit;
-      mPositionInheritanceMode = inherit ?  INHERIT_PARENT_POSITION : DONT_INHERIT_POSITION;
-      SetDirtyFlag(TransformFlag);
+      mTransformManager->SetInheritPosition( mTransformId, inherit );
     }
   }
 
@@ -526,17 +408,10 @@ public:
    */
   void SetPositionInheritanceMode( PositionInheritanceMode mode )
   {
-    mPositionInheritanceMode = mode;
-
-    SetDirtyFlag(TransformFlag);
-  }
-
-  /**
-   * @return The position inheritance mode.
-   */
-  PositionInheritanceMode GetPositionInheritanceMode() const
-  {
-    return mPositionInheritanceMode;
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      mTransformManager->SetInheritPosition(mTransformId, mode == INHERIT_PARENT_POSITION );
+    }
   }
 
   /**
@@ -546,62 +421,12 @@ public:
    */
   const Quaternion& GetOrientation(BufferIndex bufferIndex) const
   {
-    return mOrientation[bufferIndex];
-  }
-
-  /**
-   * Sets both the local & base orientations of the node.
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] orientation The new local & base orientation.
-   */
-  void BakeOrientation(BufferIndex updateBufferIndex, const Quaternion& orientation)
-  {
-    mOrientation.Bake( updateBufferIndex, orientation );
-  }
-
-  /**
-   * Sets the orientation of the node derived from the rotation of all its parents.
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] orientation The world orientation.
-   */
-  void SetWorldOrientation( BufferIndex updateBufferIndex, const Quaternion& orientation )
-  {
-    mWorldOrientation.Set( updateBufferIndex, orientation );
-  }
-
-  /**
-   * Sets the orientation of the node derived from the rotation of all its parents.
-   * This method should only be called when the parents world orientation is up-to-date.
-   * @pre The node has a parent.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void InheritWorldOrientation( BufferIndex updateBufferIndex )
-  {
-    DALI_ASSERT_DEBUG(mParent != NULL);
-
-    const Quaternion& localOrientation = mOrientation[updateBufferIndex];
-
-    if(localOrientation.IsIdentity())
-    {
-      mWorldOrientation.Set( updateBufferIndex, mParent->GetWorldOrientation(updateBufferIndex) );
-    }
-    else
+    if( mTransformId != INVALID_TRANSFORM_ID )
     {
-      Quaternion finalOrientation( mParent->GetWorldOrientation(updateBufferIndex) );
-      finalOrientation *= localOrientation;
-      mWorldOrientation.Set( updateBufferIndex, finalOrientation );
+      return mOrientation.Get(0);
     }
-  }
 
-  /**
-   * Copies the previous inherited orientation, if this changed in the previous frame.
-   * This method should be called instead of InheritWorldOrientation i.e. if the inherited orientation
-   * does not need to be recalculated in the current frame.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void CopyPreviousWorldOrientation( BufferIndex updateBufferIndex )
-  {
-    mWorldOrientation.CopyPrevious( updateBufferIndex );
+    return Quaternion::IDENTITY;
   }
 
   /**
@@ -611,7 +436,7 @@ public:
    */
   const Quaternion& GetWorldOrientation( BufferIndex bufferIndex ) const
   {
-    return mWorldOrientation[bufferIndex];
+    return mWorldOrientation.Get(0);
   }
 
   /**
@@ -620,66 +445,27 @@ public:
    */
   void SetInheritOrientation(bool inherit)
   {
-    if (inherit != mInheritOrientation)
+    if( mTransformId != INVALID_TRANSFORM_ID )
     {
-      mInheritOrientation = inherit;
-
-      SetDirtyFlag(TransformFlag);
+      mTransformManager->SetInheritOrientation(mTransformId, inherit );
     }
   }
 
   /**
-   * Query whether the node inherits orientation from its parent.
-   * @return True if the parent orientation is inherited.
-   */
-  bool IsOrientationInherited() const
-  {
-    return mInheritOrientation;
-  }
-
-  /**
    * Retrieve the local scale of the node, relative to its parent.
    * @param[in] bufferIndex The buffer to read from.
    * @return The local scale.
    */
   const Vector3& GetScale(BufferIndex bufferIndex) const
   {
-    return mScale[bufferIndex];
-  }
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      return mScale.Get(0);
+    }
 
-  /**
-   * Sets the scale of the node derived from the scale of all its parents and a pre-scale
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] scale The world scale.
-   */
-  void SetWorldScale(BufferIndex updateBufferIndex, const Vector3& scale)
-  {
-    mWorldScale.Set( updateBufferIndex, scale );
+    return Vector3::ONE;
   }
 
-  /**
-   * Sets the scale of the node derived from the scale of all its parents and a pre-scale.
-   * This method should only be called when the parents world scale is up-to-date.
-   * @pre The node has a parent.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void InheritWorldScale(BufferIndex updateBufferIndex)
-  {
-    DALI_ASSERT_DEBUG(mParent != NULL);
-
-    mWorldScale.Set( updateBufferIndex, mParent->GetWorldScale(updateBufferIndex) * mScale[updateBufferIndex] );
-  }
-
-  /**
-   * Copies the previous inherited scale, if this changed in the previous frame.
-   * This method should be called instead of InheritWorldScale i.e. if the inherited scale
-   * does not need to be recalculated in the current frame.
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void CopyPreviousWorldScale( BufferIndex updateBufferIndex )
-  {
-    mWorldScale.CopyPrevious( updateBufferIndex );
-  }
 
   /**
    * Retrieve the scale of the node derived from the scale of all its parents.
@@ -688,7 +474,7 @@ public:
    */
   const Vector3& GetWorldScale( BufferIndex bufferIndex ) const
   {
-    return mWorldScale[bufferIndex];
+    return mWorldScale.Get(0);
   }
 
   /**
@@ -697,24 +483,13 @@ public:
    */
   void SetInheritScale( bool inherit )
   {
-    if( inherit != mInheritScale )
+    if( mTransformId != INVALID_TRANSFORM_ID )
     {
-      mInheritScale = inherit;
-
-      SetDirtyFlag( TransformFlag );
+      mTransformManager->SetInheritScale(mTransformId, inherit );
     }
   }
 
   /**
-   * Query whether the Node inherits scale.
-   * @return if scale is inherited
-   */
-  bool IsScaleInherited() const
-  {
-    return mInheritScale;
-  }
-
-  /**
    * Retrieve the visibility of the node.
    * @param[in] bufferIndex The buffer to read from.
    * @return True if the node is visible.
@@ -834,24 +609,25 @@ public:
    */
   const Vector3& GetSize(BufferIndex bufferIndex) const
   {
-    return mSize[bufferIndex];
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      return mSize.Get(0);
+    }
+
+    return Vector3::ZERO;
   }
 
   /**
-   * Set the world-matrix of a node, with scale + rotation + translation.
-   * Scale and rotation are centered at the origin.
-   * Translation is applied independently of the scale or rotatation axis.
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] scale The scale.
-   * @param[in] rotation The rotation.
-   * @param[in] translation The translation.
+   * Checks if local matrix has changed since last update
+   * @return true if local matrix has changed, false otherwise
    */
-  void SetWorldMatrix( BufferIndex updateBufferIndex, const Vector3& scale, const Quaternion& rotation, const Vector3& translation )
+  bool IsLocalMatrixDirty() const
   {
-    mWorldMatrix.Get( updateBufferIndex ).SetTransformComponents( scale, rotation, translation );
-    mWorldMatrix.SetDirty( updateBufferIndex );
+    return (mTransformId != INVALID_TRANSFORM_ID) &&
+           (mTransformManager->IsLocalMatrixDirty( mTransformId ));
   }
 
+
   /**
    * Retrieve the cached world-matrix of a node.
    * @param[in] bufferIndex The buffer to read from.
@@ -859,16 +635,7 @@ public:
    */
   const Matrix& GetWorldMatrix( BufferIndex bufferIndex ) const
   {
-    return mWorldMatrix[ bufferIndex ];
-  }
-
-  /**
-   * Copy previous frames world matrix
-   * @param[in] updateBufferIndex The current update buffer index.
-   */
-  void CopyPreviousWorldMatrix( BufferIndex updateBufferIndex )
-  {
-    mWorldMatrix.CopyPrevious( updateBufferIndex );
+    return mWorldMatrix.Get(bufferIndex);
   }
 
   /**
@@ -907,6 +674,15 @@ public:
     return mDrawMode;
   }
 
+  /*
+   * Returns the transform id of the node
+   * @return The transform component id of the node
+   */
+  TransformId GetTransformId() const
+  {
+    return mTransformId;
+  }
+
   /**
    * Equality operator, checks for identity, not values.
    *
@@ -943,6 +719,14 @@ public:
    */
   void PrepareRender( BufferIndex bufferIndex );
 
+  /**
+   * Called by UpdateManager when the node is added.
+   * Creates a new transform component in the transform manager and initialize all the properties
+   * related to the transformation
+   * @param[in] transformManager A pointer to the trnasform manager (Owned by UpdateManager)
+   */
+  void CreateTransform( SceneGraph::TransformManager* transformManager );
+
 protected:
 
   /**
@@ -974,11 +758,6 @@ private: // from NodeDataProvider
     return GetWorldColor( bufferId );
   }
 
-  virtual const Vector3& GetRenderSize( unsigned int bufferId ) const
-  {
-    return GetSize( bufferId );
-  }
-
 public: // From UniformMapDataProvider
   /**
    * @copydoc UniformMapDataProvider::GetUniformMapChanged
@@ -1018,22 +797,24 @@ private:
 
 public: // Default properties
 
-  PropertyVector3                mParentOrigin;  ///< Local transform; the position is relative to this. Sets the TransformFlag dirty when changed
-  PropertyVector3                mAnchorPoint;   ///< Local transform; local center of rotation. Sets the TransformFlag dirty when changed
+  TransformManager* mTransformManager;
+  TransformId mTransformId;
+  TransformManagerPropertyVector3    mParentOrigin;  ///< Local transform; the position is relative to this. Sets the TransformFlag dirty when changed
+  TransformManagerPropertyVector3    mAnchorPoint;   ///< Local transform; local center of rotation. Sets the TransformFlag dirty when changed
+  TransformManagerPropertyVector3    mSize;          ///< Size is provided for layouting
+  TransformManagerPropertyVector3    mPosition;      ///< Local transform; distance between parent-origin & anchor-point
+  TransformManagerPropertyQuaternion mOrientation;   ///< Local transform; rotation relative to parent node
+  TransformManagerPropertyVector3    mScale;         ///< Local transform; scale relative to parent node
 
-  AnimatableProperty<Vector3>    mSize;          ///< Size is provided for layouting
-  AnimatableProperty<Vector3>    mPosition;      ///< Local transform; distance between parent-origin & anchor-point
-  AnimatableProperty<Quaternion> mOrientation;   ///< Local transform; rotation relative to parent node
-  AnimatableProperty<Vector3>    mScale;         ///< Local transform; scale relative to parent node
-  AnimatableProperty<bool>       mVisible;       ///< Visibility can be inherited from the Node hierachy
-  AnimatableProperty<Vector4>    mColor;         ///< Color can be inherited from the Node hierarchy
+  AnimatableProperty<bool>           mVisible;       ///< Visibility can be inherited from the Node hierachy
+  AnimatableProperty<Vector4>        mColor;         ///< Color can be inherited from the Node hierarchy
 
   // Inherited properties; read-only from public API
 
-  InheritedVector3    mWorldPosition;     ///< Full inherited position
-  InheritedQuaternion mWorldOrientation;  ///< Full inherited orientation
-  InheritedVector3    mWorldScale;        ///< Full inherited scale
-  InheritedMatrix     mWorldMatrix;       ///< Full inherited world matrix
+  TransformManagerVector3Input    mWorldPosition;     ///< Full inherited position
+  TransformManagerVector3Input    mWorldScale;
+  TransformManagerQuaternionInput mWorldOrientation;  ///< Full inherited orientation
+  TransformManagerMatrixInput     mWorldMatrix;       ///< Full inherited world matrix
   InheritedColor      mWorldColor;        ///< Full inherited color
 
 protected:
@@ -1055,12 +836,8 @@ protected:
   int  mDirtyFlags:8;                               ///< A composite set of flags for each of the Node properties
 
   bool mIsRoot:1;                                    ///< True if the node cannot have a parent
-  bool mInheritPosition:1;                           ///< Whether the parent's position should be inherited.
-  bool mInheritOrientation:1;                        ///< Whether the parent's orientation should be inherited.
-  bool mInheritScale:1;                              ///< Whether the parent's scale should be inherited.
 
   DrawMode::Type          mDrawMode:2;               ///< How the Node and its children should be drawn
-  PositionInheritanceMode mPositionInheritanceMode:2;///< Determines how position is inherited, 2 bits is enough.
   ColorMode               mColorMode:2;              ///< Determines whether mWorldColor is inherited, 2 bits is enough
 
   // Changes scope, should be at end of class
index 5c06a12..d22fd54 100644 (file)
@@ -230,7 +230,7 @@ bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
   // Check camera node
   if ( NULL == mCameraNode ||
        NULL == mCameraNode->GetParent() ||
-       !mCameraNode->HasAttachment() )
+       NULL == mCameraAttachment )
   {
     // Camera node is missing or disconnected
     TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
@@ -238,6 +238,8 @@ bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
     return false;
   }
 
+  mCameraAttachment->Update( updateBufferIndex, *mCameraNode );
+
   TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
   return true;
 }