1 #ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
2 #define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
5 * Copyright (c) 2018 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/common/property-resetter.h>
34 #include <dali/internal/update/animation/scene-graph-constraint.h>
35 #include <dali/internal/update/animation/property-accessor.h>
36 #include <dali/internal/update/animation/property-component-accessor.h>
46 * Helper to add only unique entries to the propertyOwner container
47 * @param propertyOwners to add the entries to
48 * @param object to add
50 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
52 const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
53 if( iter == propertyOwners.End() )
55 // each owner should only be added once
56 propertyOwners.PushBack( object );
61 * Connects a constraint which takes another property as an input.
63 template < typename PropertyType >
64 class Constraint : public ConstraintBase
68 typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
69 typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
70 typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
71 typedef const SceneGraph::TransformManagerPropertyHandler<PropertyType> TransformManagerProperty;
74 * Construct a new constraint.
75 * @param[in] object The property-owning object.
76 * @param[in] targetIndex The index of the property to constrain.
77 * @param[in] sources The sources of the input properties passed to func.
78 * @param[in] func The constraint function.
79 * @return A newly allocated active-constraint.
81 static ConstraintBase* New( Object& object,
82 Property::Index targetIndex,
83 SourceContainer& sources,
84 ConstraintFunctionPtr func )
86 return new Constraint< PropertyType >( object, targetIndex, sources, func );
90 * @copydoc ConstraintBase::Clone()
92 virtual ConstraintBase* Clone( Object& object )
94 DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
96 ConstraintBase* clone( NULL );
98 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
100 clone = new Constraint< PropertyType >( object,
105 clone->SetRemoveAction(mRemoveAction);
106 clone->SetTag( mTag );
113 * Virtual destructor.
115 virtual ~Constraint()
117 // This is not responsible for removing constraints.
123 * Private constructor; see also Constraint::New().
125 Constraint( Object& object,
126 Property::Index targetIndex,
127 SourceContainer& sources,
128 ConstraintFunctionPtr& func )
129 : ConstraintBase( object, targetIndex, sources ),
130 mTargetIndex( targetIndex ),
131 mUserFunction( func )
136 Constraint( const Constraint& );
139 Constraint& operator=( const Constraint& rhs );
142 * Create and connect a constraint and property resetter for a scene-graph property
144 void ConnectConstraint()
146 // Should not come here if target object has been destroyed
147 DALI_ASSERT_DEBUG( NULL != mTargetObject );
149 // Guard against double connections
150 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
152 // Short-circuit until the target scene-object exists
153 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
154 if ( NULL == targetObject )
159 // Build a container of property-owners, providing the scene-graph properties
160 SceneGraph::PropertyOwnerContainer propertyOwners;
161 propertyOwners.PushBack( targetObject );
163 // Build the constraint function; this requires a scene-graph property from each source
164 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
168 // Create the SceneGraphConstraint and PropertyResetter, and connect them to the scene-graph
170 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
171 OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
173 // The targetProperty should exist, when targetObject exists
174 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
176 if( targetProperty->IsTransformManagerProperty() ) //It is a property managed by the transform manager
178 // Connect the constraint
179 mSceneGraphConstraint =
180 SceneGraph::Constraint<PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
184 // Don't create a resetter for transform manager property, it's less efficient
186 else //SceneGraph property
188 // Connect the constraint
189 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
193 // Connect the resetter
194 resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
197 OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
198 ApplyConstraintMessage( GetEventThreadServices(), *targetObject, transferOwnership );
200 if( resetter != nullptr )
202 AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
208 * Helper for ConnectConstraint. Creates a connected constraint-function.
209 * Also populates the property-owner container, for each input connected to the constraint-function.
210 * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
211 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
213 PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
215 PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
217 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
219 Source& source = *iter;
221 PropertyInputImpl* inputProperty( NULL );
222 int componentIndex( Property::INVALID_COMPONENT_INDEX );
224 if ( OBJECT_PROPERTY == source.sourceType )
226 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
228 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
230 // The property owner will not exist, if the target object is off-stage
233 AddUnique( propertyOwners, owner );
234 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
235 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
237 // The scene-object property should exist, when the property owner exists
238 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
241 else if ( LOCAL_PROPERTY == source.sourceType )
243 DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
245 inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
246 componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
248 // The target scene-object should provide this property
249 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
253 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
255 Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
257 // This will not exist, if the target object is off-stage
258 if ( NULL != objectParent )
260 DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
262 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
264 // The property owner will not exist, if the parent object is off-stage
267 AddUnique( propertyOwners, owner );
268 inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
269 componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
271 // The scene-object property should exist, when the property owner exists
272 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
277 if ( NULL == inputProperty )
282 // Exit if a scene-graph object is not available from one of the sources
286 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
294 Property::Index mTargetIndex;
296 ConstraintFunctionPtr mUserFunction;
300 * Variant which allows float components to be animated individually.
303 class Constraint<float> : public ConstraintBase
307 typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
310 * Construct a new constraint.
311 * @param[in] object The property-owning object.
312 * @param[in] targetIndex The index of the property to constrain.
313 * @param[in] sources The sources of the input properties passed to func.
314 * @param[in] func The constraint function.
315 * @return A newly allocated constraint.
317 static ConstraintBase* New( Object& object,
318 Property::Index targetIndex,
319 SourceContainer& sources,
320 ConstraintFunctionPtr func )
322 return new Constraint< float >( object, targetIndex, sources, func );
326 * @copydoc ConstraintBase::Clone()
328 virtual ConstraintBase* Clone( Object& object )
330 DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
332 ConstraintBase* clone( NULL );
334 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
336 clone = new Constraint< float >( object,
341 clone->SetRemoveAction(mRemoveAction);
342 clone->SetTag( mTag );
348 * Virtual destructor.
350 virtual ~Constraint()
352 // This is not responsible for removing constraints.
358 * Private constructor; see also Constraint::New().
360 Constraint( Object& object,
361 Property::Index targetIndex,
362 SourceContainer& sources,
363 ConstraintFunctionPtr& func )
364 : ConstraintBase( object, targetIndex, sources ),
365 mTargetIndex( targetIndex ),
366 mUserFunction( func )
371 Constraint( const Constraint& );
374 Constraint& operator=( const Constraint& rhs );
377 * Create and connect a constraint for a scene-object.
379 void ConnectConstraint()
381 // Should not come here if target-object has been destroyed
382 DALI_ASSERT_DEBUG( NULL != mTargetObject );
384 // Guard against double connections
385 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
387 // Short-circuit until the target scene-object exists
388 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
389 if ( NULL == targetObject )
394 // Build a container of property-owners, providing the scene-graph properties
395 SceneGraph::PropertyOwnerContainer propertyOwners;
396 propertyOwners.PushBack( targetObject );
398 // Build the constraint function; this requires a scene-graph property from each source
399 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
403 // Create the SceneGraphConstraint, and connect to the scene-graph
405 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
406 OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
408 // The targetProperty should exist, when targetObject exists
409 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
411 const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
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 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
421 resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
425 // Expecting Vector2, Vector3 or Vector4 type
427 if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
429 // Constrain float component of Vector2 property
431 if ( 0 == componentIndex )
433 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
434 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
436 else if ( 1 == componentIndex )
438 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
439 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
441 if( mSceneGraphConstraint )
443 resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
446 else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
448 // Constrain float component of Vector3 property
449 if( targetProperty->IsTransformManagerProperty() )
451 if ( 0 == componentIndex )
453 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
454 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
456 else if ( 1 == componentIndex )
458 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
459 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
461 else if ( 2 == componentIndex )
463 typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
464 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
466 // Do not create a resetter for transform manager property
470 if ( 0 == componentIndex )
472 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
473 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
475 else if ( 1 == componentIndex )
477 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
478 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
480 else if ( 2 == componentIndex )
482 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
483 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
485 if( mSceneGraphConstraint )
487 resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
491 else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
493 // Constrain float component of Vector4 property
495 if ( 0 == componentIndex )
497 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
498 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
500 else if ( 1 == componentIndex )
502 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
503 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
505 else if ( 2 == componentIndex )
507 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
508 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
510 else if ( 3 == componentIndex )
512 typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
513 mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
516 if( mSceneGraphConstraint )
518 resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
523 if( mSceneGraphConstraint )
525 OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
526 ApplyConstraintMessage( GetEventThreadServices(), *targetObject, transferOwnership );
528 if( resetter != nullptr )
530 AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
536 * Helper for ConnectConstraint. Creates a connected constraint-function.
537 * Also populates the property-owner container, for each input connected to the constraint-function.
538 * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
539 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
541 PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
543 PropertyConstraint<float>* func = mUserFunction->Clone();
545 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
547 Source& source = *iter;
549 PropertyInputImpl* inputProperty( NULL );
550 int componentIndex( Property::INVALID_COMPONENT_INDEX );
552 if ( OBJECT_PROPERTY == source.sourceType )
554 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
556 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
558 // The property owner will not exist, if the target object is off-stage
561 AddUnique( propertyOwners, owner );
562 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
563 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
565 // The scene-object property should exist, when the property owner exists
566 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
569 else if ( LOCAL_PROPERTY == source.sourceType )
571 DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
573 inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
574 componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
576 // The target scene-object should provide this property
577 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
581 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
583 Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
585 // This will not exist, if the target object is off-stage
586 if ( NULL != objectParent )
588 DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
590 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
592 // The property owner will not exist, if the parent object is off-stage
595 AddUnique( propertyOwners, owner );
596 inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
597 componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
599 // The scene-object property should exist, when the property owner exists
600 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
605 if ( NULL == inputProperty )
610 // Exit if a scene-graph object is not available from one of the sources
614 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
622 Property::Index mTargetIndex;
624 ConstraintFunctionPtr mUserFunction;
627 } // namespace Internal
631 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__