X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-impl.cpp;h=d36e103eb351ce44e24db4f8b0f14fdaf1b3f107;hb=63a75802b362f787f4331567cbbc137b9ecde652;hp=a9eddf4bf03a07cce1535afe4381b1d099929d2d;hpb=7f980d4fce89b03e0b5f3fe7947fa7b6e840127c;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index a9eddf4..d36e103 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -57,6 +57,11 @@ using Dali::Internal::SceneGraph::Node; using Dali::Internal::SceneGraph::AnimatableProperty; using Dali::Internal::SceneGraph::PropertyBase; +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" ); +Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" ); +#endif + namespace Dali { @@ -87,32 +92,6 @@ inline const Vector2& GetDefaultDimensionPadding() const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET; -int GetSiblingOrder( ActorPtr actor ) -{ - Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER ); - int order; - value.Get( order ); - return order; -} - -bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target ) -{ - bool validTarget = true; - - if( &actor == &target ) - { - DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" ); - validTarget = false; - } - else if( actor.GetParent() != target.GetParent() ) - { - DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" ); - validTarget = false; - } - - return validTarget; -} - } // unnamed namespace /** @@ -127,6 +106,7 @@ struct Actor::RelayoutData for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { resizePolicies[ i ] = ResizePolicy::DEFAULT; + useAssignedSize[ i ] = false; negotiatedDimensions[ i ] = 0.0f; dimensionNegotiated[ i ] = false; dimensionDirty[ i ] = false; @@ -138,6 +118,7 @@ struct Actor::RelayoutData } ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies + bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies @@ -226,6 +207,8 @@ DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali: DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE ) DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION ) DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE ) +DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION ) +DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION ) DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER ) DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY ) DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION ) @@ -325,6 +308,10 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED ) DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN ) DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE ) +DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION ) +DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT ) +DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT ) +DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION ) bool GetAnchorPointConstant( const std::string& value, Vector3& anchor ) { @@ -385,9 +372,27 @@ float GetDimensionValue( const Vector3& values, Dimension::Type dimension ) return GetDimensionValue( values.GetVectorXY(), dimension ); } -unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder ) +/** + * @brief Recursively emits the visibility-changed-signal on the actor tree. + * @param[in] actor The actor to emit the signal on + * @param[in] visible The new visibility of the actor + * @param[in] type Whether the actor's visible property has changed or a parent's + */ +void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type ) { - return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER; + if( actor ) + { + actor->EmitVisibilityChangedSignal( visible, type ); + + if( actor->GetChildCount() > 0 ) + { + ActorContainer& children = actor->GetChildrenInternal(); + for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter ) + { + EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT ); + } + } + } } } // unnamed namespace @@ -489,6 +494,8 @@ void Actor::Add( Actor& child ) // Notification for derived classes OnChildAdd( child ); + InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection ); + // Only put in a relayout request if there is a suitable dependency if( RelayoutDependentOnChildren() ) { @@ -811,11 +818,10 @@ const Vector2 Actor::GetCurrentScreenPosition() const { StagePtr stage = Stage::GetCurrent(); Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); - Vector3 actorSize = GetCurrentSize() * GetCurrentScale(); + Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale(); Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage Vector3 halfActorSize( actorSize * 0.5f ); - // Anchor point offset first set to TOP_LEFT (0,0.5) then moved to required anchor point. - Vector3 anchorPointOffSet = halfActorSize - actorSize * GetCurrentAnchorPoint(); + Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT ); return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x, halfStageSize.height + worldPosition.y - anchorPointOffSet.y ); @@ -868,6 +874,8 @@ void Actor::SetOrientation( const Radian& angle, const Vector3& axis ) void Actor::SetOrientation( const Quaternion& orientation ) { + mTargetOrientation = orientation; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -877,15 +885,13 @@ void Actor::SetOrientation( const Quaternion& orientation ) void Actor::RotateBy( const Radian& angle, const Vector3& axis ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler::BakeRelative, Quaternion(angle, axis) ); - } + RotateBy( Quaternion(angle, axis) ); } void Actor::RotateBy( const Quaternion& relativeRotation ) { + mTargetOrientation *= Quaternion( relativeRotation ); + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -927,6 +933,8 @@ void Actor::SetScale( float x, float y, float z ) void Actor::SetScale( const Vector3& scale ) { + mTargetScale = scale; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -936,6 +944,8 @@ void Actor::SetScale( const Vector3& scale ) void Actor::SetScaleX( float x ) { + mTargetScale.x = x; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -945,6 +955,8 @@ void Actor::SetScaleX( float x ) void Actor::SetScaleY( float y ) { + mTargetScale.y = y; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -954,6 +966,8 @@ void Actor::SetScaleY( float y ) void Actor::SetScaleZ( float z ) { + mTargetScale.z = z; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -963,6 +977,8 @@ void Actor::SetScaleZ( float z ) void Actor::ScaleBy(const Vector3& relativeScale) { + mTargetScale *= relativeScale; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1021,11 +1037,7 @@ Matrix Actor::GetCurrentWorldMatrix() const void Actor::SetVisible( bool visible ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty::Bake, visible ); - } + SetVisibleInternal( visible, SendMessage::TRUE ); } bool Actor::IsVisible() const @@ -1041,6 +1053,8 @@ bool Actor::IsVisible() const void Actor::SetOpacity( float opacity ) { + mTargetColor.a = opacity; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1066,7 +1080,7 @@ ClippingMode::Type Actor::GetClippingMode() const unsigned int Actor::GetSortingDepth() { - return GetDepthIndex( mDepth, mSiblingOrder ); + return mSortedDepth; } const Vector4& Actor::GetCurrentWorldColor() const @@ -1081,6 +1095,8 @@ const Vector4& Actor::GetCurrentWorldColor() const void Actor::SetColor( const Vector4& color ) { + mTargetColor = color; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1090,6 +1106,8 @@ void Actor::SetColor( const Vector4& color ) void Actor::SetColorRed( float red ) { + mTargetColor.r = red; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1099,6 +1117,8 @@ void Actor::SetColorRed( float red ) void Actor::SetColorGreen( float green ) { + mTargetColor.g = green; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1108,6 +1128,8 @@ void Actor::SetColorGreen( float green ) void Actor::SetColorBlue( float blue ) { + mTargetColor.b = blue; + if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value @@ -1237,89 +1259,74 @@ void Actor::SetSizeInternal( const Vector3& size ) } } -void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize ) -{ - mTargetSize = targetSize; - - // Notify deriving classes - OnSizeAnimation( animation, mTargetSize ); -} - -void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property ) +void Actor::SetWidth( float width ) { - if ( Dali::Actor::Property::SIZE_WIDTH == property ) - { - mTargetSize.width = targetSize; - } - else if ( Dali::Actor::Property::SIZE_HEIGHT == property ) + if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout ) { - mTargetSize.height = targetSize; + SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH ); + mRelayoutData->preferredSize.width = width; } - else if ( Dali::Actor::Property::SIZE_DEPTH == property ) + else { - mTargetSize.depth = targetSize; + mTargetSize.width = width; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeX, width ); + } } - // Notify deriving classes - OnSizeAnimation( animation, mTargetSize ); -} -void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition ) -{ - mTargetPosition = targetPosition; + RelayoutRequest(); } -void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property ) +void Actor::SetHeight( float height ) { - if ( Dali::Actor::Property::POSITION_X == property ) - { - mTargetPosition.x = targetPosition; - } - else if ( Dali::Actor::Property::POSITION_Y == property ) + if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout ) { - mTargetPosition.y = targetPosition; + SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT ); + mRelayoutData->preferredSize.height = height; } - else if ( Dali::Actor::Property::POSITION_Z == property ) + else { - mTargetPosition.z = targetPosition; + mTargetSize.height = height; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeY, height ); + } } + + RelayoutRequest(); } -void Actor::SetWidth( float width ) +void Actor::SetDepth( float depth ) { - mTargetSize.width = width; + mTargetSize.depth = depth; if( NULL != mNode ) { // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeX, width ); + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeZ, depth ); } } -void Actor::SetHeight( float height ) +Vector3 Actor::GetTargetSize() const { - mTargetSize.height = height; + Vector3 size = mTargetSize; - if( NULL != mNode ) + // Should return preferred size if size is fixed as set by SetSize + if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED ) { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeY, height ); + size.width = GetPreferredSize().width; } -} - -void Actor::SetDepth( float depth ) -{ - mTargetSize.depth = depth; - - if( NULL != mNode ) + if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::BakeZ, depth ); + size.height = GetPreferredSize().height; } -} -const Vector3& Actor::GetTargetSize() const -{ - return mTargetSize; + return size; } const Vector3& Actor::GetCurrentSize() const @@ -1350,7 +1357,15 @@ void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimensio { if( dimension & ( 1 << i ) ) { - mRelayoutData->resizePolicies[ i ] = policy; + if ( policy == ResizePolicy::USE_ASSIGNED_SIZE ) + { + mRelayoutData->useAssignedSize[ i ] = true; + } + else + { + mRelayoutData->resizePolicies[ i ] = policy; + mRelayoutData->useAssignedSize[ i ] = false; + } } } @@ -1413,7 +1428,14 @@ ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const { if( ( dimension & ( 1 << i ) ) ) { - return mRelayoutData->resizePolicies[ i ]; + if( mRelayoutData->useAssignedSize[ i ] ) + { + return ResizePolicy::USE_ASSIGNED_SIZE; + } + else + { + return mRelayoutData->resizePolicies[ i ]; + } } } } @@ -1962,6 +1984,24 @@ bool Actor::EmitWheelEventSignal( const WheelEvent& event ) return consumed; } +void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type ) +{ + if( ! mVisibilityChangedSignal.Empty() ) + { + Dali::Actor handle( this ); + mVisibilityChangedSignal.Emit( handle, visible, type ); + } +} + +void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type ) +{ + if( ! mLayoutDirectionChangedSignal.Empty() ) + { + Dali::Actor handle( this ); + mLayoutDirectionChangedSignal.Emit( handle, type ); + } +} + Dali::Actor::TouchSignalType& Actor::TouchedSignal() { return mTouchedSignal; @@ -1997,6 +2037,16 @@ Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal() return mOnRelayoutSignal; } +DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal() +{ + return mVisibilityChangedSignal; +} + +Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal() +{ + return mLayoutDirectionChangedSignal; +} + bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { bool connected( true ); @@ -2048,11 +2098,15 @@ Actor::Actor( DerivedType derivedType ) mAnchorPoint( NULL ), mRelayoutData( NULL ), mGestureData( NULL ), - mTargetSize( 0.0f, 0.0f, 0.0f ), + mTargetOrientation( Quaternion::IDENTITY ), + mTargetColor( Color::WHITE ), + mTargetSize( Vector3::ZERO ), + mTargetPosition( Vector3::ZERO ), + mTargetScale( Vector3::ONE ), mName(), mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved + mSortedDepth( 0u ), mDepth( 0u ), - mSiblingOrder(0u), mIsRoot( ROOT_LAYER == derivedType ), mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ), mIsOnStage( false ), @@ -2068,6 +2122,9 @@ Actor::Actor( DerivedType derivedType ) mInheritOrientation( true ), mInheritScale( true ), mPositionUsesAnchorPoint( true ), + mVisible( true ), + mInheritLayoutDirection( true ), + mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), mColorMode( Node::DEFAULT_COLOR_MODE ), @@ -2077,11 +2134,10 @@ Actor::Actor( DerivedType derivedType ) void Actor::Initialize() { - // Node creation - SceneGraph::Node* node = CreateNode(); - - AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph - mNode = node; // Keep raw-pointer to Node + // Node creation, keep raw-pointer to Node for messaging + mNode = CreateNode(); + OwnerPointer< SceneGraph::Node > transferOwnership( const_cast< SceneGraph::Node* >( mNode ) ); + AddNodeMessage( GetEventThreadServices().GetUpdateManager(), transferOwnership ); OnInitialize(); @@ -2135,6 +2191,12 @@ void Actor::ConnectToStage( unsigned int parentDepth ) // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks. ActorContainer connectionList; + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + // This stage is atomic i.e. not interrupted by user callbacks. RecursiveConnectToStage( connectionList, parentDepth + 1 ); @@ -2154,7 +2216,6 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in mIsOnStage = true; mDepth = depth; - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); ConnectToSceneGraph(); @@ -2227,6 +2288,12 @@ void Actor::DisconnectFromStage() // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks. ActorContainer disconnectionList; + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + // This stage is atomic i.e. not interrupted by user callbacks RecursiveDisconnectFromStage( disconnectionList ); @@ -2312,6 +2379,44 @@ bool Actor::IsNodeConnected() const return connected; } +// This method initiates traversal of the actor tree using depth-first +// traversal to set a depth index based on traversal order. It sends a +// single message to update manager to update all the actor's nodes in +// this tree with the depth index. The sceneGraphNodeDepths vector's +// elements are ordered by depth, and could be used to reduce sorting +// in the update thread. +void Actor::RebuildDepthTree() +{ + DALI_LOG_TIMER_START(depthTimer); + + // Vector of scene-graph nodes and their depths to send to UpdateManager + // in a single message + OwnerPointer sceneGraphNodeDepths( new SceneGraph::NodeDepths() ); + + int depthIndex = 1; + DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex ); + + SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths ); + DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: "); +} + +void Actor::DepthTraverseActorTree( OwnerPointer& sceneGraphNodeDepths, int& depthIndex ) +{ + mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER; + sceneGraphNodeDepths->Add( const_cast( mNode ), mSortedDepth ); + + // Create/add to children of this node + if( mChildren ) + { + for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it ) + { + Actor* childActor = (*it).Get(); + ++depthIndex; + childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex ); + } + } +} + unsigned int Actor::GetDefaultPropertyCount() const { return DEFAULT_PROPERTY_COUNT; @@ -2745,10 +2850,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr if( property.Get( value ) ) { - if( static_cast(value) != mSiblingOrder ) - { - SetSiblingOrder( value ); - } + SetSiblingOrder( value ); } break; } @@ -2781,6 +2883,28 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } + case Dali::Actor::Property::LAYOUT_DIRECTION: + { + Dali::LayoutDirection::Type direction = mLayoutDirection; + mInheritLayoutDirection = false; + + if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) ) + { + InheritLayoutDirectionRecursively( this, direction, true ); + } + break; + } + + case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION: + { + bool value = false; + if( property.Get( value ) ) + { + SetInheritLayoutDirection( value ); + } + break; + } + default: { // this can happen in the case of a non-animatable default property so just do nothing @@ -2949,834 +3073,1281 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const { Property::Value value; - if( index >= DEFAULT_PROPERTY_COUNT ) + if( ! GetCachedPropertyValue( index, value ) ) { - return value; + // If property value is not stored in the event-side, then it must be a scene-graph only property + GetCurrentPropertyValue( index, value ); } - switch( index ) - { - case Dali::Actor::Property::PARENT_ORIGIN: - { - value = GetCurrentParentOrigin(); - break; - } + return value; +} - case Dali::Actor::Property::PARENT_ORIGIN_X: - { - value = GetCurrentParentOrigin().x; - break; - } +Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const +{ + Property::Value value; - case Dali::Actor::Property::PARENT_ORIGIN_Y: - { - value = GetCurrentParentOrigin().y; - break; - } + if( ! GetCurrentPropertyValue( index, value ) ) + { + // If unable to retrieve scene-graph property value, then it must be an event-side only property + GetCachedPropertyValue( index, value ); + } - case Dali::Actor::Property::PARENT_ORIGIN_Z: - { - value = GetCurrentParentOrigin().z; - break; - } + return value; +} - case Dali::Actor::Property::ANCHOR_POINT: +void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType ) +{ + switch( animationType ) + { + case Animation::TO: + case Animation::BETWEEN: { - value = GetCurrentAnchorPoint(); - break; - } + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + if( value.Get( mTargetSize ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } - case Dali::Actor::Property::ANCHOR_POINT_X: - { - value = GetCurrentAnchorPoint().x; - break; - } + case Dali::Actor::Property::SIZE_WIDTH: + { + if( value.Get( mTargetSize.width ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } - case Dali::Actor::Property::ANCHOR_POINT_Y: - { - value = GetCurrentAnchorPoint().y; - break; - } + case Dali::Actor::Property::SIZE_HEIGHT: + { + if( value.Get( mTargetSize.height ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } - case Dali::Actor::Property::ANCHOR_POINT_Z: - { - value = GetCurrentAnchorPoint().z; - break; - } + case Dali::Actor::Property::SIZE_DEPTH: + { + if( value.Get( mTargetSize.depth ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } - case Dali::Actor::Property::SIZE: - { - Vector3 size = GetTargetSize(); + case Dali::Actor::Property::POSITION: + { + value.Get( mTargetPosition ); + break; + } - // Should return preferred size if size is fixed as set by SetSize - if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED ) - { - size.width = GetPreferredSize().width; - } - if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) - { - size.height = GetPreferredSize().height; - } + case Dali::Actor::Property::POSITION_X: + { + value.Get( mTargetPosition.x ); + break; + } - value = size; + case Dali::Actor::Property::POSITION_Y: + { + value.Get( mTargetPosition.y ); + break; + } - break; - } + case Dali::Actor::Property::POSITION_Z: + { + value.Get( mTargetPosition.z ); + break; + } - case Dali::Actor::Property::SIZE_WIDTH: - { - if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED ) + case Dali::Actor::Property::ORIENTATION: + { + value.Get( mTargetOrientation ); + break; + } + + case Dali::Actor::Property::SCALE: + { + value.Get( mTargetScale ); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + value.Get( mTargetScale.x ); + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + value.Get( mTargetScale.y ); + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + value.Get( mTargetScale.z ); + break; + } + + case Dali::Actor::Property::VISIBLE: + { + SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE ); + break; + } + + case Dali::Actor::Property::COLOR: + { + value.Get( mTargetColor ); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + value.Get( mTargetColor.r ); + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + value.Get( mTargetColor.g ); + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + value.Get( mTargetColor.b ); + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value.Get( mTargetColor.a ); + break; + } + + default: + { + // Not an animatable property. Do nothing. + break; + } + } + break; + } + + case Animation::BY: + { + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + if( AdjustValue< Vector3 >( mTargetSize, value ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + if( AdjustValue< float >( mTargetSize.width, value ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + if( AdjustValue< float >( mTargetSize.height, value ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + if( AdjustValue< float >( mTargetSize.depth, value ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::POSITION: + { + AdjustValue< Vector3 >( mTargetPosition, value ); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + AdjustValue< float >( mTargetPosition.x, value ); + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + AdjustValue< float >( mTargetPosition.y, value ); + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + AdjustValue< float >( mTargetPosition.z, value ); + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + Quaternion relativeValue; + if( value.Get( relativeValue ) ) + { + mTargetOrientation *= relativeValue; + } + break; + } + + case Dali::Actor::Property::SCALE: + { + AdjustValue< Vector3 >( mTargetScale, value ); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + AdjustValue< float >( mTargetScale.x, value ); + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + AdjustValue< float >( mTargetScale.y, value ); + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + AdjustValue< float >( mTargetScale.z, value ); + break; + } + + case Dali::Actor::Property::VISIBLE: + { + bool relativeValue = false; + if( value.Get( relativeValue ) ) + { + bool visible = mVisible || relativeValue; + SetVisibleInternal( visible, SendMessage::FALSE ); + } + break; + } + + case Dali::Actor::Property::COLOR: + { + AdjustValue< Vector4 >( mTargetColor, value ); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + AdjustValue< float >( mTargetColor.r, value ); + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + AdjustValue< float >( mTargetColor.g, value ); + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + AdjustValue< float >( mTargetColor.b, value ); + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + AdjustValue< float >( mTargetColor.a, value ); + break; + } + + default: + { + // Not an animatable property. Do nothing. + break; + } + } + break; + } + } +} + +const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const +{ + return mNode; +} + +const SceneGraph::PropertyOwner* Actor::GetSceneObject() const +{ + // This method should only return an object connected to the scene-graph + return OnStage() ? mNode : NULL; +} + +const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const +{ + DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" ); + + const PropertyBase* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if( !OnStage() ) + { + return property; + } + + if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) + { + AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); + DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); + + property = animatable->GetSceneGraphProperty(); + } + else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties + ( index <= PROPERTY_CUSTOM_MAX_INDEX ) ) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); + + property = custom->GetSceneGraphProperty(); + } + else if( NULL != mNode ) + { + switch( index ) + { + case Dali::Actor::Property::SIZE: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_WIDTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_HEIGHT: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_DEPTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::POSITION: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_X: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Y: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Z: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::ORIENTATION: + property = &mNode->mOrientation; + break; + + case Dali::Actor::Property::SCALE: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_X: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Y: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Z: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::VISIBLE: + property = &mNode->mVisible; + break; + + case Dali::Actor::Property::COLOR: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_RED: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_GREEN: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_BLUE: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + property = &mNode->mColor; + break; + + default: + break; + } + } + + return property; +} + +const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const +{ + const PropertyInputImpl* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if( !OnStage() ) + { + return property; + } + + if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) + { + AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); + DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); + + property = animatable->GetSceneGraphProperty(); + } + else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties + ( index <= PROPERTY_CUSTOM_MAX_INDEX ) ) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); + property = custom->GetSceneGraphProperty(); + } + else if( NULL != mNode ) + { + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_X: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::ANCHOR_POINT: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_X: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_Y: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_Z: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::SIZE: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_WIDTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_HEIGHT: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_DEPTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::POSITION: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_X: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Y: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Z: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_X: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_Y: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_Z: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::ORIENTATION: + property = &mNode->mOrientation; + break; + + case Dali::Actor::Property::WORLD_ORIENTATION: + property = &mNode->mWorldOrientation; + break; + + case Dali::Actor::Property::SCALE: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_X: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Y: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Z: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::WORLD_SCALE: + property = &mNode->mWorldScale; + break; + + case Dali::Actor::Property::VISIBLE: + property = &mNode->mVisible; + break; + + case Dali::Actor::Property::COLOR: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_RED: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_GREEN: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_BLUE: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + property = &mNode->mColor; + break; + } + + case Dali::Actor::Property::WORLD_COLOR: + property = &mNode->mWorldColor; + break; + + case Dali::Actor::Property::WORLD_MATRIX: + property = &mNode->mWorldMatrix; + break; + + default: + break; + } + } + + return property; +} + +int Actor::GetPropertyComponentIndex( Property::Index index ) const +{ + int componentIndex( Property::INVALID_COMPONENT_INDEX ); + + if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index); + if( animatableProperty ) + { + componentIndex = animatableProperty->componentIndex; + } + } + else + { + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN_X: + case Dali::Actor::Property::ANCHOR_POINT_X: + case Dali::Actor::Property::SIZE_WIDTH: + case Dali::Actor::Property::POSITION_X: + case Dali::Actor::Property::WORLD_POSITION_X: + case Dali::Actor::Property::SCALE_X: + case Dali::Actor::Property::COLOR_RED: { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().width; + componentIndex = 0; + break; } - else + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + case Dali::Actor::Property::ANCHOR_POINT_Y: + case Dali::Actor::Property::SIZE_HEIGHT: + case Dali::Actor::Property::POSITION_Y: + case Dali::Actor::Property::WORLD_POSITION_Y: + case Dali::Actor::Property::SCALE_Y: + case Dali::Actor::Property::COLOR_GREEN: { - value = GetTargetSize().width; + componentIndex = 1; + break; } - break; - } - case Dali::Actor::Property::SIZE_HEIGHT: - { - if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) + case Dali::Actor::Property::PARENT_ORIGIN_Z: + case Dali::Actor::Property::ANCHOR_POINT_Z: + case Dali::Actor::Property::SIZE_DEPTH: + case Dali::Actor::Property::POSITION_Z: + case Dali::Actor::Property::WORLD_POSITION_Z: + case Dali::Actor::Property::SCALE_Z: + case Dali::Actor::Property::COLOR_BLUE: { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().height; + componentIndex = 2; + break; } - else + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { - value = GetTargetSize().height; + componentIndex = 3; + break; } - break; - } - case Dali::Actor::Property::SIZE_DEPTH: - { - value = GetTargetSize().depth; - break; + default: + { + // Do nothing + break; + } } + } - case Dali::Actor::Property::POSITION: - { - value = GetTargetPosition(); - break; - } + return componentIndex; +} - case Dali::Actor::Property::POSITION_X: +void Actor::SetParent( Actor* parent ) +{ + if( parent ) + { + DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" ); + + mParent = parent; + + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + parent->OnStage() ) { - value = GetTargetPosition().x; - break; + // Instruct each actor to create a corresponding node in the scene graph + ConnectToStage( parent->GetHierarchyDepth() ); } - case Dali::Actor::Property::POSITION_Y: + // Resolve the name and index for the child properties if any + ResolveChildProperties(); + } + else // parent being set to NULL + { + DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" ); + + mParent = NULL; + + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + OnStage() ) { - value = GetTargetPosition().y; - break; + DALI_ASSERT_ALWAYS( mNode != NULL ); + + if( NULL != mNode ) + { + // Disconnect the Node & its children from the scene-graph. + DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); + } + + // Instruct each actor to discard pointers to the scene-graph + DisconnectFromStage(); } + } +} - case Dali::Actor::Property::POSITION_Z: +SceneGraph::Node* Actor::CreateNode() const +{ + return Node::New(); +} + +bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ ) +{ + bool done = false; + Actor* actor = dynamic_cast< Actor* >( object ); + + if( actor ) + { + if( 0 == actionName.compare( ACTION_SHOW ) ) { - value = GetTargetPosition().z; - break; + actor->SetVisible( true ); + done = true; } - - case Dali::Actor::Property::WORLD_POSITION: + else if( 0 == actionName.compare( ACTION_HIDE ) ) { - value = GetCurrentWorldPosition(); - break; + actor->SetVisible( false ); + done = true; } + } - case Dali::Actor::Property::WORLD_POSITION_X: + return done; +} + +bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; + + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: { - value = GetCurrentWorldPosition().x; + value = GetCurrentParentOrigin(); break; } - case Dali::Actor::Property::WORLD_POSITION_Y: + case Dali::Actor::Property::PARENT_ORIGIN_X: { - value = GetCurrentWorldPosition().y; + value = GetCurrentParentOrigin().x; break; } - case Dali::Actor::Property::WORLD_POSITION_Z: + case Dali::Actor::Property::PARENT_ORIGIN_Y: { - value = GetCurrentWorldPosition().z; + value = GetCurrentParentOrigin().y; break; } - case Dali::Actor::Property::ORIENTATION: + case Dali::Actor::Property::PARENT_ORIGIN_Z: { - value = GetCurrentOrientation(); + value = GetCurrentParentOrigin().z; break; } - case Dali::Actor::Property::WORLD_ORIENTATION: + case Dali::Actor::Property::ANCHOR_POINT: { - value = GetCurrentWorldOrientation(); + value = GetCurrentAnchorPoint(); break; } - case Dali::Actor::Property::SCALE: + case Dali::Actor::Property::ANCHOR_POINT_X: { - value = GetCurrentScale(); + value = GetCurrentAnchorPoint().x; break; } - case Dali::Actor::Property::SCALE_X: + case Dali::Actor::Property::ANCHOR_POINT_Y: { - value = GetCurrentScale().x; + value = GetCurrentAnchorPoint().y; break; } - case Dali::Actor::Property::SCALE_Y: + case Dali::Actor::Property::ANCHOR_POINT_Z: { - value = GetCurrentScale().y; + value = GetCurrentAnchorPoint().z; break; } - case Dali::Actor::Property::SCALE_Z: + case Dali::Actor::Property::SIZE: { - value = GetCurrentScale().z; + value = GetTargetSize(); break; } - case Dali::Actor::Property::WORLD_SCALE: + case Dali::Actor::Property::SIZE_WIDTH: { - value = GetCurrentWorldScale(); + value = GetTargetSize().width; break; } - case Dali::Actor::Property::VISIBLE: + case Dali::Actor::Property::SIZE_HEIGHT: { - value = IsVisible(); + value = GetTargetSize().height; break; } - case Dali::Actor::Property::COLOR: + case Dali::Actor::Property::SIZE_DEPTH: { - value = GetCurrentColor(); + value = GetTargetSize().depth; break; } - case Dali::Actor::Property::COLOR_RED: + case Dali::Actor::Property::POSITION: { - value = GetCurrentColor().r; + value = GetTargetPosition(); break; } - case Dali::Actor::Property::COLOR_GREEN: + case Dali::Actor::Property::POSITION_X: { - value = GetCurrentColor().g; + value = GetTargetPosition().x; break; } - case Dali::Actor::Property::COLOR_BLUE: + case Dali::Actor::Property::POSITION_Y: { - value = GetCurrentColor().b; + value = GetTargetPosition().y; break; } - case Dali::Actor::Property::COLOR_ALPHA: - case Dali::DevelActor::Property::OPACITY: + case Dali::Actor::Property::POSITION_Z: { - value = GetCurrentColor().a; + value = GetTargetPosition().z; break; } - case Dali::Actor::Property::WORLD_COLOR: + case Dali::Actor::Property::ORIENTATION: { - value = GetCurrentWorldColor(); + value = mTargetOrientation; break; } - case Dali::Actor::Property::WORLD_MATRIX: + case Dali::Actor::Property::SCALE: { - value = GetCurrentWorldMatrix(); + value = mTargetScale; break; } - case Dali::Actor::Property::NAME: + case Dali::Actor::Property::SCALE_X: { - value = GetName(); + value = mTargetScale.x; break; } - case Dali::Actor::Property::SENSITIVE: + case Dali::Actor::Property::SCALE_Y: { - value = IsSensitive(); + value = mTargetScale.y; break; } - case Dali::Actor::Property::LEAVE_REQUIRED: + case Dali::Actor::Property::SCALE_Z: { - value = GetLeaveRequired(); + value = mTargetScale.z; break; } - case Dali::Actor::Property::INHERIT_POSITION: + case Dali::Actor::Property::VISIBLE: { - value = IsPositionInherited(); + value = mVisible; break; } - case Dali::Actor::Property::INHERIT_ORIENTATION: + case Dali::Actor::Property::COLOR: { - value = IsOrientationInherited(); + value = mTargetColor; break; } - case Dali::Actor::Property::INHERIT_SCALE: + case Dali::Actor::Property::COLOR_RED: { - value = IsScaleInherited(); + value = mTargetColor.r; break; } - case Dali::Actor::Property::COLOR_MODE: + case Dali::Actor::Property::COLOR_GREEN: { - value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); + value = mTargetColor.g; break; } - case Dali::Actor::Property::POSITION_INHERITANCE: + case Dali::Actor::Property::COLOR_BLUE: { - value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); + value = mTargetColor.b; break; } - case Dali::Actor::Property::DRAW_MODE: + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { - value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); + value = mTargetColor.a; break; } - case Dali::Actor::Property::SIZE_MODE_FACTOR: + case Dali::Actor::Property::NAME: { - value = GetSizeModeFactor(); + value = GetName(); break; } - case Dali::Actor::Property::WIDTH_RESIZE_POLICY: + case Dali::Actor::Property::SENSITIVE: { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); + value = IsSensitive(); break; } - case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: + case Dali::Actor::Property::LEAVE_REQUIRED: { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); + value = GetLeaveRequired(); break; } - case Dali::Actor::Property::SIZE_SCALE_POLICY: + case Dali::Actor::Property::INHERIT_POSITION: { - value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT ); + value = IsPositionInherited(); break; } - case Dali::Actor::Property::WIDTH_FOR_HEIGHT: + case Dali::Actor::Property::INHERIT_ORIENTATION: { - value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); + value = IsOrientationInherited(); break; } - case Dali::Actor::Property::HEIGHT_FOR_WIDTH: + case Dali::Actor::Property::INHERIT_SCALE: { - value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH ); + value = IsScaleInherited(); break; } - case Dali::Actor::Property::PADDING: + case Dali::Actor::Property::COLOR_MODE: { - Vector2 widthPadding = GetPadding( Dimension::WIDTH ); - Vector2 heightPadding = GetPadding( Dimension::HEIGHT ); - value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y ); + value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); break; } - case Dali::Actor::Property::MINIMUM_SIZE: + case Dali::Actor::Property::POSITION_INHERITANCE: { - value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); + value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); break; } - case Dali::Actor::Property::MAXIMUM_SIZE: + case Dali::Actor::Property::DRAW_MODE: { - value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); break; } - case Dali::DevelActor::Property::SIBLING_ORDER: + case Dali::Actor::Property::SIZE_MODE_FACTOR: { - value = static_cast(mSiblingOrder); + value = GetSizeModeFactor(); break; } - case Dali::Actor::Property::CLIPPING_MODE: + case Dali::Actor::Property::WIDTH_RESIZE_POLICY: { - value = mClippingMode; + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); break; } - case Dali::DevelActor::Property::SCREEN_POSITION: + case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: { - value = GetCurrentScreenPosition(); + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); break; } - case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + case Dali::Actor::Property::SIZE_SCALE_POLICY: { - value = mPositionUsesAnchorPoint; + value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT ); break; } - } - - return value; -} - -const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const -{ - return mNode; -} - -const SceneGraph::PropertyOwner* Actor::GetSceneObject() const -{ - // This method should only return an object connected to the scene-graph - return OnStage() ? mNode : NULL; -} - -const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const -{ - DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" ); - - const PropertyBase* property( NULL ); - - // This method should only return a property of an object connected to the scene-graph - if( !OnStage() ) - { - return property; - } - - if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) - { - AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); - DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); - - property = animatable->GetSceneGraphProperty(); - } - else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties - ( index <= PROPERTY_CUSTOM_MAX_INDEX ) ) - { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); - property = custom->GetSceneGraphProperty(); - } - else if( NULL != mNode ) - { - switch( index ) + case Dali::Actor::Property::WIDTH_FOR_HEIGHT: { - case Dali::Actor::Property::SIZE: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_WIDTH: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_HEIGHT: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_DEPTH: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::POSITION: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_X: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_Y: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_Z: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::ORIENTATION: - property = &mNode->mOrientation; - break; - - case Dali::Actor::Property::SCALE: - property = &mNode->mScale; - break; - - case Dali::Actor::Property::SCALE_X: - property = &mNode->mScale; - break; - - case Dali::Actor::Property::SCALE_Y: - property = &mNode->mScale; - break; - - case Dali::Actor::Property::SCALE_Z: - property = &mNode->mScale; - break; - - case Dali::Actor::Property::VISIBLE: - property = &mNode->mVisible; - break; - - case Dali::Actor::Property::COLOR: - property = &mNode->mColor; - break; - - case Dali::Actor::Property::COLOR_RED: - property = &mNode->mColor; - break; - - case Dali::Actor::Property::COLOR_GREEN: - property = &mNode->mColor; - break; - - case Dali::Actor::Property::COLOR_BLUE: - property = &mNode->mColor; - break; - - case Dali::Actor::Property::COLOR_ALPHA: - case Dali::DevelActor::Property::OPACITY: - property = &mNode->mColor; - break; - - default: - break; + value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); + break; } - } - - return property; -} - -const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const -{ - const PropertyInputImpl* property( NULL ); - - // This method should only return a property of an object connected to the scene-graph - if( !OnStage() ) - { - return property; - } - - if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) - { - AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); - DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); - - property = animatable->GetSceneGraphProperty(); - } - else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties - ( index <= PROPERTY_CUSTOM_MAX_INDEX ) ) - { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); - property = custom->GetSceneGraphProperty(); - } - else if( NULL != mNode ) - { - switch( index ) - { - case Dali::Actor::Property::PARENT_ORIGIN: - property = &mNode->mParentOrigin; - break; - - case Dali::Actor::Property::PARENT_ORIGIN_X: - property = &mNode->mParentOrigin; - break; - - case Dali::Actor::Property::PARENT_ORIGIN_Y: - property = &mNode->mParentOrigin; - break; - - case Dali::Actor::Property::PARENT_ORIGIN_Z: - property = &mNode->mParentOrigin; - break; - - case Dali::Actor::Property::ANCHOR_POINT: - property = &mNode->mAnchorPoint; - break; - - case Dali::Actor::Property::ANCHOR_POINT_X: - property = &mNode->mAnchorPoint; - break; - - case Dali::Actor::Property::ANCHOR_POINT_Y: - property = &mNode->mAnchorPoint; - break; - - case Dali::Actor::Property::ANCHOR_POINT_Z: - property = &mNode->mAnchorPoint; - break; - - case Dali::Actor::Property::SIZE: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_WIDTH: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_HEIGHT: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::SIZE_DEPTH: - property = &mNode->mSize; - break; - - case Dali::Actor::Property::POSITION: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_X: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_Y: - property = &mNode->mPosition; - break; - - case Dali::Actor::Property::POSITION_Z: - property = &mNode->mPosition; - break; - case Dali::Actor::Property::WORLD_POSITION: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::HEIGHT_FOR_WIDTH: + { + value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_X: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::PADDING: + { + Vector2 widthPadding = GetPadding( Dimension::WIDTH ); + Vector2 heightPadding = GetPadding( Dimension::HEIGHT ); + value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_Y: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::MINIMUM_SIZE: + { + value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_Z: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::MAXIMUM_SIZE: + { + value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + break; + } - case Dali::Actor::Property::ORIENTATION: - property = &mNode->mOrientation; - break; + case Dali::Actor::Property::CLIPPING_MODE: + { + value = mClippingMode; + break; + } - case Dali::Actor::Property::WORLD_ORIENTATION: - property = &mNode->mWorldOrientation; - break; + case Dali::DevelActor::Property::SIBLING_ORDER: + { + value = static_cast( GetSiblingOrder() ); + break; + } - case Dali::Actor::Property::SCALE: - property = &mNode->mScale; - break; + case Dali::DevelActor::Property::SCREEN_POSITION: + { + value = GetCurrentScreenPosition(); + break; + } - case Dali::Actor::Property::SCALE_X: - property = &mNode->mScale; - break; + case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + { + value = mPositionUsesAnchorPoint; + break; + } - case Dali::Actor::Property::SCALE_Y: - property = &mNode->mScale; - break; + case Dali::Actor::Property::LAYOUT_DIRECTION: + { + value = mLayoutDirection; + break; + } - case Dali::Actor::Property::SCALE_Z: - property = &mNode->mScale; - break; + case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION: + { + value = IsLayoutDirectionInherited(); + break; + } - case Dali::Actor::Property::WORLD_SCALE: - property = &mNode->mWorldScale; - break; + default: + { + // Must be a scene-graph only property + valueSet = false; + break; + } + } - case Dali::Actor::Property::VISIBLE: - property = &mNode->mVisible; - break; + return valueSet; +} - case Dali::Actor::Property::COLOR: - property = &mNode->mColor; - break; +bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; - case Dali::Actor::Property::COLOR_RED: - property = &mNode->mColor; - break; + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + value = GetCurrentSize(); + break; + } - case Dali::Actor::Property::COLOR_GREEN: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetCurrentSize().width; + break; + } - case Dali::Actor::Property::COLOR_BLUE: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetCurrentSize().height; + break; + } - case Dali::Actor::Property::COLOR_ALPHA: - case Dali::DevelActor::Property::OPACITY: - { - property = &mNode->mColor; - break; - } + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetCurrentSize().depth; + break; + } - case Dali::Actor::Property::WORLD_COLOR: - property = &mNode->mWorldColor; - break; + case Dali::Actor::Property::POSITION: + { + value = GetCurrentPosition(); + break; + } - case Dali::Actor::Property::WORLD_MATRIX: - property = &mNode->mWorldMatrix; - break; + case Dali::Actor::Property::POSITION_X: + { + value = GetCurrentPosition().x; + break; + } - default: - break; + case Dali::Actor::Property::POSITION_Y: + { + value = GetCurrentPosition().y; + break; } - } - return property; -} + case Dali::Actor::Property::POSITION_Z: + { + value = GetCurrentPosition().z; + break; + } -int Actor::GetPropertyComponentIndex( Property::Index index ) const -{ - int componentIndex( Property::INVALID_COMPONENT_INDEX ); + case Dali::Actor::Property::WORLD_POSITION: + { + value = GetCurrentWorldPosition(); + break; + } - if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) - { - // check whether the animatable property is registered already, if not then register one. - AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index); - if( animatableProperty ) + case Dali::Actor::Property::WORLD_POSITION_X: { - componentIndex = animatableProperty->componentIndex; + value = GetCurrentWorldPosition().x; + break; } - } - else - { - switch( index ) + + case Dali::Actor::Property::WORLD_POSITION_Y: { - case Dali::Actor::Property::PARENT_ORIGIN_X: - case Dali::Actor::Property::ANCHOR_POINT_X: - case Dali::Actor::Property::SIZE_WIDTH: - case Dali::Actor::Property::POSITION_X: - case Dali::Actor::Property::WORLD_POSITION_X: - case Dali::Actor::Property::SCALE_X: - case Dali::Actor::Property::COLOR_RED: - { - componentIndex = 0; - break; - } + value = GetCurrentWorldPosition().y; + break; + } - case Dali::Actor::Property::PARENT_ORIGIN_Y: - case Dali::Actor::Property::ANCHOR_POINT_Y: - case Dali::Actor::Property::SIZE_HEIGHT: - case Dali::Actor::Property::POSITION_Y: - case Dali::Actor::Property::WORLD_POSITION_Y: - case Dali::Actor::Property::SCALE_Y: - case Dali::Actor::Property::COLOR_GREEN: - { - componentIndex = 1; - break; - } + case Dali::Actor::Property::WORLD_POSITION_Z: + { + value = GetCurrentWorldPosition().z; + break; + } - case Dali::Actor::Property::PARENT_ORIGIN_Z: - case Dali::Actor::Property::ANCHOR_POINT_Z: - case Dali::Actor::Property::SIZE_DEPTH: - case Dali::Actor::Property::POSITION_Z: - case Dali::Actor::Property::WORLD_POSITION_Z: - case Dali::Actor::Property::SCALE_Z: - case Dali::Actor::Property::COLOR_BLUE: - { - componentIndex = 2; - break; - } + case Dali::Actor::Property::ORIENTATION: + { + value = GetCurrentOrientation(); + break; + } - case Dali::Actor::Property::COLOR_ALPHA: - case Dali::DevelActor::Property::OPACITY: - { - componentIndex = 3; - break; - } + case Dali::Actor::Property::WORLD_ORIENTATION: + { + value = GetCurrentWorldOrientation(); + break; + } - default: - { - // Do nothing - break; - } + case Dali::Actor::Property::SCALE: + { + value = GetCurrentScale(); + break; } - } - return componentIndex; -} + case Dali::Actor::Property::SCALE_X: + { + value = GetCurrentScale().x; + break; + } -void Actor::SetParent( Actor* parent ) -{ - if( parent ) - { - DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" ); + case Dali::Actor::Property::SCALE_Y: + { + value = GetCurrentScale().y; + break; + } - mParent = parent; + case Dali::Actor::Property::SCALE_Z: + { + value = GetCurrentScale().z; + break; + } - if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction - parent->OnStage() ) + case Dali::Actor::Property::WORLD_SCALE: { - // Instruct each actor to create a corresponding node in the scene graph - ConnectToStage( parent->GetHierarchyDepth() ); + value = GetCurrentWorldScale(); + break; } - // Resolve the name and index for the child properties if any - ResolveChildProperties(); - } - else // parent being set to NULL - { - DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" ); + case Dali::Actor::Property::COLOR: + { + value = GetCurrentColor(); + break; + } - mParent = NULL; + case Dali::Actor::Property::COLOR_RED: + { + value = GetCurrentColor().r; + break; + } - if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction - OnStage() ) + case Dali::Actor::Property::COLOR_GREEN: { - DALI_ASSERT_ALWAYS( mNode != NULL ); + value = GetCurrentColor().g; + break; + } - if( NULL != mNode ) - { - // Disconnect the Node & its children from the scene-graph. - DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); - } + case Dali::Actor::Property::COLOR_BLUE: + { + value = GetCurrentColor().b; + break; + } - // Instruct each actor to discard pointers to the scene-graph - DisconnectFromStage(); + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value = GetCurrentColor().a; + break; } - } -} -SceneGraph::Node* Actor::CreateNode() const -{ - return Node::New(); -} + case Dali::Actor::Property::WORLD_COLOR: + { + value = GetCurrentWorldColor(); + break; + } -bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ ) -{ - bool done = false; - Actor* actor = dynamic_cast< Actor* >( object ); + case Dali::Actor::Property::WORLD_MATRIX: + { + value = GetCurrentWorldMatrix(); + break; + } - if( actor ) - { - if( 0 == actionName.compare( ACTION_SHOW ) ) + case Dali::Actor::Property::VISIBLE: { - actor->SetVisible( true ); - done = true; + value = IsVisible(); + break; } - else if( 0 == actionName.compare( ACTION_HIDE ) ) + + default: { - actor->SetVisible( false ); - done = true; + // Must be an event-side only property + valueSet = false; + break; } } - return done; + return valueSet; } void Actor::EnsureRelayoutData() @@ -4062,7 +4633,7 @@ float Actor::NegotiateFromChildren( Dimension::Type dimension ) float Actor::GetSize( Dimension::Type dimension ) const { - return GetDimensionValue( GetTargetSize(), dimension ); + return GetDimensionValue( mTargetSize, dimension ); } float Actor::GetNaturalSize( Dimension::Type dimension ) const @@ -4228,7 +4799,7 @@ void Actor::NegotiateDimensions( const Vector2& allocatedSize ) } } -Vector2 Actor::ApplySizeSetPolicy( const Vector2 size ) +Vector2 Actor::ApplySizeSetPolicy( const Vector2& size ) { switch( mRelayoutData->sizeSetPolicy ) { @@ -4332,13 +4903,15 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont // relayout container afterwards, the dirty flags would still be clear... // causing a relayout to be skipped. Here we force any actors added to the // container to be relayed out. - if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE) + DALI_LOG_TIMER_START( NegSizeTimer1 ); + + if( GetUseAssignedSize(Dimension::WIDTH ) ) { - SetLayoutNegotiated(false, Dimension::WIDTH); + SetLayoutNegotiated( false, Dimension::WIDTH ); } - if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE) + if( GetUseAssignedSize( Dimension::HEIGHT ) ) { - SetLayoutNegotiated(false, Dimension::HEIGHT); + SetLayoutNegotiated( false, Dimension::HEIGHT ); } // Do the negotiation @@ -4348,20 +4921,19 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont SetNegotiatedSize( container ); // Negotiate down to children - const Vector2 newBounds = GetTargetSize().GetVectorXY(); - for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) { ActorPtr child = GetChildAt( i ); // Forces children that have already been laid out to be relayed out // if they have assigned size during relayout. - if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE) + if( child->GetUseAssignedSize(Dimension::WIDTH) ) { child->SetLayoutNegotiated(false, Dimension::WIDTH); child->SetLayoutDirty(true, Dimension::WIDTH); } - if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE) + + if( child->GetUseAssignedSize(Dimension::HEIGHT) ) { child->SetLayoutNegotiated(false, Dimension::HEIGHT); child->SetLayoutDirty(true, Dimension::HEIGHT); @@ -4370,9 +4942,41 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont // Only relayout if required if( child->RelayoutRequired() ) { - container.Add( Dali::Actor( child.Get() ), newBounds ); + container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() ); + } + } + DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: "); +} + +void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension ) +{ + if( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->useAssignedSize[ i ] = use; + } + } + } +} + +bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->useAssignedSize[ i ]; + } } } + + return false; } void Actor::RelayoutRequest( Dimension::Type dimension ) @@ -4489,189 +5093,107 @@ Object* Actor::GetParentObject() const return mParent; } -void Actor::SetSiblingOrder( unsigned int order ) +void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) { - mSiblingOrder = std::min( order, static_cast( DevelLayer::SIBLING_ORDER_MULTIPLIER ) ); - if( mIsOnStage ) + if( mVisible != visible ) { - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); - } -} - -void Actor::DefragmentSiblingIndexes( ActorContainer& siblings ) -{ - // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER ) - // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range. - - // Start at index 0, while index <= highest order - // Find next index higher than 0 - // if nextHigher > index+1 - // set all nextHigher orders to index+1 + if( sendMessage == SendMessage::TRUE && NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty::Bake, visible ); + } - // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling. + mVisible = visible; - ActorIter end = siblings.end(); - int highestOrder = 0; - for( ActorIter iter = siblings.begin(); iter != end; ++iter ) - { - ActorPtr sibling = (*iter); - int siblingOrder = sibling->mSiblingOrder; - highestOrder = std::max( highestOrder, siblingOrder ); + // Emit the signal on this actor and all its children + EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF ); } +} - for ( int index = 0; index <= highestOrder; index++ ) +void Actor::SetSiblingOrder( unsigned int order ) +{ + if ( mParent ) { - int nextHighest = -1; + ActorContainer& siblings = *(mParent->mChildren); + unsigned int currentOrder = GetSiblingOrder(); - // Find Next highest - for( ActorIter iter = siblings.begin(); iter != end; ++iter ) + if( order != currentOrder ) { - ActorPtr sibling = (*iter); - int siblingOrder = sibling->mSiblingOrder; - - if ( siblingOrder > index ) + if( order == 0 ) + { + LowerToBottom(); + } + else if( order < siblings.size() -1 ) { - if ( nextHighest == -1 ) + if( order > currentOrder ) + { + RaiseAbove( *siblings[order] ); + } + else { - nextHighest = siblingOrder; + LowerBelow( *siblings[order] ); } - nextHighest = std::min( nextHighest, siblingOrder ); + } + else + { + RaiseToTop(); } } + } +} + +unsigned int Actor::GetSiblingOrder() const +{ + unsigned int order = 0; - // Check if a gap exists between indexes, if so set next index to consecutive number - if ( ( nextHighest - index ) > 1 ) + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + for( size_t i=0; imSiblingOrder; - if ( siblingOrder == nextHighest ) - { - sibling->mSiblingOrder = index + 1; - if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER ) - { - DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" ); - sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER; - } - sibling->SetSiblingOrder( sibling->mSiblingOrder ); - } + order = i; + break; } } } + + return order; } -bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom ) +void Actor::RequestRebuildDepthTree() { - // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1 - bool defragmentationRequired( false ); - ActorIter end = siblings.end(); - for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter ) + if( mIsOnStage ) { - // Move actors at nearest order and above up by 1 - ActorPtr sibling = (*iter); - if ( sibling != this ) + StagePtr stage = Stage::GetCurrent(); + if( stage ) { - // Iterate through container of actors, any actor with a sibling order of the target or greater should - // be incremented by 1. - if ( sibling->mSiblingOrder >= targetLevelToShiftFrom ) - { - sibling->mSiblingOrder++; - if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER ) - { - // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so - // can re-order all sibling orders. - defragmentationRequired = true; - } - sibling->SetSiblingOrder( sibling->mSiblingOrder ); - } + stage->RequestRebuildDepthTree(); } } - return defragmentationRequired; } void Actor::Raise() { - /* - 1) Check if already at top and nothing to be done. - This Actor can have highest sibling order but if not exclusive then another actor at same sibling - order can be positioned above it due to insertion order of actors. - 2) Find nearest sibling level above, these are the siblings this actor needs to be above - 3) a) There may be other levels above this target level - b) Increment all sibling levels at the level above nearest(target) - c) Now have a vacant sibling level - 4) Set this actor's sibling level to nearest +1 as now vacated. - - Note May not just be sibling level + 1 as could be empty levels in-between - - Example: - - 1 ) Initial order - ActorC ( sibling level 4 ) - ActorB ( sibling level 3 ) - ActorA ( sibling level 1 ) - - 2 ) ACTION: Raise A above B - a) Find nearest level above A = Level 3 - b) Increment levels above Level 3 - - ActorC ( sibling level 5 ) - ActorB ( sibling level 3 ) NEAREST - ActorA ( sibling level 1 ) - - 3 ) Set Actor A sibling level to nearest +1 as vacant - - ActorC ( sibling level 5 ) - ActorA ( sibling level 4 ) - ActorB ( sibling level 3 ) - - 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER - If shifting causes this ceiling to be reached. then a defragmentation can be performed to - remove any empty sibling order gaps and start from sibling level 0 again. - If the number of actors reaches this maximum and all using exclusive sibling order values then - defragmention will stop and new sibling orders will be set to same max value. - */ if ( mParent ) { - int nearestLevel = mSiblingOrder; - int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER; - bool defragmentationRequired( false ); - - ActorContainer* siblings = mParent->mChildren; - - // Find Nearest sibling level above this actor - ActorIter end = siblings->end(); - for( ActorIter iter = siblings->begin(); iter != end; ++iter ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this ) // If not already at end { - ActorPtr sibling = (*iter); - if ( sibling != this ) + for( size_t i=0; i= mSiblingOrder ) ) + if( siblings[i] == this ) { - int distanceToNextLevel = order - mSiblingOrder; - if ( distanceToNextLevel < shortestDistanceToNextLevel ) - { - nearestLevel = order; - shortestDistanceToNextLevel = distanceToNextLevel; - } + // Swap with next + ActorPtr next = siblings[i+1]; + siblings[i+1] = this; + siblings[i] = next; + break; } } } - - if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top - { - mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level - defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder ); - // Move current actor to newly vacated order level - SetSiblingOrder( mSiblingOrder ); - if ( defragmentationRequired ) - { - DefragmentSiblingIndexes( *siblings ); - } - } - SetSiblingOrder( mSiblingOrder ); + RequestRebuildDepthTree(); } else { @@ -4681,63 +5203,24 @@ void Actor::Raise() void Actor::Lower() { - /** - 1) Check if actor already at bottom and if nothing needs to be done - This Actor can have lowest sibling order but if not exclusive then another actor at same sibling - order can be positioned above it due to insertion order of actors so need to move this actor below it. - 2) Find nearest sibling level below, this Actor needs to be below it - 3) a) Need to vacate a sibling level below nearest for this actor to occupy - b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level. - c) Set this actor's sibling level to this newly vacated level. - 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER - If shifting causes this ceiling to be reached. then a defragmentation can be performed to - remove any empty sibling order gaps and start from sibling level 0 again. - If the number of actors reaches this maximum and all using exclusive sibling order values then - defragmention will stop and new sibling orders will be set to same max value. - */ - if ( mParent ) { - // 1) Find nearest level below - int nearestLevel = mSiblingOrder; - int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER; - - ActorContainer* siblings = mParent->mChildren; - - ActorIter end = siblings->end(); - for( ActorIter iter = siblings->begin(); iter != end; ++iter ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this ) // If not already at beginning { - ActorPtr sibling = (*iter); - if ( sibling != this ) + for( size_t i=1; imChildren; - - ActorIter end = siblings->end(); - for( ActorIter iter = siblings->begin(); iter != end; ++iter ) - { - ActorPtr sibling = (*iter); - if ( sibling != this ) - { - maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder ); - } - } - - bool defragmentationRequired( false ); - - if ( maxOrder >= mSiblingOrder ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this ) // If not already at end { - mSiblingOrder = maxOrder + 1; - if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER ) + ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this ); + if( iter != siblings.end() ) { - defragmentationRequired = true; + siblings.erase(iter); + siblings.push_back(ActorPtr(this)); } } - - SetSiblingOrder( mSiblingOrder ); - - if ( defragmentationRequired ) - { - DefragmentSiblingIndexes( *siblings ); - } + RequestRebuildDepthTree(); } else { @@ -4800,62 +5252,21 @@ void Actor::RaiseToTop() void Actor::LowerToBottom() { - /** - See Actor::LowerToBottom() - - 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done. - 2 ) a ) Check if the bottom position 0 is vacant. - b ) If 0 position is not vacant then shift up all sibling order values from 0 and above - c ) 0 sibling position is vacant. - 3 ) Set this actor to vacant sibling order 0; - 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER - If shifting causes this ceiling to be reached. then a defragmentation can be performed to - remove any empty sibling order gaps and start from sibling level 0 again. - If the number of actors reaches this maximum and all using exclusive sibling order values then - defragmention will stop and new sibling orders will be set to same max value. - */ - if ( mParent ) { - bool defragmentationRequired( false ); - bool orderZeroFree ( true ); - - ActorContainer* siblings = mParent->mChildren; - - bool actorAtLowestOrder = true; - ActorIter end = siblings->end(); - for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter ) - { - ActorPtr sibling = (*iter); - if ( sibling != this ) - { - int siblingOrder = GetSiblingOrder( sibling ); - if ( siblingOrder <= mSiblingOrder ) - { - actorAtLowestOrder = false; - } - - if ( siblingOrder == 0 ) - { - orderZeroFree = false; - } - } - } - - if ( ! actorAtLowestOrder ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this ) // If not already at bottom, { - if ( ! orderZeroFree ) - { - defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 ); - } - mSiblingOrder = 0; - SetSiblingOrder( mSiblingOrder ); + ActorPtr thisPtr(this); // ensure this actor remains referenced. - if ( defragmentationRequired ) + ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this ); + if( iter != siblings.end() ) { - DefragmentSiblingIndexes( *siblings ); + siblings.erase(iter); + siblings.insert(siblings.begin(), thisPtr); } } + RequestRebuildDepthTree(); } else { @@ -4865,36 +5276,25 @@ void Actor::LowerToBottom() void Actor::RaiseAbove( Internal::Actor& target ) { - /** - 1 ) a) Find target actor's sibling order - b) If sibling order of target is the same as this actor then need to this Actor's sibling order - needs to be above it or the insertion order will determine which is drawn on top. - 2 ) Shift up by 1 all sibling order greater than target sibling order - 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above - 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER - If shifting causes this ceiling to be reached. then a defragmentation can be performed to - remove any empty sibling order gaps and start from sibling level 0 again. - If the number of actors reaches this maximum and all using exclusive sibling order values then - defragmention will stop and new sibling orders will be set to same max value. - */ - if ( mParent ) { - if ( ValidateActors( *this, target ) ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this && target.mParent == mParent ) // If not already at top { - // Find target's sibling order - // Set actor sibling order to this number +1 - int targetSiblingOrder = GetSiblingOrder( &target ); - ActorContainer* siblings = mParent->mChildren; - mSiblingOrder = targetSiblingOrder + 1; - bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder ); - - SetSiblingOrder( mSiblingOrder ); + ActorPtr thisPtr(this); // ensure this actor remains referenced. - if ( defragmentationRequired ) + ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target ); + ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this ); + if( thisIter < targetIter ) { - DefragmentSiblingIndexes( *(mParent->mChildren) ); + siblings.erase(thisIter); + // Erasing early invalidates the targetIter. (Conversely, inserting first may also + // invalidate thisIter) + targetIter = std::find( siblings.begin(), siblings.end(), &target ); + ++targetIter; + siblings.insert(targetIter, thisPtr); } + RequestRebuildDepthTree(); } } else @@ -4905,59 +5305,22 @@ void Actor::RaiseAbove( Internal::Actor& target ) void Actor::LowerBelow( Internal::Actor& target ) { - /** - 1 ) a) Find target actor's sibling order - b) If sibling order of target is the same as this actor then need to this Actor's sibling order - needs to be below it or the insertion order will determine which is drawn on top. - 2 ) Shift the target sibling order and all sibling orders at that level or above by 1 - 3 ) Set this actor to the sibling order of the target before it changed. - 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER - If shifting causes this ceiling to be reached. then a defragmentation can be performed to - remove any empty sibling order gaps and start from sibling level 0 again. - If the number of actors reaches this maximum and all using exclusive sibling order values then - defragmention will stop and new sibling orders will be set to same max value. - */ - if ( mParent ) { - if ( ValidateActors( *this, target ) ) + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom { - bool defragmentationRequired ( false ); - // Find target's sibling order - // Set actor sibling order to target sibling order - 1 - int targetSiblingOrder = GetSiblingOrder( &target); - ActorContainer* siblings = mParent->mChildren; - if ( targetSiblingOrder == 0 ) - { - //lower to botton - ActorIter end = siblings->end(); - for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter ) - { - ActorPtr sibling = (*iter); - if ( sibling != this ) - { - sibling->mSiblingOrder++; - if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER ) - { - defragmentationRequired = true; - } - sibling->SetSiblingOrder( sibling->mSiblingOrder ); - } - } - mSiblingOrder = 0; - } - else - { - defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder ); + ActorPtr thisPtr(this); // ensure this actor remains referenced. - mSiblingOrder = targetSiblingOrder; - } - SetSiblingOrder( mSiblingOrder ); + ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target ); + ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this ); - if ( defragmentationRequired ) + if( thisIter > targetIter ) { - DefragmentSiblingIndexes( *(mParent->mChildren) ); + siblings.erase(thisIter); // this only invalidates iterators at or after this point. + siblings.insert(targetIter, thisPtr); } + RequestRebuildDepthTree(); } } else @@ -4966,6 +5329,46 @@ void Actor::LowerBelow( Internal::Actor& target ) } } +void Actor::SetInheritLayoutDirection( bool inherit ) +{ + if( mInheritLayoutDirection != inherit ) + { + mInheritLayoutDirection = inherit; + + if( inherit && mParent ) + { + InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection ); + } + } +} + +bool Actor::IsLayoutDirectionInherited() const +{ + return mInheritLayoutDirection; +} + +void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set ) +{ + if( actor && ( actor->mInheritLayoutDirection || set ) ) + { + if( actor->mLayoutDirection != direction) + { + actor->mLayoutDirection = direction; + actor->EmitLayoutDirectionChangedSignal( direction ); + actor->RelayoutRequest(); + } + + if( actor->GetChildCount() > 0 ) + { + ActorContainer& children = actor->GetChildrenInternal(); + for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter ) + { + InheritLayoutDirectionRecursively( *iter, direction ); + } + } + } +} + } // namespace Internal } // namespace Dali