[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / transition-data-impl.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
18 // CLASS HEADER
19 #include <dali-toolkit/internal/visuals/transition-data-impl.h>
20
21 // EXTERNAL HEADERS
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24 #include <dali/dali.h>
25 #include <dali/devel-api/scripting/enum-helper.h>
26 #include <dali/integration-api/debug.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 const char* TOKEN_ANIMATION_TYPE("animationType");
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 } // namespace
60
61 namespace Dali
62 {
63 namespace Toolkit
64 {
65 namespace Internal
66 {
67 namespace
68 {
69 /// Parses a Property::Array and sets up the animator appropriately
70 void ParseArray(TransitionData::Animator* animator, const Property::Array* array)
71 {
72   bool    valid = true;
73   Vector4 controlPoints;
74   if(array && array->Count() >= 4)
75   {
76     for(size_t vecIdx = 0; vecIdx < 4; ++vecIdx)
77     {
78       const Property::Value& v = array->GetElementAt(vecIdx);
79       if(v.GetType() == Property::FLOAT)
80       {
81         controlPoints[vecIdx] = v.Get<float>();
82       }
83       else
84       {
85         valid = false;
86         break;
87       }
88     }
89   }
90   else
91   {
92     valid = false;
93   }
94
95   if(valid)
96   {
97     Vector2 controlPoint1(controlPoints.x, controlPoints.y);
98     Vector2 controlPoint2(controlPoints.z, controlPoints.w);
99     animator->alphaFunction = AlphaFunction(controlPoint1, controlPoint2);
100   }
101   else
102   {
103     animator->animate = false;
104   }
105 }
106
107 /// Parses a string value and sets up the animator appropriately
108 void ParseString(TransitionData::Animator* animator, std::string alphaFunctionValue)
109 {
110   if(alphaFunctionValue == "LINEAR")
111   {
112     animator->alphaFunction = AlphaFunction(AlphaFunction::LINEAR);
113   }
114   else if(!alphaFunctionValue.compare(0, 5, "EASE_"))
115   {
116     if(alphaFunctionValue == "EASE_IN")
117     {
118       animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN);
119     }
120     else if(alphaFunctionValue == "EASE_OUT")
121     {
122       animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT);
123     }
124     else if(!alphaFunctionValue.compare(5, 3, "IN_"))
125     {
126       if(!alphaFunctionValue.compare(8, -1, "SQUARE"))
127       {
128         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
129       }
130       else if(!alphaFunctionValue.compare(8, -1, "OUT"))
131       {
132         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT);
133       }
134       else if(!alphaFunctionValue.compare(8, -1, "OUT_SINE"))
135       {
136         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
137       }
138       else if(!alphaFunctionValue.compare(8, -1, "SINE"))
139       {
140         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SINE);
141       }
142     }
143     else if(!alphaFunctionValue.compare(5, 4, "OUT_"))
144     {
145       if(!alphaFunctionValue.compare(9, -1, "SQUARE"))
146       {
147         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
148       }
149       else if(!alphaFunctionValue.compare(9, -1, "SINE"))
150       {
151         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
152       }
153       else if(!alphaFunctionValue.compare(9, -1, "BACK"))
154       {
155         animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
156       }
157     }
158   }
159   else if(alphaFunctionValue == "REVERSE")
160   {
161     animator->alphaFunction = AlphaFunction(AlphaFunction::REVERSE);
162   }
163   else if(alphaFunctionValue == "BOUNCE")
164   {
165     animator->alphaFunction = AlphaFunction(AlphaFunction::BOUNCE);
166   }
167   else if(alphaFunctionValue == "SIN")
168   {
169     animator->alphaFunction = AlphaFunction(AlphaFunction::SIN);
170   }
171 }
172 } // unnamed namespace
173
174 TransitionData::TransitionData()
175 {
176 }
177
178 TransitionData::~TransitionData()
179 {
180 }
181
182 TransitionDataPtr TransitionData::New(const Property::Array& value)
183 {
184   TransitionDataPtr transitionData(new TransitionData());
185   transitionData->Initialize(value);
186   return transitionData;
187 }
188
189 TransitionDataPtr TransitionData::New(const Property::Map& value)
190 {
191   TransitionDataPtr transitionData(new TransitionData());
192   transitionData->Initialize(value);
193   return transitionData;
194 }
195
196 void TransitionData::Initialize(const Property::Map& map)
197 {
198   TransitionData::Animator* animator = ConvertMap(map);
199   Add(animator);
200 }
201
202 void TransitionData::Initialize(const Property::Array& array)
203 {
204   for(unsigned int arrayIdx = 0, transitionArrayCount = array.Count(); arrayIdx < transitionArrayCount; ++arrayIdx)
205   {
206     const Property::Value& element = array.GetElementAt(arrayIdx);
207     // Expect each child to be an object representing an animator:
208
209     const Property::Map* map = element.GetMap();
210     if(map != NULL)
211     {
212       TransitionData::Animator* animator = ConvertMap(*map);
213       Add(animator);
214     }
215   }
216 }
217
218 TransitionData::Animator* TransitionData::ConvertMap(const Property::Map& map)
219 {
220   TransitionData::Animator* animator = new TransitionData::Animator();
221   animator->alphaFunction            = AlphaFunction::LINEAR;
222   animator->timePeriodDelay          = 0.0f;
223   animator->timePeriodDuration       = 1.0f;
224
225   for(unsigned int mapIdx = 0; mapIdx < map.Count(); ++mapIdx)
226   {
227     const KeyValuePair pair(map.GetKeyValue(mapIdx));
228     if(pair.first.type == Property::Key::INDEX)
229     {
230       continue; // We don't consider index keys.
231     }
232
233     const std::string&     key(pair.first.stringKey);
234     const Property::Value& value(pair.second);
235
236     if(key == TOKEN_TARGET)
237     {
238       animator->objectName = value.Get<std::string>();
239     }
240     else if(key == TOKEN_PROPERTY)
241     {
242       if(value.GetType() == Property::STRING)
243       {
244         animator->propertyKey = Property::Key(value.Get<std::string>());
245       }
246       else
247       {
248         animator->propertyKey = Property::Key(value.Get<int>());
249       }
250     }
251     else if(key == TOKEN_INITIAL_VALUE)
252     {
253       animator->initialValue = value;
254     }
255     else if(key == TOKEN_TARGET_VALUE)
256     {
257       animator->targetValue = value;
258     }
259     else if(key == TOKEN_ANIMATOR)
260     {
261       animator->animate         = true;
262       Property::Map animatorMap = value.Get<Property::Map>();
263       for(size_t animatorMapIdx = 0; animatorMapIdx < animatorMap.Count(); ++animatorMapIdx)
264       {
265         const KeyValuePair pair(animatorMap.GetKeyValue(animatorMapIdx));
266
267         if(pair.first.type == Property::Key::INDEX)
268         {
269           continue; // We don't consider index keys.
270         }
271
272         const std::string&     key(pair.first.stringKey);
273         const Property::Value& value(pair.second);
274
275         if(key == TOKEN_ALPHA_FUNCTION)
276         {
277           if(value.GetType() == Property::ARRAY)
278           {
279             ParseArray(animator, value.GetArray());
280           }
281           else if(value.GetType() == Property::VECTOR4)
282           {
283             Vector4 controlPoints = value.Get<Vector4>();
284             Vector2 controlPoint1(controlPoints.x, controlPoints.y);
285             Vector2 controlPoint2(controlPoints.z, controlPoints.w);
286             animator->alphaFunction = AlphaFunction(controlPoint1, controlPoint2);
287           }
288           else if(value.GetType() == Property::STRING)
289           {
290             ParseString(animator, value.Get<std::string>());
291           }
292           else
293           {
294             animator->animate = false;
295           }
296         }
297         else if(key == TOKEN_TIME_PERIOD)
298         {
299           Property::Map timeMap = value.Get<Property::Map>();
300           for(size_t timeMapIdx = 0; timeMapIdx < timeMap.Count(); ++timeMapIdx)
301           {
302             const KeyValuePair pair(timeMap.GetKeyValue(timeMapIdx));
303             if(pair.first.type == Property::Key::INDEX)
304             {
305               continue;
306             }
307             const std::string& key(pair.first.stringKey);
308
309             if(key == TOKEN_DELAY)
310             {
311               animator->timePeriodDelay = pair.second.Get<float>();
312             }
313             else if(key == TOKEN_DURATION)
314             {
315               animator->timePeriodDuration = pair.second.Get<float>();
316             }
317           }
318         }
319         else if(key == TOKEN_ANIMATION_TYPE)
320         {
321           if((value.GetType() == Property::STRING))
322           {
323             if(value.Get<std::string>() == "TO")
324             {
325               animator->animationType = AnimationType::TO;
326             }
327             else if(value.Get<std::string>() == "BETWEEN")
328             {
329               animator->animationType = AnimationType::BETWEEN;
330             }
331             else if(value.Get<std::string>() == "BY")
332             {
333               animator->animationType = AnimationType::BY;
334             }
335           }
336         }
337       }
338     }
339   }
340   return animator;
341 }
342
343 void TransitionData::Add(Animator* animator)
344 {
345   mAnimators.PushBack(animator);
346 }
347
348 TransitionData::Iterator TransitionData::Begin() const
349 {
350   return mAnimators.Begin();
351 }
352
353 TransitionData::Iterator TransitionData::End() const
354 {
355   return mAnimators.End();
356 }
357
358 size_t TransitionData::Count() const
359 {
360   return mAnimators.Count();
361 }
362
363 Property::Map TransitionData::GetAnimatorAt(size_t index)
364 {
365   DALI_ASSERT_ALWAYS(index < Count() && "index exceeds bounds");
366
367   Animator*     animator = mAnimators[index];
368   Property::Map map;
369   map[TOKEN_TARGET] = animator->objectName;
370   if(animator->propertyKey.type == Property::Key::INDEX)
371   {
372     map[TOKEN_PROPERTY] = animator->propertyKey.indexKey;
373   }
374   else
375   {
376     map[TOKEN_PROPERTY] = animator->propertyKey.stringKey;
377   }
378   if(animator->initialValue.GetType() != Property::NONE)
379   {
380     map[TOKEN_INITIAL_VALUE] = animator->initialValue;
381   }
382   if(animator->targetValue.GetType() != Property::NONE)
383   {
384     map[TOKEN_TARGET_VALUE] = animator->targetValue;
385   }
386   if(animator->animate)
387   {
388     Property::Map animateMap;
389
390     if(animator->alphaFunction.GetMode() == AlphaFunction::BUILTIN_FUNCTION)
391     {
392       animateMap.Add(TOKEN_ALPHA_FUNCTION, GetEnumerationName(animator->alphaFunction.GetBuiltinFunction(), ALPHA_FUNCTION_BUILTIN_TABLE, ALPHA_FUNCTION_BUILTIN_TABLE_COUNT));
393     }
394     else if(animator->alphaFunction.GetMode() == AlphaFunction::BEZIER)
395     {
396       Vector4 controlPoints = animator->alphaFunction.GetBezierControlPoints();
397       animateMap.Add(TOKEN_ALPHA_FUNCTION, controlPoints);
398     }
399     animateMap.Add(TOKEN_TIME_PERIOD, Property::Map().Add(TOKEN_DELAY, animator->timePeriodDelay).Add(TOKEN_DURATION, animator->timePeriodDuration));
400
401     map[TOKEN_ANIMATOR] = animateMap;
402   }
403
404   return map;
405 }
406
407 } // namespace Internal
408 } // namespace Toolkit
409 } // namespace Dali