Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / internal / event / common / object-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/common/object-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
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>
34
35 using Dali::Internal::SceneGraph::AnimatableProperty;
36 using Dali::Internal::SceneGraph::PropertyBase;
37
38 namespace Dali
39 {
40
41 namespace Internal
42 {
43
44 namespace // unnamed namespace
45 {
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;
49
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
52 #endif
53 } // unnamed namespace
54
55 Object::Object()
56 : mEventThreadServices( *Stage::GetCurrent() ),
57   mTypeInfo( NULL ),
58   mConstraints( NULL ),
59   mPropertyNotifications( NULL )
60 {
61 }
62
63 void Object::AddObserver(Observer& observer)
64 {
65   // make sure an observer doesn't observe the same object twice
66   // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
67   DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
68
69   mObservers.PushBack( &observer );
70 }
71
72 void Object::RemoveObserver(Observer& observer)
73 {
74   // Find the observer...
75   const ConstObserverIter endIter =  mObservers.End();
76   for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
77   {
78     if( (*iter) == &observer)
79     {
80       mObservers.Erase( iter );
81       break;
82     }
83   }
84   DALI_ASSERT_DEBUG(endIter != mObservers.End());
85 }
86
87 void Object::OnSceneObjectAdd()
88 {
89   // Notification for observers
90   for( ConstObserverIter iter = mObservers.Begin(),  endIter =  mObservers.End(); iter != endIter; ++iter)
91   {
92     (*iter)->SceneObjectAdded(*this);
93   }
94
95   // enable property notifications in scene graph
96   EnablePropertyNotifications();
97 }
98
99 void Object::OnSceneObjectRemove()
100 {
101   // Notification for observers
102   for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
103   {
104     (*iter)->SceneObjectRemoved(*this);
105   }
106
107   // disable property notifications in scene graph
108   DisablePropertyNotifications();
109 }
110
111 int Object::GetPropertyComponentIndex( Property::Index index ) const
112 {
113   return Property::INVALID_COMPONENT_INDEX;
114 }
115
116 bool Object::Supports( Capability capability ) const
117 {
118   return (capability & SUPPORTED_CAPABILITIES);
119 }
120
121 unsigned int Object::GetPropertyCount() const
122 {
123   unsigned int count = GetDefaultPropertyCount();
124
125   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
126
127   const TypeInfo* typeInfo( GetTypeInfo() );
128   if ( typeInfo )
129   {
130     unsigned int manual( typeInfo->GetPropertyCount() );
131     count += manual;
132
133     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties:  %d\n", manual );
134   }
135
136   unsigned int custom( mCustomProperties.Count() );
137   count += custom;
138   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
139
140   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties:   %d\n", count );
141
142   return count;
143 }
144
145 std::string Object::GetPropertyName( Property::Index index ) const
146 {
147   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
148
149   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
150   {
151     return GetDefaultPropertyName( index );
152   }
153
154   if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
155     || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
156   {
157     const TypeInfo* typeInfo( GetTypeInfo() );
158     if ( typeInfo )
159     {
160       return typeInfo->GetPropertyName( index );
161     }
162     else
163     {
164       DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
165     }
166   }
167
168   CustomPropertyMetadata* custom = FindCustomProperty( index );
169   if( custom )
170   {
171     return custom->name;
172   }
173   return "";
174 }
175
176 Property::Index Object::GetPropertyIndex(const std::string& name) const
177 {
178   Property::Index index = GetDefaultPropertyIndex( name );
179
180   if(index == Property::INVALID_INDEX)
181   {
182     const TypeInfo* typeInfo( GetTypeInfo() );
183     if ( typeInfo )
184     {
185       index = typeInfo->GetPropertyIndex( name );
186       if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
187       {
188         // check whether the animatable property is registered already, if not then register one.
189         AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
190         if(!animatableProperty)
191         {
192           const TypeInfo* typeInfo( GetTypeInfo() );
193           if (typeInfo)
194           {
195             index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
196           }
197         }
198       }
199     }
200   }
201
202   if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
203   {
204     Property::Index count = PROPERTY_CUSTOM_START_INDEX;
205     const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
206     for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
207     {
208       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
209       if ( custom->name == name )
210       {
211         index = count;
212         break;
213       }
214     }
215   }
216
217   return index;
218 }
219
220 bool Object::IsPropertyWritable( Property::Index index ) const
221 {
222   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
223
224   bool writable = false;
225
226   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
227   {
228     writable = IsDefaultPropertyWritable( index );
229   }
230   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
231   {
232     const TypeInfo* typeInfo( GetTypeInfo() );
233     if ( typeInfo )
234     {
235       writable = typeInfo->IsPropertyWritable( index );
236     }
237     else
238     {
239       DALI_ASSERT_ALWAYS( ! "Invalid property index" );
240     }
241   }
242   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
243   {
244     // Type Registry scene-graph properties are writable.
245     writable = true;
246   }
247   else
248   {
249     CustomPropertyMetadata* custom = FindCustomProperty( index );
250     if( custom )
251     {
252       writable = custom->IsWritable();
253     }
254   }
255
256   return writable;
257 }
258
259 bool Object::IsPropertyAnimatable( Property::Index index ) const
260 {
261   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
262
263   bool animatable = false;
264
265   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
266   {
267     animatable = IsDefaultPropertyAnimatable( index );
268   }
269   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
270   {
271     // Type Registry event-thread only properties are not animatable.
272     animatable = false;
273   }
274   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
275   {
276     // Type Registry scene-graph properties are animatable.
277     animatable = true;
278   }
279   else
280   {
281     CustomPropertyMetadata* custom = FindCustomProperty( index );
282     if( custom )
283     {
284       animatable = custom->IsAnimatable();
285     }
286   }
287
288   return animatable;
289 }
290
291 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
292 {
293   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
294
295   bool isConstraintInput = false;
296
297   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
298   {
299     isConstraintInput = IsDefaultPropertyAConstraintInput( index );
300   }
301   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
302   {
303     // Type Registry event-thread only properties cannot be used as an input to a constraint.
304     isConstraintInput = false;
305   }
306   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
307   {
308     // scene graph properties can be used as input to a constraint.
309     isConstraintInput = true;
310   }
311   else
312   {
313     CustomPropertyMetadata* custom = FindCustomProperty( index );
314     if( custom )
315     {
316       // ... custom properties can be used as input to a constraint.
317       isConstraintInput = true;
318     }
319   }
320
321   return isConstraintInput;
322 }
323
324 Property::Type Object::GetPropertyType( Property::Index index ) const
325 {
326   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
327
328   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
329   {
330     return GetDefaultPropertyType( index );
331   }
332
333   if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
334     || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
335   {
336     const TypeInfo* typeInfo( GetTypeInfo() );
337     if ( typeInfo )
338     {
339       return typeInfo->GetPropertyType( index );
340     }
341     else
342     {
343       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
344     }
345   }
346
347   CustomPropertyMetadata* custom = FindCustomProperty( index );
348   if( custom )
349   {
350     return custom->type;
351   }
352   return Property::NONE;
353 }
354
355 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
356 {
357   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
358
359   bool propertySet( true );
360
361   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
362   {
363     SetDefaultProperty( index, propertyValue );
364   }
365   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
366   {
367     const TypeInfo* typeInfo( GetTypeInfo() );
368     typeInfo->SetProperty( this, index, propertyValue );
369   }
370   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
371   {
372     // check whether the animatable property is registered already, if not then register one.
373     AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
374     if(!animatableProperty)
375     {
376       const TypeInfo* typeInfo( GetTypeInfo() );
377       if ( Property::INVALID_INDEX == RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, propertyValue ) )
378       {
379         DALI_LOG_ERROR("Cannot register property\n");
380         propertySet = false;
381       }
382     }
383     else
384     {
385       // set the scene graph property value
386       SetSceneGraphProperty( index, *animatableProperty, propertyValue );
387     }
388   }
389   else
390   {
391     CustomPropertyMetadata* custom = FindCustomProperty( index );
392     if( custom )
393     {
394       if( custom->IsAnimatable() )
395       {
396         // set the scene graph property value
397         SetSceneGraphProperty( index, *custom, propertyValue );
398       }
399       else if( custom->IsWritable() )
400       {
401         custom->value = propertyValue;
402       }
403       else
404       {
405         // trying to set value on read only property is no-op
406         propertySet = false;
407       }
408     }
409     else
410     {
411       DALI_LOG_ERROR("Invalid property index\n");
412       propertySet = false;
413     }
414   }
415
416   // Let derived classes know that a property has been set
417   // 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
418   if ( propertySet )
419   {
420     OnPropertySet(index, propertyValue);
421   }
422 }
423
424 Property::Value Object::GetProperty(Property::Index index) const
425 {
426   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
427
428   Property::Value value;
429
430   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
431   {
432     value = GetDefaultProperty( index );
433   }
434   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
435   {
436     const TypeInfo* typeInfo( GetTypeInfo() );
437     if ( typeInfo )
438     {
439       value = typeInfo->GetProperty( this, index );
440     }
441     else
442     {
443       DALI_LOG_ERROR("Cannot find property index\n");
444     }
445   }
446   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
447   {
448     // check whether the animatable property is registered already, if not then register one.
449     AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
450     if(!animatableProperty)
451     {
452       const TypeInfo* typeInfo( GetTypeInfo() );
453       if (typeInfo)
454       {
455         if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index))))
456         {
457           value = Property::Value(typeInfo->GetPropertyType(index)); // Return an initialized property value according to the type
458         }
459         else
460         {
461           DALI_LOG_ERROR("Cannot register property\n");
462         }
463       }
464       else
465       {
466         DALI_LOG_ERROR("Cannot find property index\n");
467       }
468     }
469     else
470     {
471       // get the animatable property value
472       value = GetPropertyValue( animatableProperty );
473     }
474   }
475   else if(mCustomProperties.Count() > 0)
476   {
477     CustomPropertyMetadata* custom = FindCustomProperty( index );
478     if(custom)
479     {
480       // get the custom property value
481       value = GetPropertyValue( custom );
482     }
483     else
484     {
485       DALI_LOG_ERROR("Invalid property index\n");
486     }
487   } // if custom
488
489   return value;
490 }
491
492 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
493 {
494   indices.clear();
495
496   // Default Properties
497   GetDefaultPropertyIndices( indices );
498
499   // Manual Properties
500   const TypeInfo* typeInfo( GetTypeInfo() );
501   if ( typeInfo )
502   {
503     typeInfo->GetPropertyIndices( indices );
504   }
505
506   // Custom Properties
507   if ( mCustomProperties.Count() > 0 )
508   {
509     indices.reserve( indices.size() + mCustomProperties.Count() );
510
511     PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
512     const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
513     int i=0;
514     for ( ; iter != endIter; ++iter, ++i )
515     {
516       indices.push_back( PROPERTY_CUSTOM_START_INDEX + i );
517     }
518   }
519 }
520
521 Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
522 {
523   // Create a new property
524   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
525
526   switch ( propertyValue.GetType() )
527   {
528     case Property::BOOLEAN:
529     {
530       newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
531       break;
532     }
533
534     case Property::INTEGER:
535     {
536       newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
537       break;
538     }
539
540     case Property::UNSIGNED_INTEGER:
541     {
542       newProperty = new AnimatableProperty<unsigned int>( propertyValue.Get<unsigned int>() );
543       break;
544     }
545
546     case Property::FLOAT:
547     {
548       newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
549       break;
550     }
551
552     case Property::VECTOR2:
553     {
554       newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
555       break;
556     }
557
558     case Property::VECTOR3:
559     {
560       newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
561       break;
562     }
563
564     case Property::VECTOR4:
565     {
566       newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
567       break;
568     }
569
570     case Property::MATRIX:
571     {
572       newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
573       break;
574     }
575
576     case Property::MATRIX3:
577     {
578       newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
579       break;
580     }
581
582     case Property::ROTATION:
583     {
584       newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
585       break;
586     }
587
588     case Property::RECTANGLE:
589     case Property::STRING:
590     case Property::ARRAY:
591     case Property::MAP:
592     {
593       DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
594       DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
595       break;
596     }
597
598     default:
599     {
600       DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
601       DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" );
602       break;
603     }
604   }
605
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 )
610   {
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)
614     {
615       mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
616     }
617     else
618     {
619       mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue.GetType(), property ) );
620     }
621
622     // queue a message to add the property
623     InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
624
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 );
628
629     return index;
630   }
631   else
632   {
633     // property was orphaned and killed so return invalid index
634     return Property::INVALID_INDEX;
635   }
636 }
637
638 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
639 {
640   return RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
641 }
642
643 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
644 {
645   Property::Index index = Property::INVALID_INDEX;
646
647   if(Property::ANIMATABLE == accessMode)
648   {
649     index = RegisterProperty(name, propertyValue);
650   }
651   else
652   {
653     // Add entry to the property lookup
654     index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
655     mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
656   }
657
658   return index;
659 }
660
661 Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
662                                                                 int componentIndex,
663                                                                 const Dali::PropertyCondition& condition)
664 {
665   if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
666   {
667     if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
668     {
669       DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
670     }
671     else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
672     {
673       // check whether the animatable property is registered already, if not then register one.
674       AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
675       if( !animatable )
676       {
677         const TypeInfo* typeInfo( GetTypeInfo() );
678         if ( typeInfo )
679         {
680           if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
681           {
682             animatable = FindAnimatableProperty( index );
683           }
684         }
685       }
686       DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
687     }
688     else if ( mCustomProperties.Count() > 0 )
689     {
690       CustomPropertyMetadata* custom = FindCustomProperty( index );
691       DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
692       DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
693     }
694   }
695
696   Dali::Handle self(this);
697   Property target( self, index );
698
699   PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
700   Dali::PropertyNotification propertyNotification(internal.Get());
701
702   if( !mPropertyNotifications )
703   {
704     mPropertyNotifications = new PropertyNotificationContainer;
705   }
706   mPropertyNotifications->push_back(propertyNotification);
707
708   return propertyNotification;
709 }
710
711 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
712 {
713   if( mPropertyNotifications )
714   {
715     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
716     while(iter != mPropertyNotifications->end() )
717     {
718       if(*iter == propertyNotification)
719       {
720         mPropertyNotifications->erase(iter);
721         // As we can't ensure all references are removed, we can just disable
722         // the notification.
723         GetImplementation(propertyNotification).Disable();
724         return;
725       }
726       ++iter;
727     }
728   }
729 }
730
731 void Object::RemovePropertyNotifications()
732 {
733   if( mPropertyNotifications )
734   {
735     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
736     while(iter != mPropertyNotifications->end() )
737     {
738       // As we can't ensure all references are removed, we can just disable
739       // the notification.
740       GetImplementation(*iter).Disable();
741       ++iter;
742     }
743
744     mPropertyNotifications->clear();
745   }
746 }
747
748 void Object::EnablePropertyNotifications()
749 {
750   if( mPropertyNotifications )
751   {
752     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
753     PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
754
755     for( ; iter != endIter; ++iter )
756     {
757       GetImplementation(*iter).Enable();
758     }
759   }
760 }
761
762 void Object::DisablePropertyNotifications()
763 {
764   if( mPropertyNotifications )
765   {
766     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
767     PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
768
769     for( ; iter != endIter; ++iter )
770     {
771       GetImplementation(*iter).Disable();
772     }
773   }
774 }
775
776 void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName )
777 {
778   // Get the address of the property if it's a scene property
779   const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
780
781   // Check instead for newly registered properties
782   if( propertyPtr == NULL )
783   {
784     PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
785     if( animatable != NULL )
786     {
787       propertyPtr = animatable->GetSceneGraphProperty();
788     }
789   }
790
791   if( propertyPtr == NULL )
792   {
793     PropertyMetadata* custom = FindCustomProperty( propertyIndex );
794     if( custom != NULL )
795     {
796       propertyPtr = custom->GetSceneGraphProperty();
797     }
798   }
799
800   // @todo MESH_REWORK Store mappings for unstaged objects?
801
802   if( propertyPtr != NULL )
803   {
804     const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
805
806     if( sceneObject != NULL )
807     {
808       SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
809       // Message takes ownership of Uniform map (and will delete it after copy)
810       AddUniformMapMessage( GetEventThreadServices(), *sceneObject, map);
811     }
812     else
813     {
814       // @todo MESH_REWORK FIXME Need to store something that can be sent to the scene
815       // object when staged.
816       DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
817     }
818   }
819 }
820
821 void Object::RemoveUniformMapping( const std::string& uniformName )
822 {
823   const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
824   RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
825 }
826
827 Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
828 {
829   Property::Value value;
830
831   DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
832
833   if( !entry->IsAnimatable() )
834   {
835     value = entry->value;
836   }
837   else
838   {
839     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
840
841     switch ( entry->type )
842     {
843       case Property::BOOLEAN:
844       {
845         const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
846         DALI_ASSERT_DEBUG( NULL != property );
847
848         value = (*property)[ bufferIndex ];
849         break;
850       }
851
852       case Property::INTEGER:
853       {
854         const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
855         DALI_ASSERT_DEBUG( NULL != property );
856
857         value = (*property)[ bufferIndex ];
858         break;
859       }
860
861       case Property::UNSIGNED_INTEGER:
862       {
863         const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry->GetSceneGraphProperty() );
864         DALI_ASSERT_DEBUG( NULL != property );
865
866         value = (*property)[ bufferIndex ];
867         break;
868       }
869
870       case Property::FLOAT:
871       {
872         const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
873         DALI_ASSERT_DEBUG( NULL != property );
874
875         value = (*property)[ bufferIndex ];
876         break;
877       }
878
879       case Property::VECTOR2:
880       {
881         const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
882         DALI_ASSERT_DEBUG( NULL != property );
883
884         value = (*property)[ bufferIndex ];
885         break;
886       }
887
888       case Property::VECTOR3:
889       {
890         const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
891         DALI_ASSERT_DEBUG( NULL != property );
892
893         value = (*property)[ bufferIndex ];
894         break;
895       }
896
897       case Property::VECTOR4:
898       {
899         const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
900         DALI_ASSERT_DEBUG( NULL != property );
901
902         value = (*property)[ bufferIndex ];
903         break;
904       }
905
906       case Property::MATRIX:
907       {
908         const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
909         DALI_ASSERT_DEBUG( NULL != property );
910
911         value = (*property)[ bufferIndex ];
912         break;
913       }
914
915       case Property::MATRIX3:
916       {
917         const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
918         DALI_ASSERT_DEBUG( NULL != property );
919
920         value = (*property)[ bufferIndex ];
921         break;
922       }
923
924       case Property::ROTATION:
925       {
926         const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
927         DALI_ASSERT_DEBUG( NULL != property );
928
929         value = (*property)[ bufferIndex ];
930         break;
931       }
932
933       default:
934       {
935         DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
936         break;
937       }
938     } // switch(type)
939   } // if animatable
940
941   return value;
942 }
943
944 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
945 {
946   switch ( entry.type )
947   {
948     case Property::BOOLEAN:
949     {
950       const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
951       DALI_ASSERT_DEBUG( NULL != property );
952
953       // property is being used in a separate thread; queue a message to set the property
954       BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
955       break;
956     }
957
958     case Property::INTEGER:
959     {
960       const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
961       DALI_ASSERT_DEBUG( NULL != property );
962
963       // property is being used in a separate thread; queue a message to set the property
964       BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
965       break;
966     }
967
968     case Property::UNSIGNED_INTEGER:
969     {
970       const AnimatableProperty<unsigned int>* property = dynamic_cast< const AnimatableProperty<unsigned int>* >( entry.GetSceneGraphProperty() );
971       DALI_ASSERT_DEBUG( NULL != property );
972
973       // property is being used in a separate thread; queue a message to set the property
974       BakeMessage<unsigned int>( GetEventThreadServices(), *property, value.Get<unsigned int>() );
975       break;
976     }
977
978     case Property::FLOAT:
979     {
980       const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
981       DALI_ASSERT_DEBUG( NULL != property );
982
983       // property is being used in a separate thread; queue a message to set the property
984       BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
985       break;
986     }
987
988     case Property::VECTOR2:
989     {
990       const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
991       DALI_ASSERT_DEBUG( NULL != property );
992
993       // property is being used in a separate thread; queue a message to set the property
994       BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
995       break;
996     }
997
998     case Property::VECTOR3:
999     {
1000       const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1001       DALI_ASSERT_DEBUG( NULL != property );
1002
1003       // property is being used in a separate thread; queue a message to set the property
1004       BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1005       break;
1006     }
1007
1008     case Property::VECTOR4:
1009     {
1010       const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1011       DALI_ASSERT_DEBUG( NULL != property );
1012
1013       // property is being used in a separate thread; queue a message to set the property
1014       BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1015       break;
1016     }
1017
1018     case Property::ROTATION:
1019     {
1020       const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1021       DALI_ASSERT_DEBUG( NULL != property );
1022
1023       // property is being used in a separate thread; queue a message to set the property
1024       BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1025       break;
1026     }
1027
1028     case Property::MATRIX:
1029     {
1030       const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1031       DALI_ASSERT_DEBUG( NULL != property );
1032
1033       // property is being used in a separate thread; queue a message to set the property
1034       BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1035       break;
1036     }
1037
1038     case Property::MATRIX3:
1039     {
1040       const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1041       DALI_ASSERT_DEBUG( NULL != property );
1042
1043       // property is being used in a separate thread; queue a message to set the property
1044       BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1045       break;
1046     }
1047
1048     default:
1049     {
1050       // non-animatable scene graph property, do nothing
1051     }
1052   }
1053 }
1054
1055 const TypeInfo* Object::GetTypeInfo() const
1056 {
1057   if ( !mTypeInfo )
1058   {
1059     // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1060     // especially as the type-info does not change during the life-time of an application
1061
1062     Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1063     if ( typeInfoHandle )
1064     {
1065       mTypeInfo = &GetImplementation( typeInfoHandle );
1066     }
1067   }
1068
1069   return mTypeInfo;
1070 }
1071
1072 void Object::ApplyConstraint( ConstraintBase& constraint )
1073 {
1074   if( !mConstraints )
1075   {
1076     mConstraints = new ConstraintContainer;
1077   }
1078   mConstraints->push_back( Dali::Constraint( &constraint ) );
1079 }
1080
1081 void Object::RemoveConstraint( ConstraintBase& constraint )
1082 {
1083   // NULL if the Constraint sources are destroyed before Constraint::Apply()
1084   if( mConstraints )
1085   {
1086     ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1087     if( it != mConstraints->end() )
1088     {
1089       mConstraints->erase( it );
1090     }
1091   }
1092 }
1093
1094 void Object::RemoveConstraints()
1095 {
1096   // guard against constraint sending messages during core destruction
1097   if( mConstraints && Stage::IsInstalled() )
1098   {
1099     // If we have nothing in the scene-graph, just clear constraint containers
1100     const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1101     if ( NULL != propertyOwner )
1102     {
1103       const ConstraintConstIter endIter = mConstraints->end();
1104       for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1105       {
1106         GetImplementation( *iter ).RemoveInternal();
1107       }
1108     }
1109
1110     delete mConstraints;
1111     mConstraints = NULL;
1112   }
1113 }
1114
1115 void Object::RemoveConstraints( unsigned int tag )
1116 {
1117   // guard against constraint sending messages during core destruction
1118   if( mConstraints && Stage::IsInstalled() )
1119   {
1120     ConstraintIter iter( mConstraints->begin() );
1121     while(iter != mConstraints->end() )
1122     {
1123       ConstraintBase& constraint = GetImplementation( *iter );
1124       if( constraint.GetTag() == tag )
1125       {
1126         GetImplementation( *iter ).RemoveInternal();
1127         iter = mConstraints->erase( iter );
1128       }
1129       else
1130       {
1131         ++iter;
1132       }
1133     }
1134
1135     if ( mConstraints->empty() )
1136     {
1137       delete mConstraints;
1138       mConstraints = NULL;
1139     }
1140   }
1141 }
1142
1143 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1144 {
1145   mTypeInfo = typeInfo;
1146 }
1147
1148 Object::~Object()
1149 {
1150   // Notification for observers
1151   for( ConstObserverIter iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
1152   {
1153     (*iter)->ObjectDestroyed(*this);
1154   }
1155
1156   delete mConstraints;
1157   delete mPropertyNotifications;
1158 }
1159
1160 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1161 {
1162   CustomPropertyMetadata* property( NULL );
1163   int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1164   if( arrayIndex >= 0 )
1165   {
1166     if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1167     {
1168       property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1169     }
1170   }
1171   return property;
1172 }
1173
1174 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1175 {
1176   for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1177   {
1178     AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1179     if( property->index == index )
1180     {
1181       return property;
1182     }
1183   }
1184   return NULL;
1185 }
1186
1187 } // namespace Internal
1188
1189 } // namespace Dali