Merge "Fixed shader compilation error handling" into tizen
[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 char* 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, SourceContainer& sources, unsigned int sourceCount )
78 : mEventToUpdate( eventToUpdate ),
79   mTargetPropertyIndex( targetPropertyIndex ),
80   mSources( sources ),
81   mSourceCount( sourceCount ),
82   mTargetProxy( NULL ),
83   mObservedProxies(),
84   mSceneGraphConstraint( NULL ),
85   mCustomWeight( NULL ),
86   mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
87   mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
88   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
89   mTag(0),
90   mApplyAnimation()
91 {
92   // Skip init when any of the proxy objects have been destroyed
93   if ( mSources.size() != mSourceCount )
94   {
95     // Discard all proxy pointers
96     mTargetProxy = NULL;
97     mSources.clear();
98   }
99
100   // Observe the objects providing properties
101   for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
102   {
103     if ( OBJECT_PROPERTY == iter->sourceType )
104     {
105       DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
106
107       ObserveProxy( *(iter->object) );
108     }
109   }
110 }
111
112 ActiveConstraintBase::~ActiveConstraintBase()
113 {
114   StopObservation();
115
116   // Disconnect from internal animation signals
117   if ( mApplyAnimation )
118   {
119     GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
120   }
121 }
122
123 void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
124 {
125   const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
126   const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
127
128   if( sceneProperty )
129   {
130     mCustomWeight = sceneProperty;
131
132     ObserveProxy( weightObject );
133   }
134 }
135
136 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
137 {
138   DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
139
140   // No need to do anything, if the source objects are gone
141   if( mSources.size() == mSourceCount )
142   {
143     mTargetProxy = &parent;
144
145     ConnectConstraint();
146   }
147
148   if ( applyTime.durationSeconds > 0.0f )
149   {
150     DALI_ASSERT_DEBUG( !mApplyAnimation );
151
152     // Set start weight
153     SetWeight( 0.0f );
154
155     // Automatically animate (increase) the weight, until the constraint is fully applied
156     mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
157     Dali::ActiveConstraint self( this );
158     mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
159     mApplyAnimation.Play();
160
161     // Chain "Finish" to "Applied" signal
162     GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
163   }
164 }
165
166 void ActiveConstraintBase::OnParentDestroyed()
167 {
168   // Stop observing the remaining proxies
169   StopObservation();
170
171   // Discard all proxy pointers
172   mTargetProxy = NULL;
173   mSources.clear();
174 }
175
176 void ActiveConstraintBase::OnParentSceneObjectAdded()
177 {
178   if ( NULL == mSceneGraphConstraint &&
179        mTargetProxy )
180   {
181     ConnectConstraint();
182   }
183 }
184
185 void ActiveConstraintBase::OnParentSceneObjectRemoved()
186 {
187   if ( mSceneGraphConstraint )
188   {
189     // Notify base class that the scene-graph constraint is being removed
190     OnSceneObjectRemove();
191
192     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
193     mSceneGraphConstraint = NULL;
194   }
195 }
196
197 void ActiveConstraintBase::BeginRemove()
198 {
199   // Stop observing the remaining proxies
200   StopObservation();
201
202   // Discard all proxy pointers
203   mSources.clear();
204
205   const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
206
207   if ( propertyOwner &&
208        mSceneGraphConstraint )
209   {
210     // Notify base class that the scene-graph constraint is being removed
211     OnSceneObjectRemove();
212
213     // Remove from scene-graph
214     RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
215
216     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
217     mSceneGraphConstraint = NULL;
218   }
219 }
220
221 ProxyObject* ActiveConstraintBase::GetParent()
222 {
223   return mTargetProxy;
224 }
225
226 bool ActiveConstraintBase::Supports( Capability capability ) const
227 {
228   return false; // switch-off support for dynamic properties
229 }
230
231 Dali::Handle ActiveConstraintBase::GetTargetObject()
232 {
233   return Dali::Handle( mTargetProxy );
234 }
235
236 Property::Index ActiveConstraintBase::GetTargetProperty()
237 {
238   return mTargetPropertyIndex;
239 }
240
241 void ActiveConstraintBase::SetWeight( float weight )
242 {
243   if ( mSceneGraphConstraint )
244   {
245     BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
246   }
247   else
248   {
249     mOffstageWeight = weight;
250   }
251 }
252
253 float ActiveConstraintBase::GetCurrentWeight() const
254 {
255   float currentWeight( mOffstageWeight );
256
257   if ( mSceneGraphConstraint )
258   {
259     currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
260   }
261
262   return currentWeight;
263 }
264
265 ActiveConstraintSignalV2& ActiveConstraintBase::AppliedSignal()
266 {
267   return mAppliedSignal;
268 }
269
270 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
271 {
272   bool connected( true );
273   ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
274
275   if ( Dali::ActiveConstraint::SIGNAL_APPLIED == signalName )
276   {
277     constraint->AppliedSignal().Connect( tracker, functor );
278   }
279   else
280   {
281     // signalName does not match any signal
282     connected = false;
283   }
284
285   return connected;
286 }
287
288 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
289 {
290   mAlphaFunction = alphaFunc;
291 }
292
293 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
294 {
295   return mAlphaFunction;
296 }
297
298 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
299 {
300   mRemoveAction = action;
301 }
302
303 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
304 {
305   return mRemoveAction;
306 }
307
308 void ActiveConstraintBase::SetTag(const unsigned int tag)
309 {
310   mTag = tag;
311 }
312
313 unsigned int ActiveConstraintBase::GetTag() const
314 {
315   return mTag;
316 }
317
318 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
319 {
320   return DEFAULT_PROPERTY_COUNT;
321 }
322
323 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
324 {
325   indices.reserve( DEFAULT_PROPERTY_COUNT );
326
327   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
328   {
329     indices.push_back( i );
330   }
331 }
332
333 const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
334 {
335   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
336   {
337     return DEFAULT_PROPERTY_NAMES[index];
338   }
339   else
340   {
341     return NULL;
342   }
343 }
344
345 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
346 {
347   Property::Index index = Property::INVALID_INDEX;
348
349   // Only one name to compare with...
350   if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[0] ) ) // dont want to convert rhs to string
351   {
352     index = 0;
353   }
354
355   return index;
356 }
357
358 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
359 {
360   return true; // All default properties are currently writable
361 }
362
363 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
364 {
365   return true; // All default properties are currently animatable
366 }
367
368 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
369 {
370   return true; // All default properties can currently be used as a constraint input
371 }
372
373 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
374 {
375   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
376   {
377     return DEFAULT_PROPERTY_TYPES[index];
378   }
379   else
380   {
381     // Index out-of-range
382     return Property::NONE;
383   }
384 }
385
386 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
387 {
388   switch ( index )
389   {
390     case Dali::ActiveConstraint::WEIGHT:
391     {
392       SetWeight( propertyValue.Get<float>() );
393       break;
394     }
395
396     default:
397     {
398       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
399       break;
400     }
401   }
402 }
403
404 void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
405 {
406   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
407 }
408
409 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
410 {
411   Property::Value value;
412
413   switch ( index )
414   {
415     case Dali::ActiveConstraint::WEIGHT:
416     {
417       value = GetCurrentWeight();
418       break;
419     }
420
421     default:
422     {
423       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
424       break;
425     }
426   }
427
428   return value;
429 }
430
431 void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
432 {
433   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
434 }
435
436 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
437 {
438   return mSceneGraphConstraint;
439 }
440
441 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
442 {
443   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
444
445   // This method should only return a property which is part of the scene-graph
446   if ( !mSceneGraphConstraint )
447   {
448     return NULL;
449   }
450
451   return &mSceneGraphConstraint->mWeight;
452 }
453
454 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
455 {
456   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
457
458   // This method should only return a property which is part of the scene-graph
459   if ( !mSceneGraphConstraint )
460   {
461     return NULL;
462   }
463
464   return &mSceneGraphConstraint->mWeight;
465 }
466
467 void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy )
468 {
469   // Should not be getting callbacks when mSources has been cleared
470    DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
471
472   if ( NULL == mSceneGraphConstraint &&
473        mTargetProxy )
474   {
475     ConnectConstraint();
476   }
477 }
478
479 void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy )
480 {
481   // Notify base class that the scene-graph constraint is being removed
482   OnSceneObjectRemove();
483
484   if ( mSceneGraphConstraint )
485   {
486     // Preserve the previous weight
487     mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
488
489     const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
490
491     if( propertyOwner )
492     {
493       // Remove from scene-graph
494       RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
495     }
496
497     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
498     mSceneGraphConstraint = NULL;
499   }
500 }
501
502 void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy )
503 {
504   // Remove proxy pointer from observation set
505   ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
506   DALI_ASSERT_DEBUG( mObservedProxies.End() != iter );
507   mObservedProxies.Erase( iter );
508
509   // Stop observing the remaining proxies
510   StopObservation();
511
512   // Discard all proxy & scene-graph pointers
513   mSceneGraphConstraint = NULL;
514   mTargetProxy = NULL;
515   mSources.clear();
516 }
517
518 void ActiveConstraintBase::ObserveProxy( ProxyObject& proxy )
519 {
520   ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
521   if ( mObservedProxies.End() == iter )
522   {
523     proxy.AddObserver( *this );
524     mObservedProxies.PushBack( &proxy );
525   }
526 }
527
528 void ActiveConstraintBase::StopObservation()
529 {
530   const ProxyObjectIter end = mObservedProxies.End();
531   for( ProxyObjectIter iter = mObservedProxies.Begin(); iter != end; ++iter )
532   {
533     (*iter)->RemoveObserver( *this );
534   }
535
536   mObservedProxies.Clear();
537 }
538
539 void ActiveConstraintBase::FirstApplyFinished( Object* object )
540 {
541   // trust the object is correct as its set in FirstApply (in this same file)
542   ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( object );
543
544   // This is necessary when the constraint was not added to scene-graph during the animation
545   self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
546
547   // The animation is no longer needed
548   GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL );
549   self->mApplyAnimation.Reset();
550
551   // Chain "Finish" to "Applied" signal
552
553   if ( !self->mAppliedSignal.Empty() )
554   {
555     Dali::ActiveConstraint handle( self );
556     self->mAppliedSignal.Emit( handle );
557   }
558
559   // WARNING - this constraint may now have been deleted; don't do anything else here
560 }
561
562 } // namespace Internal
563
564 } // namespace Dali