Merge branch 'main' into non-uniform-scale-ux

This commit is contained in:
greerdv
2021-05-07 19:55:26 +01:00
41 changed files with 1422 additions and 216 deletions
+1 -1
View File
@@ -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 <AzFramework/Utils/SystemUtilsApple.h>
#endif
#include "StringUtils.h"
+1 -1
View File
@@ -51,7 +51,7 @@
#define LOG_BACKUP_PATH "@log@/LogBackups"
#if defined(IOS)
#include "SystemUtilsApple.h"
#include <AzFramework/Utils/SystemUtilsApple.h>
#endif
//////////////////////////////////////////////////////////////////////
@@ -15,7 +15,7 @@
#include <AzCore/std/string/string.h>
#include "MobileDetectSpec.h"
#include "SystemUtilsApple.h"
#include <AzFramework/Utils/SystemUtilsApple.h>
namespace MobileSysInspect
{
@@ -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
)
@@ -13,8 +13,6 @@ set(FILES
../../MobileDetectSpec_Ios.cpp
../../MobileDetectSpec.cpp
../../MobileDetectSpec.h
../../SystemUtilsApple.h
../../SystemUtilsApple.mm
)
+1 -1
View File
@@ -66,7 +66,7 @@ __pragma(comment(lib, "Winmm.lib"))
#endif
#if defined(APPLE)
#include "SystemUtilsApple.h"
#include <AzFramework/Utils/SystemUtilsApple.h>
#endif
@@ -9,7 +9,3 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(FILES
SystemUtilsApple.h
SystemUtilsApple.mm
)
@@ -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 <AzCore/Math/MathMatrixSerializer.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/Json/StackedString.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/string/osstring.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ::JsonMathMatrixSerializerInternal
{
template<typename MatrixType, size_t RowCount, size_t ColumnCount>
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<float>());
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<float>(), 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<float>());
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<float>(), 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<AZStd::string_view, 6> 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<typename MatrixType>
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>(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<typename MatrixType, size_t RowCount, size_t ColumnCount>
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<MatrixType>() == outputValueTypeId,
"Unable to deserialize Matrix%zux%zu to json because the provided type is %s",
RowCount, ColumnCount, outputValueTypeId.ToString<OSString>().c_str());
AZ_UNUSED(outputValueTypeId);
MatrixType* matrix = reinterpret_cast<MatrixType*>(outputValue);
AZ_Assert(matrix, "Output value for JsonMatrix%zux%zuSerializer can't be null.", RowCount, ColumnCount);
switch (inputValue.GetType())
{
case rapidjson::kArrayType:
return LoadArray<MatrixType, RowCount, ColumnCount>(*matrix, inputValue, context);
case rapidjson::kObjectType:
return LoadObject<MatrixType>(*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<typename MatrixType>
AZ::Quaternion CreateQuaternion(const MatrixType& matrix);
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix3x3>(const AZ::Matrix3x3& matrix)
{
return Quaternion::CreateFromMatrix3x3(matrix);
}
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix3x4>(const AZ::Matrix3x4& matrix)
{
return Quaternion::CreateFromMatrix3x4(matrix);
}
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix4x4>(const AZ::Matrix4x4& matrix)
{
return Quaternion::CreateFromMatrix4x4(matrix);
}
template<typename MatrixType>
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<const MatrixType*>(inputValue);
AZ_Assert(matrix, "Input value for JsonMatrixSerializer can't be null.");
const MatrixType* defaultMatrix = reinterpret_cast<const MatrixType*>(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<typename MatrixType>
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<const MatrixType*>(inputValue);
AZ_Assert(matrix, "Input value for JsonMatrixSerializer can't be null.");
const MatrixType* defaultMatrix = reinterpret_cast<const MatrixType*>(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<Matrix3x3, 3, 3>(
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<Matrix3x3>(
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<Matrix3x4, 3, 4>(
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<Matrix3x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation<Matrix3x4>(
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<Matrix4x4, 4, 4>(
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<Matrix4x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation<Matrix4x4>(
outputValue,
inputValue,
defaultValue,
valueTypeId,
context);
result.GetResultCode().Combine(resultTranslation);
return result;
}
}
@@ -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 <AzCore/Serialization/Json/BaseJsonSerializer.h>
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;
};
}
@@ -24,6 +24,7 @@
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector4.h>
#include <AzCore/Math/MathMatrixSerializer.h>
#include <AzCore/Math/MathVectorSerializer.h>
#include <AzCore/Math/Color.h>
#include <AzCore/Math/ColorSerializer.h>
@@ -366,6 +367,9 @@ namespace AZ
{
context.Serializer<JsonColorSerializer>()->HandlesType<Color>();
context.Serializer<JsonUuidSerializer>()->HandlesType<Uuid>();
context.Serializer<JsonMatrix3x3Serializer>()->HandlesType<Matrix3x3>();
context.Serializer<JsonMatrix3x4Serializer>()->HandlesType<Matrix3x4>();
context.Serializer<JsonMatrix4x4Serializer>()->HandlesType<Matrix4x4>();
context.Serializer<JsonVector2Serializer>()->HandlesType<Vector2>();
context.Serializer<JsonVector3Serializer>()->HandlesType<Vector3>();
context.Serializer<JsonVector4Serializer>()->HandlesType<Vector4>();
@@ -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
@@ -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 <AzCore/Casting/numeric_cast.h>
#include <AzCore/Math/MathMatrixSerializer.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Math/Random.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/Serialization/Json/DoubleSerializer.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
namespace JsonSerializationTests
{
namespace DataHelper
{
// Build Matrix
template <typename MatrixType>
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 <typename MatrixType>
MatrixType BuildMatrix(const AZ::Vector3& angles, float scale, const AZ::Vector3& translation)
{
auto matrix = BuildMatrixRotationWithSale<MatrixType>(angles, scale);
matrix.SetTranslation(translation);
return matrix;
}
template <>
AZ::Matrix3x3 BuildMatrix(const AZ::Vector3& angles, float scale, const AZ::Vector3&)
{
return BuildMatrixRotationWithSale<AZ::Matrix3x3>(angles, scale);
}
// Arbitrary Matrix
template <typename MatrixType>
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 <typename MatrixType>
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 <typename MatrixType>
MatrixType CreateArbitraryMatrix(size_t seed);
template <>
AZ::Matrix3x3 CreateArbitraryMatrix(size_t seed)
{
AZ::SimpleLcgRandom random(seed);
return CreateArbitraryMatrixRotationAndSale<AZ::Matrix3x3>(random);
}
template <>
AZ::Matrix3x4 CreateArbitraryMatrix(size_t seed)
{
AZ::SimpleLcgRandom random(seed);
auto matrix = CreateArbitraryMatrixRotationAndSale<AZ::Matrix3x4>(random);
AssignArbitrarySetTranslation<AZ::Matrix3x4>(matrix, random);
return matrix;
}
template <>
AZ::Matrix4x4 CreateArbitraryMatrix(size_t seed)
{
AZ::SimpleLcgRandom random(seed);
auto matrix = CreateArbitraryMatrixRotationAndSale<AZ::Matrix4x4>(random);
AssignArbitrarySetTranslation<AZ::Matrix4x4>(matrix, random);
return matrix;
}
// CreateQuaternion
template<typename MatrixType>
AZ::Quaternion CreateQuaternion(const MatrixType& matrix);
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix3x3>(const AZ::Matrix3x3& matrix)
{
return AZ::Quaternion::CreateFromMatrix3x3(matrix);
}
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix3x4>(const AZ::Matrix3x4& matrix)
{
return AZ::Quaternion::CreateFromMatrix3x4(matrix);
}
template<>
AZ::Quaternion CreateQuaternion<AZ::Matrix4x4>(const AZ::Matrix4x4& matrix)
{
return AZ::Quaternion::CreateFromMatrix4x4(matrix);
}
template<typename MatrixType>
void AddRotation(rapidjson::Value& value, const MatrixType& matrix, rapidjson::Document::AllocatorType& allocator)
{
AZ::Quaternion rotation = CreateQuaternion<MatrixType>(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 <typename MatrixType>
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<typename MatrixType, size_t RowCount, size_t ColumnCount, typename Serializer>
class MathMatrixSerializerTestDescription :
public JsonSerializerConformityTestDescriptor<MatrixType>
{
public:
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
{
return AZStd::make_shared<Serializer>();
}
AZStd::shared_ptr<MatrixType> CreateDefaultInstance() override
{
return AZStd::make_shared<MatrixType>(MatrixType::CreateIdentity());
}
AZStd::shared_ptr<MatrixType> 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<MatrixType>(angles, scale, translation);
return AZStd::make_shared<MatrixType>(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<AZ::Matrix3x3, 3, 3, AZ::JsonMatrix3x3Serializer>,
MathMatrixSerializerTestDescription<AZ::Matrix3x4, 3, 4, AZ::JsonMatrix3x4Serializer>,
MathMatrixSerializerTestDescription<AZ::Matrix4x4, 4, 4, AZ::JsonMatrix4x4Serializer>
>;
INSTANTIATE_TYPED_TEST_CASE_P(JsonMathMatrixSerializer, JsonSerializerConformityTests, MathMatrixSerializerConformityTestTypes);
template<typename T>
class JsonMathMatrixSerializerTests
: public BaseJsonSerializerFixture
{
public:
using Descriptor = T;
void SetUp() override
{
BaseJsonSerializerFixture::SetUp();
m_serializer = AZStd::make_unique<typename T::Serializer>();
}
void TearDown() override
{
m_serializer.reset();
BaseJsonSerializerFixture::TearDown();
}
protected:
AZStd::unique_ptr<typename T::Serializer> 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<TypeParam>::Descriptor::ElementCount; ++i)
{
arrayValue.PushBack(static_cast<float>(i + 1), this->m_jsonDocument->GetAllocator());
}
auto output = JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType::CreateZero();
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType>(),
*this->m_jsonDocument,
*this->m_jsonDeserializationContext);
ASSERT_EQ(Outcomes::Success, result.GetOutcome());
for (int r = 0; r < JsonMathMatrixSerializerTests<TypeParam>::Descriptor::RowCount; ++r)
{
for (int c = 0; c < JsonMathMatrixSerializerTests<TypeParam>::Descriptor::ColumnCount; ++c)
{
auto testValue = static_cast<float>((r * JsonMathMatrixSerializerTests<TypeParam>::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<TypeParam>::Descriptor::ElementCount; ++i)
{
if (i == 1)
{
arrayValue.PushBack(rapidjson::StringRef("Invalid"), this->m_jsonDocument->GetAllocator());
}
else
{
arrayValue.PushBack(static_cast<float>(i + 1), this->m_jsonDocument->GetAllocator());
}
}
auto output = JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType::CreateZero();
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType>(),
*this->m_jsonDocument,
*this->m_jsonDeserializationContext);
EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome());
for (int r = 0; r < JsonMathMatrixSerializerTests<TypeParam>::Descriptor::RowCount; ++r)
{
for (int c = 0; c < JsonMathMatrixSerializerTests<TypeParam>::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<AZ::JsonFloatSerializer>()->template HandlesType<float>();
this->m_jsonRegistrationContext->DisableRemoveReflection();
rapidjson::Value& arrayValue = this->m_jsonDocument->SetArray();
for (size_t i = 0; i < JsonMathMatrixSerializerTests<TypeParam>::Descriptor::ElementCount + 1; ++i)
{
arrayValue.PushBack(static_cast<float>(i + 1), this->m_jsonDocument->GetAllocator());
}
typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType output;
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType>(),
*this->m_jsonDocument,
*this->m_jsonDeserializationContext);
EXPECT_EQ(Outcomes::Catastrophic, result.GetOutcome());
this->m_jsonRegistrationContext->template Serializer<AZ::JsonFloatSerializer>()->template HandlesType<float>();
}
// Load object tests
TYPED_TEST(JsonMathMatrixSerializerTests, Load_ValidObjectLowerCase_ReturnsSuccessAndLoadsMatrix)
{
using namespace AZ::JsonSerializationResult;
rapidjson::Value& objectValue = this->m_jsonDocument->SetObject();
auto input = JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType::CreateIdentity();
DataHelper::AddData(objectValue, input, this->m_jsonDocument->GetAllocator());
auto output = JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType::CreateZero();
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::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<TypeParam>::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<TypeParam>::Descriptor::MatrixType::CreateZero();
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::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<TypeParam>::Descriptor::MatrixType::CreateIdentity();
rapidjson::Value& objectInput = this->m_jsonDocument->SetObject();
this->m_serializer->Store(
objectInput,
&defaultValue,
&defaultValue,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType>(),
*this->m_jsonSerializationContext);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
objectInput.Accept(writer);
auto output = defaultValue;
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::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<TypeParam>::Descriptor::MatrixType::CreateIdentity();
auto input = JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType::CreateZero();
rapidjson::Value& objectInput = this->m_jsonDocument->SetObject();
this->m_serializer->Store(
objectInput,
&input,
&defaultValue,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::Descriptor::MatrixType>(),
*this->m_jsonSerializationContext);
auto output = defaultValue;
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename JsonMathMatrixSerializerTests<TypeParam>::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<TypeParam>::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<typename Descriptor::MatrixType>(),
*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<TypeParam>::Descriptor;
auto defaultValue = Descriptor::MatrixType::CreateIdentity();
size_t elementCount = Descriptor::RowCount * Descriptor::ColumnCount;
auto input = DataHelper::CreateArbitraryMatrix<typename Descriptor::MatrixType>(elementCount);
rapidjson::Value& objectInput = this->m_jsonDocument->SetObject();
this->m_serializer->Store(
objectInput,
&input,
&defaultValue,
azrtti_typeid<typename Descriptor::MatrixType>(),
*this->m_jsonSerializationContext);
auto output = defaultValue;
ResultCode result = this->m_serializer->Load(
&output,
azrtti_typeid<typename Descriptor::MatrixType>(),
*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
@@ -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
@@ -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"
@@ -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
)
@@ -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"
@@ -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
)
@@ -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<ViewportInteractionRequests, ViewportEBusTraits>;
@@ -19,7 +19,7 @@
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
#include <CrySystem/SystemUtilsApple.h>
#include <AzFramework/Utils/SystemUtilsApple.h>
#import <UIKit/UIKit.h>
+34 -26
View File
@@ -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<SandboxEditor::LegacyViewportCameraController>());
}
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 <moc_EditorViewportWidget.cpp>
+19 -6
View File
@@ -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
};
@@ -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();
}
@@ -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;
};
@@ -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();
@@ -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;
@@ -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;
@@ -151,7 +151,7 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(2); // [LYN-2281] Skinned mesh loading fixes
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(3); // [LYN-3349] Rolling back rotation change
}
}
@@ -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<RPI::Pass> luminanceHeatmap = passSystem->GetRootPass()->FindPassByNameRecursive(m_luminanceHeatmapNameId);
@@ -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;
@@ -99,6 +99,9 @@ namespace AtomToolsFramework
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> 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<QPoint> m_lastCursorPosition;
// The viewport settings (e.g. grid snapping, grid size) for this viewport.
const AzToolsFramework::ViewportInteraction::ViewportSettings* m_viewportSettings = nullptr;
};
} //namespace AtomToolsFramework
@@ -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)
@@ -88,6 +88,9 @@ namespace AZ
{
ExposureControlRequestBus::Handler::BusDisconnect(m_entityId);
m_configuration.SetHeatmapEnabled(false);
OnConfigChanged();
if (m_postProcessInterface)
{
m_postProcessInterface->RemoveExposureControlSettingsInterface();
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
@@ -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)
+9 -1
View File
@@ -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)
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<?include "cpack_variables.wxi"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" @CPACK_WIX_CUSTOM_XMLNS_EXPANDED@
RequiredVersion="3.6.3303.0">
<Product Id="$(var.CPACK_WIX_PRODUCT_GUID)"
Name="$(var.CPACK_PACKAGE_NAME)"
Language="1033"
Version="$(var.CPACK_PACKAGE_VERSION)"
Manufacturer="$(var.CPACK_PACKAGE_VENDOR)"
UpgradeCode="$(var.CPACK_WIX_UPGRADE_GUID)">
<Package InstallerVersion="301" Compressed="yes"/>
<!-- auto distribute the installable files across N cab files and embed them in the final MSI -->
<MediaTemplate EmbedCab="yes"/>
<MajorUpgrade
Schedule="afterInstallInitialize"
AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."/>
<WixVariable Id="WixUILicenseRtf" Value="$(var.CPACK_WIX_LICENSE_RTF)"/>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALL_ROOT"/>
<?ifdef CPACK_WIX_PRODUCT_ICON?>
<Property Id="ARPPRODUCTICON">ProductIcon.ico</Property>
<Icon Id="ProductIcon.ico" SourceFile="$(var.CPACK_WIX_PRODUCT_ICON)"/>
<?endif?>
<?ifdef CPACK_WIX_UI_BANNER?>
<WixVariable Id="WixUIBannerBmp" Value="$(var.CPACK_WIX_UI_BANNER)"/>
<?endif?>
<?ifdef CPACK_WIX_UI_DIALOG?>
<WixVariable Id="WixUIDialogBmp" Value="$(var.CPACK_WIX_UI_DIALOG)"/>
<?endif?>
<FeatureRef Id="ProductFeature"/>
<UIRef Id="$(var.CPACK_WIX_UI_REF)" />
<?include "properties.wxi"?>
<?include "product_fragment.wxi"?>
</Product>
</Wix>
@@ -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")
@@ -23,4 +23,6 @@ set(FILES
PAL_windows.cmake
PALDetection_windows.cmake
Install_windows.cmake
Packaging_windows.cmake
PackagingTemplate.wxs.in
)