#include <utility>
// INTERNAL INCLUDES
-#include <dali/public-api/common/map-wrapper.h>
#include <dali/public-api/common/constants.h>
#include <dali/public-api/object/property.h>
class CustomProperty
{
public:
- /**
- * Default constructor.
- */
- CustomProperty()
- : type(Property::NONE),
- mProperty(NULL),
- mAccessMode(Property::READ_ONLY)
- {
- }
/**
- * Convenience constructor.
+ * Constructor for scene graph based properties
* @param [in] newName The name 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.
*/
- CustomProperty(const std::string& newName,
+ CustomProperty( const std::string& newName,
Property::Type newType,
const SceneGraph::PropertyBase* newProperty)
: name(newName),
type(newType),
+ value(), // value is held by newProperty
mProperty(newProperty),
mAccessMode(Property::ANIMATABLE)
{
DALI_ASSERT_DEBUG(mProperty && "Uninitialized scenegraph property") ;
}
- CustomProperty(const std::string& newName,
+ /**
+ * Constructor for event side only properties
+ * @param [in] newName The name of the custom property.
+ * @param [in] newIndex The index 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.
+ */
+ CustomProperty( const std::string& newName,
Property::Value newValue,
- Property::AccessMode accessMode)
+ Property::AccessMode accessMode )
: name(newName),
+ type(newValue.GetType()),
value(newValue),
mProperty(NULL),
mAccessMode(accessMode)
{
- type = value.GetType() ;
DALI_ASSERT_DEBUG(accessMode != Property::ANIMATABLE && "Animatable must have scenegraph property") ;
}
+ /**
+ * @return true if the property is animatable (i.e. if its a scene graph property)
+ */
bool IsAnimatable(void) const
{
- return NULL != mProperty ;
+ return NULL != mProperty;
}
+ /**
+ * @return true if the property can be written to
+ */
bool IsWritable(void) const
{
return (mAccessMode == Property::ANIMATABLE) || (mAccessMode == Property::READ_WRITE) ;
}
- std::string name; ///< The name of the property
-
- Property::Type type; ///< The type of the property
-
- Property::Value value ; ///< The property value for a non animatable and custom property
-
+ /**
+ * @return the scene graph property
+ */
const SceneGraph::PropertyBase* GetSceneGraphProperty() const
{
DALI_ASSERT_DEBUG(mProperty && "Get on uninitialized SceneGraph property") ;
return mProperty ;
}
+ std::string name; ///< The name of the property
+ Property::Type type; ///< The type of the property
+ Property::Value value; ///< The property value for a non animatable and custom property
+
+private:
+
+ // Not implemented
+ CustomProperty();
+ CustomProperty( const CustomProperty& );
+ CustomProperty& operator=( const CustomProperty& );
+
private:
const SceneGraph::PropertyBase* mProperty; ///< A pointer to a scene-graph property; should not be modified from actor-thread.
Property::AccessMode mAccessMode; ///< The mode of the property
};
-/**
- * Used for accessing scene-graph properties by property index
- */
-typedef std::map<Property::Index, CustomProperty> CustomPropertyLookup;
-
} // namespace Internal
} // namespace Dali
typedef Dali::Vector<ProxyObject::Observer*>::Iterator ObserverIter;
typedef Dali::Vector<ProxyObject::Observer*>::ConstIterator ConstObserverIter;
-static std::string EMPTY_PROPERTY_NAME;
-
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_PROXY_OBJECT" );
#endif
} // unnamed namespace
ProxyObject::ProxyObject()
-: mNextCustomPropertyIndex( 0u ),
- mCustomProperties( NULL ),
- mTypeInfo( NULL ),
+: mTypeInfo( NULL ),
mConstraints( NULL ),
mPropertyNotifications( NULL )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties: %d\n", manual );
}
- if( mCustomProperties )
- {
- unsigned int custom( mCustomProperties->size() );
- count += custom;
-
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom );
- }
+ unsigned int custom( mCustomProperties.Count() );
+ count += custom;
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom );
DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties: %d\n", count );
}
}
- if( mCustomProperties )
+ CustomProperty* custom = FindCustomProperty( index );
+ if( custom )
{
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Property index is invalid" );
-
- return entry->second.name;
+ return custom->name;
}
- return EMPTY_PROPERTY_NAME;
+ return "";
}
Property::Index ProxyObject::GetPropertyIndex(const std::string& name) const
}
}
- if( index == Property::INVALID_INDEX && mCustomProperties )
+ if( ( index == Property::INVALID_INDEX )&&( mCustomProperties.Count() > 0 ) )
{
- // This is slow, but we're not (supposed to be) using property names frequently
- for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); mCustomProperties->end() != iter; ++iter )
+ Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+ const CustomPropertyLookup::ConstIterator end = mCustomProperties.End();
+ for( CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
{
- if (iter->second.name == name)
+ CustomProperty* custom = *iter;
+ if ( custom->name == name )
{
- index = iter->first;
+ index = count;
break;
}
}
}
else
{
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
+ DALI_ASSERT_ALWAYS( ! "Invalid property index" );
}
}
- if( mCustomProperties)
+ CustomProperty* custom = FindCustomProperty( index );
+ if( custom )
{
// Check that the index is valid
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
- return entry->second.IsWritable();
+ return custom->IsWritable();
}
return false;
}
return false;
}
- if( mCustomProperties )
+ CustomProperty* custom = FindCustomProperty( index );
+ if( custom )
{
- // Check custom property
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
- return entry->second.IsAnimatable();
+ return custom->IsAnimatable();
}
return false;
}
-bool ProxyObject::IsPropertyAConstraintInput(Property::Index index) const
+bool ProxyObject::IsPropertyAConstraintInput( Property::Index index ) const
{
DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
return false;
}
- if( mCustomProperties )
+ CustomProperty* custom = FindCustomProperty( index );
+ if( custom )
{
- // Check custom property
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
// ... custom properties can be used as input to a constraint.
return true;
}
}
}
- if( mCustomProperties )
+ CustomProperty* custom = FindCustomProperty( index );
+ if( custom )
{
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find Property index" );
-
- return entry->second.type;
+ return custom->type;
}
return Property::NONE;
}
DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
}
}
- else if( mCustomProperties )
+ else
{
- CustomPropertyLookup::iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
- DALI_ASSERT_ALWAYS( entry->second.IsWritable() && "Property is read-only" );
-
- // this is only relevant for non animatable properties
- if(entry->second.IsWritable())
- {
- entry->second.value = propertyValue;
- }
+ CustomProperty* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+ DALI_ASSERT_ALWAYS( custom->IsWritable() && "Property is read-only" );
- SetCustomProperty(index, entry->second, propertyValue);
+ // this is only relevant for non animatable properties, but we'll do it anyways
+ custom->value = propertyValue;
+ // set the scene graph property value
+ SetCustomProperty(index, *custom, propertyValue);
}
}
DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
}
}
- else if( mCustomProperties )
+ else if( mCustomProperties.Count() > 0 )
{
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
+ CustomProperty* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
- if( !entry->second.IsAnimatable() )
+ if( !custom->IsAnimatable() )
{
- value = entry->second.value;
+ value = custom->value;
}
else
{
BufferIndex bufferIndex( Stage::GetCurrent()->GetEventBufferIndex() );
- switch ( entry->second.type )
+ switch ( custom->type )
{
case Property::BOOLEAN:
{
- const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::FLOAT:
{
- const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::INTEGER:
{
- const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::VECTOR2:
{
- const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::VECTOR3:
{
- const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::VECTOR4:
{
- const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::MATRIX:
{
- const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::MATRIX3:
{
- const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
case Property::ROTATION:
{
- const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->second.GetSceneGraphProperty() );
+ const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( custom->GetSceneGraphProperty() );
DALI_ASSERT_DEBUG( NULL != property );
value = (*property)[ bufferIndex ];
}
// Custom Properties
- if ( mCustomProperties )
+ if ( mCustomProperties.Count() > 0 )
{
- indices.reserve( indices.size() + mCustomProperties->size() );
+ indices.reserve( indices.size() + mCustomProperties.Count() );
- const CustomPropertyLookup::const_iterator endIter = mCustomProperties->end();
- for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); iter != endIter; ++iter )
+ CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin();
+ const CustomPropertyLookup::ConstIterator endIter = mCustomProperties.End();
+ int i=0;
+ for ( ; iter != endIter; ++iter, ++i )
{
- indices.push_back( iter->first );
+ indices.push_back( PROPERTY_CUSTOM_START_INDEX + i );
}
}
}
Property::Index ProxyObject::RegisterProperty( std::string name, const Property::Value& propertyValue)
{
- // Assert that property name is unused
- DALI_ASSERT_ALWAYS( Property::INVALID_INDEX == GetPropertyIndex(name) && "Property index is out of bounds" );
-
// Create a new property
Dali::Internal::OwnerPointer<PropertyBase> newProperty;
}
}
- // Default properties start from index zero
- if ( 0u == mNextCustomPropertyIndex )
- {
- mNextCustomPropertyIndex = PROPERTY_CUSTOM_START_INDEX;
- }
-
- // Add entry to the property lookup
- const Property::Index index = mNextCustomPropertyIndex++;
-
- CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() == entry && "Custom property already registered" );
-
- (*mCustomProperties)[ index ] = CustomProperty( name, propertyValue.GetType(), newProperty.Get() );
+ const Property::Index index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+ mCustomProperties.PushBack( new CustomProperty( name, propertyValue.GetType(), newProperty.Get() ) );
// The derived class now passes ownership of this new property to a scene-object
// TODO: change this so that OwnerPointer is passed all the way as owership passing cannot be done with a reference
}
else
{
- // Default properties start from index zero
- if ( 0u == mNextCustomPropertyIndex )
- {
- mNextCustomPropertyIndex = PROPERTY_CUSTOM_START_INDEX;
- }
-
// Add entry to the property lookup
- index = mNextCustomPropertyIndex++;
- GetCustomPropertyLookup()[ index ] = CustomProperty( name, propertyValue, accessMode );
+ index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+ mCustomProperties.PushBack( new CustomProperty( name, propertyValue, accessMode ) );
}
return index;
{
if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
{
- DALI_ASSERT_ALWAYS( false && "Property notification added to non animatable property." );
+ DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
}
- else if ( mCustomProperties )
+ else if ( mCustomProperties.Count() > 0 )
{
- CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
- DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
- DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "Property notification added to non animatable property (currently not suppported )");
+ CustomProperty* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+ DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
}
}
}
}
-CustomPropertyLookup& ProxyObject::GetCustomPropertyLookup() const
-{
- // lazy create
- if( !mCustomProperties )
- {
- mCustomProperties = new CustomPropertyLookup;
- }
- return *mCustomProperties;
-}
-
const TypeInfo* ProxyObject::GetTypeInfo() const
{
if ( !mTypeInfo )
(*iter)->ProxyDestroyed(*this);
}
- delete mCustomProperties;
delete mConstraints;
delete mPropertyNotifications;
}
+CustomProperty* ProxyObject::FindCustomProperty( Property::Index index ) const
+{
+ CustomProperty* property( NULL );
+ int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
+ if( arrayIndex >= 0 )
+ {
+ if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
+ {
+ property = mCustomProperties[ arrayIndex ];
+ }
+ }
+ return property;
+}
+
} // namespace Internal
} // namespace Dali
#include <dali/public-api/object/property-index.h>
#include <dali/public-api/object/property-input.h>
#include <dali/public-api/object/property-notification.h>
+#include <dali/internal/common/owner-container.h>
#include <dali/internal/event/common/object-impl.h>
#include <dali/internal/event/common/custom-property.h>
#include <dali/internal/event/common/property-input-impl.h>
namespace Internal
{
+class Stage;
+class PropertyInputImpl;
+class ProxyObject;
+class Constraint;
+class TypeInfo;
+
/**
* @brief Structure for setting up default properties and their details.
*/
bool constraintInput:1; ///< Whether the property can be used as an input to a constraint.
};
-class Stage;
-class PropertyInputImpl;
-class ProxyObject;
-class Constraint;
-class TypeInfo;
-
namespace SceneGraph
{
class PropertyBase;
virtual Property::Index RegisterProperty(std::string name, const Property::Value& propertyValue);
/**
- * @copydoc Dali::Handle::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
+ * @copydoc Dali::Internal::Object::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
*/
virtual Property::Index RegisterProperty(std::string name, const Property::Value& propertyValue, Property::AccessMode accessMode);
/**
- * @copydoc Dali::Handle::AddPropertyNotification()
+ * @copydoc Dali::Internal::Object::AddPropertyNotification()
*/
virtual Dali::PropertyNotification AddPropertyNotification(Property::Index index,
int componentIndex,
const Dali::PropertyCondition& condition);
/**
- * @copydoc Dali::Handle::RemovePropertyNotification()
+ * @copydoc Dali::Internal::Object::RemovePropertyNotification()
*/
virtual void RemovePropertyNotification(Dali::PropertyNotification propertyNotification);
/**
- * @copydoc Dali::Handle::RemovePropertyNotifications()
+ * @copydoc Dali::Internal::Object::RemovePropertyNotifications()
*/
void RemovePropertyNotifications();
protected:
/**
- * Not all proxy objects will have custom properties so we want to only create the lookup when its actually needed
- * @return the custom property lookup
- */
- CustomPropertyLookup& GetCustomPropertyLookup() const;
-
- /**
* Retrieves the TypeInfo for this object. Only retrieves it from the type-registry once and then stores a pointer
* to it locally there-after. The type info will not change during the life-time of the application.
* @return The type-info for this object (Can be NULL)
*/
const TypeInfo* GetTypeInfo() const;
-private:
+ /**
+ * Helper to find custom property
+ * @param index
+ * @return pointer to the property
+ */
+ CustomProperty* FindCustomProperty( Property::Index index ) const;
- Property::Index mNextCustomPropertyIndex; ///< The ID of the next custom property to be registered
+private:
- mutable CustomPropertyLookup* mCustomProperties; ///< Used for accessing custom Node properties, mutable so it can be lazy initialized from const function
+ typedef OwnerContainer<CustomProperty*> CustomPropertyLookup;
+ CustomPropertyLookup mCustomProperties; ///< Used for accessing custom Node properties
mutable TypeInfo const * mTypeInfo; ///< The type-info for this object, mutable so it can be lazy initialized from const method if it is required
Dali::Vector<Observer*> mObservers;