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