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