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