X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-impl.cpp;h=8d923b3db220e77c57a8040f19dcf30df8e3514c;hb=e08e2992259823c5f9832ad959ffa510b0445a6c;hp=68d81d4b9cc6cf02007ef680ec042f7cf04a442d;hpb=ec1bd81a4e903f1c96350a35e918715a2e1278ef;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..8d923b3 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,14 +57,17 @@ 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 { namespace Internal { -unsigned int Actor::mActorCounter = 0; - namespace { /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet. @@ -98,9 +101,10 @@ struct Actor::RelayoutData : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false ) { // Set size negotiation defaults - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t 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 +116,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,62 +151,67 @@ 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_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX ) +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( "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( "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 ) +DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT ) +DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED ) +DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties ) // Signals @@ -212,6 +222,10 @@ const char* const SIGNAL_ON_STAGE = "onStage"; const char* const SIGNAL_OFF_STAGE = "offStage"; const char* const SIGNAL_ON_RELAYOUT = "onRelayout"; const char* const SIGNAL_TOUCH = "touch"; +const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged"; +const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged"; +const char* const SIGNAL_CHILD_ADDED = "childAdded"; +const char* const SIGNAL_CHILD_REMOVED = "childRemoved"; // Actions @@ -223,7 +237,7 @@ BaseHandle CreateActor() return Dali::Actor::New(); } -TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor ); +TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties ); SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal ); SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal ); @@ -232,6 +246,10 @@ SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectS SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal ); SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal ); SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal ); TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction ); TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction ); @@ -261,17 +279,9 @@ DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR ) DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA ) DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE ) -DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE ) -DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION ) -DALI_ENUM_TO_STRING( USE_PARENT_POSITION ) -DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION ) -DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION ) -DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE ) - DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE ) DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL ) DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL ) DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE ) DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY ) @@ -296,12 +306,16 @@ 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 ) { - for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i ) + for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i ) { - size_t sizeIgnored = 0; + uint32_t sizeIgnored = 0; if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) ) { anchor = ANCHOR_CONSTANT_TABLE[ i ].value; @@ -356,16 +370,35 @@ 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 ActorPtr Actor::New() { - ActorPtr actor( new Actor( BASIC ) ); + // pass a reference to actor, actor does not own its node + ActorPtr actor( new Actor( BASIC, *CreateNode() ) ); // Second-phase construction actor->Initialize(); @@ -373,6 +406,16 @@ ActorPtr Actor::New() return actor; } +const SceneGraph::Node* Actor::CreateNode() +{ + // create node. Nodes are owned by the update manager + SceneGraph::Node* node = SceneGraph::Node::New(); + OwnerPointer< SceneGraph::Node > transferOwnership( node ); + AddNodeMessage( Stage::GetCurrent()->GetUpdateManager(), transferOwnership ); + + return node; +} + const std::string& Actor::GetName() const { return mName; @@ -382,16 +425,13 @@ void Actor::SetName( const std::string& name ) { mName = name; - if( NULL != mNode ) - { - // ATTENTION: string for debug purposes is not thread safe. - DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name ); - } + // ATTENTION: string for debug purposes is not thread safe. + DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name ); } -unsigned int Actor::GetId() const +uint32_t Actor::GetId() const { - return mId; + return GetNode().GetId(); } bool Actor::OnStage() const @@ -439,7 +479,7 @@ void Actor::Add( Actor& child ) // if we already have parent, unparent us first if( oldParent ) { - oldParent->Remove( child ); // This causes OnChildRemove callback + oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal // Old parent may need to readjust to missing child if( oldParent->RelayoutDependentOnChildren() ) @@ -459,6 +499,9 @@ void Actor::Add( Actor& child ) // Notification for derived classes OnChildAdd( child ); + EmitChildAddedSignal( child ); + + InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection ); // Only put in a relayout request if there is a suitable dependency if( RelayoutDependentOnChildren() ) @@ -511,6 +554,7 @@ void Actor::Remove( Actor& child ) // Notification for derived classes OnChildRemove( child ); + EmitChildRemovedSignal( child ); } void Actor::Unparent() @@ -524,12 +568,12 @@ void Actor::Unparent() } } -unsigned int Actor::GetChildCount() const +uint32_t Actor::GetChildCount() const { - return ( NULL != mChildren ) ? mChildren->size() : 0; + return ( NULL != mChildren ) ? static_cast( mChildren->size() ) : 0; // only 4,294,967,295 children per actor } -ActorPtr Actor::GetChildAt( unsigned int index ) const +ActorPtr Actor::GetChildAt( uint32_t index ) const { DALI_ASSERT_ALWAYS( index < GetChildCount() ); @@ -559,10 +603,10 @@ ActorPtr Actor::FindChildByName( const std::string& actorName ) return child; } -ActorPtr Actor::FindChildById( const unsigned int id ) +ActorPtr Actor::FindChildById( const uint32_t id ) { ActorPtr child = 0; - if( id == mId ) + if( id == GetId() ) { child = this; } @@ -584,11 +628,8 @@ ActorPtr Actor::FindChildById( const unsigned int id ) void Actor::SetParentOrigin( const Vector3& origin ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SetParentOriginMessage( GetEventThreadServices(), *mNode, origin ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin ); // Cache for event-thread access if( !mParentOrigin ) @@ -635,11 +676,8 @@ const Vector3& Actor::GetCurrentParentOrigin() const void Actor::SetAnchorPoint( const Vector3& anchor ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor ); // Cache for event-thread access if( !mAnchorPoint ) @@ -698,66 +736,46 @@ void Actor::SetPosition( const Vector3& position ) { mTargetPosition = position; - 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->mPosition, &SceneGraph::TransformManagerPropertyHandler::Bake, position ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler::Bake, position ); } void Actor::SetX( float x ) { mTargetPosition.x = x; - 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->mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeX, x ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeX, x ); } void Actor::SetY( float y ) { mTargetPosition.y = y; - 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->mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeY, y ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeY, y ); } void Actor::SetZ( float z ) { mTargetPosition.z = z; - 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->mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeZ, z ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeZ, z ); } void Actor::TranslateBy( const Vector3& distance ) { mTargetPosition += distance; - 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->mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeRelative, distance ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler::BakeRelative, distance ); } const Vector3& Actor::GetCurrentPosition() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex()); - } - - return Vector3::ZERO; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex()); } const Vector3& Actor::GetTargetPosition() const @@ -767,39 +785,38 @@ const Vector3& Actor::GetTargetPosition() const const Vector3& Actor::GetCurrentWorldPosition() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); - } - - return Vector3::ZERO; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); } -void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode ) +const Vector2 Actor::GetCurrentScreenPosition() const { - // this flag is not animatable so keep the value - mPositionInheritanceMode = mode; - if( NULL != mNode ) + StagePtr stage = Stage::GetCurrent(); + if( stage && OnStage() ) { - // mNode is being used in a separate thread; queue a message to set the value - SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION ); + Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); + Vector3 cameraPosition = stage->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); + worldPosition -= cameraPosition; + + Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale(); + 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 ); } -} -PositionInheritanceMode Actor::GetPositionInheritanceMode() const -{ - // Cached for event-thread access - return mPositionInheritanceMode; + return Vector2::ZERO; } void Actor::SetInheritPosition( bool inherit ) { - if( mInheritPosition != inherit && NULL != mNode ) + if( mInheritPosition != inherit ) { - // non animateable so keep local copy + // non animatable so keep local copy mInheritPosition = inherit; - SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit ); + SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit ); } } @@ -820,51 +837,35 @@ void Actor::SetOrientation( const Radian& angle, const Vector3& axis ) void Actor::SetOrientation( const Quaternion& orientation ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler::Bake, orientation ); - } + mTargetOrientation = orientation; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler::Bake, 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 ) { - 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, relativeRotation ); - } + mTargetOrientation *= Quaternion( relativeRotation ); + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler::BakeRelative, relativeRotation ); } const Quaternion& Actor::GetCurrentOrientation() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex()); - } - - return Quaternion::IDENTITY; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex()); } const Quaternion& Actor::GetCurrentWorldOrientation() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() ); - } - - return Quaternion::IDENTITY; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() ); } void Actor::SetScale( float scale ) @@ -879,80 +880,64 @@ void Actor::SetScale( float x, float y, float z ) void Actor::SetScale( const Vector3& scale ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler::Bake, scale ); - } + mTargetScale = scale; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler::Bake, scale ); } void Actor::SetScaleX( float x ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler::BakeX, x ); - } + mTargetScale.x = x; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler::BakeX, x ); } void Actor::SetScaleY( float y ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler::BakeY, y ); - } + mTargetScale.y = y; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler::BakeY, y ); } void Actor::SetScaleZ( float z ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler::BakeZ, z ); - } + mTargetScale.z = z; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler::BakeZ, z ); } void Actor::ScaleBy(const Vector3& relativeScale) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler::BakeRelativeMultiply, relativeScale ); - } + mTargetScale *= relativeScale; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler::BakeRelativeMultiply, relativeScale ); } const Vector3& Actor::GetCurrentScale() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex()); - } - - return Vector3::ONE; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex()); } const Vector3& Actor::GetCurrentWorldScale() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() ); - } - - return Vector3::ONE; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() ); } void Actor::SetInheritScale( bool inherit ) { - - if( mInheritScale != inherit && NULL != mNode ) + if( mInheritScale != inherit ) { - // non animateable so keep local copy + // non animatable so keep local copy mInheritScale = inherit; - // mNode is being used in a separate thread; queue a message to set the value - SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit ); + // node is being used in a separate thread; queue a message to set the value + SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit ); } } @@ -963,52 +948,32 @@ bool Actor::IsScaleInherited() const Matrix Actor::GetCurrentWorldMatrix() const { - if( NULL != mNode ) - { - return mNode->GetWorldMatrix(0); - } - - return Matrix::IDENTITY; + return GetNode().GetWorldMatrix(0); } 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 { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() ); - } - - return true; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() ); } void Actor::SetOpacity( float opacity ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeW, opacity ); - } + mTargetColor.a = opacity; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeW, opacity ); } float Actor::GetCurrentOpacity() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex()); - } - - return 1.0f; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex()); } ClippingMode::Type Actor::GetClippingMode() const @@ -1016,76 +981,62 @@ ClippingMode::Type Actor::GetClippingMode() const return mClippingMode; } -unsigned int Actor::GetSortingDepth() +uint32_t Actor::GetSortingDepth() { - return GetDepthIndex( mDepth, mSiblingOrder ); + return mSortedDepth; } const Vector4& Actor::GetCurrentWorldColor() const { - if( NULL != mNode ) - { - return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() ); - } - - return Color::WHITE; + return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() ); } void Actor::SetColor( const Vector4& color ) { - 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->mColor, &AnimatableProperty::Bake, color ); - } + mTargetColor = color; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::Bake, color ); } void Actor::SetColorRed( float red ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeX, red ); - } + mTargetColor.r = red; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeX, red ); } void Actor::SetColorGreen( float green ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeY, green ); - } + mTargetColor.g = green; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeY, green ); } void Actor::SetColorBlue( float blue ) { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeZ, blue ); - } + mTargetColor.b = blue; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeZ, blue ); } const Vector4& Actor::GetCurrentColor() const { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex()); - } - - return Color::WHITE; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex()); } void Actor::SetInheritOrientation( bool inherit ) { - if( mInheritOrientation != inherit && NULL != mNode) + if( mInheritOrientation != inherit ) { - // non animateable so keep local copy + // non animatable so keep local copy mInheritOrientation = inherit; - // mNode is being used in a separate thread; queue a message to set the value - SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit ); + // node is being used in a separate thread; queue a message to set the value + SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit ); } } @@ -1113,13 +1064,10 @@ const Vector3& Actor::GetSizeModeFactor() const void Actor::SetColorMode( ColorMode colorMode ) { - // non animateable so keep local copy + // non animatable so keep local copy mColorMode = colorMode; - if( NULL != mNode ) - { - // mNode is being used in a separate thread; queue a message to set the value - SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode ); - } + // node is being used in a separate thread; queue a message to set the value + SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode ); } ColorMode Actor::GetColorMode() const @@ -1166,15 +1114,14 @@ void Actor::SetSizeInternal( const Vector3& size ) // dont allow recursive loop DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" ); // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one - if( ( NULL != mNode )&& - ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )|| - ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )|| - ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) ) + if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )|| + ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )|| + ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) { mTargetSize = size; - // mNode is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler::Bake, mTargetSize ); + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformPropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler::Bake, mTargetSize ); // Notification for derived classes mInsideOnSizeSet = true; @@ -1189,100 +1136,71 @@ 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; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().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; + + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().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 ); - } + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodeTransformComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().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 { - if( NULL != mNode ) - { - // mNode is being used in a separate thread; copy the value from the previous update - return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() ); - } - - return Vector3::ZERO; + // node is being used in a separate thread; copy the value from the previous update + return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() ); } Vector3 Actor::GetNaturalSize() const @@ -1298,11 +1216,19 @@ void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimensio ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH); ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { 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; + } } } @@ -1361,11 +1287,18 @@ ResizePolicy::Type Actor::GetResizePolicy( 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 ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { - return mRelayoutData->resizePolicies[ i ]; + if( mRelayoutData->useAssignedSize[ i ] ) + { + return ResizePolicy::USE_ASSIGNED_SIZE; + } + else + { + return mRelayoutData->resizePolicies[ i ]; + } } } } @@ -1394,7 +1327,7 @@ void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type d { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -1408,7 +1341,7 @@ Dimension::Type Actor::GetDimensionDependency( 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 ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { @@ -1445,7 +1378,7 @@ void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension ) { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -1458,7 +1391,7 @@ bool Actor::IsLayoutDirty( Dimension::Type dimension ) const { if ( mRelayoutData ) { - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] ) { @@ -1480,32 +1413,32 @@ bool Actor::RelayoutRequired( Dimension::Type dimension ) const return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension ); } -unsigned int Actor::AddRenderer( Renderer& renderer ) +uint32_t Actor::AddRenderer( Renderer& renderer ) { if( !mRenderers ) { mRenderers = new RendererContainer; } - unsigned int index = mRenderers->size(); + uint32_t index = static_cast( mRenderers->size() ); // 4,294,967,295 renderers per actor RendererPtr rendererPtr = RendererPtr( &renderer ); mRenderers->push_back( rendererPtr ); - AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() ); + AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() ); return index; } -unsigned int Actor::GetRendererCount() const +uint32_t Actor::GetRendererCount() const { - unsigned int rendererCount(0); + uint32_t rendererCount(0); if( mRenderers ) { - rendererCount = mRenderers->size(); + rendererCount = static_cast( mRenderers->size() ); // 4,294,967,295 renderers per actor } return rendererCount; } -RendererPtr Actor::GetRendererAt( unsigned int index ) +RendererPtr Actor::GetRendererAt( uint32_t index ) { RendererPtr renderer; if( index < GetRendererCount() ) @@ -1526,19 +1459,19 @@ void Actor::RemoveRenderer( Renderer& renderer ) if( (*iter).Get() == &renderer ) { mRenderers->erase( iter ); - RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() ); + DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() ); break; } } } } -void Actor::RemoveRenderer( unsigned int index ) +void Actor::RemoveRenderer( uint32_t index ) { if( index < GetRendererCount() ) { RendererPtr renderer = ( *mRenderers )[ index ]; - RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() ); + DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() ); mRenderers->erase( mRenderers->begin()+index ); } } @@ -1552,11 +1485,9 @@ void Actor::SetDrawMode( DrawMode::Type drawMode ) { // this flag is not animatable so keep the value mDrawMode = drawMode; - if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) ) - { - // mNode is being used in a separate thread; queue a message to set the value - SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode ); - } + + // node is being used in a separate thread; queue a message to set the value + SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode ); } DrawMode::Type Actor::GetDrawMode() const @@ -1575,11 +1506,11 @@ bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float sc Vector2 converted( screenX, screenY ); // do a reverse traversal of all lists (as the default onscreen one is typically the last one) - const int taskCount = taskList.GetTaskCount(); - for( int i = taskCount - 1; i >= 0; --i ) + uint32_t taskCount = taskList.GetTaskCount(); + for( uint32_t i = taskCount; i > 0; --i ) { - Dali::RenderTask task = taskList.GetTask( i ); - if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) ) + RenderTaskPtr task = taskList.GetTask( i - 1 ); + if( ScreenToLocal( *task, localX, localY, screenX, screenY ) ) { // found a task where this conversion was ok so return return true; @@ -1614,7 +1545,7 @@ bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& l bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const { - // Early-out if mNode is NULL + // Early-out if not on stage if( !OnStage() ) { return false; @@ -1622,7 +1553,7 @@ bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMat // Get the ModelView matrix Matrix modelView; - Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix ); + Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix ); // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects Matrix invertedMvp( false/*don't init*/); @@ -1630,19 +1561,19 @@ bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMat bool success = invertedMvp.Invert(); // Convert to GL coordinates - Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f ); + Vector4 screenPos( screenX - static_cast( viewport.x ), static_cast( viewport.height ) - screenY - static_cast( viewport.y ), 0.f, 1.f ); Vector4 nearPos; if( success ) { - success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos ); + success = Unproject( screenPos, invertedMvp, static_cast( viewport.width ), static_cast( viewport.height ), nearPos ); } Vector4 farPos; if( success ) { screenPos.z = 1.0f; - success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos ); + success = Unproject( screenPos, invertedMvp, static_cast( viewport.width ), static_cast( viewport.height ), farPos ); } if( success ) @@ -1725,8 +1656,8 @@ bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) con C = o dot o - r^2 */ - // Early out if mNode is NULL - if( !mNode ) + // Early-out if not on stage + if( !OnStage() ) { return false; } @@ -1734,14 +1665,14 @@ bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) con BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed. - const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) ); + const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) ); Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z ); // Compute the radius is not needed, square radius it's enough. - const Vector3& size( mNode->GetSize( bufferIndex ) ); + const Vector3& size( GetNode().GetSize( bufferIndex ) ); // Scale the sphere. - const Vector3& scale( mNode->GetWorldScale( bufferIndex ) ); + const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) ); const float width = size.width * scale.width; const float height = size.height * scale.height; @@ -1759,14 +1690,14 @@ bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vecto { bool hit = false; - if( OnStage() && NULL != mNode ) + if( OnStage() ) { // Transforms the ray to the local reference system. // Calculate the inverse of Model matrix Matrix invModelMatrix( false/*don't init*/); BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); - invModelMatrix = mNode->GetWorldMatrix(0); + invModelMatrix = GetNode().GetWorldMatrix(0); invModelMatrix.Invert(); Vector4 rayOriginLocal( invModelMatrix * rayOrigin ); @@ -1782,7 +1713,7 @@ bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vecto // Ray travels distance * rayDirLocal to intersect with plane. distance = a / b; - const Vector3& size = mNode->GetSize( bufferIndex ); + const Vector3& size = GetNode().GetSize( bufferIndex ); hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f; hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f; @@ -1914,6 +1845,42 @@ 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 ); + } +} + +void Actor::EmitChildAddedSignal( Actor& child ) +{ + if( ! mChildAddedSignal.Empty() ) + { + Dali::Actor handle( &child ); + mChildAddedSignal.Emit( handle ); + } +} + +void Actor::EmitChildRemovedSignal( Actor& child ) +{ + if( ! mChildRemovedSignal.Empty() ) + { + Dali::Actor handle( &child ); + mChildRemovedSignal.Emit( handle ); + } +} + Dali::Actor::TouchSignalType& Actor::TouchedSignal() { return mTouchedSignal; @@ -1949,6 +1916,31 @@ Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal() return mOnRelayoutSignal; } +DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal() +{ + return mVisibilityChangedSignal; +} + +Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal() +{ + return mLayoutDirectionChangedSignal; +} + +DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal() +{ + return mChildAddedSignal; +} + +DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal() +{ + return mChildRemovedSignal; +} + +DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal() +{ + return mChildOrderChangedSignal; +} + bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { bool connected( true ); @@ -1982,6 +1974,22 @@ bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tra { actor->TouchSignal().Connect( tracker, functor ); } + else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) ) + { + actor->VisibilityChangedSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) ) + { + actor->LayoutDirectionChangedSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) ) + { + actor->ChildAddedSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) ) + { + actor->ChildRemovedSignal().Connect( tracker, functor ); + } else { // signalName does not match any signal @@ -1991,20 +1999,35 @@ bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tra return connected; } -Actor::Actor( DerivedType derivedType ) -: mParent( NULL ), +Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node ) +: Object( &node ), + mParent( NULL ), mChildren( NULL ), mRenderers( NULL ), - mNode( NULL ), mParentOrigin( NULL ), mAnchorPoint( NULL ), mRelayoutData( NULL ), mGestureData( NULL ), - mTargetSize( 0.0f, 0.0f, 0.0f ), + mTouchedSignal(), + mTouchSignal(), + mHoveredSignal(), + mWheelEventSignal(), + mOnStageSignal(), + mOffStageSignal(), + mOnRelayoutSignal(), + mVisibilityChangedSignal(), + mLayoutDirectionChangedSignal(), + mChildAddedSignal(), + mChildRemovedSignal(), + mChildOrderChangedSignal(), + 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 ), @@ -2019,8 +2042,11 @@ Actor::Actor( DerivedType derivedType ) mInheritPosition( true ), 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 ), mClippingMode( ClippingMode::DISABLED ) { @@ -2028,12 +2054,6 @@ 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 - OnInitialize(); GetEventThreadServices().RegisterObject( this ); @@ -2057,11 +2077,7 @@ Actor::~Actor() // Guard to allow handle destruction after Core has been destroyed if( EventThreadServices::IsCoreRunning() ) { - if( NULL != mNode ) - { - DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); - mNode = NULL; // Node is about to be destroyed - } + DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() ); GetEventThreadServices().UnregisterObject( this ); } @@ -2074,18 +2090,21 @@ Actor::~Actor() delete mAnchorPoint; // Delete optional relayout data - if( mRelayoutData ) - { - delete mRelayoutData; - } + delete mRelayoutData; } -void Actor::ConnectToStage( unsigned int parentDepth ) +void Actor::ConnectToStage( uint32_t parentDepth ) { // This container is used instead of walking the Actor hierarchy. // 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 ); @@ -2099,13 +2118,12 @@ void Actor::ConnectToStage( unsigned int parentDepth ) RelayoutRequest(); } -void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth ) +void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth ) { DALI_ASSERT_ALWAYS( !OnStage() ); mIsOnStage = true; - mDepth = depth; - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); + mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice ConnectToSceneGraph(); @@ -2121,7 +2139,7 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in ActorConstIter endIter = mChildren->end(); for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter ) { - (*iter)->RecursiveConnectToStage( connectionList, depth+1 ); + (*iter)->RecursiveConnectToStage( connectionList, depth + 1 ); } } } @@ -2134,13 +2152,10 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in */ void Actor::ConnectToSceneGraph() { - DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL ); + DALI_ASSERT_DEBUG( mParent != NULL); - if( NULL != mNode ) - { - // Reparent Node in next Update - ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode ); - } + // Reparent Node in next Update + ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() ); // Request relayout on all actors that are added to the scenegraph RelayoutRequest(); @@ -2178,6 +2193,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 ); @@ -2191,7 +2212,8 @@ void Actor::DisconnectFromStage() void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList ) { - DALI_ASSERT_ALWAYS( OnStage() ); + // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value + mIsOnStage = false; // Recursively disconnect children if( mChildren ) @@ -2210,8 +2232,6 @@ void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList ) OnStageDisconnectionInternal(); DisconnectFromSceneGraph(); - - mIsOnStage = false; } /** @@ -2252,9 +2272,9 @@ bool Actor::IsNodeConnected() const { bool connected( false ); - if( OnStage() && ( NULL != mNode ) ) + if( OnStage() ) { - if( IsRoot() || mNode->GetParent() ) + if( IsRoot() || GetNode().GetParent() ) { connected = true; } @@ -2263,88 +2283,42 @@ bool Actor::IsNodeConnected() const return connected; } -unsigned int Actor::GetDefaultPropertyCount() const -{ - return DEFAULT_PROPERTY_COUNT; -} - -void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +// 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() { - indices.Reserve( DEFAULT_PROPERTY_COUNT ); + DALI_LOG_TIMER_START(depthTimer); - for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) - { - indices.PushBack( i ); - } -} + // Vector of scene-graph nodes and their depths to send to UpdateManager + // in a single message + OwnerPointer sceneGraphNodeDepths( new SceneGraph::NodeDepths() ); -const char* Actor::GetDefaultPropertyName( Property::Index index ) const -{ - if( index < DEFAULT_PROPERTY_COUNT ) - { - return DEFAULT_PROPERTY_DETAILS[ index ].name; - } + int32_t depthIndex = 1; + DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex ); - return NULL; + SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths ); + DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: "); } -Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const +void Actor::DepthTraverseActorTree( OwnerPointer& sceneGraphNodeDepths, int32_t& depthIndex ) { - Property::Index index = Property::INVALID_INDEX; + mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER; + sceneGraphNodeDepths->Add( const_cast( &GetNode() ), mSortedDepth ); - // Look for name in default properties - for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + // Create/add to children of this node + if( mChildren ) { - const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; - if( 0 == name.compare( property->name ) ) + for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it ) { - index = i; - break; + Actor* childActor = (*it).Get(); + ++depthIndex; + childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex ); } } - - return index; -} - -bool Actor::IsDefaultPropertyWritable( Property::Index index ) const -{ - if( index < DEFAULT_PROPERTY_COUNT ) - { - return DEFAULT_PROPERTY_DETAILS[ index ].writable; - } - - return false; -} - -bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const -{ - if( index < DEFAULT_PROPERTY_COUNT ) - { - return DEFAULT_PROPERTY_DETAILS[ index ].animatable; - } - - return false; -} - -bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const -{ - if( index < DEFAULT_PROPERTY_COUNT ) - { - return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput; - } - - return false; -} - -Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const -{ - if( index < DEFAULT_PROPERTY_COUNT ) - { - return DEFAULT_PROPERTY_DETAILS[ index ].type; - } - - // index out of range...return Property::NONE - return Property::NONE; } void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property ) @@ -2536,8 +2510,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; } @@ -2587,16 +2566,6 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } - case Dali::Actor::Property::POSITION_INHERITANCE: - { - PositionInheritanceMode mode = mPositionInheritanceMode; - if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) ) - { - SetPositionInheritanceMode( mode ); - } - break; - } - case Dali::Actor::Property::DRAW_MODE: { DrawMode::Type mode = mDrawMode; @@ -2615,7 +2584,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr case Dali::Actor::Property::WIDTH_RESIZE_POLICY: { - ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set. + ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH ); if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) ) { SetResizePolicy( type, Dimension::WIDTH ); @@ -2625,7 +2594,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: { - ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set. + ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT ); if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) ) { SetResizePolicy( type, Dimension::HEIGHT ); @@ -2635,7 +2604,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr case Dali::Actor::Property::SIZE_SCALE_POLICY: { - SizeScalePolicy::Type type; + SizeScalePolicy::Type type = GetSizeScalePolicy(); if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) ) { SetSizeScalePolicy( type ); @@ -2691,14 +2660,7 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr if( property.Get( value ) ) { - if( static_cast(value) != mSiblingOrder ) - { - mSiblingOrder = value; - if( mIsOnStage ) - { - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); - } - } + SetSiblingOrder( value ); } break; } @@ -2709,10 +2671,40 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) ) { mClippingMode = convertedValue; - if( NULL != mNode ) - { - SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode ); - } + SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode ); + } + break; + } + + case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + { + bool value = false; + if( property.Get( value ) && value != mPositionUsesAnchorPoint ) + { + mPositionUsesAnchorPoint = value; + SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint ); + } + 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; } @@ -2736,7 +2728,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); break; } @@ -2747,7 +2739,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); break; } @@ -2758,7 +2750,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); break; } @@ -2771,15 +2763,15 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeX, value.Get() ); } else if(entry.componentIndex == 1) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeY, value.Get() ); } else { - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); } break; @@ -2793,19 +2785,19 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeX, value.Get() ); } else if(entry.componentIndex == 1) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeY, value.Get() ); } else if(entry.componentIndex == 2) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeZ, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeZ, value.Get() ); } else { - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); } break; @@ -2819,23 +2811,23 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeX, value.Get() ); } else if(entry.componentIndex == 1) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeY, value.Get() ); } else if(entry.componentIndex == 2) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeZ, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeZ, value.Get() ); } else if(entry.componentIndex == 3) { - SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeW, value.Get() ); + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::BakeW, value.Get() ); } else { - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty::Bake, value.Get() ); } break; @@ -2847,7 +2839,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty::Bake, value.Get() ); break; } @@ -2858,7 +2850,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty::Bake, value.Get() ); break; } @@ -2869,7 +2861,7 @@ void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty::Bake, value.Get() ); break; } @@ -2885,816 +2877,1092 @@ 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 ) - { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().width; - } - else - { - value = GetTargetSize().width; - } - break; - } + case Dali::Actor::Property::ORIENTATION: + { + value.Get( mTargetOrientation ); + 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::SCALE: + { + value.Get( mTargetScale ); + break; + } - case Dali::Actor::Property::SIZE_DEPTH: - { - value = GetTargetSize().depth; - break; - } + case Dali::Actor::Property::SCALE_X: + { + value.Get( mTargetScale.x ); + break; + } - case Dali::Actor::Property::POSITION: - { - value = GetTargetPosition(); - break; - } + case Dali::Actor::Property::SCALE_Y: + { + value.Get( mTargetScale.y ); + break; + } - case Dali::Actor::Property::POSITION_X: - { - value = GetTargetPosition().x; - break; - } + case Dali::Actor::Property::SCALE_Z: + { + value.Get( mTargetScale.z ); + break; + } - case Dali::Actor::Property::POSITION_Y: - { - value = GetTargetPosition().y; - break; - } + case Dali::Actor::Property::VISIBLE: + { + SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE ); + break; + } - case Dali::Actor::Property::POSITION_Z: - { - value = GetTargetPosition().z; - break; - } + case Dali::Actor::Property::COLOR: + { + value.Get( mTargetColor ); + break; + } - case Dali::Actor::Property::WORLD_POSITION: - { - value = GetCurrentWorldPosition(); - break; - } + case Dali::Actor::Property::COLOR_RED: + { + value.Get( mTargetColor.r ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_X: - { - value = GetCurrentWorldPosition().x; - break; - } + case Dali::Actor::Property::COLOR_GREEN: + { + value.Get( mTargetColor.g ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_Y: - { - value = GetCurrentWorldPosition().y; - break; - } + case Dali::Actor::Property::COLOR_BLUE: + { + value.Get( mTargetColor.b ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_Z: - { - value = GetCurrentWorldPosition().z; + 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 Dali::Actor::Property::ORIENTATION: + case Animation::BY: { - value = GetCurrentOrientation(); + 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; } + } +} - case Dali::Actor::Property::WORLD_ORIENTATION: +const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const +{ + const PropertyBase* property( NULL ); + + switch( index ) + { + case Dali::Actor::Property::SIZE: // FALLTHROUGH + case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH + case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH + case Dali::Actor::Property::SIZE_DEPTH: { - value = GetCurrentWorldOrientation(); + property = &GetNode().mSize; break; } - - case Dali::Actor::Property::SCALE: + case Dali::Actor::Property::POSITION: // FALLTHROUGH + case Dali::Actor::Property::POSITION_X: // FALLTHROUGH + case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH + case Dali::Actor::Property::POSITION_Z: { - value = GetCurrentScale(); + property = &GetNode().mPosition; break; } - - case Dali::Actor::Property::SCALE_X: + case Dali::Actor::Property::ORIENTATION: { - value = GetCurrentScale().x; + property = &GetNode().mOrientation; break; } - - case Dali::Actor::Property::SCALE_Y: + case Dali::Actor::Property::SCALE: // FALLTHROUGH + case Dali::Actor::Property::SCALE_X: // FALLTHROUGH + case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH + case Dali::Actor::Property::SCALE_Z: { - value = GetCurrentScale().y; + property = &GetNode().mScale; break; } - - case Dali::Actor::Property::SCALE_Z: + case Dali::Actor::Property::VISIBLE: { - value = GetCurrentScale().z; + property = &GetNode().mVisible; break; } - - case Dali::Actor::Property::WORLD_SCALE: + case Dali::Actor::Property::COLOR: // FALLTHROUGH + case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH + case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH + case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH + case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH + case Dali::DevelActor::Property::OPACITY: { - value = GetCurrentWorldScale(); + property = &GetNode().mColor; break; } - - case Dali::Actor::Property::VISIBLE: + default: { - value = IsVisible(); break; } + } + if( !property ) + { + // not our property, ask base + property = Object::GetSceneObjectAnimatableProperty( index ); + } - case Dali::Actor::Property::COLOR: + return property; +} + +const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const +{ + const PropertyInputImpl* property( NULL ); + + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH + case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH + case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH + case Dali::Actor::Property::PARENT_ORIGIN_Z: { - value = GetCurrentColor(); + property = &GetNode().mParentOrigin; break; } - - case Dali::Actor::Property::COLOR_RED: + case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH + case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH + case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH + case Dali::Actor::Property::ANCHOR_POINT_Z: { - value = GetCurrentColor().r; + property = &GetNode().mAnchorPoint; break; } - - case Dali::Actor::Property::COLOR_GREEN: + case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH + case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH + case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH + case Dali::Actor::Property::WORLD_POSITION_Z: { - value = GetCurrentColor().g; + property = &GetNode().mWorldPosition; break; } - - case Dali::Actor::Property::COLOR_BLUE: + case Dali::Actor::Property::WORLD_ORIENTATION: { - value = GetCurrentColor().b; + property = &GetNode().mWorldOrientation; break; } - - case Dali::Actor::Property::COLOR_ALPHA: + case Dali::Actor::Property::WORLD_SCALE: { - value = GetCurrentColor().a; + property = &GetNode().mWorldScale; break; } - case Dali::Actor::Property::WORLD_COLOR: { - value = GetCurrentWorldColor(); + property = &GetNode().mWorldColor; break; } - case Dali::Actor::Property::WORLD_MATRIX: { - value = GetCurrentWorldMatrix(); + property = &GetNode().mWorldMatrix; break; } - - case Dali::Actor::Property::NAME: + case Dali::DevelActor::Property::CULLED: { - value = GetName(); + property = &GetNode().mCulled; break; } - - case Dali::Actor::Property::SENSITIVE: + default: { - value = IsSensitive(); break; } + } + if( !property ) + { + // reuse animatable property getter as animatable properties are inputs as well + // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered + property = GetSceneObjectAnimatableProperty( index ); + } - case Dali::Actor::Property::LEAVE_REQUIRED: - { - value = GetLeaveRequired(); - break; - } + return property; +} - case Dali::Actor::Property::INHERIT_POSITION: - { - value = IsPositionInherited(); - break; - } +int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const +{ + int32_t componentIndex = Property::INVALID_COMPONENT_INDEX; - case Dali::Actor::Property::INHERIT_ORIENTATION: + 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: { - value = IsOrientationInherited(); + componentIndex = 0; break; } - case Dali::Actor::Property::INHERIT_SCALE: + 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 = IsScaleInherited(); + componentIndex = 1; break; } - case Dali::Actor::Property::COLOR_MODE: + 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: { - value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); + componentIndex = 2; break; } - case Dali::Actor::Property::POSITION_INHERITANCE: + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: { - value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); + componentIndex = 3; break; } - case Dali::Actor::Property::DRAW_MODE: + default: { - value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); + // Do nothing break; } + } + if( Property::INVALID_COMPONENT_INDEX == componentIndex ) + { + // ask base + componentIndex = Object::GetPropertyComponentIndex( index ); + } - case Dali::Actor::Property::SIZE_MODE_FACTOR: - { - value = GetSizeModeFactor(); - break; - } + return componentIndex; +} - case Dali::Actor::Property::WIDTH_RESIZE_POLICY: - { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); - break; - } +void Actor::SetParent( Actor* parent ) +{ + if( parent ) + { + DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" ); - case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: - { - value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT ); - break; - } + mParent = parent; - case Dali::Actor::Property::SIZE_SCALE_POLICY: + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + parent->OnStage() ) { - value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT ); - break; + // Instruct each actor to create a corresponding node in the scene graph + ConnectToStage( parent->GetHierarchyDepth() ); } - case Dali::Actor::Property::WIDTH_FOR_HEIGHT: - { - value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); - 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" ); + + mParent = NULL; + + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + OnStage() ) + { + // Disconnect the Node & its children from the scene-graph. + DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() ); + + // Instruct each actor to discard pointers to the scene-graph + DisconnectFromStage(); } + } +} - case Dali::Actor::Property::HEIGHT_FOR_WIDTH: +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 = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH ); - break; + actor->SetVisible( true ); + done = true; + } + else if( 0 == actionName.compare( ACTION_HIDE ) ) + { + actor->SetVisible( false ); + done = true; } + } - case Dali::Actor::Property::PADDING: + return done; +} + +bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; + + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: { - Vector2 widthPadding = GetPadding( Dimension::WIDTH ); - Vector2 heightPadding = GetPadding( Dimension::HEIGHT ); - value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y ); + value = GetCurrentParentOrigin(); break; } - case Dali::Actor::Property::MINIMUM_SIZE: + case Dali::Actor::Property::PARENT_ORIGIN_X: { - value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); + value = GetCurrentParentOrigin().x; break; } - case Dali::Actor::Property::MAXIMUM_SIZE: + case Dali::Actor::Property::PARENT_ORIGIN_Y: { - value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + value = GetCurrentParentOrigin().y; break; } - case Dali::DevelActor::Property::SIBLING_ORDER: + case Dali::Actor::Property::PARENT_ORIGIN_Z: { - value = static_cast(mSiblingOrder); + value = GetCurrentParentOrigin().z; break; } - case Dali::Actor::Property::CLIPPING_MODE: + case Dali::Actor::Property::ANCHOR_POINT: { - value = mClippingMode; + value = GetCurrentAnchorPoint(); 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::ANCHOR_POINT_X: { - 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; + value = GetCurrentAnchorPoint().x; + break; + } - case Dali::Actor::Property::POSITION_X: - property = &mNode->mPosition; - break; + case Dali::Actor::Property::ANCHOR_POINT_Y: + { + value = GetCurrentAnchorPoint().y; + break; + } - case Dali::Actor::Property::POSITION_Y: - property = &mNode->mPosition; - break; + case Dali::Actor::Property::ANCHOR_POINT_Z: + { + value = GetCurrentAnchorPoint().z; + break; + } - case Dali::Actor::Property::POSITION_Z: - property = &mNode->mPosition; - break; + case Dali::Actor::Property::SIZE: + { + value = GetTargetSize(); + break; + } - case Dali::Actor::Property::ORIENTATION: - property = &mNode->mOrientation; - break; + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetTargetSize().width; + break; + } - case Dali::Actor::Property::SCALE: - property = &mNode->mScale; - break; + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetTargetSize().height; + break; + } - case Dali::Actor::Property::SCALE_X: - property = &mNode->mScale; - break; + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetTargetSize().depth; + break; + } - case Dali::Actor::Property::SCALE_Y: - property = &mNode->mScale; - break; + case Dali::Actor::Property::POSITION: + { + value = GetTargetPosition(); + break; + } - case Dali::Actor::Property::SCALE_Z: - property = &mNode->mScale; - break; + case Dali::Actor::Property::POSITION_X: + { + value = GetTargetPosition().x; + break; + } - case Dali::Actor::Property::VISIBLE: - property = &mNode->mVisible; - break; + case Dali::Actor::Property::POSITION_Y: + { + value = GetTargetPosition().y; + break; + } - case Dali::Actor::Property::COLOR: - property = &mNode->mColor; - break; + case Dali::Actor::Property::POSITION_Z: + { + value = GetTargetPosition().z; + break; + } - case Dali::Actor::Property::COLOR_RED: - property = &mNode->mColor; - break; + case Dali::Actor::Property::ORIENTATION: + { + value = mTargetOrientation; + break; + } - case Dali::Actor::Property::COLOR_GREEN: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SCALE: + { + value = mTargetScale; + break; + } - case Dali::Actor::Property::COLOR_BLUE: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SCALE_X: + { + value = mTargetScale.x; + break; + } - case Dali::Actor::Property::COLOR_ALPHA: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SCALE_Y: + { + value = mTargetScale.y; + break; + } - default: - break; + case Dali::Actor::Property::SCALE_Z: + { + value = mTargetScale.z; + break; } - } - return property; -} + case Dali::Actor::Property::VISIBLE: + { + value = mVisible; + break; + } -const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const -{ - const PropertyInputImpl* property( NULL ); + case Dali::Actor::Property::COLOR: + { + value = mTargetColor; + break; + } - // This method should only return a property of an object connected to the scene-graph - if( !OnStage() ) - { - return property; - } + case Dali::Actor::Property::COLOR_RED: + { + value = mTargetColor.r; + break; + } - 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" ); + case Dali::Actor::Property::COLOR_GREEN: + { + value = mTargetColor.g; + break; + } - 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::COLOR_BLUE: { - case Dali::Actor::Property::PARENT_ORIGIN: - property = &mNode->mParentOrigin; - break; + value = mTargetColor.b; + break; + } - case Dali::Actor::Property::PARENT_ORIGIN_X: - property = &mNode->mParentOrigin; - break; + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value = mTargetColor.a; + break; + } - case Dali::Actor::Property::PARENT_ORIGIN_Y: - property = &mNode->mParentOrigin; - break; + case Dali::Actor::Property::NAME: + { + value = GetName(); + break; + } - case Dali::Actor::Property::PARENT_ORIGIN_Z: - property = &mNode->mParentOrigin; - break; + case Dali::Actor::Property::SENSITIVE: + { + value = IsSensitive(); + break; + } - case Dali::Actor::Property::ANCHOR_POINT: - property = &mNode->mAnchorPoint; - break; + case Dali::Actor::Property::LEAVE_REQUIRED: + { + value = GetLeaveRequired(); + break; + } - case Dali::Actor::Property::ANCHOR_POINT_X: - property = &mNode->mAnchorPoint; - break; + case Dali::Actor::Property::INHERIT_POSITION: + { + value = IsPositionInherited(); + break; + } - case Dali::Actor::Property::ANCHOR_POINT_Y: - property = &mNode->mAnchorPoint; - break; + case Dali::Actor::Property::INHERIT_ORIENTATION: + { + value = IsOrientationInherited(); + break; + } - case Dali::Actor::Property::ANCHOR_POINT_Z: - property = &mNode->mAnchorPoint; - break; + case Dali::Actor::Property::INHERIT_SCALE: + { + value = IsScaleInherited(); + break; + } - case Dali::Actor::Property::SIZE: - property = &mNode->mSize; - break; + case Dali::Actor::Property::COLOR_MODE: + { + value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); + break; + } - case Dali::Actor::Property::SIZE_WIDTH: - property = &mNode->mSize; - 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_HEIGHT: - property = &mNode->mSize; - break; + case Dali::Actor::Property::SIZE_MODE_FACTOR: + { + value = GetSizeModeFactor(); + break; + } - case Dali::Actor::Property::SIZE_DEPTH: - property = &mNode->mSize; - 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::POSITION: - property = &mNode->mPosition; - 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::POSITION_X: - property = &mNode->mPosition; - 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::POSITION_Y: - property = &mNode->mPosition; - 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::POSITION_Z: - property = &mNode->mPosition; - 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: - 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_X: - 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_Y: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::MAXIMUM_SIZE: + { + value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + break; + } - case Dali::Actor::Property::WORLD_POSITION_Z: - property = &mNode->mWorldPosition; - break; + case Dali::Actor::Property::CLIPPING_MODE: + { + value = mClippingMode; + break; + } - case Dali::Actor::Property::ORIENTATION: - property = &mNode->mOrientation; - break; + case Dali::DevelActor::Property::SIBLING_ORDER: + { + value = static_cast( GetSiblingOrder() ); + break; + } - case Dali::Actor::Property::WORLD_ORIENTATION: - property = &mNode->mWorldOrientation; - break; + case Dali::DevelActor::Property::SCREEN_POSITION: + { + value = GetCurrentScreenPosition(); + break; + } - case Dali::Actor::Property::SCALE: - property = &mNode->mScale; - break; + case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT: + { + value = mPositionUsesAnchorPoint; + break; + } - case Dali::Actor::Property::SCALE_X: - property = &mNode->mScale; - break; + case Dali::Actor::Property::LAYOUT_DIRECTION: + { + value = mLayoutDirection; + break; + } - case Dali::Actor::Property::SCALE_Y: - property = &mNode->mScale; - break; + case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION: + { + value = IsLayoutDirectionInherited(); + break; + } - case Dali::Actor::Property::SCALE_Z: - property = &mNode->mScale; - break; + default: + { + // Must be a scene-graph only property + valueSet = false; + break; + } + } - case Dali::Actor::Property::WORLD_SCALE: - property = &mNode->mWorldScale; - break; + return valueSet; +} - case Dali::Actor::Property::VISIBLE: - property = &mNode->mVisible; - break; +bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const +{ + bool valueSet = true; - case Dali::Actor::Property::COLOR: - property = &mNode->mColor; - break; + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + value = GetCurrentSize(); + break; + } - case Dali::Actor::Property::COLOR_RED: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetCurrentSize().width; + break; + } - case Dali::Actor::Property::COLOR_GREEN: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetCurrentSize().height; + break; + } - case Dali::Actor::Property::COLOR_BLUE: - property = &mNode->mColor; - break; + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetCurrentSize().depth; + break; + } - case Dali::Actor::Property::COLOR_ALPHA: - property = &mNode->mColor; - break; + case Dali::Actor::Property::POSITION: + { + value = GetCurrentPosition(); + break; + } - case Dali::Actor::Property::WORLD_COLOR: - property = &mNode->mWorldColor; - break; + case Dali::Actor::Property::POSITION_X: + { + value = GetCurrentPosition().x; + break; + } - case Dali::Actor::Property::WORLD_MATRIX: - property = &mNode->mWorldMatrix; - break; + case Dali::Actor::Property::POSITION_Y: + { + value = GetCurrentPosition().y; + break; + } - default: - break; + case Dali::Actor::Property::POSITION_Z: + { + value = GetCurrentPosition().z; + break; } - } - return property; -} + case Dali::Actor::Property::WORLD_POSITION: + { + value = GetCurrentWorldPosition(); + break; + } -int Actor::GetPropertyComponentIndex( Property::Index index ) const -{ - int componentIndex( Property::INVALID_COMPONENT_INDEX ); + case Dali::Actor::Property::WORLD_POSITION_X: + { + value = GetCurrentWorldPosition().x; + 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_Y: { - componentIndex = animatableProperty->componentIndex; + value = GetCurrentWorldPosition().y; + break; } - } - else - { - switch( index ) + + case Dali::Actor::Property::WORLD_POSITION_Z: { - 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().z; + 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::ORIENTATION: + { + value = GetCurrentOrientation(); + 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::WORLD_ORIENTATION: + { + value = GetCurrentWorldOrientation(); + break; + } - case Dali::Actor::Property::COLOR_ALPHA: - { - componentIndex = 3; - break; - } + case Dali::Actor::Property::SCALE: + { + value = GetCurrentScale(); + break; + } - default: - { - // Do nothing - break; - } + case Dali::Actor::Property::SCALE_X: + { + value = GetCurrentScale().x; + break; } - } - return componentIndex; -} + case Dali::Actor::Property::SCALE_Y: + { + value = GetCurrentScale().y; + break; + } -void Actor::SetParent( Actor* parent ) -{ - if( parent ) - { - DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" ); + case Dali::Actor::Property::SCALE_Z: + { + value = GetCurrentScale().z; + break; + } - mParent = parent; + case Dali::Actor::Property::WORLD_SCALE: + { + value = GetCurrentWorldScale(); + break; + } - if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction - parent->OnStage() ) + case Dali::Actor::Property::COLOR: { - // Instruct each actor to create a corresponding node in the scene graph - ConnectToStage( parent->GetHierarchyDepth() ); + value = GetCurrentColor(); + 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_RED: + { + value = GetCurrentColor().r; + break; + } - mParent = NULL; + case Dali::Actor::Property::COLOR_GREEN: + { + value = GetCurrentColor().g; + break; + } - if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction - OnStage() ) + case Dali::Actor::Property::COLOR_BLUE: { - DALI_ASSERT_ALWAYS( mNode != NULL ); + value = GetCurrentColor().b; + break; + } - if( NULL != mNode ) - { - // Disconnect the Node & its children from the scene-graph. - DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); - } + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value = GetCurrentColor().a; + break; + } - // Instruct each actor to discard pointers to the scene-graph - DisconnectFromStage(); + case Dali::Actor::Property::WORLD_COLOR: + { + value = GetCurrentWorldColor(); + break; } - } -} -SceneGraph::Node* Actor::CreateNode() const -{ - return Node::New(); -} + case Dali::Actor::Property::WORLD_MATRIX: + { + value = GetCurrentWorldMatrix(); + 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::VISIBLE: + { + value = IsVisible(); + break; + } - if( actor ) - { - if( 0 == actionName.compare( ACTION_SHOW ) ) + case DevelActor::Property::CULLED: { - actor->SetVisible( true ); - done = true; + value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() ); + 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() @@ -3709,7 +3977,7 @@ void Actor::EnsureRelayoutData() bool Actor::RelayoutDependentOnParent( Dimension::Type dimension ) { // Check if actor is dependent on parent - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { @@ -3727,7 +3995,7 @@ bool Actor::RelayoutDependentOnParent( Dimension::Type dimension ) bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension ) { // Check if actor is dependent on children - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { @@ -3759,7 +4027,7 @@ bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension ) bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension ) { // Check each possible dimension and see if it is dependent on the input one - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -3772,7 +4040,7 @@ bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension:: void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension ) { - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -3784,7 +4052,7 @@ void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type d float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const { // If more than one dimension is requested, just return the first one found - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { @@ -3799,7 +4067,7 @@ void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension ) { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -3813,7 +4081,7 @@ Vector2 Actor::GetPadding( 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 ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) ) { @@ -3829,7 +4097,7 @@ void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension ) { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -3842,7 +4110,7 @@ bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const { if ( mRelayoutData ) { - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] ) { @@ -3962,7 +4230,7 @@ float Actor::NegotiateFromChildren( Dimension::Type dimension ) { float maxDimensionPoint = 0.0f; - for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) + for( uint32_t i = 0, count = GetChildCount(); i < count; ++i ) { ActorPtr child = GetChildAt( i ); @@ -3980,7 +4248,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 @@ -4077,7 +4345,7 @@ void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& alloca recursionStack.push_back( ActorDimensionPair( this, dimension ) ); // Dimension dependency check - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i ); @@ -4097,7 +4365,7 @@ void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& alloca // Children dependency check if( RelayoutDependentOnChildren( dimension ) ) { - for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) + for( uint32_t i = 0, count = GetChildCount(); i < count; ++i ) { ActorPtr child = GetChildAt( i ); @@ -4137,7 +4405,7 @@ void Actor::NegotiateDimensions( const Vector2& allocatedSize ) // Negotiate all dimensions that require it ActorDimensionStack recursionStack; - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i ); @@ -4146,7 +4414,7 @@ void Actor::NegotiateDimensions( const Vector2& allocatedSize ) } } -Vector2 Actor::ApplySizeSetPolicy( const Vector2 size ) +Vector2 Actor::ApplySizeSetPolicy( const Vector2& size ) { switch( mRelayoutData->sizeSetPolicy ) { @@ -4250,13 +4518,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,20 +4536,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 ) + for( uint32_t 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); @@ -4288,9 +4557,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( uint32_t 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( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->useAssignedSize[ i ]; + } } } + + return false; } void Actor::RelayoutRequest( Dimension::Type dimension ) @@ -4344,7 +4645,7 @@ void Actor::SetMinimumSize( float size, Dimension::Type dimension ) { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -4359,7 +4660,7 @@ float Actor::GetMinimumSize( Dimension::Type dimension ) const { if ( mRelayoutData ) { - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -4375,7 +4676,7 @@ void Actor::SetMaximumSize( float size, Dimension::Type dimension ) { EnsureRelayoutData(); - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -4390,7 +4691,7 @@ float Actor::GetMaximumSize( Dimension::Type dimension ) const { if ( mRelayoutData ) { - for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { if( dimension & ( 1 << i ) ) { @@ -4407,6 +4708,306 @@ Object* Actor::GetParentObject() const return mParent; } +void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) +{ + if( mVisible != visible ) + { + if( sendMessage == SendMessage::TRUE ) + { + // node is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().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( uint32_t order ) +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + uint32_t currentOrder = GetSiblingOrder(); + + if( order != currentOrder ) + { + if( order == 0 ) + { + LowerToBottom(); + } + else if( order < siblings.size() -1 ) + { + if( order > currentOrder ) + { + RaiseAbove( *siblings[order] ); + } + else + { + LowerBelow( *siblings[order] ); + } + } + else + { + RaiseToTop(); + } + } + } +} + +uint32_t Actor::GetSiblingOrder() const +{ + uint32_t order = 0; + + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + for( std::size_t i = 0; i < siblings.size(); ++i ) + { + if( siblings[i] == this ) + { + order = static_cast( i ); + break; + } + } + } + + return order; +} + +void Actor::RequestRebuildDepthTree() +{ + if( mIsOnStage ) + { + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + } +} + +void Actor::Raise() +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this ) // If not already at end + { + for( std::size_t i=0; imChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::Lower() +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this ) // If not already at beginning + { + for( std::size_t i=1; imChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::RaiseToTop() +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this ) // If not already at end + { + ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this ); + if( iter != siblings.end() ) + { + siblings.erase(iter); + siblings.push_back(ActorPtr(this)); + } + } + + Dali::Actor handle( this ); + mParent->mChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::LowerToBottom() +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this ) // If not already at bottom, + { + ActorPtr thisPtr(this); // ensure this actor remains referenced. + + ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this ); + if( iter != siblings.end() ) + { + siblings.erase(iter); + siblings.insert(siblings.begin(), thisPtr); + } + } + + Dali::Actor handle( this ); + mParent->mChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::RaiseAbove( Internal::Actor& target ) +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.back() != this && target.mParent == mParent ) // If not already at top + { + ActorPtr thisPtr(this); // ensure this actor remains referenced. + + ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target ); + ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this ); + if( thisIter < targetIter ) + { + 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); + } + + Dali::Actor handle( this ); + mParent->mChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +void Actor::LowerBelow( Internal::Actor& target ) +{ + if ( mParent ) + { + ActorContainer& siblings = *(mParent->mChildren); + if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom + { + ActorPtr thisPtr(this); // ensure this actor remains referenced. + + ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target ); + ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this ); + + if( thisIter > targetIter ) + { + siblings.erase(thisIter); // this only invalidates iterators at or after this point. + siblings.insert(targetIter, thisPtr); + } + + Dali::Actor handle( this ); + mParent->mChildOrderChangedSignal.Emit( handle ); + + RequestRebuildDepthTree(); + } + } + else + { + DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" ); + } +} + +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