Merge "fix ellipsis not working issue when the given width is too narrow" into devel...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-gradient / animated-gradient-visual.cpp
1 /*
2  * Copyright (c) 2018 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 //CLASS HEADER
18 #include <dali-toolkit/internal/visuals/animated-gradient/animated-gradient-visual.h>
19
20 //INTERNAL INCLUDES
21 #include <dali-toolkit/devel-api/visuals/animated-gradient-visual-properties-devel.h>
22 #include <dali-toolkit/public-api/visuals/visual-properties.h>
23 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
24 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
25 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
26 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
27 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
28 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41 DALI_ENUM_TO_STRING_TABLE_BEGIN( GRADIENT_TYPE )
42 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::GradientType, LINEAR )
43 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::GradientType, RADIAL )
44 DALI_ENUM_TO_STRING_TABLE_END( GRADIENT_TYPE )
45
46 DALI_ENUM_TO_STRING_TABLE_BEGIN( UNIT_TYPE )
47 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::UnitType, OBJECT_BOUNDING_BOX )
48 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::UnitType, USER_SPACE )
49 DALI_ENUM_TO_STRING_TABLE_END( UNIT_TYPE )
50
51 DALI_ENUM_TO_STRING_TABLE_BEGIN( SPREAD_TYPE )
52 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::SpreadType, REFLECT )
53 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::SpreadType, REPEAT )
54 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::SpreadType, CLAMP )
55 DALI_ENUM_TO_STRING_TABLE_END( SPREAD_TYPE )
56
57 DALI_ENUM_TO_STRING_TABLE_BEGIN( DIRECTION_TYPE )
58 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType, FORWARD )
59 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType, BACKWARD )
60 DALI_ENUM_TO_STRING_TABLE_END( DIRECTION_TYPE )
61
62 DALI_ENUM_TO_STRING_TABLE_BEGIN( MOTION_TYPE )
63 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType, LOOP )
64 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType, MIRROR )
65 DALI_ENUM_TO_STRING_TABLE_END( MOTION_TYPE )
66
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( EASING_TYPE )
68 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType, LINEAR )
69 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType, IN )
70 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType, OUT )
71 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType, IN_OUT )
72 DALI_ENUM_TO_STRING_TABLE_END( EASING_TYPE )
73
74 // Default values of each properties
75 const Toolkit::DevelAnimatedGradientVisual::GradientType::Type DEFAULT_GRADIENT_TYPE = Toolkit::DevelAnimatedGradientVisual::GradientType::LINEAR;
76 const Toolkit::DevelAnimatedGradientVisual::UnitType::Type     DEFAULT_UNIT_TYPE     = Toolkit::DevelAnimatedGradientVisual::UnitType::OBJECT_BOUNDING_BOX;
77 const Toolkit::DevelAnimatedGradientVisual::SpreadType::Type   DEFAULT_SPREAD_TYPE   = Toolkit::DevelAnimatedGradientVisual::SpreadType::REFLECT;
78
79 const float DEFAULT_START_POSITION[] = { -0.5f, 0.0f };
80 const float DEFAULT_START_COLOR[]    = { 143.0f/255.0f, 170.0f/255.0f, 220.0f/255.0f, 255.0f/255.0f };
81 const float DEFAULT_END_POSITION[]   = { 0.5f, 0.0f };
82 const float DEFAULT_END_COLOR[]      = { 255.0f/255.0f, 163.0f/255.0f, 163.0f/255.0f, 255.0f/255.0f };
83 const float DEFAULT_ROTATE_CENTER[]  = { 0.0f, 0.0f };
84 const float DEFAULT_ROTATE_AMOUNT    = 0.0f;
85
86 const float DEFAULT_ANIMATION_START_VALUE  = 0.0f;
87 const float DEFAULT_ANIMATION_TARGET_VALUE = 0.0f;
88 const float DEFAULT_ANIMATION_DURATION     = 3.0f;
89 const float DEFAULT_ANIMATION_DELAY        = 0.0f;
90 const int   DEFAULT_ANIMATION_REPEAT       = 0;
91 const float DEFAULT_ANIMATION_REPEAT_DELAY = 0.0f;
92
93 const Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::Type DEFAULT_ANIMATION_DIRECTION_TYPE = Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::FORWARD;
94 const Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::Type    DEFAULT_ANIMATION_MOTION_TYPE    = Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::LOOP;
95 const Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::Type    DEFAULT_ANIMATION_EASING_TYPE    = Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::LINEAR;
96
97 Property::Value GetStartValue( const Property::Map& map, Property::Index index, const char* const name )
98 {
99   // Get start value of animation parameter
100   Property::Value* res = map.Find( index, name );
101   if( res )
102   {
103     Property::Map* s_map = res->GetMap();
104     if( s_map )
105     {
106       res = s_map->Find( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::START, START_VALUE_NAME );
107       DALI_ASSERT_ALWAYS( res && "Start value is not setup in Property::Map" );
108     }
109   }
110   else
111   {
112     DALI_ASSERT_ALWAYS( !"Start value is not setup even default" );
113   }
114   return *res;
115 }
116
117 VisualFactoryCache::ShaderType GetShaderType( Toolkit::DevelAnimatedGradientVisual::GradientType::Type grad, Toolkit::DevelAnimatedGradientVisual::UnitType::Type unit, Toolkit::DevelAnimatedGradientVisual::SpreadType::Type spread )
118 {
119   return static_cast<VisualFactoryCache::ShaderType>(
120     VisualFactoryCache::ANIMATED_GRADIENT_SHADER_LINEAR_BOUNDING_REFLECT +
121     static_cast<unsigned int>( grad ) * 6 + // 6 is the number of UnitType * SpreadType
122     static_cast<unsigned int>( unit ) * 3 + // 3 is the number of SpreadType.
123     static_cast<unsigned int>( spread )
124   );
125 }
126
127 } // unnamed namespace
128
129 AnimatedGradientVisualPtr AnimatedGradientVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties )
130 {
131   AnimatedGradientVisualPtr animatedGradientVisualPtr( new AnimatedGradientVisual( factoryCache ) );
132   animatedGradientVisualPtr->SetProperties( properties );
133   return animatedGradientVisualPtr;
134 }
135
136 AnimatedGradientVisual::AnimatedGradientVisual( VisualFactoryCache& factoryCache )
137 : Visual::Base( factoryCache, Visual::FittingMode::FILL, static_cast<Toolkit::Visual::Type>( Toolkit::DevelVisual::ANIMATED_GRADIENT ) )
138 {
139   SetupDefaultValue();
140 }
141
142 AnimatedGradientVisual::~AnimatedGradientVisual()
143 {
144
145 }
146
147 void AnimatedGradientVisual::SetupDefaultValue()
148 {
149   mGradientType = DEFAULT_GRADIENT_TYPE;
150   mUnitType     = DEFAULT_UNIT_TYPE;
151   mSpreadType   = DEFAULT_SPREAD_TYPE;
152
153   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION] = Vector2( DEFAULT_START_POSITION );
154   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR]    = Vector4( DEFAULT_START_COLOR );
155   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION]   = Vector2( DEFAULT_END_POSITION );
156   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR]      = Vector4( DEFAULT_END_COLOR );
157   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER]  = Vector2( DEFAULT_ROTATE_CENTER );
158   mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT]  = DEFAULT_ROTATE_AMOUNT;
159   // Default Offset value is very special. unlimited animation from 0.0f to 2.0f
160   {
161     Property::Map map;
162     map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::START, 0.0f );
163     map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET, 2.0f );
164     map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT, -1 );
165
166     mValueMap[Toolkit::DevelAnimatedGradientVisual::Property::OFFSET] = map;
167   }
168 }
169
170 void AnimatedGradientVisual::DoSetProperties( const Property::Map& propertyMap )
171 {
172   //GRADIENT_TYPE
173   Property::Value* gradientTypeValue = propertyMap.Find( Toolkit::DevelAnimatedGradientVisual::Property::GRADIENT_TYPE, GRADIENT_TYPE_NAME );
174   Toolkit::DevelAnimatedGradientVisual::GradientType::Type gradientType = mGradientType;
175   if( gradientTypeValue )
176   {
177     Scripting::GetEnumerationProperty( *gradientTypeValue, GRADIENT_TYPE_TABLE, GRADIENT_TYPE_TABLE_COUNT, gradientType );
178   }
179
180   //UNIT_TYPE
181   Property::Value* unitTypeValue = propertyMap.Find( Toolkit::DevelAnimatedGradientVisual::Property::UNIT_TYPE, UNIT_TYPE_NAME );
182   Toolkit::DevelAnimatedGradientVisual::UnitType::Type unitType = mUnitType;
183   if( unitTypeValue )
184   {
185     Scripting::GetEnumerationProperty( *unitTypeValue, UNIT_TYPE_TABLE, UNIT_TYPE_TABLE_COUNT, unitType );
186   }
187
188   //SPREAD_TYPE
189   Property::Value* spreadTypeValue = propertyMap.Find( Toolkit::DevelAnimatedGradientVisual::Property::SPREAD_TYPE, SPREAD_TYPE_NAME );
190   Toolkit::DevelAnimatedGradientVisual::SpreadType::Type spreadType = mSpreadType;
191   if( spreadTypeValue )
192   {
193     Scripting::GetEnumerationProperty( *spreadTypeValue, SPREAD_TYPE_TABLE, SPREAD_TYPE_TABLE_COUNT, spreadType );
194   }
195
196   mGradientType = gradientType;
197   mUnitType = unitType;
198   mSpreadType = spreadType;
199
200   SetupGradientAnimationData(propertyMap);
201 }
202
203 void AnimatedGradientVisual::SetupGradientAnimationData( const Property::Map& propertyMap )
204 {
205   mGradientAnimationDataList.Clear(); // Clear Transition Information. All animation will deleted safely
206
207   static Property::Map propertyNameMap;
208   static Property::Map propertyUniformNameMap;
209   if( propertyNameMap.Empty() )
210   {
211     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION] = START_POSITION_NAME;
212     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR   ] = START_COLOR_NAME;
213     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION  ] = END_POSITION_NAME;
214     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR     ] = END_COLOR_NAME;
215     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER ] = ROTATE_CENTER_NAME;
216     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT ] = ROTATE_AMOUNT_NAME;
217     propertyNameMap[Toolkit::DevelAnimatedGradientVisual::Property::OFFSET        ] = OFFSET_NAME;
218   }
219   if( propertyUniformNameMap.Empty() )
220   {
221     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION] = UNIFORM_START_POINT_NAME;
222     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR   ] = UNIFORM_START_COLOR_NAME;
223     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION  ] = UNIFORM_END_POINT_NAME;
224     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR     ] = UNIFORM_END_COLOR_NAME;
225     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER ] = UNIFORM_ROTATE_CENTER_NAME;
226     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT ] = UNIFORM_ROTATE_ANGLE_NAME;
227     propertyUniformNameMap[Toolkit::DevelAnimatedGradientVisual::Property::OFFSET        ] = UNIFORM_OFFSET_NAME;
228   }
229
230   Property::Map::SizeType map_index_end = propertyNameMap.Count();
231   for( Property::Map::SizeType map_index = 0; map_index < map_index_end; map_index++ )
232   {
233     KeyValuePair property_pair = propertyNameMap.GetKeyValue( map_index );
234     KeyValuePair uniform_pair = propertyUniformNameMap.GetKeyValue( map_index );
235     Property::Index index = property_pair.first.indexKey;
236     const std::string property_name = property_pair.second.Get< std::string >();
237     const std::string uniform_name = uniform_pair.second.Get< std::string >();
238
239     Property::Map map;
240     Property::Value default_value = mValueMap[index];
241
242     map["target"] = "background";
243     map["property"] = uniform_name;
244
245     Property::Value *value = propertyMap.Find( index, property_name );
246     if( !value )
247     {
248       value = &default_value;
249     }
250     else
251     {
252       // Update value list
253       mValueMap[index] = (*value);
254     }
255
256     int loop_count = 0;
257     float delay = 0.0f;
258     bool forward = true;
259     bool auto_mirror = false;
260     std::string ease_str = "LINEAR";
261     Property::Map *map_value = value->GetMap();
262     if( map_value )
263     {
264       auto getValueFromMap = [ &map_value ]( const Property::Index& index, const std::string& name, Property::Value& res ) -> void
265       {
266         Property::Value *sub_value = map_value->Find( index, name );
267         if( sub_value )
268         {
269           res = *sub_value;
270         }
271       };
272
273       Property::Value value_start        = DEFAULT_ANIMATION_START_VALUE;
274       Property::Value value_target       = DEFAULT_ANIMATION_TARGET_VALUE;
275       Property::Value value_duration     = DEFAULT_ANIMATION_DURATION;
276       Property::Value value_delay        = DEFAULT_ANIMATION_DELAY;
277       Property::Value value_repeat       = DEFAULT_ANIMATION_REPEAT;
278       Property::Value value_repeat_delay = DEFAULT_ANIMATION_REPEAT_DELAY;
279
280       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::START       , START_VALUE_NAME   , value_start );
281       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET      , TARGET_VALUE_NAME  , value_target );
282       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DURATION    , DURATION_NAME      , value_duration );
283       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DELAY       , DELAY_NAME         , value_delay );
284       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT      , REPEAT_NAME        , value_repeat );
285       getValueFromMap( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT_DELAY, REPEAT_DELAY_NAME  , value_repeat_delay );
286
287       Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::Type direction_type = DEFAULT_ANIMATION_DIRECTION_TYPE;
288       Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::Type    motion_type    = DEFAULT_ANIMATION_MOTION_TYPE;
289       Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::Type    easing_type    = DEFAULT_ANIMATION_EASING_TYPE;
290
291       Property::Value *direction_sub_value = map_value->Find( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION, DIRECTION_TYPE_NAME );
292       if( direction_sub_value )
293       {
294         Scripting::GetEnumerationProperty( *direction_sub_value, DIRECTION_TYPE_TABLE, DIRECTION_TYPE_TABLE_COUNT, direction_type );
295       }
296       Property::Value *motion_sub_value = map_value->Find( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::MOTION_TYPE, MOTION_TYPE_NAME );
297       if( motion_sub_value )
298       {
299         Scripting::GetEnumerationProperty( *motion_sub_value   , MOTION_TYPE_TABLE   , MOTION_TYPE_TABLE_COUNT   , motion_type );
300       }
301       Property::Value *easing_sub_value = map_value->Find( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE, EASING_TYPE_NAME );
302       if( easing_sub_value )
303       {
304         Scripting::GetEnumerationProperty( *easing_sub_value   , EASING_TYPE_TABLE   , EASING_TYPE_TABLE_COUNT   , easing_type );
305       }
306
307       forward = ( direction_type == Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::FORWARD );
308       delay = value_delay.Get< float >();
309       loop_count = value_repeat.Get< int >();
310       auto_mirror = ( motion_type == Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::MIRROR );
311
312       switch( easing_type )
313       {
314         case Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::LINEAR:
315         {
316           ease_str = "LINEAR";
317           break;
318         }
319         case Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN:
320         {
321           ease_str = "EASE_IN_SQUARE";
322           break;
323         }
324         case Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::OUT:
325         {
326           ease_str = "EASE_OUT_SQUARE";
327           break;
328         }
329         case Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN_OUT:
330         {
331           ease_str = "EASE_IN_OUT";
332           break;
333         }
334       }
335
336       map["initialValue"] = forward ? value_start : value_target;
337       map["targetValue"] = forward ? value_target : value_start;
338       if( loop_count != 0 )
339       {
340         map["animator"] = Property::Map()
341                           .Add( "alphaFunction", ease_str )
342                           .Add( "timePeriod", Property::Map()
343                                              .Add( "delay", value_repeat_delay.Get< float >() )
344                                              .Add( "duration", value_duration.Get< float >() ) );
345       }
346     }
347     else
348     {
349       map["initialValue"] = *value;
350       map["targetValue"] = *value;
351     }
352
353     AnimatedGradientVisual::GradientAnimationData *animData = new AnimatedGradientVisual::GradientAnimationData();
354     animData->transition = Toolkit::TransitionData::New( map );
355     animData->index = index;
356     animData->loop_count = loop_count;
357     animData->delay = delay;
358     animData->forward = forward;
359     animData->auto_mirror = auto_mirror;
360     mGradientAnimationDataList.PushBack( animData );
361   }
362 }
363
364 void AnimatedGradientVisual::SetupAnimation()
365 {
366   for( auto&& elem : mGradientAnimationDataList )
367   {
368     Toolkit::TransitionData& transition = elem->transition;
369     Animation& animation = elem->animation;
370     int loop_count = elem->loop_count;
371     bool auto_mirror = elem->auto_mirror;
372     bool without_animation = ( loop_count == 0 );
373
374     const Internal::TransitionData& transitionData = Toolkit::GetImplementation( transition );
375     for( auto iter = transitionData.Begin(); iter != transitionData.End(); iter++ )
376     {
377       TransitionData::Animator *animator = (*iter);
378       AnimateProperty( animation, *animator );
379     }
380     if( animation && !without_animation )
381     {
382       if( loop_count < 0 )
383       {
384         animation.SetLooping( true );
385       }
386       else if( loop_count > 0 )
387       {
388         animation.SetLoopCount( loop_count );
389       }
390       if( auto_mirror )
391       {
392         animation.SetLoopingMode( Animation::LoopingMode::AUTO_REVERSE );
393       }
394     }
395   }
396 }
397
398 void AnimatedGradientVisual::PlayAnimation()
399 {
400   for( auto&& elem : mGradientAnimationDataList )
401   {
402     Animation& animation = elem->animation;
403     if( animation )
404     {
405       float delay = elem->delay;
406       if( delay > 0.0f )
407       {
408         animation.PlayAfter( delay );
409       }
410       else if( delay < 0.0f )
411       {
412         float progress = -delay / animation.GetDuration(); // (duration + repeat_duration)
413         if(progress >= 1.0f)
414         {
415           int cur_loop = animation.GetLoopCount();
416           int decrease_loop = floor( progress ) + 1;
417           while( decrease_loop > progress )
418           {
419             decrease_loop--;
420           }
421           progress -= decrease_loop;
422           if( cur_loop == 0 )
423           {
424             animation.PlayFrom( progress );
425           }
426           else
427           {
428             cur_loop -= decrease_loop;
429             if( cur_loop > 0 )
430             {
431               animation.SetLoopCount( cur_loop );
432               animation.PlayFrom( progress );
433             }
434             else
435             {
436               // animation done. make this animation finished safely.
437               animation.SetLoopCount( 1 );
438               animation.PlayFrom( 1.0f );
439             }
440           }
441         }
442         else
443         {
444           animation.PlayFrom( progress );
445         }
446       }
447       else
448       {
449         animation.Play();
450       }
451     }
452   }
453 }
454
455 void AnimatedGradientVisual::StopAnimation()
456 {
457   for( auto&& elem : mGradientAnimationDataList )
458   {
459     Animation& animation = elem->animation;
460     if( animation )
461     {
462       animation.Stop();
463     }
464   }
465 }
466
467 void AnimatedGradientVisual::OnSetTransform()
468 {
469   if( mImpl->mRenderer )
470   {
471     mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
472   }
473 }
474
475 void AnimatedGradientVisual::DoSetOnScene( Actor& actor )
476 {
477   InitializeRenderer();
478   actor.AddRenderer( mImpl->mRenderer );
479   SetupAnimation();
480   PlayAnimation();
481
482   ResourceReady( Toolkit::Visual::ResourceStatus::READY );
483 }
484
485 void AnimatedGradientVisual::DoSetOffScene( Actor& actor )
486 {
487   DALI_ASSERT_DEBUG( (bool)mImpl->mRenderer && "There should always be a renderer whilst on stage");
488
489   StopAnimation();
490   actor.RemoveRenderer( mImpl->mRenderer );
491   mImpl->mRenderer.Reset();
492 }
493
494 void AnimatedGradientVisual::DoCreatePropertyMap( Property::Map& map ) const
495 {
496   map.Clear();
497   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_GRADIENT );
498
499   //Create non-animated properties
500   map.Insert( Toolkit::DevelAnimatedGradientVisual::Property::GRADIENT_TYPE, static_cast<int>(mGradientType) );
501   map.Insert( Toolkit::DevelAnimatedGradientVisual::Property::UNIT_TYPE    , static_cast<int>(mUnitType) );
502   map.Insert( Toolkit::DevelAnimatedGradientVisual::Property::SPREAD_TYPE  , static_cast<int>(mSpreadType) );
503
504   //Create animated properties. Get from transition for more realistic test. Not from animation cause Animation may not setuped
505   for( auto&& elem : mGradientAnimationDataList )
506   {
507     Toolkit::TransitionData& transition = elem->transition;
508     Property::Index index = elem->index;
509     int loop_count = elem->loop_count;
510     float delay = elem->delay;
511     bool forward = elem->forward;
512     bool auto_mirror = elem->auto_mirror;
513
514     const Internal::TransitionData& transitionData = Toolkit::GetImplementation( transition );
515     for( auto iter = transitionData.Begin(); iter != transitionData.End(); iter++ )
516     {
517       TransitionData::Animator *animator = (*iter);
518       if( animator->animate )
519       {
520         //with animation
521         Property::Map animation_map;
522         Property::Value value_start = forward ? animator->initialValue : animator->targetValue;
523         Property::Value value_target = forward ? animator->targetValue : animator->initialValue;
524         Property::Value value_direction;
525         Property::Value value_duration = Property::Value( animator->timePeriodDuration );
526         Property::Value value_delay = Property::Value( delay );
527         Property::Value value_repeat = Property::Value( loop_count );
528         Property::Value value_repeat_delay = Property::Value( animator->timePeriodDelay );
529         Property::Value value_motion_type;
530         Property::Value value_easing_type;
531
532         if( forward )
533         {
534           value_direction = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::FORWARD );
535         }
536         else
537         {
538           value_direction = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::DirectionType::BACKWARD );
539         }
540         if( auto_mirror )
541         {
542           value_motion_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::MIRROR );
543         }
544         else
545         {
546           value_motion_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::MotionType::LOOP );
547         }
548         switch( animator->alphaFunction.GetBuiltinFunction() )
549         {
550           case Dali::AlphaFunction::LINEAR:
551           {
552             value_easing_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::LINEAR );
553             break;
554           }
555           case Dali::AlphaFunction::EASE_IN_SQUARE:
556           {
557             value_easing_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN );
558             break;
559           }
560           case Dali::AlphaFunction::EASE_OUT_SQUARE:
561           {
562             value_easing_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::OUT );
563             break;
564           }
565           case Dali::AlphaFunction::EASE_IN_OUT:
566           {
567             value_easing_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::IN_OUT );
568             break;
569           }
570           default:
571           {
572             value_easing_type = Property::Value( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::EasingType::LINEAR );
573           }
574         }
575
576         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::START       , value_start );
577         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::TARGET      , value_target );
578         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DIRECTION   , value_direction );
579         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DURATION    , value_duration );
580         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::DELAY       , value_delay );
581         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT      , value_repeat );
582         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::REPEAT_DELAY, value_repeat_delay );
583         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::MOTION_TYPE , value_motion_type );
584         animation_map.Insert( Toolkit::DevelAnimatedGradientVisual::AnimationParameter::Property::EASING_TYPE , value_easing_type );
585
586         map.Insert( index, animation_map );
587       }
588       else
589       {
590         //without animation
591         map.Insert( index, animator->targetValue );
592       }
593     }
594   }
595 }
596
597 void AnimatedGradientVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
598 {
599
600 }
601
602 Shader AnimatedGradientVisual::CreateShader()
603 {
604   Shader shader;
605
606   std::string tagUnit;
607   std::string tagGrad;
608   std::string tagSpread;
609   switch( mUnitType )
610   {
611     case Toolkit::DevelAnimatedGradientVisual::UnitType::OBJECT_BOUNDING_BOX:
612     {
613       tagUnit = "UNIT_TYPE_BOUNDING_BOX";
614       break;
615     }
616     case Toolkit::DevelAnimatedGradientVisual::UnitType::USER_SPACE:
617     {
618       tagUnit = "UNIT_TYPE_USER";
619       break;
620     }
621   }
622   switch( mGradientType )
623   {
624     case Toolkit::DevelAnimatedGradientVisual::GradientType::LINEAR:
625     {
626       tagGrad = "GRADIENT_TYPE_LINEAR";
627       break;
628     }
629     case Toolkit::DevelAnimatedGradientVisual::GradientType::RADIAL:
630     {
631       tagGrad = "GRADIENT_TYPE_RADIAL";
632       break;
633     }
634   }
635   switch( mSpreadType )
636   {
637     case Toolkit::DevelAnimatedGradientVisual::SpreadType::REFLECT:
638     {
639       tagSpread = "SPREAD_TYPE_REFLECT";
640       break;
641     }
642     case Toolkit::DevelAnimatedGradientVisual::SpreadType::REPEAT:
643     {
644       tagSpread = "SPREAD_TYPE_REPEAT";
645       break;
646     }
647     case Toolkit::DevelAnimatedGradientVisual::SpreadType::CLAMP:
648     {
649       tagSpread = "SPREAD_TYPE_CLAMP";
650       break;
651     }
652   }
653
654   std::string vert;
655   std::string frag;
656
657   vert = "#define " + tagUnit + "\n"
658        + SHADER_ANIMATED_GRADIENT_VISUAL_SHADER_VERT.data();
659   frag = "#define " + tagGrad + "\n"
660        + "#define " + tagSpread + "\n"
661        + SHADER_ANIMATED_GRADIENT_VISUAL_SHADER_FRAG.data();
662
663   shader = Shader::New( vert, frag );
664   return shader;
665 }
666
667 void AnimatedGradientVisual::InitializeRenderer()
668 {
669   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
670   VisualFactoryCache::ShaderType shaderType = GetShaderType( mGradientType, mUnitType, mSpreadType );
671   Shader shader = mFactoryCache.GetShader( shaderType );
672   if( !shader )
673   {
674     shader = CreateShader();
675     mFactoryCache.SaveShader( shaderType, shader );
676   }
677
678   mImpl->mRenderer = Renderer::New( geometry, shader );
679
680   mImpl->mRenderer.RegisterProperty( UNIFORM_START_POINT_NAME  , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::START_POSITION, START_POSITION_NAME ) );
681   mImpl->mRenderer.RegisterProperty( UNIFORM_START_COLOR_NAME  , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::START_COLOR   , START_COLOR_NAME ) );
682   mImpl->mRenderer.RegisterProperty( UNIFORM_END_POINT_NAME    , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::END_POSITION  , END_POSITION_NAME ) );
683   mImpl->mRenderer.RegisterProperty( UNIFORM_END_COLOR_NAME    , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::END_COLOR     , END_COLOR_NAME ) );
684   mImpl->mRenderer.RegisterProperty( UNIFORM_ROTATE_CENTER_NAME, GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_CENTER , ROTATE_CENTER_NAME ) );
685   mImpl->mRenderer.RegisterProperty( UNIFORM_ROTATE_ANGLE_NAME , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::ROTATE_AMOUNT , ROTATE_AMOUNT_NAME ) );
686   mImpl->mRenderer.RegisterProperty( UNIFORM_OFFSET_NAME       , GetStartValue( mValueMap, Toolkit::DevelAnimatedGradientVisual::Property::OFFSET        , OFFSET_NAME ) );
687
688   //Register transform properties
689   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
690 }
691
692 }//namespace Internal
693
694 }//namespace Toolkit
695
696 }//namespace Dali