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