/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/devel-api/object/handle-devel.h>
#include <dali/internal/update/animation/scene-graph-constraint-base.h>
#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
#include <dali/internal/update/common/property-owner-messages.h>
#include <dali/internal/update/common/uniform-map.h>
#include <dali/internal/event/animation/constraint-impl.h>
namespace // unnamed namespace
{
-const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES; // Object provides this capability
+const int32_t SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES; // Object provides this capability
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
} // unnamed namespace
-Object::Object()
-: mEventThreadServices( *Stage::GetCurrent() ),
- mTypeInfo( NULL ),
- mConstraints( NULL ),
- mPropertyNotifications( NULL )
+IntrusivePtr<Object> Object::New()
{
+ return new Object( nullptr ); // no scene object by default
}
void Object::AddObserver(Observer& observer)
}
}
-Property::Value Object::GetProperty(Property::Index index) const
+Property::Value Object::GetProperty( Property::Index index ) const
{
DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE );
}
+void Object::SetProperties( const Property::Map& properties )
+{
+ const auto count = properties.Count();
+ for( auto position = 0u; position < count; ++position )
+ {
+ // GetKeyAt and GetValue both return references which means no potential copying of maps/arrays.
+ // Iterating twice to get the value we want should still be fairly quick in a Property::Map.
+
+ const auto& key = properties.GetKeyAt( position );
+ const auto propertyIndex = ( key.type == Property::Key::INDEX ) ? key.indexKey : GetPropertyIndex( key.stringKey );
+
+ if( propertyIndex != Property::INVALID_INDEX )
+ {
+ const auto& value = properties.GetValue( position );
+ SetProperty( propertyIndex, value );
+ }
+ }
+}
+
+void Object::GetProperties( Property::Map& properties )
+{
+ properties.Clear();
+
+ Property::IndexContainer indexContainer;
+ GetPropertyIndices( indexContainer );
+
+ for( auto index : indexContainer )
+ {
+ properties[ index ] = GetProperty( index );
+ }
+}
+
Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
{
return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode );
else
{
// Otherwise register the property
-
if( Property::ANIMATABLE == accessMode )
{
index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>( mCustomProperties.Count() ), propertyValue );
}
else
{
- PropertyMetadata* propertyMetadata = NULL;
+ PropertyMetadata* propertyMetadata = nullptr;
if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
{
propertyMetadata = FindAnimatableProperty( index );
const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
// Check instead for newly registered properties
- if( propertyPtr == NULL )
+ if( propertyPtr == nullptr )
{
PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
- if( animatable != NULL )
+ if( animatable )
{
propertyPtr = animatable->GetSceneGraphProperty();
}
}
- if( propertyPtr == NULL )
+ if( propertyPtr == nullptr )
{
PropertyMetadata* custom = FindCustomProperty( propertyIndex );
- if( custom != NULL )
+ if( custom )
{
propertyPtr = custom->GetSceneGraphProperty();
}
}
- if( propertyPtr != NULL )
+ if( propertyPtr )
{
- const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
+ const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
- if( sceneObject != NULL )
- {
- OwnerPointer< SceneGraph::UniformPropertyMapping > map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
- // Message takes ownership of Uniform map (and will delete it after copy)
- AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map );
- }
- else
- {
- DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
- }
+ OwnerPointer< SceneGraph::UniformPropertyMapping > map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
+ // Message takes ownership of Uniform map (and will delete it after copy)
+ AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, map );
}
}
-void Object::RemoveUniformMapping( const std::string& uniformName )
+void Object::RemoveUniformMapping( const std::string& uniformName ) const
{
- const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
- RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
+ const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
+ RemoveUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, uniformName);
}
void Object::ApplyConstraint( ConstraintBase& constraint )
void Object::RemoveConstraint( ConstraintBase& constraint )
{
- // NULL if the Constraint sources are destroyed before Constraint::Apply()
+ // nullptr if the Constraint sources are destroyed before Constraint::Apply()
if( mConstraints )
{
ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
// guard against constraint sending messages during core destruction
if( mConstraints && Stage::IsInstalled() )
{
- // If we have nothing in the scene-graph, just clear constraint containers
- const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
- if ( NULL != propertyOwner )
+ for ( auto&& item : *mConstraints )
{
- const auto endIter = mConstraints->end();
- for ( auto iter = mConstraints->begin(); endIter != iter; ++iter )
- {
- GetImplementation( *iter ).RemoveInternal();
- }
+ GetImplementation( item ).RemoveInternal();
}
delete mConstraints;
- mConstraints = NULL;
+ mConstraints = nullptr;
}
}
if ( mConstraints->empty() )
{
delete mConstraints;
- mConstraints = NULL;
+ mConstraints = nullptr;
}
}
}
mTypeInfo = typeInfo;
}
+const SceneGraph::PropertyOwner& Object::GetSceneObject() const
+{
+ if( !mUpdateObject )
+ {
+ auto sceneObject = SceneGraph::PropertyOwner::New();
+ OwnerPointer< SceneGraph::PropertyOwner > transferOwnership( sceneObject );
+ mUpdateObject = sceneObject;
+ AddObjectMessage( const_cast<EventThreadServices&>( GetEventThreadServices() ).GetUpdateManager(), transferOwnership );
+ }
+ DALI_ASSERT_DEBUG( mUpdateObject && "there must always be a scene object" );
+ return *mUpdateObject;
+}
+
+const PropertyBase* Object::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+ const SceneGraph::PropertyBase* property = nullptr;
+ if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
+ {
+ AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
+ DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+
+ property = animatable->GetSceneGraphProperty();
+ }
+ else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
+ ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
+ {
+ CustomPropertyMetadata* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+
+ property = custom->GetSceneGraphProperty();
+ }
+ return property;
+}
+
+const PropertyInputImpl* Object::GetSceneObjectInputProperty( Property::Index index ) const
+{
+ // reuse animatable version as they are inputs as well
+ return GetSceneObjectAnimatableProperty( index );
+}
+
int32_t Object::GetPropertyComponentIndex( Property::Index index ) const
{
int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
- const TypeInfo* typeInfo( GetTypeInfo() );
- if ( typeInfo )
+ if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ // check whether the animatable property is registered already, if not then register one.
+ AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
+ if( animatableProperty )
+ {
+ componentIndex = animatableProperty->componentIndex;
+ }
+ }
+ if( Property::INVALID_COMPONENT_INDEX == componentIndex )
{
- componentIndex = typeInfo->GetComponentIndex(index);
+ const TypeInfo* typeInfo( GetTypeInfo() );
+ if ( typeInfo )
+ {
+ componentIndex = typeInfo->GetComponentIndex(index);
+ }
}
return componentIndex;
return mPropertySetSignal;
}
+Object::Object( const SceneGraph::PropertyOwner* sceneObject )
+: mEventThreadServices( EventThreadServices::Get() ),
+ mUpdateObject( sceneObject ),
+ mTypeInfo( nullptr ),
+ mConstraints( nullptr ),
+ mPropertyNotifications( nullptr )
+{
+}
+
Object::~Object()
{
// Notification for observers
- for( auto iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
+ for( auto&& item : mObservers )
{
- (*iter)->ObjectDestroyed(*this);
+ item->ObjectDestroyed( *this );
}
-
delete mConstraints;
delete mPropertyNotifications;
+
+ // Guard to allow handle destruction after Core has been destroyed
+ if( Stage::IsInstalled() )
+ {
+ if( nullptr != mUpdateObject )
+ {
+ RemoveObjectMessage( GetEventThreadServices().GetUpdateManager(), mUpdateObject );
+ }
+ }
}
void Object::OnSceneObjectAdd()
{
// Notification for observers
- for( auto iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
+ for( auto&& item : mObservers )
{
- (*iter)->SceneObjectAdded(*this);
+ item->SceneObjectAdded(*this);
}
// enable property notifications in scene graph
void Object::OnSceneObjectRemove()
{
// Notification for observers
- for( auto iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
+ for( auto&& item : mObservers )
{
- (*iter)->SceneObjectRemoved(*this);
+ item->SceneObjectRemoved(*this);
}
// disable property notifications in scene graph
CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
{
- CustomPropertyMetadata* property( NULL );
+ CustomPropertyMetadata* property = nullptr;
if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
{
for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++ )
}
else
{
- int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
+ int32_t arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
if( arrayIndex >= 0 )
{
- if( arrayIndex < static_cast<int>( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties
+ if( arrayIndex < static_cast<int32_t>( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties
{
property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
}
return property;
}
}
- return NULL;
+ return nullptr;
}
-Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index key, 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;
case Property::INTEGER:
{
- newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
+ newProperty = new AnimatableProperty<int32_t>( propertyValue.Get<int32_t>() );
break;
}
}
}
- // get the scene property owner from derived class
- const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
- // we can only pass properties to scene graph side if there is a scene object
- if( scenePropertyOwner )
+ // get the scene property owner
+ const SceneGraph::PropertyOwner& scenePropertyOwner = GetSceneObject();
+ // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
+ const PropertyBase* property = newProperty.Get();
+ if(index >= PROPERTY_CUSTOM_START_INDEX)
{
- // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
- const PropertyBase* property = newProperty.Get();
- if(index >= PROPERTY_CUSTOM_START_INDEX)
- {
- DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
+ DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
- mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue, property ) );
- }
- else
- {
- mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue, property ) );
- }
-
- // queue a message to add the property
- InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty ); // Message takes ownership
-
- return index;
+ mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue, property ) );
}
else
{
- // property was orphaned and killed so return invalid index
- return Property::INVALID_INDEX;
+ mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue, property ) );
}
+
+ // queue a message to add the property
+ InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), scenePropertyOwner, newProperty ); // Message takes ownership
+
+ return index;
}
void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
}
}
+void Object::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+ // do nothing
+}
+
+Property::Value Object::GetDefaultProperty(Property::Index index) const
+{
+ return Property::Value();
+}
+
+Property::Value Object::GetDefaultPropertyCurrentValue( Property::Index index ) const
+{
+ return GetDefaultProperty( index );
+}
+
void Object::EnablePropertyNotifications()
{
if( mPropertyNotifications )
case Property::BOOLEAN:
{
const AnimatableProperty<bool>* property = static_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::INTEGER:
{
- const AnimatableProperty<int>* property = static_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ const AnimatableProperty<int32_t>* property = static_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::FLOAT:
{
const AnimatableProperty<float>* property = static_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::VECTOR2:
{
const AnimatableProperty<Vector2>* property = static_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
if(entry.componentIndex == 0)
{
case Property::VECTOR3:
{
const AnimatableProperty<Vector3>* property = static_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
if(entry.componentIndex == 0)
{
case Property::VECTOR4:
{
const AnimatableProperty<Vector4>* property = static_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
if(entry.componentIndex == 0)
{
case Property::MATRIX:
{
const AnimatableProperty<Matrix>* property = static_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::MATRIX3:
{
const AnimatableProperty<Matrix3>* property = static_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::ROTATION:
{
const AnimatableProperty<Quaternion>* property = static_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
value = (*property)[ bufferIndex ];
break;
case Property::BOOLEAN:
{
const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
case Property::INTEGER:
{
- const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ const AnimatableProperty<int32_t>* property = dynamic_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
- BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
+ BakeMessage<int32_t>( GetEventThreadServices(), *property, value.Get<int32_t>() );
break;
}
case Property::FLOAT:
{
const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
case Property::VECTOR2:
{
const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
if(entry.componentIndex == 0)
case Property::VECTOR3:
{
const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
if(entry.componentIndex == 0)
case Property::VECTOR4:
{
const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
if(entry.componentIndex == 0)
case Property::ROTATION:
{
const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
case Property::MATRIX:
{
const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
case Property::MATRIX3:
{
const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
+ DALI_ASSERT_DEBUG( property );
// property is being used in a separate thread; queue a message to set the property
BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );