Size Relative feature: Implementation in dali-core plus UTC tests 43/35143/6
authorTom Robinson <tom.robinson@samsung.com>
Mon, 9 Feb 2015 16:14:41 +0000 (16:14 +0000)
committerTom Robinson <tom.robinson@samsung.com>
Wed, 11 Feb 2015 10:02:29 +0000 (10:02 +0000)
Change-Id: I851ca67c4a224f426ffd64713e8fe9c3041941ab

automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-Handle.cpp
automated-tests/src/dali/utc-Dali-Scripting.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/update/manager/update-algorithms.cpp
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/public-api/actors/actor-enumerations.h
dali/public-api/actors/actor.cpp
dali/public-api/actors/actor.h

index 758765f..12d5c7a 100644 (file)
@@ -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
index fdfb01f..0d7c5e3 100644 (file)
@@ -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<float>(),         TEST_LOCATION);
-  DALI_TEST_EQUALS( "a string",  valueMap.GetValue("key").Get<std::string>(),  TEST_LOCATION);
+  DALI_TEST_EQUALS( 5.f,         valueMap.GetValue("2key").Get<float>(),        TEST_LOCATION);
+  DALI_TEST_EQUALS( "a string",  valueMap.GetValue("key").Get<std::string>(),   TEST_LOCATION);
 
   // ordered map
   valueMap = Property::Value(Property::MAP);
index 1d3aa68..5927568 100644 (file)
@@ -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 );
   }
index a06b19e..846a32c 100644 (file)
@@ -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<std::string>(), SIZE_MODE_TABLE, SIZE_MODE_TABLE_COUNT ) );
+      break;
+    }
+
+    case Dali::Actor::SIZE_MODE_FACTOR:
+    {
+      SetSizeModeFactor( property.Get<Vector3>() );
+      break;
+    }
+
     case Dali::Actor::INHERIT_SCALE:
     {
       SetInheritScale( property.Get<bool>() );
@@ -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();
index df1bff7..5b6fe64 100644 (file)
@@ -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:
 
index 0c9e900..a4e0c4b 100644 (file)
@@ -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 );
   }
 }
 
index 7b39c79..91636c8 100644 (file)
@@ -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 )
 {
 }
 
index bc9aa1f..637e05d 100644 (file)
@@ -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;
index ad8560d..9cf5de1 100644 (file)
@@ -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
 
index b76f941..f720c2f 100644 (file)
@@ -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();
index d159f15..21d91af 100644 (file)
@@ -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.