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