Dali 3D User Interface Engine
constraint-impl.h
Go to the documentation of this file.
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
36 
37 namespace Dali
38 {
39 
40 namespace Internal
41 {
42 
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 
61 template < typename PropertyType >
62 class Constraint : public ConstraintBase
63 {
64 public:
65 
69 
78  static ConstraintBase* New( Object& object,
79  Property::Index targetIndex,
80  SourceContainer& sources,
82  {
83  return new Constraint< PropertyType >( object, targetIndex, sources, func );
84  }
85 
89  virtual ConstraintBase* Clone( Object& object )
90  {
91  DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
92 
93  ConstraintBase* clone( NULL );
94 
95  ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
96 
97  clone = new Constraint< PropertyType >( object,
99  mSources,
100  funcPtr );
101 
103  clone->SetTag( mTag );
104 
105  return clone;
106  }
107 
108 
112  virtual ~Constraint()
113  {
114  // This is not responsible for removing constraints.
115  }
116 
117 private:
118 
122  Constraint( Object& object,
123  Property::Index targetIndex,
124  SourceContainer& sources,
125  ConstraintFunctionPtr& func )
126  : ConstraintBase( object, targetIndex, sources ),
127  mTargetIndex( targetIndex ),
128  mUserFunction( func )
129  {
130  }
131 
132  // Undefined
133  Constraint( const Constraint& );
134 
135  // Undefined
136  Constraint& operator=( const Constraint& rhs );
137 
142  {
143  // Should not come here if target-object has been destroyed
144  DALI_ASSERT_DEBUG( NULL != mTargetObject );
145 
146  // Guard against double connections
148 
149  // Short-circuit until the target scene-object exists
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 
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  DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
177  sceneGraphConstraint->SetRemoveAction( mRemoveAction );
178 
179  // object is being used in a separate thread; queue a message to apply the constraint
180  ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
181 
182  // Keep a raw-pointer to the scene-graph constraint
183  mSceneGraphConstraint = sceneGraphConstraint;
184  }
185  }
186 
194  {
196 
197  for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
198  {
199  Source& source = *iter;
200 
201  PropertyInputImpl* inputProperty( NULL );
202  int componentIndex( Property::INVALID_COMPONENT_INDEX );
203 
204  if ( OBJECT_PROPERTY == source.sourceType )
205  {
207 
208  SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
209 
210  // The property owner will not exist, if the target object is off-stage
211  if( NULL != owner )
212  {
213  AddUnique( propertyOwners, owner );
214  inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
215  componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
216 
217  // The scene-object property should exist, when the property owner exists
218  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
219  }
220  }
221  else if ( LOCAL_PROPERTY == source.sourceType )
222  {
224 
225  inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
226  componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
227 
228  // The target scene-object should provide this property
229  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
230  }
231  else
232  {
233  DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
234 
235  Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
236 
237  // This will not exist, if the target object is off-stage
238  if ( NULL != objectParent )
239  {
241 
242  SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
243 
244  // The property owner will not exist, if the parent object is off-stage
245  if ( NULL != owner )
246  {
247  AddUnique( propertyOwners, owner );
248  inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
249  componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
250 
251  // The scene-object property should exist, when the property owner exists
252  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
253  }
254  }
255  }
256 
257  if ( NULL == inputProperty )
258  {
259  delete func;
260  func = NULL;
261 
262  // Exit if a scene-graph object is not available from one of the sources
263  break;
264  }
265 
266  func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
267  }
268 
269  return func;
270  }
271 
272 protected:
273 
275 
277 };
278 
282 template <>
283 class Constraint<float> : public ConstraintBase
284 {
285 public:
286 
288 
297  static ConstraintBase* New( Object& object,
298  Property::Index targetIndex,
299  SourceContainer& sources,
300  ConstraintFunctionPtr func )
301  {
302  return new Constraint< float >( object, targetIndex, sources, func );
303  }
304 
308  virtual ConstraintBase* Clone( Object& object )
309  {
310  DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
311 
312  ConstraintBase* clone( NULL );
313 
314  ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
315 
316  clone = new Constraint< float >( object,
317  mTargetIndex,
318  mSources,
319  funcPtr );
320 
322  clone->SetTag( mTag );
323 
324  return clone;
325  }
326 
330  virtual ~Constraint()
331  {
332  // This is not responsible for removing constraints.
333  }
334 
335 private:
336 
340  Constraint( Object& object,
341  Property::Index targetIndex,
342  SourceContainer& sources,
343  ConstraintFunctionPtr& func )
344  : ConstraintBase( object, targetIndex, sources ),
345  mTargetIndex( targetIndex ),
346  mUserFunction( func )
347  {
348  }
349 
350  // Undefined
351  Constraint( const Constraint& );
352 
353  // Undefined
354  Constraint& operator=( const Constraint& rhs );
355 
360  {
361  // Should not come here if target-object has been destroyed
362  DALI_ASSERT_DEBUG( NULL != mTargetObject );
363 
364  // Guard against double connections
366 
367  // Short-circuit until the target scene-object exists
369  if ( NULL == targetObject )
370  {
371  return;
372  }
373 
374  // Build a container of property-owners, providing the scene-graph properties
375  SceneGraph::PropertyOwnerContainer propertyOwners;
376  propertyOwners.PushBack( targetObject );
377 
378  // Build the constraint function; this requires a scene-graph property from each source
379  ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
380 
381  if ( func )
382  {
383  // Create the SceneGraphConstraint, and connect to the scene-graph
384 
386 
387  // The targetProperty should exist, when targetObject exists
388  DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
389 
390  const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
391 
392  SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
393 
394  if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
395  {
396  // Not a Vector2, Vector3 or Vector4 component, expecting float type
397  DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
398 
400 
401  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
402  propertyOwners,
403  func );
404  }
405  else
406  {
407  // Expecting Vector2, Vector3 or Vector4 type
408 
409  if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
410  {
411  // Constrain float component of Vector2 property
412 
413  if ( 0 == componentIndex )
414  {
416  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
417  }
418  else if ( 1 == componentIndex )
419  {
421  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
422  }
423  }
424  else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
425  {
426  // Constrain float component of Vector3 property
427 
428  if ( 0 == componentIndex )
429  {
431  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
432  }
433  else if ( 1 == componentIndex )
434  {
436  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
437  }
438  else if ( 2 == componentIndex )
439  {
441  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
442  }
443  }
444  else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
445  {
446  // Constrain float component of Vector4 property
447 
448  if ( 0 == componentIndex )
449  {
451  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
452  }
453  else if ( 1 == componentIndex )
454  {
456  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
457  }
458  else if ( 2 == componentIndex )
459  {
461  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
462  }
463  else if ( 3 == componentIndex )
464  {
466  sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
467  }
468  }
469  }
470 
471  DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
472  sceneGraphConstraint->SetRemoveAction( mRemoveAction );
473 
474  // object is being used in a separate thread; queue a message to apply the constraint
475  ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
476 
477  // Keep a raw-pointer to the scene-graph constraint
478  mSceneGraphConstraint = sceneGraphConstraint;
479  }
480  }
481 
489  {
490  PropertyConstraint<float>* func = mUserFunction->Clone();
491 
492  for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
493  {
494  Source& source = *iter;
495 
496  PropertyInputImpl* inputProperty( NULL );
497  int componentIndex( Property::INVALID_COMPONENT_INDEX );
498 
499  if ( OBJECT_PROPERTY == source.sourceType )
500  {
502 
503  SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
504 
505  // The property owner will not exist, if the target object is off-stage
506  if( NULL != owner )
507  {
508  AddUnique( propertyOwners, owner );
509  inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
510  componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
511 
512  // The scene-object property should exist, when the property owner exists
513  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
514  }
515  }
516  else if ( LOCAL_PROPERTY == source.sourceType )
517  {
519 
520  inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
521  componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
522 
523  // The target scene-object should provide this property
524  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
525  }
526  else
527  {
528  DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
529 
530  Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
531 
532  // This will not exist, if the target object is off-stage
533  if ( NULL != objectParent )
534  {
536 
537  SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
538 
539  // The property owner will not exist, if the parent object is off-stage
540  if ( NULL != owner )
541  {
542  AddUnique( propertyOwners, owner );
543  inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
544  componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
545 
546  // The scene-object property should exist, when the property owner exists
547  DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
548  }
549  }
550  }
551 
552  if ( NULL == inputProperty )
553  {
554  delete func;
555  func = NULL;
556 
557  // Exit if a scene-graph object is not available from one of the sources
558  break;
559  }
560 
561  func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
562  }
563 
564  return func;
565  }
566 
567 protected:
568 
570 
572 };
573 
574 } // namespace Internal
575 
576 } // namespace Dali
577 
578 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
Dali Docs Home
Read more about Dali