2 * Copyright (c) 2023 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.
19 #include <dali-scene3d/internal/loader/json-util.h>
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>
35 using namespace Toolkit;
44 Property::Value ReadPrimitiveHelper(const TreeNode* tn, bool (*reader)(const TreeNode*, T&))
49 return Property::Value(value);
51 return Property::Value();
55 Property::Value ReadVectorHelper(const TreeNode* tn)
57 static_assert(sizeof(T) % sizeof(float) == 0, "");
59 if(ReadVector(tn, value.AsFloat(), sizeof(T) / sizeof(float)))
61 return Property::Value(value);
63 return Property::Value();
66 Property::Value ReadVectorSingleFloatHelper(const TreeNode* tn)
69 if(ReadVector(tn, &value, 1u))
71 return Property::Value(value);
73 return Property::Value();
76 Property::Value ReadRotationHelper(const TreeNode* tn)
82 // degrees as per spec
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))));
92 ReadVector(tn, v.AsFloat(), 4u);
94 return Property::Value(Quaternion(v));
97 return Property::Value();
102 bool ReadQuadHelper(const TreeNode* tn, const std::array<T*, 4>& quad)
104 auto i = quad.begin();
105 auto iEnd = quad.end();
106 auto iJson = tn->CBegin();
107 while(iJson != tn->CEnd() && i != iEnd)
110 if(ReadInt(&(*iJson).second, value) && value <= std::numeric_limits<T>::max())
124 const std::map<std::string_view, Property::Value (*)(const TreeNode*)>& GetTypeIds()
126 static const std::map<std::string_view, Property::Value (*)(const TreeNode*)> kTypeIds{
128 {"boolean", [](const TreeNode* tn) {
129 return ReadPrimitiveHelper<bool>(tn, ReadBool);
131 {"float", [](const TreeNode* tn) {
132 return ReadPrimitiveHelper<float>(tn, ReadFloat);
134 {"integer", [](const TreeNode* tn) {
135 return ReadPrimitiveHelper<int>(tn, ReadInt);
137 {"vector2", ReadVectorHelper<Vector2>},
138 {"vector3", ReadVectorHelper<Vector3>},
139 {"vector4", ReadVectorHelper<Vector4>},
140 {"matrix3", ReadVectorHelper<Matrix3>},
141 {"matrix", ReadVectorHelper<Matrix>},
142 {"rectangle", [](const TreeNode* tn) {
144 if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
146 return Property::Value(value);
148 return Property::Value();
150 {"rotation", ReadRotationHelper},
151 // STRING - not particularly animatable
152 // ARRAY - not particularly animatable
153 // MAP - not particularly animatable
154 {"extents", [](const TreeNode* tn) {
156 if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
158 return Property::Value(value);
160 return Property::Value();
166 Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
167 ReadVectorHelper<Matrix>,
168 ReadVectorHelper<Matrix3>,
169 ReadVectorHelper<Vector4>,
170 ReadVectorHelper<Vector3>,
171 ReadVectorHelper<Vector2>,
172 ReadVectorSingleFloatHelper};
176 bool ReadBool(const TreeNode* node, bool& num)
183 bool returnValue = false;
184 if(node->GetType() == TreeNode::BOOLEAN)
186 num = node->GetBoolean();
193 bool ReadInt(const TreeNode* node, int& num)
200 bool returnValue = false;
201 if(node->GetType() == TreeNode::INTEGER)
203 num = node->GetInteger();
206 else if(node->GetType() == TreeNode::FLOAT)
208 num = static_cast<int>(node->GetFloat());
215 bool ReadFloat(const TreeNode* node, float& num)
222 bool returnValue = false;
223 if(node->GetType() == TreeNode::FLOAT)
225 num = node->GetFloat();
228 else if(node->GetType() == TreeNode::INTEGER)
230 num = static_cast<float>(node->GetInteger());
237 bool ReadIndex(const Toolkit::TreeNode* node, Index& num)
239 bool returnValue = node && node->GetType() == TreeNode::INTEGER;
242 num = static_cast<Index>(node->GetInteger());
248 bool ReadBlob(const Toolkit::TreeNode* node, unsigned int& offset, unsigned int& length)
255 int iOffset, iLength;
256 bool success = ReadInt(node->GetChild("byteOffset"), iOffset) &&
257 ReadInt(node->GetChild("byteLength"), iLength) &&
258 iOffset >= 0 && iLength >= 0; // 0 length might not be sensible, but is not an error at this stage.
261 offset = static_cast<unsigned int>(iOffset);
262 length = static_cast<unsigned int>(iLength);
267 size_t GetNumericalArraySize(const TreeNode* node)
270 if(node->GetType() == TreeNode::ARRAY)
272 for(auto i0 = node->CBegin(), i1 = node->CEnd(); i0 != i1 &&
273 ((*i0).second.GetType() == TreeNode::FLOAT || (*i0).second.GetType() == TreeNode::INTEGER);
282 bool ReadVector(const TreeNode* node, float* num, unsigned int size)
289 bool returnValue = false;
290 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
292 unsigned int offset = 0u;
293 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
295 const TreeNode& coord = (*it).second;
296 if(!ReadFloat(&coord, *(num + offset)))
307 bool ReadVector(const Toolkit::TreeNode* node, int* num, unsigned int size)
314 bool returnValue = false;
315 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
317 unsigned int offset = 0u;
318 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
320 const TreeNode& coord = (*it).second;
321 if(!ReadInt(&coord, *(num + offset)))
332 bool ReadColor(const TreeNode* node, Vector4& color)
339 if(!ReadVector(node, color.AsFloat(), 4))
341 if(!ReadVector(node, color.AsFloat(), 3))
351 bool ReadTimePeriod(const TreeNode* node, TimePeriod& timePeriod)
358 if(!ReadFloat(node->GetChild("delay"), timePeriod.delaySeconds) || !ReadFloat(node->GetChild("duration"), timePeriod.durationSeconds))
365 bool ReadString(const TreeNode* node, std::string& strValue)
372 bool returnValue = false;
373 if(node->GetType() == TreeNode::STRING)
375 strValue = node->GetString();
381 bool ReadStringVector(const TreeNode* node, std::vector<std::string>& strvector)
388 bool returnValue = false;
389 if(node->GetType() == TreeNode::ARRAY)
391 for(TreeNode::ConstIterator it = node->CBegin(); it != node->CEnd(); ++it)
393 const TreeNode& strNode = (*it).second;
394 if(strNode.GetType() == TreeNode::STRING)
396 strvector.push_back(strNode.GetString());
408 Property::Value ReadPropertyValue(const Property::Type& propType, const TreeNode& tn)
412 case Property::BOOLEAN:
413 return ReadPrimitiveHelper<bool>(&tn, ReadBool);
415 case Property::FLOAT:
416 return ReadPrimitiveHelper<float>(&tn, ReadFloat);
418 case Property::INTEGER:
419 return ReadPrimitiveHelper<int>(&tn, ReadInt);
421 case Property::VECTOR2:
422 return ReadVectorHelper<Vector2>(&tn);
424 case Property::VECTOR3:
425 return ReadVectorHelper<Vector3>(&tn);
427 case Property::VECTOR4:
428 return ReadVectorHelper<Vector4>(&tn);
430 case Property::MATRIX3:
431 return ReadVectorHelper<Matrix3>(&tn);
433 case Property::MATRIX:
434 return ReadVectorHelper<Matrix>(&tn);
436 case Property::RECTANGLE:
439 if(ReadQuadHelper<int>(&tn, {&value.x, &value.y, &value.width, &value.height}))
441 return Property::Value(value);
446 case Property::ROTATION:
447 return ReadRotationHelper(&tn);
449 case Property::EXTENTS:
452 if(ReadQuadHelper<uint16_t>(&tn, {&value.start, &value.end, &value.top, &value.bottom}))
454 return Property::Value(value);
459 case Property::NONE: // fall
462 DALI_ASSERT_ALWAYS(!"Property type incorrect");
465 return Property::Value();
468 Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
470 Property::Value propValue;
471 if(tn.GetType() == TreeNode::OBJECT) // attempt to disambiguate type.
473 auto jsonType = tn.GetChild("type");
474 if(jsonType && jsonType->GetType() == TreeNode::STRING)
476 auto iFind = GetTypeIds().find(jsonType->GetString());
477 if(iFind != GetTypeIds().end())
479 propValue = iFind->second(tn.GetChild("value"));
484 if(propValue.GetType() == Property::NONE)
490 case TreeNode::BOOLEAN:
491 propValue = ReadPrimitiveHelper<bool>(&tn, ReadBool);
494 case TreeNode::INTEGER:
495 propValue = ReadPrimitiveHelper<int>(&tn, ReadInt);
498 case TreeNode::FLOAT:
499 propValue = ReadPrimitiveHelper<float>(&tn, ReadFloat);
508 bool allNumbers = true;
509 for(auto i0 = tn.CBegin(), i1 = tn.CEnd(); i0 != i1; ++i0)
511 auto type = (*i0).second.GetType();
512 if(!(type == TreeNode::FLOAT || type == TreeNode::INTEGER))
521 // NOTE: rotations / rectangles / extents must be disambiguated in all circumstances.
522 for(auto& r : kArrayPropertyProcessors)
525 if(propValue.GetType() != Property::NONE)
536 } // namespace Loader
537 } // namespace Scene3D