Merge "Use Control's own PanGestureDetector in ScrollBar" into devel/master
[platform/core/uifw/dali-toolkit.git] / docs / content / programming-guide / constraints.h
1 /*! \page constraints Constraints
2  *
3
4 <h1 class="pg">Introduction</h1>
5
6 Constraints are used to modify the property of an actor, based on other properties of the same actor; properties of the actor's parent; or properties of another actor altogether, when the modification needs to be at run-time.
7 Custom functions or functors can be supplied, where the desired value of the property can be calculated.
8 These functions (or functors) are called in every frame so should be fast and not too complex otherwise it will hit performance.
9
10 Multiple constraints can be applied to the same actor at the same time.
11 The order in which constraints are applied is important as this is the order in which they are processed in the update thread.
12
13 Constraints are applied after animations have been applied.
14 This means that Constraints override the values set by Animations.
15
16 Not all properties can be used as a constraint input, please see Dali::Handle::IsPropertyAConstraintInput() for more details.
17
18 <h1 class="pg">When to use a Constraint</h1>
19
20 Constraints are designed as a way of modifying properties that cannot be modified by any existing built in functionality; Like Animations, Size negotiation or Parent anchor, origin settings.
21 As they provide the ability for the application developer to execute their own code within the update thread, DALi can no-longer guarantee the timeliness of this code, or how optimised it may be.
22
23 Generally, you should not use constraints with the SIZE property as constraining the size and size negotiation are mutually exclusive.
24 Consider the following use cases as an example of when and when not to use a constraint:
25
26 <table>
27   <tr>
28     <td><b>Requirement:</b></td>
29     <td><b>Desired Solution:</b></td>
30   </tr>
31   <tr>
32     <td>Need a child to be 50% the size of it's parent.</td>
33     <td>Use Size negotiation.</td>
34   </tr>
35   <tr>
36     <td>Need to zoom an actor in to the screen via it's scale property.</td>
37     <td>Use an Animation.</td>
38   </tr>
39   <tr>
40     <td>Need an actor to appear centered around the bottom-right corner of it's parent.</td>
41     <td>Use ParentOrigin & AnchorPoint.</td>
42   </tr>
43   <tr>
44     <td>Need to lay out a series of controls with various alignment requirements.</td>
45     <td>Use either Anchor & origin settings, or a TableView.</td>
46   </tr>
47   <tr>
48     <td>Need to automatically modify the position property of one actor based on the position property of another actor, that is neither a parent OR a child.</td>
49     <td>Use a Constraint.</td>
50   </tr>
51   <tr>
52     <td>Need to position an actor relative to it's parent actor in a NON-UNIFORM way, IE. a non-linear calculation needs to be performed that requires a functor.</td>
53     <td>Use a Constraint.</td>
54   </tr>
55   <tr>
56     <td>Need to modify an actor's property in real time based on some calculations that require additional data to be stored in-between frames.</td>
57     <td>Use a Constraint. The constraint functor can hold any variables within it that need to be preserved frame-to-frame.</td>
58   </tr>
59 </table>
60
61 For most general cases, the position and size requirements of a child or parent actor (from it's child or parent) can be calculated with Size Negotiation.
62
63 <h1 class="pg">Constraint Sources</h1>
64
65 These are properties of this (or another actor) that are used as inputs into the constraint.
66 The constraint will take these values, optionally perform a calculation on them (if using a custom functor) and write the result to the specified property of the target actor.
67 The source actor is specified as either the same actor, it's parent or another actor.
68
69 <h2 class="pg">Local Source</h2>
70
71 A local source is based on the local properties (i.e. size, position, scale, orientation, color) of an actor.
72 For example, the actor's orientation could be used as a constraint input source.
73
74 @code
75 Dali::ConstraintSource source( Dali::LocalSource( Dali::Actor::Property::ORIENTATION ) );
76 @endcode
77
78 <h2 class="pg">Parent Source</h2>
79
80 A parent source is based on properties of the actor's parent.
81 For example, a parent's position can be used as a constraint input source.
82
83 @code
84 Dali::ConstraintSource source( Dali::ParentSource( Dali::Actor::Property::POSITION ) );
85 @endcode
86
87 <h2 class="pg">Source</h2>
88
89 Finally, you can base your source on the properties of another handle altogether.
90 For example, a sibling actor's color could be used as a constraint input source.
91
92 @code
93 Dali::ConstraintSource source( Dali::Source( anotherHandle, Dali::Actor::Property::COLOR ) );
94 @endcode
95
96 <h1 class="pg">The Constraint Function</h1>
97
98 The signature of the constraint function is:
99
100 @code
101 void Function( PropertyType& current, const Dali::PropertyInputContainer& inputs );
102 @endcode
103
104 Here 'current' is a reference to the target property type, e.g. float, Vector2, Vector3 etc.
105 This is an in/out parameter.
106 It represents the current value of the property and the expectation is that it will be modified by the function to the desired value.
107
108 The 'inputs' parameter holds all the constraint input sources.
109 Each element is a pointer to the property-input and can be accessed using the indexing operator[].
110 The order in which the sources are added is the order in which the property-inputs are sorted in the container. For example:
111
112 @code
113 constraint.AddSource( Dali::LocalSource( Dali::Actor::Property::POSITION ) );
114 constraint.AddSource( Dali::LocalSource( Dali::Actor::Property::SIZE ) );
115 constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::POSITION ) );
116 constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) );
117 @endcode
118
119 In the constraint function this equates to:
120 @code
121 const Dali::Vector3& position( inputs[0]->GetVector3() );
122 const Dali::Vector3& size( inputs[1]->GetVector3() );
123 const Dali::Vector3& parentPosition( inputs[2]->GetVector3() );
124 const Dali::Vector3& parentSize( inputs[3]->GetVector3() );
125 @endcode
126
127 <h1 class="pg">Creating a Constraint</h1>
128
129 <h2 class="pg">Using C Functions</h2>
130
131 If you do not have any data that is changed at runtime, then C functions should be used.
132 For example, the color of an actor could be changed based on its position along the x-axis till a preset distance of 100, beyond which it is transparent.
133
134 @code
135 Dali::Actor actor = Actor::New();
136
137 Dali::Constraint constraint = Dali::Constraint::New< Vector4 >( actor, Dali::Actor::Property::COLOR, MyConstraintFunction ); // Creates a constraint that targets actor
138 constraint.AddSource( Dali::LocalSource( Dali::Actor::Property::POSITION ) ); // Adds the POSITION property as a constraint input
139 constraint.Apply(); // The constraint is applied
140 @endcode
141
142 And the actual C Function:
143
144 @code
145 void MyConstraintFunction( Dali::Vector4& current, const Dali::PropertyInputContainer& inputs )
146 {
147   const Dali::Vector3& position( inputs[0]->GetVector3() );
148
149   float distance = fabs( position.x );
150
151   // More than 100.0f away, opacity is 0.0f
152   if ( distance > 100.0f )
153   {
154     current.a = 0.0f;
155   }
156   else
157   {
158     // Otherwise it will blend between fully opaque and transparent
159     current.a = ( 100.0f - distance ) / 100.0f;
160   }
161 }
162 @endcode
163
164 Please have a look at Dali::Constraint::New() for more details.
165
166 <h2 class="pg">Using Functors</h2>
167
168 If you need to store some data in a struct/class, then a functor can be used.
169 Reusing the last example, the color of an actor is changed based on its position along the x-axis, but the distance when it is transparent is different for each applied constraint.
170
171 @code
172 Dali::Actor actor = Actor::New();
173
174 Dali::Constraint constraint = Dali::Constraint::New< Vector4 >( actor, Dali::Actor::Property::COLOR, MyFunctor( 200 ) ); // Creates a constraint that targets actor, and uses MyFunctor with a distance of 200
175 constraint.AddSource( Dali::LocalSource( Dali::Actor::Property::POSITION ) ); // Adds the POSITION property as a constraint input
176 constraint.Apply(); // The constraint is applied
177 @endcode
178
179 And the struct:
180
181 @code
182 struct MyFunctor
183 {
184   /// Constructor which takes the distance at which the actor will be fully transparent
185   MyFunctor( float distance )
186   : mDistance( distance )
187   {
188   }
189
190   /// Functor
191   void operator()( Dali::Vector4& current, const Dali::PropertyInputContainer& inputs )
192   {
193     const Dali::Vector3& position( inputs[0]->GetVector3() );
194
195     float distance = fabs( position.x );
196
197     // More than mDistance away, opacity is 0.0f
198     if ( distance > mDistance )
199     {
200       current.a = 0.0f;
201     }
202     else
203     {
204       // Otherwise it will blend between fully opaque and transparent
205       current.a = ( 100.0f - mDistance ) / 100.0f;
206     }
207   }
208
209   // Data
210   const float mDistance;
211 };
212 @endcode
213
214 MyFunctor could then be used with another constraint with a different distance.
215
216 Please have a look at Dali::Constraint::New(Handle, Property::Index, const T&) for more details.
217
218 Instead of using the default functor, another method can be declared in the class or struct and used as the constraint function.
219 Please have a look at the appropriate Dali::Constraint::New() method for more details.
220
221 <h1 class="pg">Removing Constraints</h1>
222
223 The actor's constraints can later be removed in several ways:
224
225 @code
226 mConstraint.Remove(); // mConstraint is a base-handle to a constraint
227 actor.RemoveConstraints(); // Removes ALL constraints applied to an actor
228 actor.RemoveConstraint( tag ); // All constraints with the tag are removed from the actor (tag can be set using SetTag)
229 @endcode
230
231 \section constraints-equal-to Equal To Constraint
232
233 The built in Dali::EqualToConstraint can be used if all that is required is setting a property equal to another property:
234 @code
235 Dali::Constraint constraint = Dali::Constraint::New< Vector3 >( actor, Dali::Actor::Property::POSITION, Dali::EqualToConstraint() );
236 constraint.AddSource( Dali::Source( anotherActor, Dali::Actor::Property::POSITION ) );
237 constraint.Apply();
238 @endcode
239 Here actor's position is set to equal the position of anotherActor.
240
241 \section constraints-relative-to Relative To Constraint
242
243 The built in Dali::RelativeToConstraint and Dali::RelativeToConstraintFloat can be used if all that is required is setting a property relative to another property:
244 @code
245 Dali::Constraint constraint = Dali::Constraint::New< Vector3 >( actor, Dali::Actor::Property::POSITION, Dali::RelativeToConstraint( 2.0f ) );
246 constraint.AddSource( Dali::Source( anotherActor, Dali::Actor::Property::POSITION ) );
247 constraint.Apply();
248 @endcode
249 Here actor's position is relative to the position of anotherActor, i.e., if anotherActor is at (10.0f, 20.0f, 30.0f), actor will be at (20.0f, 40.0f, 60.0f).
250 *
251 */