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