/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
//EXTERNAL INCLUDES
#include <algorithm>
#include <cstring>
+#include <type_traits>
//INTERNAL INCLUDES
#include <dali/public-api/common/constants.h>
-#include <dali/public-api/common/compile-time-assert.h>
#include <dali/internal/common/math.h>
namespace Dali
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) );
+static const float gDefaultTransformComponentStaticData[] = { 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, true };
+
+static_assert( sizeof(gDefaultTransformComponentAnimatableData) == sizeof(TransformComponentAnimatable), "gDefaultTransformComponentAnimatableData should have the same number of floats as specified in TransformComponentAnimatable" );
+static_assert( sizeof(gDefaultTransformComponentStaticData) == sizeof(TransformComponentStatic), "gDefaultTransformComponentStaticData should have the same number of floats as specified in TransformComponentStatic" );
+
+/**
+ * @brief Calculates the center position for the transform component
+ * @param[out] centerPosition The calculated center-position of the transform component
+ * @param[in] transformComponentStatic A const reference to the static component transform struct
+ * @param[in] transformComponentAnimatable A const reference to the animatable component transform struct
+ * @param[in] size The size of the current transform component
+ * @param[in] half Halfway point of the transform
+ * @param[in] topLeft The top-left coords of the transform
+ */
+inline void CalculateCenterPosition(
+ Vector3& centerPosition,
+ const TransformComponentStatic& transformComponentStatic,
+ const TransformComponentAnimatable& transformComponentAnimatable,
+ const Vector3& size,
+ const Vector3& half,
+ const Vector3& topLeft )
+{
+ // Calculate the center-point by applying the scale and rotation on the anchor point.
+ centerPosition = ( half - transformComponentStatic.mAnchorPoint ) * size * transformComponentAnimatable.mScale;
+ centerPosition *= transformComponentAnimatable.mOrientation;
+
+ // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
+ if( ! transformComponentStatic.mPositionUsesAnchorPoint )
+ {
+ centerPosition -= ( topLeft - transformComponentStatic.mAnchorPoint ) * size;
+ }
}
+} // unnamed namespace
+
TransformManager::TransformManager()
:mComponentCount(0),
mReorder(false)
mSizeBase.PushBack(Vector3(0.0f,0.0f,0.0f));
mComponentDirty.PushBack(false);
mLocalMatrixDirty.PushBack(false);
+ mComponentChanged.PushBack(false);
+ mPrevWorld.PushBack(Matrix::IDENTITY);
+ mUpdateSizeHint.PushBack(Vector3(0.0f,0.0f,0.0f));
+ mUpdateSizeHintBase.PushBack(Vector3(0.0f,0.0f,0.0f));
}
else
{
mSizeBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
mComponentDirty[mComponentCount] = false;
mLocalMatrixDirty[mComponentCount] = false;
+ mComponentChanged[mComponentCount] = false;
+ mPrevWorld[mComponentCount].SetIdentity();
+ mUpdateSizeHint[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
+ mUpdateSizeHintBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
}
mComponentCount++;
{
//Move the last element to the gap
mComponentCount--;
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
mTxComponentAnimatable[index] = mTxComponentAnimatable[mComponentCount];
mTxComponentStatic[index] = mTxComponentStatic[mComponentCount];
mInheritanceMode[index] = mInheritanceMode[mComponentCount];
mComponentDirty[index] = mComponentDirty[mComponentCount];
mLocalMatrixDirty[index] = mLocalMatrixDirty[mComponentCount];
mBoundingSpheres[index] = mBoundingSpheres[mComponentCount];
+ mComponentChanged[index] = mComponentChanged[mComponentCount];
+ mPrevWorld[index] = mPrevWorld[mComponentCount];
+ mUpdateSizeHint[index] = mUpdateSizeHint[mComponentCount];
+ mUpdateSizeHintBase[index] = mUpdateSizeHintBase[mComponentCount];
TransformId lastItemId = mComponentId[mComponentCount];
mIds[ lastItemId ] = index;
void TransformManager::SetParent( TransformId id, TransformId parentId )
{
DALI_ASSERT_ALWAYS( id != parentId );
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
mParent[ index ] = parentId;
mComponentDirty[ index ] = true;
mReorder = true;
void TransformManager::SetInheritPosition( TransformId id, bool inherit )
{
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
if( inherit )
{
mInheritanceMode[ index ] |= INHERIT_POSITION;
void TransformManager::SetInheritScale( TransformId id, bool inherit )
{
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
if( inherit )
{
mInheritanceMode[ index ] |= INHERIT_SCALE;
void TransformManager::SetInheritOrientation( TransformId id, bool inherit )
{
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
if( inherit )
{
mInheritanceMode[ index ] |= INHERIT_ORIENTATION;
{
mInheritanceMode[ index ] &= ~INHERIT_ORIENTATION;
}
-
mComponentDirty[index] = true;
}
memcpy( &mTxComponentAnimatable[0], &mTxComponentAnimatableBaseValue[0], sizeof(TransformComponentAnimatable)*mComponentCount );
memcpy( &mSize[0], &mSizeBase[0], sizeof(Vector3)*mComponentCount );
memset( &mLocalMatrixDirty[0], false, sizeof(bool)*mComponentCount );
+ memcpy( &mUpdateSizeHint[0], &mUpdateSizeHintBase[0], sizeof(Vector3)*mComponentCount );
}
}
}
//Iterate through all components to compute its world matrix
- Vector3 anchorPosition;
+ Vector3 centerPosition;
Vector3 localPosition;
- Vector3 half( 0.5f,0.5f,0.5f );
+ const Vector3 half( 0.5f,0.5f,0.5f );
+ const Vector3 topLeft( 0.0f, 0.0f, 0.5f );
for( unsigned int i(0); i<mComponentCount; ++i )
{
+ mPrevWorld[i] = mWorld[i];
+
if( DALI_LIKELY( mInheritanceMode[i] != DONT_INHERIT_TRANSFORM && mParent[i] != INVALID_TRANSFORM_ID ) )
{
- const unsigned int& parentIndex = mIds[mParent[i] ];
+ const TransformId& parentIndex = mIds[mParent[i] ];
if( DALI_LIKELY( mInheritanceMode[i] == INHERIT_ALL ) )
{
if( mComponentDirty[i] || mLocalMatrixDirty[parentIndex])
{
//Full transform inherited
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 );
+ CalculateCenterPosition( centerPosition, mTxComponentStatic[ i ], mTxComponentAnimatable[ i ], mSize[ i ], half, topLeft );
+ localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + ( mTxComponentStatic[i].mParentOrigin - half ) * mSize[parentIndex];
+ mLocal[i].SetTransformComponents( mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition );
}
//Update the world matrix
if( (mInheritanceMode[i] & INHERIT_POSITION) == 0 )
{
//Don't inherit position
+ CalculateCenterPosition( centerPosition, mTxComponentStatic[ i ], mTxComponentAnimatable[ i ], mSize[ i ], half, topLeft );
mLocal[i].SetTransformComponents( localScale, localOrientation, Vector3::ZERO );
Matrix::Multiply( mWorld[i], mLocal[i], parentMatrix );
- mWorld[i].SetTranslation( mTxComponentAnimatable[i].mPosition);
+ mWorld[i].SetTranslation( mTxComponentAnimatable[i].mPosition + centerPosition );
}
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];
+ CalculateCenterPosition( centerPosition, mTxComponentStatic[ i ], mTxComponentAnimatable[ i ], mSize[ i ], half, topLeft );
+ localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + ( 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;
+ CalculateCenterPosition( centerPosition, mTxComponentStatic[ i ], mTxComponentAnimatable[ i ], mSize[ i ], half, topLeft );
+ localPosition = mTxComponentAnimatable[i].mPosition + centerPosition;
mLocal[i].SetTransformComponents( mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition );
mWorld[i] = mLocal[i];
mLocalMatrixDirty[i] = true;
mBoundingSpheres[i] = mWorld[i].GetTranslation();
mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace );
+ mComponentChanged[i] = false;
+
+ // Due to parent transformation child transformation could be changed
+ if( mComponentDirty[i] ||
+ mPrevWorld[i] != mWorld[i] )
+ {
+ mComponentChanged[i] = true;
+ }
+
mComponentDirty[i] = false;
+
}
}
std::swap( mLocal[i], mLocal[j] );
std::swap( mComponentDirty[i], mComponentDirty[j] );
std::swap( mBoundingSpheres[i], mBoundingSpheres[j] );
+ std::swap( mWorld[i], mWorld[j] );
+ std::swap( mComponentChanged[i], mComponentChanged[j] );
+ std::swap( mPrevWorld[i], mPrevWorld[j] );
+ std::swap( mUpdateSizeHint[i], mUpdateSizeHint[j] );
+ std::swap( mUpdateSizeHintBase[i], mUpdateSizeHintBase[j] );
mIds[ mComponentId[i] ] = i;
mIds[ mComponentId[j] ] = j;
mOrderedComponents.Resize(mComponentCount);
TransformId parentId;
- for( size_t i(0); i<mComponentCount; ++i )
+ for( TransformId i = 0; i<mComponentCount; ++i )
{
mOrderedComponents[i].id = mComponentId[i];
mOrderedComponents[i].level = 0u;
}
}
- std::sort( mOrderedComponents.Begin(), mOrderedComponents.End());
- for( size_t i(0); i<mComponentCount-1; ++i )
+ std::stable_sort( mOrderedComponents.Begin(), mOrderedComponents.End());
+ TransformId previousIndex = 0;
+ for( TransformId newIndex = 0; newIndex < mComponentCount-1; ++newIndex )
{
- SwapComponents( mIds[mOrderedComponents[i].id], i);
+ previousIndex = mIds[mOrderedComponents[newIndex].id];
+ if( previousIndex != newIndex )
+ {
+ SwapComponents( previousIndex, newIndex);
+ }
}
}
{
case TRANSFORM_PROPERTY_POSITION:
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mPosition;
}
case TRANSFORM_PROPERTY_SCALE:
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mScale;
}
case TRANSFORM_PROPERTY_PARENT_ORIGIN:
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mTxComponentStatic[ index ].mParentOrigin;
}
case TRANSFORM_PROPERTY_ANCHOR_POINT:
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mTxComponentStatic[ index ].mAnchorPoint;
}
case TRANSFORM_PROPERTY_SIZE:
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mSize[ index ];
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ TransformId index( mIds[id] );
+ mComponentDirty[ index ] = true;
+ return mUpdateSizeHint[ index ];
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
{
return mSize[ mIds[id] ];
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ return mUpdateSizeHint[ mIds[id] ];
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
{
return mSize[ mIds[id] ][component];
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ return mUpdateSizeHint[ mIds[id] ][component];
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::SetVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ] = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ 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] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ][component] = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ][component] = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ] = mSizeBase[index] = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeRelativeVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ] = mSizeBase[index] = mSize[ index ] + value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = mUpdateSizeHint[ index ] + value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeMultiplyVector3PropertyValue( TransformId id, TransformManagerProperty property, const Vector3& value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ] = mSizeBase[index] = mSize[ index ] * value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = mUpdateSizeHint[ 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] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ][component] = mSizeBase[index][component] = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ][component] = mUpdateSizeHintBase[index][component] = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeXVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ].x = mSizeBase[index].x = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ].x = mUpdateSizeHintBase[index].x = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeYVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ].y = mSizeBase[index].y = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ].y = mUpdateSizeHintBase[index].y = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManagerProperty property, float value )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
switch( property )
mSize[ index ].z = mSizeBase[index].z = value;
break;
}
+ case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+ {
+ mUpdateSizeHint[ index ].z = mUpdateSizeHintBase[index].z = value;
+ break;
+ }
default:
{
DALI_ASSERT_ALWAYS(false);
Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mComponentDirty[ index ] = true;
return mTxComponentAnimatable[ index ].mOrientation;
}
void TransformManager::SetQuaternionPropertyValue( TransformId id, const Quaternion& q )
{
- unsigned int index( mIds[id] );
+ TransformId index( mIds[id] );
mTxComponentAnimatable[ index ].mOrientation = q;
mComponentDirty[ index ] = true;
}
void TransformManager::BakeQuaternionPropertyValue( TransformId id, const Quaternion& q )
{
- unsigned int index( mIds[id] );
+ TransformId 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] );
+ TransformId index( mIds[id] );
mTxComponentAnimatable[ index ].mOrientation = mTxComponentAnimatableBaseValue[index].mOrientation = mTxComponentAnimatable[ index ].mOrientation * q;
mComponentDirty[ index ] = true;
}
return mBoundingSpheres[ mIds[id] ];
}
+bool TransformManager::IsComponentChanged( TransformId id )
+{
+ return mComponentChanged[ mIds[id]];
+}
+
void TransformManager::GetWorldMatrixAndSize( TransformId id, Matrix& worldMatrix, Vector3& size ) const
{
- unsigned int index = mIds[id];
+ TransformId index = mIds[id];
worldMatrix = mWorld[index];
size = mSize[index];
}
+const Vector3& TransformManager::GetUpdateSizeHint( TransformId id ) const
+{
+ return mUpdateSizeHint[ mIds[id] ];
+}
+
+void TransformManager::SetPositionUsesAnchorPoint( TransformId id, bool value )
+{
+ TransformId index( mIds[ id ] );
+ mComponentDirty[ index ] = true;
+ mTxComponentStatic[ index ].mPositionUsesAnchorPoint = value;
+}
+
} //namespace SceneGraph
} //namespace Internal
} //namespace Dali