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