[dali_1.2.34] Merge branch 'devel/master'
[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   typedef const SceneGraph::TransformManagerPropertyHandler<PropertyType> TransformManagerProperty;
70
71   /**
72    * Construct a new constraint.
73    * @param[in] object The property-owning object.
74    * @param[in] targetIndex The index of the property to constrain.
75    * @param[in] sources The sources of the input properties passed to func.
76    * @param[in] func The constraint function.
77    * @return A newly allocated active-constraint.
78    */
79   static ConstraintBase* New( Object& object,
80                               Property::Index targetIndex,
81                               SourceContainer& sources,
82                               ConstraintFunctionPtr func )
83   {
84     return new Constraint< PropertyType >( object, targetIndex, sources, func );
85   }
86
87   /**
88    * @copydoc ConstraintBase::Clone()
89    */
90   virtual ConstraintBase* Clone( Object& object )
91   {
92     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
93
94     ConstraintBase* clone( NULL );
95
96     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
97
98     clone = new Constraint< PropertyType >( object,
99                                             mTargetIndex,
100                                             mSources,
101                                             funcPtr );
102
103     clone->SetRemoveAction(mRemoveAction);
104     clone->SetTag( mTag );
105
106     return clone;
107   }
108
109
110   /**
111    * Virtual destructor.
112    */
113   virtual ~Constraint()
114   {
115     // This is not responsible for removing constraints.
116   }
117
118 private:
119
120   /**
121    * Private constructor; see also Constraint::New().
122    */
123   Constraint( Object& object,
124               Property::Index targetIndex,
125               SourceContainer& sources,
126               ConstraintFunctionPtr& func )
127   : ConstraintBase( object, targetIndex, sources ),
128     mTargetIndex( targetIndex ),
129     mUserFunction( func )
130   {
131   }
132
133   // Undefined
134   Constraint( const Constraint& );
135
136   // Undefined
137   Constraint& operator=( const Constraint& rhs );
138
139   /**
140    * Create and connect a constraint for a scene-object.
141    */
142   void ConnectConstraint()
143   {
144     // Should not come here if target-object has been destroyed
145     DALI_ASSERT_DEBUG( NULL != mTargetObject );
146
147     // Guard against double connections
148     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
149
150     // Short-circuit until the target scene-object exists
151     SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
152     if ( NULL == targetObject )
153     {
154       return;
155     }
156
157     // Build a container of property-owners, providing the scene-graph properties
158     SceneGraph::PropertyOwnerContainer propertyOwners;
159     propertyOwners.PushBack( targetObject );
160
161     // Build the constraint function; this requires a scene-graph property from each source
162     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
163
164     if ( func )
165     {
166       // Create the SceneGraphConstraint, and connect to the scene-graph
167
168       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
169
170       // The targetProperty should exist, when targetObject exists
171       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
172
173       if( targetProperty->IsTransformManagerProperty() )  //It is a property managed by the transform manager
174       {
175         // Connect the constraint
176         SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraph::Constraint<PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
177                                                                                       propertyOwners,
178                                                                                       func );
179         DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
180         sceneGraphConstraint->SetRemoveAction( mRemoveAction );
181
182         // object is being used in a separate thread; queue a message to apply the constraint
183         ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
184
185         // Keep a raw-pointer to the scene-graph constraint
186         mSceneGraphConstraint = sceneGraphConstraint;
187       }
188       else  //SceneGraph property
189       {
190         // Connect the constraint
191         SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
192                                                                                       propertyOwners,
193                                                                                       func );
194         DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
195         sceneGraphConstraint->SetRemoveAction( mRemoveAction );
196
197         // object is being used in a separate thread; queue a message to apply the constraint
198         ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
199
200         // Keep a raw-pointer to the scene-graph constraint
201         mSceneGraphConstraint = sceneGraphConstraint;
202       }
203     }
204   }
205
206   /**
207    * Helper for ConnectConstraint. Creates a connected constraint-function.
208    * Also populates the property-owner container, for each input connected to the constraint-function.
209    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
210    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
211    */
212   PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
213   {
214     PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
215
216     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
217     {
218       Source& source = *iter;
219
220       PropertyInputImpl* inputProperty( NULL );
221       int componentIndex( Property::INVALID_COMPONENT_INDEX );
222
223       if ( OBJECT_PROPERTY == source.sourceType )
224       {
225         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
226
227         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
228
229         // The property owner will not exist, if the target object is off-stage
230         if( NULL != owner )
231         {
232           AddUnique( propertyOwners, owner );
233           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
234           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
235
236           // The scene-object property should exist, when the property owner exists
237           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
238         }
239       }
240       else if ( LOCAL_PROPERTY == source.sourceType )
241       {
242         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
243
244         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
245         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
246
247         // The target scene-object should provide this property
248         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
249       }
250       else
251       {
252         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
253
254         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
255
256         // This will not exist, if the target object is off-stage
257         if ( NULL != objectParent )
258         {
259           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
260
261           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
262
263           // The property owner will not exist, if the parent object is off-stage
264           if ( NULL != owner )
265           {
266             AddUnique( propertyOwners, owner );
267             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
268             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
269
270             // The scene-object property should exist, when the property owner exists
271             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
272           }
273         }
274       }
275
276       if ( NULL == inputProperty )
277       {
278         delete func;
279         func = NULL;
280
281         // Exit if a scene-graph object is not available from one of the sources
282         break;
283       }
284
285       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
286     }
287
288     return func;
289   }
290
291 protected:
292
293   Property::Index mTargetIndex;
294
295   ConstraintFunctionPtr mUserFunction;
296 };
297
298 /**
299  * Variant which allows float components to be animated individually.
300  */
301 template <>
302 class Constraint<float> : public ConstraintBase
303 {
304 public:
305
306   typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
307
308   /**
309    * Construct a new constraint.
310    * @param[in] object The property-owning object.
311    * @param[in] targetIndex The index of the property to constrain.
312    * @param[in] sources The sources of the input properties passed to func.
313    * @param[in] func The constraint function.
314    * @return A newly allocated constraint.
315    */
316   static ConstraintBase* New( Object& object,
317                               Property::Index targetIndex,
318                               SourceContainer& sources,
319                               ConstraintFunctionPtr func )
320   {
321     return new Constraint< float >( object, targetIndex, sources, func );
322   }
323
324   /**
325    * @copydoc ConstraintBase::Clone()
326    */
327   virtual ConstraintBase* Clone( Object& object )
328   {
329     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
330
331     ConstraintBase* clone( NULL );
332
333     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
334
335     clone = new Constraint< float >( object,
336                                      mTargetIndex,
337                                      mSources,
338                                      funcPtr );
339
340     clone->SetRemoveAction(mRemoveAction);
341     clone->SetTag( mTag );
342
343     return clone;
344   }
345
346   /**
347    * Virtual destructor.
348    */
349   virtual ~Constraint()
350   {
351     // This is not responsible for removing constraints.
352   }
353
354 private:
355
356   /**
357    * Private constructor; see also Constraint::New().
358    */
359   Constraint( Object& object,
360               Property::Index targetIndex,
361               SourceContainer& sources,
362               ConstraintFunctionPtr& func )
363   : ConstraintBase( object, targetIndex, sources ),
364     mTargetIndex( targetIndex ),
365     mUserFunction( func )
366   {
367   }
368
369   // Undefined
370   Constraint( const Constraint& );
371
372   // Undefined
373   Constraint& operator=( const Constraint& rhs );
374
375   /**
376    * Create and connect a constraint for a scene-object.
377    */
378   void ConnectConstraint()
379   {
380     // Should not come here if target-object has been destroyed
381     DALI_ASSERT_DEBUG( NULL != mTargetObject );
382
383     // Guard against double connections
384     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
385
386     // Short-circuit until the target scene-object exists
387     SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
388     if ( NULL == targetObject )
389     {
390       return;
391     }
392
393     // Build a container of property-owners, providing the scene-graph properties
394     SceneGraph::PropertyOwnerContainer propertyOwners;
395     propertyOwners.PushBack( targetObject );
396
397     // Build the constraint function; this requires a scene-graph property from each source
398     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
399
400     if ( func )
401     {
402       // Create the SceneGraphConstraint, and connect to the scene-graph
403
404       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
405
406       // The targetProperty should exist, when targetObject exists
407       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
408
409       const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
410
411       SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
412
413       if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
414       {
415         // Not a Vector2, Vector3 or Vector4 component, expecting float type
416         DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
417
418         typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
419
420         sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
421                                                            propertyOwners,
422                                                            func );
423       }
424       else
425       {
426         // Expecting Vector2, Vector3 or Vector4 type
427
428         if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
429         {
430           // Constrain float component of Vector2 property
431
432           if ( 0 == componentIndex )
433           {
434             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
435             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
436           }
437           else if ( 1 == componentIndex )
438           {
439             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
440             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
441           }
442         }
443         else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
444         {
445           // Constrain float component of Vector3 property
446           if( targetProperty->IsTransformManagerProperty() )
447           {
448             if ( 0 == componentIndex )
449             {
450               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
451               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
452             }
453             else if ( 1 == componentIndex )
454             {
455               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
456               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
457             }
458             else if ( 2 == componentIndex )
459             {
460               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
461               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
462             }
463           }
464           else
465           {
466             if ( 0 == componentIndex )
467             {
468               typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
469               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
470             }
471             else if ( 1 == componentIndex )
472             {
473               typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
474               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
475             }
476             else if ( 2 == componentIndex )
477             {
478               typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
479               sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
480             }
481           }
482         }
483         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
484         {
485           // Constrain float component of Vector4 property
486
487           if ( 0 == componentIndex )
488           {
489             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
490             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
491           }
492           else if ( 1 == componentIndex )
493           {
494             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
495             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
496           }
497           else if ( 2 == componentIndex )
498           {
499             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
500             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
501           }
502           else if ( 3 == componentIndex )
503           {
504             typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
505             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
506           }
507         }
508       }
509
510       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
511       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
512
513         // object is being used in a separate thread; queue a message to apply the constraint
514       ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
515
516       // Keep a raw-pointer to the scene-graph constraint
517       mSceneGraphConstraint = sceneGraphConstraint;
518     }
519   }
520
521   /**
522    * Helper for ConnectConstraint. Creates a connected constraint-function.
523    * Also populates the property-owner container, for each input connected to the constraint-function.
524    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
525    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
526    */
527   PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
528   {
529     PropertyConstraint<float>* func = mUserFunction->Clone();
530
531     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
532     {
533       Source& source = *iter;
534
535       PropertyInputImpl* inputProperty( NULL );
536       int componentIndex( Property::INVALID_COMPONENT_INDEX );
537
538       if ( OBJECT_PROPERTY == source.sourceType )
539       {
540         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
541
542         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
543
544         // The property owner will not exist, if the target object is off-stage
545         if( NULL != owner )
546         {
547           AddUnique( propertyOwners, owner );
548           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
549           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
550
551           // The scene-object property should exist, when the property owner exists
552           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
553         }
554       }
555       else if ( LOCAL_PROPERTY == source.sourceType )
556       {
557         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
558
559         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
560         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
561
562         // The target scene-object should provide this property
563         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
564       }
565       else
566       {
567         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
568
569         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
570
571         // This will not exist, if the target object is off-stage
572         if ( NULL != objectParent )
573         {
574           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
575
576           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
577
578           // The property owner will not exist, if the parent object is off-stage
579           if ( NULL != owner )
580           {
581             AddUnique( propertyOwners, owner );
582             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
583             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
584
585             // The scene-object property should exist, when the property owner exists
586             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
587           }
588         }
589       }
590
591       if ( NULL == inputProperty )
592       {
593         delete func;
594         func = NULL;
595
596         // Exit if a scene-graph object is not available from one of the sources
597         break;
598       }
599
600       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
601     }
602
603     return func;
604   }
605
606 protected:
607
608   Property::Index mTargetIndex;
609
610   ConstraintFunctionPtr mUserFunction;
611 };
612
613 } // namespace Internal
614
615 } // namespace Dali
616
617 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__