diff --git a/CHANGES.md b/CHANGES.md index dd2bc7a37..150640f2f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,17 @@ ### ? - ? +##### Breaking Changes :mega: + +- `FCesiumPrimitiveMetadata::GetPropertyAttributeIndices` is now deprecated. Use `GetPropertyAttributes` to directly get the `FCesiumPropertyAttribute`s instead. + +##### Additions :tada: + +- Added `FCesiumPropertyAttributeProperty` to represent glTF property attribute properties and `UCesiumPropertyAttributePropertyBlueprintLibrary` to retrieve their values. +- Added `FCesiumPropertyAttribute` to represent glTF property attributes and `UCesiumPropertyAttributeBlueprintLibrary` to act upon them with Blueprints. +- Added `UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributes` to retrieve the property attributes from a `FCesiumPrimitiveMetadata`. +- Added `UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger64`. Although 64-bit integers aren't directly supported by property textures, this enables the lossless retrieval of 32-bit unsigned integers. + ##### Fixes :wrench: - Fixed error messages in the Unreal log about uninitialized fields in `FCesiumGeocoderServiceAttribution` and `FCesiumGeocoderServiceFeature`. diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index e1036fd7b..4df6f8457 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -1093,7 +1093,7 @@ static void loadPrimitiveFeaturesMetadata( pFeatures ? FCesiumPrimitiveFeatures(model, primitive, *pFeatures) : FCesiumPrimitiveFeatures(); primitiveResult.Metadata = - pMetadata ? FCesiumPrimitiveMetadata(primitive, *pMetadata) + pMetadata ? FCesiumPrimitiveMetadata(model, primitive, *pMetadata) : FCesiumPrimitiveMetadata(); PRAGMA_DISABLE_DEPRECATION_WARNINGS diff --git a/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp b/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp index 10d15324c..d35de16d6 100644 --- a/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp +++ b/Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp @@ -1,26 +1,51 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumPrimitiveMetadata.h" -#include "CesiumGltf/AccessorView.h" -#include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h" -#include "CesiumGltf/Model.h" #include "CesiumGltfPrimitiveComponent.h" +#include "CesiumPropertyAttribute.h" + +#include +#include +#include static FCesiumPrimitiveMetadata EmptyPrimitiveMetadata; FCesiumPrimitiveMetadata::FCesiumPrimitiveMetadata( - const CesiumGltf::MeshPrimitive& Primitive, - const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata) - : _propertyTextureIndices(), _propertyAttributeIndices() { - this->_propertyTextureIndices.Reserve(Metadata.propertyTextures.size()); - for (const int64 propertyTextureIndex : Metadata.propertyTextures) { + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& metadata) + : _propertyTextureIndices(), + _propertyAttributes(), + _propertyAttributeIndices() { + this->_propertyTextureIndices.Reserve(metadata.propertyTextures.size()); + for (const int64 propertyTextureIndex : metadata.propertyTextures) { this->_propertyTextureIndices.Emplace(propertyTextureIndex); } - this->_propertyAttributeIndices.Reserve(Metadata.propertyAttributes.size()); - for (const int64 propertyAttributeIndex : Metadata.propertyAttributes) { + // For backwards compatibility with GetPropertyAttributeIndices(). + this->_propertyAttributeIndices.Reserve(metadata.propertyAttributes.size()); + for (const int64 propertyAttributeIndex : metadata.propertyAttributes) { this->_propertyAttributeIndices.Emplace(propertyAttributeIndex); } + + const auto* pModelMetadata = + model.getExtension(); + if (!pModelMetadata) { + return; + } + + for (const int64 propertyAttributeIndex : metadata.propertyAttributes) { + if (propertyAttributeIndex < 0 || + propertyAttributeIndex >= + int64_t(pModelMetadata->propertyAttributes.size())) { + continue; + } + + this->_propertyAttributes.Emplace(FCesiumPropertyAttribute( + model, + primitive, + pModelMetadata->propertyAttributes[propertyAttributeIndex])); + } } const FCesiumPrimitiveMetadata& @@ -41,6 +66,12 @@ UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices( return PrimitiveMetadata._propertyTextureIndices; } +const TArray& +UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributes( + UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) { + return PrimitiveMetadata._propertyAttributes; +} + const TArray& UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributeIndices( UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) { diff --git a/Source/CesiumRuntime/Private/CesiumPropertyAttribute.cpp b/Source/CesiumRuntime/Private/CesiumPropertyAttribute.cpp new file mode 100644 index 000000000..2b6a935b7 --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumPropertyAttribute.cpp @@ -0,0 +1,143 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyAttribute.h" +#include + +static FCesiumPropertyAttributeProperty EmptyPropertyAttributeProperty; + +FCesiumPropertyAttribute::FCesiumPropertyAttribute( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::PropertyAttribute& propertyAttribute, + const TSharedPtr& pEnumCollection) + : _status( + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttributeClass), + _name(propertyAttribute.name.value_or("").c_str()), + _className(propertyAttribute.classProperty.c_str()), + _elementCount(0), + _properties() { + CesiumGltf::PropertyAttributeView propertyAttributeView{ + model, + propertyAttribute}; + switch (propertyAttributeView.status()) { + case CesiumGltf::PropertyAttributeViewStatus::Valid: + _status = ECesiumPropertyAttributeStatus::Valid; + break; + default: + // Status was already set in initializer list. + return; + } + + const CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = + model.getExtension(); + // If there was no schema, we would've gotten ErrorMissingSchema for the + // propertyAttributeView status. + check(pExtension != nullptr && pExtension->schema != nullptr); + + propertyAttributeView.forEachProperty( + primitive, + [&properties = _properties, + &elementCount = _elementCount, + &Schema = *pExtension->schema, + &propertyAttributeView, + &pEnumCollection]( + const std::string& propertyName, + auto propertyValue) mutable { + FString key(UTF8_TO_TCHAR(propertyName.data())); + const CesiumGltf::ClassProperty* pClassProperty = + propertyAttributeView.getClassProperty(propertyName); + check(pClassProperty); + + TSharedPtr pEnumDefinition(nullptr); + if (pEnumCollection.IsValid() && pClassProperty->enumType.has_value()) { + pEnumDefinition = pEnumCollection->Get( + FString(UTF8_TO_TCHAR(pClassProperty->enumType.value().c_str()))); + } + + if (elementCount == 0) { + // Use the first non-zero property size to compare against all the + // others. + elementCount = propertyValue.size(); + } + + if (propertyValue.size() > 0 && elementCount != propertyValue.size()) { + UE_LOG( + LogCesium, + Error, + TEXT( + "The size of one or more property attribute properties does not match the others.")); + } + + properties.Add( + key, + FCesiumPropertyAttributeProperty(propertyValue, pEnumDefinition)); + }); +} + +/*static*/ ECesiumPropertyAttributeStatus +UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) { + return PropertyAttribute._status; +} + +/*static*/ const FString& +UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeName( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) { + return PropertyAttribute._name; +} + +/*static*/ const TMap& +UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) { + return PropertyAttribute._properties; +} + +/*static*/ const TArray +UCesiumPropertyAttributeBlueprintLibrary::GetPropertyNames( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) { + TArray names; + PropertyAttribute._properties.GenerateKeyArray(names); + return names; +} + +/*static*/ const FCesiumPropertyAttributeProperty& +UCesiumPropertyAttributeBlueprintLibrary::FindProperty( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute, + const FString& PropertyName) { + const FCesiumPropertyAttributeProperty* property = + PropertyAttribute._properties.Find(PropertyName); + return property ? *property : EmptyPropertyAttributeProperty; +} + +/*static*/ TMap +UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute, + int64 Index) { + TMap values; + if (Index < 0 || Index >= PropertyAttribute._elementCount) { + return values; + } + + for (const auto& pair : PropertyAttribute._properties) { + const FCesiumPropertyAttributeProperty& property = pair.Value; + ECesiumPropertyAttributePropertyStatus status = + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property); + if (status == ECesiumPropertyAttributePropertyStatus::Valid) { + values.Add( + pair.Key, + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + pair.Value, + Index)); + } else if ( + status == + ECesiumPropertyAttributePropertyStatus::EmptyPropertyWithDefault) { + values.Add( + pair.Key, + UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue( + pair.Value)); + } + } + + return values; +} diff --git a/Source/CesiumRuntime/Private/CesiumPropertyAttributeProperty.cpp b/Source/CesiumRuntime/Private/CesiumPropertyAttributeProperty.cpp new file mode 100644 index 000000000..2c394f0c7 --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumPropertyAttributeProperty.cpp @@ -0,0 +1,870 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyAttributeProperty.h" +#include "CesiumMetadataEnum.h" +#include "UnrealMetadataConversions.h" +#include +#include +#include + +namespace { +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView of the specified type. If the type does not + * match, the callback is performed on an invalid PropertyAttributePropertyView + * instead. + * + * @param property The std::any containing the property. + * @param callback The callback function. + * + * @tparam TProperty The property type. + * @tparam Normalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template < + typename TProperty, + bool Normalized, + typename TResult, + typename Callback> +TResult propertyAttributePropertyCallback( + const std::any& property, + Callback&& callback) { + const CesiumGltf::PropertyAttributePropertyView* + pProperty = std::any_cast< + CesiumGltf::PropertyAttributePropertyView>( + &property); + if (pProperty) { + return callback(*pProperty); + } + + return callback(CesiumGltf::PropertyAttributePropertyView()); +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView on a scalar type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyAttributePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult scalarPropertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyAttributePropertyCallback< + int8_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyAttributePropertyCallback< + uint8_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyAttributePropertyCallback< + int16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyAttributePropertyCallback< + uint16_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyAttributePropertyCallback< + uint32_t, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyAttributePropertyCallback( + property, + std::forward(callback)); + default: + return callback(CesiumGltf::PropertyAttributePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView on a glm::vecN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyAttributePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::vecN + * @tparam Normalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyAttributePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyAttributePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyAttributePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyAttributePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyAttributePropertyCallback< + glm::vec, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyAttributePropertyCallback< + glm::vec, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyAttributePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView on a glm::vecN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyAttributePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult vecNPropertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.Type) { + case ECesiumMetadataType::Vec2: + return vecNPropertyAttributePropertyCallback< + 2, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + case ECesiumMetadataType::Vec3: + return vecNPropertyAttributePropertyCallback< + 3, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + case ECesiumMetadataType::Vec4: + return vecNPropertyAttributePropertyCallback< + 4, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyAttributePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView on a glm::matN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyAttributePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam N The dimensions of the glm::matN + * @tparam TNormalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNPropertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + switch (valueType.ComponentType) { + case ECesiumMetadataComponentType::Int8: + return propertyAttributePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint8: + return propertyAttributePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Int16: + return propertyAttributePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint16: + return propertyAttributePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Uint32: + return propertyAttributePropertyCallback< + glm::mat, + Normalized, + TResult, + Callback>(property, std::forward(callback)); + case ECesiumMetadataComponentType::Float32: + return propertyAttributePropertyCallback< + glm::mat, + false, + TResult, + Callback>(property, std::forward(callback)); + default: + return callback(CesiumGltf::PropertyAttributePropertyView()); + } +} + +/** + * Callback on a std::any, assuming that it contains a + * PropertyAttributePropertyView on a glm::matN type. If the valueType does not + * have a valid component type, the callback is performed on an invalid + * PropertyAttributePropertyView instead. + * + * @param property The std::any containing the property. + * @param valueType The FCesiumMetadataValueType of the property. + * @param callback The callback function. + * + * @tparam Normalized Whether the PropertyAttributePropertyView is normalized. + * @tparam TResult The type of the output from the callback function. + * @tparam Callback The callback function type. + */ +template +TResult matNPropertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + Callback&& callback) { + if (valueType.Type == ECesiumMetadataType::Mat2) { + return matNPropertyAttributePropertyCallback< + 2, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat3) { + return matNPropertyAttributePropertyCallback< + 3, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + if (valueType.Type == ECesiumMetadataType::Mat4) { + return matNPropertyAttributePropertyCallback< + 4, + Normalized, + TResult, + Callback>(property, valueType, std::forward(callback)); + } + + return callback(CesiumGltf::PropertyAttributePropertyView()); +} + +template +TResult propertyAttributePropertyCallback( + const std::any& property, + const FCesiumMetadataValueType& valueType, + bool normalized, + Callback&& callback) { + if (valueType.bIsArray) { + // Array types are not supported for property attribute properties. + return callback(CesiumGltf::PropertyAttributePropertyView()); + } + + switch (valueType.Type) { + case ECesiumMetadataType::Scalar: + return normalized ? scalarPropertyAttributePropertyCallback< + true, + TResult, + Callback>( + property, + valueType, + std::forward(callback)) + : scalarPropertyAttributePropertyCallback< + false, + TResult, + Callback>( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Enum: + return scalarPropertyAttributePropertyCallback( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Vec2: + case ECesiumMetadataType::Vec3: + case ECesiumMetadataType::Vec4: + return normalized + ? vecNPropertyAttributePropertyCallback( + property, + valueType, + std::forward(callback)) + : vecNPropertyAttributePropertyCallback< + false, + TResult, + Callback>( + property, + valueType, + std::forward(callback)); + case ECesiumMetadataType::Mat2: + case ECesiumMetadataType::Mat3: + case ECesiumMetadataType::Mat4: + return normalized + ? matNPropertyAttributePropertyCallback( + property, + valueType, + std::forward(callback)) + : matNPropertyAttributePropertyCallback< + false, + TResult, + Callback>( + property, + valueType, + std::forward(callback)); + default: + return callback(CesiumGltf::PropertyAttributePropertyView()); + } +} + +} // namespace + +ECesiumPropertyAttributePropertyStatus +UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return Property._status; +} + +ECesiumMetadataBlueprintType +UCesiumPropertyAttributePropertyBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return CesiumMetadataValueTypeToBlueprintType(Property._valueType); +} + +FCesiumMetadataValueType +UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return Property._valueType; +} + +int64 UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> int64 { return view.size(); }); +} + +uint8 UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + uint8 DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, DefaultValue](const auto& v) -> uint8 { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +int32 UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + int32 DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, DefaultValue](const auto& v) -> int32 { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +int64 UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + int64 DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, DefaultValue](const auto& v) -> int64 { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +float UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + float DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, DefaultValue](const auto& v) -> float { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +double UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + double DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, DefaultValue](const auto& v) -> double { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + +FIntPoint UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntPoint( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FIntPoint& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FIntPoint { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntPoint(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toIntPoint(*maybeVec2) + : DefaultValue; + } + }); +} + +FVector2D UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector2D& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FVector2D { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector2D(value, DefaultValue); + } else { + auto maybeVec2 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec2 ? UnrealMetadataConversions::toVector2D(*maybeVec2) + : DefaultValue; + } + }); +} + +FIntVector UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FIntVector& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FIntVector { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toIntVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toIntVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector3f UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector3f& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FVector3f { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector3f(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector3f(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FVector { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector(value, DefaultValue); + } else { + auto maybeVec3 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec3 ? UnrealMetadataConversions::toVector(*maybeVec3) + : DefaultValue; + } + }); +} + +FVector4 UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector4& DefaultValue) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &DefaultValue](const auto& v) -> FVector4 { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return DefaultValue; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return DefaultValue; + } + + auto value = *maybeValue; + if constexpr (CesiumGltf::IsMetadataString::value) { + return UnrealMetadataConversions::toVector4(value, DefaultValue); + } else { + auto maybeVec4 = CesiumGltf:: + MetadataConversions::convert(value); + return maybeVec4 ? UnrealMetadataConversions::toVector4(*maybeVec4) + : DefaultValue; + } + }); +} + +FMatrix UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FMatrix& DefaultValue) { + auto maybeMat4 = propertyAttributePropertyCallback>( + Property._property, + Property._valueType, + Property._normalized, + [Index](const auto& v) -> std::optional { + // size() returns zero if the view is invalid. + if (Index < 0 || Index >= v.size()) { + return std::nullopt; + } + auto maybeValue = v.get(Index); + if (!maybeValue) { + return std::nullopt; + } + + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value); + }); + + return maybeMat4 ? UnrealMetadataConversions::toMatrix(*maybeMat4) + : DefaultValue; +} + +FCesiumMetadataValue UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &pEnumDefinition = Property._pEnumDefinition]( + const auto& view) -> FCesiumMetadataValue { + // size() returns zero if the view is invalid. + if (Index >= 0 && Index < view.size()) { + return FCesiumMetadataValue(view.get(Index), pEnumDefinition); + } + return FCesiumMetadataValue(); + }); +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetRawValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [Index, &pEnumDefinition = Property._pEnumDefinition]( + const auto& view) -> FCesiumMetadataValue { + // Return an empty value if the property is empty. + if (view.status() == CesiumGltf::PropertyAttributePropertyViewStatus:: + EmptyPropertyWithDefault) { + return FCesiumMetadataValue(); + } + + // size() returns zero if the view is invalid. + if (Index >= 0 && Index < view.size()) { + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.getRaw(Index)), + pEnumDefinition); + } + + return FCesiumMetadataValue(); + }); +} + +bool UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return Property._normalized; +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetOffset( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no offset is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.offset())); + }); +} + +FCesiumMetadataValue UCesiumPropertyAttributePropertyBlueprintLibrary::GetScale( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no scale is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.scale())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetMinimumValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no min is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.min())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetMaximumValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no max is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.max())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetNoDataValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no "no data" value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.noData())); + }); +} + +FCesiumMetadataValue +UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property) { + return propertyAttributePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [](const auto& view) -> FCesiumMetadataValue { + // Returns an empty value if no default value is specified. + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.defaultValue())); + }); +} diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp index e4cfac944..0e4cca91c 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp @@ -1,20 +1,21 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumPropertyTable.h" -#include "CesiumGltf/PropertyTableView.h" + +#include static FCesiumPropertyTableProperty EmptyPropertyTableProperty; FCesiumPropertyTable::FCesiumPropertyTable( - const CesiumGltf::Model& Model, - const CesiumGltf::PropertyTable& PropertyTable, - const TSharedPtr& EnumCollection) + const CesiumGltf::Model& model, + const CesiumGltf::PropertyTable& propertyTable, + const TSharedPtr& pEnumCollection) : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTableClass), - _name(PropertyTable.name.value_or("").c_str()), - _className(PropertyTable.classProperty.c_str()), - _count(PropertyTable.count), + _name(propertyTable.name.value_or("").c_str()), + _className(propertyTable.classProperty.c_str()), + _count(propertyTable.count), _properties() { - CesiumGltf::PropertyTableView propertyTableView{Model, PropertyTable}; + CesiumGltf::PropertyTableView propertyTableView{model, propertyTable}; switch (propertyTableView.status()) { case CesiumGltf::PropertyTableViewStatus::Valid: _status = ECesiumPropertyTableStatus::Valid; @@ -25,7 +26,7 @@ FCesiumPropertyTable::FCesiumPropertyTable( } const CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = - Model.getExtension(); + model.getExtension(); // If there was no schema, we would've gotten ErrorMissingSchema for the // propertyTableView status. check(pExtension != nullptr && pExtension->schema != nullptr); @@ -33,7 +34,7 @@ FCesiumPropertyTable::FCesiumPropertyTable( propertyTableView.forEachProperty([&properties = _properties, &Schema = *pExtension->schema, &propertyTableView, - &EnumCollection]( + &pEnumCollection]( const std::string& propertyName, auto propertyValue) mutable { FString key(UTF8_TO_TCHAR(propertyName.data())); @@ -41,15 +42,15 @@ FCesiumPropertyTable::FCesiumPropertyTable( propertyTableView.getClassProperty(propertyName); check(pClassProperty); - TSharedPtr EnumDefinition(nullptr); - if (EnumCollection.IsValid() && pClassProperty->enumType.has_value()) { - EnumDefinition = EnumCollection->Get( + TSharedPtr pEnumDefinition(nullptr); + if (pEnumCollection.IsValid() && pClassProperty->enumType.has_value()) { + pEnumDefinition = pEnumCollection->Get( FString(UTF8_TO_TCHAR(pClassProperty->enumType.value().c_str()))); } properties.Add( key, - FCesiumPropertyTableProperty(propertyValue, EnumDefinition)); + FCesiumPropertyTableProperty(propertyValue, pEnumDefinition)); }); } diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp index 840bb4a93..b12e9f389 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp @@ -1,10 +1,11 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumPropertyTableProperty.h" -#include "CesiumGltf/MetadataConversions.h" -#include "CesiumGltf/PropertyTypeTraits.h" #include "CesiumMetadataEnum.h" #include "UnrealMetadataConversions.h" + +#include +#include #include namespace { diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp index be51d6ff4..1463f3e67 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp @@ -1,21 +1,22 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumPropertyTexture.h" -#include "CesiumGltf/Model.h" -#include "CesiumGltf/PropertyTexturePropertyView.h" -#include "CesiumGltf/PropertyTextureView.h" #include "CesiumMetadataPickingBlueprintLibrary.h" +#include +#include +#include + static FCesiumPropertyTextureProperty EmptyPropertyTextureProperty; FCesiumPropertyTexture::FCesiumPropertyTexture( - const CesiumGltf::Model& Model, - const CesiumGltf::PropertyTexture& PropertyTexture, + const CesiumGltf::Model& model, + const CesiumGltf::PropertyTexture& propertyTexture, const TSharedPtr& pEnumCollection) : _status(ECesiumPropertyTextureStatus::ErrorInvalidPropertyTextureClass), - _name(PropertyTexture.name.value_or("").c_str()), - _className(PropertyTexture.classProperty.c_str()) { - CesiumGltf::PropertyTextureView propertyTextureView(Model, PropertyTexture); + _name(propertyTexture.name.value_or("").c_str()), + _className(propertyTexture.classProperty.c_str()) { + CesiumGltf::PropertyTextureView propertyTextureView(model, propertyTexture); switch (propertyTextureView.status()) { case CesiumGltf::PropertyTextureViewStatus::Valid: _status = ECesiumPropertyTextureStatus::Valid; @@ -26,7 +27,7 @@ FCesiumPropertyTexture::FCesiumPropertyTexture( } const CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = - Model.getExtension(); + model.getExtension(); // If there was no schema, we would've gotten ErrorMissingSchema for the // propertyTextureView status. check(pExtension != nullptr && pExtension->schema != nullptr); @@ -35,8 +36,8 @@ FCesiumPropertyTexture::FCesiumPropertyTexture( for (const auto& classPropertyPair : pClass->properties) { { const auto& propertyPair = - PropertyTexture.properties.find(classPropertyPair.first); - if (propertyPair == PropertyTexture.properties.end()) { + propertyTexture.properties.find(classPropertyPair.first); + if (propertyPair == propertyTexture.properties.end()) { continue; } diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp index 3236b980d..28ab0b0a8 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp @@ -512,6 +512,30 @@ int32 UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( }); } +int64 UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + int64 DefaultValue) { + return propertyTexturePropertyCallback( + Property._property, + Property._valueType, + Property._normalized, + [&UV, DefaultValue](const auto& view) -> int64 { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { + return DefaultValue; + } + auto maybeValue = view.get(UV.X, UV.Y); + if (maybeValue) { + auto value = *maybeValue; + return CesiumGltf::MetadataConversions:: + convert(value) + .value_or(DefaultValue); + } + return DefaultValue; + }); +} + float UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( UPARAM(ref) const FCesiumPropertyTextureProperty& Property, const FVector2D& UV, diff --git a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h index a166f8d8c..cc3a1df50 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h @@ -1,9 +1,9 @@ #pragma once -#include "CesiumGltf/ExtensionExtMeshFeatures.h" -#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" -#include "CesiumGltf/Model.h" -#include "CesiumGltf/PropertyTypeTraits.h" +#include +#include +#include +#include #include #include #include @@ -225,3 +225,65 @@ CesiumGltf::PropertyTextureProperty& AddPropertyTexturePropertyToModel( property.index = static_cast(model.textures.size() - 1); return property; } + +/** + * @brief Adds the given values to the given model and primitive as a property + * attribute property in EXT_structural_metadata. This also creates a class + * property definition for the new property in the schema. If the model doesn't + * already contain EXT_structural_metadata, this function adds it. + * + * This assumes the given values are not booleans, arrays, or strings. + * + * @returns The newly created property attribute property in the model + * extension. + */ +template +CesiumGltf::PropertyAttributeProperty& AddPropertyAttributePropertyToModel( + CesiumGltf::Model& model, + CesiumGltf::MeshPrimitive& primitive, + CesiumGltf::PropertyAttribute& propertyAttribute, + const std::string& propertyName, + const std::string& type, + const std::string& componentType, + const std::vector& values, + const std::string& attributeName) { + CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension = + model.getExtension(); + if (pExtension == nullptr) { + pExtension = + &model.addExtension(); + } + + if (!pExtension->schema) { + pExtension->schema.emplace(); + } + CesiumGltf::Schema& schema = *pExtension->schema; + + const std::string& className = propertyAttribute.classProperty; + CesiumGltf::Class& theClass = schema.classes[className]; + + CesiumGltf::ClassProperty& classProperty = theClass.properties[propertyName]; + classProperty.type = type; + classProperty.componentType = componentType; + + std::vector data(values.size() * sizeof(T)); + std::memcpy(data.data(), values.data(), data.size()); + + std::string accessorType = CesiumGltf::convertPropertyTypeToAccessorType( + CesiumGltf::convertStringToPropertyType(type)); + int32_t accessorComponentType = + CesiumGltf::convertPropertyComponentTypeToAccessorComponentType( + CesiumGltf::convertStringToPropertyComponentType(componentType)); + + primitive.attributes[attributeName] = AddBufferToModel( + model, + accessorType, + accessorComponentType, + std::move(data)); + + CesiumGltf::PropertyAttributeProperty& property = + propertyAttribute.properties[propertyName]; + property.attribute = attributeName; + + return property; +} diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp index 8ddaf594b..afef3bba8 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp @@ -658,7 +658,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.Metadata = - FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + FCesiumPrimitiveMetadata(model, *pPrimitive, *pPrimitiveMetadata); FHitResult Hit; Hit.FaceIndex = -1; @@ -687,7 +687,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.Metadata = - FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + FCesiumPrimitiveMetadata(model, *pPrimitive, *pPrimitiveMetadata); FHitResult Hit; Hit.FaceIndex = 0; @@ -724,7 +724,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.Metadata = - FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + FCesiumPrimitiveMetadata(model, *pPrimitive, *pPrimitiveMetadata); FHitResult Hit; Hit.FaceIndex = 0; @@ -768,7 +768,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.Metadata = - FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + FCesiumPrimitiveMetadata(model, *pPrimitive, *pPrimitiveMetadata); FHitResult Hit; Hit.FaceIndex = 0; @@ -857,7 +857,7 @@ void FCesiumMetadataPickingSpec::Define() { pPrimitiveMetadata->propertyTextures.push_back(1); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.Metadata = - FCesiumPrimitiveMetadata(*pPrimitive, *pPrimitiveMetadata); + FCesiumPrimitiveMetadata(model, *pPrimitive, *pPrimitiveMetadata); FHitResult Hit; Hit.Component = pPrimitiveComponent; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttribute.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttribute.spec.cpp new file mode 100644 index 000000000..1b00d42fd --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttribute.spec.cpp @@ -0,0 +1,684 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyAttribute.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" +#include +#include +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyAttributeSpec, + "Cesium.Unit.PropertyAttribute", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension; +CesiumGltf::PropertyAttribute* pPropertyAttribute; +TObjectPtr pModelComponent; +TObjectPtr pPrimitiveComponent; +END_DEFINE_SPEC(FCesiumPropertyAttributeSpec) + +void FCesiumPropertyAttributeSpec::Define() { + using namespace CesiumGltf; + + BeforeEach([this]() { + model = Model(); + Mesh& mesh = model.meshes.emplace_back(); + pPrimitive = &mesh.primitives.emplace_back(); + pPrimitive->mode = MeshPrimitive::Mode::POINTS; + pExtension = &model.addExtension(); + pExtension->schema.emplace(); + pPropertyAttribute = &pExtension->propertyAttributes.emplace_back(); + }); + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyAttribute propertyAttribute; + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttribute); + TestTrue( + "Properties", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .IsEmpty()); + }); + + It("constructs invalid instance for missing schema", [this]() { + pExtension->schema.reset(); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttributeClass); + TestTrue( + "Properties", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .IsEmpty()); + }); + + It("constructs invalid instance for missing class", [this]() { + pPropertyAttribute->classProperty = "nonexistent class"; + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttributeClass); + TestTrue( + "Properties", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .IsEmpty()); + }); + + It("constructs valid instance with valid property", [this]() { + pPropertyAttribute->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::vector values{1, 2, 3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + values, + "_TEST"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 1); + }); + + It("constructs valid instance with invalid property", [this]() { + // Even if one of its properties is invalid, the property Attribute itself + // is still valid. + pPropertyAttribute->classProperty = "testClass"; + std::string propertyName("testProperty"); + std::vector values{1, 2, 3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, // Incorrect component type + values, + "_TEST"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 1); + }); + }); + + Describe("GetProperties", [this]() { + BeforeEach([this]() { pPropertyAttribute->classProperty = "testClass"; }); + + It("returns no properties for invalid property Attribute", [this]() { + FCesiumPropertyAttribute propertyAttribute; + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttribute); + const auto properties = + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + "_SCALAR"); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + "_VECTOR"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + + const auto properties = + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute); + + TestTrue( + "has scalar property", + properties.Contains(FString(scalarPropertyName.c_str()))); + const FCesiumPropertyAttributeProperty& scalarProperty = + *properties.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(scalarProperty), + ECesiumPropertyAttributePropertyStatus::Valid); + for (size_t i = 0; i < scalarValues.size(); i++) { + std::string label("Property value " + std::to_string(i)); + TestEqual( + label.c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + scalarProperty, + int64(i)), + scalarValues[i]); + } + + TestTrue( + "has vec2 property", + properties.Contains(FString(vec2PropertyName.c_str()))); + const FCesiumPropertyAttributeProperty& vec2Property = + *properties.Find(FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(vec2Property), + ECesiumPropertyAttributePropertyStatus::Valid); + for (size_t i = 0; i < vec2Values.size(); i++) { + std::string label("Property value " + std::to_string(i)); + FVector2D expected( + static_cast(vec2Values[i][0]), + static_cast(vec2Values[i][1])); + TestEqual( + label.c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + vec2Property, + int64(i), + FVector2D::Zero()), + expected); + } + }); + + It("gets invalid property", [this]() { + // Even invalid properties should still be retrieved. + std::vector values{0, 1, 2, 3}; + std::string propertyName("badProperty"); + + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, + values, + "_TEST"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + + const auto properties = + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute); + + TestTrue( + "has invalid property", + properties.Contains(FString(propertyName.c_str()))); + const FCesiumPropertyAttributeProperty& property = + *properties.Find(FString(propertyName.c_str())); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidPropertyData); + }); + }); + + Describe("GetPropertyNames", [this]() { + BeforeEach([this]() { pPropertyAttribute->classProperty = "testClass"; }); + + It("returns empty array for invalid property Attribute", [this]() { + FCesiumPropertyAttribute propertyAttribute; + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttribute); + const auto properties = + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute); + TestTrue("properties are empty", properties.IsEmpty()); + }); + + It("gets all property names", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + "_SCALAR"); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + "_VECTOR"); + + std::string invalidPropertyName("badProperty"); + std::vector invalidPropertyValues{0, 1, 2, 3}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + invalidPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, // Incorrect component type + invalidPropertyValues, + "_BAD"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + + const auto propertyNames = + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyNames( + propertyAttribute); + TestEqual("number of names", propertyNames.Num(), 3); + TestTrue( + "has scalar property name", + propertyNames.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "has vec2 property name", + propertyNames.Contains(FString(vec2PropertyName.c_str()))); + TestTrue( + "has invalid property name", + propertyNames.Contains(FString(invalidPropertyName.c_str()))); + }); + }); + + Describe("FindProperty", [this]() { + BeforeEach([this]() { pPropertyAttribute->classProperty = "testClass"; }); + + It("returns invalid instance for nonexistent property", [this]() { + std::string propertyName("testProperty"); + std::vector values{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + values, + "_TEST"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 1); + + FCesiumPropertyAttributeProperty property = + UCesiumPropertyAttributeBlueprintLibrary::FindProperty( + propertyAttribute, + FString("nonexistent property")); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + }); + + It("finds existing properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + "_SCALAR"); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + "_VECTOR"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 2); + + FCesiumPropertyAttributeProperty scalarProperty = + UCesiumPropertyAttributeBlueprintLibrary::FindProperty( + propertyAttribute, + FString(scalarPropertyName.c_str())); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(scalarProperty), + ECesiumPropertyAttributePropertyStatus::Valid); + + FCesiumPropertyAttributeProperty vec2Property = + UCesiumPropertyAttributeBlueprintLibrary::FindProperty( + propertyAttribute, + FString(vec2PropertyName.c_str())); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(vec2Property), + ECesiumPropertyAttributePropertyStatus::Valid); + }); + }); + + Describe("GetMetadataValuesAtIndex", [this]() { + BeforeEach([this]() { pPropertyAttribute->classProperty = "testClass"; }); + + It("returns empty map for invalid property attribute", [this]() { + FCesiumPropertyAttribute propertyAttribute; + + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttribute); + TestTrue( + "Properties", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .IsEmpty()); + + const auto values = + UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + propertyAttribute, + 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + + It("returns empty map for invalid index", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + "_SCALAR"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 1); + + auto values = + UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + propertyAttribute, + -1); + TestTrue("values map is empty", values.IsEmpty()); + + values = + UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + propertyAttribute, + 100); + TestTrue("values map is empty", values.IsEmpty()); + }); + + It("returns values of valid properties", [this]() { + std::string scalarPropertyName("scalarProperty"); + std::vector scalarValues{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + scalarPropertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT8, + scalarValues, + "_SCALAR"); + + std::string vec2PropertyName("vec2Property"); + std::vector vec2Values{ + glm::u8vec2(1, 2), + glm::u8vec2(0, 4), + glm::u8vec2(8, 9), + glm::u8vec2(11, 0), + }; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + vec2PropertyName, + ClassProperty::Type::VEC2, + ClassProperty::ComponentType::UINT8, + vec2Values, + "_VECTOR"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 2); + + for (size_t i = 0; i < scalarValues.size(); i++) { + const auto values = + UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + propertyAttribute, + int64(i)); + TestEqual("number of values", values.Num(), 2); + + TestTrue( + "contains scalar value", + values.Contains(FString(scalarPropertyName.c_str()))); + TestTrue( + "contains vec2 value", + values.Contains(FString(vec2PropertyName.c_str()))); + + const FCesiumMetadataValue& scalarValue = + *values.Find(FString(scalarPropertyName.c_str())); + TestEqual( + "scalar value", + UCesiumMetadataValueBlueprintLibrary::GetInteger(scalarValue, 0), + scalarValues[i]); + + const FCesiumMetadataValue& vec2Value = + *values.Find(FString(vec2PropertyName.c_str())); + FVector2D expected(vec2Values[i][0], vec2Values[i][1]); + TestEqual( + "vec2 value", + UCesiumMetadataValueBlueprintLibrary::GetVector2D( + vec2Value, + FVector2D::Zero()), + expected); + } + }); + + It("does not return value for invalid property", [this]() { + std::string propertyName("badProperty"); + std::vector data{-1, 2, -3, 4}; + AddPropertyAttributePropertyToModel( + model, + *pPrimitive, + *pPropertyAttribute, + propertyName, + ClassProperty::Type::SCALAR, + ClassProperty::ComponentType::INT32, + data, + "_TEST"); + + FCesiumPropertyAttribute propertyAttribute( + model, + *pPrimitive, + *pPropertyAttribute); + + TestEqual( + "PropertyAttributeStatus", + UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus( + propertyAttribute), + ECesiumPropertyAttributeStatus::Valid); + TestEqual( + "Property Count", + UCesiumPropertyAttributeBlueprintLibrary::GetProperties( + propertyAttribute) + .Num(), + 1); + + const auto values = + UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex( + propertyAttribute, + 0); + TestTrue("values map is empty", values.IsEmpty()); + }); + }); +} diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttributeProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttributeProperty.spec.cpp new file mode 100644 index 000000000..ee73602f9 --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyAttributeProperty.spec.cpp @@ -0,0 +1,3255 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumPropertyAttributeProperty.h" +#include "CesiumGltfSpecUtility.h" +#include "Misc/AutomationTest.h" +#include + +BEGIN_DEFINE_SPEC( + FCesiumPropertyAttributePropertySpec, + "Cesium.Unit.PropertyAttributeProperty", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ServerContext | + EAutomationTestFlags::CommandletContext | + EAutomationTestFlags::ProductFilter) +END_DEFINE_SPEC(FCesiumPropertyAttributePropertySpec) + +void FCesiumPropertyAttributePropertySpec::Define() { + using namespace CesiumGltf; + + Describe("Constructor", [this]() { + It("constructs invalid instance by default", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + }); + + It("constructs invalid instance from view with invalid definition", + [this]() { + PropertyAttributePropertyView propertyView( + PropertyAttributePropertyViewStatus::ErrorTypeMismatch); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + }); + + It("constructs invalid instance from view with invalid data", [this]() { + PropertyAttributePropertyView propertyView( + PropertyAttributePropertyViewStatus:: + ErrorAccessorComponentTypeMismatch); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidPropertyData); + + FCesiumMetadataValueType expectedType; // Invalid type + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + 0); + }); + + It("constructs valid instance", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint32_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + int64_t(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint32, + false); + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Integer64); + + TestFalse( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + // Check that undefined properties return empty values + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetOffset(property); + TestTrue("Offset", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetScale(property); + TestTrue("Scale", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetMaximumValue( + property); + TestTrue("Max", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetMinimumValue( + property); + TestTrue("Min", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetNoDataValue( + property); + TestTrue("NoData", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue( + property); + TestTrue("Default", UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("constructs valid normalized instance", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int8_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + int64_t(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int8, + false); + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Integer); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + }); + + It("constructs valid instance with additional properties", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + double offset = 1.0; + double scale = 2.0; + double min = 1.0; + double max = 3.0; + int8_t noData = 1; + double defaultValue = 12.3; + + classProperty.offset = offset; + classProperty.scale = scale; + classProperty.min = min; + classProperty.max = max; + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int8_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "Size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + int64_t(values.size())); + + FCesiumMetadataValueType expectedType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int8, + false); + TestTrue( + "ValueType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValueType( + property) == expectedType); + TestEqual( + "BlueprintType", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetBlueprintType( + property), + ECesiumMetadataBlueprintType::Integer); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetOffset(property); + TestEqual( + "Offset", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + offset); + + value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetScale(property); + TestEqual( + "Scale", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + scale); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetMaximumValue( + property); + TestEqual( + "Max", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + max); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetMinimumValue( + property); + TestEqual( + "Min", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + min); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetNoDataValue( + property); + TestEqual( + "NoData", + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0.0), + noData); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue( + property); + TestEqual( + "Default", + UCesiumMetadataValueBlueprintLibrary::GetFloat64(value, 0.0), + defaultValue); + }); + }); + + Describe("GetByte", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + 0), + 0); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint8_t), + 0, + values.size()); + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + -1), + 0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + 10), + 0); + }); + + It("gets from uint8 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint8_t), + 0, + values.size()); + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + int64_t(i)), + values[i]); + } + }); + + It("converts compatible values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.0f, 2.0f, 256.0f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected{0, 2, 0, 4}; + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + int64_t(i), + 0), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + uint8_t noDataValue = 0; + uint8_t defaultValue = 255; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{1, 2, 3, 0}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint8), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + int64_t(i)), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetByte( + property, + int64_t(i)), + values[i]); + } + } + }); + }); + + Describe("GetInteger", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + 0), + 0); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + -1), + 0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + 10), + 0); + }); + + It("gets from int16 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + int64_t(i)), + values[i]); + } + }); + + It("converts compatible values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + -1.0f, + 2.0f, + float(std::numeric_limits::max()), + 4.0f, + 2.54f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected{-1, 2, 0, 4, 2}; + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + int64_t(i)), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + int16_t noDataValue = -1; + int16_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + int64_t(i)), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger( + property, + int64_t(i)), + values[i]); + } + } + }); + }); + + Describe("GetInteger64", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + 0), + 0); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + std::vector + values{1, 2, 3, 4, std::numeric_limits::max()}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint32_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + -1), + 0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + 10), + 0); + }); + + It("gets from uint32 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + std::vector + values{1, 2, 3, 4, std::numeric_limits::max()}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint32_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + int64_t(i)), + int64_t(values[i])); + } + }); + + It("converts compatible values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + float(std::numeric_limits::max()), + 2.0f, + float(std::numeric_limits::max()), + 4.0f, + 2.54f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected{0, 2, int64_t(values[2]), 4, 2}; + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + int64_t(i)), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + int32_t noDataValue = -1; + int32_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + int64_t(i)), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetInteger64( + property, + int64_t(i)), + values[i]); + } + } + }); + }); + + Describe("GetFloat", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + 0), + 0.0f); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.54f, 52.78f, -39.0f, 4.005f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + -1), + 0.0f); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + 10), + 0.0f); + }); + + It("gets from float property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.54f, 52.78f, -39.0f, 4.005f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + i), + values[i]); + } + }); + + It("converts integer values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int8_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + i), + static_cast(values[i])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + float offset = 5.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat( + property, + i), + values[i] * scale + offset); + } + }); + }); + + Describe("GetFloat64", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + 0), + 0.0); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + -1), + 0.0); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + 10), + 0.0); + }); + + It("gets float values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-1.1, 2.2, -3.3, 4.0}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + i), + double(values[i])); + } + }); + + It("gets from normalized uint8 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + std::vector values{0, 128, 255, 0}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint8_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + i), + double(values[i]) / 255.0); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + float offset = 5.0; + float scale = 2.0; + + classProperty.offset = offset; + classProperty.scale = scale; + + std::vector values{0, 128, 255, 0}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint8_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetFloat64( + property, + i), + (double(values[i]) / 255.0) * scale + offset); + } + }); + }); + + Describe("GetIntPoint", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntPoint( + property, + 0, + FIntPoint(0)), + FIntPoint(0)); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{ + glm::i8vec2(1, 1), + glm::i8vec2(-1, -1), + glm::i8vec2(2, 4), + glm::i8vec2(0, -8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + -1, + FIntVector(0)), + FIntVector(0)); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + 10, + FIntVector(0)), + FIntVector(0)); + }); + + It("gets from i8vec2 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{ + glm::i8vec2(1, 1), + glm::i8vec2(-1, -1), + glm::i8vec2(2, 4), + glm::i8vec2(0, -8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FIntPoint expected(values[i][0], values[i][1]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntPoint( + property, + int64_t(i), + FIntPoint(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < values.size(); i++) { + FIntPoint expectedIntPoint(expected[i]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntPoint( + property, + int64_t(i), + FIntPoint(0)), + expectedIntPoint); + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + glm::i8vec2 noData(-1, -1); + FIntPoint defaultValue(5, 22); + + classProperty.noData = {noData[0], noData[1]}; + classProperty.defaultProperty = {defaultValue[0], defaultValue[1]}; + + std::vector values{ + glm::i8vec2(1, 1), + glm::i8vec2(-1, -1), + glm::i8vec2(2, 4), + glm::i8vec2(0, -8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FIntPoint expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntPoint(values[i][0], values[i][1]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntPoint( + property, + int64_t(i), + FIntPoint(0)), + expected); + } + }); + }); + + Describe("GetVector2D", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + 0, + FVector2D::Zero()), + FVector2D::Zero()); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec2(1.0f, 1.1f), + glm::vec2(-1.0f, -0.1f), + glm::vec2(2.2f, 4.2f), + glm::vec2(0.0f, -8.0f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + -1, + FVector2D::Zero()), + + FVector2D::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + 10, + FVector2D::Zero()), + FVector2D::Zero()); + }); + + It("gets from glm::vec2 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec2(1.0f, 1.1f), + glm::vec2(-1.0f, -0.1f), + glm::vec2(2.2f, 4.2f), + glm::vec2(0.0f, -8.0f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + int64_t(i), + FVector2D::Zero()), + FVector2D(values[i][0], values[i][1])); + } + }); + + It("gets from normalized glm::u8vec2 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::u8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec2 expected = glm::dvec2(values[i][0], values[i][1]) / 255.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + int64_t(i), + FVector2D::Zero()), + FVector2D(expected[0], expected[1])); + } + }); + + It("converts unnormalized glm::u8vec2 values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::u8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + int64_t(i), + FVector2D::Zero()), + FVector2D(values[i][0], values[i][1])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + FVector2D offset(3.0, 2.4); + FVector2D scale(2.0, -1.0); + + classProperty.offset = {offset[0], offset[1]}; + classProperty.scale = {scale[0], scale[1]}; + + std::vector values{ + glm::u8vec2(1, 1), + glm::u8vec2(0, 255), + glm::u8vec2(10, 4), + glm::u8vec2(128, 8)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::u8vec2), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FVector2D expected( + double(values[i][0]) / 255.0 * scale[0] + offset[0], + double(values[i][1]) / 255.0 * scale[1] + offset[1]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector2D( + property, + int64_t(i), + FVector2D::Zero()), + expected); + } + }); + }); + + Describe("GetIntVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + 0, + FIntVector(0)), + FIntVector(0)); + }); + + It("gets from glm::i8vec3 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FIntVector expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + i, + FIntVector(0)), + expected); + } + }); + + It("converts compatible values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < values.size(); i++) { + FIntVector expectedIntVector(expected[i]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + i, + FIntVector(0)), + expectedIntVector); + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + glm::i8vec3 noData(-1, -1, 2); + FIntVector defaultValue(1, 2, 3); + + classProperty.noData = {noData[0], noData[1], noData[2]}; + classProperty.defaultProperty = { + defaultValue[0], + defaultValue[1], + defaultValue[2]}; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FIntVector expected; + if (values[i] == noData) { + expected = defaultValue; + } else { + expected = FIntVector(values[i][0], values[i][1], values[i][2]); + } + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetIntVector( + property, + i, + FIntVector(0)), + expected); + } + }); + }); + + Describe("GetVector3f", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + 0, + FVector3f::Zero()), + FVector3f::Zero()); + }); + + It("returns default value for invalid index", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec3), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + -1, + FVector3f::Zero()), + FVector3f::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + 10, + FVector3f::Zero()), + FVector3f::Zero()); + }); + + It("gets from glm::vec3 property", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec3), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FVector3f expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + int64_t(i), + FVector3f(0)), + expected); + } + }); + + It("converts vec2 values", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec2(1.0f, 2.0f), + glm::vec2(-5.9f, 8.2f), + glm::vec2(20.5f, 2.0f), + glm::vec2(-1.0f, -1.0f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec2), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected(4); + for (size_t i = 0; i < values.size(); i++) { + expected[i] = FVector3f(float(values[i][0]), float(values[i][1]), 0.0f); + } + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + int64_t(i), + FVector3f::Zero()), + expected[i]); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + FVector3f offset(1.0f, 4.5f, -2.0f); + FVector3f scale(0.5f, -1.0f, 2.2f); + + classProperty.offset = {offset[0], offset[1], offset[2]}; + classProperty.scale = {scale[0], scale[1], scale[2]}; + + std::vector values{ + glm::vec3(1.0f, 1.9f, -1.0f), + glm::vec3(-1.0f, -1.8f, 2.5f), + glm::vec3(10.0f, 4.4f, 5.4f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec3), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FVector3f expected( + values[i][0] * scale[0] + offset[0], + values[i][1] * scale[1] + offset[1], + values[i][2] * scale[2] + offset[2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector3f( + property, + int64_t(i), + FVector3f::Zero()), + expected); + } + }); + }); + + Describe("GetVector", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + 0, + FVector::Zero()), + FVector::Zero()); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.02f, 0.1f, -1.11f), + glm::vec3(-1.0f, -1.0f, 2.0f), + glm::vec3(0.02f, 4.2f, 2.01f), + glm::vec3(10.0f, 8.067f, 5.213f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec3), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + -1, + FVector::Zero()), + FVector::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + 10, + FVector::Zero()), + FVector::Zero()); + }); + + It("gets from glm::vec3 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec3(1.02f, 0.1f, -1.11f), + glm::vec3(-1.0f, -1.0f, 2.0f), + glm::vec3(0.02f, 4.2f, 2.01f), + glm::vec3(10.0f, 8.067f, 5.213f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestFalse( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec3 expected(values[i][0], values[i][1], values[i][2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector::Zero()), + FVector(expected[0], expected[1], expected[2])); + } + }); + + It("gets from normalized glm::i8vec3 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec3 expected = + glm::dvec3(values[i][0], values[i][1], values[i][2]) / 127.0; + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector::Zero()), + FVector(expected[0], expected[1], expected[2])); + } + }); + + It("converts unnormalized glm::i8vec3 values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{ + glm::i8vec3(1, 1, -1), + glm::i8vec3(-1, -1, 2), + glm::i8vec3(0, 4, 2), + glm::i8vec3(10, 8, 5)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector::Zero()), + FVector(values[i][0], values[i][1], values[i][2])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC3; + classProperty.componentType = ClassProperty::ComponentType::UINT8; + classProperty.normalized = true; + + FVector offset(1.0, 2.0, 3.0); + FVector scale(0.5, -1.0, 2.0); + + classProperty.offset = {offset[0], offset[1], offset[2]}; + classProperty.scale = {scale[0], scale[1], scale[2]}; + + std::vector values{ + glm::u8vec3(0, 128, 255), + glm::u8vec3(255, 255, 255), + glm::u8vec3(10, 20, 30), + glm::u8vec3(128, 0, 0)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::u8vec3), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FVector expected( + double(values[i][0]) / 255.0 * scale[0] + offset[0], + double(values[i][1]) / 255.0 * scale[1] + offset[1], + double(values[i][2]) / 255.0 * scale[2] + offset[2]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector::Zero()), + expected); + } + }); + }); + + Describe("GetVector4", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + property, + 0, + FVector4::Zero()), + FVector4::Zero()); + }); + + It("returns default value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec4(1.02f, 0.1f, -1.11f, 1.0f), + glm::vec4(-1.0f, -1.0f, 2.0f, 0.0f), + glm::vec4(0.02f, 4.2f, 2.01f, 6.0f), + glm::vec4(10.0f, 8.067f, 5.213f, 0.0f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + static_cast(values.size())); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + property, + -1, + FVector4::Zero()), + FVector4::Zero()); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + property, + 10, + FVector4::Zero()), + FVector4::Zero()); + }); + + It("gets from glm::vec4 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec4(1.02f, 0.1f, -1.11f, 1.0f), + glm::vec4(-1.0f, -1.0f, 2.0f, 0.0f), + glm::vec4(0.02f, 4.2f, 2.01f, 6.0f), + glm::vec4(10.0f, 8.067f, 5.213f, 0.0f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + property, + int64_t(i), + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("gets from normalized glm::i8vec4 property", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + std::vector values{ + glm::i8vec4(1, 1, -1, 1), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(0, 4, 2, -8), + glm::i8vec4(10, 8, 5, 27)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec4), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + expected /= 127.0; + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("converts unnormalized glm::i8vec4 values", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + + std::vector values{ + glm::i8vec4(-1, 2, 5, 8), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(3, 5, 7, 0), + glm::i8vec4(1, -1, -2, 5)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec4), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + glm::dvec4 expected( + values[i][0], + values[i][1], + values[i][2], + values[i][3]); + + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector4( + property, + int64_t(i), + FVector4::Zero()), + FVector4(expected[0], expected[1], expected[2], expected[3])); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + FVector4 offset(1.0, 2.0, 3.0, -1.0); + FVector4 scale(0.5, -1.0, 2.0, 3.5); + + classProperty.offset = {offset[0], offset[1], offset[2], offset[3]}; + classProperty.scale = {scale[0], scale[1], scale[2], scale[3]}; + + std::vector values{ + glm::i8vec4(1, 1, -1, 1), + glm::i8vec4(-1, -1, 2, 0), + glm::i8vec4(0, 4, 2, -8), + glm::i8vec4(10, 8, 5, 27)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8vec4), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + FVector4 expected( + values[i][0] / 127.0 * scale[0] + offset[0], + values[i][1] / 127.0 * scale[1] + offset[1], + values[i][2] / 127.0 * scale[2] + offset[2], + values[i][3] / 127.0 * scale[3] + offset[3]); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetVector( + property, + int64_t(i), + FVector4::Zero()), + expected); + } + }); + }); + + Describe("GetMatrix", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + 0, + FMatrix::Identity), + FMatrix::Identity); + }); + + It("returns default value for invalid index", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + // clang-format off + std::vector values{ + glm::mat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::mat4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestEqual( + "negative index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + -1, + FMatrix::Identity), + + FMatrix::Identity); + TestEqual( + "out-of-range positive index", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + 10, + FMatrix::Identity), + FMatrix::Identity); + }); + + It("gets from glm::dmat4 property", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + // clang-format off + std::vector values{ + glm::mat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::mat4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(1.0, 5.0, 9.0, 13.0), + FPlane4d(2.0, 6.0, 10.0, 14.0), + FPlane4d(3.0, 7.0, 11.0, 15.0), + FPlane4d(4.0, 8.0, 12.0, 16.0)); + expected[1] = FMatrix( + FPlane4d(1.0, 0.0, 0.0, -1.5), + FPlane4d(0.0, -2.5, 0.0, 4.0), + FPlane4d(0.0, 0.0, 0.5, 2.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + int64_t(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("gets from glm::u8mat4x4 property", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::INT8; + classProperty.normalized = true; + + // clang-format off + std::vector values{ + glm::i8mat4x4( + 127, 0, 0, 0, + 0, 127, 0, 0, + 0, 0, 127, 0, + 0, 0, -127, 127), + glm::i8mat4x4( + 0, -127, 0, 0, + 127, 0, 0, 0, + 0, 0, 127, 0, + 0, 0, 127, 127), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::i8mat4x4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView + propertyView(propertyAttributeProperty, classProperty, accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + TestTrue( + "IsNormalized", + UCesiumPropertyAttributePropertyBlueprintLibrary::IsNormalized( + property)); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(1.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 1.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 1.0, -1.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + expected[1] = FMatrix( + FPlane4d(0.0, 1.0, 0.0, 0.0), + FPlane4d(-1.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, 1.0, 1.0), + FPlane4d(0.0, 0.0, 0.0, 1.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + int64_t(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("converts compatible values", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{-2.0f, 10.5f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(-2.0, 0.0, 0.0, 0.0), + FPlane4d(0.0, -2.0, 0.0, 0.0), + FPlane4d(0.0, 0.0, -2.0, 0.0), + FPlane4d(0.0, 0.0, 0.0, -2.0)); + expected[1] = FMatrix( + FPlane4d(10.5, 0.0, 0.0, 0.0), + FPlane4d(0.0, 10.5, 0.0, 0.0), + FPlane4d(0.0, 0.0, 10.5, 0.0), + FPlane4d(0.0, 0.0, 0.0, 10.5)); + for (size_t i = 0; i < expected.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + int64_t(i), + FMatrix::Identity), + expected[i]); + } + }); + + It("returns default values for incompatible type", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::VEC2; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + std::vector values{ + glm::vec2(-2.0f, 10.5f), + glm::vec2(1.5f, 0.1f)}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::vec2), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + int64_t(i), + FMatrix::Identity), + FMatrix::Identity); + } + }); + + It("gets with offset / scale", [this]() { + CesiumGltf::PropertyAttributeProperty propertyAttributeProperty; + CesiumGltf::ClassProperty classProperty; + classProperty.type = ClassProperty::Type::MAT4; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + double offset = 1.0; + double scale = 2.0; + + CesiumUtility::JsonValue::Array offsetArray(16); + CesiumUtility::JsonValue::Array scaleArray(16); + for (size_t i = 0; i < 16; i++) { + offsetArray[i] = offset; + scaleArray[i] = scale; + } + + classProperty.offset = offsetArray; + classProperty.scale = scaleArray; + + // clang-format off + std::vector values{ + glm::mat4( + 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0), + glm::mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, -2.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + -1.5, 4.0, 2.0, 1.0), + }; + // clang-format on + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(glm::mat4), + 0, + values.size()); + + CesiumGltf::PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + std::vector expected(2); + expected[0] = FMatrix( + FPlane4d(3.0, 11.0, 19.0, 27.0), + FPlane4d(5.0, 13.0, 21.0, 29.0), + FPlane4d(7.0, 15.0, 23.0, 31.0), + FPlane4d(9.0, 17.0, 25.0, 33.0)); + expected[1] = FMatrix( + FPlane4d(3.0, 1.0, 1.0, -2.0), + FPlane4d(1.0, -4.0, 1.0, 9.0), + FPlane4d(1.0, 1.0, 2.0, 5.0), + FPlane4d(1.0, 1.0, 1.0, 3.0)); + + for (size_t i = 0; i < values.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyAttributePropertyBlueprintLibrary::GetMatrix( + property, + int64_t(i), + FMatrix::Identity), + expected[i]); + } + }); + }); + + Describe("GetValue", [this]() { + It("returns empty value for invalid property", [this]() { + FCesiumPropertyAttributeProperty property; + TestEqual( + "PropertyAttributePropertyStatus", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty); + + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + 0); + TestTrue( + "value empty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("returns empty value for invalid index", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint32_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + TestEqual( + "size", + UCesiumPropertyAttributePropertyBlueprintLibrary::GetPropertySize( + property), + int64_t(values.size())); + + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + -1); + TestTrue( + "negative index", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + + value = UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + 10); + TestTrue( + "out-of-range positive index", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + }); + + It("gets value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + std::vector values{1, 2, 3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(uint32_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Uint32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + int64_t(i)); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + }); + + It("gets with offset / scale", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + float offset = 1.0f; + float scale = 2.0f; + + classProperty.offset = offset; + classProperty.scale = scale; + + std::vector values{-1.1f, 2.0f, -3.5f, 4.0f}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(float), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Float32, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + i); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetFloat(value, 0), + values[i] * scale + offset); + } + }); + + It("gets with noData", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + int16_t noData = -1; + classProperty.noData = noData; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int16, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + i); + if (values[i] == noData) { + TestTrue( + "value empty", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); + } else { + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + + It("gets with noData / default value", [this]() { + PropertyAttributeProperty propertyAttributeProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::INT16; + + int16_t noData = -1; + int16_t defaultValue = 15; + + classProperty.noData = noData; + classProperty.defaultProperty = defaultValue; + + std::vector values{-1, 2, -3, 4}; + std::vector data = GetValuesAsBytes(values); + + AccessorView accessorView( + data.data(), + sizeof(int16_t), + 0, + values.size()); + + PropertyAttributePropertyView propertyView( + propertyAttributeProperty, + classProperty, + accessorView); + FCesiumPropertyAttributeProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyAttributePropertyBlueprintLibrary:: + GetPropertyAttributePropertyStatus(property), + ECesiumPropertyAttributePropertyStatus::Valid); + + FCesiumMetadataValueType valueType( + ECesiumMetadataType::Scalar, + ECesiumMetadataComponentType::Int16, + false); + for (size_t i = 0; i < values.size(); i++) { + FCesiumMetadataValue value = + UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue( + property, + i); + TestTrue( + "value type", + UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == + valueType); + if (values[i] == noData) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), + values[i]); + } + } + }); + }); +} diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp index e158006f3..be7abf258 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp @@ -26,7 +26,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), @@ -50,7 +50,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), @@ -73,7 +73,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::ErrorInvalidPropertyData); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), @@ -97,7 +97,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); @@ -106,11 +106,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType expectedType( ECesiumMetadataType::Scalar, @@ -131,10 +131,10 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTablePropertyBlueprintLibrary:: @@ -178,7 +178,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); @@ -187,11 +187,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType expectedType( ECesiumMetadataType::Scalar, @@ -212,10 +212,10 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTablePropertyBlueprintLibrary:: @@ -232,8 +232,7 @@ void FCesiumPropertyTablePropertySpec::Define() { classProperty.count = 3; std::vector values{1, 2, 3, 4, 5, 6}; - const int64_t size = - static_cast(values.size()) / *classProperty.count; + const int64_t size = int64_t(values.size()) / *classProperty.count; std::vector data = GetValuesAsBytes(values); CesiumGltf::PropertyTablePropertyView> @@ -253,11 +252,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(size)); + int64_t(size)); FCesiumMetadataValueType expectedType( ECesiumMetadataType::Scalar, @@ -277,7 +276,7 @@ void FCesiumPropertyTablePropertySpec::Define() { "IsNormalized", UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), *classProperty.count); @@ -301,7 +300,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector offsets{0, 1, 3, 6}; std::vector offsetsData = GetValuesAsBytes(offsets); - int64_t size = static_cast(offsets.size()) - 1; + int64_t size = int64_t(offsets.size()) - 1; CesiumGltf::PropertyTablePropertyView> propertyView( propertyTableProperty, @@ -321,7 +320,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), @@ -346,10 +345,10 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); // The arrays vary in length, so GetArraySize() should return zero. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTablePropertyBlueprintLibrary:: @@ -383,7 +382,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); @@ -392,11 +391,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType expectedType( ECesiumMetadataType::Scalar, @@ -417,10 +416,10 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTablePropertyBlueprintLibrary:: @@ -498,7 +497,7 @@ void FCesiumPropertyTablePropertySpec::Define() { propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); @@ -507,11 +506,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType expectedType( ECesiumMetadataType::Scalar, @@ -531,10 +530,10 @@ void FCesiumPropertyTablePropertySpec::Define() { "IsNormalized", UCesiumPropertyTablePropertyBlueprintLibrary::IsNormalized(property)); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTablePropertyBlueprintLibrary:: @@ -549,7 +548,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "Offset0", UCesiumMetadataValueBlueprintLibrary::GetFloat64( @@ -569,7 +568,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "Scale0", UCesiumMetadataValueBlueprintLibrary::GetFloat64( @@ -590,7 +589,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "Max0", UCesiumMetadataValueBlueprintLibrary::GetFloat64( @@ -611,7 +610,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "Min0", UCesiumMetadataValueBlueprintLibrary::GetFloat64( @@ -632,7 +631,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "NoData0", UCesiumMetadataValueBlueprintLibrary::GetInteger( @@ -653,7 +652,7 @@ void FCesiumPropertyTablePropertySpec::Define() { TestEqual( TEXT("Size"), UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(*classProperty.count)); + int64_t(*classProperty.count)); TestEqual( "DefaultValue0", UCesiumMetadataValueBlueprintLibrary::GetFloat64( @@ -694,7 +693,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(8), + int64_t(8), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -702,11 +701,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(8)); + int64_t(8)); TestFalse( "negative index", @@ -730,7 +729,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(8), + int64_t(8), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -741,18 +740,18 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector expected{true, false, false, false, true, true, false, true}; - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(expected.size())); + int64_t(expected.size())); for (size_t i = 0; i < expected.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( property, - static_cast(i), + int64_t(i), false), expected[i]); } @@ -787,7 +786,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size()), std::span(), std::span(offsetsData.data(), offsetsData.size()), @@ -800,11 +799,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{true, false, false, true, false, true}; for (size_t i = 0; i < expected.size(); i++) { @@ -812,7 +811,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetBoolean( property, - static_cast(i), + int64_t(i), false), expected[i]); } @@ -845,7 +844,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -853,11 +852,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -881,7 +880,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -889,18 +888,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -918,7 +917,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -926,11 +925,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{1, 24, 255, 0, 0, 28}; for (size_t i = 0; i < expected.size(); i++) { @@ -938,7 +937,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( property, - static_cast(i), + int64_t(i), 0), expected[i]); } @@ -962,7 +961,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -970,11 +969,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { if (values[i] == noDataValue) { @@ -982,7 +981,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( property, - static_cast(i), + int64_t(i), 0), defaultValue); } else { @@ -990,7 +989,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -1024,7 +1023,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1032,11 +1031,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -1064,7 +1063,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1072,18 +1071,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -1107,7 +1106,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1115,11 +1114,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{1, -24, 0, 2456, 0}; for (size_t i = 0; i < expected.size(); i++) { @@ -1127,7 +1126,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( property, - static_cast(i), + int64_t(i), 0), expected[i]); } @@ -1151,7 +1150,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1159,11 +1158,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { if (values[i] == noDataValue) { @@ -1171,7 +1170,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( property, - static_cast(i), + int64_t(i), 0), defaultValue); } else { @@ -1179,7 +1178,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -1188,7 +1187,7 @@ void FCesiumPropertyTablePropertySpec::Define() { }); Describe("GetInteger64", [this]() { - int64_t defaultInt64 = static_cast(0); + int64_t defaultInt64 = int64_t(0); It("returns default value for invalid property", [this, defaultInt64]() { FCesiumPropertyTableProperty property; @@ -1197,7 +1196,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); - TestEqual( + TestEqual( "value", UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, @@ -1217,7 +1216,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1225,19 +1224,19 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); - TestEqual( + TestEqual( "negative index", UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, -1), defaultInt64); - TestEqual( + TestEqual( "out-of-range positive index", UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, @@ -1245,7 +1244,7 @@ void FCesiumPropertyTablePropertySpec::Define() { defaultInt64); }); - It("gets from int64 property", [this, defaultInt64]() { + It("gets from int64_t property", [this, defaultInt64]() { CesiumGltf::PropertyTableProperty propertyTableProperty; CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; @@ -1257,7 +1256,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1265,18 +1264,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { - TestEqual( + TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, - static_cast(i), + int64_t(i), defaultInt64), values[i]); } @@ -1298,7 +1297,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1306,19 +1305,19 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{10, 20, 30, 0}; for (size_t i = 0; i < expected.size(); i++) { - TestEqual( + TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, - static_cast(i), + int64_t(i), defaultInt64), expected[i]); } @@ -1342,7 +1341,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1350,27 +1349,27 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { if (values[i] == noDataValue) { - TestEqual( + TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, - static_cast(i), + int64_t(i), defaultInt64), defaultValue); } else { - TestEqual( + TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetInteger64( property, - static_cast(i), + int64_t(i), defaultInt64), values[i]); } @@ -1406,7 +1405,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1414,11 +1413,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -1442,7 +1441,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1450,18 +1449,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -1483,7 +1482,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1491,11 +1490,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected(4); for (size_t i = 0; i < values.size(); i++) { @@ -1508,7 +1507,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( property, - static_cast(i), + int64_t(i), 0.0f), expected[i]); } @@ -1532,7 +1531,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1540,18 +1539,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( property, - static_cast(i), + int64_t(i), 0), values[i] * scale + offset); } @@ -1586,7 +1585,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1594,11 +1593,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -1626,7 +1625,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1634,18 +1633,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( property, - static_cast(i), + int64_t(i), 0), values[i]); } @@ -1664,7 +1663,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1672,11 +1671,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestTrue( "IsNormalized", @@ -1687,7 +1686,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( property, - static_cast(i), + int64_t(i), 0), static_cast(values[i]) / 255.0); } @@ -1721,7 +1720,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size()), std::span(), std::span(offsetsData.data(), offsetsData.size()), @@ -1733,11 +1732,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ 0.0, @@ -1748,7 +1747,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( property, - static_cast(i), + int64_t(i), 0.0), expected[i]); } @@ -1772,7 +1771,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1780,18 +1779,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat64( property, - static_cast(i), + int64_t(i), 0), values[i] * scale + offset); } @@ -1830,7 +1829,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1838,11 +1837,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -1875,7 +1874,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1883,11 +1882,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FIntPoint expected(values[i][0], values[i][1]); @@ -1895,7 +1894,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( property, - static_cast(i), + int64_t(i), FIntPoint(0)), expected); } @@ -1916,7 +1915,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1924,11 +1923,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ FIntPoint(1, 2), @@ -1939,7 +1938,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( property, - static_cast(i), + int64_t(i), FIntPoint(0)), expected[i]); } @@ -1966,7 +1965,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -1974,11 +1973,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FIntPoint expected; @@ -1992,7 +1991,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( property, - static_cast(i), + int64_t(i), FIntPoint(0)), expected); } @@ -2031,7 +2030,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2039,11 +2038,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -2076,7 +2075,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2084,11 +2083,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector2D expected(values[i][0], values[i][1]); @@ -2096,7 +2095,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( property, - static_cast(i), + int64_t(i), FVector2D::Zero()), expected); } @@ -2118,7 +2117,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2126,11 +2125,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestTrue( "IsNormalized", @@ -2142,7 +2141,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( property, - static_cast(i), + int64_t(i), FVector2D::Zero()), FVector2D(expected[0], expected[1])); } @@ -2176,7 +2175,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size()), std::span(), std::span(offsetsData.data(), offsetsData.size()), @@ -2188,11 +2187,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ FVector2D(10, 3), @@ -2203,7 +2202,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( property, - static_cast(i), + int64_t(i), FVector2D::Zero()), expected[i]); } @@ -2230,7 +2229,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2238,11 +2237,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector2D expected( @@ -2253,7 +2252,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( property, - static_cast(i), + int64_t(i), FVector2D::Zero()), expected); } @@ -2292,7 +2291,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2300,11 +2299,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -2337,7 +2336,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2345,11 +2344,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FIntVector expected(values[i][0], values[i][1], values[i][2]); @@ -2357,7 +2356,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( property, - static_cast(i), + int64_t(i), FIntVector(0)), expected); } @@ -2379,7 +2378,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2387,11 +2386,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ FIntVector(1, 2, 3), @@ -2403,7 +2402,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( property, - static_cast(i), + int64_t(i), FIntVector(0)), expected[i]); } @@ -2434,7 +2433,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2442,11 +2441,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FIntVector expected; @@ -2460,7 +2459,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( property, - static_cast(i), + int64_t(i), FIntVector(0)), expected); } @@ -2499,7 +2498,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2507,11 +2506,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -2544,7 +2543,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2552,11 +2551,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector3f expected(values[i][0], values[i][1], values[i][2]); @@ -2564,8 +2563,8 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( property, - static_cast(i), - FVector3f(0)), + int64_t(i), + FVector3f::Zero()), expected); } }); @@ -2586,7 +2585,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2594,11 +2593,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected(4); for (size_t i = 0; i < 2; i++) { @@ -2614,7 +2613,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( property, - static_cast(i), + int64_t(i), FVector3f::Zero()), expected[i]); } @@ -2641,7 +2640,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2649,11 +2648,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector3f expected( @@ -2664,7 +2663,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( property, - static_cast(i), + int64_t(i), FVector3f(0)), expected); } @@ -2703,7 +2702,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2711,11 +2710,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -2748,7 +2747,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2756,11 +2755,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector expected(values[i][0], values[i][1], values[i][2]); @@ -2768,7 +2767,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector::Zero()), expected); } @@ -2790,7 +2789,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2798,11 +2797,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestTrue( "IsNormalized", @@ -2815,7 +2814,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector::Zero()), FVector(expected[0], expected[1], expected[2])); } @@ -2852,7 +2851,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size()), std::span(), std::span(offsetsData.data(), offsetsData.size()), @@ -2864,11 +2863,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ FVector(10, 3, 4), @@ -2879,7 +2878,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector::Zero()), expected[i]); } @@ -2906,7 +2905,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2914,11 +2913,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector expected( @@ -2929,7 +2928,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector::Zero()), expected); } @@ -2968,7 +2967,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -2976,11 +2975,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -3013,7 +3012,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3021,11 +3020,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector4 expected( @@ -3037,7 +3036,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector4::Zero()), expected); } @@ -3059,7 +3058,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3067,11 +3066,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestTrue( "IsNormalized", @@ -3089,7 +3088,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector4::Zero()), FVector4(expected[0], expected[1], expected[2], expected[3])); } @@ -3126,7 +3125,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size()), std::span(), std::span(offsetsData.data(), offsetsData.size()), @@ -3138,11 +3137,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected{ FVector4(10, 3, 4, 2), @@ -3153,7 +3152,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( property, - static_cast(i), + int64_t(i), FVector4::Zero()), expected[i]); } @@ -3180,7 +3179,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3188,11 +3187,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { FVector4 expected( @@ -3204,7 +3203,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( property, - static_cast(i), + int64_t(i), FVector4::Zero()), expected); } @@ -3253,7 +3252,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3261,11 +3260,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestEqual( "negative index", @@ -3309,7 +3308,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3317,11 +3316,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected(2); expected[0] = FMatrix( @@ -3340,7 +3339,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( property, - static_cast(i), + int64_t(i), FMatrix::Identity), expected[i]); } @@ -3372,7 +3371,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3380,11 +3379,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); TestTrue( "IsNormalized", @@ -3407,7 +3406,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( property, - static_cast(i), + int64_t(i), FMatrix::Identity), expected[i]); } @@ -3425,7 +3424,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3433,11 +3432,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected(2); expected[0] = FMatrix( @@ -3455,7 +3454,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( property, - static_cast(i), + int64_t(i), FMatrix::Identity), expected[i]); } @@ -3475,7 +3474,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3483,18 +3482,18 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); for (size_t i = 0; i < values.size(); i++) { TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( property, - static_cast(i), + int64_t(i), FMatrix::Identity), FMatrix::Identity); } @@ -3538,7 +3537,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3546,11 +3545,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); std::vector expected(2); expected[0] = FMatrix( @@ -3569,7 +3568,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTablePropertyBlueprintLibrary::GetMatrix( property, - static_cast(i), + int64_t(i), FMatrix::Identity), expected[i]); } @@ -3589,7 +3588,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -3597,11 +3596,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumPropertyArray array = UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, 0); @@ -3647,7 +3646,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4, 5, 6}; std::vector data = GetValuesAsBytes(values); - int64 size = static_cast(values.size()) / *classProperty.count; + int64_t size = int64_t(values.size()) / *classProperty.count; CesiumGltf::PropertyTablePropertyView> propertyView( @@ -3665,7 +3664,7 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), @@ -3705,7 +3704,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4, 5, 6}; std::vector data = GetValuesAsBytes(values); - int64 size = static_cast(values.size()) / *classProperty.count; + int64_t size = int64_t(values.size()) / *classProperty.count; CesiumGltf::PropertyTablePropertyView> propertyView( @@ -3723,21 +3722,22 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), size); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), *classProperty.count); - for (int64 i = 0; i < size; i++) { + for (int64_t i = 0; i < size; i++) { FCesiumPropertyArray array = UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Int32, @@ -3747,8 +3747,8 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == valueType); - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -3773,7 +3773,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector offsets{0, 2, 3, 6}; std::vector offsetsData = GetValuesAsBytes(offsets); - int64 size = static_cast(offsets.size() - 1); + int64_t size = int64_t(offsets.size() - 1); CesiumGltf::PropertyTablePropertyView> propertyView( @@ -3793,26 +3793,26 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), size); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), - static_cast(0)); + int64_t(0)); std::vector> expected{{1, 2}, {3}, {4, 5, 6}}; - for (int64 i = 0; i < size; i++) { + for (int64_t i = 0; i < size; i++) { const std::vector& expectedArray = expected[static_cast(i)]; FCesiumPropertyArray array = UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); - TestEqual( + TestEqual( "array size", UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(expectedArray.size())); + int64_t(expectedArray.size())); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Int32, @@ -3826,9 +3826,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = - UCesiumPropertyArrayBlueprintLibrary::GetValue( - array, - static_cast(j)); + UCesiumPropertyArrayBlueprintLibrary::GetValue(array, int64_t(j)); TestEqual( label.c_str(), UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), @@ -3849,7 +3847,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; std::vector data = GetValuesAsBytes(values); - int64 size = static_cast(values.size()) / *classProperty.count; + int64_t size = int64_t(values.size()) / *classProperty.count; CesiumGltf::PropertyTablePropertyView> propertyView( @@ -3867,21 +3865,22 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), size); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), *classProperty.count); - for (int64 i = 0; i < size - 1; i++) { + for (int64_t i = 0; i < size - 1; i++) { FCesiumPropertyArray array = UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Int32, @@ -3891,8 +3890,8 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == valueType); - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -3910,10 +3909,10 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary::GetArray( property, size - 1); - TestEqual( + TestEqual( "array size", UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(0)); + int64_t(0)); FCesiumMetadataValueType valueType( ECesiumMetadataType::Invalid, ECesiumMetadataComponentType::None, @@ -3937,7 +3936,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; std::vector data = GetValuesAsBytes(values); - int64 size = static_cast(values.size()) / *classProperty.count; + int64_t size = int64_t(values.size()) / *classProperty.count; CesiumGltf::PropertyTablePropertyView> propertyView( @@ -3955,21 +3954,22 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), size); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTablePropertyBlueprintLibrary::GetArraySize(property), *classProperty.count); - for (int64 i = 0; i < size; i++) { + for (int64_t i = 0; i < size; i++) { FCesiumPropertyArray array = UCesiumPropertyTablePropertyBlueprintLibrary::GetArray(property, i); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Int32, @@ -3995,8 +3995,8 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumMetadataValueBlueprintLibrary::GetInteger(value1, 0), 20); } else { - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -4019,11 +4019,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty); - TestEqual( + TestEqual( "Size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(0)); + int64_t(0)); FCesiumMetadataValue value = UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, 0); @@ -4046,7 +4046,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -4054,26 +4054,23 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValue value = UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, -1); - FCesiumMetadataValueType valueType; // Unknown type TestTrue( - "negative index value type", - UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == - valueType); + "negative index", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); value = UCesiumPropertyTablePropertyBlueprintLibrary::GetValue(property, 10); TestTrue( - "out-of-range positive index value type", - UCesiumMetadataValueBlueprintLibrary::GetValueType(value) == - valueType); + "out-of-range positive index", + UCesiumMetadataValueBlueprintLibrary::IsEmpty(value)); }); It("gets value for valid feature IDs", [this]() { @@ -4088,7 +4085,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -4096,11 +4093,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, @@ -4138,7 +4135,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -4146,11 +4143,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, @@ -4185,7 +4182,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -4193,11 +4190,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, @@ -4243,7 +4240,7 @@ void FCesiumPropertyTablePropertySpec::Define() { CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, - static_cast(values.size()), + int64_t(values.size()), std::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -4251,11 +4248,11 @@ void FCesiumPropertyTablePropertySpec::Define() { UCesiumPropertyTablePropertyBlueprintLibrary:: GetPropertyTablePropertyStatus(property), ECesiumPropertyTablePropertyStatus::Valid); - TestEqual( + TestEqual( "size", UCesiumPropertyTablePropertyBlueprintLibrary::GetPropertySize( property), - static_cast(values.size())); + int64_t(values.size())); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp index 0c23881d2..942b01491 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp @@ -125,11 +125,11 @@ void FCesiumPropertyTexturePropertySpec::Define() { property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTexturePropertyBlueprintLibrary:: @@ -214,11 +214,11 @@ void FCesiumPropertyTexturePropertySpec::Define() { property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTexturePropertyBlueprintLibrary:: @@ -278,7 +278,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::IsNormalized( property)); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), @@ -356,11 +356,11 @@ void FCesiumPropertyTexturePropertySpec::Define() { property)); // Test that the returns are as expected for non-array properties. - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), - static_cast(0)); + int64_t(0)); TestEqual( "ArrayElementBlueprintType", UCesiumPropertyTexturePropertyBlueprintLibrary:: @@ -737,6 +737,174 @@ void FCesiumPropertyTexturePropertySpec::Define() { }); }); + Describe("GetInteger64", [this]() { + It("returns default value for invalid property", [this]() { + FCesiumPropertyTextureProperty property; + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty); + TestEqual( + "value", + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger64( + property, + FVector2D::Zero()), + 0); + }); + + It("gets from uint32 property", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{1, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger64( + property, + texCoords[i]), + int64_t(values[i])); + } + }); + + It("converts compatible values", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::FLOAT32; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{ + 1.234f, + -24.5f, + std::numeric_limits::lowest(), + 2456.80f}; + image.pixelData = GetValuesAsBytes(values); + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + std::vector expected{1, -24, 0, 2456}; + for (size_t i = 0; i < texCoords.size(); i++) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + expected[i]); + } + }); + + It("gets with noData / default value", [this]() { + PropertyTextureProperty propertyTextureProperty; + ClassProperty classProperty; + classProperty.type = ClassProperty::Type::SCALAR; + classProperty.componentType = ClassProperty::ComponentType::UINT32; + + uint32_t noDataValue = 0; + uint32_t defaultValue = 10; + + classProperty.noData = noDataValue; + classProperty.defaultProperty = defaultValue; + + Sampler sampler; + ImageAsset image; + image.width = 2; + image.height = 2; + image.channels = 4; + image.bytesPerChannel = 1; + + std::vector values{0, 2, 3, 4}; + image.pixelData = GetValuesAsBytes(values); + + if (FPlatformProperties::IsLittleEndian()) { + propertyTextureProperty.channels = {0, 1, 2, 3}; + } else { + propertyTextureProperty.channels = {3, 2, 1, 0}; + } + + PropertyTexturePropertyView propertyView( + propertyTextureProperty, + classProperty, + sampler, + image); + FCesiumPropertyTextureProperty property(propertyView); + TestEqual( + "status", + UCesiumPropertyTexturePropertyBlueprintLibrary:: + GetPropertyTexturePropertyStatus(property), + ECesiumPropertyTexturePropertyStatus::Valid); + + for (size_t i = 0; i < texCoords.size(); i++) { + if (values[i] == noDataValue) { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + defaultValue); + } else { + TestEqual( + std::string("value" + std::to_string(i)).c_str(), + UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( + property, + texCoords[i]), + values[i]); + } + } + }); + }); + Describe("GetFloat", [this]() { It("returns default value for invalid property", [this]() { FCesiumPropertyTextureProperty property; @@ -833,7 +1001,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( property, texCoords[i]), - static_cast(values[i])); + float(values[i])); } }); @@ -946,7 +1114,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( property, texCoords[i]), - static_cast(values[i]) / 255.0); + double(values[i]) / 255.0); } }); @@ -990,7 +1158,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( property, texCoords[i]), - static_cast(values[i])); + double(values[i])); } }); @@ -1037,7 +1205,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( property, texCoords[i]), - (static_cast(values[i]) / 255.0) * scale + offset); + (double(values[i]) / 255.0) * scale + offset); } }); }); @@ -1371,8 +1539,8 @@ void FCesiumPropertyTexturePropertySpec::Define() { for (size_t i = 0; i < texCoords.size(); i++) { FVector2D expected( - static_cast(values[i][0]) / 255.0 * scale[0] + offset[0], - static_cast(values[i][1]) / 255.0 * scale[1] + offset[1]); + double(values[i][0]) / 255.0 * scale[0] + offset[0], + double(values[i][1]) / 255.0 * scale[1] + offset[1]); TestEqual( std::string("value" + std::to_string(i)).c_str(), @@ -1718,9 +1886,9 @@ void FCesiumPropertyTexturePropertySpec::Define() { for (size_t i = 0; i < texCoords.size(); i++) { FVector expected( - static_cast(values[i][0]) / 255.0 * scale[0] + offset[0], - static_cast(values[i][1]) / 255.0 * scale[1] + offset[1], - static_cast(values[i][2]) / 255.0 * scale[2] + offset[2]); + double(values[i][0]) / 255.0 * scale[0] + offset[0], + double(values[i][1]) / 255.0 * scale[1] + offset[1], + double(values[i][2]) / 255.0 * scale[2] + offset[2]); TestEqual( std::string("value" + std::to_string(i)).c_str(), UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( @@ -2021,7 +2189,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary:: GetPropertyTexturePropertyStatus(property), ECesiumPropertyTexturePropertyStatus::Valid); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), @@ -2032,8 +2200,9 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( property, texCoords[i]); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Uint8, @@ -2043,8 +2212,8 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == valueType); - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -2052,7 +2221,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { TestEqual( label.c_str(), UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), - values[static_cast(arrayOffset + j)]); + values[size_t(arrayOffset + j)]); } } }); @@ -2089,7 +2258,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary:: GetPropertyTexturePropertyStatus(property), ECesiumPropertyTexturePropertyStatus::Valid); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), @@ -2100,8 +2269,9 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( property, texCoords[i]); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Uint8, @@ -2111,8 +2281,8 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyArrayBlueprintLibrary::GetElementValueType(array) == valueType); - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -2120,7 +2290,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { TestEqual( label.c_str(), UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), - values[static_cast(arrayOffset + j)]); + values[size_t(arrayOffset + j)]); } } @@ -2130,10 +2300,10 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( property, texCoords[texCoords.size() - 1]); - TestEqual( + TestEqual( "array size", UCesiumPropertyArrayBlueprintLibrary::GetSize(array), - static_cast(0)); + int64_t(0)); FCesiumMetadataValueType valueType( ECesiumMetadataType::Invalid, ECesiumMetadataComponentType::None, @@ -2177,7 +2347,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary:: GetPropertyTexturePropertyStatus(property), ECesiumPropertyTexturePropertyStatus::Valid); - TestEqual( + TestEqual( "ArraySize", UCesiumPropertyTexturePropertyBlueprintLibrary::GetArraySize( property), @@ -2188,8 +2358,9 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( property, texCoords[i]); - int64 arraySize = UCesiumPropertyArrayBlueprintLibrary::GetSize(array); - TestEqual("array size", arraySize, *classProperty.count); + int64_t arraySize = + UCesiumPropertyArrayBlueprintLibrary::GetSize(array); + TestEqual("array size", arraySize, *classProperty.count); FCesiumMetadataValueType valueType( ECesiumMetadataType::Scalar, ECesiumMetadataComponentType::Uint8, @@ -2215,8 +2386,8 @@ void FCesiumPropertyTexturePropertySpec::Define() { UCesiumMetadataValueBlueprintLibrary::GetInteger(value1, 0), 20); } else { - int64 arrayOffset = i * arraySize; - for (int64 j = 0; j < arraySize; j++) { + int64_t arrayOffset = i * arraySize; + for (int64_t j = 0; j < arraySize; j++) { std::string label( "array" + std::to_string(i) + " value" + std::to_string(j)); FCesiumMetadataValue value = @@ -2224,7 +2395,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { TestEqual( label.c_str(), UCesiumMetadataValueBlueprintLibrary::GetInteger(value, 0), - values[static_cast(arrayOffset + j)]); + values[size_t(arrayOffset + j)]); } } } diff --git a/Source/CesiumRuntime/Public/CesiumModelMetadata.h b/Source/CesiumRuntime/Public/CesiumModelMetadata.h index 59f07a7c9..7adc18264 100644 --- a/Source/CesiumRuntime/Public/CesiumModelMetadata.h +++ b/Source/CesiumRuntime/Public/CesiumModelMetadata.h @@ -37,7 +37,6 @@ struct CESIUMRUNTIME_API FCesiumModelMetadata { TArray _propertyTables; TArray _propertyTextures; TSharedPtr _enumDefinitions; - // TODO: property attributes friend class UCesiumModelMetadataBlueprintLibrary; }; diff --git a/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h b/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h index b8b76af08..6463ca595 100644 --- a/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h +++ b/Source/CesiumRuntime/Public/CesiumPrimitiveMetadata.h @@ -2,6 +2,7 @@ #pragma once +#include "CesiumPropertyAttribute.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "UObject/ObjectMacros.h" @@ -16,9 +17,9 @@ struct ExtensionMeshPrimitiveExtStructuralMetadata; /** * A Blueprint-accessible wrapper for a glTF Primitive's EXT_structural_metadata - * extension. It holds the indices of the property textures / attributes - * associated with this primitive, which index into the respective arrays in the - * model's EXT_structural_metadata extension. + * extension. It holds the property attributes used by the primitive, as well as + * the indices of the property textures associated with it, which index into the + * array of property textures in the model's EXT_structural_metadata extension. */ USTRUCT(BlueprintType) struct CESIUMRUNTIME_API FCesiumPrimitiveMetadata { @@ -33,16 +34,21 @@ struct CESIUMRUNTIME_API FCesiumPrimitiveMetadata { /** * Constructs a primitive metadata instance. * - * @param Primitive The mesh primitive containing the EXT_structural_metadata + * @param model The model containing the given mesh primitive. + * @param primitive The mesh primitive containing the EXT_structural_metadata * extension - * @param Metadata The EXT_structural_metadata of the glTF mesh primitive. + * @param metadata The EXT_structural_metadata of the glTF mesh primitive. */ FCesiumPrimitiveMetadata( - const CesiumGltf::MeshPrimitive& Primitive, - const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata); + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& metadata); private: TArray _propertyTextureIndices; + TArray _propertyAttributes; + + // For backwards compatibility with GetPropertyAttributeIndices(). TArray _propertyAttributeIndices; friend class UCesiumPrimitiveMetadataBlueprintLibrary; @@ -78,14 +84,28 @@ class CESIUMRUNTIME_API UCesiumPrimitiveMetadataBlueprintLibrary UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata); /** - * Get the indices of the property attributes that are associated with the - * primitive. This can be used to retrieve the actual property attributes from - * the model's FCesiumModelMetadata. + * Get the property attributes that are associated with the primitive. */ UFUNCTION( BlueprintCallable, BlueprintPure, Category = "Cesium|Primitive|Metadata") + static const TArray& + GetPropertyAttributes(UPARAM(ref) + const FCesiumPrimitiveMetadata& PrimitiveMetadata); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Get the indices of the property attributes that are associated with the + * primitive. + */ + UFUNCTION( + Category = "Cesium|Primitive|Metadata", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Retrieve property attributes directly through GetPropertyAttributes instead.")) static const TArray& GetPropertyAttributeIndices( UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata); + PRAGMA_ENABLE_DEPRECATION_WARNINGS }; diff --git a/Source/CesiumRuntime/Public/CesiumPropertyAttribute.h b/Source/CesiumRuntime/Public/CesiumPropertyAttribute.h new file mode 100644 index 000000000..4230de357 --- /dev/null +++ b/Source/CesiumRuntime/Public/CesiumPropertyAttribute.h @@ -0,0 +1,190 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataEnum.h" +#include "CesiumMetadataValue.h" +#include "CesiumPropertyAttributeProperty.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumPropertyAttribute.generated.h" + +namespace CesiumGltf { +struct Model; +struct PropertyAttribute; +} // namespace CesiumGltf + +/** + * @brief Reports the status of a FCesiumPropertyAttribute. If the property + * attribute cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumPropertyAttributeStatus : uint8 { + /* The property attribute is valid. */ + Valid = 0, + /* The property attribute instance was not initialized from an actual glTF + property attribute. */ + ErrorInvalidPropertyAttribute, + /* The property attribute's class could not be found in the schema of the + metadata extension. */ + ErrorInvalidPropertyAttributeClass +}; + +/** + * A Blueprint-accessible wrapper for a glTF property attribute. + * Provides access to {@link FCesiumPropertyAttributeProperty} views of + * per-vertex metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyAttribute { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an empty property attribute instance. + */ + FCesiumPropertyAttribute() + : _status(ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttribute) { + } + + /** + * Constructs a property attribute from the given glTF. + * + * @param model The model that stores EXT_structural_metadata. + * @param primitive The primitive that contains the target property attribute. + * @param propertyAttribute The target property attribute. + */ + FCesiumPropertyAttribute( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::PropertyAttribute& propertyAttribute) + : FCesiumPropertyAttribute( + model, + primitive, + propertyAttribute, + FCesiumMetadataEnumCollection::GetOrCreateFromModel(model)) {} + + /** + * Constructs a property attribute from the given glTF. + * + * @param model The model that stores EXT_structural_metadata. + * @param primitive The primitive that contains the target property attribute. + * @param propertyAttribute The target property attribute. + * @param pEnumCollection The enum collection to use, if any. + */ + FCesiumPropertyAttribute( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::PropertyAttribute& propertyAttribute, + const TSharedPtr& pEnumCollection); + + /** + * Gets the name of the metadata class that this property attribute conforms + * to. + */ + FString getClassName() const { return _className; } + +private: + ECesiumPropertyAttributeStatus _status; + FString _name; + FString _className; + + int64 _elementCount; + TMap _properties; + + friend class UCesiumPropertyAttributeBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyAttributeBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property attribute. If an error occurred while + * parsing the property attribute from the glTF extension, this briefly + * conveys why. + * + * @param PropertyAttribute The property attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static ECesiumPropertyAttributeStatus GetPropertyAttributeStatus( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute); + + /** + * Gets the name of the property attribute. If no name was specified in the + * glTF extension, this returns an empty string. + * + * @param PropertyAttribute The property attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static const FString& GetPropertyAttributeName( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute); + + /** + * Gets all the properties of the property attribute, mapped by property name. + * + * @param PropertyAttribute The property attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static const TMap& + GetProperties(UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute); + + /** + * Gets the names of the properties in this property attribute. + * + * @param PropertyAttribute The property attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static const TArray + GetPropertyNames(UPARAM(ref) + const FCesiumPropertyAttribute& PropertyAttribute); + + /** + * Retrieve a FCesiumPropertyAttributeProperty by name. If the property + * attribute does not contain a property with that name, this returns an + * invalid FCesiumPropertyAttributeProperty. + * + * @param PropertyAttribute The property attribute. + * @param PropertyName The name of the property to find. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static const FCesiumPropertyAttributeProperty& FindProperty( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute, + const FString& PropertyName); + + /** + * Gets all of the property values for the given vertex index, mapped by + * property name. This will only include values from valid property attribute + * properties. + * + * If the index is out-of-bounds, the returned map will be empty. + * + * @param PropertyAttribute The property attribute. + * @param Index The index of the target vertex. + * @return The property values mapped by property name. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttribute") + static TMap GetMetadataValuesAtIndex( + UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute, + int64 Index); +}; diff --git a/Source/CesiumRuntime/Public/CesiumPropertyAttributeProperty.h b/Source/CesiumRuntime/Public/CesiumPropertyAttributeProperty.h new file mode 100644 index 000000000..7274be520 --- /dev/null +++ b/Source/CesiumRuntime/Public/CesiumPropertyAttributeProperty.h @@ -0,0 +1,850 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataEnum.h" +#include "CesiumMetadataValue.h" +#include "CesiumMetadataValueType.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" + +#include +#include +#include + +#include "CesiumPropertyAttributeProperty.generated.h" + +/** + * @brief Reports the status of a FCesiumPropertyAttributeProperty. If the + * property attribute property cannot be accessed, this briefly indicates why. + */ +UENUM(BlueprintType) +enum class ECesiumPropertyAttributePropertyStatus : uint8 { + /* The property attribute property is valid. */ + Valid = 0, + /* The property attribute property is empty but has a specified default value. + */ + EmptyPropertyWithDefault, + /* The property attribute property does not exist in the glTF, or the property + definition itself contains errors. */ + ErrorInvalidProperty, + /* The data associated with the property attribute property is malformed and + cannot be retrieved. */ + ErrorInvalidPropertyData +}; + +/** + * A Blueprint-accessible wrapper for a glTF property attribute property in + * EXT_structural_metadata. Provides per-vertex access to metadata encoded in a + * glTF primitive's vertices. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumPropertyAttributeProperty { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an invalid property with an unknown type. + */ + FCesiumPropertyAttributeProperty() + : _status(ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty), + _property(), + _valueType(), + _normalized(false) {} + + /** + * Construct a wrapper for the property attribute property view. + * + * @param Property The PropertyAttributePropertyView to be stored in this + * struct. + */ + template + FCesiumPropertyAttributeProperty( + const CesiumGltf::PropertyAttributePropertyView& Property) + : FCesiumPropertyAttributeProperty( + Property, + TSharedPtr(nullptr)) {} + + /** + * Construct a wrapper for the property attribute property view. + * + * @param Property The PropertyAttributePropertyView to be stored in this + * struct. + * @param EnumDefinition The enum definition to use, if any. + */ + template + FCesiumPropertyAttributeProperty( + const CesiumGltf::PropertyAttributePropertyView& Property, + const TSharedPtr& EnumDefinition) + : _status(ECesiumPropertyAttributePropertyStatus::ErrorInvalidProperty), + _property(Property), + _valueType(), + _normalized(Normalized), + _pEnumDefinition(EnumDefinition) { + switch (Property.status()) { + case CesiumGltf::PropertyAttributePropertyViewStatus::Valid: + _status = ECesiumPropertyAttributePropertyStatus::Valid; + break; + case CesiumGltf::PropertyAttributePropertyViewStatus:: + EmptyPropertyWithDefault: + _status = + ECesiumPropertyAttributePropertyStatus::EmptyPropertyWithDefault; + break; + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorInvalidPropertyAttribute: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorNonexistentProperty: + case CesiumGltf::PropertyAttributePropertyViewStatus::ErrorTypeMismatch: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorComponentTypeMismatch: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorArrayTypeMismatch: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorInvalidNormalization: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorNormalizationMismatch: + case CesiumGltf::PropertyAttributePropertyViewStatus::ErrorInvalidOffset: + case CesiumGltf::PropertyAttributePropertyViewStatus::ErrorInvalidScale: + case CesiumGltf::PropertyAttributePropertyViewStatus::ErrorInvalidMax: + case CesiumGltf::PropertyAttributePropertyViewStatus::ErrorInvalidMin: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorInvalidNoDataValue: + case CesiumGltf::PropertyAttributePropertyViewStatus:: + ErrorInvalidDefaultValue: + // The status was already set in the initializer list. + return; + default: + _status = + ECesiumPropertyAttributePropertyStatus::ErrorInvalidPropertyData; + return; + } + + _valueType = TypeToMetadataValueType(EnumDefinition); + _normalized = Normalized; + } + +private: + ECesiumPropertyAttributePropertyStatus _status; + + std::any _property; + + FCesiumMetadataValueType _valueType; + bool _normalized; + TSharedPtr _pEnumDefinition; + + friend class UCesiumPropertyAttributePropertyBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumPropertyAttributePropertyBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the status of the property attribute property. If this property + * attribute property is invalid in any way, this will briefly indicate why. + * + * @param Property The property attribute property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static ECesiumPropertyAttributePropertyStatus + GetPropertyAttributePropertyStatus( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the best-fitting type for the property that is accessible from + * Blueprints. For the most precise representation of the values possible in + * Blueprints, you should retrieve it using this type. + * + * @param Property The property attribute property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) + const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the type of the metadata value as defined in the + * EXT_structural_metadata extension. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + * + * @param Property The property attribute property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValueType + GetValueType(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the number of values in the property. + * + * @param Property The property attribute property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static int64 + GetPropertySize(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Attempts to retrieve the value at the given index as an unsigned 8-bit + * integer. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * If the value is an integer between 0 and 255, it is returned as-is. + * Otherwise, if the value is a floating-point number in the aforementioned + * range, it is truncated (rounded toward zero) and returned. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Byte. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static uint8 GetByte( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + uint8 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given index as a signed 32-bit + * integer. + * + * Although property attribute properties do not directly support + * 32-bit signed integers, this can be used to losslessly retrieve values from + * smaller integer properties. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * If the value is an integer between -2,147,483,648 and 2,147,483,647, it + * is returned as-is. Otherwise, if the value is a floating-point number in + * the aforementioned range, it is truncated (rounded toward zero) and + * returned. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static int32 GetInteger( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + int32 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given index as a signed 64-bit + * integer. + * + * Although property attribute properties do not directly support + * 64-bit integers, this can be used to losslessly retrieve values from + * unsigned 32-bit integer properties. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * If the value is an integer and between -2^63 and (2^63 - 1), it is + * returned as-is. Otherwise, if the value is a floating-point number in the + * aforementioned range, it is truncated (rounded toward zero) and returned. + * + * In all other cases, the user-defined default value is returned. If the + * index ID is out-of-range, or if the property table property is somehow + * invalid, the user-defined default value is returned. + * + * @param Property The property table property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static int64 GetInteger64( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + int64 DefaultValue = 0); + + /** + * Attempts to retrieve the value for the given index as a single-precision + * floating-point number. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * If the value is already a single-precision floating-point number, it is + * returned as-is. Otherwise, if the value is a scalar of any other type + * within the range of values that a single-precision float can represent, it + * is converted to its closest representation as a single-precision float and + * returned. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static float GetFloat( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + float DefaultValue = 0.0f); + + /** + * Attempts to retrieve the value for the given index as a double-precision + * floating-point number. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * If the value is a single-precision floating-point number, it is returned + * as-is. Otherwise, if the value is an integer, it is converted to the + * closest representation as a double-precision floating-point number. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a Float64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static double GetFloat64( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + double DefaultValue = 0.0); + + /** + * Attempts to retrieve the value for the given index as a FIntPoint. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FIntPoint. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntPoint will have this value in both of its + * components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed, the default value is returned. + * + * If the index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntPoint. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FIntPoint GetIntPoint( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FIntPoint& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FVector2D. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 2-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3- or 4-dimensional vector, it will use the first two + * components to construct the FVector2D. + * + * - If the value is a scalar, the resulting FVector2D will have this value in + * both of its components. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector2D. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FVector2D GetVector2D( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector2D& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FIntVector. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to 32-bit signed integers if possible. + * + * - If the value is a 4-dimensional vector, it will use the first three + * components to construct the FIntVector. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FIntVector. The Z component will be set to zero. + * + * - If the value is a scalar that can be converted to a 32-bit signed + * integer, the resulting FIntVector will have this value in all of its + * components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * 32-bit signed integer, the default value is returned. + * + * If the index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FIntVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FIntVector GetIntVector( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FIntVector& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FVector3f. + * + * For numeric properties, the raw value transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to the closest represenattribute single-precision floats, if possible. + * + * - If the value is a 4-dimensional vector, a FVector3f containing the first + * three components will be returned. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector3f. The Z-component will be set to zero. + * + * - If the value is a scalar that can be converted to a single-precision + * floating-point number, then the resulting FVector3f will have this value in + * all of its components. + * + * In all other cases, the user-defined default value is returned. In all + * vector cases, if any of the relevant components cannot be represented as a + * single-precision float, the user-defined default value is returned. + * + * If the index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector3f. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FVector3f GetVector3f( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector3f& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FVector. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 3-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 4-dimensional vector, a FVector containing the first + * three components will be returned. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector. The Z-component will be set to zero. + * + * - If the value is a scalar, then the resulting FVector will have this value + * as a double-precision floating-point number in all of its components. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FVector GetVector( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FVector4. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 4-dimensional vector, its components will be converted + * to double-precision floating-point numbers. + * + * - If the value is a 3-dimensional vector, it will become the XYZ-components + * of the FVector4. The W-component will be set to zero. + * + * - If the value is a 2-dimensional vector, it will become the XY-components + * of the FVector4. The Z- and W-components will be set to zero. + * + * - If the value is a scalar, then the resulting FVector4 will have this + * value as a double-precision floating-point number in all of its components. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FVector4. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FVector4 GetVector4( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FVector4& DefaultValue); + + /** + * Attempts to retrieve the value for the given index as a FMatrix. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is further converted. If the raw + * value is equal to the property's "no data" value, then the property's + * default value will be converted if possible. If the property-defined + * default value cannot be converted, or does not exist, then the user-defined + * default value is returned. + * + * Property values are converted as follows: + * + * - If the value is a 4-by-4 matrix, its components will be converted to + * double-precision floating-point numbers. + * + * - If the value is a 3-by-3 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 3-by-3 matrix is returned in an FMatrix where the fourth row and + * column are filled with zeroes. + * + * - If the value is a 2-by-2 matrix, it will initialize the corresponding + * entries of the FMatrix, while all other entries are set to zero. In other + * words, the 2-by-2 matrix is returned in an FMatrix where the third and + * fourth rows / columns are filled with zeroes. + * + * - If the value is a scalar, then the resulting FMatrix will have this value + * along its diagonal, including the very last component. All other entries + * will be zero. + * + * In all other cases, the user-defined default value is returned. If the + * index is out-of-range, or if the property attribute property is + * somehow invalid, the user-defined default value is returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @param DefaultValue The default value to fall back on. + * @return The property value as a FMatrix. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FMatrix GetMatrix( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index, + const FMatrix& DefaultValue); + + /** + * Retrieves the value of the property for the given index. This allows the + * value to be acted on more generically; its true value can be retrieved + * later as a specific Blueprints type. + * + * For numeric properties, the raw value will be transformed by the property's + * normalization, scale, and offset before it is returned. If the raw value is + * equal to the property's "no data" value, an empty value will be returned. + * However, if the property itself specifies a default value, then the + * property-defined default value will be returned. + * + * @param Property The property attribute property. + * @param Index The index. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue GetValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index); + + /** + * Retrieves the raw value of the property for the given index. This is the + * value of the property without normalization, offset, or scale applied. + * + * If this property specifies a "no data" value, and the raw value is equal to + * this "no data" value, the value is returned as-is. + * + * If this property is an empty property with a specified default value, it + * will not have any raw data to retrieve. The returned value will be empty. + + * @param Property The property attribute property. + * @param Index The index. + * @return The raw property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue GetRawValue( + UPARAM(ref) const FCesiumPropertyAttributeProperty& Property, + int64 Index); + + /** + * Whether this property is normalized. Only applicable when this property has + * an integer component type. + * + * @param Property The property attribute property. + * @return Whether this property is normalized. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static bool + IsNormalized(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the offset of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If an offset is not defined or applicable, this + * returns an empty value. + * + * @param Property The property attribute property. + * @return The offset of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetOffset(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the scale of this property. This can be defined by the class property + * that it implements, or overridden by the instance of the property itself. + * + * This is only applicable to properties with floating-point or normalized + * integer component types. If a scale is not defined or applicable, this + * returns an empty value. + * + * @param Property The property attribute property. + * @return The scale of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetScale(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the minimum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise minimum of all property values with normalization, + * offset, and scale applied. If a minimum value is not defined or + * applicable, this returns an empty value. + * + * @param Property The property attribute property. + * @return The minimum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetMinimumValue(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the maximum value of this property. This can be defined by the class + * property that it implements, or overridden by the instance of the property + * itself. + * + * This is only applicable to scalar, vecN and matN properties. It represents + * the component-wise maximum of all property values with normalization, + * offset, and scale applied. If a maximum value is not defined or applicable, + * this returns an empty value. + * + * @param Property The property attribute property. + * @return The maximum value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetMaximumValue(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the "no data" value of this property, as defined by its class + * property. This value functions a sentinel value, indicating missing data + * wherever it appears. The value is compared against the property's raw data, + * without normalization, offset, or scale applied. + * + * If a "no data" value is not defined or applicable, this returns an empty + * value. + * + * @param Property The property attribute property. + * @return The "no data" value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetNoDataValue(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); + + /** + * Gets the default value of this property, as defined by its class + * property. This default value is used use when encountering a "no data" + * value in the property. + * + * If a default value is not defined, this returns an empty value. + * + * @param Property The property attribute property. + * @return The default value of the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyAttributeProperty") + static FCesiumMetadataValue + GetDefaultValue(UPARAM(ref) const FCesiumPropertyAttributeProperty& Property); +}; diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTable.h b/Source/CesiumRuntime/Public/CesiumPropertyTable.h index 4671fe174..d576a2329 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTable.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTable.h @@ -25,7 +25,7 @@ enum class ECesiumPropertyTableStatus : uint8 { /* The property table instance was not initialized from an actual glTF property table. */ ErrorInvalidPropertyTable, - /* The property table's class could be found in the schema of the metadata + /* The property table's class could not be found in the schema of the metadata extension. */ ErrorInvalidPropertyTableClass }; @@ -44,32 +44,32 @@ struct CESIUMRUNTIME_API FCesiumPropertyTable { * Construct an empty property table instance. */ FCesiumPropertyTable() - : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTable){}; + : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTable) {} /** * Constructs a property table from a glTF Property Table. * - * @param Model The model that stores EXT_structural_metadata. - * @param PropertyTable The target property table. + * @param model The model that stores EXT_structural_metadata. + * @param propertyTable The target property table. */ FCesiumPropertyTable( - const CesiumGltf::Model& Model, - const CesiumGltf::PropertyTable& PropertyTable) + const CesiumGltf::Model& model, + const CesiumGltf::PropertyTable& propertyTable) : FCesiumPropertyTable( - Model, - PropertyTable, - FCesiumMetadataEnumCollection::GetOrCreateFromModel(Model)) {} + model, + propertyTable, + FCesiumMetadataEnumCollection::GetOrCreateFromModel(model)) {} /** * Constructs a property table from a glTF Property Table. * - * @param Model The model that stores EXT_structural_metadata. - * @param PropertyTable The target property table. + * @param model The model that stores EXT_structural_metadata. + * @param propertyTable The target property table. * @param pEnumCollection The enum collection to use, if any. */ FCesiumPropertyTable( - const CesiumGltf::Model& Model, - const CesiumGltf::PropertyTable& PropertyTable, + const CesiumGltf::Model& model, + const CesiumGltf::PropertyTable& propertyTable, const TSharedPtr& pEnumCollection); /** diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h b/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h index 2c6259b2d..5488c810c 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTableProperty.h @@ -2,18 +2,17 @@ #pragma once -#include "CesiumGltf/PropertyTablePropertyView.h" -#include "CesiumGltf/PropertyTypeTraits.h" #include "CesiumMetadataEnum.h" #include "CesiumMetadataValue.h" #include "CesiumMetadataValueType.h" #include "CesiumPropertyArray.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "UObject/ObjectMacros.h" + +#include +#include #include -#include -#include -#include + #include "CesiumPropertyTableProperty.generated.h" /** @@ -58,31 +57,31 @@ struct CESIUMRUNTIME_API FCesiumPropertyTableProperty { /** * Construct a wrapper for the property table property view. * - * @param Property The PropertyTablePropertyView to be stored in this struct. + * @param property The PropertyTablePropertyView to be stored in this struct. */ template FCesiumPropertyTableProperty( - const CesiumGltf::PropertyTablePropertyView& Property) + const CesiumGltf::PropertyTablePropertyView& property) : FCesiumPropertyTableProperty( - Property, + property, TSharedPtr(nullptr)) {} /** * Construct a wrapper for the property table property view. * - * @param Property The PropertyTablePropertyView to be stored in this struct. - * @param EnumDefinition The enum definition to use, if any. + * @param property The PropertyTablePropertyView to be stored in this struct. + * @param pEnumDefinition The enum definition to use, if any. */ template FCesiumPropertyTableProperty( - const CesiumGltf::PropertyTablePropertyView& Property, - const TSharedPtr& EnumDefinition) + const CesiumGltf::PropertyTablePropertyView& property, + const TSharedPtr& pEnumDefinition) : _status(ECesiumPropertyTablePropertyStatus::ErrorInvalidProperty), - _property(Property), + _property(property), _valueType(), _normalized(Normalized), - _pEnumDefinition(EnumDefinition) { - switch (Property.status()) { + _pEnumDefinition(pEnumDefinition) { + switch (property.status()) { case CesiumGltf::PropertyTablePropertyViewStatus::Valid: _status = ECesiumPropertyTablePropertyStatus::Valid; break; @@ -111,7 +110,7 @@ struct CESIUMRUNTIME_API FCesiumPropertyTableProperty { return; } - _valueType = TypeToMetadataValueType(EnumDefinition); + _valueType = TypeToMetadataValueType(pEnumDefinition); _normalized = Normalized; } diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTexture.h b/Source/CesiumRuntime/Public/CesiumPropertyTexture.h index 5efbdee04..f933beebc 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTexture.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTexture.h @@ -2,12 +2,14 @@ #pragma once -#include "CesiumGltf/PropertyTextureView.h" #include "CesiumMetadataEnum.h" #include "CesiumPropertyTextureProperty.h" #include "Containers/Array.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "Kismet/GameplayStatics.h" + +#include + #include "CesiumPropertyTexture.generated.h" namespace CesiumGltf { @@ -22,8 +24,8 @@ enum class ECesiumPropertyTextureStatus : uint8 { /* The property texture instance was not initialized from an actual glTF property texture. */ ErrorInvalidPropertyTexture, - /* The property texture's class could be found in the schema of the metadata - extension. */ + /* The property texture's class could not be found in the schema of the + metadata extension. */ ErrorInvalidPropertyTextureClass }; @@ -37,21 +39,37 @@ struct CESIUMRUNTIME_API FCesiumPropertyTexture { GENERATED_USTRUCT_BODY() public: + /** + * Construct an empty property texture instance. + */ FCesiumPropertyTexture() : _status(ECesiumPropertyTextureStatus::ErrorInvalidPropertyTexture) {} + /** + * Constructs a property texture from the given glTF. + * + * @param model The model that stores EXT_structural_metadata. + * @param propertyTexture The target property texture. + */ FCesiumPropertyTexture( const CesiumGltf::Model& model, - const CesiumGltf::PropertyTexture& PropertyTexture) + const CesiumGltf::PropertyTexture& propertyTexture) : FCesiumPropertyTexture( model, - PropertyTexture, + propertyTexture, FCesiumMetadataEnumCollection::GetOrCreateFromModel(model)) {} + /** + * Constructs a property texture from the given glTF. + * + * @param model The model that stores EXT_structural_metadata. + * @param propertyTexture The target property texture. + * @param pEnumCollection The enum collection to use, if any. + */ FCesiumPropertyTexture( const CesiumGltf::Model& model, - const CesiumGltf::PropertyTexture& PropertyTexture, - const TSharedPtr& EnumCollection); + const CesiumGltf::PropertyTexture& propertyTexture, + const TSharedPtr& pEnumCollection); /** * Gets the name of the metadata class that this property table conforms to. diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h b/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h index c4e4ad985..8f5a6d417 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h @@ -6,10 +6,12 @@ #include "CesiumMetadataValue.h" #include "GenericPlatform/GenericPlatform.h" #include "Kismet/BlueprintFunctionLibrary.h" + #include #include #include #include + #include "CesiumPropertyTextureProperty.generated.h" /** @@ -50,14 +52,14 @@ struct CESIUMRUNTIME_API FCesiumPropertyTextureProperty { template FCesiumPropertyTextureProperty( - const CesiumGltf::PropertyTexturePropertyView& Property, + const CesiumGltf::PropertyTexturePropertyView& property, const TSharedPtr& pEnumDefinition = nullptr) : _status(ECesiumPropertyTexturePropertyStatus::ErrorInvalidProperty), - _property(Property), + _property(property), _valueType(), _normalized(Normalized), _pEnumDefinition(pEnumDefinition) { - switch (Property.status()) { + switch (property.status()) { case CesiumGltf::PropertyTexturePropertyViewStatus::Valid: _status = ECesiumPropertyTexturePropertyStatus::Valid; break; @@ -320,6 +322,44 @@ class CESIUMRUNTIME_API UCesiumPropertyTexturePropertyBlueprintLibrary const FVector2D& UV, int32 DefaultValue = 0); + /** + * Attempts to retrieve the value for the given feature as a signed 64-bit + * integer. Although property texture properties do not directly support + * 64-bit integers, this can be used to losslessly retrieve values from + * unsigned 32-bit integer properties. + * + * For numeric properties, the raw value for a given feature will be + * transformed by the property's normalization, scale, and offset before it is + * further converted. If the raw value is equal to the property's "no data" + * value, then the property's default value will be converted if possible. If + * the property-defined default value cannot be converted, or does not exist, + * then the user-defined default value is returned. + * + * Property values are converted as follows: + * + * - If the value is an integer and between -2^63 and (2^63 - 1), it is + * returned as-is. + * - If the value is a floating-point number in the aforementioned range, it + * is truncated (rounded toward zero) and returned. + * + * In all other cases, the user-defined default value is returned. If the + * property texture property is somehow invalid, the user-defined default + * value is returned. + * + * @param Property The property texture property. + * @param UV The texture coordinates. + * @param DefaultValue The default value to fall back on. + * @return The property value as an Integer64. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|PropertyTextureProperty") + static int64 GetInteger64( + UPARAM(ref) const FCesiumPropertyTextureProperty& Property, + const FVector2D& UV, + int64 DefaultValue = 0); + /** * Attempts to retrieve the value at the given texture coordinates as a * single-precision floating-point number.