diff --git a/Code/CryEngine/CryCommon/WinBase.cpp b/Code/CryEngine/CryCommon/WinBase.cpp index d48a3327a7..e6ea1cd4a8 100644 --- a/Code/CryEngine/CryCommon/WinBase.cpp +++ b/Code/CryEngine/CryCommon/WinBase.cpp @@ -77,7 +77,7 @@ unsigned int g_EnableMultipleAssert = 0;//set to something else than 0 if to ena #endif #if defined(APPLE) - #include "../CrySystem/SystemUtilsApple.h" + #include #endif #include "StringUtils.h" diff --git a/Code/CryEngine/CrySystem/Log.cpp b/Code/CryEngine/CrySystem/Log.cpp index cdf145e4be..62cf29fef9 100644 --- a/Code/CryEngine/CrySystem/Log.cpp +++ b/Code/CryEngine/CrySystem/Log.cpp @@ -51,7 +51,7 @@ #define LOG_BACKUP_PATH "@log@/LogBackups" #if defined(IOS) -#include "SystemUtilsApple.h" +#include #endif ////////////////////////////////////////////////////////////////////// diff --git a/Code/CryEngine/CrySystem/MobileDetectSpec_Ios.cpp b/Code/CryEngine/CrySystem/MobileDetectSpec_Ios.cpp index 1f3275f1c6..dc0a28490d 100644 --- a/Code/CryEngine/CrySystem/MobileDetectSpec_Ios.cpp +++ b/Code/CryEngine/CrySystem/MobileDetectSpec_Ios.cpp @@ -15,7 +15,7 @@ #include #include "MobileDetectSpec.h" -#include "SystemUtilsApple.h" +#include namespace MobileSysInspect { diff --git a/Code/CryEngine/CrySystem/Platform/Mac/platform_mac_files.cmake b/Code/CryEngine/CrySystem/Platform/Mac/platform_mac_files.cmake index 9c26988e94..4d5680a30d 100644 --- a/Code/CryEngine/CrySystem/Platform/Mac/platform_mac_files.cmake +++ b/Code/CryEngine/CrySystem/Platform/Mac/platform_mac_files.cmake @@ -8,8 +8,3 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # - -set(FILES - ../../SystemUtilsApple.h - ../../SystemUtilsApple.mm -) diff --git a/Code/CryEngine/CrySystem/Platform/iOS/platform_ios_files.cmake b/Code/CryEngine/CrySystem/Platform/iOS/platform_ios_files.cmake index a5d743e6d7..bbe61fb488 100644 --- a/Code/CryEngine/CrySystem/Platform/iOS/platform_ios_files.cmake +++ b/Code/CryEngine/CrySystem/Platform/iOS/platform_ios_files.cmake @@ -13,8 +13,6 @@ set(FILES ../../MobileDetectSpec_Ios.cpp ../../MobileDetectSpec.cpp ../../MobileDetectSpec.h - ../../SystemUtilsApple.h - ../../SystemUtilsApple.mm ) diff --git a/Code/CryEngine/CrySystem/SystemWin32.cpp b/Code/CryEngine/CrySystem/SystemWin32.cpp index ce352966ac..b47519eb03 100644 --- a/Code/CryEngine/CrySystem/SystemWin32.cpp +++ b/Code/CryEngine/CrySystem/SystemWin32.cpp @@ -66,7 +66,7 @@ __pragma(comment(lib, "Winmm.lib")) #endif #if defined(APPLE) -#include "SystemUtilsApple.h" +#include #endif diff --git a/Code/CryEngine/CrySystem/crysystem_mac_files.cmake b/Code/CryEngine/CrySystem/crysystem_mac_files.cmake index 7e539e6825..f5b9ea77a2 100644 --- a/Code/CryEngine/CrySystem/crysystem_mac_files.cmake +++ b/Code/CryEngine/CrySystem/crysystem_mac_files.cmake @@ -9,7 +9,3 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(FILES - SystemUtilsApple.h - SystemUtilsApple.mm -) diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp new file mode 100644 index 0000000000..0b7e3300cf --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp @@ -0,0 +1,485 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AZ::JsonMathMatrixSerializerInternal +{ + template + JsonSerializationResult::Result LoadArray(MatrixType& output, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + + constexpr size_t ElementCount = RowCount * ColumnCount; + static_assert(ElementCount == 9 || ElementCount == 12 || ElementCount == 16, + "MathMatrixSerializer only support Matrix3x3, Matrix3x4 and Matrix4x4."); + + rapidjson::SizeType arraySize = inputValue.Size(); + if (arraySize < ElementCount) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, + "Not enough numbers in JSON array to load math matrix from."); + } + + AZ::BaseJsonSerializer* floatSerializer = context.GetRegistrationContext()->GetSerializerForType(azrtti_typeid()); + if (!floatSerializer) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "Failed to find the JSON float serializer."); + } + + constexpr const char* names[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"}; + float values[ElementCount]; + for (int i = 0; i < ElementCount; ++i) + { + ScopedContextPath subPath(context, names[i]); + JSR::Result intermediate = floatSerializer->Load(values + i, azrtti_typeid(), inputValue[i], context); + if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediate; + } + } + + size_t valueIndex = 0; + for (size_t r = 0; r < RowCount; ++r) + { + for (size_t c = 0; c < ColumnCount; ++c) + { + output.SetElement(aznumeric_caster(r), aznumeric_caster(c), values[valueIndex++]); + } + } + + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read math matrix."); + } + + JsonSerializationResult::Result LoadFloatFromObject( + float& output, + const rapidjson::Value& inputValue, + JsonDeserializerContext& context, + const char* name, + const char* altName) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + + AZ::BaseJsonSerializer* floatSerializer = context.GetRegistrationContext()->GetSerializerForType(azrtti_typeid()); + if (!floatSerializer) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "Failed to find the json float serializer."); + } + + const char* nameUsed = name; + JSR::ResultCode result(JSR::Tasks::ReadField); + auto iterator = inputValue.FindMember(rapidjson::StringRef(name)); + if (iterator == inputValue.MemberEnd()) + { + nameUsed = altName; + iterator = inputValue.FindMember(rapidjson::StringRef(altName)); + if (iterator == inputValue.MemberEnd()) + { + // field not found so leave default value + result.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed)); + nameUsed = nullptr; + } + } + + if (nameUsed) + { + ScopedContextPath subPath(context, nameUsed); + JSR::Result intermediate = floatSerializer->Load(&output, azrtti_typeid(), iterator->value, context); + if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediate; + } + else + { + result.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success)); + } + } + + return context.Report(result, "Successfully read float."); + } + + JsonSerializationResult::Result LoadVector3FromObject( + Vector3& output, + const rapidjson::Value& inputValue, + JsonDeserializerContext& context, + AZStd::fixed_vector names) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + constexpr size_t ElementCount = 3; // Vector3 + + JSR::ResultCode result(JSR::Tasks::ReadField); + float values[ElementCount]; + for (int i = 0; i < ElementCount; ++i) + { + values[i] = output.GetElement(i); + auto name = names[i * 2]; + auto altName = names[(i * 2) + 1]; + + JSR::Result intermediate = LoadFloatFromObject(values[i], inputValue, context, name.data(), altName.data()); + if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediate; + } + else + { + result.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success)); + } + } + + for (int i = 0; i < ElementCount; ++i) + { + output.SetElement(i, values[i]); + } + + return context.Report(result, "Successfully read math matrix."); + } + + JsonSerializationResult::Result LoadQuaternionAndScale( + AZ::Quaternion& quaternion, + float& scale, + const rapidjson::Value& inputValue, + JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + + JSR::ResultCode result(JSR::Tasks::ReadField); + scale = 1.0f; + JSR::Result intermediateScale = LoadFloatFromObject(scale, inputValue, context, "scale", "Scale"); + if (intermediateScale.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediateScale; + } + result.Combine(intermediateScale); + + if (AZ::IsClose(scale, 0.0f)) + { + result.Combine({ JSR::Tasks::ReadField, JSR::Outcomes::Unsupported }); + return context.Report(result, "Scale can not be zero."); + } + + AZ::Vector3 degreesRollPitchYaw = AZ::Vector3::CreateZero(); + JSR::Result intermediateDegrees = LoadVector3FromObject(degreesRollPitchYaw, inputValue, context, { "roll", "Roll", "pitch", "Pitch", "yaw", "Yaw" }); + if (intermediateDegrees.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediateDegrees; + } + result.Combine(intermediateDegrees); + + // the quaternion should be equivalent to a series of rotations in the order z, then y, then x + const AZ::Vector3 eulerRadians = AZ::Vector3DegToRad(degreesRollPitchYaw); + quaternion = AZ::Quaternion::CreateRotationX(eulerRadians.GetX()) * + AZ::Quaternion::CreateRotationY(eulerRadians.GetY()) * + AZ::Quaternion::CreateRotationZ(eulerRadians.GetZ()); + + return context.Report(result, "Successfully read math yaw, pitch, roll, and scale."); + } + + template + JsonSerializationResult::Result LoadObject(MatrixType& output, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + output = MatrixType::CreateIdentity(); + + JSR::ResultCode result(JSR::Tasks::ReadField); + float scale; + AZ::Quaternion rotation; + + JSR::Result intermediate = LoadQuaternionAndScale(rotation, scale, inputValue, context); + if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediate; + } + result.Combine(intermediate); + + AZ::Vector3 translation = AZ::Vector3::CreateZero(); + JSR::Result intermediateTranslation = LoadVector3FromObject(translation, inputValue, context, { "x", "X", "y", "Y", "z", "Z" }); + if (intermediateTranslation.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediateTranslation; + } + result.Combine(intermediateTranslation); + + // composed a matrix by rotation, then scale, then translation + auto matrix = MatrixType::CreateFromQuaternion(rotation); + matrix.MultiplyByScale(Vector3{ scale }); + matrix.SetTranslation(translation); + + if (matrix == MatrixType::CreateIdentity()) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Using identity matrix for empty object."); + } + + output = matrix; + return context.Report(result, "Successfully read math matrix."); + } + + template<> + JsonSerializationResult::Result LoadObject(Matrix3x3& output, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + output = Matrix3x3::CreateIdentity(); + + JSR::ResultCode result(JSR::Tasks::ReadField); + float scale; + AZ::Quaternion rotation; + + JSR::Result intermediate = LoadQuaternionAndScale(rotation, scale, inputValue, context); + if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed) + { + return intermediate; + } + result.Combine(intermediate); + + // composed a matrix by rotation then scale + auto matrix = Matrix3x3::CreateFromQuaternion(rotation); + matrix.MultiplyByScale(Vector3{ scale }); + + if (matrix == Matrix3x3::CreateIdentity()) + { + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Using identity matrix for empty object."); + } + + output = matrix; + return context.Report(result, "Successfully read math matrix."); + } + + template + JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + + constexpr size_t ElementCount = RowCount * ColumnCount; + static_assert(ElementCount == 9 || ElementCount == 12 || ElementCount == 16, + "MathMatrixSerializer only support Matrix3x3, Matrix3x4 and Matrix4x4."); + + AZ_Assert(azrtti_typeid() == outputValueTypeId, + "Unable to deserialize Matrix%zux%zu to json because the provided type is %s", + RowCount, ColumnCount, outputValueTypeId.ToString().c_str()); + AZ_UNUSED(outputValueTypeId); + + MatrixType* matrix = reinterpret_cast(outputValue); + AZ_Assert(matrix, "Output value for JsonMatrix%zux%zuSerializer can't be null.", RowCount, ColumnCount); + + switch (inputValue.GetType()) + { + case rapidjson::kArrayType: + return LoadArray(*matrix, inputValue, context); + case rapidjson::kObjectType: + return LoadObject(*matrix, inputValue, context); + + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kNumberType: + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; + case rapidjson::kTrueType: + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, + "Unsupported type. Math matrix can only be read from arrays or objects."); + + default: + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unknown, + "Unknown json type encountered in math matrix."); + } + } + + template + AZ::Quaternion CreateQuaternion(const MatrixType& matrix); + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix3x3& matrix) + { + return Quaternion::CreateFromMatrix3x3(matrix); + } + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix3x4& matrix) + { + return Quaternion::CreateFromMatrix3x4(matrix); + } + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix4x4& matrix) + { + return Quaternion::CreateFromMatrix4x4(matrix); + } + + template + JsonSerializationResult::Result StoreRotationAndScale(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, + const Uuid& valueTypeId, JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + AZ_UNUSED(valueTypeId); + + const MatrixType* matrix = reinterpret_cast(inputValue); + AZ_Assert(matrix, "Input value for JsonMatrixSerializer can't be null."); + const MatrixType* defaultMatrix = reinterpret_cast(defaultValue); + + if (!context.ShouldKeepDefaults() && defaultMatrix && *matrix == *defaultMatrix) + { + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "Default math Matrix used."); + } + + MatrixType matrixToExport = *matrix; + AZ::Vector3 scale = matrixToExport.ExtractScale(); + + AZ::Quaternion rotation = CreateQuaternion(matrixToExport); + auto degrees = rotation.GetEulerDegrees(); + outputValue.AddMember(rapidjson::StringRef("roll"), degrees.GetX(), context.GetJsonAllocator()); + outputValue.AddMember(rapidjson::StringRef("pitch"), degrees.GetY(), context.GetJsonAllocator()); + outputValue.AddMember(rapidjson::StringRef("yaw"), degrees.GetZ(), context.GetJsonAllocator()); + outputValue.AddMember(rapidjson::StringRef("scale"), scale.GetX(), context.GetJsonAllocator()); + + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::Success, "Math Matrix successfully stored."); + } + + template + JsonSerializationResult::Result StoreTranslation(rapidjson::Value& outputValue, const void* inputValue, + const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. + AZ_UNUSED(valueTypeId); + + const MatrixType* matrix = reinterpret_cast(inputValue); + AZ_Assert(matrix, "Input value for JsonMatrixSerializer can't be null."); + const MatrixType* defaultMatrix = reinterpret_cast(defaultValue); + + if (!context.ShouldKeepDefaults() && defaultMatrix && *matrix == *defaultMatrix) + { + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "Default math Matrix used."); + } + + auto translation = matrix->GetTranslation(); + outputValue.AddMember(rapidjson::StringRef("x"), translation.GetX(), context.GetJsonAllocator()); + outputValue.AddMember(rapidjson::StringRef("y"), translation.GetY(), context.GetJsonAllocator()); + outputValue.AddMember(rapidjson::StringRef("z"), translation.GetZ(), context.GetJsonAllocator()); + + return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::Success, "Math Matrix successfully stored."); + } +} + +namespace AZ +{ + // Matrix3x3 + + AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix3x3Serializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonMatrix3x3Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + return JsonMathMatrixSerializerInternal::Load( + outputValue, + outputValueTypeId, + inputValue, + context); + } + + JsonSerializationResult::Result JsonMatrix3x3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, + const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + outputValue.SetObject(); + + return JsonMathMatrixSerializerInternal::StoreRotationAndScale( + outputValue, + inputValue, + defaultValue, + valueTypeId, + context); + } + + + // Matrix3x4 + + AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix3x4Serializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonMatrix3x4Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + return JsonMathMatrixSerializerInternal::Load( + outputValue, + outputValueTypeId, + inputValue, + context); + } + + JsonSerializationResult::Result JsonMatrix3x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, + const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + outputValue.SetObject(); + + auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale( + outputValue, + inputValue, + defaultValue, + valueTypeId, + context); + + auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation( + outputValue, + inputValue, + defaultValue, + valueTypeId, + context); + + result.GetResultCode().Combine(resultTranslation); + return result; + } + + // Matrix4x4 + + AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix4x4Serializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonMatrix4x4Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + return JsonMathMatrixSerializerInternal::Load( + outputValue, + outputValueTypeId, + inputValue, + context); + } + + JsonSerializationResult::Result JsonMatrix4x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, + const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) + { + outputValue.SetObject(); + + auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale( + outputValue, + inputValue, + defaultValue, + valueTypeId, + context); + + auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation( + outputValue, + inputValue, + defaultValue, + valueTypeId, + context); + + result.GetResultCode().Combine(resultTranslation); + return result; + } +} diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h new file mode 100644 index 0000000000..81c9635a79 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace AZ +{ + class JsonMatrix3x3Serializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, + const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; + + class JsonMatrix3x4Serializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, + const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; + + class JsonMatrix4x4Serializer + : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, + const Uuid& valueTypeId, JsonSerializerContext& context) override; + }; +} diff --git a/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp b/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp index e918f8fdb3..3c683f1988 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -366,6 +367,9 @@ namespace AZ { context.Serializer()->HandlesType(); context.Serializer()->HandlesType(); + context.Serializer()->HandlesType(); + context.Serializer()->HandlesType(); + context.Serializer()->HandlesType(); context.Serializer()->HandlesType(); context.Serializer()->HandlesType(); context.Serializer()->HandlesType(); diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 5357ed66a6..dc0fb13f00 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -290,6 +290,8 @@ set(FILES Math/MathScriptHelpers.h Math/MathUtils.cpp Math/MathUtils.h + Math/MathMatrixSerializer.h + Math/MathMatrixSerializer.cpp Math/MathVectorSerializer.h Math/MathVectorSerializer.cpp Math/Matrix3x3.cpp diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp new file mode 100644 index 0000000000..b9d1edab76 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Serialization/Json/MathMatrixSerializerTests.cpp @@ -0,0 +1,562 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace JsonSerializationTests +{ + namespace DataHelper + { + // Build Matrix + + template + MatrixType BuildMatrixRotationWithSale(const AZ::Vector3& angles, float scale) + { + // start a matrix with angle degrees + const AZ::Vector3 eulerRadians = AZ::Vector3DegToRad(angles); + const auto rotX = MatrixType::CreateRotationX(eulerRadians.GetX()); + const auto rotY = MatrixType::CreateRotationY(eulerRadians.GetY()); + const auto rotZ = MatrixType::CreateRotationZ(eulerRadians.GetZ()); + auto matrix = rotX * rotY * rotZ; + + // apply a scale + matrix.MultiplyByScale(AZ::Vector3{ scale }); + return matrix; + } + + template + MatrixType BuildMatrix(const AZ::Vector3& angles, float scale, const AZ::Vector3& translation) + { + auto matrix = BuildMatrixRotationWithSale(angles, scale); + matrix.SetTranslation(translation); + return matrix; + } + + template <> + AZ::Matrix3x3 BuildMatrix(const AZ::Vector3& angles, float scale, const AZ::Vector3&) + { + return BuildMatrixRotationWithSale(angles, scale); + } + + // Arbitrary Matrix + + template + MatrixType CreateArbitraryMatrixRotationAndSale(AZ::SimpleLcgRandom& random) + { + // start a matrix with arbitrary degrees + float roll = random.GetRandomFloat() * 360.0f; + float pitch = random.GetRandomFloat() * 360.0f; + float yaw = random.GetRandomFloat() * 360.0f; + const AZ::Vector3 eulerRadians = AZ::Vector3DegToRad(AZ::Vector3{ roll, pitch, yaw }); + const auto rotX = MatrixType::CreateRotationX(eulerRadians.GetX()); + const auto rotY = MatrixType::CreateRotationY(eulerRadians.GetY()); + const auto rotZ = MatrixType::CreateRotationZ(eulerRadians.GetZ()); + auto matrix = rotX * rotY * rotZ; + + // apply a scale + matrix.MultiplyByScale(AZ::Vector3{ random.GetRandomFloat() }); + return matrix; + } + + template + void AssignArbitrarySetTranslation(MatrixType& matrix, AZ::SimpleLcgRandom& random) + { + float x = random.GetRandomFloat() * 10000.0f; + float y = random.GetRandomFloat() * 10000.0f; + float z = random.GetRandomFloat() * 10000.0f; + matrix.SetTranslation(AZ::Vector3{ x, y, z }); + } + + template + MatrixType CreateArbitraryMatrix(size_t seed); + + template <> + AZ::Matrix3x3 CreateArbitraryMatrix(size_t seed) + { + AZ::SimpleLcgRandom random(seed); + return CreateArbitraryMatrixRotationAndSale(random); + } + + template <> + AZ::Matrix3x4 CreateArbitraryMatrix(size_t seed) + { + AZ::SimpleLcgRandom random(seed); + auto matrix = CreateArbitraryMatrixRotationAndSale(random); + AssignArbitrarySetTranslation(matrix, random); + return matrix; + } + + template <> + AZ::Matrix4x4 CreateArbitraryMatrix(size_t seed) + { + AZ::SimpleLcgRandom random(seed); + auto matrix = CreateArbitraryMatrixRotationAndSale(random); + AssignArbitrarySetTranslation(matrix, random); + return matrix; + } + + // CreateQuaternion + + template + AZ::Quaternion CreateQuaternion(const MatrixType& matrix); + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix3x3& matrix) + { + return AZ::Quaternion::CreateFromMatrix3x3(matrix); + } + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix3x4& matrix) + { + return AZ::Quaternion::CreateFromMatrix3x4(matrix); + } + + template<> + AZ::Quaternion CreateQuaternion(const AZ::Matrix4x4& matrix) + { + return AZ::Quaternion::CreateFromMatrix4x4(matrix); + } + + template + void AddRotation(rapidjson::Value& value, const MatrixType& matrix, rapidjson::Document::AllocatorType& allocator) + { + AZ::Quaternion rotation = CreateQuaternion(matrix); + const auto degrees = rotation.GetEulerDegrees(); + value.AddMember("yaw", degrees.GetX(), allocator); + value.AddMember("pitch", degrees.GetY(), allocator); + value.AddMember("roll", degrees.GetZ(), allocator); + } + + void AddScale(rapidjson::Value& value, float scale, rapidjson::Document::AllocatorType& allocator) + { + value.AddMember("scale", scale, allocator); + } + + void AddTranslation(rapidjson::Value& value, const AZ::Vector3& translation, rapidjson::Document::AllocatorType& allocator) + { + value.AddMember("x", translation.GetX(), allocator); + value.AddMember("y", translation.GetY(), allocator); + value.AddMember("z", translation.GetZ(), allocator); + } + + template + void AddData(rapidjson::Value& value, const MatrixType& matrix, rapidjson::Document::AllocatorType& allocator); + + template <> + void AddData(rapidjson::Value& value, const AZ::Matrix3x3& matrix, rapidjson::Document::AllocatorType& allocator) + { + AddScale(value, matrix.RetrieveScale().GetX(), allocator); + AddRotation(value, matrix, allocator); + } + + template <> + void AddData(rapidjson::Value& value, const AZ::Matrix3x4& matrix, rapidjson::Document::AllocatorType& allocator) + { + AddScale(value, matrix.RetrieveScale().GetX(), allocator); + AddTranslation(value, matrix.GetTranslation(), allocator); + AddRotation(value, matrix, allocator); + } + + template <> + void AddData(rapidjson::Value& value, const AZ::Matrix4x4& matrix, rapidjson::Document::AllocatorType& allocator) + { + AddScale(value, matrix.RetrieveScale().GetX(), allocator); + AddTranslation(value, matrix.GetTranslation(), allocator); + AddRotation(value, matrix, allocator); + } + }; + + template + class MathMatrixSerializerTestDescription : + public JsonSerializerConformityTestDescriptor + { + public: + AZStd::shared_ptr CreateSerializer() override + { + return AZStd::make_shared(); + } + + AZStd::shared_ptr CreateDefaultInstance() override + { + return AZStd::make_shared(MatrixType::CreateIdentity()); + } + + AZStd::shared_ptr CreateFullySetInstance() override + { + auto angles = AZ::Vector3 { 0.0f, 0.0f, 0.0f }; + auto scale = 10.0f; + auto translation = AZ::Vector3{ 10.0f, 20.0f, 30.0f }; + auto matrix = DataHelper::BuildMatrix(angles, scale, translation); + return AZStd::make_shared(matrix); + } + + AZStd::string_view GetJsonForFullySetInstance() override + { + if constexpr (RowCount * ColumnCount == 9) + { + return "{\"roll\":0.0,\"pitch\":0.0,\"yaw\":0.0,\"scale\":10.0}"; + } + else if constexpr (RowCount * ColumnCount == 12) + { + return "{\"roll\":0.0,\"pitch\":0.0,\"yaw\":0.0,\"scale\":10.0,\"x\":10.0,\"y\":20.0,\"z\":30.0}"; + } + else if constexpr (RowCount * ColumnCount == 16) + { + return "{\"roll\":0.0,\"pitch\":0.0,\"yaw\":0.0,\"scale\":10.0,\"x\":10.0,\"y\":20.0,\"z\":30.0}"; + } + else + { + static_assert((RowCount >= 3 && RowCount <= 4) && (ColumnCount >= 3 && ColumnCount <= 4), + "Only matrix 3x3, 3x4 or 4x4 are supported by this test."); + } + return "{}"; + } + + void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override + { + features.EnableJsonType(rapidjson::kArrayType); + features.EnableJsonType(rapidjson::kObjectType); + features.m_fixedSizeArray = true; + features.m_supportsPartialInitialization = false; + features.m_supportsInjection = false; + } + + bool AreEqual(const MatrixType& lhs, const MatrixType& rhs) override + { + for (int r = 0; r < RowCount; ++r) + { + for (int c = 0; c < ColumnCount; ++c) + { + if (!AZ::IsClose(lhs.GetElement(r, c), rhs.GetElement(r, c), AZ::Constants::Tolerance)) + { + return false; + } + } + } + return true; + } + }; + + using MathMatrixSerializerConformityTestTypes = ::testing::Types< + MathMatrixSerializerTestDescription, + MathMatrixSerializerTestDescription, + MathMatrixSerializerTestDescription + >; + INSTANTIATE_TYPED_TEST_CASE_P(JsonMathMatrixSerializer, JsonSerializerConformityTests, MathMatrixSerializerConformityTestTypes); + + template + class JsonMathMatrixSerializerTests + : public BaseJsonSerializerFixture + { + public: + using Descriptor = T; + + void SetUp() override + { + BaseJsonSerializerFixture::SetUp(); + m_serializer = AZStd::make_unique(); + } + + void TearDown() override + { + m_serializer.reset(); + BaseJsonSerializerFixture::TearDown(); + } + + protected: + AZStd::unique_ptr m_serializer; + }; + + struct Matrix3x3Descriptor + { + using MatrixType = AZ::Matrix3x3; + using Serializer = AZ::JsonMatrix3x3Serializer; + constexpr static size_t RowCount = 3; + constexpr static size_t ColumnCount = 3; + constexpr static size_t ElementCount = RowCount * ColumnCount; + constexpr static bool HasTranslation = false; + }; + + struct Matrix3x4Descriptor + { + using MatrixType = AZ::Matrix3x4; + using Serializer = AZ::JsonMatrix3x4Serializer; + constexpr static size_t RowCount = 3; + constexpr static size_t ColumnCount = 4; + constexpr static size_t ElementCount = RowCount * ColumnCount; + constexpr static bool HasTranslation = true; + }; + + struct Matrix4x4Descriptor + { + using MatrixType = AZ::Matrix4x4; + using Serializer = AZ::JsonMatrix4x4Serializer; + constexpr static size_t RowCount = 4; + constexpr static size_t ColumnCount = 4; + constexpr static size_t ElementCount = RowCount * ColumnCount; + constexpr static bool HasTranslation = true; + }; + + using JsonMathMatrixSerializerTypes = ::testing::Types < + Matrix3x3Descriptor, Matrix3x4Descriptor, Matrix4x4Descriptor>; + TYPED_TEST_CASE(JsonMathMatrixSerializerTests, JsonMathMatrixSerializerTypes); + + // Load array tests + + TYPED_TEST(JsonMathMatrixSerializerTests, Load_Array_ReturnsConvertAndLoadsMatrix) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value& arrayValue = this->m_jsonDocument->SetArray(); + for (size_t i = 0; i < JsonMathMatrixSerializerTests::Descriptor::ElementCount; ++i) + { + arrayValue.PushBack(static_cast(i + 1), this->m_jsonDocument->GetAllocator()); + } + + auto output = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateZero(); + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + ASSERT_EQ(Outcomes::Success, result.GetOutcome()); + + for (int r = 0; r < JsonMathMatrixSerializerTests::Descriptor::RowCount; ++r) + { + for (int c = 0; c < JsonMathMatrixSerializerTests::Descriptor::ColumnCount; ++c) + { + auto testValue = static_cast((r * JsonMathMatrixSerializerTests::Descriptor::ColumnCount) + c + 1); + EXPECT_FLOAT_EQ(testValue, output.GetElement(r, c)); + } + } + } + + TYPED_TEST(JsonMathMatrixSerializerTests, Load_InvalidEntries_ReturnsUnsupportedAndLeavesMatrixUntouched) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value& arrayValue = this->m_jsonDocument->SetArray(); + for (size_t i = 0; i < JsonMathMatrixSerializerTests::Descriptor::ElementCount; ++i) + { + if (i == 1) + { + arrayValue.PushBack(rapidjson::StringRef("Invalid"), this->m_jsonDocument->GetAllocator()); + } + else + { + arrayValue.PushBack(static_cast(i + 1), this->m_jsonDocument->GetAllocator()); + } + } + + auto output = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateZero(); + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome()); + + for (int r = 0; r < JsonMathMatrixSerializerTests::Descriptor::RowCount; ++r) + { + for (int c = 0; c < JsonMathMatrixSerializerTests::Descriptor::ColumnCount; ++c) + { + EXPECT_FLOAT_EQ(0.0f, output.GetElement(r, c)); + } + } + } + + TYPED_TEST(JsonMathMatrixSerializerTests, Load_FloatSerializerMissingForArray_ReturnsCatastrophic) + { + using namespace AZ::JsonSerializationResult; + + this->m_jsonRegistrationContext->EnableRemoveReflection(); + this->m_jsonRegistrationContext->template Serializer()->template HandlesType(); + this->m_jsonRegistrationContext->DisableRemoveReflection(); + + rapidjson::Value& arrayValue = this->m_jsonDocument->SetArray(); + for (size_t i = 0; i < JsonMathMatrixSerializerTests::Descriptor::ElementCount + 1; ++i) + { + arrayValue.PushBack(static_cast(i + 1), this->m_jsonDocument->GetAllocator()); + } + + typename JsonMathMatrixSerializerTests::Descriptor::MatrixType output; + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + EXPECT_EQ(Outcomes::Catastrophic, result.GetOutcome()); + + this->m_jsonRegistrationContext->template Serializer()->template HandlesType(); + } + + // Load object tests + TYPED_TEST(JsonMathMatrixSerializerTests, Load_ValidObjectLowerCase_ReturnsSuccessAndLoadsMatrix) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value& objectValue = this->m_jsonDocument->SetObject(); + auto input = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateIdentity(); + DataHelper::AddData(objectValue, input, this->m_jsonDocument->GetAllocator()); + + auto output = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateZero(); + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + ASSERT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_TRUE(input == output); + } + + TYPED_TEST(JsonMathMatrixSerializerTests, Load_ValidObjectWithExtraFields_ReturnsPartialConvertAndLoadsMatrix) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value& objectValue = this->m_jsonDocument->SetObject(); + auto input = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateIdentity(); + DataHelper::AddScale(objectValue, input.RetrieveScale().GetX(), this->m_jsonDocument->GetAllocator()); + DataHelper::AddRotation(objectValue, input, this->m_jsonDocument->GetAllocator()); + objectValue.AddMember(rapidjson::StringRef("extra"), "no value", this->m_jsonDocument->GetAllocator()); + + auto output = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateZero(); + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + ASSERT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_TRUE(input == output); + } + + TYPED_TEST(JsonMathMatrixSerializerTests, SaveLoad_Identity_LoadsDefaultMatrixWithIdentity) + { + using namespace AZ::JsonSerializationResult; + + auto defaultValue = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateIdentity(); + + rapidjson::Value& objectInput = this->m_jsonDocument->SetObject(); + this->m_serializer->Store( + objectInput, + &defaultValue, + &defaultValue, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonSerializationContext); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + objectInput.Accept(writer); + + auto output = defaultValue; + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + + EXPECT_TRUE(defaultValue == output); + } + + TYPED_TEST(JsonMathMatrixSerializerTests, LoadSave_Zero_SavesAndLoadsIdentityMatrix) + { + using namespace AZ::JsonSerializationResult; + + auto defaultValue = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateIdentity(); + auto input = JsonMathMatrixSerializerTests::Descriptor::MatrixType::CreateZero(); + + rapidjson::Value& objectInput = this->m_jsonDocument->SetObject(); + this->m_serializer->Store( + objectInput, + &input, + &defaultValue, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonSerializationContext); + + auto output = defaultValue; + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid::Descriptor::MatrixType>(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + + ASSERT_EQ(Outcomes::Unsupported, result.GetOutcome()); + EXPECT_TRUE(defaultValue == output); + } + + TYPED_TEST(JsonMathMatrixSerializerTests, Load_InvalidFields_ReturnsUnsupportedAndLeavesMatrixUntouched) + { + using namespace AZ::JsonSerializationResult; + using Descriptor = typename JsonMathMatrixSerializerTests::Descriptor; + + const auto defaultValue = Descriptor::MatrixType::CreateIdentity(); + rapidjson::Value& objectValue = this->m_jsonDocument->SetObject(); + auto input = Descriptor::MatrixType::CreateIdentity(); + DataHelper::AddData(objectValue, input, this->m_jsonDocument->GetAllocator()); + objectValue["yaw"] = "Invalid"; + + auto output = Descriptor::MatrixType::CreateZero(); + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + ASSERT_EQ(Outcomes::Unsupported, result.GetOutcome()); + EXPECT_TRUE(input == output); + } + + TYPED_TEST(JsonMathMatrixSerializerTests, LoadSave_Arbitrary_SavesAndLoadsArbitraryMatrix) + { + using namespace AZ::JsonSerializationResult; + using Descriptor = typename JsonMathMatrixSerializerTests::Descriptor; + + auto defaultValue = Descriptor::MatrixType::CreateIdentity(); + size_t elementCount = Descriptor::RowCount * Descriptor::ColumnCount; + auto input = DataHelper::CreateArbitraryMatrix(elementCount); + + rapidjson::Value& objectInput = this->m_jsonDocument->SetObject(); + this->m_serializer->Store( + objectInput, + &input, + &defaultValue, + azrtti_typeid(), + *this->m_jsonSerializationContext); + + auto output = defaultValue; + ResultCode result = this->m_serializer->Load( + &output, + azrtti_typeid(), + *this->m_jsonDocument, + *this->m_jsonDeserializationContext); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + + for (int r = 0; r < Descriptor::RowCount; ++r) + { + for (int c = 0; c < Descriptor::ColumnCount; ++c) + { + EXPECT_NEAR(input.GetElement(r, c), output.GetElement(r, c), AZ::Constants::Tolerance); + } + } + } + +} // namespace JsonSerializationTests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index 2129761bfe..f90717d003 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -111,6 +111,7 @@ set(FILES Serialization/Json/JsonSerializerMock.h Serialization/Json/MapSerializerTests.cpp Serialization/Json/MathVectorSerializerTests.cpp + Serialization/Json/MathMatrixSerializerTests.cpp Serialization/Json/SmartPointerSerializerTests.cpp Serialization/Json/StringSerializerTests.cpp Serialization/Json/TestCases.h diff --git a/Code/CryEngine/CrySystem/SystemUtilsApple.h b/Code/Framework/AzFramework/Platform/Common/Apple/AzFramework/Utils/SystemUtilsApple.h similarity index 100% rename from Code/CryEngine/CrySystem/SystemUtilsApple.h rename to Code/Framework/AzFramework/Platform/Common/Apple/AzFramework/Utils/SystemUtilsApple.h diff --git a/Code/CryEngine/CrySystem/SystemUtilsApple.mm b/Code/Framework/AzFramework/Platform/Common/Apple/AzFramework/Utils/SystemUtilsApple.mm similarity index 100% rename from Code/CryEngine/CrySystem/SystemUtilsApple.mm rename to Code/Framework/AzFramework/Platform/Common/Apple/AzFramework/Utils/SystemUtilsApple.mm diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Utils/SystemUtilsApple.h b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Utils/SystemUtilsApple.h new file mode 100644 index 0000000000..33a89bd146 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Utils/SystemUtilsApple.h @@ -0,0 +1,16 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once + +#include "../../../Common/Apple/AzFramework/Utils/SystemUtilsApple.h" diff --git a/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake index 9f4a09418f..b69278665a 100644 --- a/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzFramework/Platform/Mac/platform_mac_files.cmake @@ -36,4 +36,6 @@ set(FILES ../Common/Unimplemented/AzFramework/Input/Devices/VirtualKeyboard/InputDeviceVirtualKeyboard_Unimplemented.cpp AzFramework/Archive/ArchiveVars_Platform.h AzFramework/Archive/ArchiveVars_Mac.h + ../Common/Apple/AzFramework/Utils/SystemUtilsApple.h + ../Common/Apple/AzFramework/Utils/SystemUtilsApple.mm ) diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Utils/SystemUtilsApple.h b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Utils/SystemUtilsApple.h new file mode 100644 index 0000000000..5ac96c8523 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Utils/SystemUtilsApple.h @@ -0,0 +1,15 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include "../../../Common/Apple/AzFramework/Utils/SystemUtilsApple.h" diff --git a/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake b/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake index c3e5e7b7c1..f1bf958067 100644 --- a/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake +++ b/Code/Framework/AzFramework/Platform/iOS/platform_ios_files.cmake @@ -36,5 +36,7 @@ set(FILES AzFramework/Process/ProcessCommon.h AzFramework/Process/ProcessWatcher_iOS.cpp AzFramework/Process/ProcessCommunicator_iOS.cpp + ../Common/Apple/AzFramework/Utils/SystemUtilsApple.h + ../Common/Apple/AzFramework/Utils/SystemUtilsApple.mm ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 4e7a520698..ee95412376 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -178,6 +178,24 @@ namespace AzToolsFramework ~ViewportInteractionRequests() = default; }; + /// Interface to return only viewport specific settings (e.g. snapping). + class ViewportSettings + { + public: + virtual ~ViewportSettings() = default; + + /// Return if grid snapping is enabled. + virtual bool GridSnappingEnabled() const = 0; + /// Return the grid snapping size. + virtual float GridSize() const = 0; + /// Does the grid currently want to be displayed. + virtual bool ShowGrid() const = 0; + /// Return if angle snapping is enabled. + virtual bool AngleSnappingEnabled() const = 0; + /// Return the angle snapping/step size. + virtual float AngleStep() const = 0; + }; + /// Type to inherit to implement ViewportInteractionRequests. using ViewportInteractionRequestBus = AZ::EBus; diff --git a/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm b/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm index ca7ab2def0..d78a83607b 100644 --- a/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm +++ b/Code/LauncherUnified/Platform/iOS/O3DEApplicationDelegate_iOS.mm @@ -19,7 +19,7 @@ #include // for AZ_MAX_PATH_LEN -#include +#include #import diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index d9344746a2..e208e83067 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -161,6 +161,7 @@ EditorViewportWidget::EditorViewportWidget(const QString& name, QWidget* parent) , m_camFOV(gSettings.viewports.fDefaultFov) , m_defaultViewName(name) , m_renderViewport(nullptr) //m_renderViewport is initialized later, in SetViewportId + , m_editorViewportSettings(this) { // need this to be set in order to allow for language switching on Windows setAttribute(Qt::WA_InputMethodEnabled); @@ -1098,32 +1099,6 @@ AzFramework::CameraState EditorViewportWidget::GetCameraState() return m_renderViewport->GetCameraState(); } -bool EditorViewportWidget::GridSnappingEnabled() -{ - return GetViewManager()->GetGrid()->IsEnabled(); -} - -float EditorViewportWidget::GridSize() -{ - const CGrid* grid = GetViewManager()->GetGrid(); - return grid->scale * grid->size; -} - -bool EditorViewportWidget::ShowGrid() -{ - return gSettings.viewports.bShowGridGuide; -} - -bool EditorViewportWidget::AngleSnappingEnabled() -{ - return GetViewManager()->GetGrid()->IsAngleSnapEnabled(); -} - -float EditorViewportWidget::AngleStep() -{ - return GetViewManager()->GetGrid()->GetAngleSnap(); -} - AZ::Vector3 EditorViewportWidget::PickTerrain(const AzFramework::ScreenPoint& point) { FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR); @@ -1234,6 +1209,8 @@ void EditorViewportWidget::SetViewportId(int id) m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); } + m_renderViewport->SetViewportSettings(&m_editorViewportSettings); + UpdateScene(); if (m_pPrimaryViewport == this) @@ -2853,4 +2830,35 @@ void EditorViewportWidget::SetAsActiveViewport() } } +EditorViewportSettings::EditorViewportSettings(const EditorViewportWidget* editorViewportWidget) + : m_editorViewportWidget(editorViewportWidget) +{ +} + +bool EditorViewportSettings::GridSnappingEnabled() const +{ + return m_editorViewportWidget->GetViewManager()->GetGrid()->IsEnabled(); +} + +float EditorViewportSettings::GridSize() const +{ + const CGrid* grid = m_editorViewportWidget->GetViewManager()->GetGrid(); + return grid->scale * grid->size; +} + +bool EditorViewportSettings::ShowGrid() const +{ + return gSettings.viewports.bShowGridGuide; +} + +bool EditorViewportSettings::AngleSnappingEnabled() const +{ + return m_editorViewportWidget->GetViewManager()->GetGrid()->IsAngleSnapEnabled(); +} + +float EditorViewportSettings::AngleStep() const +{ + return m_editorViewportWidget->GetViewManager()->GetGrid()->GetAngleSnap(); +} + #include diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index 09474200f1..8675c035f6 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -65,6 +65,23 @@ namespace AzToolsFramework class ManipulatorManager; } +class EditorViewportWidget; + +//! Viewport settings for the EditorViewportWidget +struct EditorViewportSettings : public AzToolsFramework::ViewportInteraction::ViewportSettings +{ + explicit EditorViewportSettings(const EditorViewportWidget* editorViewportWidget); + + bool GridSnappingEnabled() const override; + float GridSize() const override; + bool ShowGrid() const override; + bool AngleSnappingEnabled() const override; + float AngleStep() const override; + +private: + const EditorViewportWidget* m_editorViewportWidget = nullptr; +}; + // EditorViewportWidget window AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING @@ -189,13 +206,7 @@ public: virtual void OnStartPlayInEditor(); virtual void OnStopPlayInEditor(); - // AzToolsFramework::ViewportInteractionRequestBus AzFramework::CameraState GetCameraState(); - bool GridSnappingEnabled(); - float GridSize(); - bool ShowGrid(); - bool AngleSnappingEnabled(); - float AngleStep(); AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition); // AzToolsFramework::ViewportFreezeRequestBus @@ -596,5 +607,7 @@ private: AZ::Name m_defaultViewportContextName; + EditorViewportSettings m_editorViewportSettings; + AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING }; diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp index 30a7978c50..19b516b681 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.cpp @@ -124,131 +124,29 @@ namespace AssetProcessor NativeLegacyRCCompiler::NativeLegacyRCCompiler() : m_resourceCompilerInitialized(false) - , m_systemRoot() - , m_rcExecutableFullPath() , m_requestedQuit(false) { } - - bool NativeLegacyRCCompiler::Initialize(const QString& systemRoot, const QString& rcExecutableFullPath) + + bool NativeLegacyRCCompiler::Initialize() { - // QFile::exists(normalizedPath) - if (!QDir(systemRoot).exists()) - { - AZ_TracePrintf(AssetProcessor::DebugChannel, QString("Cannot locate system root dir %1").arg(systemRoot).toUtf8().data()); - return false; - } - - if (!AZ::IO::SystemFile::Exists(rcExecutableFullPath.toUtf8().data())) - { - AZ_TracePrintf(AssetProcessor::DebugChannel, QString("Invalid executable path '%1'").arg(rcExecutableFullPath).toUtf8().data()); - return false; - } - this->m_systemRoot.setPath(systemRoot); - this->m_rcExecutableFullPath = rcExecutableFullPath; this->m_resourceCompilerInitialized = true; return true; } - bool NativeLegacyRCCompiler::Execute(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, - const QString& params, const QString& dest, const AssetBuilderSDK::JobCancelListener* jobCancelListener, Result& result) const + bool NativeLegacyRCCompiler::Execute( + [[maybe_unused]] const QString& inputFile, + [[maybe_unused]] const QString& watchFolder, + [[maybe_unused]] const QString& platformIdentifier, + [[maybe_unused]] const QString& params, + [[maybe_unused]] const QString& dest, + [[maybe_unused]] const AssetBuilderSDK::JobCancelListener* jobCancelListener, + [[maybe_unused]] Result& result) const { - if (!this->m_resourceCompilerInitialized) - { - result.m_exitCode = JobExitCode_RCCouldNotBeLaunched; - result.m_crashed = false; - AZ_Warning("RC Builder", false, "RC Compiler has not been initialized before use."); - return false; - } + // running RC.EXE is deprecated. + AZ_Error("RC Builder", false, "running RC.EXE is deprecated"); - // build the command line: - QString commandString = NativeLegacyRCCompiler::BuildCommand(inputFile, watchFolder, platformIdentifier, params, dest); - - AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; - - // while it might be tempting to set the executable in processLaunchInfo.m_processExecutableString, it turns out that RC.EXE - // won't work if you do that because it assumes the first command line param is the exe name, which is not the case if you do it that way... - - QString formatter("\"%1\" %2"); - processLaunchInfo.m_commandlineParameters = QString(formatter).arg(m_rcExecutableFullPath).arg(commandString).toUtf8().data(); - processLaunchInfo.m_showWindow = false; - processLaunchInfo.m_workingDirectory = m_systemRoot.absolutePath().toUtf8().data(); - processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_IDLE; - - AZ_TracePrintf("RC Builder", "Executing RC.EXE: '%s' ...\n", processLaunchInfo.m_commandlineParameters.c_str()); - AZ_TracePrintf("Rc Builder", "Executing RC.EXE with working directory: '%s' ...\n", processLaunchInfo.m_workingDirectory.c_str()); - - AzFramework::ProcessWatcher* watcher = AzFramework::ProcessWatcher::LaunchProcess(processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT); - - if (!watcher) - { - result.m_exitCode = JobExitCode_RCCouldNotBeLaunched; - result.m_crashed = false; - AZ_Error("RC Builder", false, "RC failed to execute\n"); - - return false; - } - - QElapsedTimer ticker; - ticker.start(); - - // it created the process, wait for it to exit: - bool finishedOK = false; - { - CommunicatorTracePrinter tracer(watcher->GetCommunicator(), "RC Builder"); // allow this to go out of scope... - while ((!m_requestedQuit) && (!finishedOK)) - { - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(NativeLegacyRCCompiler::s_maxSleepTime)); - - tracer.Pump(); - - if (ticker.elapsed() > s_jobMaximumWaitTime || (jobCancelListener && jobCancelListener->IsCancelled())) - { - break; - } - - AZ::u32 exitCode = 0; - if (!watcher->IsProcessRunning(&exitCode)) - { - finishedOK = true; // we either cant wait for it, or it finished. - result.m_exitCode = exitCode; - result.m_crashed = (exitCode == 100) || (exitCode == 101); // these indicate fatal errors. - break; - } - } - tracer.Pump(); // empty whats left if possible. - } - if (!finishedOK) - { - if (watcher->IsProcessRunning()) - { - watcher->TerminateProcess(0xFFFFFFFF); - } - - if (!this->m_requestedQuit) - { - if (jobCancelListener == nullptr || !jobCancelListener->IsCancelled()) - { - AZ_Error("RC Builder", false, "RC failed to complete within the maximum allowed time and was terminated. please see %s/rc_log.log for details", result.m_outputDir.toUtf8().data()); - } - else - { - AZ_TracePrintf("RC Builder", "RC was terminated. There was a request to cancel the job.\n"); - result.m_exitCode = JobExitCode_JobCancelled; - } - } - else - { - AZ_Warning("RC Builder", false, "RC terminated because the application is shutting down.\n"); - result.m_exitCode = JobExitCode_JobCancelled; - } - result.m_crashed = false; - } - AZ_TracePrintf("RC Builder", "RC.EXE execution has ended\n"); - - delete watcher; - - return finishedOK; + return false; } QString NativeLegacyRCCompiler::BuildCommand(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest) @@ -438,22 +336,7 @@ namespace AssetProcessor bool InternalRecognizerBasedBuilder::Initialize(const RecognizerConfiguration& recognizerConfig) { InitializeAssetRecognizers(recognizerConfig.GetAssetRecognizerContainer()); - - // Get the engine root since rc.exe will exist there and not in any external project folder - QString systemRoot; - QString rcFullPath; - - // Validate that the engine root contains the necessary rc.exe - if (!FindRC(rcFullPath)) - { - return false; - } - if (!m_rcCompiler->Initialize(systemRoot, rcFullPath)) - { - AssetBuilderSDK::BuilderLog(m_internalRecognizerBuilderUuid, "Unable to find rc.exe from the engine root (%1).", rcFullPath.toUtf8().data()); - return false; - } - return true; + return m_rcCompiler->Initialize(); } diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.h b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.h index 06facc5eba..56c0091aee 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.h +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/RCBuilder.h @@ -31,7 +31,7 @@ namespace AssetProcessor }; virtual ~RCCompiler() = default; - virtual bool Initialize(const QString& systemRoot, const QString& rcExecutableFullPath) = 0; + virtual bool Initialize() = 0; virtual bool Execute(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest, const AssetBuilderSDK::JobCancelListener* jobCancelListener, Result& result) const = 0; virtual void RequestQuit() = 0; @@ -44,7 +44,7 @@ namespace AssetProcessor public: NativeLegacyRCCompiler(); - bool Initialize(const QString& systemRoot, const QString& rcExecutableFullPath) override; + bool Initialize() override; bool Execute(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest, const AssetBuilderSDK::JobCancelListener* jobCancelListener, Result& result) const override; static QString BuildCommand(const QString& inputFile, const QString& watchFolder, const QString& platformIdentifier, const QString& params, const QString& dest); @@ -53,8 +53,6 @@ namespace AssetProcessor static const int s_maxSleepTime; static const unsigned int s_jobMaximumWaitTime; bool m_resourceCompilerInitialized; - QDir m_systemRoot; - QString m_rcExecutableFullPath; volatile bool m_requestedQuit; }; diff --git a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp index 07d0a5b85d..86f02be330 100644 --- a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.cpp @@ -43,19 +43,6 @@ TEST_F(RCBuilderTest, Shutdown_NormalShutdown_Requested) } -TEST_F(RCBuilderTest, Initialize_StandardInitialization_Fail) -{ - MockRCCompiler* mockRC = new MockRCCompiler(); - TestInternalRecognizerBasedBuilder test(mockRC); - - MockRecognizerConfiguration configuration; - - mockRC->SetResultInitialize(false); - bool initialization_result = test.Initialize(configuration); - ASSERT_FALSE(initialization_result); -} - - TEST_F(RCBuilderTest, Initialize_StandardInitializationWithDuplicateAndInvalidRecognizers_Valid) { MockRCCompiler* mockRC = new MockRCCompiler(); diff --git a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h index 1e401aa3f0..379db316f9 100644 --- a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h +++ b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h @@ -34,7 +34,7 @@ public: { } - bool Initialize([[maybe_unused]] const QString& systemRoot, [[maybe_unused]] const QString& rcExecutableFullPath) override + bool Initialize() override { m_initialize++; return m_initializeResult; diff --git a/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp b/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp index e918dbc678..9a93fe9a63 100644 --- a/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp @@ -47,7 +47,7 @@ namespace AssetProcessor { } - bool Initialize([[maybe_unused]] const QString& systemRoot, [[maybe_unused]] const QString& rcExecutableFullPath) override + bool Initialize() override { m_initialize++; return m_initializeResult; diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp index dd92e6bb8b..0ee25195bc 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -151,7 +151,7 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(2); // [LYN-2281] Skinned mesh loading fixes + serializeContext->Class()->Version(3); // [LYN-3349] Rolling back rotation change } } diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp index f56a753fb6..b22f4b5861 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.cpp @@ -69,9 +69,8 @@ namespace AZ if (m_shouldUpdatePassParameters) { - auto* passSystem = AZ::RPI::PassSystemInterface::Get(); - UpdateEyeAdaptationPass(passSystem); - UpdateLuminanceHeatmap(passSystem); + UpdateEyeAdaptationPass(); + UpdateLuminanceHeatmap(); m_shouldUpdatePassParameters = false; } @@ -140,7 +139,8 @@ namespace AZ if (m_heatmapEnabled != value) { m_heatmapEnabled = value; - m_shouldUpdatePassParameters = true; + // Update immediately so that the ExposureControlSettings can just be turned off and killed without having to wait for another Simulate() call + UpdateLuminanceHeatmap(); } } @@ -198,8 +198,10 @@ namespace AZ } } - void ExposureControlSettings::UpdateEyeAdaptationPass(RPI::PassSystemInterface* passSystem) + void ExposureControlSettings::UpdateEyeAdaptationPass() { + auto* passSystem = AZ::RPI::PassSystemInterface::Get(); + // [GFX-TODO][ATOM-13224] Remove UpdateLuminanceHeatmap and UpdateEyeAdaptationPass auto passTemplateName = m_eyeAdaptationPassTemplateNameId; @@ -220,8 +222,10 @@ namespace AZ } } - void ExposureControlSettings::UpdateLuminanceHeatmap(RPI::PassSystemInterface* passSystem) + void ExposureControlSettings::UpdateLuminanceHeatmap() { + auto* passSystem = AZ::RPI::PassSystemInterface::Get(); + // [GFX-TODO][ATOM-13194] Support multiple views for the luminance heatmap // [GFX-TODO][ATOM-13224] Remove UpdateLuminanceHeatmap and UpdateEyeAdaptationPass const RPI::Ptr luminanceHeatmap = passSystem->GetRootPass()->FindPassByNameRecursive(m_luminanceHeatmapNameId); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.h index ebf5a1fe01..566f60dd28 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ExposureControl/ExposureControlSettings.h @@ -84,8 +84,8 @@ namespace AZ void UpdateExposureControlRelatedPassParameters(); - void UpdateLuminanceHeatmap(RPI::PassSystemInterface* passSystem); - void UpdateEyeAdaptationPass(RPI::PassSystemInterface* passSystem); + void UpdateLuminanceHeatmap(); + void UpdateEyeAdaptationPass(); PostProcessSettings* m_parentSettings = nullptr; bool m_shouldUpdatePassParameters = true; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index f31d130ee6..ff2a9cdf98 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -99,6 +99,9 @@ namespace AtomToolsFramework AZStd::optional ViewportScreenToWorldRay( const AzFramework::ScreenPoint& screenPosition) override; + //! Set interface for providing viewport specific settings (e.g. snapping properties). + void SetViewportSettings(AzToolsFramework::ViewportInteraction::ViewportSettings* viewportSettings); + // AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler ... void BeginCursorCapture() override; void EndCursorCapture() override; @@ -156,5 +159,7 @@ namespace AtomToolsFramework bool m_capturingCursor = false; // The last known position of the mouse cursor, if one is available. AZStd::optional m_lastCursorPosition; + // The viewport settings (e.g. grid snapping, grid size) for this viewport. + const AzToolsFramework::ViewportInteraction::ViewportSettings* m_viewportSettings = nullptr; }; } //namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 94038d1977..961de670e8 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -384,27 +384,32 @@ namespace AtomToolsFramework bool RenderViewportWidget::GridSnappingEnabled() { - return false; + return m_viewportSettings ? m_viewportSettings->GridSnappingEnabled() : false; } float RenderViewportWidget::GridSize() { - return 0.0f; + return m_viewportSettings ? m_viewportSettings->GridSize() : 0.0f; } bool RenderViewportWidget::ShowGrid() { - return false; + return m_viewportSettings ? m_viewportSettings->ShowGrid() : false; } bool RenderViewportWidget::AngleSnappingEnabled() { - return false; + return m_viewportSettings ? m_viewportSettings->AngleSnappingEnabled() : false; } float RenderViewportWidget::AngleStep() { - return 0.0f; + return m_viewportSettings ? m_viewportSettings->AngleStep() : 0.0f; + } + + void RenderViewportWidget::SetViewportSettings(AzToolsFramework::ViewportInteraction::ViewportSettings* viewportSettings) + { + m_viewportSettings = viewportSettings; } AzFramework::ScreenPoint RenderViewportWidget::ViewportWorldToScreen(const AZ::Vector3& worldPosition) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/ExposureControlComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/ExposureControlComponentController.cpp index 3b73c65f96..967db514c6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/ExposureControlComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/ExposureControlComponentController.cpp @@ -88,6 +88,9 @@ namespace AZ { ExposureControlRequestBus::Handler::BusDisconnect(m_entityId); + m_configuration.SetHeatmapEnabled(false); + OnConfigChanged(); + if (m_postProcessInterface) { m_postProcessInterface->RemoveExposureControlSettingsInterface(); diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 4056242a47..620995a85b 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARG ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index e564d64fc3..8636715c39 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 939948d501..bdc93d9a0e 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index 25fddb90d0..4f6565edc7 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -13,7 +13,13 @@ if(NOT PAL_TRAIT_BUILD_CPACK_SUPPORTED) return() endif() -set(CPACK_GENERATOR "ZIP") +ly_get_absolute_pal_filename(pal_dir ${CMAKE_SOURCE_DIR}/cmake/Platform/${PAL_HOST_PLATFORM_NAME}) +include(${pal_dir}/Packaging_${PAL_HOST_PLATFORM_NAME_LOWERCASE}.cmake) + +# if we get here and the generator hasn't been set, then a non fatal error occurred disabling packaging support +if(NOT CPACK_GENERATOR) + return() +endif() set(CPACK_PACKAGE_VENDOR "${PROJECT_NAME}") set(CPACK_PACKAGE_VERSION "${LY_VERSION_STRING}") @@ -27,6 +33,8 @@ set(DEFAULT_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt") set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE}) +set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_VERSION}") + # IMPORTANT: required to be included AFTER setting all property overrides include(CPack REQUIRED) diff --git a/cmake/Platform/Windows/PackagingTemplate.wxs.in b/cmake/Platform/Windows/PackagingTemplate.wxs.in new file mode 100644 index 0000000000..3e5db03ec2 --- /dev/null +++ b/cmake/Platform/Windows/PackagingTemplate.wxs.in @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + ProductIcon.ico + + + + + + + + + + + + + + + + + + + diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake new file mode 100644 index 0000000000..8aa6f2386d --- /dev/null +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -0,0 +1,92 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_WIX_PATH "" CACHE PATH "Path to the WiX install path") + +if(LY_WIX_PATH) + file(TO_CMAKE_PATH ${LY_QTIFW_PATH} CPACK_WIX_ROOT) +elseif(DEFINED ENV{WIX}) + file(TO_CMAKE_PATH $ENV{WIX} CPACK_WIX_ROOT) +endif() + +if(CPACK_WIX_ROOT) + if(NOT EXISTS ${CPACK_WIX_ROOT}) + message(FATAL_ERROR "Invalid path supplied for LY_WIX_PATH argument or WIX environment variable") + endif() +else() + # early out as no path to WiX has been supplied effectively disabling support + return() +endif() + +set(CPACK_GENERATOR "WIX") + +# CPack will generate the WiX product/upgrade GUIDs further down the chain if they weren't supplied +# however, they are unique for each run. instead, let's do the auto generation here and add it to +# the cache for run persistence. an additional cache file will be used to store the information on +# the original generation so we still have the ability to detect if they are still being used. +set(_guid_cache_file "${CMAKE_BINARY_DIR}/installer/wix_guid_cache.cmake") +if(NOT EXISTS ${_guid_cache_file}) + set(_wix_guid_namespace "6D43F57A-2917-4AD9-B758-1F13CDB08593") + + # based the ISO-8601 standard (YYYY-MM-DDTHH-mm-ssTZD) e.g., 20210506145533 + string(TIMESTAMP _guid_gen_timestamp "%Y%m%d%H%M%S") + + file(WRITE ${_guid_cache_file} "set(_wix_guid_gen_timestamp ${_guid_gen_timestamp})\n") + + string(UUID _default_product_guid + NAMESPACE ${_wix_guid_namespace} + NAME "ProductID_${_guid_gen_timestamp}" + TYPE SHA1 + UPPER + ) + file(APPEND ${_guid_cache_file} "set(_wix_default_product_guid ${_default_product_guid})\n") + + string(UUID _default_upgrade_guid + NAMESPACE ${_wix_guid_namespace} + NAME "UpgradeCode_${_guid_gen_timestamp}" + TYPE SHA1 + UPPER + ) + file(APPEND ${_guid_cache_file} "set(_wix_default_upgrade_guid ${_default_upgrade_guid})\n") +endif() +include(${_guid_cache_file}) + +set(LY_WIX_PRODUCT_GUID "${_wix_default_product_guid}" CACHE STRING "GUID for the Product ID field. Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") +set(LY_WIX_UPGRADE_GUID "${_wix_default_upgrade_guid}" CACHE STRING "GUID for the Upgrade Code field. Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") + +set(_uses_default_product_guid FALSE) +if(NOT LY_WIX_PRODUCT_GUID OR LY_WIX_PRODUCT_GUID STREQUAL ${_wix_default_product_guid}) + set(_uses_default_product_guid TRUE) + set(LY_WIX_PRODUCT_GUID ${_wix_default_product_guid}) +endif() + +set(_uses_default_upgrade_guid FALSE) +if(NOT LY_WIX_UPGRADE_GUID OR LY_WIX_UPGRADE_GUID STREQUAL ${_wix_default_upgrade_guid}) + set(_uses_default_upgrade_guid TRUE) + set(LY_WIX_UPGRADE_GUID ${_wix_default_upgrade_guid}) +endif() + +if(_uses_default_product_guid OR _uses_default_upgrade_guid) + message(STATUS "One or both WiX GUIDs were auto generated. It is recommended you supply your own GUIDs through LY_WIX_PRODUCT_GUID and LY_WIX_UPGRADE_GUID.") + + if(_uses_default_product_guid) + message(STATUS "-> Default LY_WIX_PRODUCT_GUID = ${LY_WIX_PRODUCT_GUID}") + endif() + + if(_uses_default_upgrade_guid) + message(STATUS "-> Default LY_WIX_UPGRADE_GUID = ${LY_WIX_UPGRADE_GUID}") + endif() +endif() + +set(CPACK_WIX_PRODUCT_GUID ${LY_WIX_PRODUCT_GUID}) +set(CPACK_WIX_UPGRADE_GUID ${LY_WIX_UPGRADE_GUID}) + +set(CPACK_WIX_TEMPLATE "${CMAKE_SOURCE_DIR}/cmake/Platform/Windows/PackagingTemplate.wxs.in") diff --git a/cmake/Platform/Windows/platform_windows_files.cmake b/cmake/Platform/Windows/platform_windows_files.cmake index bf9cb05d17..2fc869b43e 100644 --- a/cmake/Platform/Windows/platform_windows_files.cmake +++ b/cmake/Platform/Windows/platform_windows_files.cmake @@ -23,4 +23,6 @@ set(FILES PAL_windows.cmake PALDetection_windows.cmake Install_windows.cmake + Packaging_windows.cmake + PackagingTemplate.wxs.in )