2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "dali-scene-loader/internal/json-util.h"
20 #include "dali/public-api/common/extents.h"
21 #include "dali/public-api/math/matrix3.h"
22 #include "dali/public-api/math/matrix.h"
23 #include "dali/public-api/math/quaternion.h"
24 #include "dali/public-api/math/radian.h"
25 #include "dali/public-api/math/vector2.h"
26 #include "dali/public-api/math/vector3.h"
27 #include "dali/public-api/object/property-value.h"
28 #include "dali/devel-api/common/map-wrapper.h"
33 using namespace Toolkit;
41 Property::Value ReadPrimitiveHelper(const TreeNode* tn, bool(*reader)(const TreeNode*, T&))
44 if (reader(tn, value))
46 return Property::Value(value);
48 return Property::Value();
52 Property::Value ReadVectorHelper(const TreeNode* tn)
54 static_assert(sizeof(T) % sizeof(float) == 0, "");
56 if (ReadVector(tn, value.AsFloat(), sizeof(T) / sizeof(float)))
58 return Property::Value(value);
60 return Property::Value();
63 Property::Value ReadVectorSingleFloatHelper(const TreeNode* tn)
66 if (ReadVector(tn, &value, 1u))
68 return Property::Value(value);
70 return Property::Value();
73 Property::Value ReadRotationHelper(const TreeNode* tn)
79 // degrees as per spec
81 ReadVector(tn, rotation.AsFloat(), 3u);
82 return Property::Value(Quaternion(Radian(Degree(rotation.x)),
83 Radian(Degree(rotation.y)),
84 Radian(Degree(rotation.z))));
89 ReadVector(tn, v.AsFloat(), 4u);
91 return Property::Value(Quaternion(v));
94 return Property::Value();
99 bool ReadQuadHelper(const TreeNode* tn, const std::array<T*, 4>& quad)
101 auto i = quad.begin();
102 auto iEnd = quad.end();
103 auto iJson = tn->CBegin();
104 while (iJson != tn->CEnd() && i != iEnd)
107 if (ReadInt(&(*iJson).second, value) && value <= std::numeric_limits<T>::max())
121 const std::map<std::string, Property::Value(*)(const TreeNode*)> kTypeIds {
123 { "boolean", [](const TreeNode* tn) {
124 return ReadPrimitiveHelper<bool>(tn, ReadBool);
126 { "float", [](const TreeNode* tn) {
127 return ReadPrimitiveHelper<float>(tn, ReadFloat);
129 { "integer", [](const TreeNode* tn) {
130 return ReadPrimitiveHelper<int>(tn, ReadInt);
132 { "vector2", ReadVectorHelper<Vector2> },
133 { "vector3", ReadVectorHelper<Vector3> },
134 { "vector4", ReadVectorHelper<Vector4> },
135 { "matrix3", ReadVectorHelper<Matrix3> },
136 { "matrix", ReadVectorHelper<Matrix> },
137 { "rectangle", [](const TreeNode* tn) {
139 if (ReadQuadHelper<int>(tn, { &value.x, &value.y, &value.width, &value.height }))
141 return Property::Value(value);
143 return Property::Value();
145 { "rotation", ReadRotationHelper },
146 // STRING - not particularly animatable
147 // ARRAY - not particularly animatable
148 // MAP - not particularly animatable
149 { "extents", [](const TreeNode* tn) {
151 if (ReadQuadHelper<uint16_t>(tn, { &value.start, &value.end, &value.top, &value.bottom }))
153 return Property::Value(value);
155 return Property::Value();
159 Property::Value(* const kArrayPropertyProcessors[])(const TreeNode*) {
160 ReadVectorHelper<Matrix>,
161 ReadVectorHelper<Matrix3>,
162 ReadVectorHelper<Vector4>,
163 ReadVectorHelper<Vector3>,
164 ReadVectorHelper<Vector2>,
165 ReadVectorSingleFloatHelper
170 bool ReadBool(const TreeNode* node, bool& num)
177 bool returnValue = false;
178 if (node->GetType() == TreeNode::BOOLEAN)
180 num = node->GetBoolean();
187 bool ReadInt(const TreeNode* node, int& num)
194 bool returnValue = false;
195 if (node->GetType() == TreeNode::INTEGER)
197 num = node->GetInteger();
200 else if (node->GetType() == TreeNode::FLOAT)
202 num = static_cast<int>(node->GetFloat());
209 bool ReadFloat(const TreeNode* node, float& num)
216 bool returnValue = false;
217 if (node->GetType() == TreeNode::FLOAT)
219 num = node->GetFloat();
222 else if (node->GetType() == TreeNode::INTEGER)
224 num = static_cast<float>(node->GetInteger());
231 bool ReadIndex(const Toolkit::TreeNode* node, Index& num)
233 bool returnValue = node && node->GetType() == TreeNode::INTEGER;
236 num = static_cast<Index>(node->GetInteger());
242 bool ReadBlob(const Toolkit::TreeNode* node, unsigned int& offset, unsigned int& length)
249 int iOffset, iLength;
250 bool success = ReadInt(node->GetChild("byteOffset"), iOffset) &&
251 ReadInt(node->GetChild("byteLength"), iLength) &&
252 iOffset >= 0 && iLength >= 0; // 0 length might not be sensible, but is not an error at this stage.
255 offset = static_cast<unsigned int>( iOffset );
256 length = static_cast<unsigned int>( iLength );
261 size_t GetNumericalArraySize(const TreeNode* node)
264 if (node->GetType() == TreeNode::ARRAY)
266 for (auto i0 = node->CBegin(), i1 = node->CEnd(); i0 != i1 &&
267 ((*i0).second.GetType() == TreeNode::FLOAT || (*i0).second.GetType() == TreeNode::INTEGER);
276 bool ReadVector(const TreeNode* node, float* num, unsigned int size)
283 bool returnValue = false;
284 if ((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
286 unsigned int offset = 0u;
287 for (TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
289 const TreeNode& coord = (*it).second;
290 if (!ReadFloat(&coord, *(num + offset)))
301 bool ReadVector(const Toolkit::TreeNode* node, int* num, unsigned int size)
308 bool returnValue = false;
309 if ((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
311 unsigned int offset = 0u;
312 for (TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
314 const TreeNode& coord = (*it).second;
315 if (!ReadInt(&coord, *(num + offset)))
326 bool ReadColor(const TreeNode* node, Vector4& color)
333 if (!ReadVector(node, color.AsFloat(), 4))
335 if (!ReadVector(node, color.AsFloat(), 3))
345 bool ReadTimePeriod(const TreeNode* node, TimePeriod& timePeriod)
352 if (!ReadFloat(node->GetChild("delay"), timePeriod.delaySeconds) || !ReadFloat(node->GetChild("duration"), timePeriod.durationSeconds))
359 bool ReadString(const TreeNode* node, std::string& strValue)
366 bool returnValue = false;
367 if (node->GetType() == TreeNode::STRING)
369 strValue = node->GetString();
375 bool ReadStringVector(const TreeNode* node, std::vector<std::string>& strvector)
382 bool returnValue = false;
383 if (node->GetType() == TreeNode::ARRAY)
385 for (TreeNode::ConstIterator it = node->CBegin(); it != node->CEnd(); ++it)
387 const TreeNode& strNode = (*it).second;
388 if (strNode.GetType() == TreeNode::STRING)
390 strvector.push_back(strNode.GetString());
402 Property::Value ReadPropertyValue(const Property::Type& propType, const TreeNode& tn)
406 case Property::BOOLEAN:
407 return ReadPrimitiveHelper<bool>(&tn, ReadBool);
409 case Property::FLOAT:
410 return ReadPrimitiveHelper<float>(&tn, ReadFloat);
412 case Property::INTEGER:
413 return ReadPrimitiveHelper<int>(&tn, ReadInt);
415 case Property::VECTOR2:
416 return ReadVectorHelper<Vector2>(&tn);
418 case Property::VECTOR3:
419 return ReadVectorHelper<Vector3>(&tn);
421 case Property::VECTOR4:
422 return ReadVectorHelper<Vector4>(&tn);
424 case Property::MATRIX3:
425 return ReadVectorHelper<Matrix3>(&tn);
427 case Property::MATRIX:
428 return ReadVectorHelper<Matrix>(&tn);
430 case Property::RECTANGLE:
433 if (ReadQuadHelper<int>(&tn, { &value.x, &value.y, &value.width, &value.height }))
435 return Property::Value(value);
440 case Property::ROTATION:
441 return ReadRotationHelper(&tn);
443 case Property::EXTENTS:
446 if (ReadQuadHelper<uint16_t>(&tn, { &value.start, &value.end, &value.top, &value.bottom }))
448 return Property::Value(value);
453 case Property::NONE: // fall
456 DALI_ASSERT_ALWAYS(!"Property type incorrect");
459 return Property::Value();
462 Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
464 Property::Value propValue;
465 if (tn.GetType() == TreeNode::OBJECT) // attempt to disambiguate type.
467 auto jsonType = tn.GetChild("type");
468 if (jsonType && jsonType->GetType() == TreeNode::STRING)
470 auto iFind = kTypeIds.find(jsonType->GetString());
471 if (iFind != kTypeIds.end())
473 propValue = iFind->second(tn.GetChild("value"));
478 if (propValue.GetType() == Property::NONE)
482 switch (tn.GetType())
484 case TreeNode::BOOLEAN:
485 propValue = ReadPrimitiveHelper<bool>(&tn, ReadBool);
488 case TreeNode::INTEGER:
489 propValue = ReadPrimitiveHelper<int>(&tn, ReadInt);
492 case TreeNode::FLOAT:
493 propValue = ReadPrimitiveHelper<float>(&tn, ReadFloat);
502 bool allNumbers = true;
503 for (auto i0 = tn.CBegin(), i1 = tn.CEnd(); i0 != i1; ++i0)
505 auto type = (*i0).second.GetType();
506 if(!(type == TreeNode::FLOAT || type == TreeNode::INTEGER))
515 // NOTE: rotations / rectangles / extents must be disambiguated in all circumstances.
516 for (auto& r : kArrayPropertyProcessors)
519 if (propValue.GetType() != Property::NONE)