Make shader version be top of the code
[platform/core/uifw/dali-toolkit.git] / dali-scene-loader / internal / json-util.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 #include "dali-scene-loader/internal/json-util.h"
18
19 // EXTERNAL INCLUDES
20 #include <array>
21 #include "dali/devel-api/common/map-wrapper.h"
22 #include "dali/public-api/common/extents.h"
23 #include "dali/public-api/math/matrix.h"
24 #include "dali/public-api/math/matrix3.h"
25 #include "dali/public-api/math/quaternion.h"
26 #include "dali/public-api/math/radian.h"
27 #include "dali/public-api/math/vector2.h"
28 #include "dali/public-api/math/vector3.h"
29 #include "dali/public-api/object/property-value.h"
30
31 namespace Dali
32 {
33 using namespace Toolkit;
34
35 namespace SceneLoader
36 {
37 namespace
38 {
39 template<typename T>
40 Property::Value ReadPrimitiveHelper(const TreeNode* tn, bool (*reader)(const TreeNode*, T&))
41 {
42   T value;
43   if(reader(tn, value))
44   {
45     return Property::Value(value);
46   }
47   return Property::Value();
48 }
49
50 template<typename T>
51 Property::Value ReadVectorHelper(const TreeNode* tn)
52 {
53   static_assert(sizeof(T) % sizeof(float) == 0, "");
54   T value;
55   if(ReadVector(tn, value.AsFloat(), sizeof(T) / sizeof(float)))
56   {
57     return Property::Value(value);
58   }
59   return Property::Value();
60 }
61
62 Property::Value ReadVectorSingleFloatHelper(const TreeNode* tn)
63 {
64   float value;
65   if(ReadVector(tn, &value, 1u))
66   {
67     return Property::Value(value);
68   }
69   return Property::Value();
70 }
71
72 Property::Value ReadRotationHelper(const TreeNode* tn)
73 {
74   switch(tn->Size())
75   {
76     case 3:
77     {
78       // degrees as per spec
79       Vector3 rotation;
80       ReadVector(tn, rotation.AsFloat(), 3u);
81       return Property::Value(Quaternion(Radian(Degree(rotation.x)),
82                                         Radian(Degree(rotation.y)),
83                                         Radian(Degree(rotation.z))));
84     }
85     case 4:
86     {
87       Vector4 v;
88       ReadVector(tn, v.AsFloat(), 4u);
89       //Quaternion
90       return Property::Value(Quaternion(v));
91     }
92     default:
93       return Property::Value();
94   }
95 }
96
97 template<typename T>
98 bool ReadQuadHelper(const TreeNode* tn, const std::array<T*, 4>& quad)
99 {
100   auto i     = quad.begin();
101   auto iEnd  = quad.end();
102   auto iJson = tn->CBegin();
103   while(iJson != tn->CEnd() && i != iEnd)
104   {
105     int value;
106     if(ReadInt(&(*iJson).second, value) && value <= std::numeric_limits<T>::max())
107     {
108       **i = value;
109       ++i;
110       ++iJson;
111     }
112     else
113     {
114       return false;
115     }
116   }
117   return true;
118 }
119
120 const std::map<std::string, Property::Value (*)(const TreeNode*)> kTypeIds{
121   // NONE
122   {"boolean", [](const TreeNode* tn) {
123      return ReadPrimitiveHelper<bool>(tn, ReadBool);
124    }},
125   {"float", [](const TreeNode* tn) {
126      return ReadPrimitiveHelper<float>(tn, ReadFloat);
127    }},
128   {"integer", [](const TreeNode* tn) {
129      return ReadPrimitiveHelper<int>(tn, ReadInt);
130    }},
131   {"vector2", ReadVectorHelper<Vector2>},
132   {"vector3", ReadVectorHelper<Vector3>},
133   {"vector4", ReadVectorHelper<Vector4>},
134   {"matrix3", ReadVectorHelper<Matrix3>},
135   {"matrix", ReadVectorHelper<Matrix>},
136   {"rectangle", [](const TreeNode* tn) {
137      Rect<int> value;
138      if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
139      {
140        return Property::Value(value);
141      }
142      return Property::Value();
143    }},
144   {"rotation", ReadRotationHelper},
145   // STRING - not particularly animatable
146   // ARRAY - not particularly animatable
147   // MAP - not particularly animatable
148   {"extents", [](const TreeNode* tn) {
149      Extents value;
150      if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
151      {
152        return Property::Value(value);
153      }
154      return Property::Value();
155    }},
156 };
157
158 Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
159   ReadVectorHelper<Matrix>,
160   ReadVectorHelper<Matrix3>,
161   ReadVectorHelper<Vector4>,
162   ReadVectorHelper<Vector3>,
163   ReadVectorHelper<Vector2>,
164   ReadVectorSingleFloatHelper};
165
166 } // namespace
167
168 bool ReadBool(const TreeNode* node, bool& num)
169 {
170   if(!node)
171   {
172     return false;
173   }
174
175   bool returnValue = false;
176   if(node->GetType() == TreeNode::BOOLEAN)
177   {
178     num         = node->GetBoolean();
179     returnValue = true;
180   }
181
182   return returnValue;
183 }
184
185 bool ReadInt(const TreeNode* node, int& num)
186 {
187   if(!node)
188   {
189     return false;
190   }
191
192   bool returnValue = false;
193   if(node->GetType() == TreeNode::INTEGER)
194   {
195     num         = node->GetInteger();
196     returnValue = true;
197   }
198   else if(node->GetType() == TreeNode::FLOAT)
199   {
200     num         = static_cast<int>(node->GetFloat());
201     returnValue = true;
202   }
203
204   return returnValue;
205 }
206
207 bool ReadFloat(const TreeNode* node, float& num)
208 {
209   if(!node)
210   {
211     return false;
212   }
213
214   bool returnValue = false;
215   if(node->GetType() == TreeNode::FLOAT)
216   {
217     num         = node->GetFloat();
218     returnValue = true;
219   }
220   else if(node->GetType() == TreeNode::INTEGER)
221   {
222     num         = static_cast<float>(node->GetInteger());
223     returnValue = true;
224   }
225
226   return returnValue;
227 }
228
229 bool ReadIndex(const Toolkit::TreeNode* node, Index& num)
230 {
231   bool returnValue = node && node->GetType() == TreeNode::INTEGER;
232   if(returnValue)
233   {
234     num = static_cast<Index>(node->GetInteger());
235   }
236
237   return returnValue;
238 }
239
240 bool ReadBlob(const Toolkit::TreeNode* node, unsigned int& offset, unsigned int& length)
241 {
242   if(!node)
243   {
244     return false;
245   }
246
247   int  iOffset, iLength;
248   bool success = ReadInt(node->GetChild("byteOffset"), iOffset) &&
249                  ReadInt(node->GetChild("byteLength"), iLength) &&
250                  iOffset >= 0 && iLength >= 0; // 0 length might not be sensible, but is not an error at this stage.
251   if(success)
252   {
253     offset = static_cast<unsigned int>(iOffset);
254     length = static_cast<unsigned int>(iLength);
255   }
256   return success;
257 }
258
259 size_t GetNumericalArraySize(const TreeNode* node)
260 {
261   size_t size = 0;
262   if(node->GetType() == TreeNode::ARRAY)
263   {
264     for(auto i0 = node->CBegin(), i1 = node->CEnd(); i0 != i1 &&
265                                                      ((*i0).second.GetType() == TreeNode::FLOAT || (*i0).second.GetType() == TreeNode::INTEGER);
266         ++i0)
267     {
268       ++size;
269     }
270   }
271   return size;
272 }
273
274 bool ReadVector(const TreeNode* node, float* num, unsigned int size)
275 {
276   if(!node)
277   {
278     return false;
279   }
280
281   bool returnValue = false;
282   if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
283   {
284     unsigned int offset = 0u;
285     for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
286     {
287       const TreeNode& coord = (*it).second;
288       if(!ReadFloat(&coord, *(num + offset)))
289       {
290         return false;
291       }
292     }
293     returnValue = true;
294   }
295
296   return returnValue;
297 }
298
299 bool ReadVector(const Toolkit::TreeNode* node, int* num, unsigned int size)
300 {
301   if(!node)
302   {
303     return false;
304   }
305
306   bool returnValue = false;
307   if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
308   {
309     unsigned int offset = 0u;
310     for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
311     {
312       const TreeNode& coord = (*it).second;
313       if(!ReadInt(&coord, *(num + offset)))
314       {
315         return false;
316       }
317     }
318     returnValue = true;
319   }
320
321   return returnValue;
322 }
323
324 bool ReadColor(const TreeNode* node, Vector4& color)
325 {
326   if(nullptr == node)
327   {
328     return false;
329   }
330
331   if(!ReadVector(node, color.AsFloat(), 4))
332   {
333     if(!ReadVector(node, color.AsFloat(), 3))
334     {
335       return false;
336     }
337     color.a = 1.f;
338   }
339
340   return true;
341 }
342
343 bool ReadTimePeriod(const TreeNode* node, TimePeriod& timePeriod)
344 {
345   if(!node)
346   {
347     return false;
348   }
349
350   if(!ReadFloat(node->GetChild("delay"), timePeriod.delaySeconds) || !ReadFloat(node->GetChild("duration"), timePeriod.durationSeconds))
351   {
352     return false;
353   }
354   return true;
355 }
356
357 bool ReadString(const TreeNode* node, std::string& strValue)
358 {
359   if(!node)
360   {
361     return false;
362   }
363
364   bool returnValue = false;
365   if(node->GetType() == TreeNode::STRING)
366   {
367     strValue    = node->GetString();
368     returnValue = true;
369   }
370   return returnValue;
371 }
372
373 bool ReadStringVector(const TreeNode* node, std::vector<std::string>& strvector)
374 {
375   if(!node)
376   {
377     return false;
378   }
379
380   bool returnValue = false;
381   if(node->GetType() == TreeNode::ARRAY)
382   {
383     for(TreeNode::ConstIterator it = node->CBegin(); it != node->CEnd(); ++it)
384     {
385       const TreeNode& strNode = (*it).second;
386       if(strNode.GetType() == TreeNode::STRING)
387       {
388         strvector.push_back(strNode.GetString());
389       }
390       else
391       {
392         return false;
393       }
394     }
395     returnValue = true;
396   }
397   return returnValue;
398 }
399
400 Property::Value ReadPropertyValue(const Property::Type& propType, const TreeNode& tn)
401 {
402   switch(propType)
403   {
404     case Property::BOOLEAN:
405       return ReadPrimitiveHelper<bool>(&tn, ReadBool);
406
407     case Property::FLOAT:
408       return ReadPrimitiveHelper<float>(&tn, ReadFloat);
409
410     case Property::INTEGER:
411       return ReadPrimitiveHelper<int>(&tn, ReadInt);
412
413     case Property::VECTOR2:
414       return ReadVectorHelper<Vector2>(&tn);
415
416     case Property::VECTOR3:
417       return ReadVectorHelper<Vector3>(&tn);
418
419     case Property::VECTOR4:
420       return ReadVectorHelper<Vector4>(&tn);
421
422     case Property::MATRIX3:
423       return ReadVectorHelper<Matrix3>(&tn);
424
425     case Property::MATRIX:
426       return ReadVectorHelper<Matrix>(&tn);
427
428     case Property::RECTANGLE:
429     {
430       Rect<int> value;
431       if(ReadQuadHelper<int>(&tn, {&value.x, &value.y, &value.width, &value.height}))
432       {
433         return Property::Value(value);
434       }
435       break;
436     }
437
438     case Property::ROTATION:
439       return ReadRotationHelper(&tn);
440
441     case Property::EXTENTS:
442     {
443       Extents value;
444       if(ReadQuadHelper<uint16_t>(&tn, {&value.start, &value.end, &value.top, &value.bottom}))
445       {
446         return Property::Value(value);
447       }
448       break;
449     }
450
451     case Property::NONE: // fall
452     default:
453     {
454       DALI_ASSERT_ALWAYS(!"Property type incorrect");
455     }
456   }
457   return Property::Value();
458 }
459
460 Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
461 {
462   Property::Value propValue;
463   if(tn.GetType() == TreeNode::OBJECT) // attempt to disambiguate type.
464   {
465     auto jsonType = tn.GetChild("type");
466     if(jsonType && jsonType->GetType() == TreeNode::STRING)
467     {
468       auto iFind = kTypeIds.find(jsonType->GetString());
469       if(iFind != kTypeIds.end())
470       {
471         propValue = iFind->second(tn.GetChild("value"));
472       }
473     }
474   }
475
476   if(propValue.GetType() == Property::NONE)
477   {
478     if(tn.Size() == 0)
479     {
480       switch(tn.GetType())
481       {
482         case TreeNode::BOOLEAN:
483           propValue = ReadPrimitiveHelper<bool>(&tn, ReadBool);
484           break;
485
486         case TreeNode::INTEGER:
487           propValue = ReadPrimitiveHelper<int>(&tn, ReadInt);
488           break;
489
490         case TreeNode::FLOAT:
491           propValue = ReadPrimitiveHelper<float>(&tn, ReadFloat);
492           break;
493
494         default:
495           break;
496       }
497     }
498     else
499     {
500       bool allNumbers = true;
501       for(auto i0 = tn.CBegin(), i1 = tn.CEnd(); i0 != i1; ++i0)
502       {
503         auto type = (*i0).second.GetType();
504         if(!(type == TreeNode::FLOAT || type == TreeNode::INTEGER))
505         {
506           allNumbers = false;
507           break;
508         }
509       }
510
511       if(allNumbers)
512       {
513         // NOTE: rotations / rectangles / extents must be disambiguated in all circumstances.
514         for(auto& r : kArrayPropertyProcessors)
515         {
516           propValue = r(&tn);
517           if(propValue.GetType() != Property::NONE)
518           {
519             break;
520           }
521         }
522       }
523     }
524   }
525   return propValue;
526 }
527
528 } // namespace SceneLoader
529 } // namespace Dali