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 * Connects a constraint which takes another property as an input.
48 template < typename PropertyType >
49 class Constraint : public ConstraintBase
53 using ConstraintFunctionPtr = typename PropertyConstraintPtr<PropertyType>::Type;
56 * Construct a new constraint.
57 * @param[in] object The property-owning object.
58 * @param[in] targetIndex The index of the property to constrain.
59 * @param[in] sources The sources of the input properties passed to func.
60 * @param[in] func The constraint function.
61 * @return A newly allocated active-constraint.
63 static ConstraintBase* New( Object& object,
64 Property::Index targetIndex,
65 SourceContainer& sources,
66 ConstraintFunctionPtr func )
68 return new Constraint( object, targetIndex, sources, func );
76 // This is not responsible for removing constraints.
82 * @copydoc ConstraintBase::DoClone()
84 ConstraintBase* DoClone( Object& object ) override final
86 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
87 return new Constraint( object,
94 * Private constructor; see also Constraint::New().
96 Constraint( Object& object,
97 Property::Index targetIndex,
98 SourceContainer& sources,
99 ConstraintFunctionPtr& func )
100 : ConstraintBase( object, targetIndex, sources ),
101 mUserFunction( func )
106 Constraint() = delete;
107 Constraint( const Constraint& ) = delete;
108 Constraint& operator=( const Constraint& rhs ) = delete;
112 * @copydoc ConstraintBase::ConnectConstraint()
114 void ConnectConstraint() override final
116 // Should not come here if target object has been destroyed
117 DALI_ASSERT_DEBUG( nullptr != mTargetObject );
119 // Guard against double connections
120 DALI_ASSERT_DEBUG( nullptr == mSceneGraphConstraint );
122 SceneGraph::PropertyOwner& targetObject = const_cast< SceneGraph::PropertyOwner& >( mTargetObject->GetSceneObject() );
124 // Build a container of property-owners, providing the scene-graph properties
125 SceneGraph::PropertyOwnerContainer propertyOwners;
126 propertyOwners.PushBack( &targetObject );
128 // Build the constraint function; this requires a scene-graph property from each source
129 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
133 OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
134 // Create the SceneGraphConstraint and PropertyResetter, and connect them to the scene-graph
135 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetPropertyIndex );
136 DALI_ASSERT_ALWAYS( targetProperty && "Constraint target property does not exist" );
137 if( targetProperty->IsTransformManagerProperty() ) //It is a property managed by the transform manager
139 // Connect the constraint
140 mSceneGraphConstraint = SceneGraph::Constraint< PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
144 // Don't create a resetter for transform manager property, it's less efficient
146 else //SceneGraph property
148 // Connect the constraint
149 mSceneGraphConstraint = SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> >::New( *targetProperty,
153 resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
155 OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
156 ApplyConstraintMessage( GetEventThreadServices(), targetObject, transferOwnership );
159 AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
165 * Helper for ConnectConstraint. Creates a connected constraint-function.
166 * Also populates the property-owner container, for each input connected to the constraint-function.
167 * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
168 * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
170 PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
172 PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
174 for ( auto&& source : mSources )
176 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
177 PropertyInputImpl* inputProperty = AddInputProperty( source, propertyOwners, componentIndex );
179 if ( nullptr == inputProperty )
184 // Exit if a scene-graph object is not available from one of the sources
188 func->AddInput( inputProperty, componentIndex );
196 ConstraintFunctionPtr mUserFunction;
201 * Variant which allows float components to be constrained individually.
204 class Constraint<float> : public ConstraintBase
208 using ConstraintFunctionPtr = typename PropertyConstraintPtr<float>::Type;
211 * Construct a new constraint.
212 * @param[in] object The property-owning object.
213 * @param[in] targetIndex The index of the property to constrain.
214 * @param[in] sources The sources of the input properties passed to func.
215 * @param[in] func The constraint function.
216 * @return A newly allocated constraint.
218 static ConstraintBase* New( Object& object,
219 Property::Index targetIndex,
220 SourceContainer& sources,
221 ConstraintFunctionPtr func )
223 return new Constraint( object, targetIndex, sources, func );
227 * Virtual destructor.
229 virtual ~Constraint()
231 // This is not responsible for removing constraints.
237 * @copydoc ConstraintBase::DoClone()
239 virtual ConstraintBase* DoClone( Object& object ) override final
241 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
242 return new Constraint( object,
243 mTargetPropertyIndex,
249 * Private constructor; see also Constraint::New().
251 Constraint( Object& object,
252 Property::Index targetIndex,
253 SourceContainer& sources,
254 ConstraintFunctionPtr& func )
255 : ConstraintBase( object, targetIndex, sources ),
256 mUserFunction( func )
261 Constraint() = delete;
262 Constraint( const Constraint& ) = delete;
263 Constraint& operator=( const Constraint& rhs ) = delete;
266 * @copydoc ConstraintBase::ConnectConstraint()
268 void ConnectConstraint() override final
270 // Should not come here if target object has been destroyed
271 DALI_ASSERT_DEBUG( nullptr != mTargetObject );
272 // Guard against double connections
273 DALI_ASSERT_DEBUG( nullptr == mSceneGraphConstraint );
275 SceneGraph::PropertyOwner& targetObject = const_cast< SceneGraph::PropertyOwner& >( mTargetObject->GetSceneObject() );
277 // Build a container of property-owners, providing the scene-graph properties
278 SceneGraph::PropertyOwnerContainer propertyOwners;
279 propertyOwners.PushBack( &targetObject );
281 // Build the constraint function; this requires a scene-graph property from each source
282 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
286 // Create the SceneGraphConstraint, and connect to the scene-graph
287 bool resetterRequired = false;
288 const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetPropertyIndex );
289 // The targetProperty should exist, when targetObject exists
290 DALI_ASSERT_ALWAYS( nullptr != targetProperty && "Constraint target property does not exist" );
291 const int32_t componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetPropertyIndex );
292 if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
294 // Not a Vector2, Vector3 or Vector4 component, expecting float type
295 DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
297 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyAccessor<float> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
298 resetterRequired = true;
302 // Expecting Vector2, Vector3 or Vector4 type
303 if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
305 // Constrain float component of Vector2 property
306 if ( 0 == componentIndex )
308 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
310 else if ( 1 == componentIndex )
312 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
314 resetterRequired = (mSceneGraphConstraint != nullptr);
316 else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
318 // Constrain float component of Vector3 property
319 if( targetProperty->IsTransformManagerProperty() )
321 if ( 0 == componentIndex )
323 mSceneGraphConstraint = SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> >::New( *targetProperty,
328 else if ( 1 == componentIndex )
330 mSceneGraphConstraint = SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> >::New( *targetProperty,
335 else if ( 2 == componentIndex )
337 mSceneGraphConstraint = SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> >::New( *targetProperty,
342 // Do not create a resetter for transform manager property
346 if ( 0 == componentIndex )
348 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
350 else if ( 1 == componentIndex )
352 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
354 else if ( 2 == componentIndex )
356 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
358 resetterRequired = (mSceneGraphConstraint != nullptr);
361 else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
363 // Constrain float component of Vector4 property
364 if ( 0 == componentIndex )
366 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
368 else if ( 1 == componentIndex )
370 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
372 else if ( 2 == componentIndex )
374 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
376 else if ( 3 == componentIndex )
378 mSceneGraphConstraint = SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> >::New( *targetProperty, propertyOwners, func, mRemoveAction );
381 resetterRequired = (mSceneGraphConstraint != nullptr);
384 if( mSceneGraphConstraint )
386 OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
387 ApplyConstraintMessage( GetEventThreadServices(), targetObject, transferOwnership );
388 if( resetterRequired )
390 OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
391 AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
398 * Helper for ConnectConstraint. Creates a connected constraint-function.
399 * Also populates the property-owner container, for each input connected to the constraint-function.
400 * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
401 * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
403 PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
405 PropertyConstraint<float>* func = mUserFunction->Clone();
407 for ( auto&& source : mSources )
409 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
410 PropertyInputImpl* inputProperty = AddInputProperty( source, propertyOwners, componentIndex );
412 if ( nullptr == inputProperty )
417 // Exit if a scene-graph object is not available from one of the sources
421 func->AddInput( inputProperty, componentIndex );
429 ConstraintFunctionPtr mUserFunction;
433 } // namespace Internal
437 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__