Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / active-constraint-impl.h
1 #ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
2 #define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
3
4 /*
5  * Copyright (c) 2014 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 // EXTERNAL INCLUDES
22 #include <boost/function.hpp>
23
24 // INTERNAL INCLUDES
25 #include <dali/internal/common/message.h>
26 #include <dali/internal/event/common/event-thread-services.h>
27 #include <dali/internal/event/common/object-impl.h>
28 #include <dali/internal/event/common/thread-local-storage.h>
29 #include <dali/internal/event/common/stage-impl.h>
30 #include <dali/internal/event/animation/active-constraint-base.h>
31 #include <dali/internal/event/animation/constraint-source-impl.h>
32 #include <dali/internal/event/animation/property-constraint-ptr.h>
33 #include <dali/internal/update/common/animatable-property.h>
34 #include <dali/internal/update/common/property-owner.h>
35 #include <dali/internal/update/common/property-owner-messages.h>
36 #include <dali/internal/update/animation/scene-graph-constraint.h>
37 #include <dali/internal/update/animation/property-accessor.h>
38 #include <dali/internal/update/animation/property-component-accessor.h>
39
40 namespace Dali
41 {
42
43 namespace Internal
44 {
45
46 /**
47  * Helper to add only unique entries to the propertyOwner container
48  * @param propertyOwners to add the entries to
49  * @param object to add
50  */
51 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
52 {
53   const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
54   if( iter == propertyOwners.End() )
55   {
56     // each owner should only be added once
57     propertyOwners.PushBack( object );
58   }
59 }
60
61 /**
62  * Connects a constraint which takes another property as an input.
63  */
64 template < typename PropertyType >
65 class ActiveConstraint : public ActiveConstraintBase
66 {
67 public:
68
69   typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
70   typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
71   typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
72
73   /**
74    * Construct a new active-constraint.
75    * @param[in] targetIndex The index of the property to constrain.
76    * @param[in] sources The sources of the input properties passed to func.
77    * @param[in] func The constraint function.
78    * @return A newly allocated active-constraint.
79    */
80   static ActiveConstraintBase* New( Property::Index targetIndex,
81                                     SourceContainer& sources,
82                                     ConstraintFunctionPtr func )
83   {
84     return new ActiveConstraint< PropertyType >( targetIndex, sources, sources.size(), func );
85   }
86
87   /**
88    * Virtual destructor.
89    */
90   virtual ~ActiveConstraint()
91   {
92     // This is not responsible for removing constraints.
93   }
94
95   /**
96    * @copydoc ActiveConstraintBase::Clone()
97    */
98   virtual ActiveConstraintBase* Clone()
99   {
100     ActiveConstraintBase* clone( NULL );
101
102     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
103
104     clone = new ActiveConstraint< PropertyType >( mTargetIndex,
105                                                   mSources,
106                                                   mSourceCount,
107                                                   funcPtr );
108
109     clone->SetAlphaFunction(mAlphaFunction);
110     clone->SetRemoveAction(mRemoveAction);
111     clone->SetTag( mTag );
112
113     return clone;
114   }
115
116 private:
117
118   /**
119    * Private constructor; see also ActiveConstraint::New().
120    */
121   ActiveConstraint( Property::Index targetIndex,
122                     SourceContainer& sources,
123                     unsigned int sourceCount,
124                     ConstraintFunctionPtr& func )
125   : ActiveConstraintBase( targetIndex, sources, sourceCount ),
126     mTargetIndex( targetIndex ),
127     mUserFunction( func )
128   {
129   }
130
131   // Undefined
132   ActiveConstraint( const ActiveConstraint& );
133
134   // Undefined
135   ActiveConstraint& operator=( const ActiveConstraint& rhs );
136
137   /**
138    * Create and connect a constraint for a scene-object.
139    */
140   void ConnectConstraint()
141   {
142     // Should not come here any objects have been destroyed
143     DALI_ASSERT_DEBUG( NULL != mTargetObject );
144     DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
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                                                                                      mCustomWeight );
177       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
178       sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
179       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
180
181       // object is being used in a separate thread; queue a message to apply the constraint
182       ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
183
184       // Keep a raw-pointer to the scene-graph constraint
185       mSceneGraphConstraint = sceneGraphConstraint;
186
187       // Notify Object base-class that the scene-graph constraint has been added
188       OnSceneObjectAdd();
189     }
190   }
191
192   /**
193    * Helper for ConnectConstraint. Creates a connected constraint-function.
194    * Also populates the property-owner container, for each input connected to the constraint-function.
195    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
196    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
197    */
198   PropertyConstraintBase<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
199   {
200     PropertyConstraintBase<PropertyType>* func = mUserFunction->Clone();
201     bool usingComponentFunc( false );
202
203     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
204     {
205       Source& source = *iter;
206
207       PropertyInputImpl* inputProperty( NULL );
208       int componentIndex( Property::INVALID_COMPONENT_INDEX );
209
210       if ( OBJECT_PROPERTY == source.sourceType )
211       {
212         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
213
214         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
215
216         // The property owner will not exist, if the target object is off-stage
217         if( NULL != owner )
218         {
219           AddUnique( propertyOwners, owner );
220           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
221           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
222
223           // The scene-object property should exist, when the property owner exists
224           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
225         }
226       }
227       else if ( LOCAL_PROPERTY == source.sourceType )
228       {
229         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
230
231         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
232         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
233
234         // The target scene-object should provide this property
235         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
236       }
237       else
238       {
239         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
240
241         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
242
243         // This will not exist, if the target object is off-stage
244         if ( NULL != objectParent )
245         {
246           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
247
248           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
249
250           // The property owner will not exist, if the parent object is off-stage
251           if ( NULL != owner )
252           {
253             AddUnique( propertyOwners, owner );
254             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
255             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
256
257             // The scene-object property should exist, when the property owner exists
258             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
259           }
260         }
261       }
262
263       if ( NULL == inputProperty )
264       {
265         delete func;
266         func = NULL;
267
268         // Exit if a scene-graph object is not available from one of the sources
269         break;
270       }
271       else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
272       {
273         // Special case where component indices are required
274         if ( !usingComponentFunc )
275         {
276           PropertyConstraintBase<PropertyType>* componentFunc = func->CloneComponentFunc();
277           usingComponentFunc = true;
278
279           // Switch to function supporting component indices
280           delete func;
281           func = componentFunc;
282         }
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 ActiveConstraint<float> : public ActiveConstraintBase
303 {
304 public:
305
306   typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
307
308   /**
309    * Construct a new active-constraint.
310    * @param[in] targetIndex The index of the property to constrain.
311    * @param[in] sources The sources of the input properties passed to func.
312    * @param[in] func The constraint function.
313    * @return A newly allocated active-constraint.
314    */
315   static ActiveConstraintBase* New( Property::Index targetIndex,
316                                     SourceContainer& sources,
317                                     ConstraintFunctionPtr func )
318   {
319     return new ActiveConstraint< float >( targetIndex, sources, sources.size(), func );
320   }
321
322   /**
323    * Virtual destructor.
324    */
325   virtual ~ActiveConstraint()
326   {
327     // This is not responsible for removing constraints.
328   }
329
330   /**
331    * @copydoc ActiveConstraintBase::Clone()
332    */
333   virtual ActiveConstraintBase* Clone()
334   {
335     ActiveConstraintBase* clone( NULL );
336
337     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
338
339     clone = new ActiveConstraint< float >( mTargetIndex,
340                                            mSources,
341                                            mSourceCount,
342                                            funcPtr );
343
344     clone->SetAlphaFunction(mAlphaFunction);
345     clone->SetRemoveAction(mRemoveAction);
346     clone->SetTag( mTag );
347
348     return clone;
349   }
350
351 private:
352
353   /**
354    * Private constructor; see also ActiveConstraint::New().
355    */
356   ActiveConstraint( Property::Index targetIndex,
357                     SourceContainer& sources,
358                     unsigned int sourceCount,
359                     ConstraintFunctionPtr& func )
360   : ActiveConstraintBase( targetIndex, sources, sourceCount ),
361     mTargetIndex( targetIndex ),
362     mUserFunction( func )
363   {
364   }
365
366   // Undefined
367   ActiveConstraint( const ActiveConstraint& );
368
369   // Undefined
370   ActiveConstraint& operator=( const ActiveConstraint& rhs );
371
372   /**
373    * Create and connect a constraint for a scene-object.
374    */
375   void ConnectConstraint()
376   {
377     // Should not come here any objects have been destroyed
378     DALI_ASSERT_DEBUG( NULL != mTargetObject );
379     DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
380
381     // Guard against double connections
382     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
383
384     // Short-circuit until the target scene-object exists
385     SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
386     if ( NULL == targetObject )
387     {
388       return;
389     }
390
391     // Build a container of property-owners, providing the scene-graph properties
392     SceneGraph::PropertyOwnerContainer propertyOwners;
393     propertyOwners.PushBack( targetObject );
394
395     // Build the constraint function; this requires a scene-graph property from each source
396     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
397
398     if ( func )
399     {
400       // Create the SceneGraphConstraint, and connect to the scene-graph
401
402       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
403
404       // The targetProperty should exist, when targetObject exists
405       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
406
407       const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
408
409       SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
410
411       if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
412       {
413         // Not a Vector3 or Vector4 component, expecting float type
414         DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
415
416         typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
417
418         sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
419                                                            propertyOwners,
420                                                            func,
421                                                            mCustomWeight );
422       }
423       else
424       {
425         // Expecting Vector3 or Vector4 type
426
427         if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
428         {
429           // Constrain float component of Vector3 property
430
431           if ( 0 == componentIndex )
432           {
433             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
434             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
435           }
436           else if ( 1 == componentIndex )
437           {
438             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
439             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
440           }
441           else if ( 2 == componentIndex )
442           {
443             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
444             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
445           }
446         }
447         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
448         {
449           // Constrain float component of Vector4 property
450
451           if ( 0 == componentIndex )
452           {
453             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
454             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
455           }
456           else if ( 1 == componentIndex )
457           {
458             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
459             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
460           }
461           else if ( 2 == componentIndex )
462           {
463             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
464             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
465           }
466           else if ( 3 == componentIndex )
467           {
468             typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
469             sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mCustomWeight );
470           }
471         }
472       }
473
474       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
475       sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
476       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
477
478         // object is being used in a separate thread; queue a message to apply the constraint
479       ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
480
481       // Keep a raw-pointer to the scene-graph constraint
482       mSceneGraphConstraint = sceneGraphConstraint;
483
484       // Notify Object base-class that the scene-graph constraint has been added
485       OnSceneObjectAdd();
486     }
487   }
488
489   /**
490    * Helper for ConnectConstraint. Creates a connected constraint-function.
491    * Also populates the property-owner container, for each input connected to the constraint-function.
492    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
493    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
494    */
495   PropertyConstraintBase<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
496   {
497     PropertyConstraintBase<float>* func = mUserFunction->Clone();
498     bool usingComponentFunc( false );
499
500     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
501     {
502       Source& source = *iter;
503
504       PropertyInputImpl* inputProperty( NULL );
505       int componentIndex( Property::INVALID_COMPONENT_INDEX );
506
507       if ( OBJECT_PROPERTY == source.sourceType )
508       {
509         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
510
511         SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
512
513         // The property owner will not exist, if the target object is off-stage
514         if( NULL != owner )
515         {
516           AddUnique( propertyOwners, owner );
517           inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
518           componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
519
520           // The scene-object property should exist, when the property owner exists
521           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
522         }
523       }
524       else if ( LOCAL_PROPERTY == source.sourceType )
525       {
526         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
527
528         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
529         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
530
531         // The target scene-object should provide this property
532         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
533       }
534       else
535       {
536         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
537
538         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
539
540         // This will not exist, if the target object is off-stage
541         if ( NULL != objectParent )
542         {
543           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
544
545           SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
546
547           // The property owner will not exist, if the parent object is off-stage
548           if ( NULL != owner )
549           {
550             AddUnique( propertyOwners, owner );
551             inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
552             componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
553
554             // The scene-object property should exist, when the property owner exists
555             DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
556           }
557         }
558       }
559
560       if ( NULL == inputProperty )
561       {
562         delete func;
563         func = NULL;
564
565         // Exit if a scene-graph object is not available from one of the sources
566         break;
567       }
568       else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
569       {
570         // Special case where component indices are required
571         if ( !usingComponentFunc )
572         {
573           PropertyConstraintBase<float>* componentFunc = func->CloneComponentFunc();
574           usingComponentFunc = true;
575
576           // Switch to function supporting component indices
577           delete func;
578           func = componentFunc;
579         }
580       }
581
582       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
583     }
584
585     return func;
586   }
587
588 protected:
589
590   Property::Index mTargetIndex;
591
592   ConstraintFunctionPtr mUserFunction;
593 };
594
595 } // namespace Internal
596
597 } // namespace Dali
598
599 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__