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, Property::Value (*)(const TreeNode*)> kTypeIds{
126 {"boolean", [](const TreeNode* tn) {
127 return ReadPrimitiveHelper<bool>(tn, ReadBool);
129 {"float", [](const TreeNode* tn) {
130 return ReadPrimitiveHelper<float>(tn, ReadFloat);
132 {"integer", [](const TreeNode* tn) {
133 return ReadPrimitiveHelper<int>(tn, ReadInt);
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) {
142 if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
144 return Property::Value(value);
146 return Property::Value();
148 {"rotation", ReadRotationHelper},
149 // STRING - not particularly animatable
150 // ARRAY - not particularly animatable
151 // MAP - not particularly animatable
152 {"extents", [](const TreeNode* tn) {
154 if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
156 return Property::Value(value);
158 return Property::Value();
162 Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
163 ReadVectorHelper<Matrix>,
164 ReadVectorHelper<Matrix3>,
165 ReadVectorHelper<Vector4>,
166 ReadVectorHelper<Vector3>,
167 ReadVectorHelper<Vector2>,
168 ReadVectorSingleFloatHelper};
172 bool ReadBool(const TreeNode* node, bool& num)
179 bool returnValue = false;
180 if(node->GetType() == TreeNode::BOOLEAN)
182 num = node->GetBoolean();
189 bool ReadInt(const TreeNode* node, int& num)
196 bool returnValue = false;
197 if(node->GetType() == TreeNode::INTEGER)
199 num = node->GetInteger();
202 else if(node->GetType() == TreeNode::FLOAT)
204 num = static_cast<int>(node->GetFloat());
211 bool ReadFloat(const TreeNode* node, float& num)
218 bool returnValue = false;
219 if(node->GetType() == TreeNode::FLOAT)
221 num = node->GetFloat();
224 else if(node->GetType() == TreeNode::INTEGER)
226 num = static_cast<float>(node->GetInteger());
233 bool ReadIndex(const Toolkit::TreeNode* node, Index& num)
235 bool returnValue = node && node->GetType() == TreeNode::INTEGER;
238 num = static_cast<Index>(node->GetInteger());
244 bool ReadBlob(const Toolkit::TreeNode* node, unsigned int& offset, unsigned int& length)
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.
257 offset = static_cast<unsigned int>(iOffset);
258 length = static_cast<unsigned int>(iLength);
263 size_t GetNumericalArraySize(const TreeNode* node)
266 if(node->GetType() == TreeNode::ARRAY)
268 for(auto i0 = node->CBegin(), i1 = node->CEnd(); i0 != i1 &&
269 ((*i0).second.GetType() == TreeNode::FLOAT || (*i0).second.GetType() == TreeNode::INTEGER);
278 bool ReadVector(const TreeNode* node, float* num, unsigned int size)
285 bool returnValue = false;
286 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
288 unsigned int offset = 0u;
289 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
291 const TreeNode& coord = (*it).second;
292 if(!ReadFloat(&coord, *(num + offset)))
303 bool ReadVector(const Toolkit::TreeNode* node, int* num, unsigned int size)
310 bool returnValue = false;
311 if((node->Size() >= size) && (node->GetType() == TreeNode::ARRAY))
313 unsigned int offset = 0u;
314 for(TreeNode::ConstIterator it = node->CBegin(); offset < size; ++it, ++offset)
316 const TreeNode& coord = (*it).second;
317 if(!ReadInt(&coord, *(num + offset)))
328 bool ReadColor(const TreeNode* node, Vector4& color)
335 if(!ReadVector(node, color.AsFloat(), 4))
337 if(!ReadVector(node, color.AsFloat(), 3))
347 bool ReadTimePeriod(const TreeNode* node, TimePeriod& timePeriod)
354 if(!ReadFloat(node->GetChild("delay"), timePeriod.delaySeconds) || !ReadFloat(node->GetChild("duration"), timePeriod.durationSeconds))
361 bool ReadString(const TreeNode* node, std::string& strValue)
368 bool returnValue = false;
369 if(node->GetType() == TreeNode::STRING)
371 strValue = node->GetString();
377 bool ReadStringVector(const TreeNode* node, std::vector<std::string>& strvector)
384 bool returnValue = false;
385 if(node->GetType() == TreeNode::ARRAY)
387 for(TreeNode::ConstIterator it = node->CBegin(); it != node->CEnd(); ++it)
389 const TreeNode& strNode = (*it).second;
390 if(strNode.GetType() == TreeNode::STRING)
392 strvector.push_back(strNode.GetString());
404 Property::Value ReadPropertyValue(const Property::Type& propType, const TreeNode& tn)
408 case Property::BOOLEAN:
409 return ReadPrimitiveHelper<bool>(&tn, ReadBool);
411 case Property::FLOAT:
412 return ReadPrimitiveHelper<float>(&tn, ReadFloat);
414 case Property::INTEGER:
415 return ReadPrimitiveHelper<int>(&tn, ReadInt);
417 case Property::VECTOR2:
418 return ReadVectorHelper<Vector2>(&tn);
420 case Property::VECTOR3:
421 return ReadVectorHelper<Vector3>(&tn);
423 case Property::VECTOR4:
424 return ReadVectorHelper<Vector4>(&tn);
426 case Property::MATRIX3:
427 return ReadVectorHelper<Matrix3>(&tn);
429 case Property::MATRIX:
430 return ReadVectorHelper<Matrix>(&tn);
432 case Property::RECTANGLE:
435 if(ReadQuadHelper<int>(&tn, {&value.x, &value.y, &value.width, &value.height}))
437 return Property::Value(value);
442 case Property::ROTATION:
443 return ReadRotationHelper(&tn);
445 case Property::EXTENTS:
448 if(ReadQuadHelper<uint16_t>(&tn, {&value.start, &value.end, &value.top, &value.bottom}))
450 return Property::Value(value);
455 case Property::NONE: // fall
458 DALI_ASSERT_ALWAYS(!"Property type incorrect");
461 return Property::Value();
464 Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
466 Property::Value propValue;
467 if(tn.GetType() == TreeNode::OBJECT) // attempt to disambiguate type.
469 auto jsonType = tn.GetChild("type");
470 if(jsonType && jsonType->GetType() == TreeNode::STRING)
472 auto iFind = kTypeIds.find(jsonType->GetString());
473 if(iFind != kTypeIds.end())
475 propValue = iFind->second(tn.GetChild("value"));
480 if(propValue.GetType() == Property::NONE)
486 case TreeNode::BOOLEAN:
487 propValue = ReadPrimitiveHelper<bool>(&tn, ReadBool);
490 case TreeNode::INTEGER:
491 propValue = ReadPrimitiveHelper<int>(&tn, ReadInt);
494 case TreeNode::FLOAT:
495 propValue = ReadPrimitiveHelper<float>(&tn, ReadFloat);
504 bool allNumbers = true;
505 for(auto i0 = tn.CBegin(), i1 = tn.CEnd(); i0 != i1; ++i0)
507 auto type = (*i0).second.GetType();
508 if(!(type == TreeNode::FLOAT || type == TreeNode::INTEGER))
517 // NOTE: rotations / rectangles / extents must be disambiguated in all circumstances.
518 for(auto& r : kArrayPropertyProcessors)
521 if(propValue.GetType() != Property::NONE)
532 } // namespace Loader
533 } // namespace Scene3D