2 * Copyright (c) 2021 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"
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"
33 using namespace Toolkit;
40 Property::Value ReadPrimitiveHelper(const TreeNode* tn, bool (*reader)(const TreeNode*, T&))
45 return Property::Value(value);
47 return Property::Value();
51 Property::Value ReadVectorHelper(const TreeNode* tn)
53 static_assert(sizeof(T) % sizeof(float) == 0, "");
55 if(ReadVector(tn, value.AsFloat(), sizeof(T) / sizeof(float)))
57 return Property::Value(value);
59 return Property::Value();
62 Property::Value ReadVectorSingleFloatHelper(const TreeNode* tn)
65 if(ReadVector(tn, &value, 1u))
67 return Property::Value(value);
69 return Property::Value();
72 Property::Value ReadRotationHelper(const TreeNode* tn)
78 // degrees as per spec
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))));
88 ReadVector(tn, v.AsFloat(), 4u);
90 return Property::Value(Quaternion(v));
93 return Property::Value();
98 bool ReadQuadHelper(const TreeNode* tn, const std::array<T*, 4>& quad)
100 auto i = quad.begin();
101 auto iEnd = quad.end();
102 auto iJson = tn->CBegin();
103 while(iJson != tn->CEnd() && i != iEnd)
106 if(ReadInt(&(*iJson).second, value) && value <= std::numeric_limits<T>::max())
120 const std::map<std::string, Property::Value (*)(const TreeNode*)> kTypeIds{
122 {"boolean", [](const TreeNode* tn) {
123 return ReadPrimitiveHelper<bool>(tn, ReadBool);
125 {"float", [](const TreeNode* tn) {
126 return ReadPrimitiveHelper<float>(tn, ReadFloat);
128 {"integer", [](const TreeNode* tn) {
129 return ReadPrimitiveHelper<int>(tn, ReadInt);
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) {
138 if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
140 return Property::Value(value);
142 return Property::Value();
144 {"rotation", ReadRotationHelper},
145 // STRING - not particularly animatable
146 // ARRAY - not particularly animatable
147 // MAP - not particularly animatable
148 {"extents", [](const TreeNode* tn) {
150 if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
152 return Property::Value(value);
154 return Property::Value();
158 Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
159 ReadVectorHelper<Matrix>,
160 ReadVectorHelper<Matrix3>,
161 ReadVectorHelper<Vector4>,
162 ReadVectorHelper<Vector3>,
163 ReadVectorHelper<Vector2>,
164 ReadVectorSingleFloatHelper};
168 bool ReadBool(const TreeNode* node, bool& num)
175 bool returnValue = false;
176 if(node->GetType() == TreeNode::BOOLEAN)
178 num = node->GetBoolean();
185 bool ReadInt(const TreeNode* node, int& num)
192 bool returnValue = false;
193 if(node->GetType() == TreeNode::INTEGER)
195 num = node->GetInteger();
198 else if(node->GetType() == TreeNode::FLOAT)
200 num = static_cast<int>(node->GetFloat());
207 bool ReadFloat(const TreeNode* node, float& num)
214 bool returnValue = false;
215 if(node->GetType() == TreeNode::FLOAT)
217 num = node->GetFloat();
220 else if(node->GetType() == TreeNode::INTEGER)
222 num = static_cast<float>(node->GetInteger());
229 bool ReadIndex(const Toolkit::TreeNode* node, Index& num)
231 bool returnValue = node && node->GetType() == TreeNode::INTEGER;
234 num = static_cast<Index>(node->GetInteger());
240 bool ReadBlob(const Toolkit::TreeNode* node, unsigned int& offset, unsigned int& length)
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.
253 offset = static_cast<unsigned int>(iOffset);
254 length = static_cast<unsigned int>(iLength);
259 size_t GetNumericalArraySize(const TreeNode* node)
262 if(node->GetType() == TreeNode::ARRAY)
264 for(auto i0 = node->CBegin(), i1 = node->CEnd(); i0 != i1 &&
265 ((*i0).second.GetType() == TreeNode::FLOAT || (*i0).second.GetType() == TreeNode::INTEGER);
274 bool ReadVector(const TreeNode* node, float* num, unsigned int size)
281 bool returnValue = false;
282 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
284 unsigned int offset = 0u;
285 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
287 const TreeNode& coord = (*it).second;
288 if(!ReadFloat(&coord, *(num + offset)))
299 bool ReadVector(const Toolkit::TreeNode* node, int* num, unsigned int size)
306 bool returnValue = false;
307 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
309 unsigned int offset = 0u;
310 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
312 const TreeNode& coord = (*it).second;
313 if(!ReadInt(&coord, *(num + offset)))
324 bool ReadColor(const TreeNode* node, Vector4& color)
331 if(!ReadVector(node, color.AsFloat(), 4))
333 if(!ReadVector(node, color.AsFloat(), 3))
343 bool ReadTimePeriod(const TreeNode* node, TimePeriod& timePeriod)
350 if(!ReadFloat(node->GetChild("delay"), timePeriod.delaySeconds) || !ReadFloat(node->GetChild("duration"), timePeriod.durationSeconds))
357 bool ReadString(const TreeNode* node, std::string& strValue)
364 bool returnValue = false;
365 if(node->GetType() == TreeNode::STRING)
367 strValue = node->GetString();
373 bool ReadStringVector(const TreeNode* node, std::vector<std::string>& strvector)
380 bool returnValue = false;
381 if(node->GetType() == TreeNode::ARRAY)
383 for(TreeNode::ConstIterator it = node->CBegin(); it != node->CEnd(); ++it)
385 const TreeNode& strNode = (*it).second;
386 if(strNode.GetType() == TreeNode::STRING)
388 strvector.push_back(strNode.GetString());
400 Property::Value ReadPropertyValue(const Property::Type& propType, const TreeNode& tn)
404 case Property::BOOLEAN:
405 return ReadPrimitiveHelper<bool>(&tn, ReadBool);
407 case Property::FLOAT:
408 return ReadPrimitiveHelper<float>(&tn, ReadFloat);
410 case Property::INTEGER:
411 return ReadPrimitiveHelper<int>(&tn, ReadInt);
413 case Property::VECTOR2:
414 return ReadVectorHelper<Vector2>(&tn);
416 case Property::VECTOR3:
417 return ReadVectorHelper<Vector3>(&tn);
419 case Property::VECTOR4:
420 return ReadVectorHelper<Vector4>(&tn);
422 case Property::MATRIX3:
423 return ReadVectorHelper<Matrix3>(&tn);
425 case Property::MATRIX:
426 return ReadVectorHelper<Matrix>(&tn);
428 case Property::RECTANGLE:
431 if(ReadQuadHelper<int>(&tn, {&value.x, &value.y, &value.width, &value.height}))
433 return Property::Value(value);
438 case Property::ROTATION:
439 return ReadRotationHelper(&tn);
441 case Property::EXTENTS:
444 if(ReadQuadHelper<uint16_t>(&tn, {&value.start, &value.end, &value.top, &value.bottom}))
446 return Property::Value(value);
451 case Property::NONE: // fall
454 DALI_ASSERT_ALWAYS(!"Property type incorrect");
457 return Property::Value();
460 Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
462 Property::Value propValue;
463 if(tn.GetType() == TreeNode::OBJECT) // attempt to disambiguate type.
465 auto jsonType = tn.GetChild("type");
466 if(jsonType && jsonType->GetType() == TreeNode::STRING)
468 auto iFind = kTypeIds.find(jsonType->GetString());
469 if(iFind != kTypeIds.end())
471 propValue = iFind->second(tn.GetChild("value"));
476 if(propValue.GetType() == Property::NONE)
482 case TreeNode::BOOLEAN:
483 propValue = ReadPrimitiveHelper<bool>(&tn, ReadBool);
486 case TreeNode::INTEGER:
487 propValue = ReadPrimitiveHelper<int>(&tn, ReadInt);
490 case TreeNode::FLOAT:
491 propValue = ReadPrimitiveHelper<float>(&tn, ReadFloat);
500 bool allNumbers = true;
501 for(auto i0 = tn.CBegin(), i1 = tn.CEnd(); i0 != i1; ++i0)
503 auto type = (*i0).second.GetType();
504 if(!(type == TreeNode::FLOAT || type == TreeNode::INTEGER))
513 // NOTE: rotations / rectangles / extents must be disambiguated in all circumstances.
514 for(auto& r : kArrayPropertyProcessors)
517 if(propValue.GetType() != Property::NONE)
528 } // namespace SceneLoader