Added integer keys for custom properties. 16/83416/3
authorDavid Steele <david.steele@samsung.com>
Wed, 10 Aug 2016 14:06:49 +0000 (15:06 +0100)
committerDavid Steele <david.steele@samsung.com>
Thu, 11 Aug 2016 13:31:22 +0000 (14:31 +0100)
Custom properties (those that are registered, rather than predefined
in the DEFAULT range), can now also be registered with an integer key
in addition to the name.

The key can then be used to retrieve the property index. This is of
use for renderer properties that are well specified in toolkit.

Change-Id: Ieda47070f30f5cb53514c9358843f24868a3da3e
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/utc-Dali-Handle.cpp
dali/internal/event/common/object-impl.cpp
dali/internal/event/common/object-impl.h
dali/internal/event/common/property-metadata.h
dali/public-api/object/handle.cpp
dali/public-api/object/handle.h
dali/public-api/object/property.cpp
dali/public-api/object/property.h

index 4595d31..387676b 100644 (file)
@@ -592,7 +592,7 @@ int UtcDaliHandleSetProperty02(void)
   END_TEST;
 }
 
-int UtcDaliHandleRegisterProperty(void)
+int UtcDaliHandleRegisterProperty01(void)
 {
   tet_infoline("Positive Test Dali::Handle::RegisterProperty()");
   TestApplication application;
@@ -629,6 +629,108 @@ int UtcDaliHandleRegisterProperty(void)
   END_TEST;
 }
 
+int UtcDaliHandleRegisterProperty02(void)
+{
+  tet_infoline("Positive Test Dali::Handle::RegisterProperty() int key");
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  stage.Add( actor );
+
+  const unsigned int defaultPropertyCount = actor.GetPropertyCount();
+
+  application.SendNotification();
+  application.Render();
+
+  Property::Index key1 = CORE_PROPERTY_MAX_INDEX+1;
+  Property::Index key2 = CORE_PROPERTY_MAX_INDEX+2;
+
+  const Vector4 testColor(0.5f, 0.2f, 0.9f, 1.0f);
+  const float withFlake(99.f);
+
+  Property::Index index1 = actor.RegisterProperty( "MyPropertyOne", Vector3::ONE );
+  Property::Index index2 = actor.RegisterProperty( key1, "sideColor", testColor);
+  Property::Index index3 = actor.RegisterProperty( key2, "iceCream", withFlake );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetPropertyCount(), defaultPropertyCount + 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty< Vector3 >( index1 ), Vector3::ONE, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty< Vector4 >( index2 ), testColor, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty< float >( index3 ), withFlake, TEST_LOCATION );
+
+  // No new property should be registered when we call the below functions
+  Property::Index testIndex2 = actor.RegisterProperty( "iceCream", 2200.f );
+  Property::Index testIndex1 = actor.RegisterProperty( "sideColor", Color::BLACK );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( index2, testIndex1, TEST_LOCATION ); // We should have the same index as per the first registration
+  DALI_TEST_EQUALS( index3, testIndex2, TEST_LOCATION ); // We should have the same index as per the first registration
+  DALI_TEST_EQUALS( actor.GetPropertyCount(), defaultPropertyCount + 3, TEST_LOCATION ); // Property count should be the same
+  DALI_TEST_EQUALS( actor.GetProperty< Vector4 >( index2 ), Color::BLACK, TEST_LOCATION ); // Value should be what we sent on second RegisterProperty call
+  DALI_TEST_EQUALS( actor.GetProperty< float >( index3 ), 2200.f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliHandleGetPropertyIndex02(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyIndex() int key");
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  stage.Add( actor );
+
+  const unsigned int defaultPropertyCount = actor.GetPropertyCount();
+
+  application.SendNotification();
+  application.Render();
+
+  Property::Index key1 = CORE_PROPERTY_MAX_INDEX+1;
+  Property::Index key2 = CORE_PROPERTY_MAX_INDEX+2;
+
+  const Vector4 testColor(0.5f, 0.2f, 0.9f, 1.0f);
+  const float withFlake(99.f);
+
+  Property::Index index1 = actor.RegisterProperty( "MyPropertyOne", Vector3::ONE );
+  Property::Index index2 = actor.RegisterProperty( key1, "sideColor", testColor);
+  Property::Index index3 = actor.RegisterProperty( "MyPropertyTwo", Vector3::ONE );
+  Property::Index index4 = actor.RegisterProperty( key2, "iceCream", withFlake );
+  Property::Index index5 = actor.RegisterProperty( "MyPropertyThree", Vector3::ONE );
+
+  application.SendNotification();
+  application.Render();
+
+  // Test that we can get the property index from the integer key
+  Property::Index testIndex1 = actor.GetPropertyIndex( key1 );
+  Property::Index testIndex2 = actor.GetPropertyIndex( key2 );
+
+  DALI_TEST_EQUALS( index2, testIndex1, TEST_LOCATION );
+  DALI_TEST_EQUALS( index4, testIndex2, TEST_LOCATION );
+
+  // Test that we keep the same indices on the named properties
+  Property::Index testIndex = actor.GetPropertyIndex("MyPropertyOne");
+  DALI_TEST_EQUALS(testIndex, index1, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("MyPropertyTwo");
+  DALI_TEST_EQUALS(testIndex, index3, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("MyPropertyThree");
+  DALI_TEST_EQUALS(testIndex, index5, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("sideColor");
+  DALI_TEST_EQUALS(testIndex, index2, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("iceCream");
+  DALI_TEST_EQUALS(testIndex, index4, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(defaultPropertyCount+5, actor.GetPropertyCount(), TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliHandleGetProperty(void)
 {
   tet_infoline("Positive Test Dali::Handle::GetProperty()");
@@ -692,8 +794,27 @@ int UtcDaliHandleGetPropertyIndices(void)
   // Actor
   Actor actor = Actor::New();
   actor.GetPropertyIndices( indices );
-  DALI_TEST_CHECK( indices.Size() );
-  DALI_TEST_EQUALS( indices.Size(), actor.GetPropertyCount(), TEST_LOCATION );
+  int numDefaultProperties = indices.Size();
+  DALI_TEST_CHECK( numDefaultProperties > 0 );
+  DALI_TEST_EQUALS( numDefaultProperties, actor.GetPropertyCount(), TEST_LOCATION );
+
+  const Vector4 testColor(0.5f, 0.2f, 0.9f, 1.0f);
+  const float withFlake(99.f);
+
+  Property::Index key1 = CORE_PROPERTY_MAX_INDEX+1;
+  Property::Index key2 = CORE_PROPERTY_MAX_INDEX+2;
+
+  actor.RegisterProperty( "MyPropertyOne", Vector3::ONE );
+  actor.RegisterProperty( key1, "sideColor", testColor);
+  actor.RegisterProperty( "MyPropertyTwo", 1234 );
+  Property::Index index4 = actor.RegisterProperty( key2, "iceCream", withFlake );
+  actor.RegisterProperty( "MyPropertyThree", Vector2(.2f,.7f) );
+
+  actor.GetPropertyIndices( indices );
+
+  DALI_TEST_EQUALS( indices.Size(), numDefaultProperties + 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( indices[indices.Size()-2], index4, TEST_LOCATION );
+
   END_TEST;
 }
 
@@ -785,4 +906,3 @@ int UtcDaliHandleWeightNew(void)
 
   END_TEST;
 }
-
index a9af750..14a5008 100644 (file)
@@ -243,6 +243,36 @@ Property::Index Object::GetPropertyIndex(const std::string& name) const
   return index;
 }
 
+Property::Index Object::GetPropertyIndex( Property::Index key ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  if( mCustomProperties.Count() > 0 )
+  {
+    Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+    const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
+    for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
+    {
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
+      if( custom->key == key )
+      {
+        if( custom->childPropertyIndex != Property::INVALID_INDEX )
+        {
+          // If it is a child property, return the child property index
+          index = custom->childPropertyIndex;
+        }
+        else
+        {
+          index = count;
+        }
+        break;
+      }
+    }
+  }
+
+  return index;
+}
+
 bool Object::IsPropertyWritable( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
@@ -567,7 +597,7 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
   }
 }
 
-Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
+Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue) const
 {
   // Create a new property
   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
@@ -650,7 +680,7 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
     {
       DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
 
-      mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
+      mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue.GetType(), property ) );
     }
     else
     {
@@ -675,14 +705,33 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
 
 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
 {
-  return RegisterProperty( name, propertyValue, Property::ANIMATABLE );
+  return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE );
+}
+
+Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue )
+{
+  return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE );
 }
 
 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
 {
-  // If property with the required name already exists, then just set it.
-  Property::Index index = GetPropertyIndex( name );
-  if( index != Property::INVALID_INDEX )
+  return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode );
+}
+
+Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue, Property::AccessMode accessMode )
+{
+  // If property with the required key already exists, then just set it.
+  Property::Index index = Property::INVALID_INDEX;
+  if( key != Property::INVALID_KEY ) // Try integer key first if it's valid
+  {
+    index = GetPropertyIndex( key );
+  }
+  if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name
+  {
+    index = GetPropertyIndex( name );
+  }
+
+  if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it.
   {
     SetProperty( index, propertyValue );
   }
@@ -690,9 +739,9 @@ Property::Index Object::RegisterProperty( const std::string& name, const Propert
   {
     // Otherwise register the property
 
-    if(Property::ANIMATABLE == accessMode)
+    if( Property::ANIMATABLE == accessMode )
     {
-      index = RegisterSceneGraphProperty( name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue );
+      index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue );
       AddUniformMapping( index, name );
     }
     else
@@ -1329,28 +1378,29 @@ AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index i
 
   // check whether the animatable property is registered already, if not then register one.
   AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
-  if(!animatableProperty)
+  if( !animatableProperty )
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
-    if (typeInfo)
+    if( typeInfo )
     {
       Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
-      if(basePropertyIndex == Property::INVALID_INDEX)
+      if( basePropertyIndex == Property::INVALID_INDEX )
       {
         // If the property is not a component of a base property, register the whole property itself.
         const  std::string& propertyName = typeInfo->GetPropertyName(index);
-        RegisterSceneGraphProperty(propertyName, index, typeInfo->GetPropertyDefaultValue(index));
+        RegisterSceneGraphProperty(propertyName, Property::INVALID_KEY, index, typeInfo->GetPropertyDefaultValue(index));
         AddUniformMapping( index, propertyName );
       }
       else
       {
-        // Since the property is a component of a base property, check whether the base property is regsitered.
+        // Since the property is a component of a base property, check whether the base property is registered.
         animatableProperty = FindAnimatableProperty( basePropertyIndex );
-        if(!animatableProperty)
+        if( !animatableProperty )
         {
           // If the base property is not registered yet, register the base property first.
           const  std::string& basePropertyName = typeInfo->GetPropertyName(basePropertyIndex);
-          if(Property::INVALID_INDEX != RegisterSceneGraphProperty(basePropertyName, basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
+
+          if( Property::INVALID_INDEX != RegisterSceneGraphProperty( basePropertyName, Property::INVALID_KEY, basePropertyIndex, Property::Value(typeInfo->GetPropertyType( basePropertyIndex ) ) ) )
           {
             animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
             AddUniformMapping( basePropertyIndex, basePropertyName );
index b7e6836..b4fbc53 100644 (file)
@@ -151,6 +151,11 @@ public:
   virtual Property::Index GetPropertyIndex( const std::string& name ) const;
 
   /**
+   * @copydoc Dali::Handle::GetPropertyIndex()
+   */
+  virtual Property::Index GetPropertyIndex( Property::Index key ) const;
+
+  /**
    * @copydoc Dali::Handle::IsPropertyWritable()
    */
   virtual bool IsPropertyWritable( Property::Index index ) const;
@@ -191,11 +196,21 @@ public:
   virtual Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue );
 
   /**
+   * @copydoc Dali::Handle::RegisterProperty()
+   */
+  virtual Property::Index RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue );
+
+  /**
    * @copydoc Dali::Handle::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
    */
   virtual Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode );
 
   /**
+   * @brief Implementing method for this override
+   */
+  virtual Property::Index RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue, Property::AccessMode accessMode );
+
+  /**
    * @copydoc Dali::Handle::AddPropertyNotification()
    */
   virtual Dali::PropertyNotification AddPropertyNotification( Property::Index index,
@@ -352,11 +367,12 @@ protected:
   /**
    * Helper to register a scene-graph property
    * @param [in] name The name of the property.
+   * @param [in] key The key of the property
    * @param [in] index The index of the property
    * @param [in] value The value of the property.
    * @return The index of the registered property or Property::INVALID_INDEX if registration failed.
    */
-  Property::Index RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const;
+  Property::Index RegisterSceneGraphProperty(const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue) const;
 
   /**
    * Check whether the animatable property is registered already, if not then register one.
index 0900afe..b0af410 100644 (file)
@@ -201,13 +201,16 @@ public:
   /**
    * Constructor for metadata of scene graph based properties
    * @param [in] newName The name of the custom property.
+   * @param [in] newKey  The key of the custom property.
    * @param [in] newType The type ID of the custom property.
    * @param [in] newProperty A pointer to the scene-graph owned property.
    */
   CustomPropertyMetadata( const std::string& newName,
+                          Property::Index newKey,
                           Property::Type newType,
                           const SceneGraph::PropertyBase* newProperty)
   : name(newName),
+    key(newKey),
     childPropertyIndex(Property::INVALID_INDEX),
     mAccessMode(Property::ANIMATABLE)
   {
@@ -226,6 +229,7 @@ public:
                           Property::Value newValue,
                           Property::AccessMode accessMode )
   : name(newName),
+    key(Property::INVALID_KEY),
     childPropertyIndex(Property::INVALID_INDEX),
     mAccessMode(accessMode)
   {
@@ -242,6 +246,7 @@ public:
   }
 
   std::string name;       ///< The name of the property
+  Property::Index key;    ///< The key of the property
   Property::Index childPropertyIndex; ///< The index as a child property
 
 private:
index 80da558..ea5ddd9 100644 (file)
@@ -90,6 +90,11 @@ Property::Index Handle::GetPropertyIndex( const std::string& name ) const
   return GetImplementation(*this).GetPropertyIndex( name );
 }
 
+Property::Index Handle::GetPropertyIndex( Property::Index key ) const
+{
+  return GetImplementation(*this).GetPropertyIndex( key );
+}
+
 bool Handle::IsPropertyWritable( Property::Index index ) const
 {
   return GetImplementation(*this).IsPropertyWritable( index );
@@ -120,6 +125,11 @@ Property::Index Handle::RegisterProperty( const std::string& name, const Propert
   return GetImplementation(*this).RegisterProperty( name, propertyValue );
 }
 
+Property::Index Handle::RegisterProperty( Property::Index key, const std::string& name, const Property::Value& propertyValue )
+{
+  return GetImplementation(*this).RegisterProperty( name, key, propertyValue );
+}
+
 Property::Index Handle::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
 {
   return GetImplementation(*this).RegisterProperty( name, propertyValue, accessMode );
index 7d0e5a0..b0f7f6b 100644 (file)
@@ -178,6 +178,23 @@ public:
   Property::Index GetPropertyIndex( const std::string& name ) const;
 
   /**
+   * @brief Query the index of a custom property matching the given key.
+   *
+   * Returns the first custom property that matches the given integer key. This is
+   * useful for other classes that know the key but not the name. Requires the property
+   * to have been registered with the associated key.
+   *
+   * @note This key is not the same as the Property enum found in
+   * objects such as Actor (which is a preset index).
+   *
+   * @SINCE_1_2.1
+   * @param [in] key The integer key of the property
+   * @return The index of the property, or Property::INVALID_INDEX if no property exists with the given key.
+   * @note The key is not the same as the returned index, though it has the same type.
+   */
+  Property::Index GetPropertyIndex( Property::Index key ) const;
+
+  /**
    * @brief Query whether a property can be set using SetProperty().
    *
    * @SINCE_1_0.0
@@ -252,6 +269,40 @@ public:
   Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue );
 
   /**
+   * @brief Register a new animatable property with an integer key.
+   *
+   * @SINCE_1_2.1
+   * @param [in] key  The integer key of the property.
+   * @param [in] name The text key of the property.
+   * @param [in] propertyValue The new value of the property.
+   * @return The index of the property or Property::INVALID_INDEX if registration failed
+   * @pre The object supports dynamic properties i.e. Supports(Handle::DYNAMIC_PROPERTIES) returns true.
+   * Property names and keys are expected to be unique, but this is not enforced.
+   * Property indices are unique to each registered custom property in a given object.
+   * @note Returns Property::INVALID_INDEX if registration failed. This can happen if you try to register
+   * animatable property on an object that does not have scene graph object.
+   * @note The returned property index is not the same as the integer key (though it shares a type)
+   *
+   * This version of RegisterProperty associates both an integer key
+   * and the text key with the property, allowing for lookup of the
+   * property index by either key or name ( which is useful when other
+   * classes know the key but not the name )
+   *
+   * @note Only the following types can be animated:
+   *       - Property::BOOLEAN
+   *       - Property::FLOAT
+   *       - Property::INTEGER
+   *       - Property::VECTOR2
+   *       - Property::VECTOR3
+   *       - Property::VECTOR4
+   *       - Property::MATRIX3
+   *       - Property::MATRIX
+   *       - Property::ROTATION
+   * @note If a property with the desired name already exists, then the value given is just set.
+   */
+  Property::Index RegisterProperty( Property::Index key, const std::string& name, const Property::Value& propertyValue );
+
+  /**
    * @brief Register a new property.
    *
    * Properties can be set as non animatable using property attributes.
index cc2386a..ba6cf7d 100644 (file)
@@ -24,7 +24,8 @@
 namespace Dali
 {
 
-const int Property::INVALID_INDEX = -1;
+const int Property::INVALID_INDEX           = -1;
+const int Property::INVALID_KEY             = -1;
 const int Property::INVALID_COMPONENT_INDEX = -1;
 
 Property::Property(Handle& obj, Property::Index propIndex)
index 03c40e0..b280269 100644 (file)
@@ -48,6 +48,7 @@ struct DALI_IMPORT_API Property
   typedef int Index;
 
   static const int INVALID_INDEX; ///< -1 is not a valid property index
+  static const int INVALID_KEY;   ///< -1 is not a valid property key
   static const int INVALID_COMPONENT_INDEX; ///< -1 is not a valid property index
 
   typedef Dali::Vector< Index > IndexContainer; ///< A vector of property indices @SINCE_1_0.0