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/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 )
231 bool Object::IsPropertyWritable( Property::Index index ) const
233 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
235 bool writable = false;
237 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
239 writable = IsDefaultPropertyWritable( index );
241 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
243 const TypeInfo* typeInfo( GetTypeInfo() );
246 writable = typeInfo->IsPropertyWritable( index );
250 DALI_ASSERT_ALWAYS( ! "Invalid property index" );
253 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
255 // Type Registry scene-graph properties are writable.
260 CustomPropertyMetadata* custom = FindCustomProperty( index );
263 writable = custom->IsWritable();
270 bool Object::IsPropertyAnimatable( Property::Index index ) const
272 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
274 bool animatable = false;
276 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
278 animatable = IsDefaultPropertyAnimatable( index );
280 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
282 // Type Registry event-thread only properties are not animatable.
285 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
287 // Type Registry scene-graph properties are animatable.
292 CustomPropertyMetadata* custom = FindCustomProperty( index );
295 animatable = custom->IsAnimatable();
302 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
304 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
306 bool isConstraintInput = false;
308 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
310 isConstraintInput = IsDefaultPropertyAConstraintInput( index );
312 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
314 // Type Registry event-thread only properties cannot be used as an input to a constraint.
315 isConstraintInput = false;
317 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
319 // scene graph properties can be used as input to a constraint.
320 isConstraintInput = true;
324 CustomPropertyMetadata* custom = FindCustomProperty( index );
327 // ... custom properties can be used as input to a constraint.
328 isConstraintInput = true;
332 return isConstraintInput;
335 Property::Type Object::GetPropertyType( Property::Index index ) const
337 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
339 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
341 return GetDefaultPropertyType( index );
344 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
345 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
347 const TypeInfo* typeInfo( GetTypeInfo() );
350 return typeInfo->GetPropertyType( index );
354 DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
358 CustomPropertyMetadata* custom = FindCustomProperty( index );
363 return Property::NONE;
366 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
368 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
370 bool propertySet( true );
372 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
374 SetDefaultProperty( index, propertyValue );
376 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
378 const TypeInfo* typeInfo( GetTypeInfo() );
381 typeInfo->SetProperty( this, index, propertyValue );
385 DALI_LOG_ERROR("Cannot find property index\n");
389 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
391 // check whether the animatable property is registered already, if not then register one.
392 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
393 if(!animatableProperty)
395 DALI_LOG_ERROR("Cannot find property index\n");
400 // set the scene graph property value
401 SetSceneGraphProperty( index, *animatableProperty, propertyValue );
406 CustomPropertyMetadata* custom = FindCustomProperty( index );
409 if( custom->IsAnimatable() )
411 // set the scene graph property value
412 SetSceneGraphProperty( index, *custom, propertyValue );
414 else if( custom->IsWritable() )
416 custom->value = propertyValue;
420 // trying to set value on read only property is no-op
426 DALI_LOG_ERROR("Invalid property index\n");
431 // Let derived classes know that a property has been set
432 // 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
435 OnPropertySet(index, propertyValue);
439 Property::Value Object::GetProperty(Property::Index index) const
441 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
443 Property::Value value;
445 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
447 value = GetDefaultProperty( index );
449 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
451 const TypeInfo* typeInfo( GetTypeInfo() );
454 value = typeInfo->GetProperty( this, index );
458 DALI_LOG_ERROR("Cannot find property index\n");
461 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
463 // check whether the animatable property is registered already, if not then register one.
464 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
465 if(!animatableProperty)
467 DALI_LOG_ERROR("Cannot find property index\n");
471 // get the animatable property value
472 value = GetPropertyValue( animatableProperty );
475 else if(mCustomProperties.Count() > 0)
477 CustomPropertyMetadata* custom = FindCustomProperty( index );
480 // get the custom property value
481 value = GetPropertyValue( custom );
485 DALI_LOG_ERROR("Invalid property index\n");
492 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
496 // Default Properties
497 GetDefaultPropertyIndices( indices );
500 const TypeInfo* typeInfo( GetTypeInfo() );
503 typeInfo->GetPropertyIndices( indices );
507 if ( mCustomProperties.Count() > 0 )
509 indices.Reserve( indices.Size() + mCustomProperties.Count() );
511 PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
512 const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
514 for ( ; iter != endIter; ++iter, ++i )
516 indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
521 Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
523 // Create a new property
524 Dali::Internal::OwnerPointer<PropertyBase> newProperty;
526 switch ( propertyValue.GetType() )
528 case Property::BOOLEAN:
530 newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
534 case Property::INTEGER:
536 newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
540 case Property::UNSIGNED_INTEGER:
542 newProperty = new AnimatableProperty<unsigned int>( propertyValue.Get<unsigned int>() );
546 case Property::FLOAT:
548 newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
552 case Property::VECTOR2:
554 newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
558 case Property::VECTOR3:
560 newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
564 case Property::VECTOR4:
566 newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
570 case Property::MATRIX:
572 newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
576 case Property::MATRIX3:
578 newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
582 case Property::ROTATION:
584 newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
588 case Property::RECTANGLE:
589 case Property::STRING:
590 case Property::ARRAY:
593 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
594 DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
600 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
601 DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" );
606 // get the scene property owner from derived class
607 const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
608 // we can only pass properties to scene graph side if there is a scene object
609 if( scenePropertyOwner )
611 // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
612 const PropertyBase* property = newProperty.Get();
613 if(index >= PROPERTY_CUSTOM_START_INDEX)
615 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
619 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
622 // queue a message to add the property
623 InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
625 // notify the derived class (optional) method in case it needs to do some more work on the new property
626 // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
627 NotifyScenePropertyInstalled( *property, name, index );
633 // property was orphaned and killed so return invalid index
634 return Property::INVALID_INDEX;
638 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
640 Property::Index index = RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
642 /// @todo: don't keep a table of mappings per handle.
643 AddUniformMapping(index, name);
648 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
650 Property::Index index = Property::INVALID_INDEX;
652 if(Property::ANIMATABLE == accessMode)
654 index = RegisterProperty(name, propertyValue);
658 // Add entry to the property lookup
659 index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
660 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
666 Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
668 const Dali::PropertyCondition& condition)
670 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
672 if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
674 DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
676 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
678 // check whether the animatable property is registered already, if not then register one.
679 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
680 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
682 else if ( mCustomProperties.Count() > 0 )
684 CustomPropertyMetadata* custom = FindCustomProperty( index );
685 DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
686 DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
690 Dali::Handle self(this);
691 Property target( self, index );
693 PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
694 Dali::PropertyNotification propertyNotification(internal.Get());
696 if( !mPropertyNotifications )
698 mPropertyNotifications = new PropertyNotificationContainer;
700 mPropertyNotifications->push_back(propertyNotification);
702 return propertyNotification;
705 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
707 if( mPropertyNotifications )
709 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
710 while(iter != mPropertyNotifications->end() )
712 if(*iter == propertyNotification)
714 mPropertyNotifications->erase(iter);
715 // As we can't ensure all references are removed, we can just disable
717 GetImplementation(propertyNotification).Disable();
725 void Object::RemovePropertyNotifications()
727 if( mPropertyNotifications )
729 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
730 while(iter != mPropertyNotifications->end() )
732 // As we can't ensure all references are removed, we can just disable
734 GetImplementation(*iter).Disable();
738 mPropertyNotifications->clear();
742 void Object::EnablePropertyNotifications()
744 if( mPropertyNotifications )
746 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
747 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
749 for( ; iter != endIter; ++iter )
751 GetImplementation(*iter).Enable();
756 void Object::DisablePropertyNotifications()
758 if( mPropertyNotifications )
760 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
761 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
763 for( ; iter != endIter; ++iter )
765 GetImplementation(*iter).Disable();
770 void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName )
772 // Get the address of the property if it's a scene property
773 const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
775 // Check instead for newly registered properties
776 if( propertyPtr == NULL )
778 PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
779 if( animatable != NULL )
781 propertyPtr = animatable->GetSceneGraphProperty();
785 if( propertyPtr == NULL )
787 PropertyMetadata* custom = FindCustomProperty( propertyIndex );
790 propertyPtr = custom->GetSceneGraphProperty();
794 // @todo MESH_REWORK Store mappings for unstaged objects?
796 if( propertyPtr != NULL )
798 const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
800 if( sceneObject != NULL )
802 SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
803 // Message takes ownership of Uniform map (and will delete it after copy)
804 AddUniformMapMessage( GetEventThreadServices(), *sceneObject, map);
808 // @todo MESH_REWORK FIXME Need to store something that can be sent to the scene
809 // object when staged.
810 DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
815 void Object::RemoveUniformMapping( const std::string& uniformName )
817 const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
818 RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
821 Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
823 Property::Value value;
825 DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
827 if( !entry->IsAnimatable() )
829 value = entry->value;
833 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
835 switch ( entry->type )
837 case Property::BOOLEAN:
839 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
840 DALI_ASSERT_DEBUG( NULL != property );
842 value = (*property)[ bufferIndex ];
846 case Property::INTEGER:
848 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
849 DALI_ASSERT_DEBUG( NULL != property );
851 value = (*property)[ bufferIndex ];
855 case Property::UNSIGNED_INTEGER:
857 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry->GetSceneGraphProperty() );
858 DALI_ASSERT_DEBUG( NULL != property );
860 value = (*property)[ bufferIndex ];
864 case Property::FLOAT:
866 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
867 DALI_ASSERT_DEBUG( NULL != property );
869 value = (*property)[ bufferIndex ];
873 case Property::VECTOR2:
875 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
876 DALI_ASSERT_DEBUG( NULL != property );
878 if(entry->componentIndex == 0)
880 value = (*property)[ bufferIndex ].x;
882 else if(entry->componentIndex == 1)
884 value = (*property)[ bufferIndex ].y;
888 value = (*property)[ bufferIndex ];
893 case Property::VECTOR3:
895 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
896 DALI_ASSERT_DEBUG( NULL != property );
898 if(entry->componentIndex == 0)
900 value = (*property)[ bufferIndex ].x;
902 else if(entry->componentIndex == 1)
904 value = (*property)[ bufferIndex ].y;
906 else if(entry->componentIndex == 2)
908 value = (*property)[ bufferIndex ].z;
912 value = (*property)[ bufferIndex ];
917 case Property::VECTOR4:
919 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
920 DALI_ASSERT_DEBUG( NULL != property );
922 if(entry->componentIndex == 0)
924 value = (*property)[ bufferIndex ].x;
926 else if(entry->componentIndex == 1)
928 value = (*property)[ bufferIndex ].y;
930 else if(entry->componentIndex == 2)
932 value = (*property)[ bufferIndex ].z;
934 else if(entry->componentIndex == 3)
936 value = (*property)[ bufferIndex ].w;
940 value = (*property)[ bufferIndex ];
945 case Property::MATRIX:
947 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
948 DALI_ASSERT_DEBUG( NULL != property );
950 value = (*property)[ bufferIndex ];
954 case Property::MATRIX3:
956 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
957 DALI_ASSERT_DEBUG( NULL != property );
959 value = (*property)[ bufferIndex ];
963 case Property::ROTATION:
965 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
966 DALI_ASSERT_DEBUG( NULL != property );
968 value = (*property)[ bufferIndex ];
974 DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
983 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
985 switch ( entry.type )
987 case Property::BOOLEAN:
989 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
990 DALI_ASSERT_DEBUG( NULL != property );
992 // property is being used in a separate thread; queue a message to set the property
993 BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
997 case Property::INTEGER:
999 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
1000 DALI_ASSERT_DEBUG( NULL != property );
1002 // property is being used in a separate thread; queue a message to set the property
1003 BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
1007 case Property::UNSIGNED_INTEGER:
1009 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry.GetSceneGraphProperty() );
1010 DALI_ASSERT_DEBUG( NULL != property );
1012 // property is being used in a separate thread; queue a message to set the property
1013 BakeMessage<unsigned int>( GetEventThreadServices(), *property, value.Get<unsigned int>() );
1017 case Property::FLOAT:
1019 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1020 DALI_ASSERT_DEBUG( NULL != property );
1022 // property is being used in a separate thread; queue a message to set the property
1023 BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
1027 case Property::VECTOR2:
1029 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1030 DALI_ASSERT_DEBUG( NULL != property );
1032 // property is being used in a separate thread; queue a message to set the property
1033 if(entry.componentIndex == 0)
1035 SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1037 else if(entry.componentIndex == 1)
1039 SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1043 BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
1048 case Property::VECTOR3:
1050 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1051 DALI_ASSERT_DEBUG( NULL != property );
1053 // property is being used in a separate thread; queue a message to set the property
1054 if(entry.componentIndex == 0)
1056 SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1058 else if(entry.componentIndex == 1)
1060 SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1062 else if(entry.componentIndex == 2)
1064 SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1068 BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1074 case Property::VECTOR4:
1076 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1077 DALI_ASSERT_DEBUG( NULL != property );
1079 // property is being used in a separate thread; queue a message to set the property
1080 if(entry.componentIndex == 0)
1082 SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1084 else if(entry.componentIndex == 1)
1086 SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1088 else if(entry.componentIndex == 2)
1090 SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1092 else if(entry.componentIndex == 3)
1094 SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1098 BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1103 case Property::ROTATION:
1105 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1106 DALI_ASSERT_DEBUG( NULL != property );
1108 // property is being used in a separate thread; queue a message to set the property
1109 BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1113 case Property::MATRIX:
1115 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1116 DALI_ASSERT_DEBUG( NULL != property );
1118 // property is being used in a separate thread; queue a message to set the property
1119 BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1123 case Property::MATRIX3:
1125 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1126 DALI_ASSERT_DEBUG( NULL != property );
1128 // property is being used in a separate thread; queue a message to set the property
1129 BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1135 // non-animatable scene graph property, do nothing
1140 const TypeInfo* Object::GetTypeInfo() const
1144 // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1145 // especially as the type-info does not change during the life-time of an application
1147 Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1148 if ( typeInfoHandle )
1150 mTypeInfo = &GetImplementation( typeInfoHandle );
1157 void Object::ApplyConstraint( ConstraintBase& constraint )
1161 mConstraints = new ConstraintContainer;
1163 mConstraints->push_back( Dali::Constraint( &constraint ) );
1166 void Object::RemoveConstraint( ConstraintBase& constraint )
1168 // NULL if the Constraint sources are destroyed before Constraint::Apply()
1171 ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1172 if( it != mConstraints->end() )
1174 mConstraints->erase( it );
1179 void Object::RemoveConstraints()
1181 // guard against constraint sending messages during core destruction
1182 if( mConstraints && Stage::IsInstalled() )
1184 // If we have nothing in the scene-graph, just clear constraint containers
1185 const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1186 if ( NULL != propertyOwner )
1188 const ConstraintConstIter endIter = mConstraints->end();
1189 for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1191 GetImplementation( *iter ).RemoveInternal();
1195 delete mConstraints;
1196 mConstraints = NULL;
1200 void Object::RemoveConstraints( unsigned int tag )
1202 // guard against constraint sending messages during core destruction
1203 if( mConstraints && Stage::IsInstalled() )
1205 ConstraintIter iter( mConstraints->begin() );
1206 while(iter != mConstraints->end() )
1208 ConstraintBase& constraint = GetImplementation( *iter );
1209 if( constraint.GetTag() == tag )
1211 GetImplementation( *iter ).RemoveInternal();
1212 iter = mConstraints->erase( iter );
1220 if ( mConstraints->empty() )
1222 delete mConstraints;
1223 mConstraints = NULL;
1228 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1230 mTypeInfo = typeInfo;
1235 // Notification for observers
1236 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
1238 (*iter)->ObjectDestroyed(*this);
1241 delete mConstraints;
1242 delete mPropertyNotifications;
1245 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1247 CustomPropertyMetadata* property( NULL );
1248 int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1249 if( arrayIndex >= 0 )
1251 if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1253 property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1259 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1261 for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1263 AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1264 if( property->index == index )
1272 AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index index) const
1274 DALI_ASSERT_ALWAYS( (( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ))
1275 && "Property index is out of bounds" );
1277 // check whether the animatable property is registered already, if not then register one.
1278 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1279 if(!animatableProperty)
1281 const TypeInfo* typeInfo( GetTypeInfo() );
1284 Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
1285 if(basePropertyIndex == Property::INVALID_INDEX)
1287 // If the property is not a component of a base property, register the whole property itself.
1288 index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
1292 // Since the property is a component of a base property, check whether the base property is regsitered.
1293 animatableProperty = FindAnimatableProperty( basePropertyIndex );
1294 if(!animatableProperty)
1296 // If the base property is not registered yet, register the base property first.
1297 if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(basePropertyIndex), basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
1299 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1303 // Create the metadata for the property component.
1304 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->type, animatableProperty->GetSceneGraphProperty() ) );
1307 // The metadata has just been added and therefore should be in the end of the vector.
1308 animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1312 return animatableProperty;
1315 } // namespace Internal