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