From: Tom Robinson Date: Mon, 9 Feb 2015 16:14:41 +0000 (+0000) Subject: Size Relative feature: Implementation in dali-core plus UTC tests X-Git-Tag: submit/tizen/20150217.020310~4^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=06ac0acbede103071356255a5ab1f76e97b04b42;p=platform%2Fcore%2Fuifw%2Fdali-core.git Size Relative feature: Implementation in dali-core plus UTC tests Change-Id: I851ca67c4a224f426ffd64713e8fe9c3041941ab --- diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index 758765f..12d5c7a 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -40,6 +40,15 @@ void utc_dali_actor_cleanup(void) namespace { +// Enumeration properties to test: +const Scripting::StringEnum< int > SIZE_MODE_VALUES[] = +{ + { "USE_OWN_SIZE", USE_OWN_SIZE }, + { "SIZE_EQUAL_TO_PARENT", SIZE_EQUAL_TO_PARENT }, + { "SIZE_RELATIVE_TO_PARENT", SIZE_RELATIVE_TO_PARENT }, + { "SIZE_FIXED_OFFSET_FROM_PARENT", SIZE_FIXED_OFFSET_FROM_PARENT }, +}; +const unsigned int SIZE_MODE_VALUES_COUNT = sizeof( SIZE_MODE_VALUES ) / sizeof( SIZE_MODE_VALUES[0] ); bool gTouchCallBackCalled=false; bool gTouchCallBack2Called=false; @@ -1165,6 +1174,213 @@ int UtcDaliActorInheritPosition(void) END_TEST; } +int UtcDaliActorSizeMode(void) +{ + tet_infoline("Testing Actor::SetSizeMode"); + TestApplication application; + + // Create a parent and a child. + Actor parent = Actor::New(); + parent.SetParentOrigin( ParentOrigin::CENTER ); + parent.SetAnchorPoint( AnchorPoint::CENTER ); + Vector3 parentPosition( 0.0f, 0.0f, 0.0f ); + parent.SetPosition( parentPosition ); + parent.SetSize( 10.0f, 20.0f, 40.0f ); + parent.SetSizeMode( USE_OWN_SIZE ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetParentOrigin( ParentOrigin::CENTER ); + child.SetAnchorPoint( AnchorPoint::CENTER ); + Vector3 childPosition( 0.0f, 0.0f, 0.0f ); + child.SetPosition( childPosition ); + child.SetSize( 1.0f, 2.0f, 4.0f ); + child.SetSizeMode( USE_OWN_SIZE ); + parent.Add( child ); + + // Flush the queue and render once. + application.SendNotification(); + application.Render(); + + // Test USE_OWN_SIZE uses the user-set size value. + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 1.0f, 2.0f, 4.0f ), TEST_LOCATION ); + // Render and check again to ensure double-buffering does not cause old value to reappear. + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 1.0f, 2.0f, 4.0f ), TEST_LOCATION ); + + // Test SIZE_EQUAL_TO_PARENT overrides size with the parents size. + child.SetSizeMode( SIZE_EQUAL_TO_PARENT ); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 10.0f, 20.0f, 40.0f ), TEST_LOCATION ); + // Render and check again to ensure double-buffering does not cause old value to reappear. + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 10.0f, 20.0f, 40.0f ), TEST_LOCATION ); + + // Test SIZE_RELATIVE_TO_PARENT overrides size with parents size * SizeModeFactor. + child.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + + application.SendNotification(); + application.Render(); + // First check without setting a relative factor, to confirm that the default factor (of 1.0f) is used. + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 10.0f, 20.0f, 40.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + // Render and check again to ensure double-buffering does not cause old value to reappear. + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 10.0f, 20.0f, 40.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Set an arbitary relative factor to check against. + child.SetSizeModeFactor( Vector3( 2.0f, 3.0f, 4.0f ) ); + + application.SendNotification(); + application.Render(); + // Check with a valid relative factor. + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 20.0f, 60.0f, 160.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + // Render and check again to ensure double-buffering does not cause old value to reappear. + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 20.0f, 60.0f, 160.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Test SIZE_FIXED_OFFSET_FROM_PARENT overrides size with parents size + SizeModeFactor. + child.SetSizeMode( SIZE_FIXED_OFFSET_FROM_PARENT ); + + application.SendNotification(); + application.Render(); + // Check with a valid relative factor. + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 12.0f, 23.0f, 44.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + // Render and check again to ensure double-buffering does not cause old value to reappear. + application.Render(); + DALI_TEST_EQUALS( child.GetCurrentSize(), Vector3( 12.0f, 23.0f, 44.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + application.SendNotification(); + + // Test the calculation order in update by having a parent with a size-relative + // factor and a rotation rotate a child anchored to one of the parents corners. + // .---. c + // .-----. | .-----. The new child is parented from the top-left of its parent. + // | '-|-' -----> | | We rotate the parent to confirm that the relative size calculation is + // | p | Rotate | .-|-. done before rotation. If it wasn't, the childs resultant + // '-----' parent '-----' | world-position would be incorrect. + // 90° '---' + // + // Create a new parent and child, and a root parent which the parent can grab relative size from. + Actor rootParent = Actor::New(); + rootParent.SetParentOrigin( ParentOrigin::CENTER ); + rootParent.SetAnchorPoint( AnchorPoint::CENTER ); + rootParent.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + rootParent.SetSize( 10.0f, 10.0f, 10.0f ); + rootParent.SetSizeMode( USE_OWN_SIZE ); + Stage::GetCurrent().Add( rootParent ); + + Actor newParent = Actor::New(); + newParent.SetParentOrigin( ParentOrigin::CENTER ); + newParent.SetAnchorPoint( AnchorPoint::CENTER ); + newParent.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + newParent.SetSize( 10.0f, 10.0f, 10.0f ); + newParent.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + newParent.SetSizeModeFactor( Vector3( 0.5f, 0.5f, 0.5f ) ); + rootParent.Add( newParent ); + + Actor newChild = Actor::New(); + newChild.SetParentOrigin( ParentOrigin::TOP_RIGHT ); + newChild.SetAnchorPoint( AnchorPoint::CENTER ); + newChild.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + newChild.SetSize( 1.0f, 1.0f, 1.0f ); + newChild.SetSizeMode( USE_OWN_SIZE ); + newParent.Add( newChild ); + + // Set up the rotation by 90 degrees on Z. + newParent.RotateBy( Radian( M_PI * 0.5f ), Vector3::ZAXIS ); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( newParent.GetCurrentSize(), Vector3( 5.0f, 5.0f, 5.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( newParent.GetCurrentWorldPosition(), Vector3( 0.0f, 0.0f, 0.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( newChild.GetCurrentWorldPosition(), Vector3( 2.5f, 2.5f, 0.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Test changing the parents size to check the child's size is updated. + Actor newParent2 = Actor::New(); + newParent2.SetParentOrigin( ParentOrigin::CENTER ); + newParent2.SetAnchorPoint( AnchorPoint::CENTER ); + newParent2.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + newParent2.SetSize( 10.0f, 10.0f, 10.0f ); + newParent2.SetSizeMode( USE_OWN_SIZE ); + rootParent.Add( newParent2 ); + + Actor newChild2 = Actor::New(); + newChild2.SetParentOrigin( ParentOrigin::TOP_RIGHT ); + newChild2.SetAnchorPoint( AnchorPoint::CENTER ); + newChild2.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + newChild2.SetSize( Vector3::ONE ); + newChild2.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + newChild2.SetSizeModeFactor( Vector3( 0.5f, 0.5f, 0.5f ) ); + newParent2.Add( newChild2 ); + + // Check the child has no size yet. + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Check the child now has a relative size to the parent. + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 5.0f, 5.0f, 5.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Change the parent's size and check the child's size changes also. + newParent2.SetSize( 100.0f, 100.0f, 100.0f ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 50.0f, 50.0f, 50.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + // Confirm the child's size is still correct on the next frame. + application.Render(); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 50.0f, 50.0f, 50.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Text that reparenting a child causes its size to update relative to its new parent. + Actor newParent3 = Actor::New(); + newParent3.SetParentOrigin( ParentOrigin::CENTER ); + newParent3.SetAnchorPoint( AnchorPoint::CENTER ); + newParent3.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); + newParent3.SetSize( 400.0f, 400.0f, 400.0f ); + newParent3.SetSizeMode( USE_OWN_SIZE ); + rootParent.Add( newParent3 ); + + // Reparent the child but don't update yet. Check it still has its old size. + newParent3.Add( newChild2 ); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 50.0f, 50.0f, 50.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Check the child's size has updated based on the new parent. + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + // Confirm the child's size is still correct on the next frame. + application.Render(); + DALI_TEST_EQUALS( newChild2.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Properties: + // Test setting and getting the SizeMode property (by string). + Actor propertyActor = Actor::New(); + propertyActor.SetParentOrigin( ParentOrigin::CENTER ); + propertyActor.SetAnchorPoint( AnchorPoint::CENTER ); + propertyActor.SetPosition( Vector3::ZERO ); + propertyActor.SetSize( Vector3::ONE ); + propertyActor.SetSizeMode( USE_OWN_SIZE ); + + // Loop through each SizeMode enumeration. + for( unsigned int propertyIndex = 0; propertyIndex < SIZE_MODE_VALUES_COUNT; ++propertyIndex ) + { + Property::Value inValue = SIZE_MODE_VALUES[ propertyIndex ].string; + propertyActor.SetProperty( Actor::SIZE_MODE, inValue ); + std::string outString = propertyActor.GetProperty( Actor::SIZE_MODE ).Get< std::string >(); + DALI_TEST_EQUALS( inValue.Get< std::string >(), outString, TEST_LOCATION ); + } + + // Test setting and getting the SizeModeFactor property. + Vector3 testPropertySizeModeFactor( 1.0f, 2.0f, 3.0f ); + Property::Value inValueFactor = testPropertySizeModeFactor; + propertyActor.SetProperty( Actor::SIZE_MODE_FACTOR, inValueFactor ); + Vector3 outValueFactor = propertyActor.GetProperty( Actor::SIZE_MODE_FACTOR ).Get< Vector3 >(); + DALI_TEST_EQUALS( testPropertySizeModeFactor, outValueFactor, TEST_LOCATION ); + + END_TEST; +} + // SetRotation(float angleRadians, Vector3 axis) int UtcDaliActorSetRotation01(void) { @@ -3010,6 +3226,8 @@ const PropertyStringIndex PROPERTY_TABLE[] = { "color-mode", Actor::COLOR_MODE, Property::STRING }, { "position-inheritance", Actor::POSITION_INHERITANCE, Property::STRING }, { "draw-mode", Actor::DRAW_MODE, Property::STRING }, + { "size-mode", Actor::SIZE_MODE, Property::STRING }, + { "size-mode-factor", Actor::SIZE_MODE_FACTOR, Property::VECTOR3 }, }; const unsigned int PROPERTY_TABLE_COUNT = sizeof( PROPERTY_TABLE ) / sizeof( PROPERTY_TABLE[0] ); } // unnamed namespace diff --git a/automated-tests/src/dali/utc-Dali-Handle.cpp b/automated-tests/src/dali/utc-Dali-Handle.cpp index fdfb01f..0d7c5e3 100644 --- a/automated-tests/src/dali/utc-Dali-Handle.cpp +++ b/automated-tests/src/dali/utc-Dali-Handle.cpp @@ -410,6 +410,8 @@ int UtcDaliHandleIsPropertyAConstraintInput(void) DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::COLOR_MODE ) ); DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::POSITION_INHERITANCE ) ); DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::DRAW_MODE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::SIZE_MODE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::SIZE_MODE_FACTOR ) ); END_TEST; } @@ -621,7 +623,7 @@ int UtcDaliHandleNonAnimtableCompositeProperties(void) valueMap.SetValue("key", 5.f); valueMap.SetValue("2key", "a string"); - DALI_TEST_EQUALS( true, valueMap.HasKey("key"), TEST_LOCATION); + DALI_TEST_EQUALS( true, valueMap.HasKey("key"), TEST_LOCATION); DALI_TEST_EQUALS( "key", valueMap.GetKey(0), TEST_LOCATION); DALI_TEST_EQUALS( true, valueMap.HasKey("2key"), TEST_LOCATION); @@ -633,8 +635,8 @@ int UtcDaliHandleNonAnimtableCompositeProperties(void) valueMap.SetItem(0, Property::Value("a string")); valueMap.SetItem(1, Property::Value(5.f)); - DALI_TEST_EQUALS( 5.f, valueMap.GetValue("2key").Get(), TEST_LOCATION); - DALI_TEST_EQUALS( "a string", valueMap.GetValue("key").Get(), TEST_LOCATION); + DALI_TEST_EQUALS( 5.f, valueMap.GetValue("2key").Get(), TEST_LOCATION); + DALI_TEST_EQUALS( "a string", valueMap.GetValue("key").Get(), TEST_LOCATION); // ordered map valueMap = Property::Value(Property::MAP); diff --git a/automated-tests/src/dali/utc-Dali-Scripting.cpp b/automated-tests/src/dali/utc-Dali-Scripting.cpp index 1d3aa68..5927568 100644 --- a/automated-tests/src/dali/utc-Dali-Scripting.cpp +++ b/automated-tests/src/dali/utc-Dali-Scripting.cpp @@ -54,7 +54,6 @@ const StringEnum< int > DRAW_MODE_VALUES[] = const unsigned int DRAW_MODE_VALUES_COUNT = sizeof( DRAW_MODE_VALUES ) / sizeof( DRAW_MODE_VALUES[0] ); - ////////////////////////////////////////////////////////////////////////////// // Helpers for string to enum comparisons for Image and ImageAttributes ////////////////////////////////////////////////////////////////////////////// @@ -809,6 +808,8 @@ int UtcDaliScriptingCreatePropertyMapActor(void) actor.SetLeaveRequired( true ); actor.SetInheritRotation( false ); actor.SetInheritScale( false ); + actor.SetSizeMode( USE_OWN_SIZE ); + actor.SetSizeModeFactor( Vector3::ONE ); Stage::GetCurrent().Add( actor ); application.SendNotification(); @@ -843,6 +844,8 @@ int UtcDaliScriptingCreatePropertyMapActor(void) DALI_TEST_EQUALS( value.GetValue( "inherit-rotation" ).Get< bool >(), false, TEST_LOCATION ); DALI_TEST_CHECK( value.HasKey( "inherit-scale" ) ); DALI_TEST_EQUALS( value.GetValue( "inherit-scale" ).Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_CHECK( value.HasKey( "size-mode-factor" ) ); + DALI_TEST_EQUALS( value.GetValue( "size-mode-factor" ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION ); Stage::GetCurrent().Remove( actor ); } diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index a06b19e..846a32c 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -106,6 +106,8 @@ const Property::Index Actor::INHERIT_SCALE = 39; const Property::Index Actor::COLOR_MODE = 40; const Property::Index Actor::POSITION_INHERITANCE = 41; const Property::Index Actor::DRAW_MODE = 42; +const Property::Index Actor::SIZE_MODE = 43; +const Property::Index Actor::SIZE_MODE_FACTOR = 44; namespace // unnamed namespace { @@ -160,9 +162,21 @@ const Internal::PropertyDetails DEFAULT_PROPERTY_DETAILS[] = { "color-mode", Property::STRING, true, false, false }, // COLOR_MODE { "position-inheritance", Property::STRING, true, false, false }, // POSITION_INHERITANCE { "draw-mode", Property::STRING, true, false, false }, // DRAW_MODE + { "size-mode", Property::STRING, true, false, false }, // SIZE_MODE + { "size-mode-factor", Property::VECTOR3, true, false, false }, // SIZE_MODE_FACTOR }; const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails ); +// Enumeration to/from text conversion tables: +const Scripting::StringEnum< SizeMode > SIZE_MODE_TABLE[] = +{ + { "USE_OWN_SIZE", USE_OWN_SIZE }, + { "SIZE_EQUAL_TO_PARENT", SIZE_EQUAL_TO_PARENT }, + { "SIZE_RELATIVE_TO_PARENT", SIZE_RELATIVE_TO_PARENT }, + { "SIZE_FIXED_OFFSET_FROM_PARENT", SIZE_FIXED_OFFSET_FROM_PARENT }, +}; +const unsigned int SIZE_MODE_TABLE_COUNT = sizeof( SIZE_MODE_TABLE ) / sizeof( SIZE_MODE_TABLE[0] ); + } // unnamed namespace namespace Internal @@ -1058,6 +1072,38 @@ bool Actor::IsRotationInherited() const return mInheritRotation; } +void Actor::SetSizeMode(SizeMode mode) +{ + // non animateable so keep local copy + mSizeMode = mode; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetSizeModeMessage( mStage->GetUpdateInterface(), *mNode, mode ); + } +} + +void Actor::SetSizeModeFactor(const Vector3& factor) +{ + // non animateable so keep local copy + mSizeModeFactor = factor; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetSizeModeFactorMessage( mStage->GetUpdateInterface(), *mNode, factor ); + } +} + +SizeMode Actor::GetSizeMode() const +{ + return mSizeMode; +} + +const Vector3& Actor::GetSizeModeFactor() const +{ + return mSizeModeFactor; +} + void Actor::SetColorMode(ColorMode colorMode) { // non animateable so keep local copy @@ -2031,6 +2077,7 @@ Actor::Actor( DerivedType derivedType ) mGestureData( NULL ), mAttachment(), mSize( 0.0f, 0.0f, 0.0f ), + mSizeModeFactor( Vector3::ONE ), mName(), mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved mIsRoot( ROOT_LAYER == derivedType ), @@ -2049,7 +2096,8 @@ Actor::Actor( DerivedType derivedType ) mInheritScale( true ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), - mColorMode( Node::DEFAULT_COLOR_MODE ) + mColorMode( Node::DEFAULT_COLOR_MODE ), + mSizeMode( Node::DEFAULT_SIZE_MODE ) { } @@ -2603,6 +2651,18 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr break; } + case Dali::Actor::SIZE_MODE: + { + SetSizeMode( Scripting::GetEnumeration< SizeMode >( property.Get(), SIZE_MODE_TABLE, SIZE_MODE_TABLE_COUNT ) ); + break; + } + + case Dali::Actor::SIZE_MODE_FACTOR: + { + SetSizeModeFactor( property.Get() ); + break; + } + case Dali::Actor::INHERIT_SCALE: { SetInheritScale( property.Get() ); @@ -2989,6 +3049,18 @@ Property::Value Actor::GetDefaultProperty(Property::Index index) const break; } + case Dali::Actor::SIZE_MODE: + { + value = Scripting::GetEnumerationName< SizeMode >( GetSizeMode(), SIZE_MODE_TABLE, SIZE_MODE_TABLE_COUNT ); + break; + } + + case Dali::Actor::SIZE_MODE_FACTOR: + { + value = GetSizeModeFactor(); + break; + } + case Dali::Actor::INHERIT_SCALE: { value = IsScaleInherited(); diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index df1bff7..5b6fe64 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -501,6 +501,32 @@ public: bool IsRotationInherited() const; /** + * @brief Defines how a child actors size is affected by its parents size. + * @param[in] mode The size relative to parent mode to use. + */ + void SetSizeMode(SizeMode mode); + + /** + * Query how the child actors size is affected by its parents size. + * @return The size relative to parent mode in use. + */ + SizeMode GetSizeMode() const; + + /** + * Sets the factor of the parents size used for the child actor. + * Note: Only used if SizeMode is SIZE_RELATIVE_TO_PARENT or SIZE_FIXED_OFFSET_FROM_PARENT. + * @param[in] factor The vector to multiply the parents size by to get the childs size. + */ + void SetSizeModeFactor(const Vector3& factor); + + /** + * Gets the factor of the parents size used for the child actor. + * Note: Only used if SizeMode is SIZE_RELATIVE_TO_PARENT or SIZE_FIXED_OFFSET_FROM_PARENT. + * @return The vector being used to multiply the parents size by to get the childs size. + */ + const Vector3& GetSizeModeFactor() const; + + /** * @copydoc Dali::Actor::GetCurrentWorldRotation() */ const Quaternion& GetCurrentWorldRotation() const; @@ -1344,14 +1370,14 @@ protected: Actor* mParent; ///< Each actor (except the root) can have one parent ActorContainer* mChildren; ///< Container of referenced actors const SceneGraph::Node* mNode; ///< Not owned - Vector3* mParentOrigin; // NULL means ParentOrigin::DEFAULT. ParentOrigin is non-animatable - Vector3* mAnchorPoint; // NULL means AnchorPoint::DEFAULT. AnchorPoint is non-animatable + Vector3* mParentOrigin; ///< NULL means ParentOrigin::DEFAULT. ParentOrigin is non-animatable + Vector3* mAnchorPoint; ///< NULL means AnchorPoint::DEFAULT. AnchorPoint is non-animatable #ifdef DYNAMICS_SUPPORT DynamicsData* mDynamicsData; ///< optional physics data #endif - ActorGestureData* mGestureData; /// Optional Gesture data. Only created when actor requires gestures + ActorGestureData* mGestureData; ///< Optional Gesture data. Only created when actor requires gestures ActorAttachmentPtr mAttachment; ///< Optional referenced attachment @@ -1364,6 +1390,7 @@ protected: Dali::Actor::OffStageSignalType mOffStageSignal; Vector3 mSize; ///< Event-side storage for size (not a pointer as most actors will have a size) + Vector3 mSizeModeFactor; ///< Factor of parent size used for certain SizeModes. std::string mName; ///< Name of the actor unsigned int mId; ///< A unique ID to identify the actor starting from 1, and 0 is reserved @@ -1385,6 +1412,7 @@ protected: DrawMode::Type mDrawMode : 2; ///< Cached: How the actor and its children should be drawn PositionInheritanceMode mPositionInheritanceMode : 2; ///< Cached: Determines how position is inherited ColorMode mColorMode : 2; ///< Cached: Determines whether mWorldColor is inherited + SizeMode mSizeMode : 2; ///< Cached: Determines how the actors parent affects the actors size. private: diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp index 0c9e900..a4e0c4b 100644 --- a/dali/internal/update/manager/update-algorithms.cpp +++ b/dali/internal/update/manager/update-algorithms.cpp @@ -176,11 +176,44 @@ inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, inline void UpdateNodeTransformValues( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex ) { // If the transform values need to be reinherited - if ( nodeDirtyFlags & TransformFlag ) + if( nodeDirtyFlags & TransformFlag ) { + // Handle size relative to parent modes. + // This must be delt with before rotation/translation as otherwise anything + // anchored to a corner of this child would appear at the wrong position. + // Note: Switch is in order of use-case commonality. + switch( node.GetSizeMode() ) + { + case USE_OWN_SIZE: + { + // Completely ignore the parents size. + break; + } + + case SIZE_EQUAL_TO_PARENT: + { + // Set the nodes size to that of the parent. + node.SetSize( updateBufferIndex, node.GetParent()->GetSize( updateBufferIndex ) ); + break; + } + + case SIZE_RELATIVE_TO_PARENT: + { + // Set the nodes size to the parents multiplied by a user defined value. + node.SetSize( updateBufferIndex, node.GetSizeModeFactor() * node.GetParent()->GetSize( updateBufferIndex ) ); + break; + } + + case SIZE_FIXED_OFFSET_FROM_PARENT: + { + // Set the nodes size to the parents plus a user defined value. + node.SetSize( updateBufferIndex, node.GetSizeModeFactor() + node.GetParent()->GetSize( updateBufferIndex ) ); + break; + } + } + // With a non-central anchor-point, the world rotation and scale affects the world position. // Therefore the world rotation & scale must be updated before the world position. - if( node.IsRotationInherited() ) { node.InheritWorldRotation( updateBufferIndex ); @@ -207,6 +240,7 @@ inline void UpdateNodeTransformValues( Node& node, int nodeDirtyFlags, BufferInd node.CopyPreviousWorldRotation( updateBufferIndex ); node.CopyPreviousWorldScale( updateBufferIndex ); node.CopyPreviousWorldPosition( updateBufferIndex ); + node.CopyPreviousSize( updateBufferIndex ); } } diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp index 7b39c79..91636c8 100644 --- a/dali/internal/update/nodes/node.cpp +++ b/dali/internal/update/nodes/node.cpp @@ -35,6 +35,7 @@ namespace SceneGraph const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION ); const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA ); +const SizeMode Node::DEFAULT_SIZE_MODE( USE_OWN_SIZE ); Node* Node::New() { @@ -61,6 +62,7 @@ Node::Node() mChildren(), mGeometryScale( Vector3::ONE ), mInitialVolume( Vector3::ONE ), + mSizeModeFactor( Vector3::ONE ), mDirtyFlags(AllFlags), mIsRoot( false ), mInheritRotation( true ), @@ -70,7 +72,8 @@ Node::Node() mIsActive( true ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ), - mColorMode( DEFAULT_COLOR_MODE ) + mColorMode( DEFAULT_COLOR_MODE ), + mSizeMode( DEFAULT_SIZE_MODE ) { } diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h index bc9aa1f..637e05d 100644 --- a/dali/internal/update/nodes/node.h +++ b/dali/internal/update/nodes/node.h @@ -46,6 +46,7 @@ namespace Internal // value types used by messages template <> struct ParameterType< ColorMode > : public BasicType< ColorMode > {}; template <> struct ParameterType< PositionInheritanceMode > : public BasicType< PositionInheritanceMode > {}; +template <> struct ParameterType< SizeMode > : public BasicType< SizeMode > {}; namespace SceneGraph { @@ -95,6 +96,7 @@ public: // Defaults static const PositionInheritanceMode DEFAULT_POSITION_INHERITANCE_MODE; static const ColorMode DEFAULT_COLOR_MODE; + static const SizeMode DEFAULT_SIZE_MODE; // Creation methods @@ -592,6 +594,51 @@ public: } /** + * @brief Defines how a child actor's size is affected by its parent's size. + * @param[in] mode The size relative to parent mode to use. + */ + void SetSizeMode( SizeMode mode ) + { + if ( mode != mSizeMode ) + { + mSizeMode = mode; + + SetDirtyFlag( TransformFlag ); + } + } + + /** + * Query how the child actor's size is affected by its parent's size. + * @return The size relative to parent mode in use. + */ + SizeMode GetSizeMode() const + { + return mSizeMode; + } + + /** + * Sets the factor of the parents size used for the child actor. + * Note: Only used for certain SizeModes. + * @param[in] factor The vector to multiply the parents size by to get the childs size. + */ + void SetSizeModeFactor( const Vector3& factor ) + { + mSizeModeFactor = factor; + + SetDirtyFlag( TransformFlag ); + } + + /** + * Gets the factor of the parents size used for the child actor. + * Note: Only used for certain SizeModes. + * @return The vector being used to multiply the parents size by to get the childs size. + */ + const Vector3& GetSizeModeFactor() const + { + return mSizeModeFactor; + } + + /** * Set the initial volume of the node. Used for calculating geometry scaling * as the node size is changed when transmitGeometryScaling is set to true. * @@ -599,7 +646,7 @@ public: * * @param[in] volume The initial volume of this nodes meshes & children */ - void SetInitialVolume( const Vector3& volume) + void SetInitialVolume( const Vector3& volume ) { mInitialVolume = volume; SetDirtyFlag(SizeFlag); @@ -741,6 +788,15 @@ public: } /** + * Copies the previously used size, if this changed in the previous frame. + * @param[in] updateBufferIndex The current update buffer index. + */ + void CopyPreviousSize( BufferIndex updateBufferIndex ) + { + SetSize( updateBufferIndex, GetSize( 1u - updateBufferIndex ) ); + } + + /** * Retrieve the visibility of the node. * @param[in] bufferIndex The buffer to read from. * @return True if the node is visible. @@ -862,6 +918,16 @@ public: } /** + * Sets the size of the node. + * @param[in] bufferIndex The buffer to write to. + * @param[in] size The size to write. + */ + void SetSize( BufferIndex bufferIndex, const Vector3& size ) + { + mSize[bufferIndex] = size; + } + + /** * Retrieve the size of the node. * @param[in] bufferIndex The buffer to read from. * @return The size. @@ -1058,7 +1124,8 @@ protected: NodeContainer mChildren; ///< Container of children; not owned Vector3 mGeometryScale; ///< Applied before calculating world transform. - Vector3 mInitialVolume; ///< Initial volume... TODO - need a better name + Vector3 mInitialVolume; ///< Initial volume... TODO - need a better name. + Vector3 mSizeModeFactor; ///< Factor of parent size. Used for certain SizeModes. // flags, compressed to bitfield int mDirtyFlags:10; ///< A composite set of flags for each of the Node properties @@ -1073,6 +1140,7 @@ protected: DrawMode::Type mDrawMode:2; ///< How the Node and its children should be drawn PositionInheritanceMode mPositionInheritanceMode:2;///< Determines how position is inherited, 2 bits is enough ColorMode mColorMode:2; ///< Determines whether mWorldColor is inherited, 2 bits is enough + SizeMode mSizeMode:2; ///< Determines how the actors parent affects the actors size. // Changes scope, should be at end of class DALI_LOG_OBJECT_STRING_DECLARATION; @@ -1091,6 +1159,28 @@ inline void SetInheritRotationMessage( EventToUpdate& eventToUpdate, const Node& new (slot) LocalType( &node, &Node::SetInheritRotation, inherit ); } +inline void SetSizeModeMessage( EventToUpdate& eventToUpdate, const Node& node, SizeMode mode ) +{ + typedef MessageValue1< Node, SizeMode > LocalType; + + // Reserve some memory inside the message queue + unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &node, &Node::SetSizeMode, mode ); +} + +inline void SetSizeModeFactorMessage( EventToUpdate& eventToUpdate, const Node& node, const Vector3& factor ) +{ + typedef MessageValue1< Node, Vector3 > LocalType; + + // Reserve some memory inside the message queue + unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &node, &Node::SetSizeModeFactor, factor ); +} + inline void SetInitialVolumeMessage( EventToUpdate& eventToUpdate, const Node& node, const Vector3& initialVolume ) { typedef MessageValue1< Node, Vector3 > LocalType; diff --git a/dali/public-api/actors/actor-enumerations.h b/dali/public-api/actors/actor-enumerations.h index ad8560d..9cf5de1 100644 --- a/dali/public-api/actors/actor-enumerations.h +++ b/dali/public-api/actors/actor-enumerations.h @@ -46,6 +46,16 @@ enum PositionInheritanceMode DONT_INHERIT_POSITION ///< Actor will not inherit position. Local position is treated as world position. This is useful if a constraint is used to override local position or if an actor is positioned globally. This option ignores parent origin, anchor point and local position. }; +/** + * @brief Actor size relative to parent mode. + */ +enum SizeMode +{ + USE_OWN_SIZE, ///< The mode is bypassed. The size Vector3 will be used as normal. + SIZE_EQUAL_TO_PARENT, ///< The actor will have the exact same size as the parent. + SIZE_RELATIVE_TO_PARENT, ///< The actors size will be ( ParentSize * SizeRelativeToParentFactor ). + SIZE_FIXED_OFFSET_FROM_PARENT ///< The actors size will be ( ParentSize + SizeRelativeToParentFactor ). +}; } // namespace Dali diff --git a/dali/public-api/actors/actor.cpp b/dali/public-api/actors/actor.cpp index b76f941..f720c2f 100644 --- a/dali/public-api/actors/actor.cpp +++ b/dali/public-api/actors/actor.cpp @@ -377,6 +377,26 @@ bool Actor::IsScaleInherited() const return GetImplementation(*this).IsScaleInherited(); } +void Actor::SetSizeMode(SizeMode mode) +{ + GetImplementation(*this).SetSizeMode(mode); +} + +SizeMode Actor::GetSizeMode() const +{ + return GetImplementation(*this).GetSizeMode(); +} + +void Actor::SetSizeModeFactor(const Vector3& factor) +{ + GetImplementation(*this).SetSizeModeFactor(factor); +} + +Vector3 Actor::GetSizeModeFactor() const +{ + return GetImplementation(*this).GetSizeModeFactor(); +} + Matrix Actor::GetCurrentWorldMatrix() const { return GetImplementation(*this).GetCurrentWorldMatrix(); diff --git a/dali/public-api/actors/actor.h b/dali/public-api/actors/actor.h index d159f15..21d91af 100644 --- a/dali/public-api/actors/actor.h +++ b/dali/public-api/actors/actor.h @@ -286,6 +286,8 @@ public: static const Property::Index COLOR_MODE; ///< name "color-mode", type STRING static const Property::Index POSITION_INHERITANCE; ///< name "position-inheritance", type STRING static const Property::Index DRAW_MODE; ///< name "draw-mode", type STRING + static const Property::Index SIZE_MODE; ///< name "size-mode", type STRING + static const Property::Index SIZE_MODE_FACTOR; ///< name "size-mode-factor", type VECTOR3 /** @} */ /// @name Signals @@ -921,6 +923,58 @@ public: bool IsScaleInherited() const; /** + * @brief Defines how a child actor's size is affected by its parent's size. + * + * The default is to ignore the parent's size and use the size property of this actor. + * + * If USE_OWN_SIZE is used, this option is bypassed and the actor's size + * property is used. + * + * If SIZE_EQUAL_TO_PARENT is used, this actor's size will be equal to that + * of its parent. The actor's size property is ignored. + * + * If SIZE_RELATIVE_TO_PARENT is used, this actor's size will be based on + * its parent's size by multiplying the parent size by + * SizeModeFactor. + * + * If SIZE_FIXED_OFFSET_FROM_PARENT is used, this actor's size will be based on + * its parent's size plus SizeModeFactor. + * + * @pre The Actor has been initialized. + * @param[in] mode The size relative to parent mode to use. + */ + void SetSizeMode(const SizeMode mode); + + /** + * @brief Returns the actor's mode for modifying its size relative to its parent. + * + * @pre The Actor has been initialized. + * @return The mode used. + */ + SizeMode GetSizeMode() const; + + /** + * @brief Sets the relative to parent size factor of the actor. + * + * This factor is only used when SizeMode is set to either: + * SIZE_RELATIVE_TO_PARENT or SIZE_FIXED_OFFSET_FROM_PARENT. + * This actor's size is set to the actor's parent size multipled by or added to this factor, + * depending on SideMode (See SetSizeMode). + * + * @pre The Actor has been initialized. + * @param [in] factor A Vector3 representing the relative factor to be applied to each axis. + */ + void SetSizeModeFactor(const Vector3& factor); + + /** + * @brief Retrieve the relative to parent size factor of the actor. + * + * @pre The Actor has been initialized. + * @return The Actor's current relative size factor. + */ + Vector3 GetSizeModeFactor() const; + + /** * @brief Retrieves the world-matrix of the actor. * * @note The actor will not have a world-matrix, unless it has previously been added to the stage.