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 );
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();
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();
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();
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 );
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 );
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
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 );
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);
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();
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 );
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();
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 );
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 )
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;
}
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 )
{
delete mShaderFactory;
delete mResourceClient;
delete mResourceManager;
+ delete mDiscardQueue;
delete mUpdateManager;
delete mTouchResampler;
delete mRenderManager;
- delete mDiscardQueue;
delete mTextureUploadedQueue;
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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) );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
{
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;
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 );
}
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;
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 );
}
}
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 );
}
}
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 );
}
}
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*/);
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() );
{
// 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.
//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;
+ }
}
}
}
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.
// 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;
+ }
}
}
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() )
}
/**
+ * 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.
$(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 \
//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
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() );
}
}
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:
/**
RenderItem& operator = ( const RenderItem& item );
Matrix mModelViewMatrix;
+ Vector3 mSize;
Render::Renderer* mRenderer;
Node* mNode;
int mDepthIndex;
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;
{
}
-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" );
GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
if( -1 != sizeLoc )
{
- Vector3 size = node.GetRenderSize( bufferIndex );
program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
}
}
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector3& size,
bool blend )
{
// Get the program to use:
}
}
- SetUniforms( bufferIndex, node, *program );
+ SetUniforms( bufferIndex, node, size, *program );
if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
{
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector3& size,
bool blend);
/**
/**
* 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
// 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
{
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
#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
{
mPropertyOwner->RemoveObserver(*this);
}
- if( mAnimatorFunction )
- {
- delete mAnimatorFunction;
- }
+ delete mAnimatorFunction;
}
/**
virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
{
mPropertyOwner = NULL;
- mPropertyAccessor.Reset();
- mEnabled = false;
}
/**
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
/*
Vector3 mForward;
};
-
} // namespace Internal
} // namespace Dali
--- /dev/null
+
+#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_ */
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 )
}
// save MV matrix onto the item
Matrix::Multiply( item.GetModelViewMatrix(), worldMatrix, viewMatrix );
+ item.SetSize( size );
}
}
}
--- /dev/null
+#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_
--- /dev/null
+/*
+ * 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
--- /dev/null
+
+#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_ */
}
}
-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
*/
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 )
UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
- UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
-
DrawMode::Type drawMode( rootNode.GetDrawMode() );
// recurse children
#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>
TextureCache& textureCache,
TouchResampler& touchResampler,
SceneGraphBuffers& sceneGraphBuffers )
- :
- renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
+ : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
notificationManager( notificationManager ),
+ transformManager(),
animationFinishedNotifier( animationFinishedNotifier ),
propertyNotifier( propertyNotifier ),
shaderSaver( NULL ),
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.
{
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);
if(node > (*iter))
{
mImpl->nodes.Insert((iter+1), node);
+ node->CreateTransform( &mImpl->transformManager);
break;
}
}
{
//Reset properties from the previous update
ResetProperties( bufferIndex );
+ mImpl->transformManager.ResetToBaseValue();
}
//Process the queued scene messages
//Update renderers and apply constraints
UpdateRenderers( bufferIndex );
+ //Update the trnasformations of all the nodes
+ mImpl->transformManager.Update();
+
//Process Property Notifications
ProcessPropertyNotifications( bufferIndex );
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:
/**
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,
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;
}
/**
* @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
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
}
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 ),
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;
Node::~Node()
{
+ if( mTransformId != INVALID_TRANSFORM_ID )
+ {
+ mTransformManager->RemoveTransform(mTransformId);
+ }
}
void Node::operator delete( void* ptr )
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);
{
// 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() )
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 );
mParent = &parentNode;
mDepth = mParent->GetDepth() + 1u;
+
+ if( mTransformId != INVALID_TRANSFORM_ID )
+ {
+ mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
+ }
}
void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
mAttachment->DisconnectedFromSceneGraph();
}
+ if( mTransformId != INVALID_TRANSFORM_ID )
+ {
+ mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
+ }
}
} // namespace SceneGraph
#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
*/
const Vector3& GetParentOrigin() const
{
- return mParentOrigin.mValue;
+ return mParentOrigin.Get(0);
}
/**
*/
void SetParentOrigin(const Vector3& origin)
{
- mParentOrigin.mValue = origin;
- mParentOrigin.OnSet();
+ mParentOrigin.Set(0,origin );
}
/**
*/
const Vector3& GetAnchorPoint() const
{
- return mAnchorPoint.mValue;
+ return mAnchorPoint.Get(0);
}
/**
*/
void SetAnchorPoint(const Vector3& anchor)
{
- mAnchorPoint.mValue = anchor;
- mAnchorPoint.OnSet();
+ mAnchorPoint.Set(0, anchor );
}
/**
*/
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;
}
/**
*/
const Vector3& GetWorldPosition( BufferIndex bufferIndex ) const
{
- return mWorldPosition[bufferIndex];
+ return mWorldPosition.Get(bufferIndex);
}
/**
*/
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 );
}
}
*/
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 );
+ }
}
/**
*/
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;
}
/**
*/
const Quaternion& GetWorldOrientation( BufferIndex bufferIndex ) const
{
- return mWorldOrientation[bufferIndex];
+ return mWorldOrientation.Get(0);
}
/**
*/
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.
*/
const Vector3& GetWorldScale( BufferIndex bufferIndex ) const
{
- return mWorldScale[bufferIndex];
+ return mWorldScale.Get(0);
}
/**
*/
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.
*/
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.
*/
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);
}
/**
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.
*
*/
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:
/**
return GetWorldColor( bufferId );
}
- virtual const Vector3& GetRenderSize( unsigned int bufferId ) const
- {
- return GetSize( bufferId );
- }
-
public: // From UniformMapDataProvider
/**
* @copydoc UniformMapDataProvider::GetUniformMapChanged
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:
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
// 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 );
return false;
}
+ mCameraAttachment->Update( updateBufferIndex, *mCameraNode );
+
TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
return true;
}