2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/common/object-impl.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
27 #include <dali/internal/update/common/animatable-property.h>
28 #include <dali/internal/update/common/property-owner-messages.h>
29 #include <dali/internal/update/common/uniform-map.h>
30 #include <dali/internal/event/animation/constraint-impl.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/common/property-notification-impl.h>
33 #include <dali/internal/event/common/type-registry-impl.h>
35 using Dali::Internal::SceneGraph::AnimatableProperty;
36 using Dali::Internal::SceneGraph::PropertyBase;
44 namespace // unnamed namespace
46 const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES; // Object provides this capability
47 typedef Dali::Vector<Object::Observer*>::Iterator ObserverIter;
48 typedef Dali::Vector<Object::Observer*>::ConstIterator ConstObserverIter;
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
55 } // unnamed namespace
58 : mEventThreadServices( *Stage::GetCurrent() ),
61 mPropertyNotifications( NULL )
65 void Object::AddObserver(Observer& observer)
67 // make sure an observer doesn't observe the same object twice
68 // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
69 DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
71 mObservers.PushBack( &observer );
74 void Object::RemoveObserver(Observer& observer)
76 // Find the observer...
77 const ConstObserverIter endIter = mObservers.End();
78 for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
80 if( (*iter) == &observer)
82 mObservers.Erase( iter );
86 DALI_ASSERT_DEBUG(endIter != mObservers.End());
89 void Object::OnSceneObjectAdd()
91 // Notification for observers
92 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
94 (*iter)->SceneObjectAdded(*this);
97 // enable property notifications in scene graph
98 EnablePropertyNotifications();
101 void Object::OnSceneObjectRemove()
103 // Notification for observers
104 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
106 (*iter)->SceneObjectRemoved(*this);
109 // disable property notifications in scene graph
110 DisablePropertyNotifications();
113 int Object::GetPropertyComponentIndex( Property::Index index ) const
115 int componentIndex = Property::INVALID_COMPONENT_INDEX;
117 const TypeInfo* typeInfo( GetTypeInfo() );
120 componentIndex = typeInfo->GetComponentIndex(index);
123 // For animatable property, check whether it is registered already and register it if not yet.
124 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) && ( NULL == RegisterAnimatableProperty(index) ) )
126 componentIndex = Property::INVALID_COMPONENT_INDEX;
129 return componentIndex;
132 bool Object::Supports( Capability capability ) const
134 return (capability & SUPPORTED_CAPABILITIES);
137 unsigned int Object::GetPropertyCount() const
139 unsigned int count = GetDefaultPropertyCount();
141 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
143 const TypeInfo* typeInfo( GetTypeInfo() );
146 unsigned int manual( typeInfo->GetPropertyCount() );
149 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties: %d\n", manual );
152 unsigned int custom( mCustomProperties.Count() );
154 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom );
156 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties: %d\n", count );
161 std::string Object::GetPropertyName( Property::Index index ) const
163 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
165 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
167 return GetDefaultPropertyName( index );
170 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
171 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
173 const TypeInfo* typeInfo( GetTypeInfo() );
176 return typeInfo->GetPropertyName( index );
180 DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
184 CustomPropertyMetadata* custom = FindCustomProperty( index );
192 Property::Index Object::GetPropertyIndex(const std::string& name) const
194 Property::Index index = GetDefaultPropertyIndex( name );
196 if(index == Property::INVALID_INDEX)
198 const TypeInfo* typeInfo( GetTypeInfo() );
201 index = typeInfo->GetPropertyIndex( name );
202 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
204 // check whether the animatable property is registered already, if not then register one.
205 if ( NULL == RegisterAnimatableProperty(index) )
207 index = Property::INVALID_INDEX;
213 if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
215 Property::Index count = PROPERTY_CUSTOM_START_INDEX;
216 const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
217 for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
219 CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
220 if ( custom->name == name )
222 if ( custom->childPropertyIndex != Property::INVALID_INDEX )
224 // If it is a child property, return the child property index
225 index = custom->childPropertyIndex;
239 bool Object::IsPropertyWritable( Property::Index index ) const
241 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
243 bool writable = false;
245 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
247 writable = IsDefaultPropertyWritable( index );
249 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
251 const TypeInfo* typeInfo( GetTypeInfo() );
254 writable = typeInfo->IsPropertyWritable( index );
258 DALI_ASSERT_ALWAYS( ! "Invalid property index" );
261 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
263 // Type Registry scene-graph properties are writable.
268 CustomPropertyMetadata* custom = FindCustomProperty( index );
271 writable = custom->IsWritable();
278 bool Object::IsPropertyAnimatable( Property::Index index ) const
280 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
282 bool animatable = false;
284 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
286 animatable = IsDefaultPropertyAnimatable( index );
288 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
290 // Type Registry event-thread only properties are not animatable.
293 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
295 // Type Registry scene-graph properties are animatable.
300 CustomPropertyMetadata* custom = FindCustomProperty( index );
303 animatable = custom->IsAnimatable();
310 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
312 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
314 bool isConstraintInput = false;
316 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
318 isConstraintInput = IsDefaultPropertyAConstraintInput( index );
320 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
322 // Type Registry event-thread only properties cannot be used as an input to a constraint.
323 isConstraintInput = false;
325 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
327 // scene graph properties can be used as input to a constraint.
328 isConstraintInput = true;
332 CustomPropertyMetadata* custom = FindCustomProperty( index );
335 // ... custom properties can be used as input to a constraint.
336 isConstraintInput = true;
340 return isConstraintInput;
343 Property::Type Object::GetPropertyType( Property::Index index ) const
345 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
347 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
349 return GetDefaultPropertyType( index );
352 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
353 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
355 const TypeInfo* typeInfo( GetTypeInfo() );
358 return typeInfo->GetPropertyType( index );
362 DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
366 CustomPropertyMetadata* custom = FindCustomProperty( index );
369 return custom->GetType();
371 else if( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX && index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX )
373 Object* parent = GetParentObject();
376 const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
379 return parentTypeInfo->GetChildPropertyType( index );
384 return Property::NONE;
387 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
389 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
391 bool propertySet( true );
393 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
395 SetDefaultProperty( index, propertyValue );
397 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
399 const TypeInfo* typeInfo( GetTypeInfo() );
402 typeInfo->SetProperty( this, index, propertyValue );
406 DALI_LOG_ERROR("Cannot find property index\n");
410 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
412 // check whether the animatable property is registered already, if not then register one.
413 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
414 if(!animatableProperty)
416 DALI_LOG_ERROR("Cannot find property index\n");
421 // set the scene graph property value
422 SetSceneGraphProperty( index, *animatableProperty, propertyValue );
427 CustomPropertyMetadata* custom = FindCustomProperty( index );
429 if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
433 // If the child property is not registered yet, register it.
434 custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE );
435 mCustomProperties.PushBack( custom );
438 custom->childPropertyIndex = index;
440 // Resolve name for the child property
441 Object* parent = GetParentObject();
444 const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
447 custom->name = parentTypeInfo->GetChildPropertyName( index );
454 if( custom->IsAnimatable() )
456 // set the scene graph property value
457 SetSceneGraphProperty( index, *custom, propertyValue );
459 else if( custom->IsWritable() )
461 custom->value = propertyValue;
465 // trying to set value on read only property is no-op
471 DALI_LOG_ERROR("Invalid property index\n");
476 // Let derived classes know that a property has been set
477 // TODO: We should not call this for read-only properties, SetDefaultProperty() && TypeInfo::SetProperty() should return a bool, which would be true if the property is set
480 OnPropertySet(index, propertyValue);
484 Property::Value Object::GetProperty(Property::Index index) const
486 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
488 Property::Value value;
490 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
492 value = GetDefaultProperty( index );
494 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
496 const TypeInfo* typeInfo( GetTypeInfo() );
499 value = typeInfo->GetProperty( this, index );
503 DALI_LOG_ERROR("Cannot find property index\n");
506 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
508 // check whether the animatable property is registered already, if not then register one.
509 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
510 if(!animatableProperty)
512 DALI_LOG_ERROR("Cannot find property index\n");
516 // get the animatable property value
517 value = GetPropertyValue( animatableProperty );
520 else if(mCustomProperties.Count() > 0)
522 CustomPropertyMetadata* custom = FindCustomProperty( index );
525 // get the custom property value
526 value = GetPropertyValue( custom );
530 DALI_LOG_ERROR("Invalid property index\n");
537 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
541 // Default Properties
542 GetDefaultPropertyIndices( indices );
545 const TypeInfo* typeInfo( GetTypeInfo() );
548 typeInfo->GetPropertyIndices( indices );
552 if ( mCustomProperties.Count() > 0 )
554 indices.Reserve( indices.Size() + mCustomProperties.Count() );
556 PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
557 const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
559 for ( ; iter != endIter; ++iter, ++i )
561 CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( *iter );
562 if ( custom->childPropertyIndex != Property::INVALID_INDEX )
564 // If it is a child property, add the child property index
565 indices.PushBack( custom->childPropertyIndex );
569 indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
575 Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
577 // Create a new property
578 Dali::Internal::OwnerPointer<PropertyBase> newProperty;
580 switch ( propertyValue.GetType() )
582 case Property::BOOLEAN:
584 newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
588 case Property::INTEGER:
590 newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
594 case Property::FLOAT:
596 newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
600 case Property::VECTOR2:
602 newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
606 case Property::VECTOR3:
608 newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
612 case Property::VECTOR4:
614 newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
618 case Property::MATRIX:
620 newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
624 case Property::MATRIX3:
626 newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
630 case Property::ROTATION:
632 newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
636 case Property::RECTANGLE:
637 case Property::STRING:
638 case Property::ARRAY:
642 DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
647 // get the scene property owner from derived class
648 const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
649 // we can only pass properties to scene graph side if there is a scene object
650 if( scenePropertyOwner )
652 // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
653 const PropertyBase* property = newProperty.Get();
654 if(index >= PROPERTY_CUSTOM_START_INDEX)
656 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
660 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
663 // queue a message to add the property
664 InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
666 // notify the derived class (optional) method in case it needs to do some more work on the new property
667 // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
668 NotifyScenePropertyInstalled( *property, name, index );
674 // property was orphaned and killed so return invalid index
675 return Property::INVALID_INDEX;
679 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
681 return RegisterProperty( name, propertyValue, Property::ANIMATABLE );
684 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
686 // If property with the required name already exists, then just set it.
687 Property::Index index = GetPropertyIndex( name );
688 if( index != Property::INVALID_INDEX )
690 SetProperty( index, propertyValue );
694 // Otherwise register the property
696 if(Property::ANIMATABLE == accessMode)
698 index = RegisterSceneGraphProperty( name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue );
699 AddUniformMapping( index, name );
703 // Add entry to the property lookup
704 index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
706 CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode );
708 // Resolve index for the child property
709 Object* parent = GetParentObject();
712 const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
715 Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name );
716 if( childPropertyIndex != Property::INVALID_INDEX )
718 customProperty->childPropertyIndex = childPropertyIndex;
719 index = childPropertyIndex;
724 mCustomProperties.PushBack( customProperty );
731 Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
733 const Dali::PropertyCondition& condition)
735 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
737 if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
739 DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
741 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
743 // check whether the animatable property is registered already, if not then register one.
744 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
745 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
747 else if ( mCustomProperties.Count() > 0 )
749 CustomPropertyMetadata* custom = FindCustomProperty( index );
750 DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
751 DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
755 Dali::Handle self(this);
756 Property target( self, index );
758 PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
759 Dali::PropertyNotification propertyNotification(internal.Get());
761 if( !mPropertyNotifications )
763 mPropertyNotifications = new PropertyNotificationContainer;
765 mPropertyNotifications->push_back(propertyNotification);
767 return propertyNotification;
770 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
772 if( mPropertyNotifications )
774 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
775 while(iter != mPropertyNotifications->end() )
777 if(*iter == propertyNotification)
779 mPropertyNotifications->erase(iter);
780 // As we can't ensure all references are removed, we can just disable
782 GetImplementation(propertyNotification).Disable();
790 void Object::RemovePropertyNotifications()
792 if( mPropertyNotifications )
794 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
795 while(iter != mPropertyNotifications->end() )
797 // As we can't ensure all references are removed, we can just disable
799 GetImplementation(*iter).Disable();
803 mPropertyNotifications->clear();
807 void Object::EnablePropertyNotifications()
809 if( mPropertyNotifications )
811 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
812 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
814 for( ; iter != endIter; ++iter )
816 GetImplementation(*iter).Enable();
821 void Object::DisablePropertyNotifications()
823 if( mPropertyNotifications )
825 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
826 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
828 for( ; iter != endIter; ++iter )
830 GetImplementation(*iter).Disable();
835 void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName ) const
837 // Get the address of the property if it's a scene property
838 const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
840 // Check instead for newly registered properties
841 if( propertyPtr == NULL )
843 PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
844 if( animatable != NULL )
846 propertyPtr = animatable->GetSceneGraphProperty();
850 if( propertyPtr == NULL )
852 PropertyMetadata* custom = FindCustomProperty( propertyIndex );
855 propertyPtr = custom->GetSceneGraphProperty();
859 if( propertyPtr != NULL )
861 const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
863 if( sceneObject != NULL )
865 SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
866 // Message takes ownership of Uniform map (and will delete it after copy)
867 AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map);
871 DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
876 void Object::RemoveUniformMapping( const std::string& uniformName )
878 const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
879 RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
882 Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
884 Property::Value value;
886 DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
888 if( !entry->IsAnimatable() )
890 value = entry->value;
894 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
896 switch ( entry->GetType() )
898 case Property::BOOLEAN:
900 const AnimatableProperty<bool>* property = static_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
901 DALI_ASSERT_DEBUG( NULL != property );
903 value = (*property)[ bufferIndex ];
907 case Property::INTEGER:
909 const AnimatableProperty<int>* property = static_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
910 DALI_ASSERT_DEBUG( NULL != property );
912 value = (*property)[ bufferIndex ];
916 case Property::FLOAT:
918 const AnimatableProperty<float>* property = static_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
919 DALI_ASSERT_DEBUG( NULL != property );
921 value = (*property)[ bufferIndex ];
925 case Property::VECTOR2:
927 const AnimatableProperty<Vector2>* property = static_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
928 DALI_ASSERT_DEBUG( NULL != property );
930 if(entry->componentIndex == 0)
932 value = (*property)[ bufferIndex ].x;
934 else if(entry->componentIndex == 1)
936 value = (*property)[ bufferIndex ].y;
940 value = (*property)[ bufferIndex ];
945 case Property::VECTOR3:
947 const AnimatableProperty<Vector3>* property = static_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
948 DALI_ASSERT_DEBUG( NULL != property );
950 if(entry->componentIndex == 0)
952 value = (*property)[ bufferIndex ].x;
954 else if(entry->componentIndex == 1)
956 value = (*property)[ bufferIndex ].y;
958 else if(entry->componentIndex == 2)
960 value = (*property)[ bufferIndex ].z;
964 value = (*property)[ bufferIndex ];
969 case Property::VECTOR4:
971 const AnimatableProperty<Vector4>* property = static_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
972 DALI_ASSERT_DEBUG( NULL != property );
974 if(entry->componentIndex == 0)
976 value = (*property)[ bufferIndex ].x;
978 else if(entry->componentIndex == 1)
980 value = (*property)[ bufferIndex ].y;
982 else if(entry->componentIndex == 2)
984 value = (*property)[ bufferIndex ].z;
986 else if(entry->componentIndex == 3)
988 value = (*property)[ bufferIndex ].w;
992 value = (*property)[ bufferIndex ];
997 case Property::MATRIX:
999 const AnimatableProperty<Matrix>* property = static_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
1000 DALI_ASSERT_DEBUG( NULL != property );
1002 value = (*property)[ bufferIndex ];
1006 case Property::MATRIX3:
1008 const AnimatableProperty<Matrix3>* property = static_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
1009 DALI_ASSERT_DEBUG( NULL != property );
1011 value = (*property)[ bufferIndex ];
1015 case Property::ROTATION:
1017 const AnimatableProperty<Quaternion>* property = static_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
1018 DALI_ASSERT_DEBUG( NULL != property );
1020 value = (*property)[ bufferIndex ];
1026 DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
1035 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1037 switch ( entry.GetType() )
1039 case Property::BOOLEAN:
1041 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
1042 DALI_ASSERT_DEBUG( NULL != property );
1044 // property is being used in a separate thread; queue a message to set the property
1045 BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
1049 case Property::INTEGER:
1051 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
1052 DALI_ASSERT_DEBUG( NULL != property );
1054 // property is being used in a separate thread; queue a message to set the property
1055 BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
1059 case Property::FLOAT:
1061 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1062 DALI_ASSERT_DEBUG( NULL != property );
1064 // property is being used in a separate thread; queue a message to set the property
1065 BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
1069 case Property::VECTOR2:
1071 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1072 DALI_ASSERT_DEBUG( NULL != property );
1074 // property is being used in a separate thread; queue a message to set the property
1075 if(entry.componentIndex == 0)
1077 SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1079 else if(entry.componentIndex == 1)
1081 SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1085 BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
1090 case Property::VECTOR3:
1092 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1093 DALI_ASSERT_DEBUG( NULL != property );
1095 // property is being used in a separate thread; queue a message to set the property
1096 if(entry.componentIndex == 0)
1098 SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1100 else if(entry.componentIndex == 1)
1102 SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1104 else if(entry.componentIndex == 2)
1106 SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1110 BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1116 case Property::VECTOR4:
1118 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1119 DALI_ASSERT_DEBUG( NULL != property );
1121 // property is being used in a separate thread; queue a message to set the property
1122 if(entry.componentIndex == 0)
1124 SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1126 else if(entry.componentIndex == 1)
1128 SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1130 else if(entry.componentIndex == 2)
1132 SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1134 else if(entry.componentIndex == 3)
1136 SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1140 BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1145 case Property::ROTATION:
1147 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1148 DALI_ASSERT_DEBUG( NULL != property );
1150 // property is being used in a separate thread; queue a message to set the property
1151 BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1155 case Property::MATRIX:
1157 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1158 DALI_ASSERT_DEBUG( NULL != property );
1160 // property is being used in a separate thread; queue a message to set the property
1161 BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1165 case Property::MATRIX3:
1167 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1168 DALI_ASSERT_DEBUG( NULL != property );
1170 // property is being used in a separate thread; queue a message to set the property
1171 BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1177 // non-animatable scene graph property, do nothing
1182 const TypeInfo* Object::GetTypeInfo() const
1186 // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1187 // especially as the type-info does not change during the life-time of an application
1189 Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1190 if ( typeInfoHandle )
1192 mTypeInfo = &GetImplementation( typeInfoHandle );
1199 void Object::ApplyConstraint( ConstraintBase& constraint )
1203 mConstraints = new ConstraintContainer;
1205 mConstraints->push_back( Dali::Constraint( &constraint ) );
1208 void Object::RemoveConstraint( ConstraintBase& constraint )
1210 // NULL if the Constraint sources are destroyed before Constraint::Apply()
1213 ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1214 if( it != mConstraints->end() )
1216 mConstraints->erase( it );
1221 void Object::RemoveConstraints()
1223 // guard against constraint sending messages during core destruction
1224 if( mConstraints && Stage::IsInstalled() )
1226 // If we have nothing in the scene-graph, just clear constraint containers
1227 const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1228 if ( NULL != propertyOwner )
1230 const ConstraintConstIter endIter = mConstraints->end();
1231 for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1233 GetImplementation( *iter ).RemoveInternal();
1237 delete mConstraints;
1238 mConstraints = NULL;
1242 void Object::RemoveConstraints( unsigned int tag )
1244 // guard against constraint sending messages during core destruction
1245 if( mConstraints && Stage::IsInstalled() )
1247 ConstraintIter iter( mConstraints->begin() );
1248 while(iter != mConstraints->end() )
1250 ConstraintBase& constraint = GetImplementation( *iter );
1251 if( constraint.GetTag() == tag )
1253 GetImplementation( *iter ).RemoveInternal();
1254 iter = mConstraints->erase( iter );
1262 if ( mConstraints->empty() )
1264 delete mConstraints;
1265 mConstraints = NULL;
1270 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1272 mTypeInfo = typeInfo;
1277 // Notification for observers
1278 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
1280 (*iter)->ObjectDestroyed(*this);
1283 delete mConstraints;
1284 delete mPropertyNotifications;
1287 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1289 CustomPropertyMetadata* property( NULL );
1291 if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
1293 for ( arrayIndex = 0; arrayIndex < (int)mCustomProperties.Count(); arrayIndex++ )
1295 CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
1296 if( custom->childPropertyIndex == index )
1304 arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1305 if( arrayIndex >= 0 )
1307 if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1309 property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1316 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1318 for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1320 AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1321 if( property->index == index )
1329 AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index index) const
1331 DALI_ASSERT_ALWAYS( (( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ))
1332 && "Property index is out of bounds" );
1334 // check whether the animatable property is registered already, if not then register one.
1335 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1336 if(!animatableProperty)
1338 const TypeInfo* typeInfo( GetTypeInfo() );
1341 Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
1342 if(basePropertyIndex == Property::INVALID_INDEX)
1344 // If the property is not a component of a base property, register the whole property itself.
1345 const std::string& propertyName = typeInfo->GetPropertyName(index);
1346 RegisterSceneGraphProperty(propertyName, index, typeInfo->GetPropertyDefaultValue(index));
1347 AddUniformMapping( index, propertyName );
1351 // Since the property is a component of a base property, check whether the base property is regsitered.
1352 animatableProperty = FindAnimatableProperty( basePropertyIndex );
1353 if(!animatableProperty)
1355 // If the base property is not registered yet, register the base property first.
1356 const std::string& basePropertyName = typeInfo->GetPropertyName(basePropertyIndex);
1357 if(Property::INVALID_INDEX != RegisterSceneGraphProperty(basePropertyName, basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
1359 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1360 AddUniformMapping( basePropertyIndex, basePropertyName );
1364 if(animatableProperty)
1366 // Create the metadata for the property component.
1367 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->GetType(), animatableProperty->GetSceneGraphProperty() ) );
1371 // The metadata has just been added and therefore should be in the end of the vector.
1372 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1376 return animatableProperty;
1379 void Object::ResolveChildProperties()
1381 // Resolve index for the child property
1382 Object* parent = GetParentObject();
1385 const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
1386 if( parentTypeInfo )
1388 // Go through each custom property
1389 for ( int arrayIndex = 0; arrayIndex < (int)mCustomProperties.Count(); arrayIndex++ )
1391 CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
1393 if( customProperty->name == "" )
1395 if( customProperty->childPropertyIndex != Property::INVALID_INDEX )
1397 // Resolve name for any child property with no name
1398 customProperty->name = parentTypeInfo->GetChildPropertyName( customProperty->childPropertyIndex );
1403 Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
1404 if( childPropertyIndex != Property::INVALID_INDEX )
1406 // Resolve index for any property with a name that matches the parent's child property name
1407 customProperty->childPropertyIndex = childPropertyIndex;
1415 } // namespace Internal