Allow registering property components for animatable properties
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-impl.h
1 #ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
2 #define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/common/message.h>
23 #include <dali/internal/event/common/event-thread-services.h>
24 #include <dali/internal/event/common/object-impl.h>
25 #include <dali/internal/event/common/thread-local-storage.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/event/animation/constraint-base.h>
28 #include <dali/internal/event/animation/constraint-source-impl.h>
29 #include <dali/internal/event/animation/property-constraint-ptr.h>
30 #include <dali/internal/update/common/animatable-property.h>
31 #include <dali/internal/update/common/property-owner.h>
32 #include <dali/internal/update/common/property-owner-messages.h>
33 #include <dali/internal/update/animation/scene-graph-constraint.h>
34 #include <dali/internal/update/animation/property-accessor.h>
35 #include <dali/internal/update/animation/property-component-accessor.h>
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 /**
44  * Helper to add only unique entries to the propertyOwner container
45  * @param propertyOwners to add the entries to
46  * @param object to add
47  */
48 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
49 {
50   const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
51   if( iter == propertyOwners.End() )
52   {
53     // each owner should only be added once
54     propertyOwners.PushBack( object );
55   }
56 }
57
58 /**
59  * Connects a constraint which takes another property as an input.
60  */
61 template < typename PropertyType >
62 class Constraint : public ConstraintBase
63 {
64 public:
65
66   typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
67   typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
68   typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
69
70   /**
71    * Construct a new constraint.
72    * @param[in] object The property-owning object.
73    * @param[in] targetIndex The index of the property to constrain.
74    * @param[in] sources The sources of the input properties passed to func.
75    * @param[in] func The constraint function.
76    * @return A newly allocated active-constraint.
77    */
78   static ConstraintBase* New( Object& object,
79                               Property::Index targetIndex,
80                               SourceContainer& sources,
81                               ConstraintFunctionPtr func )
82   {
83     return new Constraint< PropertyType >( object, targetIndex, sources, func );
84   }
85
86   /**
87    * @copydoc ConstraintBase::Clone()
88    */
89   virtual ConstraintBase* Clone( Object& object )
90   {
91     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
92
93     ConstraintBase* clone( NULL );
94
95     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
96
97     clone = new Constraint< PropertyType >( object,
98                                             mTargetIndex,
99                                             mSources,
100                                             funcPtr );
101
102     clone->SetRemoveAction(mRemoveAction);
103     clone->SetTag( mTag );
104
105     return clone;
106   }
107
108
109   /**
110    * Virtual destructor.
111    */
112   virtual ~Constraint()
113   {
114     // This is not responsible for removing constraints.
115   }
116
117 private:
118
119   /**
120    * Private constructor; see also Constraint::New().
121    */
122   Constraint( Object& object,
123               Property::Index targetIndex,
124               SourceContainer& sources,
125               ConstraintFunctionPtr& func )
126   : ConstraintBase( object, targetIndex, sources ),
127     mTargetIndex( targetIndex ),
128     mUserFunction( func )
129   {
130   }
131
132   // Undefined
133   Constraint( const Constraint& );
134
135   // Undefined
136   Constraint& operator=( const Constraint& rhs );
137
138   /**
139    * Create and connect a constraint for a scene-object.
140    */
141   void ConnectConstraint()
142   {
143     // Should not come here if target-object has been destroyed
144     DALI_ASSERT_DEBUG( NULL != mTargetObject );
145
146     // Guard against double connections
147     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
148
149     // Short-circuit until the target scene-object exists
150     SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
151     if ( NULL == targetObject )
152     {
153       return;
154     }
155
156     // Build a container of property-owners, providing the scene-graph properties
157     SceneGraph::PropertyOwnerContainer propertyOwners;
158     propertyOwners.PushBack( targetObject );
159
160     // Build the constraint function; this requires a scene-graph property from each source
161     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
162
163     if ( func )
164     {
165       // Create the SceneGraphConstraint, and connect to the scene-graph
166
167       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
168
169       // The targetProperty should exist, when targetObject exists
170       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
171
172       // Connect the constraint
173       SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
174                                                                                      propertyOwners,
175                                                                                      func );
176       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
177       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
178
179       // object is being used in a separate thread; queue a message to apply the constraint
180       ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
181
182       // Keep a raw-pointer to the scene-graph constraint
183       mSceneGraphConstraint = sceneGraphConstraint;
184     }
185   }
186
187   /**
188    * Helper for ConnectConstraint. Creates a connected constraint-function.
189    * Also populates the property-owner container, for each input connected to the constraint-function.
190    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
191    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
192    */
193   PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
194   {
195     PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
196
197     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
198     {
199       Source& source = *iter;
200
201       PropertyInputImpl* inputProperty( NULL );
202       int componentIndex( Property::INVALID_COMPONENT_INDEX );
203
204       if ( OBJECT_PROPERTY == source.sourceType )
205       {
206         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
207
208         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
209
210         // The property owner will not exist, if the target object is off-stage
211         if( NULL != owner )
212         {
213           AddUnique( propertyOwners, owner );
214           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
215           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
216
217           // The scene-object property should exist, when the property owner exists
218           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
219         }
220       }
221       else if ( LOCAL_PROPERTY == source.sourceType )
222       {
223         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
224
225         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
226         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
227
228         // The target scene-object should provide this property
229         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
230       }
231       else
232       {
233         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
234
235         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
236
237         // This will not exist, if the target object is off-stage
238         if ( NULL != objectParent )
239         {
240           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
241
242           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
243
244           // The property owner will not exist, if the parent object is off-stage
245           if ( NULL != owner )
246           {
247             AddUnique( propertyOwners, owner );
248             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
249             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
250
251             // The scene-object property should exist, when the property owner exists
252             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
253           }
254         }
255       }
256
257       if ( NULL == inputProperty )
258       {
259         delete func;
260         func = NULL;
261
262         // Exit if a scene-graph object is not available from one of the sources
263         break;
264       }
265
266       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
267     }
268
269     return func;
270   }
271
272 protected:
273
274   Property::Index mTargetIndex;
275
276   ConstraintFunctionPtr mUserFunction;
277 };
278
279 /**
280  * Variant which allows float components to be animated individually.
281  */
282 template <>
283 class Constraint<float> : public ConstraintBase
284 {
285 public:
286
287   typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
288
289   /**
290    * Construct a new constraint.
291    * @param[in] object The property-owning object.
292    * @param[in] targetIndex The index of the property to constrain.
293    * @param[in] sources The sources of the input properties passed to func.
294    * @param[in] func The constraint function.
295    * @return A newly allocated constraint.
296    */
297   static ConstraintBase* New( Object& object,
298                               Property::Index targetIndex,
299                               SourceContainer& sources,
300                               ConstraintFunctionPtr func )
301   {
302     return new Constraint< float >( object, targetIndex, sources, func );
303   }
304
305   /**
306    * @copydoc ConstraintBase::Clone()
307    */
308   virtual ConstraintBase* Clone( Object& object )
309   {
310     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
311
312     ConstraintBase* clone( NULL );
313
314     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
315
316     clone = new Constraint< float >( object,
317                                      mTargetIndex,
318                                      mSources,
319                                      funcPtr );
320
321     clone->SetRemoveAction(mRemoveAction);
322     clone->SetTag( mTag );
323
324     return clone;
325   }
326
327   /**
328    * Virtual destructor.
329    */
330   virtual ~Constraint()
331   {
332     // This is not responsible for removing constraints.
333   }
334
335 private:
336
337   /**
338    * Private constructor; see also Constraint::New().
339    */
340   Constraint( Object& object,
341               Property::Index targetIndex,
342               SourceContainer& sources,
343               ConstraintFunctionPtr& func )
344   : ConstraintBase( object, targetIndex, sources ),
345     mTargetIndex( targetIndex ),
346     mUserFunction( func )
347   {
348   }
349
350   // Undefined
351   Constraint( const Constraint& );
352
353   // Undefined
354   Constraint& operator=( const Constraint& rhs );
355
356   /**
357    * Create and connect a constraint for a scene-object.
358    */
359   void ConnectConstraint()
360   {
361     // Should not come here if target-object has been destroyed
362     DALI_ASSERT_DEBUG( NULL != mTargetObject );
363
364     // Guard against double connections
365     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
366
367     // Short-circuit until the target scene-object exists
368     SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
369     if ( NULL == targetObject )
370     {
371       return;
372     }
373
374     // Build a container of property-owners, providing the scene-graph properties
375     SceneGraph::PropertyOwnerContainer propertyOwners;
376     propertyOwners.PushBack( targetObject );
377
378     // Build the constraint function; this requires a scene-graph property from each source
379     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
380
381     if ( func )
382     {
383       // Create the SceneGraphConstraint, and connect to the scene-graph
384
385       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
386
387       // The targetProperty should exist, when targetObject exists
388       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
389
390       const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
391
392       SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
393
394       if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
395       {
396         // Not a Vector2, Vector3 or Vector4 component, expecting float type
397         DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
398
399         typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
400
401         sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
402                                                            propertyOwners,
403                                                            func );
404       }
405       else
406       {
407         // Expecting Vector2, Vector3 or Vector4 type
408
409         if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
410         {
411           // Constrain float component of Vector2 property
412
413           if ( 0 == componentIndex )
414           {
415             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
416             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
417           }
418           else if ( 1 == componentIndex )
419           {
420             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
421             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
422           }
423         }
424         else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
425         {
426           // Constrain float component of Vector3 property
427
428           if ( 0 == componentIndex )
429           {
430             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
431             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
432           }
433           else if ( 1 == componentIndex )
434           {
435             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
436             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
437           }
438           else if ( 2 == componentIndex )
439           {
440             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
441             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
442           }
443         }
444         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
445         {
446           // Constrain float component of Vector4 property
447
448           if ( 0 == componentIndex )
449           {
450             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
451             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
452           }
453           else if ( 1 == componentIndex )
454           {
455             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
456             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
457           }
458           else if ( 2 == componentIndex )
459           {
460             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
461             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
462           }
463           else if ( 3 == componentIndex )
464           {
465             typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
466             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
467           }
468         }
469       }
470
471       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
472       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
473
474         // object is being used in a separate thread; queue a message to apply the constraint
475       ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
476
477       // Keep a raw-pointer to the scene-graph constraint
478       mSceneGraphConstraint = sceneGraphConstraint;
479     }
480   }
481
482   /**
483    * Helper for ConnectConstraint. Creates a connected constraint-function.
484    * Also populates the property-owner container, for each input connected to the constraint-function.
485    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
486    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
487    */
488   PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
489   {
490     PropertyConstraint<float>* func = mUserFunction->Clone();
491
492     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
493     {
494       Source& source = *iter;
495
496       PropertyInputImpl* inputProperty( NULL );
497       int componentIndex( Property::INVALID_COMPONENT_INDEX );
498
499       if ( OBJECT_PROPERTY == source.sourceType )
500       {
501         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
502
503         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
504
505         // The property owner will not exist, if the target object is off-stage
506         if( NULL != owner )
507         {
508           AddUnique( propertyOwners, owner );
509           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
510           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
511
512           // The scene-object property should exist, when the property owner exists
513           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
514         }
515       }
516       else if ( LOCAL_PROPERTY == source.sourceType )
517       {
518         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
519
520         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
521         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
522
523         // The target scene-object should provide this property
524         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
525       }
526       else
527       {
528         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
529
530         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
531
532         // This will not exist, if the target object is off-stage
533         if ( NULL != objectParent )
534         {
535           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
536
537           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
538
539           // The property owner will not exist, if the parent object is off-stage
540           if ( NULL != owner )
541           {
542             AddUnique( propertyOwners, owner );
543             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
544             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
545
546             // The scene-object property should exist, when the property owner exists
547             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
548           }
549         }
550       }
551
552       if ( NULL == inputProperty )
553       {
554         delete func;
555         func = NULL;
556
557         // Exit if a scene-graph object is not available from one of the sources
558         break;
559       }
560
561       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
562     }
563
564     return func;
565   }
566
567 protected:
568
569   Property::Index mTargetIndex;
570
571   ConstraintFunctionPtr mUserFunction;
572 };
573
574 } // namespace Internal
575
576 } // namespace Dali
577
578 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__