Conversion to Apache 2.0 license
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / active-constraint-base.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/animation/active-constraint-base.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/animation/active-constraint.h>
23 #include <dali/public-api/object/handle.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/internal/common/event-to-update.h>
26 #include <dali/internal/event/animation/animation-impl.h>
27 #include <dali/internal/update/common/animatable-property.h>
28 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
29 #include <dali/internal/update/common/property-owner-messages.h>
30
31 using Dali::Internal::SceneGraph::AnimatableProperty;
32
33 namespace Dali
34 {
35
36 const Property::Index ActiveConstraint::WEIGHT = 0;
37
38 namespace Internal
39 {
40
41 namespace // unnamed namespace
42 {
43
44 BaseHandle Create()
45 {
46   // not directly creatable
47   return BaseHandle();
48 }
49
50 TypeRegistration mType( typeid(Dali::ActiveConstraint), typeid(Dali::Handle), Create );
51
52 SignalConnectorType signalConnector1( mType, Dali::ActiveConstraint::SIGNAL_APPLIED, &ActiveConstraintBase::DoConnectSignal );
53
54 }
55
56
57 namespace // unnamed namespace
58 {
59
60 /**
61  * We want to discourage the use of property strings (minimize string comparisons),
62  * particularly for the default properties.
63  */
64 const std::string DEFAULT_PROPERTY_NAMES[] =
65 {
66   "weight"
67 };
68 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
69
70 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
71 {
72   Property::FLOAT // WEIGHT
73 };
74
75 } // unnamed namespace
76
77 ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex )
78 : mEventToUpdate( eventToUpdate ),
79   mTargetPropertyIndex( targetPropertyIndex ),
80   mTargetProxy( NULL ),
81   mSceneGraphConstraint( NULL ),
82   mCustomWeight( NULL ),
83   mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
84   mRemoveTime( 0.0f ),
85   mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
86   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
87   mTag(0),
88   mApplyAnimation(),
89   mRemoveAnimation()
90 {
91 }
92
93 ActiveConstraintBase::~ActiveConstraintBase()
94 {
95   // Disconnect from internal animation signals
96
97   if ( mApplyAnimation )
98   {
99     GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
100   }
101
102   if( mRemoveAnimation )
103   {
104     GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL );
105   }
106 }
107
108 void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
109 {
110   const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
111   const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
112
113   if( sceneProperty )
114   {
115     mCustomWeight = sceneProperty;
116
117     OnCustomWeightSet( weightObject );
118   }
119 }
120
121 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
122 {
123   // Notify derived classes
124   OnFirstApply( parent );
125
126   if ( applyTime.durationSeconds > 0.0f )
127   {
128     DALI_ASSERT_DEBUG( !mApplyAnimation );
129
130     // Set start weight
131     SetWeight( 0.0f );
132
133     // Automatically animate (increase) the weight, until the constraint is fully applied
134     mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
135     Dali::ActiveConstraint self( this );
136     mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
137     mApplyAnimation.Play();
138
139     // Chain "Finish" to "Applied" signal
140     GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
141   }
142 }
143
144 void ActiveConstraintBase::BeginRemove()
145 {
146   // Notify derived classes
147   OnBeginRemove();
148
149   // Remove gradually by animating weight down to zero
150   if ( mRemoveTime.durationSeconds > 0.0f )
151   {
152     // Stop baking behaviour from interfering with remove animation
153     if ( mSceneGraphConstraint )
154     {
155       // Immediately remove from scene-graph
156       SetRemoveActionMessage( mEventToUpdate, *mSceneGraphConstraint, Dali::Constraint::Discard );
157     }
158
159     // Interrupt ongoing apply-animations
160     if ( mApplyAnimation )
161     {
162       mApplyAnimation.Stop();
163     }
164
165     // Reduce the weight to zero
166     mRemoveAnimation = Dali::Animation::New( mRemoveTime.delaySeconds + mRemoveTime.durationSeconds );
167     Dali::ActiveConstraint self( this );
168     mRemoveAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), 0.0f, mAlphaFunction, mRemoveTime );
169     mRemoveAnimation.Play();
170
171     // Finish removal when animation ends
172     GetImplementation(mRemoveAnimation).SetFinishedCallback( &ActiveConstraintBase::OnRemoveFinished, this );
173   }
174   else
175   {
176     OnRemoveFinished( this );
177   }
178 }
179
180 bool ActiveConstraintBase::IsRemoving()
181 {
182   return mRemoveAnimation;
183 }
184
185 ProxyObject* ActiveConstraintBase::GetParent()
186 {
187   return mTargetProxy;
188 }
189
190 bool ActiveConstraintBase::Supports( Capability capability ) const
191 {
192   return false; // switch-off support for dynamic properties
193 }
194
195 Dali::Handle ActiveConstraintBase::GetTargetObject()
196 {
197   return Dali::Handle( mTargetProxy );
198 }
199
200 Property::Index ActiveConstraintBase::GetTargetProperty()
201 {
202   return mTargetPropertyIndex;
203 }
204
205 void ActiveConstraintBase::SetWeight( float weight )
206 {
207   if ( mSceneGraphConstraint )
208   {
209     BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
210   }
211   else
212   {
213     mOffstageWeight = weight;
214   }
215 }
216
217 float ActiveConstraintBase::GetCurrentWeight() const
218 {
219   float currentWeight( mOffstageWeight );
220
221   if ( mSceneGraphConstraint )
222   {
223     currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
224   }
225
226   return currentWeight;
227 }
228
229 ActiveConstraintSignalV2& ActiveConstraintBase::AppliedSignal()
230 {
231   return mAppliedSignal;
232 }
233
234 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
235 {
236   bool connected( true );
237   ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
238
239   if ( Dali::ActiveConstraint::SIGNAL_APPLIED == signalName )
240   {
241     constraint->AppliedSignal().Connect( tracker, functor );
242   }
243   else
244   {
245     // signalName does not match any signal
246     connected = false;
247   }
248
249   return connected;
250 }
251
252 void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
253 {
254   mRemoveTime = removeTime;
255 }
256
257 TimePeriod ActiveConstraintBase::GetRemoveTime() const
258 {
259   return mRemoveTime;
260 }
261
262 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
263 {
264   mAlphaFunction = alphaFunc;
265 }
266
267 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
268 {
269   return mAlphaFunction;
270 }
271
272 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
273 {
274   mRemoveAction = action;
275 }
276
277 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
278 {
279   return mRemoveAction;
280 }
281
282 void ActiveConstraintBase::SetTag(const unsigned int tag)
283 {
284   mTag = tag;
285 }
286
287 unsigned int ActiveConstraintBase::GetTag() const
288 {
289   return mTag;
290 }
291
292
293 bool ActiveConstraintBase::IsSceneObjectRemovable() const
294 {
295   return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
296 }
297
298 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
299 {
300   return DEFAULT_PROPERTY_COUNT;
301 }
302
303 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
304 {
305   indices.reserve( DEFAULT_PROPERTY_COUNT );
306
307   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
308   {
309     indices.push_back( i );
310   }
311 }
312
313 const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
314 {
315   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
316   {
317     return DEFAULT_PROPERTY_NAMES[index];
318   }
319   else
320   {
321     // index out of range..return empty string
322     static const std::string INVALID_PROPERTY_NAME;
323     return INVALID_PROPERTY_NAME;
324   }
325 }
326
327 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
328 {
329   Property::Index index = Property::INVALID_INDEX;
330
331   // Only one name to compare with...
332   if ( name == DEFAULT_PROPERTY_NAMES[0] )
333   {
334     index = 0;
335   }
336
337   return index;
338 }
339
340 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
341 {
342   return true; // All default properties are currently writable
343 }
344
345 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
346 {
347   return true; // All default properties are currently animatable
348 }
349
350 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
351 {
352   return true; // All default properties can currently be used as a constraint input
353 }
354
355 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
356 {
357   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
358   {
359     return DEFAULT_PROPERTY_TYPES[index];
360   }
361   else
362   {
363     // Index out-of-range
364     return Property::NONE;
365   }
366 }
367
368 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
369 {
370   switch ( index )
371   {
372     case Dali::ActiveConstraint::WEIGHT:
373     {
374       SetWeight( propertyValue.Get<float>() );
375       break;
376     }
377
378     default:
379     {
380       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
381       break;
382     }
383   }
384 }
385
386 void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
387 {
388   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
389 }
390
391 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
392 {
393   Property::Value value;
394
395   switch ( index )
396   {
397     case Dali::ActiveConstraint::WEIGHT:
398     {
399       value = GetCurrentWeight();
400       break;
401     }
402
403     default:
404     {
405       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
406       break;
407     }
408   }
409
410   return value;
411 }
412
413 void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
414 {
415   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
416 }
417
418 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
419 {
420   return mSceneGraphConstraint;
421 }
422
423 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
424 {
425   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
426
427   // This method should only return a property which is part of the scene-graph
428   if ( !mSceneGraphConstraint )
429   {
430     return NULL;
431   }
432
433   return &mSceneGraphConstraint->mWeight;
434 }
435
436 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
437 {
438   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
439
440   // This method should only return a property which is part of the scene-graph
441   if ( !mSceneGraphConstraint )
442   {
443     return NULL;
444   }
445
446   return &mSceneGraphConstraint->mWeight;
447 }
448
449 void ActiveConstraintBase::FirstApplyFinished( Object* object )
450 {
451   ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
452
453   // This is necessary when the constraint was not added to scene-graph during the animation
454   self.SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
455
456   // The animation is no longer needed
457   GetImplementation(self.mApplyAnimation).SetFinishedCallback( NULL, NULL );
458   self.mApplyAnimation.Reset();
459
460   // Chain "Finish" to "Applied" signal
461
462   if ( !self.mAppliedSignal.Empty() )
463   {
464     Dali::ActiveConstraint handle( &self );
465
466     self.mAppliedSignal.Emit( handle );
467   }
468
469   // WARNING - this constraint may now have been deleted; don't do anything else here
470 }
471
472 void ActiveConstraintBase::OnRemoveFinished( Object* object )
473 {
474   ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
475
476   const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL;
477
478   if ( propertyOwner &&
479        self.mSceneGraphConstraint )
480   {
481     // Notify base class that the scene-graph constraint is being removed
482     self.OnSceneObjectRemove();
483
484     // Remove from scene-graph
485     RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) );
486
487     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
488     self.mSceneGraphConstraint = NULL;
489   }
490
491   // The animation is no longer needed
492   self.mRemoveAnimation.Reset();
493 }
494
495 } // namespace Internal
496
497 } // namespace Dali