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