[dali_1.9.29] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / devel-api / scripting / scripting.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/devel-api/scripting/scripting.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/event/common/property-helper.h>
23 #include <dali/public-api/actors/actor.h>
24 #include <dali/public-api/object/property-array.h>
25 #include <dali/public-api/object/type-registry.h>
26
27 namespace Dali
28 {
29 namespace Scripting
30 {
31 bool EnumStringToInteger(const char* const value, const StringEnum* const enumTable, uint32_t tableCount, int& integerEnum)
32 {
33   int ret = 0;
34
35   bool found = false;
36   bool done  = false;
37
38   if(value && enumTable && tableCount)
39   {
40     const char* pValue = value;
41
42     while(!done)
43     {
44       uint32_t size = 0;
45
46       const StringEnum* table = enumTable;
47
48       for(uint32_t i = 0; i < tableCount; ++i)
49       {
50         if(Internal::CompareTokens(pValue, table->string, size))
51         {
52           found = true;
53           ret |= table->value;
54           break;
55         }
56         table++;
57       }
58
59       done = true;
60
61       if(found)
62       {
63         // allow comma separated or'd value
64         if(*(pValue + size) == ',')
65         {
66           pValue += size + 1;
67           done = false;
68         }
69       }
70     }
71
72     integerEnum = ret;
73   }
74
75   if(!found)
76   {
77     DALI_LOG_ERROR("Unknown enumeration string %s\n", value);
78   }
79   return found;
80 }
81
82 uint32_t FindEnumIndex(const char* value, const StringEnum* table, uint32_t tableCount)
83 {
84   uint32_t index = 0;
85   bool     found = false;
86   for(uint32_t i = 0; i < tableCount; ++i, ++index)
87   {
88     uint32_t sizeIgnored = 0;
89     if(Internal::CompareTokens(value, table->string, sizeIgnored))
90     {
91       found = true;
92       break;
93     }
94     ++table;
95   }
96   if(!found)
97   {
98     DALI_LOG_ERROR("Unknown enumeration string %s\n", value);
99   }
100   return index;
101 }
102
103 Actor NewActor(const Property::Map& map)
104 {
105   BaseHandle handle;
106
107   // First find type and create Actor
108   Property::Value* typeValue = map.Find("type");
109   if(typeValue)
110   {
111     TypeInfo type = TypeRegistry::Get().GetTypeInfo(typeValue->Get<std::string>());
112     if(type)
113     {
114       handle = type.CreateInstance();
115     }
116   }
117
118   if(!handle)
119   {
120     DALI_LOG_ERROR("Actor type not provided\n");
121     return Actor();
122   }
123
124   Actor actor(Actor::DownCast(handle));
125
126   if(actor)
127   {
128     // Now set the properties, or create children
129     for(Property::Map::SizeType i = 0, mapCount = map.Count(); i < mapCount; ++i)
130     {
131       const KeyValuePair pair(map.GetKeyValue(i));
132       if(pair.first.type == Property::Key::INDEX)
133       {
134         continue;
135       }
136       const std::string& key(pair.first.stringKey);
137       if(key == "type")
138       {
139         continue;
140       }
141
142       const Property::Value& value(pair.second);
143
144       if(key == "actors")
145       {
146         // Create children
147         Property::Array actorArray = value.Get<Property::Array>();
148         for(Property::Array::SizeType i = 0; i < actorArray.Size(); ++i)
149         {
150           actor.Add(NewActor(actorArray[i].Get<Property::Map>()));
151         }
152       }
153       else
154       {
155         Property::Index index(actor.GetPropertyIndex(key));
156
157         if(index != Property::INVALID_INDEX)
158         {
159           actor.SetProperty(index, value);
160         }
161       }
162     }
163   }
164
165   return actor;
166 }
167
168 void CreatePropertyMap(Actor actor, Property::Map& map)
169 {
170   map.Clear();
171
172   if(actor)
173   {
174     map["type"] = actor.GetTypeName();
175
176     // Default properties
177     Property::IndexContainer indices;
178     actor.GetPropertyIndices(indices);
179     const Property::IndexContainer::ConstIterator endIter = indices.End();
180
181     for(Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter)
182     {
183       map[actor.GetPropertyName(*iter)] = actor.GetProperty(*iter);
184     }
185
186     // Children
187     std::size_t childCount(actor.GetChildCount());
188     if(childCount)
189     {
190       Property::Array childArray;
191       for(uint32_t child = 0; child < childCount; ++child)
192       {
193         Property::Map childMap;
194         CreatePropertyMap(actor.GetChildAt(child), childMap);
195         childArray.PushBack(childMap);
196       }
197       map["actors"] = childArray;
198     }
199   }
200 }
201
202 void NewAnimation(const Property::Map& map, Dali::AnimationData& outputAnimationData)
203 {
204   // Note: Builder cannot currently pass generic Property::Maps "{" that are nested, so currently we can only have one AnimateTo per animation.
205   Dali::AnimationData::AnimationDataElement* element = new Dali::AnimationData::AnimationDataElement();
206
207   element->alphaFunction      = AlphaFunction::LINEAR;
208   element->timePeriodDelay    = 0.0f;
209   element->timePeriodDuration = 1.0f;
210
211   // Now set the properties, or create children
212   for(Property::Map::SizeType i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i)
213   {
214     const KeyValuePair pair(map.GetKeyValue(i));
215     if(pair.first.type == Property::Key::INDEX)
216     {
217       continue; // We don't consider index keys.
218     }
219     const std::string& key(pair.first.stringKey);
220
221     const Property::Value& value(pair.second);
222
223     if(key == "actor")
224     {
225       element->actor = value.Get<std::string>();
226     }
227     else if(key == "property")
228     {
229       element->property = value.Get<std::string>();
230     }
231     else if(key == "value")
232     {
233       element->value = value;
234     }
235     else if(key == "alphaFunction")
236     {
237       std::string alphaFunctionValue = value.Get<std::string>();
238
239       if(alphaFunctionValue == "LINEAR")
240       {
241         element->alphaFunction = AlphaFunction::LINEAR;
242       }
243       else if(alphaFunctionValue == "REVERSE")
244       {
245         element->alphaFunction = AlphaFunction::REVERSE;
246       }
247       else if(alphaFunctionValue == "EASE_IN_SQUARE")
248       {
249         element->alphaFunction = AlphaFunction::EASE_IN_SQUARE;
250       }
251       else if(alphaFunctionValue == "EASE_OUT_SQUARE")
252       {
253         element->alphaFunction = AlphaFunction::EASE_OUT_SQUARE;
254       }
255       else if(alphaFunctionValue == "EASE_IN")
256       {
257         element->alphaFunction = AlphaFunction::EASE_IN;
258       }
259       else if(alphaFunctionValue == "EASE_OUT")
260       {
261         element->alphaFunction = AlphaFunction::EASE_OUT;
262       }
263       else if(alphaFunctionValue == "EASE_IN_OUT")
264       {
265         element->alphaFunction = AlphaFunction::EASE_IN_OUT;
266       }
267       else if(alphaFunctionValue == "EASE_IN_SINE")
268       {
269         element->alphaFunction = AlphaFunction::EASE_IN_SINE;
270       }
271       else if(alphaFunctionValue == "EASE_OUT_SINE")
272       {
273         element->alphaFunction = AlphaFunction::EASE_OUT_SINE;
274       }
275       else if(alphaFunctionValue == "EASE_IN_OUT_SINE")
276       {
277         element->alphaFunction = AlphaFunction::EASE_IN_OUT_SINE;
278       }
279       else if(alphaFunctionValue == "BOUNCE")
280       {
281         element->alphaFunction = AlphaFunction::BOUNCE;
282       }
283       else if(alphaFunctionValue == "SIN")
284       {
285         element->alphaFunction = AlphaFunction::SIN;
286       }
287       else if(alphaFunctionValue == "EASE_OUT_BACK")
288       {
289         element->alphaFunction = AlphaFunction::EASE_OUT_BACK;
290       }
291     }
292     else if(key == "timePeriod")
293     {
294       Property::Map timeMap = value.Get<Property::Map>();
295       for(Property::Map::SizeType i = 0; i < timeMap.Count(); ++i)
296       {
297         const KeyValuePair timePair(timeMap.GetKeyValue(i));
298         if(timePair.first.type == Property::Key::INDEX)
299         {
300           continue;
301         }
302         const std::string& key(timePair.first.stringKey);
303
304         if(key == "delay")
305         {
306           element->timePeriodDelay = timePair.second.Get<float>();
307         }
308         else if(key == "duration")
309         {
310           element->timePeriodDuration = timePair.second.Get<float>();
311         }
312       }
313     }
314   }
315
316   outputAnimationData.Add(element);
317 }
318
319 } // namespace Scripting
320
321 } // namespace Dali