2 * Copyright (c) 2015 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/event/animation/constraint-impl.h>
30 #include <dali/internal/event/common/stage-impl.h>
31 #include <dali/internal/event/common/property-notification-impl.h>
32 #include <dali/internal/event/common/type-registry-impl.h>
34 using Dali::Internal::SceneGraph::AnimatableProperty;
35 using Dali::Internal::SceneGraph::PropertyBase;
43 namespace // unnamed namespace
45 const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES; // Object provides this capability
46 typedef Dali::Vector<Object::Observer*>::Iterator ObserverIter;
47 typedef Dali::Vector<Object::Observer*>::ConstIterator ConstObserverIter;
49 #if defined(DEBUG_ENABLED)
50 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
52 } // unnamed namespace
55 : mEventThreadServices( *Stage::GetCurrent() ),
58 mPropertyNotifications( NULL )
62 void Object::AddObserver(Observer& observer)
64 // make sure an observer doesn't observe the same object twice
65 // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
66 DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
68 mObservers.PushBack( &observer );
71 void Object::RemoveObserver(Observer& observer)
73 // Find the observer...
74 const ConstObserverIter endIter = mObservers.End();
75 for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
77 if( (*iter) == &observer)
79 mObservers.Erase( iter );
83 DALI_ASSERT_DEBUG(endIter != mObservers.End());
86 void Object::OnSceneObjectAdd()
88 // Notification for observers
89 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
91 (*iter)->SceneObjectAdded(*this);
94 // enable property notifications in scene graph
95 EnablePropertyNotifications();
98 void Object::OnSceneObjectRemove()
100 // Notification for observers
101 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
103 (*iter)->SceneObjectRemoved(*this);
106 // disable property notifications in scene graph
107 DisablePropertyNotifications();
110 int Object::GetPropertyComponentIndex( Property::Index index ) const
112 int componentIndex = Property::INVALID_COMPONENT_INDEX;
114 const TypeInfo* typeInfo( GetTypeInfo() );
117 componentIndex = typeInfo->GetComponentIndex(index);
120 // For animatable property, check whether it is registered already and register it if not yet.
121 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) && ( NULL == RegisterAnimatableProperty(index) ) )
123 componentIndex = Property::INVALID_COMPONENT_INDEX;
126 return componentIndex;
129 bool Object::Supports( Capability capability ) const
131 return (capability & SUPPORTED_CAPABILITIES);
134 unsigned int Object::GetPropertyCount() const
136 unsigned int count = GetDefaultPropertyCount();
138 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
140 const TypeInfo* typeInfo( GetTypeInfo() );
143 unsigned int manual( typeInfo->GetPropertyCount() );
146 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties: %d\n", manual );
149 unsigned int custom( mCustomProperties.Count() );
151 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom );
153 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties: %d\n", count );
158 std::string Object::GetPropertyName( Property::Index index ) const
160 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
162 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
164 return GetDefaultPropertyName( index );
167 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
168 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
170 const TypeInfo* typeInfo( GetTypeInfo() );
173 return typeInfo->GetPropertyName( index );
177 DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
181 CustomPropertyMetadata* custom = FindCustomProperty( index );
189 Property::Index Object::GetPropertyIndex(const std::string& name) const
191 Property::Index index = GetDefaultPropertyIndex( name );
193 if(index == Property::INVALID_INDEX)
195 const TypeInfo* typeInfo( GetTypeInfo() );
198 index = typeInfo->GetPropertyIndex( name );
199 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
201 // check whether the animatable property is registered already, if not then register one.
202 if ( NULL == RegisterAnimatableProperty(index) )
204 index = Property::INVALID_INDEX;
210 if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
212 Property::Index count = PROPERTY_CUSTOM_START_INDEX;
213 const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
214 for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
216 CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
217 if ( custom->name == name )
228 bool Object::IsPropertyWritable( Property::Index index ) const
230 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
232 bool writable = false;
234 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
236 writable = IsDefaultPropertyWritable( index );
238 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
240 const TypeInfo* typeInfo( GetTypeInfo() );
243 writable = typeInfo->IsPropertyWritable( index );
247 DALI_ASSERT_ALWAYS( ! "Invalid property index" );
250 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
252 // Type Registry scene-graph properties are writable.
257 CustomPropertyMetadata* custom = FindCustomProperty( index );
260 writable = custom->IsWritable();
267 bool Object::IsPropertyAnimatable( Property::Index index ) const
269 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
271 bool animatable = false;
273 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
275 animatable = IsDefaultPropertyAnimatable( index );
277 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
279 // Type Registry event-thread only properties are not animatable.
282 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
284 // Type Registry scene-graph properties are animatable.
289 CustomPropertyMetadata* custom = FindCustomProperty( index );
292 animatable = custom->IsAnimatable();
299 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
301 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
303 bool isConstraintInput = false;
305 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
307 isConstraintInput = IsDefaultPropertyAConstraintInput( index );
309 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
311 // Type Registry event-thread only properties cannot be used as an input to a constraint.
312 isConstraintInput = false;
314 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
316 // scene graph properties can be used as input to a constraint.
317 isConstraintInput = true;
321 CustomPropertyMetadata* custom = FindCustomProperty( index );
324 // ... custom properties can be used as input to a constraint.
325 isConstraintInput = true;
329 return isConstraintInput;
332 Property::Type Object::GetPropertyType( Property::Index index ) const
334 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
336 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
338 return GetDefaultPropertyType( index );
341 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
342 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
344 const TypeInfo* typeInfo( GetTypeInfo() );
347 return typeInfo->GetPropertyType( index );
351 DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
355 CustomPropertyMetadata* custom = FindCustomProperty( index );
360 return Property::NONE;
363 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
365 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
367 bool propertySet( true );
369 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
371 SetDefaultProperty( index, propertyValue );
373 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
375 const TypeInfo* typeInfo( GetTypeInfo() );
378 typeInfo->SetProperty( this, index, propertyValue );
382 DALI_LOG_ERROR("Cannot find property index\n");
386 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
388 // check whether the animatable property is registered already, if not then register one.
389 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
390 if(!animatableProperty)
392 DALI_LOG_ERROR("Cannot find property index\n");
397 // set the scene graph property value
398 SetSceneGraphProperty( index, *animatableProperty, propertyValue );
403 CustomPropertyMetadata* custom = FindCustomProperty( index );
406 if( custom->IsAnimatable() )
408 // set the scene graph property value
409 SetSceneGraphProperty( index, *custom, propertyValue );
411 else if( custom->IsWritable() )
413 custom->value = propertyValue;
417 // trying to set value on read only property is no-op
423 DALI_LOG_ERROR("Invalid property index\n");
428 // Let derived classes know that a property has been set
429 // 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
432 OnPropertySet(index, propertyValue);
436 Property::Value Object::GetProperty(Property::Index index) const
438 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
440 Property::Value value;
442 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
444 value = GetDefaultProperty( index );
446 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
448 const TypeInfo* typeInfo( GetTypeInfo() );
451 value = typeInfo->GetProperty( this, index );
455 DALI_LOG_ERROR("Cannot find property index\n");
458 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
460 // check whether the animatable property is registered already, if not then register one.
461 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
462 if(!animatableProperty)
464 DALI_LOG_ERROR("Cannot find property index\n");
468 // get the animatable property value
469 value = GetPropertyValue( animatableProperty );
472 else if(mCustomProperties.Count() > 0)
474 CustomPropertyMetadata* custom = FindCustomProperty( index );
477 // get the custom property value
478 value = GetPropertyValue( custom );
482 DALI_LOG_ERROR("Invalid property index\n");
489 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
493 // Default Properties
494 GetDefaultPropertyIndices( indices );
497 const TypeInfo* typeInfo( GetTypeInfo() );
500 typeInfo->GetPropertyIndices( indices );
504 if ( mCustomProperties.Count() > 0 )
506 indices.Reserve( indices.Size() + mCustomProperties.Count() );
508 PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
509 const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
511 for ( ; iter != endIter; ++iter, ++i )
513 indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
518 Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
520 // Create a new property
521 Dali::Internal::OwnerPointer<PropertyBase> newProperty;
523 switch ( propertyValue.GetType() )
525 case Property::BOOLEAN:
527 newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
531 case Property::INTEGER:
533 newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
537 case Property::UNSIGNED_INTEGER:
539 newProperty = new AnimatableProperty<unsigned int>( propertyValue.Get<unsigned int>() );
543 case Property::FLOAT:
545 newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
549 case Property::VECTOR2:
551 newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
555 case Property::VECTOR3:
557 newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
561 case Property::VECTOR4:
563 newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
567 case Property::MATRIX:
569 newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
573 case Property::MATRIX3:
575 newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
579 case Property::ROTATION:
581 newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
585 case Property::RECTANGLE:
586 case Property::STRING:
587 case Property::ARRAY:
590 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
591 DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
597 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
598 DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" );
603 // get the scene property owner from derived class
604 const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
605 // we can only pass properties to scene graph side if there is a scene object
606 if( scenePropertyOwner )
608 // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
609 const PropertyBase* property = newProperty.Get();
610 if(index >= PROPERTY_CUSTOM_START_INDEX)
612 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
616 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
619 // queue a message to add the property
620 InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
622 // notify the derived class (optional) method in case it needs to do some more work on the new property
623 // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
624 NotifyScenePropertyInstalled( *property, name, index );
630 // property was orphaned and killed so return invalid index
631 return Property::INVALID_INDEX;
635 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
637 return RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
640 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
642 Property::Index index = Property::INVALID_INDEX;
644 if(Property::ANIMATABLE == accessMode)
646 index = RegisterProperty(name, propertyValue);
650 // Add entry to the property lookup
651 index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
652 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
658 Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
660 const Dali::PropertyCondition& condition)
662 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
664 if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
666 DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
668 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
670 // check whether the animatable property is registered already, if not then register one.
671 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
672 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
674 else if ( mCustomProperties.Count() > 0 )
676 CustomPropertyMetadata* custom = FindCustomProperty( index );
677 DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
678 DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
682 Dali::Handle self(this);
683 Property target( self, index );
685 PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
686 Dali::PropertyNotification propertyNotification(internal.Get());
688 if( !mPropertyNotifications )
690 mPropertyNotifications = new PropertyNotificationContainer;
692 mPropertyNotifications->push_back(propertyNotification);
694 return propertyNotification;
697 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
699 if( mPropertyNotifications )
701 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
702 while(iter != mPropertyNotifications->end() )
704 if(*iter == propertyNotification)
706 mPropertyNotifications->erase(iter);
707 // As we can't ensure all references are removed, we can just disable
709 GetImplementation(propertyNotification).Disable();
717 void Object::RemovePropertyNotifications()
719 if( mPropertyNotifications )
721 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
722 while(iter != mPropertyNotifications->end() )
724 // As we can't ensure all references are removed, we can just disable
726 GetImplementation(*iter).Disable();
730 mPropertyNotifications->clear();
734 void Object::EnablePropertyNotifications()
736 if( mPropertyNotifications )
738 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
739 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
741 for( ; iter != endIter; ++iter )
743 GetImplementation(*iter).Enable();
748 void Object::DisablePropertyNotifications()
750 if( mPropertyNotifications )
752 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
753 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
755 for( ; iter != endIter; ++iter )
757 GetImplementation(*iter).Disable();
762 Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
764 Property::Value value;
766 DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
768 if( !entry->IsAnimatable() )
770 value = entry->value;
774 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
776 switch ( entry->type )
778 case Property::BOOLEAN:
780 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
781 DALI_ASSERT_DEBUG( NULL != property );
783 value = (*property)[ bufferIndex ];
787 case Property::INTEGER:
789 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
790 DALI_ASSERT_DEBUG( NULL != property );
792 value = (*property)[ bufferIndex ];
796 case Property::UNSIGNED_INTEGER:
798 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry->GetSceneGraphProperty() );
799 DALI_ASSERT_DEBUG( NULL != property );
801 value = (*property)[ bufferIndex ];
805 case Property::FLOAT:
807 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
808 DALI_ASSERT_DEBUG( NULL != property );
810 value = (*property)[ bufferIndex ];
814 case Property::VECTOR2:
816 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
817 DALI_ASSERT_DEBUG( NULL != property );
819 if(entry->componentIndex == 0)
821 value = (*property)[ bufferIndex ].x;
823 else if(entry->componentIndex == 1)
825 value = (*property)[ bufferIndex ].y;
829 value = (*property)[ bufferIndex ];
834 case Property::VECTOR3:
836 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
837 DALI_ASSERT_DEBUG( NULL != property );
839 if(entry->componentIndex == 0)
841 value = (*property)[ bufferIndex ].x;
843 else if(entry->componentIndex == 1)
845 value = (*property)[ bufferIndex ].y;
847 else if(entry->componentIndex == 2)
849 value = (*property)[ bufferIndex ].z;
853 value = (*property)[ bufferIndex ];
858 case Property::VECTOR4:
860 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
861 DALI_ASSERT_DEBUG( NULL != property );
863 if(entry->componentIndex == 0)
865 value = (*property)[ bufferIndex ].x;
867 else if(entry->componentIndex == 1)
869 value = (*property)[ bufferIndex ].y;
871 else if(entry->componentIndex == 2)
873 value = (*property)[ bufferIndex ].z;
875 else if(entry->componentIndex == 3)
877 value = (*property)[ bufferIndex ].w;
881 value = (*property)[ bufferIndex ];
886 case Property::MATRIX:
888 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
889 DALI_ASSERT_DEBUG( NULL != property );
891 value = (*property)[ bufferIndex ];
895 case Property::MATRIX3:
897 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
898 DALI_ASSERT_DEBUG( NULL != property );
900 value = (*property)[ bufferIndex ];
904 case Property::ROTATION:
906 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
907 DALI_ASSERT_DEBUG( NULL != property );
909 value = (*property)[ bufferIndex ];
915 DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
924 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
926 switch ( entry.type )
928 case Property::BOOLEAN:
930 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
931 DALI_ASSERT_DEBUG( NULL != property );
933 // property is being used in a separate thread; queue a message to set the property
934 BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
938 case Property::INTEGER:
940 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
941 DALI_ASSERT_DEBUG( NULL != property );
943 // property is being used in a separate thread; queue a message to set the property
944 BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
948 case Property::UNSIGNED_INTEGER:
950 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry.GetSceneGraphProperty() );
951 DALI_ASSERT_DEBUG( NULL != property );
953 // property is being used in a separate thread; queue a message to set the property
954 BakeMessage<unsigned int>( GetEventThreadServices(), *property, value.Get<unsigned int>() );
958 case Property::FLOAT:
960 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
961 DALI_ASSERT_DEBUG( NULL != property );
963 // property is being used in a separate thread; queue a message to set the property
964 BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
968 case Property::VECTOR2:
970 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
971 DALI_ASSERT_DEBUG( NULL != property );
973 // property is being used in a separate thread; queue a message to set the property
974 if(entry.componentIndex == 0)
976 SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
978 else if(entry.componentIndex == 1)
980 SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
984 BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
989 case Property::VECTOR3:
991 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
992 DALI_ASSERT_DEBUG( NULL != property );
994 // property is being used in a separate thread; queue a message to set the property
995 if(entry.componentIndex == 0)
997 SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
999 else if(entry.componentIndex == 1)
1001 SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1003 else if(entry.componentIndex == 2)
1005 SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1009 BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1015 case Property::VECTOR4:
1017 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1018 DALI_ASSERT_DEBUG( NULL != property );
1020 // property is being used in a separate thread; queue a message to set the property
1021 if(entry.componentIndex == 0)
1023 SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1025 else if(entry.componentIndex == 1)
1027 SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1029 else if(entry.componentIndex == 2)
1031 SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1033 else if(entry.componentIndex == 3)
1035 SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1039 BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1044 case Property::ROTATION:
1046 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1047 DALI_ASSERT_DEBUG( NULL != property );
1049 // property is being used in a separate thread; queue a message to set the property
1050 BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1054 case Property::MATRIX:
1056 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1057 DALI_ASSERT_DEBUG( NULL != property );
1059 // property is being used in a separate thread; queue a message to set the property
1060 BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1064 case Property::MATRIX3:
1066 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1067 DALI_ASSERT_DEBUG( NULL != property );
1069 // property is being used in a separate thread; queue a message to set the property
1070 BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1076 // non-animatable scene graph property, do nothing
1081 const TypeInfo* Object::GetTypeInfo() const
1085 // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1086 // especially as the type-info does not change during the life-time of an application
1088 Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1089 if ( typeInfoHandle )
1091 mTypeInfo = &GetImplementation( typeInfoHandle );
1098 void Object::ApplyConstraint( ConstraintBase& constraint )
1102 mConstraints = new ConstraintContainer;
1104 mConstraints->push_back( Dali::Constraint( &constraint ) );
1107 void Object::RemoveConstraint( ConstraintBase& constraint )
1109 // NULL if the Constraint sources are destroyed before Constraint::Apply()
1112 ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1113 if( it != mConstraints->end() )
1115 mConstraints->erase( it );
1120 void Object::RemoveConstraints()
1122 // guard against constraint sending messages during core destruction
1123 if( mConstraints && Stage::IsInstalled() )
1125 // If we have nothing in the scene-graph, just clear constraint containers
1126 const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1127 if ( NULL != propertyOwner )
1129 const ConstraintConstIter endIter = mConstraints->end();
1130 for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1132 GetImplementation( *iter ).RemoveInternal();
1136 delete mConstraints;
1137 mConstraints = NULL;
1141 void Object::RemoveConstraints( unsigned int tag )
1143 // guard against constraint sending messages during core destruction
1144 if( mConstraints && Stage::IsInstalled() )
1146 ConstraintIter iter( mConstraints->begin() );
1147 while(iter != mConstraints->end() )
1149 ConstraintBase& constraint = GetImplementation( *iter );
1150 if( constraint.GetTag() == tag )
1152 GetImplementation( *iter ).RemoveInternal();
1153 iter = mConstraints->erase( iter );
1161 if ( mConstraints->empty() )
1163 delete mConstraints;
1164 mConstraints = NULL;
1169 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1171 mTypeInfo = typeInfo;
1176 // Notification for observers
1177 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
1179 (*iter)->ObjectDestroyed(*this);
1182 delete mConstraints;
1183 delete mPropertyNotifications;
1186 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1188 CustomPropertyMetadata* property( NULL );
1189 int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1190 if( arrayIndex >= 0 )
1192 if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1194 property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1200 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1202 for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1204 AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1205 if( property->index == index )
1213 AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index index) const
1215 DALI_ASSERT_ALWAYS( (( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ))
1216 && "Property index is out of bounds" );
1218 // check whether the animatable property is registered already, if not then register one.
1219 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1220 if(!animatableProperty)
1222 const TypeInfo* typeInfo( GetTypeInfo() );
1225 Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
1226 if(basePropertyIndex == Property::INVALID_INDEX)
1228 // If the property is not a component of a base property, register the whole property itself.
1229 index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
1233 // Since the property is a component of a base property, check whether the base property is regsitered.
1234 animatableProperty = FindAnimatableProperty( basePropertyIndex );
1235 if(!animatableProperty)
1237 // If the base property is not registered yet, register the base property first.
1238 if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(basePropertyIndex), basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
1240 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1244 // Create the metadata for the property component.
1245 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->type, animatableProperty->GetSceneGraphProperty() ) );
1248 // The metadata has just been added and therefore should be in the end of the vector.
1249 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1253 return animatableProperty;
1256 } // namespace Internal