1 #ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
2 #define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
5 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
44 * Helper to add only unique entries to the propertyOwner container
45 * @param propertyOwners to add the entries to
46 * @param object to add
48 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
50 const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
51 if( iter == propertyOwners.End() )
53 // each owner should only be added once
54 propertyOwners.PushBack( object );
59 * Connects a constraint which takes another property as an input.
61 template < typename PropertyType >
62 class Constraint : public ConstraintBase
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;
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.
79 static ConstraintBase* New( Object& object,
80 Property::Index targetIndex,
81 SourceContainer& sources,
82 ConstraintFunctionPtr func )
84 return new Constraint< PropertyType >( object, targetIndex, sources, func );
88 * @copydoc ConstraintBase::Clone()
90 virtual ConstraintBase* Clone( Object& object )
92 DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
94 ConstraintBase* clone( NULL );
96 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
98 clone = new Constraint< PropertyType >( object,
103 clone->SetRemoveAction(mRemoveAction);
104 clone->SetTag( mTag );
111 * Virtual destructor.
113 virtual ~Constraint()
115 // This is not responsible for removing constraints.
121 * Private constructor; see also Constraint::New().
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 )
134 Constraint( const Constraint& );
137 Constraint& operator=( const Constraint& rhs );
140 * Create and connect a constraint for a scene-object.
142 void ConnectConstraint()
144 // Should not come here if target-object has been destroyed
145 DALI_ASSERT_DEBUG( NULL != mTargetObject );
147 // Guard against double connections
148 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
150 // Short-circuit until the target scene-object exists
151 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
152 if ( NULL == targetObject )
157 // Build a container of property-owners, providing the scene-graph properties
158 SceneGraph::PropertyOwnerContainer propertyOwners;
159 propertyOwners.PushBack( targetObject );
161 // Build the constraint function; this requires a scene-graph property from each source
162 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
166 // Create the SceneGraphConstraint, and connect to the scene-graph
168 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
170 // The targetProperty should exist, when targetObject exists
171 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
173 if( targetProperty->IsTransformManagerProperty() ) //It is a property managed by the transform manager
175 // Connect the constraint
176 SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraph::Constraint<PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
179 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
180 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
182 // object is being used in a separate thread; queue a message to apply the constraint
183 ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
185 // Keep a raw-pointer to the scene-graph constraint
186 mSceneGraphConstraint = sceneGraphConstraint;
188 else //SceneGraph property
190 // Connect the constraint
191 SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
194 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
195 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
197 // object is being used in a separate thread; queue a message to apply the constraint
198 ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
200 // Keep a raw-pointer to the scene-graph constraint
201 mSceneGraphConstraint = sceneGraphConstraint;
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.
212 PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
214 PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
216 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
218 Source& source = *iter;
220 PropertyInputImpl* inputProperty( NULL );
221 int componentIndex( Property::INVALID_COMPONENT_INDEX );
223 if ( OBJECT_PROPERTY == source.sourceType )
225 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
227 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
229 // The property owner will not exist, if the target object is off-stage
232 AddUnique( propertyOwners, owner );
233 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
234 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
236 // The scene-object property should exist, when the property owner exists
237 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
240 else if ( LOCAL_PROPERTY == source.sourceType )
242 DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
244 inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
245 componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
247 // The target scene-object should provide this property
248 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
252 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
254 Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
256 // This will not exist, if the target object is off-stage
257 if ( NULL != objectParent )
259 DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
261 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
263 // The property owner will not exist, if the parent object is off-stage
266 AddUnique( propertyOwners, owner );
267 inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
268 componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
270 // The scene-object property should exist, when the property owner exists
271 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
276 if ( NULL == inputProperty )
281 // Exit if a scene-graph object is not available from one of the sources
285 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
293 Property::Index mTargetIndex;
295 ConstraintFunctionPtr mUserFunction;
299 * Variant which allows float components to be animated individually.
302 class Constraint<float> : public ConstraintBase
306 typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
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.
316 static ConstraintBase* New( Object& object,
317 Property::Index targetIndex,
318 SourceContainer& sources,
319 ConstraintFunctionPtr func )
321 return new Constraint< float >( object, targetIndex, sources, func );
325 * @copydoc ConstraintBase::Clone()
327 virtual ConstraintBase* Clone( Object& object )
329 DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
331 ConstraintBase* clone( NULL );
333 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
335 clone = new Constraint< float >( object,
340 clone->SetRemoveAction(mRemoveAction);
341 clone->SetTag( mTag );
347 * Virtual destructor.
349 virtual ~Constraint()
351 // This is not responsible for removing constraints.
357 * Private constructor; see also Constraint::New().
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 )
370 Constraint( const Constraint& );
373 Constraint& operator=( const Constraint& rhs );
376 * Create and connect a constraint for a scene-object.
378 void ConnectConstraint()
380 // Should not come here if target-object has been destroyed
381 DALI_ASSERT_DEBUG( NULL != mTargetObject );
383 // Guard against double connections
384 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
386 // Short-circuit until the target scene-object exists
387 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
388 if ( NULL == targetObject )
393 // Build a container of property-owners, providing the scene-graph properties
394 SceneGraph::PropertyOwnerContainer propertyOwners;
395 propertyOwners.PushBack( targetObject );
397 // Build the constraint function; this requires a scene-graph property from each source
398 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
402 // Create the SceneGraphConstraint, and connect to the scene-graph
404 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
406 // The targetProperty should exist, when targetObject exists
407 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
409 const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
411 SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
413 if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
415 // Not a Vector2, Vector3 or Vector4 component, expecting float type
416 DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
418 typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
420 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
426 // Expecting Vector2, Vector3 or Vector4 type
428 if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
430 // Constrain float component of Vector2 property
432 if ( 0 == componentIndex )
434 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
435 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
437 else if ( 1 == componentIndex )
439 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
440 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
443 else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
445 // Constrain float component of Vector3 property
446 if( targetProperty->IsTransformManagerProperty() )
448 if ( 0 == componentIndex )
450 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
451 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
453 else if ( 1 == componentIndex )
455 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
456 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
458 else if ( 2 == componentIndex )
460 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
461 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
466 if ( 0 == componentIndex )
468 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
469 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
471 else if ( 1 == componentIndex )
473 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
474 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
476 else if ( 2 == componentIndex )
478 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
479 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
483 else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
485 // Constrain float component of Vector4 property
487 if ( 0 == componentIndex )
489 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
490 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
492 else if ( 1 == componentIndex )
494 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
495 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
497 else if ( 2 == componentIndex )
499 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
500 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
502 else if ( 3 == componentIndex )
504 typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
505 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
510 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
511 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
513 // object is being used in a separate thread; queue a message to apply the constraint
514 ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
516 // Keep a raw-pointer to the scene-graph constraint
517 mSceneGraphConstraint = sceneGraphConstraint;
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.
527 PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
529 PropertyConstraint<float>* func = mUserFunction->Clone();
531 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
533 Source& source = *iter;
535 PropertyInputImpl* inputProperty( NULL );
536 int componentIndex( Property::INVALID_COMPONENT_INDEX );
538 if ( OBJECT_PROPERTY == source.sourceType )
540 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
542 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
544 // The property owner will not exist, if the target object is off-stage
547 AddUnique( propertyOwners, owner );
548 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
549 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
551 // The scene-object property should exist, when the property owner exists
552 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
555 else if ( LOCAL_PROPERTY == source.sourceType )
557 DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
559 inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
560 componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
562 // The target scene-object should provide this property
563 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
567 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
569 Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
571 // This will not exist, if the target object is off-stage
572 if ( NULL != objectParent )
574 DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
576 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
578 // The property owner will not exist, if the parent object is off-stage
581 AddUnique( propertyOwners, owner );
582 inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
583 componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
585 // The scene-object property should exist, when the property owner exists
586 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
591 if ( NULL == inputProperty )
596 // Exit if a scene-graph object is not available from one of the sources
600 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
608 Property::Index mTargetIndex;
610 ConstraintFunctionPtr mUserFunction;
613 } // namespace Internal
617 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__