X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-impl.cpp;h=8df598ebb2e686d062ff492c46edd385d058656b;hb=462cbee2270984cdca45488f3733d664dcf49187;hp=68d81d4b9cc6cf02007ef680ec042f7cf04a442d;hpb=6264fca88e12b3f64730f1ab7a50f25b95b06b27;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 68d81d4..8df598e 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,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,6 +93,32 @@ 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 /** @@ -101,6 +133,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; @@ -112,6 +145,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 @@ -146,61 +180,64 @@ namespace // unnamed namespace * Name Type writable animatable constraint-input enum for index-checking */ DALI_PROPERTY_TABLE_BEGIN -DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN ) -DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X ) -DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y ) -DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z ) -DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT ) -DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X ) -DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y ) -DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z ) -DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE ) -DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH ) -DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT ) -DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH ) -DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION ) -DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X ) -DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y ) -DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z ) -DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION ) -DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X ) -DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y ) -DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z ) -DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION ) -DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION ) -DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE ) -DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X ) -DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y ) -DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z ) -DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE ) -DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE ) -DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR ) -DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED ) -DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN ) -DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE ) -DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA ) -DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR ) -DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX ) -DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME ) -DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE ) -DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED ) -DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION ) -DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE ) -DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE ) -DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE ) -DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE ) -DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR ) -DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY ) -DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY ) -DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY ) -DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT ) -DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH ) -DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING ) -DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE ) -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( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER ) +DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN ) +DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X ) +DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y ) +DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z ) +DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT ) +DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X ) +DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y ) +DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z ) +DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE ) +DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH ) +DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT ) +DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH ) +DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION ) +DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X ) +DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y ) +DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z ) +DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION ) +DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X ) +DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y ) +DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z ) +DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION ) +DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION ) +DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE ) +DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X ) +DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y ) +DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z ) +DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE ) +DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE ) +DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR ) +DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED ) +DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN ) +DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE ) +DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA ) +DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR ) +DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX ) +DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME ) +DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE ) +DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED ) +DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION ) +DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE ) +DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE ) +DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE ) +DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE ) +DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR ) +DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY ) +DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY ) +DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY ) +DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT ) +DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH ) +DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING ) +DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE ) +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( "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 ) +DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT ) DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX ) // Signals @@ -356,9 +393,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 @@ -776,6 +831,24 @@ const Vector3& Actor::GetCurrentWorldPosition() const return Vector3::ZERO; } +const Vector2 Actor::GetCurrentScreenPosition() const +{ + if( OnStage() && NULL != mNode ) + { + StagePtr stage = Stage::GetCurrent(); + Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); + Vector3 actorSize = GetCurrentSize() * GetCurrentScale(); + Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage + Vector3 halfActorSize( actorSize * 0.5f ); + Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT ); + + return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x, + halfStageSize.height + worldPosition.y - anchorPointOffSet.y ); + } + + return Vector2::ZERO; +} + void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode ) { // this flag is not animatable so keep the value @@ -820,6 +893,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 @@ -829,15 +904,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 @@ -879,6 +952,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 @@ -888,6 +963,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 @@ -897,6 +974,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 @@ -906,6 +985,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 @@ -915,6 +996,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 @@ -973,11 +1056,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 @@ -993,6 +1072,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 @@ -1018,7 +1099,7 @@ ClippingMode::Type Actor::GetClippingMode() const unsigned int Actor::GetSortingDepth() { - return GetDepthIndex( mDepth, mSiblingOrder ); + return mSortedDepth; } const Vector4& Actor::GetCurrentWorldColor() const @@ -1033,6 +1114,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 @@ -1042,6 +1125,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 @@ -1051,6 +1136,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 @@ -1060,6 +1147,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 @@ -1189,89 +1278,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 @@ -1302,7 +1376,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; + } } } @@ -1365,7 +1447,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 ]; + } } } } @@ -1914,6 +2003,15 @@ 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 ); + } +} + Dali::Actor::TouchSignalType& Actor::TouchedSignal() { return mTouchedSignal; @@ -1949,6 +2047,11 @@ Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal() return mOnRelayoutSignal; } +DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal() +{ + return mVisibilityChangedSignal; +} + bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { bool connected( true ); @@ -2000,9 +2103,14 @@ 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 ), @@ -2019,6 +2127,8 @@ Actor::Actor( DerivedType derivedType ) mInheritPosition( true ), mInheritOrientation( true ), mInheritScale( true ), + mPositionUsesAnchorPoint( true ), + mVisible( true ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), mColorMode( Node::DEFAULT_COLOR_MODE ), @@ -2086,6 +2196,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 ); @@ -2105,7 +2221,6 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in mIsOnStage = true; mDepth = depth; - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); ConnectToSceneGraph(); @@ -2178,6 +2293,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 ); @@ -2263,6 +2384,205 @@ bool Actor::IsNodeConnected() const return connected; } +// This method generates the depth tree using the recursive function below, +// then walks the tree and sets 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); + + DepthNodeMemoryPool nodeMemoryPool; + ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder ); + + int actorCount = BuildDepthTree( nodeMemoryPool, rootNode ); + + // Vector of scene-graph nodes and their depths to send to UpdateManager + // in a single message + SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount); + + // Traverse depth tree and set mSortedDepth on each actor and scenegraph node + uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative + ActorDepthTreeNode* currentNode = rootNode; + bool firstVisit = true; + while( currentNode != rootNode || firstVisit) + { + firstVisit = false; + + // Visit node, performing action + for( std::vector::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter ) + { + (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER; + sceneGraphNodeDepths->Add( const_cast((*iter)->mNode), (*iter)->mSortedDepth ); + } + ++sortOrder; + + // Descend tree + if( currentNode->mFirstChildNode ) + { + currentNode = currentNode->mFirstChildNode; + } + else // leaf node, goto next sibling, or return up tree. + { + bool breakout=false; + while( ! currentNode->mNextSiblingNode ) + { + if( currentNode == rootNode ) // If we get to root of tree, stop + { + breakout = true; + break; + } + currentNode = currentNode->mParentNode; + } + + if( breakout ) + { + break; + } + currentNode = currentNode->mNextSiblingNode; + } + } + + SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths ); + DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: "); +} + +/** + * Structure to store the actor's associated node in the depth tree for child + * traversal + */ +struct ActorNodePair +{ + Actor* actor; + ActorDepthTreeNode* node; + ActorNodePair( Actor* actor, ActorDepthTreeNode* node ) + : actor(actor), + node(node) + { + } +}; + +/* + * Descend actor tree, building a depth tree based on actor's sibling order. + * Actors with the same sibling order share the same depth tree. Siblings + * in the depth tree are ordered by actor's sibling order. + * + * An actor tree like this: + * + * Root (SO:0) + * _/ | \_ + * _/ | \_ + * _/ | \_ + * / | \ + * A(SO:1) B(SO:2) C(SO:1) + * _/\_ | _/ \_ + * / \ | / \ + * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0) + * + * will end up as a depth tree like this: + * + * RootNode [ Root ] -> NULL + * |(mFC) + * V (mNS) + * Node [ A, C ] ------------------------> Node [ B ] -> NULL + * | | + * V V + * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL + * | | | + * V V V + * NULL NULL NULL + * + * (All nodes also point to their parents to enable storage free traversal) + */ +int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node ) +{ + int treeCount=1; // Count self and children + + // Create/add to children of this node + if( mChildren ) + { + std::vector storedChildren; + storedChildren.reserve( mChildren->size() ); + + for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it ) + { + Actor* childActor = (*it).Get(); + if( childActor->IsLayer() ) + { + Layer* layer = static_cast(childActor); + if( layer->GetBehavior() == Dali::Layer::LAYER_3D ) + { + // Ignore this actor and children. + continue; + } + } + + // If no existing depth node children + if( node->mFirstChildNode == NULL ) + { + node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder ); + node->mFirstChildNode->mParentNode = node; + storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode )); + } + else // find child node with matching sibling order (insertion sort) + { + bool addedChildActor = false; + + // depth tree child nodes ordered by sibling order + ActorDepthTreeNode* lastNode = NULL; + for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode ) + { + uint16_t actorSiblingOrder = childActor->mSiblingOrder; + uint16_t currentSiblingOrder = childNode->GetSiblingOrder(); + + if( actorSiblingOrder == currentSiblingOrder ) + { + // Don't need a new depth node, add to existing node + childNode->AddActor( childActor ); + storedChildren.push_back(ActorNodePair( childActor, childNode )); + addedChildActor = true; + break; + } + else if( actorSiblingOrder < currentSiblingOrder ) + { + break; + } + lastNode = childNode; + } + + // No matching sibling order - create new node and insert into sibling list + if( !addedChildActor ) + { + ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder ); + + newNode->mParentNode = node; + storedChildren.push_back(ActorNodePair( childActor, newNode )); + + if( lastNode == NULL ) // Insert at start of siblings + { + ActorDepthTreeNode* nextNode = node->mFirstChildNode; + node->mFirstChildNode = newNode; + newNode->mNextSiblingNode = nextNode; + } + else // insert into siblings after last node + { + newNode->mNextSiblingNode = lastNode->mNextSiblingNode; + lastNode->mNextSiblingNode = newNode; + } + } + } + } + + // Order of descent doesn't matter; we're using insertion to sort. + for( std::vector::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter ) + { + treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node ); + } + } + return treeCount; +} + unsigned int Actor::GetDefaultPropertyCount() const { return DEFAULT_PROPERTY_COUNT; @@ -2536,8 +2856,13 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr } case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { - SetOpacity( property.Get< float >() ); + float value; + if( property.Get( value ) ) + { + SetOpacity( value ); + } break; } @@ -2693,11 +3018,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr { if( static_cast(value) != mSiblingOrder ) { - mSiblingOrder = value; - if( mIsOnStage ) - { - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); - } + SetSiblingOrder( value ); } } break; @@ -2717,6 +3038,20 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } + case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + { + bool value = false; + if( property.Get( value ) && value != mPositionUsesAnchorPoint ) + { + mPositionUsesAnchorPoint = value; + if( NULL != mNode ) + { + SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint ); + } + } + break; + } + default: { // this can happen in the case of a non-animatable default property so just do nothing @@ -2885,376 +3220,169 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const { Property::Value value; - if( index >= DEFAULT_PROPERTY_COUNT ) + if( ! GetCachedPropertyValue( index, value ) ) + { + // If property value is not stored in the event-side, then it must be a scene-graph only property + GetCurrentPropertyValue( index, value ); + } + + return value; +} + +Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const +{ + Property::Value value; + + if( ! GetCurrentPropertyValue( index, value ) ) { - return value; + // If unable to retrieve scene-graph property value, then it must be an event-side only property + GetCachedPropertyValue( index, value ); } + return value; +} + +void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value ) +{ switch( index ) { - case Dali::Actor::Property::PARENT_ORIGIN: + case Dali::Actor::Property::SIZE: { - value = GetCurrentParentOrigin(); + if( value.Get( mTargetSize ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } break; } - case Dali::Actor::Property::PARENT_ORIGIN_X: + case Dali::Actor::Property::SIZE_WIDTH: { - value = GetCurrentParentOrigin().x; + if( value.Get( mTargetSize.width ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } break; } - case Dali::Actor::Property::PARENT_ORIGIN_Y: + case Dali::Actor::Property::SIZE_HEIGHT: { - value = GetCurrentParentOrigin().y; + if( value.Get( mTargetSize.height ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } break; } - case Dali::Actor::Property::PARENT_ORIGIN_Z: + case Dali::Actor::Property::SIZE_DEPTH: { - value = GetCurrentParentOrigin().z; + if( value.Get( mTargetSize.depth ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } break; } - case Dali::Actor::Property::ANCHOR_POINT: + case Dali::Actor::Property::POSITION: { - value = GetCurrentAnchorPoint(); - break; - } - - case Dali::Actor::Property::ANCHOR_POINT_X: - { - value = GetCurrentAnchorPoint().x; - break; - } - - case Dali::Actor::Property::ANCHOR_POINT_Y: - { - value = GetCurrentAnchorPoint().y; - break; - } - - case Dali::Actor::Property::ANCHOR_POINT_Z: - { - value = GetCurrentAnchorPoint().z; - break; - } - - case Dali::Actor::Property::SIZE: - { - Vector3 size = GetTargetSize(); - - // 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; - } - - value = size; - - break; - } - - case Dali::Actor::Property::SIZE_WIDTH: - { - if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED ) - { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().width; - } - else - { - value = GetTargetSize().width; - } - break; - } - - case Dali::Actor::Property::SIZE_HEIGHT: - { - if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) - { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().height; - } - else - { - value = GetTargetSize().height; - } - break; - } - - case Dali::Actor::Property::SIZE_DEPTH: - { - value = GetTargetSize().depth; - break; - } - - case Dali::Actor::Property::POSITION: - { - value = GetTargetPosition(); + value.Get( mTargetPosition ); break; } case Dali::Actor::Property::POSITION_X: { - value = GetTargetPosition().x; + value.Get( mTargetPosition.x ); break; } case Dali::Actor::Property::POSITION_Y: { - value = GetTargetPosition().y; + value.Get( mTargetPosition.y ); break; } case Dali::Actor::Property::POSITION_Z: { - value = GetTargetPosition().z; - break; - } - - case Dali::Actor::Property::WORLD_POSITION: - { - value = GetCurrentWorldPosition(); - break; - } - - case Dali::Actor::Property::WORLD_POSITION_X: - { - value = GetCurrentWorldPosition().x; - break; - } - - case Dali::Actor::Property::WORLD_POSITION_Y: - { - value = GetCurrentWorldPosition().y; - break; - } - - case Dali::Actor::Property::WORLD_POSITION_Z: - { - value = GetCurrentWorldPosition().z; + value.Get( mTargetPosition.z ); break; } case Dali::Actor::Property::ORIENTATION: { - value = GetCurrentOrientation(); - break; - } - - case Dali::Actor::Property::WORLD_ORIENTATION: - { - value = GetCurrentWorldOrientation(); + value.Get( mTargetOrientation ); break; } case Dali::Actor::Property::SCALE: { - value = GetCurrentScale(); + value.Get( mTargetScale ); break; } case Dali::Actor::Property::SCALE_X: { - value = GetCurrentScale().x; + value.Get( mTargetScale.x ); break; } case Dali::Actor::Property::SCALE_Y: { - value = GetCurrentScale().y; + value.Get( mTargetScale.y ); break; } case Dali::Actor::Property::SCALE_Z: { - value = GetCurrentScale().z; - break; - } - - case Dali::Actor::Property::WORLD_SCALE: - { - value = GetCurrentWorldScale(); + value.Get( mTargetScale.z ); break; } case Dali::Actor::Property::VISIBLE: { - value = IsVisible(); + SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE ); break; } case Dali::Actor::Property::COLOR: { - value = GetCurrentColor(); + value.Get( mTargetColor ); break; } case Dali::Actor::Property::COLOR_RED: { - value = GetCurrentColor().r; + value.Get( mTargetColor.r ); break; } case Dali::Actor::Property::COLOR_GREEN: { - value = GetCurrentColor().g; + value.Get( mTargetColor.g ); break; } case Dali::Actor::Property::COLOR_BLUE: { - value = GetCurrentColor().b; + value.Get( mTargetColor.b ); break; } case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { - value = GetCurrentColor().a; - break; - } - - case Dali::Actor::Property::WORLD_COLOR: - { - value = GetCurrentWorldColor(); - break; - } - - case Dali::Actor::Property::WORLD_MATRIX: - { - value = GetCurrentWorldMatrix(); - break; - } - - case Dali::Actor::Property::NAME: - { - value = GetName(); - break; - } - - case Dali::Actor::Property::SENSITIVE: - { - value = IsSensitive(); - break; - } - - case Dali::Actor::Property::LEAVE_REQUIRED: - { - value = GetLeaveRequired(); - break; - } - - case Dali::Actor::Property::INHERIT_POSITION: - { - value = IsPositionInherited(); - break; - } - - case Dali::Actor::Property::INHERIT_ORIENTATION: - { - value = IsOrientationInherited(); - break; - } - - case Dali::Actor::Property::INHERIT_SCALE: - { - value = IsScaleInherited(); - break; - } - - case Dali::Actor::Property::COLOR_MODE: - { - value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::POSITION_INHERITANCE: - { - value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::DRAW_MODE: - { - value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::SIZE_MODE_FACTOR: - { - value = GetSizeModeFactor(); - break; - } - - case Dali::Actor::Property::WIDTH_RESIZE_POLICY: - { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: - { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::SIZE_SCALE_POLICY: - { - value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT ); - break; - } - - case Dali::Actor::Property::WIDTH_FOR_HEIGHT: - { - value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); - 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::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::MINIMUM_SIZE: - { - value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); - break; - } - - case Dali::Actor::Property::MAXIMUM_SIZE: - { - value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); - break; - } - - case Dali::DevelActor::Property::SIBLING_ORDER: - { - value = static_cast(mSiblingOrder); + value.Get( mTargetColor.a ); break; } - case Dali::Actor::Property::CLIPPING_MODE: + default: { - value = mClippingMode; + // Not an animatable property. Do nothing. break; } } - - return value; } const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const @@ -3372,6 +3500,7 @@ const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index ind break; case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: property = &mNode->mColor; break; @@ -3540,8 +3669,11 @@ const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index ind 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; @@ -3613,6 +3745,7 @@ int Actor::GetPropertyComponentIndex( Property::Index index ) const } case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { componentIndex = 3; break; @@ -3675,26 +3808,520 @@ 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 ); +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 ) ) + { + actor->SetVisible( true ); + done = true; + } + else if( 0 == actionName.compare( ACTION_HIDE ) ) + { + actor->SetVisible( false ); + done = true; + } + } + + return done; +} + +bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; + + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: + { + value = GetCurrentParentOrigin(); + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_X: + { + value = GetCurrentParentOrigin().x; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + { + value = GetCurrentParentOrigin().y; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + { + value = GetCurrentParentOrigin().z; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT: + { + value = GetCurrentAnchorPoint(); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_X: + { + value = GetCurrentAnchorPoint().x; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Y: + { + value = GetCurrentAnchorPoint().y; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Z: + { + value = GetCurrentAnchorPoint().z; + break; + } + + case Dali::Actor::Property::SIZE: + { + value = GetTargetSize(); + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetTargetSize().width; + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetTargetSize().height; + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetTargetSize().depth; + break; + } + + case Dali::Actor::Property::POSITION: + { + value = GetTargetPosition(); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + value = GetTargetPosition().x; + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + value = GetTargetPosition().y; + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + value = GetTargetPosition().z; + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + value = mTargetOrientation; + break; + } + + case Dali::Actor::Property::SCALE: + { + value = mTargetScale; + break; + } + + case Dali::Actor::Property::SCALE_X: + { + value = mTargetScale.x; + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + value = mTargetScale.y; + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + value = mTargetScale.z; + break; + } + + case Dali::Actor::Property::VISIBLE: + { + value = mVisible; + break; + } + + case Dali::Actor::Property::COLOR: + { + value = mTargetColor; + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + value = mTargetColor.r; + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + value = mTargetColor.g; + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + value = mTargetColor.b; + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value = mTargetColor.a; + break; + } + + case Dali::Actor::Property::NAME: + { + value = GetName(); + break; + } + + case Dali::Actor::Property::SENSITIVE: + { + value = IsSensitive(); + break; + } + + case Dali::Actor::Property::LEAVE_REQUIRED: + { + value = GetLeaveRequired(); + break; + } + + case Dali::Actor::Property::INHERIT_POSITION: + { + value = IsPositionInherited(); + break; + } + + case Dali::Actor::Property::INHERIT_ORIENTATION: + { + value = IsOrientationInherited(); + break; + } + + case Dali::Actor::Property::INHERIT_SCALE: + { + value = IsScaleInherited(); + break; + } + + case Dali::Actor::Property::COLOR_MODE: + { + value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::POSITION_INHERITANCE: + { + value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::DRAW_MODE: + { + value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::SIZE_MODE_FACTOR: + { + value = GetSizeModeFactor(); + break; + } + + case Dali::Actor::Property::WIDTH_RESIZE_POLICY: + { + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: + { + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::SIZE_SCALE_POLICY: + { + value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT ); + break; + } + + case Dali::Actor::Property::WIDTH_FOR_HEIGHT: + { + value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); + 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::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::MINIMUM_SIZE: + { + value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); + break; + } + + case Dali::Actor::Property::MAXIMUM_SIZE: + { + value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + break; + } + + case Dali::Actor::Property::CLIPPING_MODE: + { + value = mClippingMode; + break; + } + + case Dali::DevelActor::Property::SIBLING_ORDER: + { + value = static_cast(mSiblingOrder); + break; + } + + case Dali::DevelActor::Property::SCREEN_POSITION: + { + value = GetCurrentScreenPosition(); + break; + } + + case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + { + value = mPositionUsesAnchorPoint; + break; + } + + default: + { + // Must be a scene-graph only property + valueSet = false; + break; + } + } + + return valueSet; +} + +bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; + + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + value = GetCurrentSize(); + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetCurrentSize().width; + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetCurrentSize().height; + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetCurrentSize().depth; + break; + } + + case Dali::Actor::Property::POSITION: + { + value = GetCurrentPosition(); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + value = GetCurrentPosition().x; + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + value = GetCurrentPosition().y; + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + value = GetCurrentPosition().z; + break; + } + + case Dali::Actor::Property::WORLD_POSITION: + { + value = GetCurrentWorldPosition(); + break; + } + + case Dali::Actor::Property::WORLD_POSITION_X: + { + value = GetCurrentWorldPosition().x; + break; + } + + case Dali::Actor::Property::WORLD_POSITION_Y: + { + value = GetCurrentWorldPosition().y; + break; + } + + case Dali::Actor::Property::WORLD_POSITION_Z: + { + value = GetCurrentWorldPosition().z; + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + value = GetCurrentOrientation(); + break; + } + + case Dali::Actor::Property::WORLD_ORIENTATION: + { + value = GetCurrentWorldOrientation(); + break; + } + + case Dali::Actor::Property::SCALE: + { + value = GetCurrentScale(); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + value = GetCurrentScale().x; + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + value = GetCurrentScale().y; + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + value = GetCurrentScale().z; + break; + } + + case Dali::Actor::Property::WORLD_SCALE: + { + value = GetCurrentWorldScale(); + break; + } + + case Dali::Actor::Property::COLOR: + { + value = GetCurrentColor(); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + value = GetCurrentColor().r; + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + value = GetCurrentColor().g; + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + value = GetCurrentColor().b; + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value = GetCurrentColor().a; + break; + } + + case Dali::Actor::Property::WORLD_COLOR: + { + value = GetCurrentWorldColor(); + break; + } + + 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() @@ -3980,7 +4607,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 @@ -4250,13 +4877,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 @@ -4266,7 +4895,7 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont SetNegotiatedSize( container ); // Negotiate down to children - const Vector2 newBounds = GetTargetSize().GetVectorXY(); + const Vector2 newBounds = mTargetSize.GetVectorXY(); for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) { @@ -4274,12 +4903,13 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont // 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); @@ -4291,6 +4921,38 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont container.Add( Dali::Actor( child.Get() ), newBounds ); } } + 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 ) @@ -4407,6 +5069,505 @@ Object* Actor::GetParentObject() const return mParent; } +void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) +{ + if( mVisible != visible ) + { + 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 ); + } + + mVisible = visible; + + // Emit the signal on this actor and all its children + EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF ); + } +} + +void Actor::SetSiblingOrder( unsigned int order ) +{ + mSiblingOrder = std::min( order, static_cast( DevelLayer::SIBLING_ORDER_MULTIPLIER ) ); + + if( mIsOnStage ) + { + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + } +} + +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 + + // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling. + + 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 ); + } + + for ( int index = 0; index <= highestOrder; index++ ) + { + int nextHighest = -1; + + // Find Next highest + for( ActorIter iter = siblings.begin(); iter != end; ++iter ) + { + ActorPtr sibling = (*iter); + int siblingOrder = sibling->mSiblingOrder; + + if ( siblingOrder > index ) + { + if ( nextHighest == -1 ) + { + nextHighest = siblingOrder; + } + nextHighest = std::min( nextHighest, siblingOrder ); + } + } + + // Check if a gap exists between indexes, if so set next index to consecutive number + if ( ( nextHighest - index ) > 1 ) + { + for( ActorIter iter = siblings.begin(); iter != end; ++iter ) + { + ActorPtr sibling = (*iter); + int siblingOrder = sibling->mSiblingOrder; + 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 ); + } + } + } + } +} + +bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom ) +{ + // 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 ) + { + // Move actors at nearest order and above up by 1 + ActorPtr sibling = (*iter); + if ( sibling != this ) + { + // 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 ); + } + } + } + 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 ) + { + ActorPtr sibling = (*iter); + if ( sibling != this ) + { + int order = GetSiblingOrder( sibling ); + + if ( ( order >= mSiblingOrder ) ) + { + int distanceToNextLevel = order - mSiblingOrder; + if ( distanceToNextLevel < shortestDistanceToNextLevel ) + { + nearestLevel = order; + shortestDistanceToNextLevel = distanceToNextLevel; + } + } + } + } + + 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 ); + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +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 ) + { + ActorPtr sibling = (*iter); + if ( sibling != this ) + { + int order = GetSiblingOrder( sibling ); + + if ( order <= mSiblingOrder ) + { + int distanceToNextLevel = mSiblingOrder - order; + if ( distanceToNextLevel < shortestDistanceToNextLevel ) + { + nearestLevel = order; + shortestDistanceToNextLevel = distanceToNextLevel; + } + } + } + } + + bool defragmentationRequired ( false ); + + // 2) If actor already not at bottom, raise all actors at required level and above + if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom + { + mSiblingOrder = nearestLevel; + defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder ); + // Move current actor to newly vacated order + SetSiblingOrder( mSiblingOrder ); + if ( defragmentationRequired ) + { + DefragmentSiblingIndexes( *siblings ); + } + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::RaiseToTop() +{ + /** + 1 ) Find highest sibling order actor + 2 ) If highest sibling level not itself then set sibling order to that + 1 + 3 ) highest sibling order can be same as itself so need to increment over that + 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 maxOrder = 0; + + ActorContainer* siblings = mParent->mChildren; + + 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 ) + { + mSiblingOrder = maxOrder + 1; + if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER ) + { + defragmentationRequired = true; + } + } + + SetSiblingOrder( mSiblingOrder ); + + if ( defragmentationRequired ) + { + DefragmentSiblingIndexes( *siblings ); + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +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 ) + { + if ( ! orderZeroFree ) + { + defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 ); + } + mSiblingOrder = 0; + SetSiblingOrder( mSiblingOrder ); + + if ( defragmentationRequired ) + { + DefragmentSiblingIndexes( *siblings ); + } + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +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 ) ) + { + // 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 ); + + if ( defragmentationRequired ) + { + DefragmentSiblingIndexes( *(mParent->mChildren) ); + } + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +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 ) ) + { + 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 ); + + mSiblingOrder = targetSiblingOrder; + } + SetSiblingOrder( mSiblingOrder ); + + if ( defragmentationRequired ) + { + DefragmentSiblingIndexes( *(mParent->mChildren) ); + } + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + } // namespace Internal } // namespace Dali