X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-impl.cpp;h=8df598ebb2e686d062ff492c46edd385d058656b;hb=462cbee2270984cdca45488f3733d664dcf49187;hp=ee6089236446be1ce359bf71f5953cd1ad07f386;hpb=b7a2625f66a16845af4fc44256126f32b9a0ac7e;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 ee60892..8df598e 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,11 @@ using Dali::Internal::SceneGraph::Node; using Dali::Internal::SceneGraph::AnimatableProperty; using Dali::Internal::SceneGraph::PropertyBase; +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" ); +Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" ); +#endif + namespace Dali { @@ -127,6 +133,7 @@ struct Actor::RelayoutData for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) { resizePolicies[ i ] = ResizePolicy::DEFAULT; + useAssignedSize[ i ] = false; negotiatedDimensions[ i ] = 0.0f; dimensionNegotiated[ i ] = false; dimensionDirty[ i ] = false; @@ -138,6 +145,7 @@ struct Actor::RelayoutData } ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies + bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies @@ -385,11 +393,6 @@ float GetDimensionValue( const Vector3& values, Dimension::Type dimension ) return GetDimensionValue( values.GetVectorXY(), dimension ); } -unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder ) -{ - return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER; -} - /** * @brief Recursively emits the visibility-changed-signal on the actor tree. * @param[in] actor The actor to emit the signal on @@ -1053,19 +1056,7 @@ Matrix Actor::GetCurrentWorldMatrix() const void Actor::SetVisible( bool visible ) { - if( mVisible != 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 ); - } - - mVisible = visible; - - // Emit the signal on this actor and all its children - EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF ); - } + SetVisibleInternal( visible, SendMessage::TRUE ); } bool Actor::IsVisible() const @@ -1108,7 +1099,7 @@ ClippingMode::Type Actor::GetClippingMode() const unsigned int Actor::GetSortingDepth() { - return GetDepthIndex( mDepth, mSiblingOrder ); + return mSortedDepth; } const Vector4& Actor::GetCurrentWorldColor() const @@ -1287,53 +1278,6 @@ 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 ) -{ - if ( Dali::Actor::Property::SIZE_WIDTH == property ) - { - mTargetSize.width = targetSize; - } - else if ( Dali::Actor::Property::SIZE_HEIGHT == property ) - { - mTargetSize.height = targetSize; - } - else if ( Dali::Actor::Property::SIZE_DEPTH == property ) - { - mTargetSize.depth = targetSize; - } - // Notify deriving classes - OnSizeAnimation( animation, mTargetSize ); -} - -void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition ) -{ - mTargetPosition = targetPosition; -} - -void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property ) -{ - if ( Dali::Actor::Property::POSITION_X == property ) - { - mTargetPosition.x = targetPosition; - } - else if ( Dali::Actor::Property::POSITION_Y == property ) - { - mTargetPosition.y = targetPosition; - } - else if ( Dali::Actor::Property::POSITION_Z == property ) - { - mTargetPosition.z = targetPosition; - } -} - void Actor::SetWidth( float width ) { if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout ) @@ -1387,9 +1331,21 @@ void Actor::SetDepth( float depth ) } } -const Vector3& Actor::GetTargetSize() const +Vector3 Actor::GetTargetSize() const { - return mTargetSize; + Vector3 size = mTargetSize; + + // 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; + } + + return size; } const Vector3& Actor::GetCurrentSize() const @@ -1420,7 +1376,15 @@ void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimensio { if( dimension & ( 1 << i ) ) { - mRelayoutData->resizePolicies[ i ] = policy; + if ( policy == ResizePolicy::USE_ASSIGNED_SIZE ) + { + mRelayoutData->useAssignedSize[ i ] = true; + } + else + { + mRelayoutData->resizePolicies[ i ] = policy; + mRelayoutData->useAssignedSize[ i ] = false; + } } } @@ -1483,7 +1447,14 @@ ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const { if( ( dimension & ( 1 << i ) ) ) { - return mRelayoutData->resizePolicies[ i ]; + if( mRelayoutData->useAssignedSize[ i ] ) + { + return ResizePolicy::USE_ASSIGNED_SIZE; + } + else + { + return mRelayoutData->resizePolicies[ i ]; + } } } } @@ -2139,6 +2110,7 @@ Actor::Actor( DerivedType derivedType ) 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 ), @@ -2224,6 +2196,12 @@ void Actor::ConnectToStage( unsigned int parentDepth ) // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks. ActorContainer connectionList; + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + // This stage is atomic i.e. not interrupted by user callbacks. RecursiveConnectToStage( connectionList, parentDepth + 1 ); @@ -2243,7 +2221,6 @@ void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned in mIsOnStage = true; mDepth = depth; - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); ConnectToSceneGraph(); @@ -2316,6 +2293,12 @@ void Actor::DisconnectFromStage() // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks. ActorContainer disconnectionList; + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } + // This stage is atomic i.e. not interrupted by user callbacks RecursiveDisconnectFromStage( disconnectionList ); @@ -2401,6 +2384,205 @@ bool Actor::IsNodeConnected() const return connected; } +// This method generates the depth tree using the recursive function below, +// then walks the tree and sets a depth index based on traversal order. It +// sends a single message to update manager to update all the actor's nodes in this +// tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered +// by depth, and could be used to reduce sorting in the update thread. +void Actor::RebuildDepthTree() +{ + DALI_LOG_TIMER_START(depthTimer); + + DepthNodeMemoryPool nodeMemoryPool; + ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder ); + + int actorCount = BuildDepthTree( nodeMemoryPool, rootNode ); + + // Vector of scene-graph nodes and their depths to send to UpdateManager + // in a single message + SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount); + + // Traverse depth tree and set mSortedDepth on each actor and scenegraph node + uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative + ActorDepthTreeNode* currentNode = rootNode; + bool firstVisit = true; + while( currentNode != rootNode || firstVisit) + { + firstVisit = false; + + // Visit node, performing action + for( std::vector::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter ) + { + (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER; + sceneGraphNodeDepths->Add( const_cast((*iter)->mNode), (*iter)->mSortedDepth ); + } + ++sortOrder; + + // Descend tree + if( currentNode->mFirstChildNode ) + { + currentNode = currentNode->mFirstChildNode; + } + else // leaf node, goto next sibling, or return up tree. + { + bool breakout=false; + while( ! currentNode->mNextSiblingNode ) + { + if( currentNode == rootNode ) // If we get to root of tree, stop + { + breakout = true; + break; + } + currentNode = currentNode->mParentNode; + } + + if( breakout ) + { + break; + } + currentNode = currentNode->mNextSiblingNode; + } + } + + SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths ); + DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: "); +} + +/** + * Structure to store the actor's associated node in the depth tree for child + * traversal + */ +struct ActorNodePair +{ + Actor* actor; + ActorDepthTreeNode* node; + ActorNodePair( Actor* actor, ActorDepthTreeNode* node ) + : actor(actor), + node(node) + { + } +}; + +/* + * Descend actor tree, building a depth tree based on actor's sibling order. + * Actors with the same sibling order share the same depth tree. Siblings + * in the depth tree are ordered by actor's sibling order. + * + * An actor tree like this: + * + * Root (SO:0) + * _/ | \_ + * _/ | \_ + * _/ | \_ + * / | \ + * A(SO:1) B(SO:2) C(SO:1) + * _/\_ | _/ \_ + * / \ | / \ + * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0) + * + * will end up as a depth tree like this: + * + * RootNode [ Root ] -> NULL + * |(mFC) + * V (mNS) + * Node [ A, C ] ------------------------> Node [ B ] -> NULL + * | | + * V V + * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL + * | | | + * V V V + * NULL NULL NULL + * + * (All nodes also point to their parents to enable storage free traversal) + */ +int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node ) +{ + int treeCount=1; // Count self and children + + // Create/add to children of this node + if( mChildren ) + { + std::vector storedChildren; + storedChildren.reserve( mChildren->size() ); + + for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it ) + { + Actor* childActor = (*it).Get(); + if( childActor->IsLayer() ) + { + Layer* layer = static_cast(childActor); + if( layer->GetBehavior() == Dali::Layer::LAYER_3D ) + { + // Ignore this actor and children. + continue; + } + } + + // If no existing depth node children + if( node->mFirstChildNode == NULL ) + { + node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder ); + node->mFirstChildNode->mParentNode = node; + storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode )); + } + else // find child node with matching sibling order (insertion sort) + { + bool addedChildActor = false; + + // depth tree child nodes ordered by sibling order + ActorDepthTreeNode* lastNode = NULL; + for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode ) + { + uint16_t actorSiblingOrder = childActor->mSiblingOrder; + uint16_t currentSiblingOrder = childNode->GetSiblingOrder(); + + if( actorSiblingOrder == currentSiblingOrder ) + { + // Don't need a new depth node, add to existing node + childNode->AddActor( childActor ); + storedChildren.push_back(ActorNodePair( childActor, childNode )); + addedChildActor = true; + break; + } + else if( actorSiblingOrder < currentSiblingOrder ) + { + break; + } + lastNode = childNode; + } + + // No matching sibling order - create new node and insert into sibling list + if( !addedChildActor ) + { + ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder ); + + newNode->mParentNode = node; + storedChildren.push_back(ActorNodePair( childActor, newNode )); + + if( lastNode == NULL ) // Insert at start of siblings + { + ActorDepthTreeNode* nextNode = node->mFirstChildNode; + node->mFirstChildNode = newNode; + newNode->mNextSiblingNode = nextNode; + } + else // insert into siblings after last node + { + newNode->mNextSiblingNode = lastNode->mNextSiblingNode; + lastNode->mNextSiblingNode = newNode; + } + } + } + } + + // Order of descent doesn't matter; we're using insertion to sort. + for( std::vector::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter ) + { + treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node ); + } + } + return treeCount; +} + unsigned int Actor::GetDefaultPropertyCount() const { return DEFAULT_PROPERTY_COUNT; @@ -3060,6 +3242,149 @@ Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) c return value; } +void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value ) +{ + switch( index ) + { + case Dali::Actor::Property::SIZE: + { + if( value.Get( mTargetSize ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + if( value.Get( mTargetSize.width ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + if( value.Get( mTargetSize.height ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + if( value.Get( mTargetSize.depth ) ) + { + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); + } + break; + } + + case Dali::Actor::Property::POSITION: + { + value.Get( mTargetPosition ); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + value.Get( mTargetPosition.x ); + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + value.Get( mTargetPosition.y ); + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + value.Get( mTargetPosition.z ); + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + value.Get( mTargetOrientation ); + break; + } + + case Dali::Actor::Property::SCALE: + { + value.Get( mTargetScale ); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + value.Get( mTargetScale.x ); + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + value.Get( mTargetScale.y ); + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + value.Get( mTargetScale.z ); + break; + } + + case Dali::Actor::Property::VISIBLE: + { + SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE ); + break; + } + + case Dali::Actor::Property::COLOR: + { + value.Get( mTargetColor ); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + value.Get( mTargetColor.r ); + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + value.Get( mTargetColor.g ); + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + value.Get( mTargetColor.b ); + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + case Dali::DevelActor::Property::OPACITY: + { + value.Get( mTargetColor.a ); + break; + } + + default: + { + // Not an animatable property. Do nothing. + break; + } + } +} + const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const { return mNode; @@ -3561,48 +3886,19 @@ bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& valu case Dali::Actor::Property::SIZE: { - Vector3 size = GetTargetSize(); - - // Should return preferred size if size is fixed as set by SetSize - if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED ) - { - size.width = GetPreferredSize().width; - } - if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) - { - size.height = GetPreferredSize().height; - } - - value = size; - + value = GetTargetSize(); 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; - } + value = GetTargetSize().width; break; } case Dali::Actor::Property::SIZE_HEIGHT: { - if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED ) - { - // Should return preferred size if size is fixed as set by SetSize - value = GetPreferredSize().height; - } - else - { - value = GetTargetSize().height; - } + value = GetTargetSize().height; break; } @@ -4011,6 +4307,12 @@ bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& val break; } + case Dali::Actor::Property::VISIBLE: + { + value = IsVisible(); + break; + } + default: { // Must be an event-side only property @@ -4305,7 +4607,7 @@ float Actor::NegotiateFromChildren( Dimension::Type dimension ) float Actor::GetSize( Dimension::Type dimension ) const { - return GetDimensionValue( GetTargetSize(), dimension ); + return GetDimensionValue( mTargetSize, dimension ); } float Actor::GetNaturalSize( Dimension::Type dimension ) const @@ -4575,13 +4877,15 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont // relayout container afterwards, the dirty flags would still be clear... // causing a relayout to be skipped. Here we force any actors added to the // container to be relayed out. - if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE) + DALI_LOG_TIMER_START( NegSizeTimer1 ); + + if( GetUseAssignedSize(Dimension::WIDTH ) ) { - SetLayoutNegotiated(false, Dimension::WIDTH); + SetLayoutNegotiated( false, Dimension::WIDTH ); } - if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE) + if( GetUseAssignedSize( Dimension::HEIGHT ) ) { - SetLayoutNegotiated(false, Dimension::HEIGHT); + SetLayoutNegotiated( false, Dimension::HEIGHT ); } // Do the negotiation @@ -4591,7 +4895,7 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont SetNegotiatedSize( container ); // Negotiate down to children - const Vector2 newBounds = GetTargetSize().GetVectorXY(); + const Vector2 newBounds = mTargetSize.GetVectorXY(); for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) { @@ -4599,12 +4903,13 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont // Forces children that have already been laid out to be relayed out // if they have assigned size during relayout. - if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE) + if( child->GetUseAssignedSize(Dimension::WIDTH) ) { child->SetLayoutNegotiated(false, Dimension::WIDTH); child->SetLayoutDirty(true, Dimension::WIDTH); } - if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE) + + if( child->GetUseAssignedSize(Dimension::HEIGHT) ) { child->SetLayoutNegotiated(false, Dimension::HEIGHT); child->SetLayoutDirty(true, Dimension::HEIGHT); @@ -4616,6 +4921,38 @@ void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& cont container.Add( Dali::Actor( child.Get() ), newBounds ); } } + DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: "); +} + +void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension ) +{ + if( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->useAssignedSize[ i ] = use; + } + } + } +} + +bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->useAssignedSize[ i ]; + } + } + } + + return false; } void Actor::RelayoutRequest( Dimension::Type dimension ) @@ -4732,12 +5069,34 @@ Object* Actor::GetParentObject() const return mParent; } +void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) +{ + if( mVisible != visible ) + { + if( sendMessage == SendMessage::TRUE && NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty::Bake, visible ); + } + + mVisible = visible; + + // Emit the signal on this actor and all its children + EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF ); + } +} + void Actor::SetSiblingOrder( unsigned int order ) { mSiblingOrder = std::min( order, static_cast( DevelLayer::SIBLING_ORDER_MULTIPLIER ) ); + if( mIsOnStage ) { - SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) ); + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + stage->RequestRebuildDepthTree(); + } } }