Dali 3D User Interface Engine
object-impl.cpp
Go to the documentation of this file.
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
20 
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 
24 // INTERNAL INCLUDES
34 
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
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 
58 : mEventThreadServices( *Stage::GetCurrent() ),
59  mTypeInfo( NULL ),
60  mConstraints( NULL ),
61  mPropertyNotifications( NULL )
62 {
63 }
64 
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 
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 
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
99 }
100 
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
111 }
112 
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.
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 ) )
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 {
195 
196  if(index == Property::INVALID_INDEX)
197  {
198  const TypeInfo* typeInfo( GetTypeInfo() );
199  if ( typeInfo )
200  {
201  index = typeInfo->GetPropertyIndex( name );
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  {
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 
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  }
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 
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  }
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 
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  }
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 
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 ) )
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->GetType();
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  }
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 
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  }
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 
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 
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
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::FLOAT:
541  {
542  newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
543  break;
544  }
545 
546  case Property::VECTOR2:
547  {
548  newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
549  break;
550  }
551 
552  case Property::VECTOR3:
553  {
554  newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
555  break;
556  }
557 
558  case Property::VECTOR4:
559  {
560  newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
561  break;
562  }
563 
564  case Property::MATRIX:
565  {
566  newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
567  break;
568  }
569 
570  case Property::MATRIX3:
571  {
572  newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
573  break;
574  }
575 
576  case Property::ROTATION:
577  {
578  newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
579  break;
580  }
581 
582  case Property::RECTANGLE:
583  case Property::STRING:
584  case Property::ARRAY:
585  case Property::MAP:
586  case Property::NONE:
587  {
588  DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
589  break;
590  }
591  }
592 
593  // get the scene property owner from derived class
594  const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
595  // we can only pass properties to scene graph side if there is a scene object
596  if( scenePropertyOwner )
597  {
598  // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
599  const PropertyBase* property = newProperty.Get();
600  if(index >= PROPERTY_CUSTOM_START_INDEX)
601  {
602  mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
603  }
604  else
605  {
606  mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
607  }
608 
609  // queue a message to add the property
610  InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
611 
612  // notify the derived class (optional) method in case it needs to do some more work on the new property
613  // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
614  NotifyScenePropertyInstalled( *property, name, index );
615 
616  return index;
617  }
618  else
619  {
620  // property was orphaned and killed so return invalid index
622  }
623 }
624 
625 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
626 {
627  return RegisterProperty( name, propertyValue, Property::ANIMATABLE );
628 }
629 
630 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
631 {
632  // If property with the required name already exists, then just set it.
633  Property::Index index = GetPropertyIndex( name );
634  if( index != Property::INVALID_INDEX )
635  {
636  SetProperty( index, propertyValue );
637  }
638  else
639  {
640  // Otherwise register the property
641 
642  if(Property::ANIMATABLE == accessMode)
643  {
645  AddUniformMapping( index, name );
646  }
647  else
648  {
649  // Add entry to the property lookup
651  mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
652  }
653  }
654 
655  return index;
656 }
657 
659  int componentIndex,
660  const Dali::PropertyCondition& condition)
661 {
662  if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
663  {
664  if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
665  {
666  DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
667  }
669  {
670  // check whether the animatable property is registered already, if not then register one.
672  DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
673  }
674  else if ( mCustomProperties.Count() > 0 )
675  {
676  CustomPropertyMetadata* custom = FindCustomProperty( index );
677  DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
678  DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
679  }
680  }
681 
682  Dali::Handle self(this);
683  Property target( self, index );
684 
685  PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
686  Dali::PropertyNotification propertyNotification(internal.Get());
687 
689  {
691  }
692  mPropertyNotifications->push_back(propertyNotification);
693 
694  return propertyNotification;
695 }
696 
698 {
700  {
702  while(iter != mPropertyNotifications->end() )
703  {
704  if(*iter == propertyNotification)
705  {
706  mPropertyNotifications->erase(iter);
707  // As we can't ensure all references are removed, we can just disable
708  // the notification.
709  GetImplementation(propertyNotification).Disable();
710  return;
711  }
712  ++iter;
713  }
714  }
715 }
716 
718 {
720  {
722  while(iter != mPropertyNotifications->end() )
723  {
724  // As we can't ensure all references are removed, we can just disable
725  // the notification.
726  GetImplementation(*iter).Disable();
727  ++iter;
728  }
729 
730  mPropertyNotifications->clear();
731  }
732 }
733 
735 {
737  {
740 
741  for( ; iter != endIter; ++iter )
742  {
743  GetImplementation(*iter).Enable();
744  }
745  }
746 }
747 
749 {
751  {
754 
755  for( ; iter != endIter; ++iter )
756  {
757  GetImplementation(*iter).Disable();
758  }
759  }
760 }
761 
762 void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName ) const
763 {
764  // Get the address of the property if it's a scene property
765  const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
766 
767  // Check instead for newly registered properties
768  if( propertyPtr == NULL )
769  {
770  PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
771  if( animatable != NULL )
772  {
773  propertyPtr = animatable->GetSceneGraphProperty();
774  }
775  }
776 
777  if( propertyPtr == NULL )
778  {
779  PropertyMetadata* custom = FindCustomProperty( propertyIndex );
780  if( custom != NULL )
781  {
782  propertyPtr = custom->GetSceneGraphProperty();
783  }
784  }
785 
786  if( propertyPtr != NULL )
787  {
788  const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
789 
790  if( sceneObject != NULL )
791  {
792  SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
793  // Message takes ownership of Uniform map (and will delete it after copy)
794  AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map);
795  }
796  else
797  {
798  DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
799  }
800  }
801 }
802 
803 void Object::RemoveUniformMapping( const std::string& uniformName )
804 {
805  const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
806  RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
807 }
808 
810 {
811  Property::Value value;
812 
813  DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
814 
815  if( !entry->IsAnimatable() )
816  {
817  value = entry->value;
818  }
819  else
820  {
821  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
822 
823  switch ( entry->GetType() )
824  {
825  case Property::BOOLEAN:
826  {
827  const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
828  DALI_ASSERT_DEBUG( NULL != property );
829 
830  value = (*property)[ bufferIndex ];
831  break;
832  }
833 
834  case Property::INTEGER:
835  {
836  const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
837  DALI_ASSERT_DEBUG( NULL != property );
838 
839  value = (*property)[ bufferIndex ];
840  break;
841  }
842 
843  case Property::FLOAT:
844  {
845  const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
846  DALI_ASSERT_DEBUG( NULL != property );
847 
848  value = (*property)[ bufferIndex ];
849  break;
850  }
851 
852  case Property::VECTOR2:
853  {
854  const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
855  DALI_ASSERT_DEBUG( NULL != property );
856 
857  if(entry->componentIndex == 0)
858  {
859  value = (*property)[ bufferIndex ].x;
860  }
861  else if(entry->componentIndex == 1)
862  {
863  value = (*property)[ bufferIndex ].y;
864  }
865  else
866  {
867  value = (*property)[ bufferIndex ];
868  }
869  break;
870  }
871 
872  case Property::VECTOR3:
873  {
874  const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
875  DALI_ASSERT_DEBUG( NULL != property );
876 
877  if(entry->componentIndex == 0)
878  {
879  value = (*property)[ bufferIndex ].x;
880  }
881  else if(entry->componentIndex == 1)
882  {
883  value = (*property)[ bufferIndex ].y;
884  }
885  else if(entry->componentIndex == 2)
886  {
887  value = (*property)[ bufferIndex ].z;
888  }
889  else
890  {
891  value = (*property)[ bufferIndex ];
892  }
893  break;
894  }
895 
896  case Property::VECTOR4:
897  {
898  const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
899  DALI_ASSERT_DEBUG( NULL != property );
900 
901  if(entry->componentIndex == 0)
902  {
903  value = (*property)[ bufferIndex ].x;
904  }
905  else if(entry->componentIndex == 1)
906  {
907  value = (*property)[ bufferIndex ].y;
908  }
909  else if(entry->componentIndex == 2)
910  {
911  value = (*property)[ bufferIndex ].z;
912  }
913  else if(entry->componentIndex == 3)
914  {
915  value = (*property)[ bufferIndex ].w;
916  }
917  else
918  {
919  value = (*property)[ bufferIndex ];
920  }
921  break;
922  }
923 
924  case Property::MATRIX:
925  {
926  const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
927  DALI_ASSERT_DEBUG( NULL != property );
928 
929  value = (*property)[ bufferIndex ];
930  break;
931  }
932 
933  case Property::MATRIX3:
934  {
935  const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
936  DALI_ASSERT_DEBUG( NULL != property );
937 
938  value = (*property)[ bufferIndex ];
939  break;
940  }
941 
942  case Property::ROTATION:
943  {
944  const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
945  DALI_ASSERT_DEBUG( NULL != property );
946 
947  value = (*property)[ bufferIndex ];
948  break;
949  }
950 
951  default:
952  {
953  DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
954  break;
955  }
956  } // switch(type)
957  } // if animatable
958 
959  return value;
960 }
961 
963 {
964  switch ( entry.GetType() )
965  {
966  case Property::BOOLEAN:
967  {
968  const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
969  DALI_ASSERT_DEBUG( NULL != property );
970 
971  // property is being used in a separate thread; queue a message to set the property
972  BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
973  break;
974  }
975 
976  case Property::INTEGER:
977  {
978  const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( 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<int>( GetEventThreadServices(), *property, value.Get<int>() );
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::VECTOR2:
997  {
998  const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( 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  if(entry.componentIndex == 0)
1003  {
1004  SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1005  }
1006  else if(entry.componentIndex == 1)
1007  {
1008  SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1009  }
1010  else
1011  {
1012  BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
1013  }
1014  break;
1015  }
1016 
1017  case Property::VECTOR3:
1018  {
1019  const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( 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  if(entry.componentIndex == 0)
1024  {
1025  SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1026  }
1027  else if(entry.componentIndex == 1)
1028  {
1029  SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1030  }
1031  else if(entry.componentIndex == 2)
1032  {
1033  SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1034  }
1035  else
1036  {
1037  BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1038  }
1039 
1040  break;
1041  }
1042 
1043  case Property::VECTOR4:
1044  {
1045  const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1046  DALI_ASSERT_DEBUG( NULL != property );
1047 
1048  // property is being used in a separate thread; queue a message to set the property
1049  if(entry.componentIndex == 0)
1050  {
1051  SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1052  }
1053  else if(entry.componentIndex == 1)
1054  {
1055  SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1056  }
1057  else if(entry.componentIndex == 2)
1058  {
1059  SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1060  }
1061  else if(entry.componentIndex == 3)
1062  {
1063  SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1064  }
1065  else
1066  {
1067  BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1068  }
1069  break;
1070  }
1071 
1072  case Property::ROTATION:
1073  {
1074  const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1075  DALI_ASSERT_DEBUG( NULL != property );
1076 
1077  // property is being used in a separate thread; queue a message to set the property
1078  BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1079  break;
1080  }
1081 
1082  case Property::MATRIX:
1083  {
1084  const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1085  DALI_ASSERT_DEBUG( NULL != property );
1086 
1087  // property is being used in a separate thread; queue a message to set the property
1088  BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1089  break;
1090  }
1091 
1092  case Property::MATRIX3:
1093  {
1094  const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1095  DALI_ASSERT_DEBUG( NULL != property );
1096 
1097  // property is being used in a separate thread; queue a message to set the property
1098  BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1099  break;
1100  }
1101 
1102  default:
1103  {
1104  // non-animatable scene graph property, do nothing
1105  }
1106  }
1107 }
1108 
1110 {
1111  if ( !mTypeInfo )
1112  {
1113  // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1114  // especially as the type-info does not change during the life-time of an application
1115 
1116  Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1117  if ( typeInfoHandle )
1118  {
1119  mTypeInfo = &GetImplementation( typeInfoHandle );
1120  }
1121  }
1122 
1123  return mTypeInfo;
1124 }
1125 
1127 {
1128  if( !mConstraints )
1129  {
1131  }
1132  mConstraints->push_back( Dali::Constraint( &constraint ) );
1133 }
1134 
1136 {
1137  // NULL if the Constraint sources are destroyed before Constraint::Apply()
1138  if( mConstraints )
1139  {
1140  ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
1141  if( it != mConstraints->end() )
1142  {
1143  mConstraints->erase( it );
1144  }
1145  }
1146 }
1147 
1149 {
1150  // guard against constraint sending messages during core destruction
1151  if( mConstraints && Stage::IsInstalled() )
1152  {
1153  // If we have nothing in the scene-graph, just clear constraint containers
1154  const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
1155  if ( NULL != propertyOwner )
1156  {
1157  const ConstraintConstIter endIter = mConstraints->end();
1158  for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
1159  {
1160  GetImplementation( *iter ).RemoveInternal();
1161  }
1162  }
1163 
1164  delete mConstraints;
1165  mConstraints = NULL;
1166  }
1167 }
1168 
1169 void Object::RemoveConstraints( unsigned int tag )
1170 {
1171  // guard against constraint sending messages during core destruction
1172  if( mConstraints && Stage::IsInstalled() )
1173  {
1174  ConstraintIter iter( mConstraints->begin() );
1175  while(iter != mConstraints->end() )
1176  {
1177  ConstraintBase& constraint = GetImplementation( *iter );
1178  if( constraint.GetTag() == tag )
1179  {
1180  GetImplementation( *iter ).RemoveInternal();
1181  iter = mConstraints->erase( iter );
1182  }
1183  else
1184  {
1185  ++iter;
1186  }
1187  }
1188 
1189  if ( mConstraints->empty() )
1190  {
1191  delete mConstraints;
1192  mConstraints = NULL;
1193  }
1194  }
1195 }
1196 
1197 void Object::SetTypeInfo( const TypeInfo* typeInfo )
1198 {
1199  mTypeInfo = typeInfo;
1200 }
1201 
1203 {
1204  // Notification for observers
1205  for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter)
1206  {
1207  (*iter)->ObjectDestroyed(*this);
1208  }
1209 
1210  delete mConstraints;
1211  delete mPropertyNotifications;
1212 }
1213 
1215 {
1216  CustomPropertyMetadata* property( NULL );
1217  int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1218  if( arrayIndex >= 0 )
1219  {
1220  if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
1221  {
1222  property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1223  }
1224  }
1225  return property;
1226 }
1227 
1229 {
1230  for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
1231  {
1232  AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
1233  if( property->index == index )
1234  {
1235  return property;
1236  }
1237  }
1238  return NULL;
1239 }
1240 
1242 {
1244  && "Property index is out of bounds" );
1245 
1246  // check whether the animatable property is registered already, if not then register one.
1247  AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1248  if(!animatableProperty)
1249  {
1250  const TypeInfo* typeInfo( GetTypeInfo() );
1251  if (typeInfo)
1252  {
1253  Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
1254  if(basePropertyIndex == Property::INVALID_INDEX)
1255  {
1256  // If the property is not a component of a base property, register the whole property itself.
1257  const std::string& propertyName = typeInfo->GetPropertyName(index);
1258  RegisterSceneGraphProperty(propertyName, index, typeInfo->GetPropertyDefaultValue(index));
1259  AddUniformMapping( index, propertyName );
1260  }
1261  else
1262  {
1263  // Since the property is a component of a base property, check whether the base property is regsitered.
1264  animatableProperty = FindAnimatableProperty( basePropertyIndex );
1265  if(!animatableProperty)
1266  {
1267  // If the base property is not registered yet, register the base property first.
1268  const std::string& basePropertyName = typeInfo->GetPropertyName(basePropertyIndex);
1269  if(Property::INVALID_INDEX != RegisterSceneGraphProperty(basePropertyName, basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
1270  {
1271  animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1272  AddUniformMapping( basePropertyIndex, basePropertyName );
1273  }
1274  }
1275 
1276  if(animatableProperty)
1277  {
1278  // Create the metadata for the property component.
1279  mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->GetType(), animatableProperty->GetSceneGraphProperty() ) );
1280  }
1281  }
1282 
1283  // The metadata has just been added and therefore should be in the end of the vector.
1284  animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1285  }
1286  }
1287 
1288  return animatableProperty;
1289 }
1290 
1291 } // namespace Internal
1292 
1293 } // namespace Dali
Dali Docs Home
Read more about Dali