cesium-native 0.46.0
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
PropertyView.h
1#pragma once
2
3#include <CesiumGltf/ClassProperty.h>
4#include <CesiumGltf/Enum.h>
5#include <CesiumGltf/PropertyAttributeProperty.h>
6#include <CesiumGltf/PropertyTableProperty.h>
7#include <CesiumGltf/PropertyTextureProperty.h>
8#include <CesiumGltf/PropertyType.h>
9#include <CesiumGltf/PropertyTypeTraits.h>
10
11#include <algorithm>
12#include <cstddef>
13#include <cstring>
14#include <optional>
15
16namespace CesiumGltf {
17
21typedef int32_t PropertyViewStatusType;
22
121
135template <typename T>
137 const ClassProperty& classProperty,
138 const CesiumGltf::Enum* pEnumDefinition = nullptr) {
139
141 convertStringToPropertyType(classProperty.type))) {
143 }
144
145 const bool isEnum = classProperty.type == ClassProperty::Type::ENUM;
146 const bool hasEnumDefinition = pEnumDefinition != nullptr;
147 if (isEnum != hasEnumDefinition) {
149 }
150
151 PropertyComponentType expectedComponentType =
153 if (isEnum) {
154 if (expectedComponentType !=
155 convertStringToPropertyComponentType(pEnumDefinition->valueType)) {
157 }
158 } else {
159 if (!classProperty.componentType &&
160 expectedComponentType != PropertyComponentType::None) {
162 }
163
164 if (classProperty.componentType &&
165 expectedComponentType != convertStringToPropertyComponentType(
166 *classProperty.componentType)) {
168 }
169 }
170
171 if (classProperty.array) {
173 }
174
176}
177
191template <typename T>
193 const ClassProperty& classProperty,
194 const CesiumGltf::Enum* pEnumDefinition = nullptr) {
195 using ElementType = typename MetadataArrayType<T>::type;
196
198 convertStringToPropertyType(classProperty.type))) {
200 }
201
202 const bool isEnum = classProperty.type == ClassProperty::Type::ENUM;
203 const bool hasEnumDefinition = pEnumDefinition != nullptr;
204 if (isEnum != hasEnumDefinition) {
206 }
207
208 PropertyComponentType expectedComponentType =
210 if (isEnum) {
211 if (expectedComponentType !=
212 convertStringToPropertyComponentType(pEnumDefinition->valueType)) {
214 }
215 } else {
216 if (!classProperty.componentType &&
217 expectedComponentType != PropertyComponentType::None) {
219 }
220
221 if (classProperty.componentType &&
222 expectedComponentType != convertStringToPropertyComponentType(
223 *classProperty.componentType)) {
225 }
226 }
227
228 if (!classProperty.array) {
230 }
231
233}
234
242template <typename T>
243static std::optional<T> getScalar(const CesiumUtility::JsonValue& jsonValue) {
244 return jsonValue.getSafeNumber<T>();
245}
246
256template <typename VecType>
257static std::optional<VecType>
258getVecN(const CesiumUtility::JsonValue& jsonValue) {
259 if (!jsonValue.isArray()) {
260 return std::nullopt;
261 }
262
263 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
264 constexpr glm::length_t N = VecType::length();
265 if (array.size() != N) {
266 return std::nullopt;
267 }
268
269 using T = typename VecType::value_type;
270
271 VecType result;
272 for (glm::length_t i = 0; i < N; i++) {
273 std::optional<T> value = getScalar<T>(array[static_cast<size_t>(i)]);
274 if (!value) {
275 return std::nullopt;
276 }
277
278 result[i] = *value;
279 }
280
281 return result;
282}
283
294template <typename MatType>
295static std::optional<MatType>
296getMatN(const CesiumUtility::JsonValue& jsonValue) {
297 if (!jsonValue.isArray()) {
298 return std::nullopt;
299 }
300
301 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
302 constexpr glm::length_t N = MatType::length();
303 if (array.size() != static_cast<size_t>(N * N)) {
304 return std::nullopt;
305 }
306
307 using T = typename MatType::value_type;
308
309 MatType result;
310 for (glm::length_t i = 0; i < N; i++) {
311 // Try to parse each value in the column.
312 for (glm::length_t j = 0; j < N; j++) {
313 std::optional<T> value =
314 getScalar<T>(array[static_cast<size_t>(i * N + j)]);
315 if (!value) {
316 return std::nullopt;
317 }
318
319 result[i][j] = *value;
320 }
321 }
322
323 return result;
324}
325
335template <typename ElementType>
336int64_t getCount(std::optional<std::vector<std::byte>>& buffer) {
337 if (!buffer) {
338 return 0;
339 }
340
341 return static_cast<int64_t>(buffer->size() / sizeof(ElementType));
342}
343
347template <typename ElementType, bool Normalized = false> class PropertyView;
348
361template <typename ElementType> class PropertyView<ElementType, false> {
362public:
367 : _status(PropertyViewStatus::ErrorNonexistentProperty),
368 _name(std::nullopt),
369 _semantic(std::nullopt),
370 _description(std::nullopt),
371 _offset(std::nullopt),
372 _scale(std::nullopt),
373 _max(std::nullopt),
374 _min(std::nullopt),
375 _required(false),
376 _noData(std::nullopt),
377 _defaultValue(std::nullopt),
378 _propertyType(PropertyType::Invalid) {}
379
383 PropertyView(const ClassProperty& classProperty)
384 : PropertyView(classProperty, nullptr) {}
385
391 const ClassProperty& classProperty,
392 const CesiumGltf::Enum* pEnumDefinition)
393 : _status(
394 validatePropertyType<ElementType>(classProperty, pEnumDefinition)),
395 _name(classProperty.name),
396 _semantic(classProperty.semantic),
397 _description(classProperty.description),
398 _offset(std::nullopt),
399 _scale(std::nullopt),
400 _max(std::nullopt),
401 _min(std::nullopt),
402 _required(classProperty.required),
403 _noData(std::nullopt),
404 _defaultValue(std::nullopt),
405 _propertyType(convertStringToPropertyType(classProperty.type)) {
406 if (_status != PropertyViewStatus::Valid) {
407 return;
408 }
409
410 if (classProperty.normalized) {
411 _status = PropertyViewStatus::ErrorNormalizationMismatch;
412 return;
413 }
414
415 if (classProperty.type != ClassProperty::Type::ENUM) {
416 getNumericPropertyValues(classProperty);
417 }
418
419 if (_status != PropertyViewStatus::Valid) {
420 return;
421 }
422
423 if (classProperty.noData) {
424 if (!_required && _propertyType == PropertyType::Enum) {
425 CESIUM_ASSERT(pEnumDefinition != nullptr);
426 if constexpr (IsMetadataInteger<ElementType>::value) {
427 // "noData" can only be defined if the property is not required.
428 _noData = getEnumValue(*classProperty.noData, *pEnumDefinition);
429 }
430 } else if (!_required && _propertyType != PropertyType::Enum) {
431 _noData = getValue(*classProperty.noData);
432 }
433
434 if (!_noData) {
435 // The value was specified but something went wrong.
437 return;
438 }
439 }
440
441 if (classProperty.defaultProperty) {
442 if (!_required && _propertyType == PropertyType::Enum) {
443 CESIUM_ASSERT(pEnumDefinition != nullptr);
444 if constexpr (IsMetadataInteger<ElementType>::value) {
445 // "default" can only be defined if the property is not required.
446 _defaultValue =
447 getEnumValue(*classProperty.defaultProperty, *pEnumDefinition);
448 }
449 } else if (!_required && _propertyType != PropertyType::Enum) {
450 _defaultValue = getValue(*classProperty.defaultProperty);
451 }
452
453 if (!_defaultValue) {
454 // The value was specified but something went wrong.
456 return;
457 }
458 }
459 }
460
461protected:
469 : _status(status),
470 _name(std::nullopt),
471 _semantic(std::nullopt),
472 _description(std::nullopt),
473 _offset(std::nullopt),
474 _scale(std::nullopt),
475 _max(std::nullopt),
476 _min(std::nullopt),
477 _required(false),
478 _noData(std::nullopt),
479 _defaultValue(std::nullopt),
480 _propertyType(PropertyType::Invalid) {}
481
487 const ClassProperty& classProperty,
488 const PropertyTableProperty& property,
489 const CesiumGltf::Enum* pEnumDefinition = nullptr)
490 : PropertyView(classProperty, pEnumDefinition) {
491 if (_status != PropertyViewStatus::Valid) {
492 return;
493 }
494
495 // If the property has its own values, override the class-provided values.
496 if (classProperty.type != ClassProperty::Type::ENUM) {
497 getNumericPropertyValues(property);
498 }
499 }
500
506 const ClassProperty& classProperty,
507 const PropertyTextureProperty& property,
508 const CesiumGltf::Enum* pEnumDefinition = nullptr)
509 : PropertyView(classProperty, pEnumDefinition) {
510 if (_status != PropertyViewStatus::Valid) {
511 return;
512 }
513
514 if (classProperty.type != ClassProperty::Type::ENUM) {
515 getNumericPropertyValues(property);
516 }
517 }
518
524 const ClassProperty& classProperty,
525 const PropertyAttributeProperty& property,
526 const CesiumGltf::Enum* pEnumDefinition = nullptr)
527 : PropertyView(classProperty, pEnumDefinition) {
528 if (_status != PropertyViewStatus::Valid) {
529 return;
530 }
531
532 // If the property has its own values, override the class-provided values.
533 if (classProperty.type != ClassProperty::Type::ENUM) {
534 getNumericPropertyValues(property);
535 }
536 }
537
538public:
545 PropertyViewStatusType status() const noexcept { return _status; }
546
551 const std::optional<std::string>& name() const noexcept { return _name; }
552
559 const std::optional<std::string>& semantic() const noexcept {
560 return _semantic;
561 }
562
567 const std::optional<std::string>& description() const noexcept {
568 return _description;
569 }
570
577 int64_t arrayCount() const noexcept { return 0; }
578
582 bool normalized() const noexcept { return false; }
583
591 std::optional<ElementType> offset() const noexcept { return _offset; }
592
600 std::optional<ElementType> scale() const noexcept { return _scale; }
601
611 std::optional<ElementType> max() const noexcept { return _max; }
612
622 std::optional<ElementType> min() const noexcept { return _min; }
623
629 bool required() const noexcept { return _required; }
630
640 std::optional<ElementType> noData() const noexcept { return _noData; }
641
650 std::optional<ElementType> defaultValue() const noexcept {
651 return _defaultValue;
652 }
653
658 PropertyType propertyType() const noexcept { return _propertyType; }
659
660protected:
663
664private:
665 std::optional<std::string> _name;
666 std::optional<std::string> _semantic;
667 std::optional<std::string> _description;
668
669 std::optional<ElementType> _offset;
670 std::optional<ElementType> _scale;
671 std::optional<ElementType> _max;
672 std::optional<ElementType> _min;
673
674 bool _required;
675 std::optional<ElementType> _noData;
676 std::optional<ElementType> _defaultValue;
677 PropertyType _propertyType;
678
689 static std::optional<ElementType>
690 getValue(const CesiumUtility::JsonValue& jsonValue) {
692 return getScalar<ElementType>(jsonValue);
693 }
694
696 return getVecN<ElementType>(jsonValue);
697 }
698
700 return getMatN<ElementType>(jsonValue);
701 }
702 }
703
704 static std::optional<ElementType> getEnumValue(
705 const CesiumUtility::JsonValue& value,
706 const CesiumGltf::Enum& enumDefinition) {
707 if (!value.isString()) {
708 return std::nullopt;
709 }
710
711 const CesiumUtility::JsonValue::String& valueStr = value.getString();
712 const auto foundValue = std::find_if(
713 enumDefinition.values.begin(),
714 enumDefinition.values.end(),
715 [&valueStr](const CesiumGltf::EnumValue& enumValue) {
716 return enumValue.name == valueStr;
717 });
718
719 if (foundValue == enumDefinition.values.end()) {
720 return std::nullopt;
721 }
722
723 return static_cast<ElementType>(foundValue->value);
724 }
725
726 using PropertyDefinitionType = std::variant<
727 ClassProperty,
728 PropertyTableProperty,
729 PropertyTextureProperty,
730 PropertyAttributeProperty>;
731
736 void getNumericPropertyValues(const PropertyDefinitionType& inProperty) {
737 std::visit(
738 [this](auto property) {
739 if (property.offset) {
740 // Only floating point types can specify an offset.
741 switch (TypeToPropertyType<ElementType>::component) {
742 case PropertyComponentType::Float32:
743 case PropertyComponentType::Float64:
744 this->_offset = getValue(*property.offset);
745 if (this->_offset) {
746 break;
747 }
748 // If it does not break here, something went wrong.
749 [[fallthrough]];
750 default:
751 this->_status = PropertyViewStatus::ErrorInvalidOffset;
752 return;
753 }
754 }
755
756 if (property.scale) {
757 // Only floating point types can specify a scale.
758 switch (TypeToPropertyType<ElementType>::component) {
759 case PropertyComponentType::Float32:
760 case PropertyComponentType::Float64:
761 this->_scale = getValue(*property.scale);
762 if (this->_scale) {
763 break;
764 }
765 // If it does not break here, something went wrong.
766 [[fallthrough]];
767 default:
768 this->_status = PropertyViewStatus::ErrorInvalidScale;
769 return;
770 }
771 }
772
773 if (property.max) {
774 this->_max = getValue(*property.max);
775 if (!this->_max) {
776 // The value was specified but something went wrong.
777 this->_status = PropertyViewStatus::ErrorInvalidMax;
778 return;
779 }
780 }
781
782 if (property.min) {
783 this->_min = getValue(*property.min);
784 if (!this->_min) {
785 // The value was specified but something went wrong.
786 this->_status = PropertyViewStatus::ErrorInvalidMin;
787 return;
788 }
789 }
790 },
791 inProperty);
792 }
793};
794
808template <typename ElementType> class PropertyView<ElementType, true> {
809private:
810 using NormalizedType = typename TypeToNormalizedType<ElementType>::type;
811
812public:
817 : _status(PropertyViewStatus::ErrorNonexistentProperty),
818 _name(std::nullopt),
819 _semantic(std::nullopt),
820 _description(std::nullopt),
821 _offset(std::nullopt),
822 _scale(std::nullopt),
823 _max(std::nullopt),
824 _min(std::nullopt),
825 _required(false),
826 _noData(std::nullopt),
827 _defaultValue(std::nullopt),
828 _propertyType(PropertyType::Invalid) {}
829
833 PropertyView(const ClassProperty& classProperty)
834 : _status(validatePropertyType<ElementType>(classProperty)),
835 _name(classProperty.name),
836 _semantic(classProperty.semantic),
837 _description(classProperty.description),
838 _offset(std::nullopt),
839 _scale(std::nullopt),
840 _max(std::nullopt),
841 _min(std::nullopt),
842 _required(classProperty.required),
843 _noData(std::nullopt),
844 _defaultValue(std::nullopt),
845 _propertyType(convertStringToPropertyType(classProperty.type)) {
846 if (_status != PropertyViewStatus::Valid) {
847 return;
848 }
849
850 if (!classProperty.normalized) {
851 _status = PropertyViewStatus::ErrorNormalizationMismatch;
852 }
853
854 getNumericPropertyValues(classProperty);
855 if (_status != PropertyViewStatus::Valid) {
856 return;
857 }
858
859 if (classProperty.noData) {
860 if (!_required) {
861 // "noData" should not be defined if the property is required.
862 _noData = getValue<ElementType>(*classProperty.noData);
863 }
864 if (!_noData) {
865 // The value was specified but something went wrong.
866 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
867 return;
868 }
869 }
870
871 if (classProperty.defaultProperty) {
872 // default value should not be defined if the property is required.
873 if (!_required) {
874 _defaultValue =
875 getValue<NormalizedType>(*classProperty.defaultProperty);
876 }
877 if (!_defaultValue) {
878 // The value was specified but something went wrong.
879 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
880 return;
881 }
882 }
883 }
884
885protected:
892 : _status(status),
893 _name(std::nullopt),
894 _semantic(std::nullopt),
895 _description(std::nullopt),
896 _offset(std::nullopt),
897 _scale(std::nullopt),
898 _max(std::nullopt),
899 _min(std::nullopt),
900 _required(false),
901 _noData(std::nullopt),
902 _defaultValue(std::nullopt),
903 _propertyType(PropertyType::Invalid) {}
904
910 const ClassProperty& classProperty,
911 const PropertyTableProperty& property)
912 : PropertyView(classProperty) {
913 if (_status != PropertyViewStatus::Valid) {
914 return;
915 }
916
917 // If the property has its own values, override the class-provided values.
918 getNumericPropertyValues(property);
919 }
920
926 const ClassProperty& classProperty,
927 const PropertyTextureProperty& property)
928 : PropertyView(classProperty) {
929 if (_status != PropertyViewStatus::Valid) {
930 return;
931 }
932
933 // If the property has its own values, override the class-provided values.
934 getNumericPropertyValues(property);
935 }
936
942 const ClassProperty& classProperty,
943 const PropertyAttributeProperty& property)
944 : PropertyView(classProperty) {
945 if (_status != PropertyViewStatus::Valid) {
946 return;
947 }
948
949 // If the property has its own values, override the class-provided values.
950 getNumericPropertyValues(property);
951 }
952
953public:
957 PropertyViewStatusType status() const noexcept { return _status; }
958
962 const std::optional<std::string>& name() const noexcept { return _name; }
963
967 const std::optional<std::string>& semantic() const noexcept {
968 return _semantic;
969 }
970
974 const std::optional<std::string>& description() const noexcept {
975 return _description;
976 }
977
981 int64_t arrayCount() const noexcept { return 0; }
982
986 bool normalized() const noexcept { return true; }
987
991 std::optional<NormalizedType> offset() const noexcept { return _offset; }
992
996 std::optional<NormalizedType> scale() const noexcept { return _scale; }
997
1001 std::optional<NormalizedType> max() const noexcept { return _max; }
1002
1006 std::optional<NormalizedType> min() const noexcept { return _min; }
1007
1011 bool required() const noexcept { return _required; }
1012
1016 std::optional<ElementType> noData() const noexcept { return _noData; }
1017
1021 std::optional<NormalizedType> defaultValue() const noexcept {
1022 return _defaultValue;
1023 }
1024
1029 PropertyType propertyType() const noexcept { return _propertyType; }
1030
1031protected:
1034
1035private:
1036 std::optional<std::string> _name;
1037 std::optional<std::string> _semantic;
1038 std::optional<std::string> _description;
1039
1040 std::optional<NormalizedType> _offset;
1041 std::optional<NormalizedType> _scale;
1042 std::optional<NormalizedType> _max;
1043 std::optional<NormalizedType> _min;
1044
1045 bool _required;
1046 std::optional<ElementType> _noData;
1047 std::optional<NormalizedType> _defaultValue;
1048 PropertyType _propertyType;
1049
1059 template <typename T>
1060 static std::optional<T> getValue(const CesiumUtility::JsonValue& jsonValue) {
1061 if constexpr (IsMetadataScalar<T>::value) {
1062 return getScalar<T>(jsonValue);
1063 }
1064
1065 if constexpr (IsMetadataVecN<T>::value) {
1066 return getVecN<T>(jsonValue);
1067 }
1068
1069 if constexpr (IsMetadataMatN<T>::value) {
1070 return getMatN<T>(jsonValue);
1071 }
1072 }
1073
1074 using PropertyDefinitionType = std::variant<
1079
1084 void getNumericPropertyValues(const PropertyDefinitionType& inProperty) {
1085 std::visit(
1086 [this](auto property) {
1087 if (property.offset) {
1088 _offset = getValue<NormalizedType>(*property.offset);
1089 if (!_offset) {
1090 // The value was specified but something went wrong.
1091 _status = PropertyViewStatus::ErrorInvalidOffset;
1092 return;
1093 }
1094 }
1095
1096 if (property.scale) {
1097 _scale = getValue<NormalizedType>(*property.scale);
1098 if (!_scale) {
1099 // The value was specified but something went wrong.
1100 _status = PropertyViewStatus::ErrorInvalidScale;
1101 return;
1102 }
1103 }
1104
1105 if (property.max) {
1106 _max = getValue<NormalizedType>(*property.max);
1107 if (!_scale) {
1108 // The value was specified but something went wrong.
1109 _status = PropertyViewStatus::ErrorInvalidMax;
1110 return;
1111 }
1112 }
1113
1114 if (property.min) {
1115 _min = getValue<NormalizedType>(*property.min);
1116 if (!_scale) {
1117 // The value was specified but something went wrong.
1118 _status = PropertyViewStatus::ErrorInvalidMin;
1119 return;
1120 }
1121 }
1122 },
1123 inProperty);
1124 }
1125};
1126
1131template <> class PropertyView<bool> {
1132public:
1137 : _status(PropertyViewStatus::ErrorNonexistentProperty),
1138 _name(std::nullopt),
1139 _semantic(std::nullopt),
1140 _description(std::nullopt),
1141 _required(false),
1142 _defaultValue(std::nullopt) {}
1143
1147 PropertyView(const ClassProperty& classProperty)
1148 : _status(validatePropertyType<bool>(classProperty)),
1149 _name(classProperty.name),
1150 _semantic(classProperty.semantic),
1151 _description(classProperty.description),
1152 _required(classProperty.required),
1153 _defaultValue(std::nullopt) {
1154 if (_status != PropertyViewStatus::Valid) {
1155 return;
1156 }
1157
1158 if (classProperty.defaultProperty) {
1159 if (!_required) {
1160 _defaultValue = getBooleanValue(*classProperty.defaultProperty);
1161 }
1162
1163 if (!_defaultValue) {
1164 // The value was specified but something went wrong.
1165 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1166 return;
1167 }
1168 }
1169 }
1170
1171protected:
1178 : _status(status),
1179 _name(std::nullopt),
1180 _semantic(std::nullopt),
1181 _description(std::nullopt),
1182 _required(false),
1183 _defaultValue(std::nullopt) {}
1184
1190 const ClassProperty& classProperty,
1191 const PropertyTableProperty& /*property*/,
1192 const CesiumGltf::Enum* /*pEnumDefinition*/)
1193 : PropertyView(classProperty) {}
1194
1195public:
1199 PropertyViewStatusType status() const noexcept { return _status; }
1200
1204 const std::optional<std::string>& name() const noexcept { return _name; }
1205
1209 const std::optional<std::string>& semantic() const noexcept {
1210 return _semantic;
1211 }
1212
1216 const std::optional<std::string>& description() const noexcept {
1217 return _description;
1218 }
1219
1223 int64_t arrayCount() const noexcept { return 0; }
1224
1228 bool normalized() const noexcept { return false; }
1229
1233 std::optional<bool> offset() const noexcept { return std::nullopt; }
1234
1238 std::optional<bool> scale() const noexcept { return std::nullopt; }
1239
1243 std::optional<bool> max() const noexcept { return std::nullopt; }
1244
1248 std::optional<bool> min() const noexcept { return std::nullopt; }
1249
1253 bool required() const noexcept { return _required; }
1254
1258 std::optional<bool> noData() const noexcept { return std::nullopt; }
1259
1263 std::optional<bool> defaultValue() const noexcept { return _defaultValue; }
1264
1269 PropertyType propertyType() const noexcept { return PropertyType::Boolean; }
1270
1271protected:
1274
1275private:
1276 std::optional<std::string> _name;
1277 std::optional<std::string> _semantic;
1278 std::optional<std::string> _description;
1279
1280 bool _required;
1281 std::optional<bool> _defaultValue;
1282
1283 static std::optional<bool>
1284 getBooleanValue(const CesiumUtility::JsonValue& value) {
1285 if (!value.isBool()) {
1286 return std::nullopt;
1287 }
1288
1289 return value.getBool();
1290 }
1291};
1292
1297template <> class PropertyView<std::string_view> {
1298public:
1303 : _status(PropertyViewStatus::ErrorNonexistentProperty),
1304 _name(std::nullopt),
1305 _semantic(std::nullopt),
1306 _description(std::nullopt),
1307 _required(false),
1308 _noData(std::nullopt),
1309 _defaultValue(std::nullopt) {}
1310
1314 PropertyView(const ClassProperty& classProperty)
1315 : _status(validatePropertyType<std::string_view>(classProperty)),
1316 _name(classProperty.name),
1317 _semantic(classProperty.semantic),
1318 _description(classProperty.description),
1319 _required(classProperty.required),
1320 _noData(std::nullopt),
1321 _defaultValue(std::nullopt) {
1322 if (_status != PropertyViewStatus::Valid) {
1323 return;
1324 }
1325
1326 if (classProperty.noData) {
1327 if (!_required) {
1328 _noData = getStringValue(*classProperty.noData);
1329 }
1330
1331 if (!_noData) {
1332 // The value was specified but something went wrong.
1333 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1334 return;
1335 }
1336 }
1337
1338 if (classProperty.defaultProperty) {
1339 if (!_required) {
1340 _defaultValue = getStringValue(*classProperty.defaultProperty);
1341 }
1342
1343 if (!_defaultValue) {
1344 // The value was specified but something went wrong.
1345 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1346 return;
1347 }
1348 }
1349 }
1350
1351protected:
1358 : _status(status),
1359 _name(std::nullopt),
1360 _semantic(std::nullopt),
1361 _description(std::nullopt),
1362 _required(false),
1363 _noData(std::nullopt),
1364 _defaultValue(std::nullopt) {}
1365
1371 const ClassProperty& classProperty,
1372 const PropertyTableProperty& /*property*/,
1373 const CesiumGltf::Enum* /*pEnumDefinition*/)
1374 : PropertyView(classProperty) {}
1375
1376public:
1380 PropertyViewStatusType status() const noexcept { return _status; }
1381
1385 const std::optional<std::string>& name() const noexcept { return _name; }
1386
1390 const std::optional<std::string>& semantic() const noexcept {
1391 return _semantic;
1392 }
1393
1397 const std::optional<std::string>& description() const noexcept {
1398 return _description;
1399 }
1400
1404 int64_t arrayCount() const noexcept { return 0; }
1405
1409 bool normalized() const noexcept { return false; }
1410
1414 std::optional<std::string_view> offset() const noexcept {
1415 return std::nullopt;
1416 }
1417
1421 std::optional<std::string_view> scale() const noexcept {
1422 return std::nullopt;
1423 }
1424
1428 std::optional<std::string_view> max() const noexcept { return std::nullopt; }
1429
1433 std::optional<std::string_view> min() const noexcept { return std::nullopt; }
1434
1438 bool required() const noexcept { return _required; }
1439
1443 std::optional<std::string_view> noData() const noexcept {
1444 if (_noData)
1445 return std::string_view(*_noData);
1446
1447 return std::nullopt;
1448 }
1449
1453 std::optional<std::string_view> defaultValue() const noexcept {
1454 if (_defaultValue)
1455 return std::string_view(*_defaultValue);
1456
1457 return std::nullopt;
1458 }
1459
1464 PropertyType propertyType() const noexcept { return PropertyType::String; }
1465
1466protected:
1469
1470private:
1471 std::optional<std::string> _name;
1472 std::optional<std::string> _semantic;
1473 std::optional<std::string> _description;
1474
1475 bool _required;
1476 std::optional<std::string> _noData;
1477 std::optional<std::string> _defaultValue;
1478
1479 static std::optional<std::string>
1480 getStringValue(const CesiumUtility::JsonValue& value) {
1481 if (!value.isString()) {
1482 return std::nullopt;
1483 }
1484
1485 return std::string(value.getString().c_str());
1486 }
1487};
1488
1502template <typename ElementType>
1503class PropertyView<PropertyArrayView<ElementType>, false> {
1504public:
1509 : _status(PropertyViewStatus::ErrorNonexistentProperty),
1510 _name(std::nullopt),
1511 _semantic(std::nullopt),
1512 _description(std::nullopt),
1513 _count(0),
1514 _offset(std::nullopt),
1515 _scale(std::nullopt),
1516 _max(std::nullopt),
1517 _min(std::nullopt),
1518 _required(false),
1519 _noData(std::nullopt),
1520 _defaultValue(std::nullopt),
1521 _propertyType(PropertyType::Invalid) {}
1522
1526 PropertyView(const ClassProperty& classProperty)
1527 : PropertyView(classProperty, nullptr) {}
1528
1534 const ClassProperty& classProperty,
1535 const CesiumGltf::Enum* pEnumDefinition)
1536 : _status(validateArrayPropertyType<PropertyArrayView<ElementType>>(
1537 classProperty,
1538 pEnumDefinition)),
1539 _name(classProperty.name),
1540 _semantic(classProperty.semantic),
1541 _description(classProperty.description),
1542 _count(classProperty.count ? *classProperty.count : 0),
1543 _offset(std::nullopt),
1544 _scale(std::nullopt),
1545 _max(std::nullopt),
1546 _min(std::nullopt),
1547 _required(classProperty.required),
1548 _noData(std::nullopt),
1549 _defaultValue(std::nullopt),
1550 _propertyType(convertStringToPropertyType(classProperty.type)) {
1551 if (_status != PropertyViewStatus::Valid) {
1552 return;
1553 }
1554
1555 if (classProperty.normalized) {
1556 _status = PropertyViewStatus::ErrorNormalizationMismatch;
1557 return;
1558 }
1559
1560 if (classProperty.type != ClassProperty::Type::ENUM) {
1561 getNumericPropertyValues(classProperty);
1562 }
1563
1564 if (_status != PropertyViewStatus::Valid) {
1565 return;
1566 }
1567
1568 if (classProperty.noData) {
1569 if (!_required && _propertyType == PropertyType::Enum) {
1570 CESIUM_ASSERT(pEnumDefinition != nullptr);
1571 if constexpr (IsMetadataInteger<ElementType>::value) {
1572 _noData = getEnumArrayValue(*classProperty.noData, *pEnumDefinition);
1573 }
1574 } else if (!_required && _propertyType != PropertyType::Enum) {
1575 _noData = getArrayValue(*classProperty.noData);
1576 }
1577
1578 if (!_noData) {
1579 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
1580 return;
1581 }
1582 }
1583
1584 if (classProperty.defaultProperty) {
1585 if (!_required && _propertyType == PropertyType::Enum) {
1586 CESIUM_ASSERT(pEnumDefinition != nullptr);
1587 if constexpr (IsMetadataInteger<ElementType>::value) {
1588 _defaultValue = getEnumArrayValue(
1589 *classProperty.defaultProperty,
1590 *pEnumDefinition);
1591 }
1592 } else if (!_required && _propertyType != PropertyType::Enum) {
1593 _defaultValue = getArrayValue(*classProperty.defaultProperty);
1594 }
1595
1596 if (!_defaultValue) {
1597 // The value was specified but something went wrong.
1598 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
1599 return;
1600 }
1601 }
1602 }
1603
1604protected:
1611 : _status(status),
1612 _name(std::nullopt),
1613 _semantic(std::nullopt),
1614 _description(std::nullopt),
1615 _count(0),
1616 _offset(std::nullopt),
1617 _scale(std::nullopt),
1618 _max(std::nullopt),
1619 _min(std::nullopt),
1620 _required(false),
1621 _noData(std::nullopt),
1622 _defaultValue(std::nullopt),
1623 _propertyType(PropertyType::Invalid) {}
1624
1630 const ClassProperty& classProperty,
1631 const PropertyTableProperty& property,
1632 const CesiumGltf::Enum* pEnumDefinition = nullptr)
1633 : PropertyView(classProperty, pEnumDefinition) {
1634 if (_status != PropertyViewStatus::Valid) {
1635 return;
1636 }
1637
1638 // If the property has its own values, override the class-provided values.
1639 if (classProperty.type != ClassProperty::Type::ENUM) {
1640 getNumericPropertyValues(property);
1641 }
1642 }
1643
1649 const ClassProperty& classProperty,
1650 const PropertyTextureProperty& property,
1651 const CesiumGltf::Enum* pEnumDefinition = nullptr)
1652 : PropertyView(classProperty, pEnumDefinition) {
1653 if (_status != PropertyViewStatus::Valid) {
1654 return;
1655 }
1656
1657 // If the property has its own values, override the class-provided values.
1658 if (classProperty.type != ClassProperty::Type::ENUM) {
1659 getNumericPropertyValues(property);
1660 }
1661 }
1662
1663public:
1667 PropertyViewStatusType status() const noexcept { return _status; }
1668
1672 const std::optional<std::string>& name() const noexcept { return _name; }
1673
1677 const std::optional<std::string>& semantic() const noexcept {
1678 return _semantic;
1679 }
1680
1684 const std::optional<std::string>& description() const noexcept {
1685 return _description;
1686 }
1687
1691 int64_t arrayCount() const noexcept { return _count; }
1692
1696 bool normalized() const noexcept { return false; }
1697
1701 std::optional<PropertyArrayView<ElementType>> offset() const noexcept {
1702 if (!_offset) {
1703 return std::nullopt;
1704 }
1705
1707 std::span<const std::byte>(_offset->data(), _offset->size()));
1708 }
1709
1713 std::optional<PropertyArrayView<ElementType>> scale() const noexcept {
1714 if (!_scale) {
1715 return std::nullopt;
1716 }
1717
1719 std::span<const std::byte>(_scale->data(), _scale->size()));
1720 }
1721
1725 std::optional<PropertyArrayView<ElementType>> max() const noexcept {
1726 if (!_max) {
1727 return std::nullopt;
1728 }
1729
1731 std::span<const std::byte>(_max->data(), _max->size()));
1732 }
1733
1737 std::optional<PropertyArrayView<ElementType>> min() const noexcept {
1738 if (!_min) {
1739 return std::nullopt;
1740 }
1741
1743 std::span<const std::byte>(_min->data(), _min->size()));
1744 }
1745
1749 bool required() const noexcept { return _required; }
1750
1754 std::optional<PropertyArrayView<ElementType>> noData() const noexcept {
1755 if (!_noData) {
1756 return std::nullopt;
1757 }
1758
1760 std::span<const std::byte>(_noData->data(), _noData->size()));
1761 }
1762
1766 std::optional<PropertyArrayView<ElementType>> defaultValue() const noexcept {
1767 if (!_defaultValue) {
1768 return std::nullopt;
1769 }
1770
1771 return PropertyArrayView<ElementType>(std::span<const std::byte>(
1772 _defaultValue->data(),
1773 _defaultValue->size()));
1774 }
1775
1780 PropertyType propertyType() const noexcept { return _propertyType; }
1781
1782protected:
1785
1786private:
1787 std::optional<std::string> _name;
1788 std::optional<std::string> _semantic;
1789 std::optional<std::string> _description;
1790
1791 int64_t _count;
1792
1793 std::optional<std::vector<std::byte>> _offset;
1794 std::optional<std::vector<std::byte>> _scale;
1795 std::optional<std::vector<std::byte>> _max;
1796 std::optional<std::vector<std::byte>> _min;
1797
1798 bool _required;
1799 std::optional<std::vector<std::byte>> _noData;
1800 std::optional<std::vector<std::byte>> _defaultValue;
1801 PropertyType _propertyType;
1802
1803 using PropertyDefinitionType = std::
1804 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
1805 void getNumericPropertyValues(const PropertyDefinitionType& inProperty) {
1806 std::visit(
1807 [this](auto property) {
1808 if (property.offset) {
1809 // Only floating point types can specify an offset.
1811 case PropertyComponentType::Float32:
1812 case PropertyComponentType::Float64:
1813 if (this->_count > 0) {
1814 this->_offset = getArrayValue(*property.offset);
1815 }
1816 if (this->_offset &&
1817 getCount<ElementType>(this->_offset) == this->_count) {
1818 break;
1819 }
1820 // If it does not break here, something went wrong.
1821 [[fallthrough]];
1822 default:
1823 this->_status = PropertyViewStatus::ErrorInvalidOffset;
1824 return;
1825 }
1826 }
1827
1828 if (property.scale) {
1829 // Only floating point types can specify a scale.
1831 case PropertyComponentType::Float32:
1832 case PropertyComponentType::Float64:
1833 if (_count > 0) {
1834 this->_scale = getArrayValue(*property.scale);
1835 }
1836 if (this->_scale &&
1837 getCount<ElementType>(this->_scale) == this->_count) {
1838 break;
1839 }
1840 // If it does not break here, something went wrong.
1841 [[fallthrough]];
1842 default:
1843 this->_status = PropertyViewStatus::ErrorInvalidScale;
1844 return;
1845 }
1846 }
1847
1848 if (property.max) {
1849 if (this->_count > 0) {
1850 this->_max = getArrayValue(*property.max);
1851 }
1852 if (!this->_max ||
1853 getCount<ElementType>(this->_max) != this->_count) {
1854 // The value was specified but something went wrong.
1855 this->_status = PropertyViewStatus::ErrorInvalidMax;
1856 return;
1857 }
1858 }
1859
1860 if (property.min) {
1861 if (this->_count > 0) {
1862 this->_min = getArrayValue(*property.min);
1863 }
1864 if (!this->_min ||
1865 getCount<ElementType>(this->_min) != this->_count) {
1866 // The value was specified but something went wrong.
1867 this->_status = PropertyViewStatus::ErrorInvalidMin;
1868 return;
1869 }
1870 }
1871 },
1872 inProperty);
1873 }
1874
1875 static std::optional<std::vector<std::byte>>
1876 getArrayValue(const CesiumUtility::JsonValue& jsonValue) {
1877 if (!jsonValue.isArray()) {
1878 return std::nullopt;
1879 }
1880
1881 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
1882 std::vector<ElementType> values;
1883 values.reserve(array.size());
1884
1885 if constexpr (IsMetadataScalar<ElementType>::value) {
1886 for (size_t i = 0; i < array.size(); i++) {
1887 std::optional<ElementType> element = getScalar<ElementType>(array[i]);
1888 if (!element) {
1889 return std::nullopt;
1890 }
1891
1892 values.push_back(*element);
1893 }
1894 }
1895 if constexpr (IsMetadataVecN<ElementType>::value) {
1896 for (size_t i = 0; i < array.size(); i++) {
1897 std::optional<ElementType> element = getVecN<ElementType>(array[i]);
1898 if (!element) {
1899 return std::nullopt;
1900 }
1901
1902 values.push_back(*element);
1903 }
1904 }
1905
1906 if constexpr (IsMetadataMatN<ElementType>::value) {
1907 for (size_t i = 0; i < array.size(); i++) {
1908 std::optional<ElementType> element = getMatN<ElementType>(array[i]);
1909 if (!element) {
1910 return std::nullopt;
1911 }
1912
1913 values.push_back(*element);
1914 }
1915 }
1916
1917 std::vector<std::byte> result(values.size() * sizeof(ElementType));
1918 std::memcpy(result.data(), values.data(), result.size());
1919
1920 return result;
1921 }
1922
1923 static std::optional<std::vector<std::byte>> getEnumArrayValue(
1924 const CesiumUtility::JsonValue& jsonValue,
1925 const CesiumGltf::Enum& enumDefinition) {
1926 if (!jsonValue.isArray()) {
1927 return std::nullopt;
1928 }
1929
1930 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
1931 std::vector<ElementType> values;
1932 values.reserve(array.size());
1933
1934 for (size_t i = 0; i < array.size(); i++) {
1935 if (!array[i].isString()) {
1936 return std::nullopt;
1937 }
1938
1939 // default and noData values for enums contain the name of the enum as a
1940 // string
1941 CesiumUtility::JsonValue::String str = array[i].getString();
1942 auto foundValue = std::find_if(
1943 enumDefinition.values.begin(),
1944 enumDefinition.values.end(),
1945 [&str](const CesiumGltf::EnumValue& enumValue) {
1946 return enumValue.name == str;
1947 });
1948
1949 if (foundValue == enumDefinition.values.end()) {
1950 return std::nullopt;
1951 }
1952
1953 values.push_back(static_cast<ElementType>(foundValue->value));
1954 }
1955
1956 std::vector<std::byte> result(values.size() * sizeof(ElementType));
1957 std::memcpy(result.data(), values.data(), result.size());
1958 return result;
1959 }
1960};
1961
1975template <typename ElementType>
1976class PropertyView<PropertyArrayView<ElementType>, true> {
1977private:
1978 using NormalizedType = typename TypeToNormalizedType<ElementType>::type;
1979
1980public:
1985 : _status(PropertyViewStatus::ErrorNonexistentProperty),
1986 _name(std::nullopt),
1987 _semantic(std::nullopt),
1988 _description(std::nullopt),
1989 _count(0),
1990 _offset(std::nullopt),
1991 _scale(std::nullopt),
1992 _max(std::nullopt),
1993 _min(std::nullopt),
1994 _required(false),
1995 _noData(std::nullopt),
1996 _defaultValue(std::nullopt),
1997 _propertyType(PropertyType::Invalid) {}
1998
2002 PropertyView(const ClassProperty& classProperty)
2003 : _status(validateArrayPropertyType<PropertyArrayView<ElementType>>(
2004 classProperty)),
2005 _name(classProperty.name),
2006 _semantic(classProperty.semantic),
2007 _description(classProperty.description),
2008 _count(classProperty.count ? *classProperty.count : 0),
2009 _offset(std::nullopt),
2010 _scale(std::nullopt),
2011 _max(std::nullopt),
2012 _min(std::nullopt),
2013 _required(classProperty.required),
2014 _noData(std::nullopt),
2015 _defaultValue(std::nullopt),
2016 _propertyType(convertStringToPropertyType(classProperty.type)) {
2017 if (_status != PropertyViewStatus::Valid) {
2018 return;
2019 }
2020
2021 if (!classProperty.normalized) {
2022 _status = PropertyViewStatus::ErrorNormalizationMismatch;
2023 return;
2024 }
2025
2026 getNumericPropertyValues(classProperty);
2027 if (_status != PropertyViewStatus::Valid) {
2028 return;
2029 }
2030
2031 if (classProperty.noData) {
2032 if (!_required) {
2033 _noData = getArrayValue<ElementType>(*classProperty.noData);
2034 }
2035
2036 if (!_noData) {
2037 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
2038 return;
2039 }
2040 }
2041
2042 if (classProperty.defaultProperty) {
2043 if (!_required) {
2044 _defaultValue =
2045 getArrayValue<NormalizedType>(*classProperty.defaultProperty);
2046 }
2047
2048 if (!_defaultValue) {
2049 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2050 return;
2051 }
2052 }
2053 }
2054
2055protected:
2062 : _status(status),
2063 _name(std::nullopt),
2064 _semantic(std::nullopt),
2065 _description(std::nullopt),
2066 _count(0),
2067 _offset(std::nullopt),
2068 _scale(std::nullopt),
2069 _max(std::nullopt),
2070 _min(std::nullopt),
2071 _required(false),
2072 _noData(std::nullopt),
2073 _defaultValue(std::nullopt),
2074 _propertyType(PropertyType::Invalid) {}
2075
2081 const ClassProperty& classProperty,
2082 const PropertyTableProperty& property)
2083 : PropertyView(classProperty) {
2084 if (_status != PropertyViewStatus::Valid) {
2085 return;
2086 }
2087
2088 // If the property has its own values, override the class-provided values.
2089 getNumericPropertyValues(property);
2090 }
2091
2097 const ClassProperty& classProperty,
2098 const PropertyTextureProperty& property)
2099 : PropertyView(classProperty) {
2100 if (_status != PropertyViewStatus::Valid) {
2101 return;
2102 }
2103
2104 // If the property has its own values, override the class-provided values.
2105 getNumericPropertyValues(property);
2106 }
2107
2108public:
2112 PropertyViewStatusType status() const noexcept { return _status; }
2113
2117 const std::optional<std::string>& name() const noexcept { return _name; }
2118
2122 const std::optional<std::string>& semantic() const noexcept {
2123 return _semantic;
2124 }
2125
2129 const std::optional<std::string>& description() const noexcept {
2130 return _description;
2131 }
2132
2136 int64_t arrayCount() const noexcept { return _count; }
2137
2141 bool normalized() const noexcept { return true; }
2142
2146 std::optional<PropertyArrayView<NormalizedType>> offset() const noexcept {
2147 if (!_offset) {
2148 return std::nullopt;
2149 }
2150
2152 std::span<const std::byte>(_offset->data(), _offset->size()));
2153 }
2154
2158 std::optional<PropertyArrayView<NormalizedType>> scale() const noexcept {
2159 if (!_scale) {
2160 return std::nullopt;
2161 }
2162
2164 std::span<const std::byte>(_scale->data(), _scale->size()));
2165 }
2166
2170 std::optional<PropertyArrayView<NormalizedType>> max() const noexcept {
2171 if (!_max) {
2172 return std::nullopt;
2173 }
2174
2176 std::span<const std::byte>(_max->data(), _max->size()));
2177 }
2178
2182 std::optional<PropertyArrayView<NormalizedType>> min() const noexcept {
2183 if (!_min) {
2184 return std::nullopt;
2185 }
2186
2188 std::span<const std::byte>(_min->data(), _min->size()));
2189 }
2190
2194 bool required() const noexcept { return _required; }
2195
2199 std::optional<PropertyArrayView<ElementType>> noData() const noexcept {
2200 if (!_noData) {
2201 return std::nullopt;
2202 }
2203
2205 std::span<const std::byte>(_noData->data(), _noData->size()));
2206 }
2207
2211 std::optional<PropertyArrayView<NormalizedType>>
2212 defaultValue() const noexcept {
2213 if (!_defaultValue) {
2214 return std::nullopt;
2215 }
2216
2217 return PropertyArrayView<NormalizedType>(std::span<const std::byte>(
2218 _defaultValue->data(),
2219 _defaultValue->size()));
2220 }
2221
2226 PropertyType propertyType() const noexcept { return _propertyType; }
2227
2228protected:
2231
2232private:
2233 std::optional<std::string> _name;
2234 std::optional<std::string> _semantic;
2235 std::optional<std::string> _description;
2236
2237 int64_t _count;
2238
2239 std::optional<std::vector<std::byte>> _offset;
2240 std::optional<std::vector<std::byte>> _scale;
2241 std::optional<std::vector<std::byte>> _max;
2242 std::optional<std::vector<std::byte>> _min;
2243
2244 bool _required;
2245 std::optional<std::vector<std::byte>> _noData;
2246 std::optional<std::vector<std::byte>> _defaultValue;
2247 PropertyType _propertyType;
2248
2249 using PropertyDefinitionType = std::
2250 variant<ClassProperty, PropertyTableProperty, PropertyTextureProperty>;
2251 void getNumericPropertyValues(const PropertyDefinitionType& inProperty) {
2252 std::visit(
2253 [this](auto property) {
2254 if (property.offset) {
2255 if (_count > 0) {
2256 _offset = getArrayValue<NormalizedType>(*property.offset);
2257 }
2258 if (!_offset || getCount<NormalizedType>(_offset) != _count) {
2259 // The value was specified but something went wrong.
2260 _status = PropertyViewStatus::ErrorInvalidOffset;
2261 return;
2262 }
2263 }
2264
2265 if (property.scale) {
2266 if (_count > 0) {
2267 _scale = getArrayValue<NormalizedType>(*property.scale);
2268 }
2269 if (!_scale || getCount<NormalizedType>(_scale) != _count) {
2270 // The value was specified but something went wrong.
2271 _status = PropertyViewStatus::ErrorInvalidScale;
2272 return;
2273 }
2274 }
2275
2276 if (property.max) {
2277 if (_count > 0) {
2278 _max = getArrayValue<NormalizedType>(*property.max);
2279 }
2280 if (!_max || getCount<NormalizedType>(_max) != _count) {
2281 // The value was specified but something went wrong.
2282 _status = PropertyViewStatus::ErrorInvalidMax;
2283 return;
2284 }
2285 }
2286
2287 if (property.min) {
2288 if (_count > 0) {
2289 _min = getArrayValue<NormalizedType>(*property.min);
2290 }
2291 if (!_min || getCount<NormalizedType>(_min) != _count) {
2292 // The value was specified but something went wrong.
2293 _status = PropertyViewStatus::ErrorInvalidMin;
2294 return;
2295 }
2296 }
2297 },
2298 inProperty);
2299 }
2300
2301 template <typename T>
2302 static std::optional<std::vector<std::byte>>
2303 getArrayValue(const CesiumUtility::JsonValue& jsonValue) {
2304 if (!jsonValue.isArray()) {
2305 return std::nullopt;
2306 }
2307
2308 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
2309 std::vector<T> values;
2310 values.reserve(array.size());
2311
2312 if constexpr (IsMetadataScalar<T>::value) {
2313 for (size_t i = 0; i < array.size(); i++) {
2314 std::optional<T> element = getScalar<T>(array[i]);
2315 if (!element) {
2316 return std::nullopt;
2317 }
2318
2319 values.push_back(*element);
2320 }
2321 }
2322
2323 if constexpr (IsMetadataVecN<T>::value) {
2324 for (size_t i = 0; i < array.size(); i++) {
2325 std::optional<T> element = getVecN<T>(array[i]);
2326 if (!element) {
2327 return std::nullopt;
2328 }
2329
2330 values.push_back(*element);
2331 }
2332 }
2333
2334 if constexpr (IsMetadataMatN<T>::value) {
2335 for (size_t i = 0; i < array.size(); i++) {
2336 std::optional<T> element = getMatN<T>(array[i]);
2337 if (!element) {
2338 return std::nullopt;
2339 }
2340
2341 values.push_back(*element);
2342 }
2343 }
2344
2345 std::vector<std::byte> result(values.size() * sizeof(T));
2346 std::memcpy(result.data(), values.data(), result.size());
2347
2348 return result;
2349 }
2350};
2351
2356template <> class PropertyView<PropertyArrayView<bool>> {
2357public:
2362 : _status(PropertyViewStatus::ErrorNonexistentProperty),
2363 _name(std::nullopt),
2364 _semantic(std::nullopt),
2365 _description(std::nullopt),
2366 _count(0),
2367 _required(false),
2368 _defaultValue(),
2369 _size(0) {}
2370
2374 PropertyView(const ClassProperty& classProperty)
2375 : _status(
2376 validateArrayPropertyType<PropertyArrayView<bool>>(classProperty)),
2377 _name(classProperty.name),
2378 _semantic(classProperty.semantic),
2379 _description(classProperty.description),
2380 _count(classProperty.count ? *classProperty.count : 0),
2381 _required(classProperty.required),
2382 _defaultValue(),
2383 _size(0) {
2384 if (_status != PropertyViewStatus::Valid) {
2385 return;
2386 }
2387
2388 if (classProperty.defaultProperty) {
2389 if (!_required) {
2390 _defaultValue =
2391 getBooleanArrayValue(*classProperty.defaultProperty, _size);
2392 }
2393
2394 if (_size == 0 || (_count > 0 && _size != _count)) {
2395 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2396 return;
2397 }
2398 }
2399 }
2400
2401protected:
2408 : _status(status),
2409 _name(std::nullopt),
2410 _semantic(std::nullopt),
2411 _description(std::nullopt),
2412 _count(0),
2413 _required(false),
2414 _defaultValue(),
2415 _size(0) {}
2416
2422 const ClassProperty& classProperty,
2423 const PropertyTableProperty& /*property*/,
2424 const CesiumGltf::Enum* /*pEnumDefinition*/)
2425 : PropertyView(classProperty) {}
2426
2427public:
2431 PropertyViewStatusType status() const noexcept { return _status; }
2432
2436 const std::optional<std::string>& name() const noexcept { return _name; }
2437
2441 const std::optional<std::string>& semantic() const noexcept {
2442 return _semantic;
2443 }
2444
2448 const std::optional<std::string>& description() const noexcept {
2449 return _description;
2450 }
2451
2455 int64_t arrayCount() const noexcept { return _count; }
2456
2460 bool normalized() const noexcept { return false; }
2461
2465 std::optional<PropertyArrayView<bool>> offset() const noexcept {
2466 return std::nullopt;
2467 }
2468
2472 std::optional<PropertyArrayView<bool>> scale() const noexcept {
2473 return std::nullopt;
2474 }
2475
2479 std::optional<PropertyArrayView<bool>> max() const noexcept {
2480 return std::nullopt;
2481 }
2482
2486 std::optional<PropertyArrayView<bool>> min() const noexcept {
2487 return std::nullopt;
2488 }
2489
2493 bool required() const noexcept { return _required; }
2494
2498 std::optional<PropertyArrayView<bool>> noData() const noexcept {
2499 return std::nullopt;
2500 }
2501
2505 std::optional<PropertyArrayView<bool>> defaultValue() const noexcept {
2506 if (_size > 0) {
2508 std::span<const std::byte>(
2509 _defaultValue.data(),
2510 _defaultValue.size()),
2511 /* bitOffset = */ 0,
2512 _size);
2513 }
2514
2515 return std::nullopt;
2516 }
2517
2522 PropertyType propertyType() const noexcept { return PropertyType::Boolean; }
2523
2524protected:
2527
2528private:
2529 std::optional<std::string> _name;
2530 std::optional<std::string> _semantic;
2531 std::optional<std::string> _description;
2532
2533 int64_t _count;
2534 bool _required;
2535
2536 std::vector<std::byte> _defaultValue;
2537 int64_t _size;
2538
2539 static std::vector<std::byte> getBooleanArrayValue(
2540 const CesiumUtility::JsonValue& jsonValue,
2541 int64_t& size) {
2542 if (!jsonValue.isArray()) {
2543 return std::vector<std::byte>();
2544 }
2545
2546 const CesiumUtility::JsonValue::Array& array = jsonValue.getArray();
2547 std::vector<std::byte> values;
2548 values.reserve((array.size() / 8) + 1);
2549
2550 size_t byteIndex = 0;
2551 uint8_t bitIndex = 0;
2552
2553 for (size_t i = 0; i < array.size(); i++, size++) {
2554 if (!array[i].isBool()) {
2555 size = 0;
2556 return values;
2557 }
2558
2559 if (values.size() < byteIndex - 1) {
2560 values.push_back(std::byte(0));
2561 }
2562
2563 std::byte value = std::byte(array[i].getBool() ? 1 : 0);
2564 value = value << bitIndex;
2565
2566 values[byteIndex] |= value;
2567
2568 bitIndex++;
2569 if (bitIndex > 7) {
2570 byteIndex++;
2571 bitIndex = 0;
2572 }
2573 }
2574
2575 return values;
2576 }
2577};
2578
2583template <> class PropertyView<PropertyArrayView<std::string_view>> {
2584public:
2589 : _status(PropertyViewStatus::ErrorNonexistentProperty),
2590 _name(std::nullopt),
2591 _semantic(std::nullopt),
2592 _description(std::nullopt),
2593 _count(0),
2594 _required(false),
2595 _noData(),
2596 _defaultValue() {}
2597
2601 PropertyView(const ClassProperty& classProperty)
2602 : _status(validateArrayPropertyType<PropertyArrayView<std::string_view>>(
2603 classProperty)),
2604 _name(classProperty.name),
2605 _semantic(classProperty.semantic),
2606 _description(classProperty.description),
2607 _count(classProperty.count ? *classProperty.count : 0),
2608 _required(classProperty.required),
2609 _noData(),
2610 _defaultValue() {
2611 if (_status != PropertyViewStatus::Valid) {
2612 return;
2613 }
2614
2615 if (classProperty.noData) {
2616 if (!_required) {
2617 _noData = getStringArrayValue(*classProperty.noData);
2618 }
2619
2620 if (_noData.size == 0 || (_count > 0 && _noData.size != _count)) {
2621 _status = PropertyViewStatus::ErrorInvalidNoDataValue;
2622 return;
2623 }
2624 }
2625
2626 if (classProperty.defaultProperty) {
2627 if (!_required) {
2628 _defaultValue = getStringArrayValue(*classProperty.defaultProperty);
2629 }
2630
2631 if (_defaultValue.size == 0 ||
2632 (_count > 0 && _defaultValue.size != _count)) {
2633 // The value was specified but something went wrong.
2634 _status = PropertyViewStatus::ErrorInvalidDefaultValue;
2635 return;
2636 }
2637 }
2638 }
2639
2640protected:
2647 : _status(status),
2648 _name(std::nullopt),
2649 _semantic(std::nullopt),
2650 _description(std::nullopt),
2651 _count(0),
2652 _required(false),
2653 _noData(),
2654 _defaultValue() {}
2655
2661 const ClassProperty& classProperty,
2662 const PropertyTableProperty& /*property*/,
2663 const CesiumGltf::Enum* /*pEnumDefinition*/)
2664 : PropertyView(classProperty) {}
2665
2666public:
2670 PropertyViewStatusType status() const noexcept { return _status; }
2671
2675 const std::optional<std::string>& name() const noexcept { return _name; }
2676
2680 const std::optional<std::string>& semantic() const noexcept {
2681 return _semantic;
2682 }
2683
2687 const std::optional<std::string>& description() const noexcept {
2688 return _description;
2689 }
2690
2694 int64_t arrayCount() const noexcept { return _count; }
2695
2699 bool normalized() const noexcept { return false; }
2700
2704 std::optional<PropertyArrayView<std::string_view>> offset() const noexcept {
2705 return std::nullopt;
2706 }
2707
2711 std::optional<PropertyArrayView<std::string_view>> scale() const noexcept {
2712 return std::nullopt;
2713 }
2714
2718 std::optional<PropertyArrayView<std::string_view>> max() const noexcept {
2719 return std::nullopt;
2720 }
2721
2725 std::optional<PropertyArrayView<std::string_view>> min() const noexcept {
2726 return std::nullopt;
2727 }
2728
2732 bool required() const noexcept { return _required; }
2733
2737 std::optional<PropertyArrayView<std::string_view>> noData() const noexcept {
2738 if (_noData.size > 0) {
2740 std::span<const std::byte>(_noData.data.data(), _noData.data.size()),
2741 std::span<const std::byte>(
2742 _noData.offsets.data(),
2743 _noData.offsets.size()),
2744 _noData.offsetType,
2745 _noData.size);
2746 }
2747
2748 return std::nullopt;
2749 }
2750
2754 std::optional<PropertyArrayView<std::string_view>>
2755 defaultValue() const noexcept {
2756 if (_defaultValue.size > 0) {
2758 std::span<const std::byte>(
2759 _defaultValue.data.data(),
2760 _defaultValue.data.size()),
2761 std::span<const std::byte>(
2762 _defaultValue.offsets.data(),
2763 _defaultValue.offsets.size()),
2764 _defaultValue.offsetType,
2765 _defaultValue.size);
2766 }
2767
2768 return std::nullopt;
2769 }
2770
2775 PropertyType propertyType() const noexcept { return PropertyType::String; }
2776
2777protected:
2780
2781private:
2782 std::optional<std::string> _name;
2783 std::optional<std::string> _semantic;
2784 std::optional<std::string> _description;
2785
2786 int64_t _count;
2787 bool _required;
2788
2789 struct StringArrayValue {
2790 std::vector<std::byte> data;
2791 std::vector<std::byte> offsets;
2792 PropertyComponentType offsetType = PropertyComponentType::None;
2793 int64_t size = 0;
2794 };
2795
2796 StringArrayValue _noData;
2797 StringArrayValue _defaultValue;
2798
2799 static StringArrayValue
2800 getStringArrayValue(const CesiumUtility::JsonValue& jsonValue) {
2801 StringArrayValue result;
2802 if (!jsonValue.isArray()) {
2803 return result;
2804 }
2805
2806 std::vector<std::string> strings;
2807 std::vector<uint64_t> stringOffsets;
2808
2809 const auto& array = jsonValue.getArray();
2810 strings.reserve(array.size());
2811 stringOffsets.reserve(array.size() + 1);
2812 stringOffsets.push_back(static_cast<uint64_t>(0));
2813
2814 for (size_t i = 0; i < array.size(); i++) {
2815 if (!array[i].isString()) {
2816 // The entire array is invalidated; return.
2817 return result;
2818 }
2819
2820 const std::string& string = array[i].getString();
2821 strings.push_back(string);
2822 stringOffsets.push_back(stringOffsets[i] + string.size());
2823 }
2824
2825 uint64_t totalLength = stringOffsets.back();
2826 result.data.resize(totalLength);
2827 for (size_t i = 0; i < strings.size(); ++i) {
2828 std::memcpy(
2829 result.data.data() + stringOffsets[i],
2830 strings[i].data(),
2831 strings[i].size());
2832 };
2833
2834 if (totalLength <= std::numeric_limits<uint8_t>::max()) {
2835 result.offsets = narrowOffsetsBuffer<uint8_t>(stringOffsets);
2836 result.offsetType = PropertyComponentType::Uint8;
2837 } else if (totalLength <= std::numeric_limits<uint16_t>::max()) {
2838 result.offsets = narrowOffsetsBuffer<uint16_t>(stringOffsets);
2839 result.offsetType = PropertyComponentType::Uint16;
2840 } else if (totalLength <= std::numeric_limits<uint32_t>::max()) {
2841 result.offsets = narrowOffsetsBuffer<uint32_t>(stringOffsets);
2842 result.offsetType = PropertyComponentType::Uint32;
2843 } else {
2844 result.offsets.resize(stringOffsets.size() * sizeof(uint64_t));
2845 std::memcpy(
2846 result.offsets.data(),
2847 stringOffsets.data(),
2848 result.offsets.size());
2849 result.offsetType = PropertyComponentType::Uint64;
2850 }
2851
2852 result.size = static_cast<int64_t>(strings.size());
2853
2854 return result;
2855 }
2856
2857 template <typename T>
2858 static std::vector<std::byte>
2859 narrowOffsetsBuffer(std::vector<uint64_t> offsets) {
2860 std::vector<std::byte> result(offsets.size() * sizeof(T));
2861 size_t bufferOffset = 0;
2862 for (size_t i = 0; i < offsets.size(); i++, bufferOffset += sizeof(T)) {
2863 T offset = static_cast<T>(offsets[i]);
2864 std::memcpy(result.data() + bufferOffset, &offset, sizeof(T));
2865 }
2866
2867 return result;
2868 }
2869};
2870
2871} // namespace CesiumGltf
A view on an array element of a PropertyTableProperty or PropertyTextureProperty.
Indicates the status of a property view.
static const PropertyViewStatusType ErrorTypeMismatch
This property view's type does not match what is specified in ClassProperty::type.
static const PropertyViewStatusType ErrorInvalidDefaultValue
The property provided an invalid default value.
static const PropertyViewStatusType ErrorInvalidMin
The property provided an invalid minimum value.
static const PropertyViewStatusType ErrorInvalidMax
The property provided an invalid maximum value.
static const PropertyViewStatusType ErrorInvalidOffset
The property provided an invalid offset value.
static const PropertyViewStatusType Valid
This property view is valid and ready to use.
static const PropertyViewStatusType ErrorNonexistentProperty
This property view is trying to view a property that does not exist.
static const PropertyViewStatusType ErrorInvalidNormalization
This property says it is normalized, but it does not have an integer component type.
static const PropertyViewStatusType ErrorArrayTypeMismatch
This property view differs from what is specified in ClassProperty::array.
static const PropertyViewStatusType ErrorInvalidNoDataValue
The property provided an invalid "no data" value.
static const PropertyViewStatusType ErrorNormalizationMismatch
This property view's normalization differs from what is specified in ClassProperty::normalized.
static const PropertyViewStatusType ErrorInvalidEnum
The property provided an invalid enum value.
static const PropertyViewStatusType EmptyPropertyWithDefault
This property view does not contain any data, but specifies a default value. This happens when a clas...
static const PropertyViewStatusType ErrorInvalidScale
The property provided an invalid scale value.
static const PropertyViewStatusType ErrorComponentTypeMismatch
This property view's component type does not match what is specified in ClassProperty::componentType.
std::optional< ElementType > offset() const noexcept
Gets the offset to apply to property values. Only applicable to SCALAR, VECN, and MATN types when the...
std::optional< ElementType > scale() const noexcept
Gets the scale to apply to property values. Only applicable to SCALAR, VECN, and MATN types when the ...
bool required() const noexcept
Whether the property must be present in every entity conforming to the class. If not required,...
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Constructs a property instance from a property table property and its class definition,...
std::optional< ElementType > defaultValue() const noexcept
Gets the default value to use when encountering a "no data" value or an omitted property....
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Constructs a property instance from a property texture property, class definition,...
PropertyView(const ClassProperty &classProperty, const PropertyAttributeProperty &property, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Constructs a property instance from a property attribute property and its class definition,...
const std::optional< std::string > & name() const noexcept
Gets the name of the property being viewed. Returns std::nullopt if no name was specified.
PropertyViewStatusType _status
Indicates the status of a property view.
const std::optional< std::string > & semantic() const noexcept
Gets the semantic of the property being viewed. The semantic is an identifier that describes how this...
bool normalized() const noexcept
Whether this property has a normalized integer type.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
int64_t arrayCount() const noexcept
Get the element count of the fixed-length arrays in this property. Only applicable when the property ...
PropertyViewStatusType status() const noexcept
Gets the status of this property view, indicating whether an error occurred.
std::optional< ElementType > noData() const noexcept
Gets the "no data" value, i.e., the value representing missing data in the property wherever it appea...
std::optional< ElementType > min() const noexcept
Gets the minimum allowed value for the property. Only applicable to SCALAR, VECN, and MATN types....
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
std::optional< ElementType > max() const noexcept
Gets the maximum allowed value for the property. Only applicable to SCALAR, VECN, and MATN types....
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
PropertyView(const ClassProperty &classProperty, const CesiumGltf::Enum *pEnumDefinition)
Constructs a property instance from a class definition and enum definition.
const std::optional< std::string > & description() const noexcept
Gets the description of the property being viewed. Returns std::nullopt if no description was specifi...
PropertyView()
Constructs an empty property instance.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
std::optional< ElementType > noData() const noexcept
Constructs an empty property instance. false>noData
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< NormalizedType > max() const noexcept
Constructs an empty property instance. false>max
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
PropertyView(const ClassProperty &classProperty, const PropertyAttributeProperty &property)
Constructs a property instance from a property attribute property and its class definition.
PropertyViewStatusType _status
Indicates the status of a property view.
std::optional< NormalizedType > scale() const noexcept
Constructs an empty property instance. false>scale
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyView()
Constructs an empty property instance.
std::optional< NormalizedType > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< NormalizedType > offset() const noexcept
Constructs an empty property instance. false>offset
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< NormalizedType > min() const noexcept
Constructs an empty property instance. false>min
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Constructs a property instance from a property texture property, its class definition,...
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< PropertyArrayView< ElementType > > offset() const noexcept
Constructs an empty property instance. false>offset
std::optional< PropertyArrayView< ElementType > > max() const noexcept
Constructs an empty property instance. false>max
std::optional< PropertyArrayView< ElementType > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< PropertyArrayView< ElementType > > min() const noexcept
Constructs an empty property instance. false>min
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
PropertyView(const ClassProperty &classProperty, const CesiumGltf::Enum *pEnumDefinition)
Constructs a property instance from a class definition and enum definition.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyType propertyType() const noexcept
Returns the PropertyType of the property that this view is accessing.
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Constructs a property instance from a property table property, its class definition,...
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< PropertyArrayView< ElementType > > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< PropertyArrayView< NormalizedType > > max() const noexcept
Constructs an empty property instance. false>max
PropertyViewStatusType _status
Indicates the status of a property view.
std::optional< PropertyArrayView< NormalizedType > > scale() const noexcept
Constructs an empty property instance. false>scale
std::optional< PropertyArrayView< ElementType > > noData() const noexcept
Constructs an empty property instance. false>noData
std::optional< PropertyArrayView< NormalizedType > > min() const noexcept
Constructs an empty property instance. false>min
PropertyView(const ClassProperty &classProperty, const PropertyTextureProperty &property)
Constructs a property instance from a property texture property and its class definition.
std::optional< PropertyArrayView< NormalizedType > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &property)
Constructs a property instance from a property table property and its class definition.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< PropertyArrayView< NormalizedType > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
std::optional< PropertyArrayView< bool > > min() const noexcept
Constructs an empty property instance. false>min
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
std::optional< PropertyArrayView< bool > > max() const noexcept
Constructs an empty property instance. false>max
std::optional< PropertyArrayView< bool > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
PropertyView()
Constructs an empty property instance.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &, const CesiumGltf::Enum *)
Constructs a property instance from a property table property and its class definition.
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
bool required() const noexcept
Constructs an empty property instance. false>required
std::optional< PropertyArrayView< bool > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< PropertyArrayView< bool > > scale() const noexcept
Constructs an empty property instance. false>scale
std::optional< PropertyArrayView< bool > > noData() const noexcept
Constructs an empty property instance. false>noData
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
std::optional< PropertyArrayView< std::string_view > > max() const noexcept
Constructs an empty property instance. false>max
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
std::optional< PropertyArrayView< std::string_view > > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyViewStatusType _status
Indicates the status of a property view.
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
std::optional< PropertyArrayView< std::string_view > > min() const noexcept
Constructs an empty property instance. false>min
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
std::optional< PropertyArrayView< std::string_view > > noData() const noexcept
Constructs an empty property instance. false>noData
bool required() const noexcept
Constructs an empty property instance. false>required
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &, const CesiumGltf::Enum *)
Constructs a property instance from a property table property and its class definition.
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< PropertyArrayView< std::string_view > > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< PropertyArrayView< std::string_view > > scale() const noexcept
Constructs an empty property instance. false>scale
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
std::optional< bool > min() const noexcept
Constructs an empty property instance. false>min
std::optional< bool > noData() const noexcept
Constructs an empty property instance. false>noData
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
bool required() const noexcept
Constructs an empty property instance. false>required
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
std::optional< bool > scale() const noexcept
Constructs an empty property instance. false>scale
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &, const CesiumGltf::Enum *)
Constructs a property instance from a property table property and its class definition.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyView()
Constructs an empty property instance.
std::optional< bool > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
std::optional< bool > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< bool > max() const noexcept
Constructs an empty property instance. false>max
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
bool required() const noexcept
Constructs an empty property instance. false>required
const std::optional< std::string > & name() const noexcept
Constructs an empty property instance. false>name
PropertyView()
Constructs an empty property instance.
std::optional< std::string_view > min() const noexcept
Constructs an empty property instance. false>min
std::optional< std::string_view > offset() const noexcept
Constructs an empty property instance. false>offset
PropertyViewStatusType _status
Indicates the status of a property view.
PropertyView(const ClassProperty &classProperty)
Constructs a property instance from a class definition only.
std::optional< std::string_view > scale() const noexcept
Constructs an empty property instance. false>scale
const std::optional< std::string > & description() const noexcept
Constructs an empty property instance. false>description
PropertyView(const ClassProperty &classProperty, const PropertyTableProperty &, const CesiumGltf::Enum *)
Constructs a property instance from a property table property and its class definition.
std::optional< std::string_view > defaultValue() const noexcept
Constructs an empty property instance. false>defaultValue
PropertyType propertyType() const noexcept
Returns the PropertyType of the property this view is accessing.
int64_t arrayCount() const noexcept
Constructs an empty property instance. false>arrayCount
PropertyView(PropertyViewStatusType status)
Constructs an invalid instance for an erroneous property.
std::optional< std::string_view > noData() const noexcept
Constructs an empty property instance. false>noData
std::optional< std::string_view > max() const noexcept
Constructs an empty property instance. false>max
const std::optional< std::string > & semantic() const noexcept
Constructs an empty property instance. false>semantic
bool normalized() const noexcept
Constructs an empty property instance. false>normalized
PropertyViewStatusType status() const noexcept
Constructs an empty property instance. false>status
Represents a metadata property in EXT_structural_metadata.
A generic implementation of a value in a JSON structure.
Definition JsonValue.h:53
bool getBool() const
Gets the bool from the value.
Definition JsonValue.h:449
const JsonValue::String & getString() const
Gets the string from the value.
Definition JsonValue.h:418
std::vector< JsonValue > Array
The type to represent an Array JSON value.
Definition JsonValue.h:78
bool isBool() const noexcept
Returns whether this value is a Bool value.
Definition JsonValue.h:570
std::string String
The type to represent a String JSON value.
Definition JsonValue.h:68
bool isArray() const noexcept
Returns whether this value is an Array value.
Definition JsonValue.h:591
bool isString() const noexcept
Returns whether this value is a String value.
Definition JsonValue.h:577
std::optional< To > getSafeNumber() const
Gets the numerical quantity from the value casted to the To type. This function should be used over g...
Definition JsonValue.h:351
const JsonValue::Array & getArray() const
Gets the array from the value.
Definition JsonValue.h:428
Classes for working with glTF models.
PropertyComponentType
The possible types of a property component.
PropertyComponentType convertStringToPropertyComponentType(const std::string &str)
Converts a string into a PropertyComponentType.
PropertyViewStatusType validatePropertyType(const ClassProperty &classProperty, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Validates a ClassProperty representing a property, checking for any type mismatches.
PropertyViewStatusType validateArrayPropertyType(const ClassProperty &classProperty, const CesiumGltf::Enum *pEnumDefinition=nullptr)
Validates a ClassProperty representing an array of values, checking for any type mismatches.
bool canRepresentPropertyType(PropertyType type)
Returns whether the type T can represent the given PropertyType.
int64_t getCount(std::optional< std::vector< std::byte > > &buffer)
Obtains the number of values of type ElementType that could fit in the buffer.
PropertyType convertStringToPropertyType(const std::string &str)
Converts a string into a PropertyType.
PropertyType
The possible types of a property in a PropertyTableView.
@ Invalid
An invalid property type.
int32_t PropertyViewStatusType
The type used for fields of PropertyViewStatus.
STL namespace.
static const std::string ENUM
ENUM
bool normalized
Specifies whether integer values are normalized. Only applicable to SCALAR, VECN, and MATN types with...
std::optional< std::string > componentType
The datatype of the element's components. Only applicable to SCALAR, VECN, and MATN types.
bool array
Whether the property is an array. When count is defined the property is a fixed-length array....
std::optional< CesiumUtility::JsonValue > noData
A noData value represents missing data — also known as a sentinel value — wherever it appears....
std::string type
The element type.
std::optional< CesiumUtility::JsonValue > defaultProperty
A default value to use when encountering a noData value or an omitted property. The value is given in...
std::vector< CesiumGltf::EnumValue > values
An array of enum values. Duplicate names or duplicate integer values are not allowed.
Definition EnumSpec.h:74
An enum value.
Definition EnumValue.h:16
This class is not meant to be instantiated directly. Use Enum instead.
Definition Enum.h:12
Check if a C++ type can be represented as a matN type.
Check if a C++ type can be represented as a scalar property type.
Check if a C++ type can be represented as a vecN type.
void type
The component type of this metadata array.
An attribute containing property values.
An array of binary property values.
A texture containing property values.
Convert an integer numeric type to the corresponding representation as a double type....
Infer the best-fitting PropertyType and PropertyComponentType for a C++ type.