2 * Copyright (c) 2014 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 return Property::INVALID_COMPONENT_INDEX;
115 bool Object::Supports( Capability capability ) const
117 return (capability & SUPPORTED_CAPABILITIES);
120 unsigned int Object::GetPropertyCount() const
122 unsigned int count = GetDefaultPropertyCount();
124 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
126 const TypeInfo* typeInfo( GetTypeInfo() );
129 unsigned int manual( typeInfo->GetPropertyCount() );
132 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties: %d\n", manual );
135 unsigned int custom( mCustomProperties.Count() );
137 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom );
139 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties: %d\n", count );
144 std::string Object::GetPropertyName( Property::Index index ) const
146 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
148 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
150 return GetDefaultPropertyName( index );
153 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
154 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
156 const TypeInfo* typeInfo( GetTypeInfo() );
159 return typeInfo->GetPropertyName( index );
163 DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
167 CustomPropertyMetadata* custom = FindCustomProperty( index );
175 Property::Index Object::GetPropertyIndex(const std::string& name) const
177 Property::Index index = GetDefaultPropertyIndex( name );
179 if(index == Property::INVALID_INDEX)
181 const TypeInfo* typeInfo( GetTypeInfo() );
184 index = typeInfo->GetPropertyIndex( name );
185 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
187 // check whether the animatable property is registered already, if not then register one.
188 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
189 if(!animatableProperty)
191 const TypeInfo* typeInfo( GetTypeInfo() );
194 index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
201 if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
203 Property::Index count = PROPERTY_CUSTOM_START_INDEX;
204 const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
205 for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
207 CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
208 if ( custom->name == name )
219 bool Object::IsPropertyWritable( Property::Index index ) const
221 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
223 bool writable = false;
225 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
227 writable = IsDefaultPropertyWritable( index );
229 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
231 const TypeInfo* typeInfo( GetTypeInfo() );
234 writable = typeInfo->IsPropertyWritable( index );
238 DALI_ASSERT_ALWAYS( ! "Invalid property index" );
241 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
243 // Type Registry scene-graph properties are writable.
248 CustomPropertyMetadata* custom = FindCustomProperty( index );
251 writable = custom->IsWritable();
258 bool Object::IsPropertyAnimatable( Property::Index index ) const
260 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
262 bool animatable = false;
264 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
266 animatable = IsDefaultPropertyAnimatable( index );
268 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
270 // Type Registry event-thread only properties are not animatable.
273 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
275 // Type Registry scene-graph properties are animatable.
280 CustomPropertyMetadata* custom = FindCustomProperty( index );
283 animatable = custom->IsAnimatable();
290 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
292 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
294 bool isConstraintInput = false;
296 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
298 isConstraintInput = IsDefaultPropertyAConstraintInput( index );
300 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
302 // Type Registry event-thread only properties cannot be used as an input to a constraint.
303 isConstraintInput = false;
305 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
307 // scene graph properties can be used as input to a constraint.
308 isConstraintInput = true;
312 CustomPropertyMetadata* custom = FindCustomProperty( index );
315 // ... custom properties can be used as input to a constraint.
316 isConstraintInput = true;
320 return isConstraintInput;
323 Property::Type Object::GetPropertyType( Property::Index index ) const
325 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
327 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
329 return GetDefaultPropertyType( index );
332 if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
333 || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
335 const TypeInfo* typeInfo( GetTypeInfo() );
338 return typeInfo->GetPropertyType( index );
342 DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
346 CustomPropertyMetadata* custom = FindCustomProperty( index );
351 return Property::NONE;
354 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
356 DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
358 bool propertySet( true );
360 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
362 SetDefaultProperty( index, propertyValue );
364 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
366 const TypeInfo* typeInfo( GetTypeInfo() );
367 typeInfo->SetProperty( this, index, propertyValue );
369 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
371 // check whether the animatable property is registered already, if not then register one.
372 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
373 if(!animatableProperty)
375 const TypeInfo* typeInfo( GetTypeInfo() );
376 if ( Property::INVALID_INDEX == RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, propertyValue ) )
378 DALI_LOG_ERROR("Cannot register property\n");
384 // set the scene graph property value
385 SetSceneGraphProperty( index, *animatableProperty, propertyValue );
390 CustomPropertyMetadata* custom = FindCustomProperty( index );
393 if( custom->IsAnimatable() )
395 // set the scene graph property value
396 SetSceneGraphProperty( index, *custom, propertyValue );
398 else if( custom->IsWritable() )
400 custom->value = propertyValue;
404 // trying to set value on read only property is no-op
410 DALI_LOG_ERROR("Invalid property index\n");
415 // Let derived classes know that a property has been set
416 // 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
419 OnPropertySet(index, propertyValue);
423 Property::Value Object::GetProperty(Property::Index index) const
425 DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
427 Property::Value value;
429 if ( index < DEFAULT_PROPERTY_MAX_COUNT )
431 value = GetDefaultProperty( index );
433 else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
435 const TypeInfo* typeInfo( GetTypeInfo() );
438 value = typeInfo->GetProperty( this, index );
442 DALI_LOG_ERROR("Cannot find property index\n");
445 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
447 // check whether the animatable property is registered already, if not then register one.
448 AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
449 if(!animatableProperty)
451 const TypeInfo* typeInfo( GetTypeInfo() );
454 if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index))))
456 value = Property::Value(typeInfo->GetPropertyType(index)); // Return an initialized property value according to the type
460 DALI_LOG_ERROR("Cannot register property\n");
465 DALI_LOG_ERROR("Cannot find property index\n");
470 // get the animatable property value
471 value = GetPropertyValue( animatableProperty );
474 else if(mCustomProperties.Count() > 0)
476 CustomPropertyMetadata* custom = FindCustomProperty( index );
479 // get the custom property value
480 value = GetPropertyValue( custom );
484 DALI_LOG_ERROR("Invalid property index\n");
491 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
495 // Default Properties
496 GetDefaultPropertyIndices( indices );
499 const TypeInfo* typeInfo( GetTypeInfo() );
502 typeInfo->GetPropertyIndices( indices );
506 if ( mCustomProperties.Count() > 0 )
508 indices.reserve( indices.size() + mCustomProperties.Count() );
510 PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
511 const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
513 for ( ; iter != endIter; ++iter, ++i )
515 indices.push_back( PROPERTY_CUSTOM_START_INDEX + i );
520 Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
522 // Create a new property
523 Dali::Internal::OwnerPointer<PropertyBase> newProperty;
525 switch ( propertyValue.GetType() )
527 case Property::BOOLEAN:
529 newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
533 case Property::INTEGER:
535 newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
539 case Property::UNSIGNED_INTEGER:
541 newProperty = new AnimatableProperty<unsigned int>( propertyValue.Get<unsigned int>() );
545 case Property::FLOAT:
547 newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
551 case Property::VECTOR2:
553 newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
557 case Property::VECTOR3:
559 newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
563 case Property::VECTOR4:
565 newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
569 case Property::MATRIX:
571 newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
575 case Property::MATRIX3:
577 newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
581 case Property::ROTATION:
583 newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
587 case Property::RECTANGLE:
588 case Property::STRING:
589 case Property::ARRAY:
592 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
593 DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
599 DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
600 DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" );
605 // get the scene property owner from derived class
606 const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
607 // we can only pass properties to scene graph side if there is a scene object
608 if( scenePropertyOwner )
610 // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
611 const PropertyBase* property = newProperty.Get();
612 if(index >= PROPERTY_CUSTOM_START_INDEX)
614 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
618 mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue.GetType(), property ) );
621 // queue a message to add the property
622 InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
624 // notify the derived class (optional) method in case it needs to do some more work on the new property
625 // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
626 NotifyScenePropertyInstalled( *property, name, index );
632 // property was orphaned and killed so return invalid index
633 return Property::INVALID_INDEX;
637 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
639 return RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
642 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
644 Property::Index index = Property::INVALID_INDEX;
646 if(Property::ANIMATABLE == accessMode)
648 index = RegisterProperty(name, propertyValue);
652 // Add entry to the property lookup
653 index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
654 mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
660 Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
662 const Dali::PropertyCondition& condition)
664 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
666 if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
668 DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
670 else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
672 // check whether the animatable property is registered already, if not then register one.
673 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
676 const TypeInfo* typeInfo( GetTypeInfo() );
679 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
681 animatable = FindAnimatableProperty( index );
685 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
687 else if ( mCustomProperties.Count() > 0 )
689 CustomPropertyMetadata* custom = FindCustomProperty( index );
690 DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
691 DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
695 Dali::Handle self(this);
696 Property target( self, index );
698 PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
699 Dali::PropertyNotification propertyNotification(internal.Get());
701 if( !mPropertyNotifications )
703 mPropertyNotifications = new PropertyNotificationContainer;
705 mPropertyNotifications->push_back(propertyNotification);
707 return propertyNotification;
710 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
712 if( mPropertyNotifications )
714 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
715 while(iter != mPropertyNotifications->end() )
717 if(*iter == propertyNotification)
719 mPropertyNotifications->erase(iter);
720 // As we can't ensure all references are removed, we can just disable
722 GetImplementation(propertyNotification).Disable();
730 void Object::RemovePropertyNotifications()
732 if( mPropertyNotifications )
734 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
735 while(iter != mPropertyNotifications->end() )
737 // As we can't ensure all references are removed, we can just disable
739 GetImplementation(*iter).Disable();
743 mPropertyNotifications->clear();
747 void Object::EnablePropertyNotifications()
749 if( mPropertyNotifications )
751 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
752 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
754 for( ; iter != endIter; ++iter )
756 GetImplementation(*iter).Enable();
761 void Object::DisablePropertyNotifications()
763 if( mPropertyNotifications )
765 PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
766 PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
768 for( ; iter != endIter; ++iter )
770 GetImplementation(*iter).Disable();
775 Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
777 Property::Value value;
779 DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
781 if( !entry->IsAnimatable() )
783 value = entry->value;
787 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
789 switch ( entry->type )
791 case Property::BOOLEAN:
793 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
794 DALI_ASSERT_DEBUG( NULL != property );
796 value = (*property)[ bufferIndex ];
800 case Property::INTEGER:
802 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
803 DALI_ASSERT_DEBUG( NULL != property );
805 value = (*property)[ bufferIndex ];
809 case Property::UNSIGNED_INTEGER:
811 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry->GetSceneGraphProperty() );
812 DALI_ASSERT_DEBUG( NULL != property );
814 value = (*property)[ bufferIndex ];
818 case Property::FLOAT:
820 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
821 DALI_ASSERT_DEBUG( NULL != property );
823 value = (*property)[ bufferIndex ];
827 case Property::VECTOR2:
829 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
830 DALI_ASSERT_DEBUG( NULL != property );
832 value = (*property)[ bufferIndex ];
836 case Property::VECTOR3:
838 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
839 DALI_ASSERT_DEBUG( NULL != property );
841 value = (*property)[ bufferIndex ];
845 case Property::VECTOR4:
847 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
848 DALI_ASSERT_DEBUG( NULL != property );
850 value = (*property)[ bufferIndex ];
854 case Property::MATRIX:
856 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
857 DALI_ASSERT_DEBUG( NULL != property );
859 value = (*property)[ bufferIndex ];
863 case Property::MATRIX3:
865 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
866 DALI_ASSERT_DEBUG( NULL != property );
868 value = (*property)[ bufferIndex ];
872 case Property::ROTATION:
874 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
875 DALI_ASSERT_DEBUG( NULL != property );
877 value = (*property)[ bufferIndex ];
883 DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
892 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
894 switch ( entry.type )
896 case Property::BOOLEAN:
898 const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
899 DALI_ASSERT_DEBUG( NULL != property );
901 // property is being used in a separate thread; queue a message to set the property
902 BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
906 case Property::INTEGER:
908 const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
909 DALI_ASSERT_DEBUG( NULL != property );
911 // property is being used in a separate thread; queue a message to set the property
912 BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
916 case Property::UNSIGNED_INTEGER:
918 const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry.GetSceneGraphProperty() );
919 DALI_ASSERT_DEBUG( NULL != property );
921 // property is being used in a separate thread; queue a message to set the property
922 BakeMessage<unsigned int>( GetEventThreadServices(), *property, value.Get<unsigned int>() );
926 case Property::FLOAT:
928 const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
929 DALI_ASSERT_DEBUG( NULL != property );
931 // property is being used in a separate thread; queue a message to set the property
932 BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
936 case Property::VECTOR2:
938 const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
939 DALI_ASSERT_DEBUG( NULL != property );
941 // property is being used in a separate thread; queue a message to set the property
942 BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
946 case Property::VECTOR3:
948 const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
949 DALI_ASSERT_DEBUG( NULL != property );
951 // property is being used in a separate thread; queue a message to set the property
952 BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
956 case Property::VECTOR4:
958 const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
959 DALI_ASSERT_DEBUG( NULL != property );
961 // property is being used in a separate thread; queue a message to set the property
962 BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
966 case Property::ROTATION:
968 const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
969 DALI_ASSERT_DEBUG( NULL != property );
971 // property is being used in a separate thread; queue a message to set the property
972 BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
976 case Property::MATRIX:
978 const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
979 DALI_ASSERT_DEBUG( NULL != property );
981 // property is being used in a separate thread; queue a message to set the property
982 BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
986 case Property::MATRIX3:
988 const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
989 DALI_ASSERT_DEBUG( NULL != property );
991 // property is being used in a separate thread; queue a message to set the property
992 BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
998 // non-animatable scene graph property, do nothing
1003 const TypeInfo* Object::GetTypeInfo() const
1007 // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1008 // especially as the type-info does not change during the life-time of an application
1010 Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1011 if ( typeInfoHandle )
1013 mTypeInfo = &GetImplementation( typeInfoHandle );
1020 void Object::ApplyConstraint( ConstraintBase& constraint )
1024 mConstraints = new ConstraintContainer;
1026 mConstraints->push_back( Dali::Constraint( &constraint ) );
1029 void Object::RemoveConstraint( ConstraintBase& constraint )
1031 // NULL if the Constraint sources are destroyed before Constraint::Apply()
1034 ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1035 if( it != mConstraints->end() )
1037 mConstraints->erase( it );
1042 void Object::RemoveConstraints()
1044 // guard against constraint sending messages during core destruction
1045 if( mConstraints && Stage::IsInstalled() )
1047 // If we have nothing in the scene-graph, just clear constraint containers
1048 const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1049 if ( NULL != propertyOwner )
1051 const ConstraintConstIter endIter = mConstraints->end();
1052 for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1054 GetImplementation( *iter ).RemoveInternal();
1058 delete mConstraints;
1059 mConstraints = NULL;
1063 void Object::RemoveConstraints( unsigned int tag )
1065 // guard against constraint sending messages during core destruction
1066 if( mConstraints && Stage::IsInstalled() )
1068 ConstraintIter iter( mConstraints->begin() );
1069 while(iter != mConstraints->end() )
1071 ConstraintBase& constraint = GetImplementation( *iter );
1072 if( constraint.GetTag() == tag )
1074 GetImplementation( *iter ).RemoveInternal();
1075 iter = mConstraints->erase( iter );
1083 if ( mConstraints->empty() )
1085 delete mConstraints;
1086 mConstraints = NULL;
1091 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1093 mTypeInfo = typeInfo;
1098 // Notification for observers
1099 for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
1101 (*iter)->ObjectDestroyed(*this);
1104 delete mConstraints;
1105 delete mPropertyNotifications;
1108 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1110 CustomPropertyMetadata* property( NULL );
1111 int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1112 if( arrayIndex >= 0 )
1114 if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1116 property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1122 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1124 for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1126 AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1127 if( property->index == index )
1135 } // namespace Internal