bda70a4bd450f79055d527aaf83da99882a406db
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / transition-data-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/visuals/transition-data-impl.h>
20
21 // EXTERNAL HEADERS
22 #include <dali/dali.h>
23 #include <dali/devel-api/scripting/enum-helper.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali-toolkit/public-api/controls/control.h>
26 #include <dali-toolkit/public-api/controls/control-impl.h>
27 #include <sstream>
28
29 using namespace Dali;
30
31 namespace
32 {
33 const char* TOKEN_TARGET("target");
34 const char* TOKEN_PROPERTY("property");
35 const char* TOKEN_INITIAL_VALUE("initialValue");
36 const char* TOKEN_TARGET_VALUE("targetValue");
37 const char* TOKEN_ANIMATOR("animator");
38 const char* TOKEN_TIME_PERIOD("timePeriod");
39 const char* TOKEN_DURATION("duration");
40 const char* TOKEN_DELAY("delay");
41 const char* TOKEN_ALPHA_FUNCTION("alphaFunction");
42
43
44 DALI_ENUM_TO_STRING_TABLE_BEGIN( ALPHA_FUNCTION_BUILTIN )
45 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, LINEAR)
46 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, REVERSE)
47 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_IN)
48 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_OUT)
49 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_IN_OUT)
50 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_IN_SQUARE)
51 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_OUT_SQUARE)
52 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_IN_SINE)
53 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_OUT_SINE)
54 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_IN_OUT_SINE)
55 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, EASE_OUT_BACK)
56 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, BOUNCE)
57 DALI_ENUM_TO_STRING_WITH_SCOPE(AlphaFunction, SIN)
58 DALI_ENUM_TO_STRING_TABLE_END( ALPHA_FUNCTION_BUILTIN )
59 }
60
61 namespace Dali
62 {
63 namespace Toolkit
64 {
65 namespace Internal
66 {
67
68 namespace
69 {
70
71 /// Parses a Property::Array and sets up the animator appropriately
72 void ParseArray(TransitionData::Animator* animator, const Property::Array* array)
73 {
74   bool valid = true;
75   Vector4 controlPoints;
76   if( array && array->Count() >= 4 )
77   {
78     for( size_t vecIdx = 0; vecIdx < 4; ++vecIdx )
79     {
80       const Property::Value& v = array->GetElementAt(vecIdx);
81       if( v.GetType() == Property::FLOAT )
82       {
83         controlPoints[vecIdx] = v.Get<float>();
84       }
85       else
86       {
87         valid = false;
88         break;
89       }
90     }
91   }
92   else
93   {
94     valid = false;
95   }
96
97   if( valid )
98   {
99     Vector2 controlPoint1( controlPoints.x, controlPoints.y );
100     Vector2 controlPoint2( controlPoints.z, controlPoints.w );
101     animator->alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
102   }
103   else
104   {
105     animator->animate = false;
106   }
107 }
108
109 /// Parses a string value and sets up the animator appropriately
110 void ParseString(TransitionData::Animator* animator, std::string alphaFunctionValue)
111 {
112   if( alphaFunctionValue == "LINEAR" )
113   {
114     animator->alphaFunction = AlphaFunction(AlphaFunction::LINEAR);
115   }
116   else if( ! alphaFunctionValue.compare(0, 5, "EASE_" ) )
117   {
118     if( alphaFunctionValue == "EASE_IN" )
119     {
120       animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN);
121     }
122     else if( alphaFunctionValue == "EASE_OUT" )
123     {
124       animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT);
125     }
126     else if( ! alphaFunctionValue.compare( 5, 3, "IN_" ) )
127     {
128       if( ! alphaFunctionValue.compare(8, -1, "SQUARE" ))
129       {
130         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
131       }
132       else if( ! alphaFunctionValue.compare(8, -1, "OUT" ))
133       {
134         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT);
135       }
136       else if( ! alphaFunctionValue.compare(8, -1, "OUT_SINE" ))
137       {
138         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
139       }
140       else if( ! alphaFunctionValue.compare(8, -1, "SINE" ))
141       {
142         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SINE);
143       }
144     }
145     else if( ! alphaFunctionValue.compare( 5, 4, "OUT_" ) )
146     {
147       if( ! alphaFunctionValue.compare(9, -1, "SQUARE" ) )
148       {
149         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
150       }
151       else if( ! alphaFunctionValue.compare(9, -1, "SINE" ) )
152       {
153         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
154       }
155       else if( ! alphaFunctionValue.compare(9, -1, "BACK" ) )
156       {
157         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
158       }
159     }
160   }
161   else if( alphaFunctionValue == "REVERSE" )
162   {
163     animator->alphaFunction = AlphaFunction(AlphaFunction::REVERSE);
164   }
165   else if( alphaFunctionValue == "BOUNCE" )
166   {
167     animator->alphaFunction = AlphaFunction(AlphaFunction::BOUNCE);
168   }
169   else if( alphaFunctionValue == "SIN" )
170   {
171     animator->alphaFunction = AlphaFunction(AlphaFunction::SIN);
172   }
173 }
174 } // unnamed namespace
175
176 TransitionData::TransitionData()
177 {
178 }
179
180 TransitionData::~TransitionData()
181 {
182 }
183
184 TransitionDataPtr TransitionData::New( const Property::Array& value )
185 {
186   TransitionDataPtr transitionData( new TransitionData() );
187   transitionData->Initialize(value);
188   return transitionData;
189 }
190
191 TransitionDataPtr TransitionData::New( const Property::Map& value )
192 {
193   TransitionDataPtr transitionData( new TransitionData() );
194   transitionData->Initialize(value);
195   return transitionData;
196 }
197
198
199 void TransitionData::Initialize( const Property::Map& map )
200 {
201   TransitionData::Animator* animator = ConvertMap( map );
202   Add( animator );
203 }
204
205 void TransitionData::Initialize( const Property::Array& array )
206 {
207   for( unsigned int arrayIdx = 0, transitionArrayCount = array.Count(); arrayIdx < transitionArrayCount; ++arrayIdx )
208   {
209     const Property::Value& element = array.GetElementAt( arrayIdx );
210     // Expect each child to be an object representing an animator:
211
212     const Property::Map* map = element.GetMap();
213     if( map != NULL )
214     {
215       TransitionData::Animator* animator = ConvertMap( *map );
216       Add( animator );
217     }
218   }
219 }
220
221 TransitionData::Animator* TransitionData::ConvertMap( const Property::Map& map)
222 {
223   TransitionData::Animator* animator = new TransitionData::Animator();
224   animator->alphaFunction = AlphaFunction::LINEAR;
225   animator->timePeriodDelay = 0.0f;
226   animator->timePeriodDuration = 1.0f;
227
228   for( unsigned int mapIdx = 0; mapIdx < map.Count(); ++mapIdx )
229   {
230     const KeyValuePair pair( map.GetKeyValue( mapIdx ) );
231     if( pair.first.type == Property::Key::INDEX )
232     {
233       continue; // We don't consider index keys.
234     }
235
236     const std::string& key( pair.first.stringKey );
237     const Property::Value& value( pair.second );
238
239     if( key == TOKEN_TARGET )
240     {
241       animator->objectName = value.Get< std::string >();
242     }
243     else if( key == TOKEN_PROPERTY )
244     {
245       if( value.GetType() == Property::STRING )
246       {
247         animator->propertyKey = Property::Key( value.Get<std::string>() );
248       }
249       else
250       {
251         animator->propertyKey = Property::Key( value.Get<int>() );
252       }
253     }
254     else if( key == TOKEN_INITIAL_VALUE )
255     {
256       animator->initialValue = value;
257     }
258     else if( key == TOKEN_TARGET_VALUE )
259     {
260       animator->targetValue = value;
261     }
262     else if( key == TOKEN_ANIMATOR )
263     {
264       animator->animate = true;
265       Property::Map animatorMap = value.Get< Property::Map >();
266       for( size_t animatorMapIdx = 0; animatorMapIdx < animatorMap.Count(); ++animatorMapIdx )
267       {
268         const KeyValuePair pair( animatorMap.GetKeyValue( animatorMapIdx ) );
269
270         if( pair.first.type == Property::Key::INDEX )
271         {
272           continue; // We don't consider index keys.
273         }
274
275         const std::string& key( pair.first.stringKey );
276         const Property::Value& value( pair.second );
277
278         if( key == TOKEN_ALPHA_FUNCTION )
279         {
280           if( value.GetType() == Property::ARRAY )
281           {
282             ParseArray(animator, value.GetArray());
283           }
284           else if( value.GetType() == Property::VECTOR4 )
285           {
286             Vector4 controlPoints = value.Get<Vector4>();
287             Vector2 controlPoint1( controlPoints.x, controlPoints.y );
288             Vector2 controlPoint2( controlPoints.z, controlPoints.w );
289             animator->alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
290           }
291           else if( value.GetType() == Property::STRING )
292           {
293             ParseString(animator, value.Get< std::string >());
294           }
295           else
296           {
297             animator->animate = false;
298           }
299         }
300         else if( key == TOKEN_TIME_PERIOD )
301         {
302           Property::Map timeMap = value.Get< Property::Map >();
303           for( size_t timeMapIdx = 0; timeMapIdx < timeMap.Count(); ++timeMapIdx )
304           {
305             const KeyValuePair pair( timeMap.GetKeyValue( timeMapIdx ) );
306             if( pair.first.type == Property::Key::INDEX )
307             {
308               continue;
309             }
310             const std::string& key( pair.first.stringKey );
311
312             if( key == TOKEN_DELAY )
313             {
314               animator->timePeriodDelay = pair.second.Get< float >();
315             }
316             else if( key == TOKEN_DURATION )
317             {
318               animator->timePeriodDuration = pair.second.Get< float >();
319             }
320           }
321         }
322       }
323     }
324   }
325   return animator;
326 }
327
328 void TransitionData::Add( Animator* animator )
329 {
330   mAnimators.PushBack( animator );
331 }
332
333 TransitionData::Iterator TransitionData::Begin() const
334 {
335   return mAnimators.Begin();
336 }
337
338 TransitionData::Iterator TransitionData::End() const
339 {
340   return mAnimators.End();
341 }
342
343 size_t TransitionData::Count() const
344 {
345   return mAnimators.Count();
346 }
347
348 Property::Map TransitionData::GetAnimatorAt( size_t index )
349 {
350   DALI_ASSERT_ALWAYS( index < Count() && "index exceeds bounds" );
351
352   Animator* animator = mAnimators[index];
353   Property::Map map;
354   map[TOKEN_TARGET] = animator->objectName;
355   if( animator->propertyKey.type == Property::Key::INDEX )
356   {
357     map[TOKEN_PROPERTY] = animator->propertyKey.indexKey;
358   }
359   else
360   {
361     map[TOKEN_PROPERTY] = animator->propertyKey.stringKey;
362   }
363   if( animator->initialValue.GetType() != Property::NONE )
364   {
365     map[TOKEN_INITIAL_VALUE] = animator->initialValue;
366   }
367   if( animator->targetValue.GetType() != Property::NONE )
368   {
369     map[TOKEN_TARGET_VALUE] = animator->targetValue;
370   }
371   if( animator->animate )
372   {
373     Property::Map animateMap;
374
375     if( animator->alphaFunction.GetMode() == AlphaFunction::BUILTIN_FUNCTION )
376     {
377       animateMap.Add(TOKEN_ALPHA_FUNCTION, GetEnumerationName( animator->alphaFunction.GetBuiltinFunction(),
378                                                                ALPHA_FUNCTION_BUILTIN_TABLE,
379                                                                ALPHA_FUNCTION_BUILTIN_TABLE_COUNT ));
380     }
381     else if( animator->alphaFunction.GetMode() == AlphaFunction::BEZIER )
382     {
383       Vector4 controlPoints = animator->alphaFunction.GetBezierControlPoints();
384       animateMap.Add( TOKEN_ALPHA_FUNCTION, controlPoints );
385     }
386     animateMap.Add(TOKEN_TIME_PERIOD, Property::Map()
387                    .Add( TOKEN_DELAY, animator->timePeriodDelay )
388                    .Add( TOKEN_DURATION, animator->timePeriodDuration ));
389
390     map[TOKEN_ANIMATOR] = animateMap;
391   }
392
393   return map;
394 }
395
396 } // namespace Internal
397 } // namespace Toolkit
398 } // namespace Dali