Merge branch 'main' into ly-as-sdk/LYN-2948

# Conflicts:
#	Code/Tools/ProjectManager/CMakeLists.txt
#	Code/Tools/ProjectManager/Source/GemCatalog.cpp
#	Code/Tools/ProjectManager/Source/GemCatalog.h
#	Code/Tools/ProjectManager/Source/GemCatalog.ui
#	Code/Tools/ProjectManager/Source/GemCatalog/GemCatalog.h
#	Code/Tools/ProjectManager/Source/ScreenFactory.cpp
#	Code/Tools/ProjectManager/project_manager_files.cmake
#	Code/Tools/ProjectManager/source/Qt/GemCatalog.h
This commit is contained in:
pappeste
2021-05-07 11:05:20 -07:00
451 changed files with 18332 additions and 1996 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>();
@@ -74,7 +74,7 @@ namespace AZ
"Unable to retrieve the correct container information for AZStd::array instance.");
}
Flags flags = Flags::None;
ContinuationFlags flags = ContinuationFlags::None;
Uuid elementTypeId = Uuid::CreateNull();
auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement)
{
@@ -82,7 +82,7 @@ namespace AZ
elementTypeId = genericClassElement->m_typeId;
if (genericClassElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
flags = Flags::ResolvePointer;
flags = ContinuationFlags::ResolvePointer;
}
return false;
};
@@ -161,7 +161,7 @@ namespace AZ
"Not enough entries in JSON array to load an AZStd::array from.");
}
Flags flags = Flags::None;
ContinuationFlags flags = ContinuationFlags::None;
Uuid elementTypeId = Uuid::CreateNull();
auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement)
{
@@ -169,7 +169,7 @@ namespace AZ
elementTypeId = genericClassElement->m_typeId;
if (genericClassElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
flags = Flags::ResolvePointer;
flags = ContinuationFlags::ResolvePointer;
}
return false;
};
@@ -208,22 +208,28 @@ namespace AZ
// BaseJsonSerializer
//
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading(void* object, const Uuid& typeId, const rapidjson::Value& value,
JsonDeserializerContext& context, Flags flags)
BaseJsonSerializer::OperationFlags BaseJsonSerializer::GetOperationsFlags() const
{
return flags & Flags::ResolvePointer ?
JsonDeserializer::LoadToPointer(object, typeId, value, context) :
JsonDeserializer::Load(object, typeId, value, context);
return OperationFlags::None;
}
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring(rapidjson::Value& output, const void* object,
const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, Flags flags)
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading(
void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags)
{
return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer
? JsonDeserializer::LoadToPointer(object, typeId, value, context)
: JsonDeserializer::Load(object, typeId, value, context);
}
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring(
rapidjson::Value& output, const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context,
ContinuationFlags flags)
{
using namespace JsonSerializationResult;
if (flags & Flags::ReplaceDefault && !context.ShouldKeepDefaults())
if ((flags & ContinuationFlags::ReplaceDefault) == ContinuationFlags::ReplaceDefault && !context.ShouldKeepDefaults())
{
if (flags & Flags::ResolvePointer)
if ((flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer)
{
return JsonSerializer::StoreFromPointer(output, object, nullptr, typeId, context);
}
@@ -248,7 +254,7 @@ namespace AZ
}
}
return flags & Flags::ResolvePointer ?
return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ?
JsonSerializer::StoreFromPointer(output, object, defaultObject, typeId, context) :
JsonSerializer::Store(output, object, defaultObject, typeId, context);
}
@@ -265,8 +271,9 @@ namespace AZ
return JsonSerializer::StoreTypeName(output, typeId, context);
}
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoadingFromJsonObjectField(void* object, const Uuid& typeId, const rapidjson::Value& value,
rapidjson::Value::StringRefType memberName, JsonDeserializerContext& context, Flags flags)
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoadingFromJsonObjectField(
void* object, const Uuid& typeId, const rapidjson::Value& value, rapidjson::Value::StringRefType memberName,
JsonDeserializerContext& context, ContinuationFlags flags)
{
using namespace JsonSerializationResult;
@@ -291,7 +298,7 @@ namespace AZ
JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoringToJsonObjectField(rapidjson::Value& output,
rapidjson::Value::StringRefType newMemberName, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context, Flags flags)
const Uuid& typeId, JsonSerializerContext& context, ContinuationFlags flags)
{
using namespace JsonSerializationResult;
@@ -161,13 +161,19 @@ namespace AZ
public:
AZ_RTTI(BaseJsonSerializer, "{7291FFDC-D339-40B5-BB26-EA067A327B21}");
enum Flags
enum class ContinuationFlags
{
None = 0, //! No extra flags.
None = 0, //! No extra flags.
ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance.
ReplaceDefault = 1 << 1 //! The default value provided for storing will be replaced with a newly created one.
};
enum class OperationFlags
{
None = 0, //! No flags that control how the custom json serializer is used.
ManualDefault = 1 << 0 //! Even if an (explicit) default is found the custom json serializer will still be called.
};
virtual ~BaseJsonSerializer() = default;
//! Transforms the data from the rapidjson Value to outputValue, if the conversion is possible and supported.
@@ -180,6 +186,9 @@ namespace AZ
virtual JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) = 0;
//! Returns the operation flags which tells the Json Serialization how this custom json serializer can be used.
virtual OperationFlags GetOperationsFlags() const;
protected:
//! Continues loading of a (sub)value. Use this function to load member variables for instance. This is more optimal than
//! directly calling the json serialization.
@@ -187,8 +196,9 @@ namespace AZ
//! @param typeId Type id of the object passed in.
//! @param value The value in the JSON document where the deserializer will start reading data from.
//! @param context The context used during deserialization. Use the value passed in from Load.
JsonSerializationResult::ResultCode ContinueLoading(void* object, const Uuid& typeId, const rapidjson::Value& value,
JsonDeserializerContext& context, Flags flags = Flags::None);
JsonSerializationResult::ResultCode ContinueLoading(
void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context,
ContinuationFlags flags = ContinuationFlags::None);
//! Continues storing of a (sub)value. Use this function to store member variables for instance. This is more optimal than
//! directly calling the json serialization.
@@ -200,8 +210,9 @@ namespace AZ
//! the settings.
//! @param typeId The type id of the object and default object.
//! @param context The context used during serialization. Use the value passed in from Store.
JsonSerializationResult::ResultCode ContinueStoring(rapidjson::Value& output, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context, Flags flags = Flags::None);
JsonSerializationResult::ResultCode ContinueStoring(
rapidjson::Value& output, const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context,
ContinuationFlags flags = ContinuationFlags::None);
//! Retrieves the type id from a json object or json string.
//! @param typeId The retrieved type id.
@@ -222,12 +233,14 @@ namespace AZ
const Uuid& typeId, JsonSerializerContext& context);
//! Helper function similar to ContinueLoading, but loads the data as a member of 'value' rather than 'value' itself, if it exists.
JsonSerializationResult::ResultCode ContinueLoadingFromJsonObjectField(void* object, const Uuid& typeId, const rapidjson::Value& value,
rapidjson::Value::StringRefType memberName, JsonDeserializerContext& context, Flags flags = Flags::None);
JsonSerializationResult::ResultCode ContinueLoadingFromJsonObjectField(
void* object, const Uuid& typeId, const rapidjson::Value& value, rapidjson::Value::StringRefType memberName,
JsonDeserializerContext& context, ContinuationFlags flags = ContinuationFlags::None);
//! Helper function similar to ContinueStoring, but stores the data as a member of 'output' rather than overwriting 'output'.
JsonSerializationResult::ResultCode ContinueStoringToJsonObjectField(rapidjson::Value& output, rapidjson::Value::StringRefType newMemberName,
const void* object, const void* defaultObject, const Uuid& typeId, JsonSerializerContext& context, Flags flags = Flags::None);
JsonSerializationResult::ResultCode ContinueStoringToJsonObjectField(
rapidjson::Value& output, rapidjson::Value::StringRefType newMemberName, const void* object, const void* defaultObject,
const Uuid& typeId, JsonSerializerContext& context, ContinuationFlags flags = ContinuationFlags::None);
//! Checks if a value is an explicit default. This useful for containers where not storing anything as a default would mean
//! a slot wouldn't be used so something has to be added to represent the fully default target.
@@ -238,6 +251,7 @@ namespace AZ
rapidjson::Value GetExplicitDefault();
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::Flags)
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::ContinuationFlags)
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::BaseJsonSerializer::OperationFlags)
} // namespace AZ
@@ -75,9 +75,10 @@ namespace AZ
auto elementCallback = [this, &array, &retVal, &index, &context]
(void* elementPtr, const Uuid& elementId, const SerializeContext::ClassData*, const SerializeContext::ClassElement* classElement)
{
Flags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ?
Flags::ResolvePointer : Flags::None;
flags |= Flags::ReplaceDefault;
ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
? ContinuationFlags::ResolvePointer
: ContinuationFlags::None;
flags |= ContinuationFlags::ReplaceDefault;
ScopedContextPath subPath(context, index);
index++;
@@ -161,8 +162,9 @@ namespace AZ
container->EnumTypes(typeEnumCallback);
AZ_Assert(classElement, "No class element found for the type in the basic container.");
Flags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ?
Flags::ResolvePointer : Flags::None;
ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
? ContinuationFlags::ResolvePointer
: ContinuationFlags::None;
const size_t capacity = container->IsFixedCapacity() ? container->Capacity(outputValue) : std::numeric_limits<size_t>::max();
@@ -22,6 +22,19 @@
namespace AZ
{
JsonSerializationResult::ResultCode JsonDeserializer::DeserializerDefaultCheck(BaseJsonSerializer* serializer, void* object,
const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context)
{
using namespace AZ::JsonSerializationResult;
bool isExplicitDefault = IsExplicitDefault(value);
bool manuallyDefaults = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::ManualDefault) ==
BaseJsonSerializer::OperationFlags::ManualDefault;
return !isExplicitDefault || (isExplicitDefault && manuallyDefaults)
? serializer->Load(object, typeId, value, context)
: context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default.");
}
JsonSerializationResult::ResultCode JsonDeserializer::Load(void* object, const Uuid& typeId, const rapidjson::Value& value,
JsonDeserializerContext& context)
{
@@ -33,17 +46,12 @@ namespace AZ
"Target object for Json Serialization is pointing to nothing during loading.");
}
if (IsExplicitDefault(value))
{
return context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default.");
}
BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId);
if (serializer)
{
return serializer->Load(object, typeId, value, context);
return DeserializerDefaultCheck(serializer, object, typeId, value, context);
}
const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId);
if (!classData)
{
@@ -56,9 +64,14 @@ namespace AZ
serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId());
if (serializer)
{
return serializer->Load(object, typeId, value, context);
return DeserializerDefaultCheck(serializer, object, typeId, value, context);
}
}
if (IsExplicitDefault(value))
{
return context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default.");
}
if (classData->m_azRtti && (classData->m_azRtti->GetTypeTraits() & AZ::TypeTraits::is_enum) == AZ::TypeTraits::is_enum)
{
@@ -113,5 +113,13 @@ namespace AZ
//! Checks if a value is an explicit default. This means the value is an object with no members.
static bool IsExplicitDefault(const rapidjson::Value& value);
private:
static JsonSerializationResult::ResultCode DeserializerDefaultCheck(
BaseJsonSerializer* serializer,
void* object,
const Uuid& typeId,
const rapidjson::Value& value,
JsonDeserializerContext& context);
};
} // namespace AZ
@@ -215,10 +215,10 @@ namespace AZ
// Load key
void* keyAddress = pairContainer->GetElementByIndex(address, pairElement, 0);
AZ_Assert(keyAddress, "Element reserved for associative container, but unable to retrieve address of the key.");
Flags keyLoadFlags = Flags::None;
ContinuationFlags keyLoadFlags = ContinuationFlags::None;
if (keyElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
keyLoadFlags = Flags::ResolvePointer;
keyLoadFlags = ContinuationFlags::ResolvePointer;
*reinterpret_cast<void**>(keyAddress) = nullptr;
}
JSR::ResultCode keyResult = ContinueLoading(keyAddress, keyElement->m_typeId, key, context, keyLoadFlags);
@@ -231,10 +231,10 @@ namespace AZ
// Load value
void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value.");
Flags valueLoadFlags = Flags::None;
ContinuationFlags valueLoadFlags = ContinuationFlags::None;
if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
{
valueLoadFlags = Flags::ResolvePointer;
valueLoadFlags = ContinuationFlags::ResolvePointer;
*reinterpret_cast<void**>(valueAddress) = nullptr;
}
JSR::ResultCode valueResult = ContinueLoading(valueAddress, valueElement->m_typeId, value, context, valueLoadFlags);
@@ -82,7 +82,7 @@ namespace AZ
{
// If the target type is the same as the type already stored in the smart pointer than no new
// instance is created and the existing instance will be updated with the data in the json document.
result = ContinueLoading(instance, elementClassId, inputValue, context, Flags::ResolvePointer);
result = ContinueLoading(instance, elementClassId, inputValue, context, ContinuationFlags::ResolvePointer);
return false;
}
}
@@ -93,7 +93,7 @@ namespace AZ
// the wrong address. In these cases explicitly reset the smart pointer. This will erase the existing
// data but that's fine as it's not being used.
void* element = nullptr;
result = ContinueLoading(&element, elementClassId, inputValue, context, Flags::ResolvePointer);
result = ContinueLoading(&element, elementClassId, inputValue, context, ContinuationFlags::ResolvePointer);
if (result.GetProcessing() != JSR::Processing::Halted && result.GetProcessing() != JSR::Processing::Altered)
{
void* elementPtr = container->ReserveElement(instance, nullptr);
@@ -155,8 +155,14 @@ namespace AZ
container->EnumElements(const_cast<void*>(defaultValue), defaultInputCallback);
}
JSR::ResultCode result = ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, Flags::ResolvePointer);
JSR::ResultCode result =
ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, ContinuationFlags::ResolvePointer);
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ?
"Successfully processed smart pointer." : "A problem occurred while processing a smart pointer.");
}
BaseJsonSerializer::OperationFlags JsonSmartPointerSerializer::GetOperationsFlags() const
{
return OperationFlags::ManualDefault;
}
} // namespace AZ
@@ -28,5 +28,7 @@ namespace AZ
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context) override;
OperationFlags GetOperationsFlags() const override;
};
} // namespace AZ
@@ -99,8 +99,9 @@ namespace AZ
ScopedContextPath subPath(context, i);
Flags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ?
Flags::ResolvePointer : Flags::None;
ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
? ContinuationFlags::ResolvePointer
: ContinuationFlags::None;
JSR::ResultCode result = ContinueStoring(elementValues[i], elementAddress, defaultElementAddress,
classElements[i]->m_typeId, context, flags);
@@ -179,8 +180,9 @@ namespace AZ
void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i);
AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i);
Flags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ?
Flags::ResolvePointer : Flags::None;
ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER
? ContinuationFlags::ResolvePointer
: ContinuationFlags::None;
while (arrayIndex < inputValue.Size())
{
@@ -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
@@ -104,6 +104,11 @@ namespace JsonSerializationTests
AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
}
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<Asset>();
}
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
{
return AZStd::make_shared<AZ::Data::AssetJsonSerializer>();
@@ -119,7 +119,8 @@ namespace JsonSerializationTests
int value = 0;
int* ptrValue = &value;
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
ResultCode result =
ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, ptrValue);
@@ -134,7 +135,8 @@ namespace JsonSerializationTests
json.Set(42);
int* ptrValue = nullptr;
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
ResultCode result =
ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, ptrValue);
@@ -150,7 +152,8 @@ namespace JsonSerializationTests
rapidjson::Value json(rapidjson::kObjectType);
int* ptrValue = nullptr;
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
ResultCode result =
ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_NE(nullptr, ptrValue);
@@ -165,7 +168,8 @@ namespace JsonSerializationTests
rapidjson::Value json(rapidjson::kNullType);
int* ptrValue = reinterpret_cast<int*>(azmalloc(sizeof(int), alignof(int), AZ::SystemAllocator));
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
ResultCode result =
ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
ASSERT_EQ(nullptr, ptrValue);
@@ -194,8 +198,8 @@ namespace JsonSerializationTests
int value = 42;
int* ptrValue = &value;
ResultCode result = ContinueStoring(*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext,
Flags::ResolvePointer);
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("42");
@@ -210,8 +214,9 @@ namespace JsonSerializationTests
int value2 = 42;
int* defaultPtrValue = &value2;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext,
ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("{}");
@@ -224,7 +229,7 @@ namespace JsonSerializationTests
int* ptrValue = nullptr;
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
@@ -238,8 +243,9 @@ namespace JsonSerializationTests
int value2 = 42;
int* defaultPtrValue = &value2;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext,
ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
@@ -252,8 +258,9 @@ namespace JsonSerializationTests
int* ptrValue = nullptr;
int* defaultPtrValue = nullptr;
ResultCode result =
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
ResultCode result = ContinueStoring(
*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext,
ContinuationFlags::ResolvePointer);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("null");
@@ -265,8 +272,8 @@ namespace JsonSerializationTests
int value = 42;
ResultCode result = ContinueStoring(*m_jsonDocument, &value, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext,
Flags::ReplaceDefault);
ResultCode result = ContinueStoring(
*m_jsonDocument, &value, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, ContinuationFlags::ReplaceDefault);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("42");
@@ -280,7 +287,7 @@ namespace JsonSerializationTests
int* ptrValue = &value;
ResultCode result = ContinueStoring(*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext,
Flags::ResolvePointer | Flags::ReplaceDefault);
ContinuationFlags::ResolvePointer | ContinuationFlags::ReplaceDefault);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
Expect_DocStrEq("42");
@@ -293,8 +300,8 @@ namespace JsonSerializationTests
int value = 42;
AZ::Uuid unknownType("{09AE3CEC-EBFC-41EC-A7F6-949721521716}");
ResultCode result = ContinueStoring(*m_jsonDocument, &value, nullptr, unknownType, *m_jsonSerializationContext,
Flags::ReplaceDefault);
ResultCode result =
ContinueStoring(*m_jsonDocument, &value, nullptr, unknownType, *m_jsonSerializationContext, ContinuationFlags::ReplaceDefault);
EXPECT_EQ(Processing::Halted, result.GetProcessing());
}
@@ -90,9 +90,14 @@ namespace JsonSerializationTests
virtual ~JsonSerializerConformityTestDescriptor() = default;
virtual AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() = 0;
//! Create an instance of the target type with all values set to default.
virtual AZStd::shared_ptr<T> CreateDefaultInstance() = 0;
//! Create an instance of the target type that constructed with default constructor.
//! This will be the same instance that Json Serialization creates for dynamic types. Typically it's the same
//! as from CreateDefaultInstance(), except of types, such as pointers, that need to do minimal (de)serialization
//! to initialize an object.
virtual AZStd::shared_ptr<T> CreateDefaultConstructedInstance() { return CreateDefaultInstance(); }
//! Create an instance of the target type with some values set and some kept on defaults.
//! If the target type doesn't support partial specialization this can be ignored and
//! tests for partial support will be skipped.
@@ -316,10 +321,10 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto original = this->m_description.CreateDefaultInstance();
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*original),
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance),
*this->m_jsonDocument, *this->m_jsonDeserializationContext);
if (this->m_features.m_mandatoryFields.empty())
@@ -339,6 +344,42 @@ namespace JsonSerializationTests
}
}
TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeEmptyObjectThroughMainLoad_SucceedsAndObjectMatchesDefaults)
{
using namespace AZ::JsonSerializationResult;
if (this->m_features.SupportsJsonType(rapidjson::kObjectType))
{
this->m_jsonDocument->Parse("{}");
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto original = this->m_description.CreateDefaultInstance();
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Load(
instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, settings);
if (this->m_features.m_mandatoryFields.empty())
{
EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
}
else
{
EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome());
bool validProcessing =
result.GetProcessing() == Processing::Altered ||
result.GetProcessing() == Processing::PartialAlter;
EXPECT_TRUE(validProcessing);
}
EXPECT_TRUE(this->m_description.AreEqual(*original, *instance));
}
}
TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults)
{
using namespace AZ::JsonSerializationResult;
@@ -349,7 +390,7 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto original = this->m_description.CreateDefaultInstance();
this->m_deserializationSettings->m_clearContainers = false;
@@ -384,7 +425,7 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto original = this->m_description.CreateDefaultInstance();
this->m_deserializationSettings->m_clearContainers = true;
@@ -488,7 +529,7 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto compare = this->m_description.CreateFullySetInstance();
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance),
@@ -499,6 +540,28 @@ namespace JsonSerializationTests
EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare));
}
TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance)
{
using namespace AZ::JsonSerializationResult;
AZStd::string_view json = this->m_description.GetJsonFor_Load_DeserializeFullySetInstance();
this->m_jsonDocument->Parse(json.data());
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto compare = this->m_description.CreateFullySetInstance();
AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, settings);
EXPECT_EQ(Outcomes::Success, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare));
}
TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported)
{
using namespace AZ::JsonSerializationResult;
@@ -518,7 +581,7 @@ namespace JsonSerializationTests
ASSERT_NE(this->m_jsonDocument->MemberEnd(), memberToErase);
this->m_jsonDocument->RemoveMember(memberToErase);
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance),
*this->m_jsonDocument, *this->m_jsonDeserializationContext);
@@ -546,7 +609,7 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto compare = this->m_description.CreatePartialDefaultInstance();
ASSERT_NE(nullptr, compare);
@@ -567,7 +630,7 @@ namespace JsonSerializationTests
ASSERT_FALSE(this->m_jsonDocument->HasParseError());
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
AZ::ScopedContextReporter reporter(*this->m_jsonDeserializationContext,
[](AZStd::string_view message, ResultCode result, AZStd::string_view path) -> ResultCode
@@ -604,7 +667,7 @@ namespace JsonSerializationTests
}
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
auto compare = this->m_description.CreateFullySetInstance();
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance),
@@ -635,7 +698,7 @@ namespace JsonSerializationTests
}
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
auto instance = this->m_description.CreateDefaultConstructedInstance();
ResultCode result = serializer->Load(instance.get(), azrtti_typeid(*instance),
*this->m_jsonDocument, *this->m_jsonDeserializationContext);
@@ -693,6 +756,36 @@ namespace JsonSerializationTests
}
}
TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeDefaultInstanceThroughMainStore_EmptyJsonReturned)
{
using namespace AZ::JsonSerializationResult;
auto serializer = this->m_description.CreateSerializer();
auto instance = this->m_description.CreateDefaultInstance();
rapidjson::Value convertedValue = this->CreateExplicitDefault();
AZ::JsonSerializerSettings settings;
settings.m_serializeContext = this->m_jsonDeserializationContext->GetSerializeContext();
settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext();
ResultCode result = AZ::JsonSerialization::Store(
convertedValue, this->m_jsonDocument->GetAllocator(), instance.get(), instance.get(), azrtti_typeid(*instance), settings);
EXPECT_EQ(Processing::Completed, result.GetProcessing());
if (convertedValue.IsObject() && !this->m_features.m_mandatoryFields.empty())
{
ASSERT_EQ(convertedValue.MemberCount(), this->m_features.m_mandatoryFields.size());
for (const AZStd::string& mandatoryField : this->m_features.m_mandatoryFields)
{
EXPECT_NE(convertedValue.MemberEnd(), convertedValue.FindMember(mandatoryField.c_str()));
}
}
else
{
EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome());
this->Expect_ExplicitDefault(convertedValue);
}
}
TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeWithDefaultsKept_FullyWrittenJson)
{
using namespace AZ::JsonSerializationResult;
@@ -924,6 +1017,20 @@ namespace JsonSerializationTests
}
}
TYPED_TEST_P(JsonSerializerConformityTests, GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared)
{
if (this->m_features.SupportsJsonType(rapidjson::kObjectType))
{
if (!this->m_features.m_mandatoryFields.empty())
{
auto serializer = this->m_description.CreateSerializer();
bool manuallyHandlesDefaults = (serializer->GetOperationsFlags() & AZ::BaseJsonSerializer::OperationFlags::ManualDefault) ==
AZ::BaseJsonSerializer::OperationFlags::ManualDefault;
EXPECT_TRUE(manuallyHandlesDefaults);
}
}
}
REGISTER_TYPED_TEST_CASE_P(JsonSerializerConformityTests,
Registration_SerializerIsRegisteredWithContext_SerializerFound,
@@ -934,14 +1041,16 @@ namespace JsonSerializationTests
Load_InvalidTypeOfArrayType_ReturnsUnsupported,
Load_InvalidTypeOfStringType_ReturnsUnsupported,
Load_InvalidTypeOfNumberType_ReturnsUnsupported,
Load_DeserializeUnreflectedType_ReturnsUnsupported,
Load_DeserializeEmptyObject_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyObjectThroughMainLoad_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyArrayWithClearEnabled_SucceedsAndObjectMatchesDefaults,
Load_DeserializeEmptyArrayWithClearedTarget_SucceedsAndObjectMatchesDefaults,
Load_InterruptClearingTarget_ContainerIsNotCleared,
Load_DeserializeFullySetInstance_SucceedsAndObjectMatchesFullySetInstance,
Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance,
Load_DeserializePartialInstance_SucceedsAndObjectMatchesParialInstance,
Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported,
Load_InsertAdditionalData_SucceedsAndObjectMatchesFullySetInstance,
@@ -950,6 +1059,7 @@ namespace JsonSerializationTests
Store_SerializeUnreflectedType_ReturnsUnsupported,
Store_SerializeDefaultInstance_EmptyJsonReturned,
Store_SerializeDefaultInstanceThroughMainStore_EmptyJsonReturned,
Store_SerializeWithDefaultsKept_FullyWrittenJson,
Store_SerializeFullySetInstance_StoredSuccessfullyAndJsonMatches,
Store_SerializeWithoutDefault_StoredSuccessfullyAndJsonMatches,
@@ -957,10 +1067,12 @@ namespace JsonSerializationTests
Store_SerializePartialInstance_StoredSuccessfullyAndJsonMatches,
Store_SerializeEmptyArray_StoredSuccessfullyAndJsonMatches,
Store_HaltedThroughCallback_StoreFailsAndHaltReported,
StoreLoad_RoundTripWithPartialDefault_IdenticalInstances,
StoreLoad_RoundTripWithFullSet_IdenticalInstances,
StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances);
StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances,
GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared);
} // namespace JsonSerializationTests
namespace AZ
@@ -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
@@ -32,6 +32,11 @@ namespace JsonSerializationTests
return AZStd::make_shared<AZ::JsonSmartPointerSerializer>();
}
AZStd::shared_ptr<SmartPointer> CreateDefaultConstructedInstance() override
{
return AZStd::make_shared<SmartPointer>();
}
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
{
context->RegisterGenericType<SmartPointer>();
@@ -228,13 +233,19 @@ namespace JsonSerializationTests
public:
using SmartPointer = typename SmartPointerSimpleDerivedClassTestDescription<T>::SmartPointer;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
// This test is specific for derived classes being used as a default value.
AZStd::shared_ptr<SmartPointer> CreateDefaultConstructedInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew SimpleInheritence());
return result;
}
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
return CreateDefaultConstructedInstance();
}
AZStd::string_view GetJsonForPartialDefaultInstance() override
{
return R"(
@@ -386,13 +397,19 @@ namespace JsonSerializationTests
public:
using SmartPointer = typename SmartPointerComplexDerivedClassTestDescription<T>::SmartPointer;
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
// This test is specific for derived classes being used as a default value.
AZStd::shared_ptr<SmartPointer> CreateDefaultConstructedInstance() override
{
auto result = AZStd::make_shared<SmartPointer>();
*result = SmartPointer(aznew MultipleInheritence());
return result;
}
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
{
return CreateDefaultConstructedInstance();
}
AZStd::string_view GetJsonForPartialDefaultInstance() override
{
return R"(
@@ -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
@@ -19,44 +19,29 @@
namespace AzPhysics
{
struct SimulatedBody;
}
namespace Physics
{
//! Requests for generic physical world bodies
class WorldBodyRequests
//! Requests for physics simulated body components.
class SimulatedBodyComponentRequests
: public AZ::ComponentBus
{
public:
using MutexType = AZStd::recursive_mutex;
//! Enable physics for this body
//! Enable physics for this body.
virtual void EnablePhysics() = 0;
//! Disable physics for this body
//! Disable physics for this body.
virtual void DisablePhysics() = 0;
//! Retrieve whether physics is enabled for this body
//! Retrieve whether physics is enabled for this body.
virtual bool IsPhysicsEnabled() const = 0;
//! Retrieves the AABB(aligned-axis bounding box) for this body
//! Retrieves the AABB(aligned-axis bounding box) for this body.
virtual AZ::Aabb GetAabb() const = 0;
//! Retrieves current WorldBody* for this body. Note: Do not hold a reference to AzPhysics::SimulatedBody* as could be deleted
virtual AzPhysics::SimulatedBody* GetWorldBody() = 0;
//! Perform a single-object raycast against this body
//! Get the Simulated Body Handle for this body.
virtual AzPhysics::SimulatedBodyHandle GetSimulatedBodyHandle() const = 0;
//! Retrieves current WorldBody* for this body.
//! @note Do not hold a reference to AzPhysics::SimulatedBody* as it could be deleted or moved.
virtual AzPhysics::SimulatedBody* GetSimulatedBody() = 0;
//! Perform a single-object raycast against this body.
virtual AzPhysics::SceneQueryHit RayCast(const AzPhysics::RayCastRequest& request) = 0;
};
using WorldBodyRequestBus = AZ::EBus<WorldBodyRequests>;
//! Notifications for generic physical world bodies
class WorldBodyNotifications
: public AZ::ComponentBus
{
public:
//! Notification for physics enabled
virtual void OnPhysicsEnabled() = 0;
//! Notification for physics disabled
virtual void OnPhysicsDisabled() = 0;
};
using WorldBodyNotificationBus = AZ::EBus<WorldBodyNotifications>;
using SimulatedBodyComponentRequestsBus = AZ::EBus<SimulatedBodyComponentRequests>;
}
@@ -48,6 +48,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<SphereShapeConfiguration>>();
serializeContext->Class<SphereShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Radius", &SphereShapeConfiguration::m_radius)
@@ -76,6 +79,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<BoxShapeConfiguration>>();
serializeContext->Class<BoxShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Configuration", &BoxShapeConfiguration::m_dimensions)
@@ -104,6 +110,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<CapsuleShapeConfiguration>>();
serializeContext->Class<CapsuleShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Height", &CapsuleShapeConfiguration::m_height)
@@ -153,6 +162,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<PhysicsAssetShapeConfiguration>>();
serializeContext->Class<PhysicsAssetShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
@@ -185,6 +197,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<NativeShapeConfiguration>>();
serializeContext->Class<NativeShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Scale", &NativeShapeConfiguration::m_nativeShapeScale)
@@ -208,6 +223,9 @@ namespace Physics
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<CookedMeshShapeConfiguration>>();
serializeContext->Class<CookedMeshShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("CookedData", &CookedMeshShapeConfiguration::m_cookedData)
@@ -21,7 +21,7 @@
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Physics/CollisionBus.h>
#include <AzFramework/Physics/WorldBodyBus.h>
#include <AzFramework/Physics/Components/SimulatedBodyComponentBus.h>
#include <AzFramework/Physics/WindBus.h>
#include <AzFramework/Physics/PhysicsSystem.h>
#include <AzFramework/Physics/Collision/CollisionEvents.h>
@@ -39,19 +39,19 @@ namespace Physics
{
namespace ReflectionUtils
{
void ReflectWorldBodyBus(AZ::ReflectContext* context)
void ReflectSimulatedBodyComponentRequestsBus(AZ::ReflectContext* context)
{
if (auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<Physics::WorldBodyRequestBus>("WorldBodyRequestBus")
behaviorContext->EBus<AzPhysics::SimulatedBodyComponentRequestsBus>("SimulatedBodyComponentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "physics")
->Attribute(AZ::Script::Attributes::Category, "PhysX")
->Event("EnablePhysics", &WorldBodyRequests::EnablePhysics)
->Event("DisablePhysics", &WorldBodyRequests::DisablePhysics)
->Event("IsPhysicsEnabled", &WorldBodyRequests::IsPhysicsEnabled)
->Event("GetAabb", &WorldBodyRequests::GetAabb)
->Event("RayCast", &WorldBodyRequests::RayCast)
->Event("EnablePhysics", &AzPhysics::SimulatedBodyComponentRequests::EnablePhysics)
->Event("DisablePhysics", &AzPhysics::SimulatedBodyComponentRequests::DisablePhysics)
->Event("IsPhysicsEnabled", &AzPhysics::SimulatedBodyComponentRequests::IsPhysicsEnabled)
->Event("GetAabb", &AzPhysics::SimulatedBodyComponentRequests::GetAabb)
->Event("RayCast", &AzPhysics::SimulatedBodyComponentRequests::RayCast)
;
}
}
@@ -131,7 +131,7 @@ namespace Physics
AnimationConfiguration::Reflect(context);
CharacterConfiguration::Reflect(context);
AzPhysics::SimulatedBody::Reflect(context);
ReflectWorldBodyBus(context);
ReflectSimulatedBodyComponentRequestsBus(context);
CollisionFilteringRequests::Reflect(context);
AzPhysics::SceneQuery::ReflectSceneQueryObjects(context);
ReflectWindBus(context);
@@ -213,6 +213,12 @@ set(FILES
StreamingInstall/StreamingInstall.cpp
StreamingInstall/StreamingInstallRequests.h
StreamingInstall/StreamingInstallNotifications.h
Physics/Collision/CollisionEvents.h
Physics/Collision/CollisionEvents.cpp
Physics/Collision/CollisionLayers.h
Physics/Collision/CollisionLayers.cpp
Physics/Collision/CollisionGroups.h
Physics/Collision/CollisionGroups.cpp
Physics/Common/PhysicsSceneQueries.h
Physics/Common/PhysicsSceneQueries.cpp
Physics/Common/PhysicsEvents.h
@@ -223,12 +229,7 @@ set(FILES
Physics/Common/PhysicsSimulatedBodyEvents.h
Physics/Common/PhysicsSimulatedBodyEvents.cpp
Physics/Common/PhysicsTypes.h
Physics/Collision/CollisionEvents.h
Physics/Collision/CollisionEvents.cpp
Physics/Collision/CollisionLayers.h
Physics/Collision/CollisionLayers.cpp
Physics/Collision/CollisionGroups.h
Physics/Collision/CollisionGroups.cpp
Physics/Components/SimulatedBodyComponentBus.h
Physics/Configuration/CollisionConfiguration.h
Physics/Configuration/CollisionConfiguration.cpp
Physics/Configuration/RigidBodyConfiguration.h
@@ -265,7 +266,6 @@ set(FILES
Physics/ShapeConfiguration.h
Physics/ShapeConfiguration.cpp
Physics/SystemBus.h
Physics/WorldBodyBus.h
Physics/ColliderComponentBus.h
Physics/RagdollPhysicsBus.h
Physics/CharacterPhysicsDataBus.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
)
@@ -117,8 +117,6 @@ namespace AzToolsFramework
{
EditorEntityModel::EditorEntityModel()
{
AzFramework::ApplicationRequests::Bus::BroadcastResult(m_isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
EntityCompositionNotificationBus::Handler::BusConnect();
EditorOnlyEntityComponentNotificationBus::Handler::BusConnect();
EditorEntityRuntimeActivationChangeNotificationBus::Handler::BusConnect();
@@ -565,7 +563,7 @@ namespace AzToolsFramework
{
//retrieve or add an entity entry to the table
//the entry must exist, even if not connected, so children and other data can be assigned
[[maybe_unused]] auto [it, inserted] = m_entityInfoTable.try_emplace(entityId, m_isPrefabEnabled);
[[maybe_unused]] auto [it, inserted] = m_entityInfoTable.try_emplace(entityId);
auto& entityInfo = it->second;
//the entity id defaults to invalid and must be set to match the requested id
@@ -882,11 +880,6 @@ namespace AzToolsFramework
}
}
EditorEntityModel::EditorEntityModelEntry::EditorEntityModelEntry(bool isPrefabEnabled)
: m_isPrefabEnabled(isPrefabEnabled)
{
}
EditorEntityModel::EditorEntityModelEntry::~EditorEntityModelEntry()
{
Disconnect();
@@ -1213,29 +1206,15 @@ namespace AzToolsFramework
auto childItr = m_childIndexCache.find(childId);
if (childItr != m_childIndexCache.end())
{
if (m_isPrefabEnabled)
{
// Take the last entry and move it into the removed spot instead of deleting the entry and having to move all
// following entries one step down.
AZ::EntityId backEntity = m_children.back();
m_children[childItr->second] = backEntity;
// Update cached index for the moved id to the new index.
m_childIndexCache[backEntity] = childItr->second;
// Now remove the deleted id from the children and cache.
m_childIndexCache.erase(childId);
m_children.erase(m_children.end() - 1);
}
else
{
m_children.erase(m_children.begin() + childItr->second);
// rebuild index cache for faster lookup
m_childIndexCache.clear();
for (auto childIdToCache : m_children)
{
m_childIndexCache[childIdToCache] = static_cast<AZ::u64>(m_childIndexCache.size());
}
}
// Take the last entry and move it into the removed spot instead of deleting the entry and having to move all
// following entries one step down.
AZ::EntityId backEntity = m_children.back();
m_children[childItr->second] = backEntity;
// Update cached index for the moved id to the new index.
m_childIndexCache[backEntity] = childItr->second;
// Now remove the deleted id from the children and cache.
m_childIndexCache.erase(childId);
m_children.erase(m_children.end() - 1);
}
}
@@ -171,7 +171,6 @@ namespace AzToolsFramework
, public PropertyEditorEntityChangeNotificationBus::Handler
{
public:
explicit EditorEntityModelEntry(bool isPrefabEnabled);
~EditorEntityModelEntry();
// Separately connect to EditorEntityInfoRequestBus and refresh Entity
@@ -336,7 +335,6 @@ namespace AzToolsFramework
bool m_visible = true;
bool m_locked = false;
bool m_connected = false;
bool m_isPrefabEnabled = false;
AZStd::string m_name;
AZStd::string m_sliceAssetName;
AZStd::unordered_map<AZ::EntityId, AZ::u64> m_childIndexCache;
@@ -375,6 +373,5 @@ namespace AzToolsFramework
AZ::EntityId m_postInstantiateBeforeEntity;
AZ::EntityId m_postInstantiateSliceParent;
bool m_gotInstantiateSliceDetails = false;
bool m_isPrefabEnabled = false;
};
}
@@ -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>;
@@ -244,6 +262,8 @@ namespace AzToolsFramework
/// from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
/// position delta.
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
/// Is mouse over viewport.
virtual bool IsMouseOver() const = 0;
protected:
~ViewportMouseCursorRequests() = default;
@@ -78,7 +78,7 @@ namespace Benchmark
}
BENCHMARK_REGISTER_F(BM_PrefabUpdateInstances, UpdateInstances_SingeEntityInstances)
->RangeMultiplier(10)
->Range(100, 1000)
->Range(100, 10000)
->Unit(benchmark::kMillisecond)
->Complexity();
@@ -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>
+1 -1
View File
@@ -3200,7 +3200,7 @@ CCryEditApp::ECreateLevelResult CCryEditApp::CreateLevel(const QString& levelNam
m_bIsExportingLegacyData = false;
}
GetIEditor()->GetGameEngine()->LoadLevel(GetIEditor()->GetGameEngine()->GetMissionName(), true, true);
GetIEditor()->GetGameEngine()->LoadLevel(true, true);
GetIEditor()->GetSystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_START, 0, 0);
GetIEditor()->GetSystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_END, 0, 0);
+5
View File
@@ -459,6 +459,11 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename)
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData);
}
{
CAutoLogTime logtime("Game Engine level load");
GetIEditor()->GetGameEngine()->LoadLevel(true, true);
}
if (!isPrefabEnabled)
{
//////////////////////////////////////////////////////////////////////////
+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
};
+1 -8
View File
@@ -539,19 +539,12 @@ void CGameEngine::SetLevelPath(const QString& path)
}
}
void CGameEngine::SetMissionName(const QString& mission)
{
m_missionName = mission;
}
bool CGameEngine::LoadLevel(
const QString& mission,
[[maybe_unused]] bool bDeleteAIGraph,
bool bReleaseResources)
{
LOADING_TIME_PROFILE_SECTION(GetIEditor()->GetSystem());
m_bLevelLoaded = false;
m_missionName = mission;
CLogFile::FormatLine("Loading map '%s' into engine...", m_levelPath.toUtf8().data());
// Switch the current directory back to the Primary CD folder first.
// The engine might have trouble to find some files when the current
@@ -600,7 +593,7 @@ bool CGameEngine::LoadLevel(
bool CGameEngine::ReloadLevel()
{
if (!LoadLevel(GetMissionName(), false, false))
if (!LoadLevel(false, false))
{
return false;
}
-6
View File
@@ -89,7 +89,6 @@ public:
//! Load new terrain level into 3d engine.
//! Also load AI triangulation for this level.
bool LoadLevel(
const QString& mission,
bool bDeleteAIGraph,
bool bReleaseResources);
//!* Reload level if it was already loaded.
@@ -107,14 +106,10 @@ public:
bool IsLevelLoaded() const { return m_bLevelLoaded; };
//! Assign new level path name.
void SetLevelPath(const QString& path);
//! Assign new current mission name.
void SetMissionName(const QString& mission);
//! Return name of currently loaded level.
const QString& GetLevelName() const { return m_levelName; };
//! Return extension of currently loaded level.
const QString& GetLevelExtension() const { return m_levelExtension; };
//! Return name of currently active mission.
const QString& GetMissionName() const { return m_missionName; };
//! Get fully specified level path.
const QString& GetLevelPath() const { return m_levelPath; };
//! Query if engine is in game mode.
@@ -172,7 +167,6 @@ private:
CLogFile m_logFile;
QString m_levelName;
QString m_levelExtension;
QString m_missionName;
QString m_levelPath;
QString m_MOD;
bool m_bLevelLoaded;
+1 -1
View File
@@ -1327,7 +1327,7 @@ QToolButton* MainWindow::CreateDebugModeButton()
QWidget* MainWindow::CreateSpacerRightWidget()
{
QWidget* spacer = new QWidget();
QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
spacer->setVisible(true);
return spacer;
@@ -1473,14 +1473,15 @@ void OutlinerListModel::OnEntityInfoUpdatedRemoveChildBegin(AZ::EntityId parentI
emit EnableSelectionUpdates(false);
auto parentIndex = GetIndexFromEntity(parentId);
auto childIndex = GetIndexFromEntity(childId);
beginRemoveRows(parentIndex, childIndex.row(), childIndex.row());
beginResetModel();
}
void OutlinerListModel::OnEntityInfoUpdatedRemoveChildEnd(AZ::EntityId parentId, AZ::EntityId childId)
{
(void)childId;
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
endRemoveRows();
endResetModel();
//must refresh partial lock/visibility of parents
m_isFilterDirty = true;
@@ -20,13 +20,18 @@
namespace AssetBundler
{
const char* DateTimeFormat = "hh:mm:ss MMM dd, yyyy";
const char* ReadOnlyFileErrorMessage = "File (%s) is Read-Only. Please check your version control and try again.";
AssetBundlerAbstractFileTableModel::AssetBundlerAbstractFileTableModel(QObject* parent)
: QAbstractTableModel(parent)
{
}
void AssetBundlerAbstractFileTableModel::Reload(const char* fileExtension, const QSet<QString>& watchedFolders, const QSet<QString>& watchedFiles, const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap)
void AssetBundlerAbstractFileTableModel::Reload(
const char* fileExtension,
const QSet<QString>& watchedFolders,
const QSet<QString>& watchedFiles,
const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap)
{
AZStd::vector<AZStd::string> keysToRemove = m_fileListKeys;
@@ -49,7 +54,9 @@ namespace AssetBundler
// If a project name is already specified, then the associated file is a default file
LoadFile(absolutePath, projectName, !projectName.empty());
keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end());
keysToRemove.erase(
AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)),
keysToRemove.end());
}
}
@@ -63,7 +70,9 @@ namespace AssetBundler
// If a project name is already specified, then the associated file is a default file
LoadFile(absolutePath, projectName, !projectName.empty());
keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end());
keysToRemove.erase(
AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)),
keysToRemove.end());
}
}
@@ -74,7 +83,9 @@ namespace AssetBundler
}
}
void AssetBundlerAbstractFileTableModel::ReloadFiles(const AZStd::vector<AZStd::string>& absoluteFilePathList, AZStd::unordered_map<AZStd::string, AZStd::string> pathToProjectNameMap)
void AssetBundlerAbstractFileTableModel::ReloadFiles(
const AZStd::vector<AZStd::string>& absoluteFilePathList,
AZStd::unordered_map<AZStd::string, AZStd::string> pathToProjectNameMap)
{
for (const AZStd::string& absoluteFilePath : absoluteFilePathList)
{
@@ -30,6 +30,7 @@ namespace AssetBundler
{
extern const char* DateTimeFormat;
extern const char* ReadOnlyFileErrorMessage;
//! Provides an abstract model that can be subclassed to create table models used to store information about files found on-disk.
class AssetBundlerAbstractFileTableModel
@@ -47,9 +48,15 @@ namespace AssetBundler
//////////////////////////////////////////////////////////////////////////
// Pure virtual functions
virtual AZStd::vector<AZStd::string> CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project = QString()) = 0;
virtual AZStd::vector<AZStd::string> CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& platforms,
const QString& project = QString()) = 0;
virtual bool DeleteFile(const QModelIndex& index) = 0;
virtual void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) = 0;
virtual void LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& projectName = "",
bool isDefaultFile = false) = 0;
virtual bool WriteToDisk(const AZStd::string& key) = 0;
//! Returns the absolute path of the file at the given index on success, returns an empty string on failure.
@@ -60,9 +67,15 @@ namespace AssetBundler
//////////////////////////////////////////////////////////////////////////
//! Reload all the data based on the watched folders and files
virtual void Reload(const char* fileExtension, const QSet<QString>& watchedFolders, const QSet<QString>& watchedFiles = QSet<QString>(), const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>());
virtual void Reload(
const char* fileExtension,
const QSet<QString>& watchedFolders,
const QSet<QString>& watchedFiles = QSet<QString>(),
const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>());
virtual void ReloadFiles(const AZStd::vector<AZStd::string>& absoluteFilePathList, AZStd::unordered_map<AZStd::string, AZStd::string> pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>());
virtual void ReloadFiles(
const AZStd::vector<AZStd::string>& absoluteFilePathList,
AZStd::unordered_map<AZStd::string, AZStd::string> pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>());
bool Save(const QModelIndex& selectedIndex);
@@ -87,12 +87,15 @@ namespace AssetBundler
{
if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath))
{
AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, absolutePath);
return false;
}
auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath);
if (!deleteResult)
{
AZ_Error(AssetBundler::AppWindowName, false,
"Unable to delete (%s). Result code: %u", absolutePath, deleteResult.GetResultCode());
return false;
}
}
@@ -104,7 +107,10 @@ namespace AssetBundler
return true;
}
void AssetListFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/)
void AssetListFileTableModel::LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& /*projectName*/,
bool /*isDefaultFile*/)
{
AZStd::string fullFileName;
AzFramework::StringFunc::Path::GetFullFileName(absoluteFilePath.c_str(), fullFileName);
@@ -56,7 +56,10 @@ namespace AssetBundler
//////////////////////////////////////////////////////////////////////////
// AssetBundlerAbstractFileTableModel overrides
AZStd::vector<AZStd::string> CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; }
AZStd::vector<AZStd::string> CreateNewFiles(
const AZStd::string& /*absoluteFilePath*/,
const AzFramework::PlatformFlags& /*platforms*/,
const QString& /*project*/) override { return {}; }
bool DeleteFile(const QModelIndex& index) override;
void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override;
bool WriteToDisk(const AZStd::string& key) override;
@@ -23,7 +23,10 @@ namespace AssetBundler
: public QAbstractTableModel
{
public:
explicit AssetListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::string& platform = "");
explicit AssetListTableModel(
QObject* parent = nullptr,
const AZStd::string& absolutePath = AZStd::string(),
const AZStd::string& platform = "");
virtual ~AssetListTableModel() {}
AZStd::shared_ptr<AzToolsFramework::AssetSeedManager> GetSeedListManager() { return m_seedListManager; }
@@ -73,14 +73,15 @@ namespace AssetBundler
{
if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath))
{
AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath);
AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, absolutePath);
return false;
}
auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath);
if (!deleteResult)
{
AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath);
AZ_Error(AssetBundler::AppWindowName, false,
"Unable to delete (%s). Result code: %u", absolutePath, deleteResult.GetResultCode());
return false;
}
}
@@ -175,7 +176,10 @@ namespace AssetBundler
return Column::ColumnFileCreationTime;
}
void BundleFileListModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/)
void BundleFileListModel::LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& /*projectName*/,
bool /*isDefaultFile*/)
{
AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath);
@@ -43,7 +43,10 @@ namespace AssetBundler
explicit BundleFileListModel();
virtual ~BundleFileListModel() {}
AZStd::vector<AZStd::string> CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; }
AZStd::vector<AZStd::string> CreateNewFiles(
const AZStd::string& /*absoluteFilePath*/,
const AzFramework::PlatformFlags& /*platforms*/,
const QString& /*project*/) override { return {}; }
bool DeleteFile(const QModelIndex& index) override;
void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override;
bool WriteToDisk(const AZStd::string& /*key*/) override { return true; }
@@ -67,7 +67,10 @@ namespace AssetBundler
{
}
AZStd::vector<AZStd::string> RulesFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/)
AZStd::vector<AZStd::string> RulesFileTableModel::CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& /*platforms*/,
const QString& /*project*/)
{
if (absoluteFilePath.empty())
{
@@ -116,14 +119,16 @@ namespace AssetBundler
// Remove file from disk
if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(rulesFileInfo->m_absolutePath.c_str()))
{
AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", rulesFileInfo->m_absolutePath.c_str());
AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, rulesFileInfo->m_absolutePath.c_str());
return false;
}
auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(rulesFileInfo->m_absolutePath.c_str());
if (!deleteResult)
{
AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", rulesFileInfo->m_absolutePath.c_str());
AZ_Error(AssetBundler::AppWindowName, false,
"Unable to delete (%s). Result code: %u", rulesFileInfo->m_absolutePath.c_str(),
deleteResult.GetResultCode());
return false;
}
@@ -134,7 +139,10 @@ namespace AssetBundler
return true;
}
void RulesFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/)
void RulesFileTableModel::LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& /*projectName*/,
bool /*isDefaultFile*/)
{
// Get the file name without the extension for display purposes
AZStd::string fileName(absoluteFilePath);
@@ -145,7 +153,8 @@ namespace AssetBundler
auto fileInfoIt = m_rulesFileInfoMap.find(key);
if (fileInfoIt != m_rulesFileInfoMap.end() && fileInfoIt->second->m_hasUnsavedChanges)
{
AZ_Warning(AssetBundler::AppWindowName, false, "Rules File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str());
AZ_Warning(AssetBundler::AppWindowName, false,
"Rules File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str());
return;
}
@@ -48,7 +48,10 @@ namespace AssetBundler
RulesFileTableModel();
virtual ~RulesFileTableModel() {}
AZStd::vector<AZStd::string> CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE, const QString& project = QString()) override;
AZStd::vector<AZStd::string> CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE,
const QString& project = QString()) override;
bool DeleteFile(const QModelIndex& index) override;
@@ -91,12 +91,19 @@ namespace AssetBundler
m_seedTabWidget = nullptr;
}
void SeedListFileTableModel::AddDefaultSeedsToInMemoryList(const AZStd::vector<AZStd::string>& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms)
void SeedListFileTableModel::AddDefaultSeedsToInMemoryList(
const AZStd::vector<AZStd::string>& defaultSeeds,
const char* projectName,
const AzFramework::PlatformFlags& platforms)
{
m_inMemoryDefaultSeedList.reset(new SeedListFileInfo(m_inMemoryDefaultSeedListKey, tr("DefaultSeeds"), QString(projectName), false, true, defaultSeeds, platforms));
m_inMemoryDefaultSeedList.reset(
new SeedListFileInfo(m_inMemoryDefaultSeedListKey, tr("DefaultSeeds"), QString(projectName), false, true, defaultSeeds, platforms));
}
AZStd::vector<AZStd::string> SeedListFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& project)
AZStd::vector<AZStd::string> SeedListFileTableModel::CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& /*platforms*/,
const QString& project)
{
if (absoluteFilePath.empty())
{
@@ -111,7 +118,8 @@ namespace AssetBundler
// Create a Seed List File and save it to disk
AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath);
AZStd::shared_ptr<SeedListFileInfo> newSeedListFile = AZStd::make_shared<SeedListFileInfo>(absoluteFilePath, QString(fileName.c_str()), project, false);
AZStd::shared_ptr<SeedListFileInfo> newSeedListFile =
AZStd::make_shared<SeedListFileInfo>(absoluteFilePath, QString(fileName.c_str()), project, false);
newSeedListFile->m_seedListModel->SetHasUnsavedChanges(true);
bool saveResult = newSeedListFile->SaveSeedFile();
if (!saveResult)
@@ -151,14 +159,15 @@ namespace AssetBundler
{
if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath))
{
AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath);
AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, absolutePath);
return false;
}
auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath);
if (!deleteResult)
{
AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath);
AZ_Error(AssetBundler::AppWindowName, false,
"Unable to delete (%s). Result code: %u", absolutePath, deleteResult.GetResultCode());
return false;
}
}
@@ -170,7 +179,11 @@ namespace AssetBundler
return true;
}
void SeedListFileTableModel::Reload(const char* fileExtension, const QSet<QString>& watchedFolders, const QSet<QString>& watchedFiles, const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap)
void SeedListFileTableModel::Reload(
const char* fileExtension,
const QSet<QString>& watchedFolders,
const QSet<QString>& watchedFiles,
const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap)
{
// Load in the Seed List files from disk
AssetBundlerAbstractFileTableModel::Reload(fileExtension, watchedFolders, watchedFiles, pathToProjectNameMap);
@@ -191,7 +204,8 @@ namespace AssetBundler
auto fileInfoIt = m_seedListFileInfoMap.find(key);
if (fileInfoIt != m_seedListFileInfoMap.end() && fileInfoIt->second->HasUnsavedChanges())
{
AZ_Warning(AssetBundler::AppWindowName, false, "Seed List File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str());
AZ_Warning(AssetBundler::AppWindowName, false,
"Seed List File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str());
return;
}
@@ -208,7 +222,8 @@ namespace AssetBundler
projectNameOnDisplay = outcome.TakeValue();
}
m_seedListFileInfoMap[key].reset(new SeedListFileInfo(absoluteFilePath, QString(fileName.c_str()), QString(projectNameOnDisplay.c_str()), true, isDefaultFile));
m_seedListFileInfoMap[key].reset(
new SeedListFileInfo(absoluteFilePath, QString(fileName.c_str()), QString(projectNameOnDisplay.c_str()), true, isDefaultFile));
AddFileKey(key);
}
@@ -241,7 +256,9 @@ namespace AssetBundler
emit dataChanged(firstIndex, lastIndex, { Qt::CheckStateRole });
}
AZStd::vector<AZStd::string> SeedListFileTableModel::GenerateAssetLists(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms)
AZStd::vector<AZStd::string> SeedListFileTableModel::GenerateAssetLists(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& platforms)
{
if (!m_checkedSeedListFiles.size())
{
@@ -280,7 +297,8 @@ namespace AssetBundler
AZStd::vector<AZStd::string> createdFiles;
for (const auto& platformIndex : AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(platforms))
{
AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(platformIndex);
AZStd::string platformSpecificCachePath =
AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(platformIndex);
AzFramework::StringFunc::Path::StripFullName(platformSpecificCachePath);
FilePath platformSpecificPath(absoluteFilePath, AZStd::string(AzFramework::PlatformHelper::GetPlatformName(platformIndex)));
@@ -304,7 +322,10 @@ namespace AssetBundler
return seedFileInfoOutcome.GetValue()->m_seedListModel;
}
bool SeedListFileTableModel::SetSeedPlatforms(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex, const AzFramework::PlatformFlags& platforms)
bool SeedListFileTableModel::SetSeedPlatforms(
const QModelIndex& seedFileIndex,
const QModelIndex& seedIndex,
const AzFramework::PlatformFlags& platforms)
{
AZStd::string key = GetFileKey(seedFileIndex);
if (key.empty())
@@ -334,7 +355,10 @@ namespace AssetBundler
return true;
}
bool SeedListFileTableModel::AddSeed(const QModelIndex& seedFileIndex, const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms)
bool SeedListFileTableModel::AddSeed(
const QModelIndex& seedFileIndex,
const AZStd::string& seedRelativePath,
const AzFramework::PlatformFlags& platforms)
{
AZStd::string key = GetFileKey(seedFileIndex);
if (key.empty())
@@ -71,15 +71,28 @@ namespace AssetBundler
explicit SeedListFileTableModel(SeedTabWidget* parentSeedTabWidget);
virtual ~SeedListFileTableModel();
void AddDefaultSeedsToInMemoryList(const AZStd::vector<AZStd::string>& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms);
void AddDefaultSeedsToInMemoryList(
const AZStd::vector<AZStd::string>& defaultSeeds,
const char* projectName,
const AzFramework::PlatformFlags& platforms);
AZStd::vector<AZStd::string> CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project) override;
AZStd::vector<AZStd::string> CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& platforms,
const QString& project) override;
bool DeleteFile(const QModelIndex& index) override;
void Reload(const char* fileExtension, const QSet<QString>& watchedFolders, const QSet<QString>& watchedFiles = QSet<QString>(), const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>()) override;
void Reload(
const char* fileExtension,
const QSet<QString>& watchedFolders,
const QSet<QString>& watchedFiles = QSet<QString>(),
const AZStd::unordered_map<AZStd::string, AZStd::string>& pathToProjectNameMap = AZStd::unordered_map<AZStd::string, AZStd::string>()) override;
void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override;
void LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& projectName = "",
bool isDefaultFile = false) override;
void SelectDefaultSeedLists(bool setSelected);
@@ -38,7 +38,11 @@ namespace AssetBundler
//////////////////////////////////////////////////////////////////////////////////////////////////
// SeedListTableModel
//////////////////////////////////////////////////////////////////////////////////////////////////
SeedListTableModel::SeedListTableModel(QObject* parent, const AZStd::string& absolutePath, const AZStd::vector<AZStd::string>& defaultSeeds, const AzFramework::PlatformFlags& platforms)
SeedListTableModel::SeedListTableModel(
QObject* parent,
const AZStd::string& absolutePath,
const AZStd::vector<AZStd::string>& defaultSeeds,
const AzFramework::PlatformFlags& platforms)
: QAbstractTableModel(parent)
{
m_seedListManager.reset(new AzToolsFramework::AssetSeedManager());
@@ -66,7 +70,10 @@ namespace AssetBundler
QString platformList;
for (const auto& seed : m_seedListManager->GetAssetSeedList())
{
assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(seed.m_assetId, AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0], absolutePath);
assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(
seed.m_assetId,
AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0],
absolutePath);
platformList = QString(m_seedListManager->GetReadablePlatformList(seed).c_str());
m_additionalSeedInfoMap[seed.m_assetId].reset(new AdditionalSeedInfo(assetInfo.m_relativePath.c_str(), platformList));
@@ -126,7 +133,8 @@ namespace AssetBundler
AZ_Error(AssetBundler::AppWindowName, false, "Unable to find additional Seed info");
return false;
}
additionalSeedInfo->second->m_platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platforms).c_str());
additionalSeedInfo->second->m_platformList =
QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platforms).c_str());
SetHasUnsavedChanges(true);
@@ -140,7 +148,8 @@ namespace AssetBundler
bool SeedListTableModel::AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms)
{
AZStd::pair<AZ::Data::AssetId, AzFramework::PlatformFlags> addSeedsResult = m_seedListManager->AddSeedAssetForValidPlatforms(seedRelativePath, platforms);
AZStd::pair<AZ::Data::AssetId, AzFramework::PlatformFlags> addSeedsResult =
m_seedListManager->AddSeedAssetForValidPlatforms(seedRelativePath, platforms);
if (!addSeedsResult.first.IsValid() || addSeedsResult.second == AzFramework::PlatformFlags::Platform_NONE)
{
@@ -36,7 +36,11 @@ namespace AssetBundler
: public QAbstractTableModel
{
public:
explicit SeedListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::vector<AZStd::string>& defaultSeeds = AZStd::vector<AZStd::string>(), const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE);
explicit SeedListTableModel(
QObject* parent = nullptr,
const AZStd::string& absolutePath = AZStd::string(),
const AZStd::vector<AZStd::string>& defaultSeeds = AZStd::vector<AZStd::string>(),
const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE);
virtual ~SeedListTableModel() {}
AZStd::shared_ptr<AzToolsFramework::AssetSeedManager> GetSeedListManager() { return m_seedListManager; }
@@ -22,7 +22,10 @@ const char QtRelativePathPrefix[] = "../";
namespace AssetBundler
{
AddSeedDialog::AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath)
AddSeedDialog::AddSeedDialog(
QWidget* parent,
const AzFramework::PlatformFlags& enabledPlatforms,
const AZStd::string& platformSpecificCachePath)
: QDialog(parent)
, m_platformSpecificCachePath(platformSpecificCachePath.c_str())
{
@@ -35,7 +38,10 @@ namespace AssetBundler
// Set up Platform selection
m_ui->platformSelectionWidget->Init(enabledPlatforms);
connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &AddSeedDialog::OnPlatformSelectionChanged);
connect(m_ui->platformSelectionWidget,
&PlatformSelectionWidget::PlatformsSelected,
this,
&AddSeedDialog::OnPlatformSelectionChanged);
// Set up Cancel and Create New File buttons
m_ui->addSeedButton->setEnabled(false);
@@ -34,7 +34,10 @@ namespace AssetBundler
Q_OBJECT
public:
explicit AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath);
explicit AddSeedDialog(
QWidget* parent,
const AzFramework::PlatformFlags& enabledPlatforms,
const AZStd::string& platformSpecificCachePath);
virtual ~AddSeedDialog() {}
AZStd::string GetFileName();
@@ -73,7 +73,10 @@ namespace AssetBundler
SetupContextMenu();
Reload();
connect(GetFileTableView()->header(), &QHeaderView::sortIndicatorChanged, m_fileTableFilterModel.get(), &AssetBundlerFileTableFilterModel::sort);
connect(GetFileTableView()->header(),
&QHeaderView::sortIndicatorChanged,
m_fileTableFilterModel.get(),
&AssetBundlerFileTableFilterModel::sort);
GetFileTableView()->header()->setSortIndicatorShown(true);
// Setting this in descending order will ensure the most recent files are at the top
GetFileTableView()->header()->setSortIndicator(GetFileTableModel()->GetTimeStampColumnIndex(), Qt::DescendingOrder);
@@ -163,9 +166,11 @@ namespace AssetBundler
return;
}
QString messageBoxText = QString(tr("Are you sure you would like to delete %1? \n\nThis will permanently delete the file.")).arg(QString(selectedFileAbsolutePath.c_str()));
QString messageBoxText =
QString(tr("Are you sure you would like to delete %1? \n\nThis will permanently delete the file.")).arg(QString(selectedFileAbsolutePath.c_str()));
QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Delete %1")).arg(GetFileTypeDisplayName()), messageBoxText);
QMessageBox::StandardButton confirmDeleteFileResult =
QMessageBox::question(this, QString(tr("Delete %1")).arg(GetFileTypeDisplayName()), messageBoxText);
if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes)
{
// User canceled out of the confirmation dialog
@@ -206,7 +211,8 @@ namespace AssetBundler
defaultFolderPath = m_guiApplicationManager->GetBundlesFolder();
break;
default:
AZ_Warning(AssetBundler::AppWindowName, false, "No default folder is defined for AssetBundlingFileType ( %i ).", static_cast<int>(fileType));
AZ_Warning(AssetBundler::AppWindowName, false,
"No default folder is defined for AssetBundlingFileType ( %i ).", static_cast<int>(fileType));
break;
}
@@ -224,7 +230,8 @@ namespace AssetBundler
void AssetBundlerTabWidget::AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath)
{
AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str());
AZStd::string assetBundlerSettingsFileAbsolutePath =
GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str());
QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath);
QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject();
QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray();
@@ -256,7 +263,8 @@ namespace AssetBundler
void AssetBundlerTabWidget::RemoveScanPathFromAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath)
{
AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str());
AZStd::string assetBundlerSettingsFileAbsolutePath =
GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str());
QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath);
QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject();
QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray();
@@ -305,7 +313,10 @@ namespace AssetBundler
void AssetBundlerTabWidget::SetupContextMenu()
{
GetFileTableView()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(GetFileTableView(), &QTreeView::customContextMenuRequested, this, &AssetBundlerTabWidget::OnFileTableContextMenuRequested);
connect(GetFileTableView(),
&QTreeView::customContextMenuRequested,
this,
&AssetBundlerTabWidget::OnFileTableContextMenuRequested);
}
void AssetBundlerTabWidget::ReadAssetBundlerSettings(const AZStd::string& filePath, AssetBundlingFileType fileType)
@@ -78,7 +78,9 @@ namespace AssetBundler
virtual void ApplyConfig() = 0;
virtual void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) = 0;
virtual void FileSelectionChanged(
const QItemSelection& /*selected*/ = QItemSelection(),
const QItemSelection& /*deselected*/ = QItemSelection()) = 0;
static void InitAssetBundlerSettings(const char* currentProjectFolderPath);
@@ -44,14 +44,22 @@ namespace AssetBundler
m_ui->mainVerticalLayout->setContentsMargins(10, 10, 10, 10);
// File view of all Asset List Files
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(
this,
m_fileTableModel->GetFileNameColumnIndex(),
m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel->setSourceModel(m_fileTableModel.data());
m_ui->assetListsTable->setModel(m_fileTableFilterModel.data());
connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->assetListsTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AssetListTabWidget::FileSelectionChanged);
connect(m_ui->assetListsTable->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&AssetListTabWidget::FileSelectionChanged);
m_ui->fileTableHeaderLayout->setContentsMargins(0, 0, 0, 0);
m_ui->fileTableVerticalLayout->setContentsMargins(0, 0, 0, 0);
@@ -70,8 +78,10 @@ namespace AssetBundler
m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data());
m_ui->assetListContentsTable->setModel(m_assetListContentsFilterModel.data());
connect(m_ui->assetListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_assetListContentsFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->assetListContentsFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_assetListContentsFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
m_ui->fileContentsHeaderLayout->setContentsMargins(0, 0, 0, 0);
@@ -121,13 +131,21 @@ namespace AssetBundler
m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth);
m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnFileName, config.assetListFileNameColumnWidth);
m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnPlatform, config.assetListPlatformColumnWidth);
m_ui->assetListsTable->header()->resizeSection(
AssetListFileTableModel::Column::ColumnFileName,
config.assetListFileNameColumnWidth);
m_ui->assetListsTable->header()->resizeSection(
AssetListFileTableModel::Column::ColumnPlatform,
config.assetListPlatformColumnWidth);
m_ui->assetListContentsFilteredSearchWidget->setFixedWidth(config.fileTableWidth);
m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnAssetName, config.productAssetNameColumnWidth);
m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnRelativePath, config.productAssetRelativePathColumnWidth);
m_ui->assetListContentsTable->header()->resizeSection(
AssetListTableModel::Column::ColumnAssetName,
config.productAssetNameColumnWidth);
m_ui->assetListContentsTable->header()->resizeSection(
AssetListTableModel::Column::ColumnRelativePath,
config.productAssetRelativePathColumnWidth);
}
@@ -65,7 +65,9 @@ namespace AssetBundler
AssetBundlerAbstractFileTableModel* GetFileTableModel() override;
void SetActiveProjectLabel(const QString& labelText) override;
void ApplyConfig() override;
void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override;
void FileSelectionChanged(
const QItemSelection& /*selected*/ = QItemSelection(),
const QItemSelection& /*deselected*/ = QItemSelection()) override;
//////////////////////////////////////////////////////////////////////////
private:
@@ -34,14 +34,22 @@ namespace AssetBundler
m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize);
m_fileTableModel.reset(new BundleFileListModel);
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(
this,
m_fileTableModel->GetFileNameColumnIndex(),
m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel->setSourceModel(m_fileTableModel.data());
m_ui->fileTableView->setModel(m_fileTableFilterModel.data());
connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BundleListTabWidget::FileSelectionChanged);
connect(m_ui->fileTableView->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&BundleListTabWidget::FileSelectionChanged);
m_ui->fileTableView->setIndentation(0);
@@ -53,7 +53,9 @@ namespace AssetBundler
AssetBundlerAbstractFileTableModel* GetFileTableModel() override;
void SetActiveProjectLabel(const QString& labelText) override;
void ApplyConfig() override;
void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override;
void FileSelectionChanged(
const QItemSelection& /*selected*/ = QItemSelection(),
const QItemSelection& /*deselected*/ = QItemSelection()) override;
private:
void ClearDisplayedBundleValues();
@@ -42,7 +42,8 @@ namespace AssetBundler
if (!IsComparisonDataIndexValid())
{
AZ_Error("AssetBundler", false, "ComparisonData index ( %u ) is out of bounds. ComparisonData cannot be displayed.", m_comparisonDataIndex);
AZ_Error("AssetBundler", false,
"ComparisonData index ( %u ) is out of bounds. ComparisonData cannot be displayed.", m_comparisonDataIndex);
return;
}
@@ -64,14 +65,26 @@ namespace AssetBundler
connect(m_ui->nameLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnNameLineEditChanged);
m_ui->comparisonTypeComboBox->installEventFilter(mouseWheelEventFilter);
connect(m_ui->comparisonTypeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnComparisonTypeComboBoxChanged);
connect(m_ui->comparisonTypeComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ComparisonDataWidget::OnComparisonTypeComboBoxChanged);
m_ui->firstInputComboBox->installEventFilter(mouseWheelEventFilter);
connect(m_ui->firstInputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnFirstInputComboBoxChanged);
connect(m_ui->firstInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnFirstInputBrowseButtonPressed);
connect(m_ui->firstInputComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ComparisonDataWidget::OnFirstInputComboBoxChanged);
connect(m_ui->firstInputBrowseButton,
&QPushButton::pressed,
this,
&ComparisonDataWidget::OnFirstInputBrowseButtonPressed);
m_ui->secondInputComboBox->installEventFilter(mouseWheelEventFilter);
connect(m_ui->secondInputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnSecondInputComboBoxChanged);
connect(m_ui->secondInputComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ComparisonDataWidget::OnSecondInputComboBoxChanged);
connect(m_ui->secondInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnSecondInputBrowseButtonPressed);
connect(m_ui->filePatternLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnFilePatternLineEditChanged);
@@ -187,7 +200,8 @@ namespace AssetBundler
m_ui->filePatternLineEdit->setText(comparisonData.m_filePattern.c_str());
}
void ComparisonDataWidget::InitComparisonTypeComboBox(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData)
void ComparisonDataWidget::InitComparisonTypeComboBox(
const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData)
{
using namespace AzToolsFramework;
@@ -225,7 +239,8 @@ namespace AssetBundler
initialSelectionIndex = ComparisonTypeIndex::Complement;
break;
default:
AZ_Warning("AssetBundler", false, "ComparisonType ( %u ) is not supported in the Asset Bundler", comparisonData.m_comparisonType);
AZ_Warning("AssetBundler", false,
"ComparisonType ( %u ) is not supported in the Asset Bundler", comparisonData.m_comparisonType);
}
}
@@ -32,7 +32,10 @@ namespace AssetBundler
m_ui->platformSelectionWidget->Init(enabledPlatforms);
m_ui->platformSelectionWidget->SetSelectedPlatforms(selectedPlatforms, partiallySelectedPlatforms);
connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &EditSeedDialog::OnPlatformSelectionChanged);
connect(m_ui->platformSelectionWidget,
&PlatformSelectionWidget::PlatformsSelected,
this,
&EditSeedDialog::OnPlatformSelectionChanged);
// Set up confirm and cancel buttons
connect(m_ui->applyChangesButton, &QPushButton::clicked, this, &QDialog::accept);
@@ -49,7 +52,9 @@ namespace AssetBundler
return m_ui->platformSelectionWidget->GetPartiallySelectedPlatforms();
}
void EditSeedDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms)
void EditSeedDialog::OnPlatformSelectionChanged(
const AzFramework::PlatformFlags& selectedPlatforms,
const AzFramework::PlatformFlags& partiallySelectedPlatforms)
{
// Disable the "Apply Changes" button if no platforms are selected
bool areAnyPlatformsSelected = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE ||
@@ -44,7 +44,9 @@ namespace AssetBundler
AzFramework::PlatformFlags GetPartiallySelectedPlatformFlags();
private:
void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms);
void OnPlatformSelectionChanged(
const AzFramework::PlatformFlags& selectedPlatforms,
const AzFramework::PlatformFlags& partiallySelectedPlatforms);
QSharedPointer<Ui::EditSeedDialog> m_ui;
};
@@ -52,26 +52,41 @@ namespace AssetBundler
// Bundle Output
m_ui->outputBundlePathLineEdit->setReadOnly(true);
connect(m_ui->outputBundlePathBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed);
connect(m_ui->outputBundlePathBrowseButton,
&QPushButton::clicked,
this,
&GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed);
// Bundle Settings files
m_ui->bundleSettingsFileLineEdit->setReadOnly(true);
m_ui->bundleSettingsFileLineEdit->setText(tr(CustomBundleSettingsText));
connect(m_ui->bundleSettingsFileBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed);
connect(m_ui->bundleSettingsFileSaveButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsSaveButtonPressed);
connect(m_ui->bundleSettingsFileBrowseButton,
&QPushButton::clicked,
this,
&GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed);
connect(m_ui->bundleSettingsFileSaveButton,
&QPushButton::clicked,
this,
&GenerateBundlesModal::OnBundleSettingsSaveButtonPressed);
// Max Bundle Size
m_ui->maxBundleSizeSpinBox->setRange(1, AzToolsFramework::MaxBundleSizeInMB);
m_ui->maxBundleSizeSpinBox->setValue(AzToolsFramework::MaxBundleSizeInMB);
m_ui->maxBundleSizeSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons);
m_ui->maxBundleSizeSpinBox->setSuffix(" MB");
connect(m_ui->maxBundleSizeSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnMaxBundleSizeChanged);
connect(m_ui->maxBundleSizeSpinBox,
QOverload<int>::of(&QSpinBox::valueChanged),
this,
&GenerateBundlesModal::OnMaxBundleSizeChanged);
// Bundle Version
m_ui->bundleVersionSpinBox->setRange(1, AzFramework::AssetBundleManifest::CurrentBundleVersion);
m_ui->bundleVersionSpinBox->setValue(AzFramework::AssetBundleManifest::CurrentBundleVersion);
m_ui->bundleVersionSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons);
connect(m_ui->bundleVersionSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnBundleVersionChanged);
connect(m_ui->bundleVersionSpinBox,
QOverload<int>::of(&QSpinBox::valueChanged),
this,
&GenerateBundlesModal::OnBundleVersionChanged);
// Cancel and Generate Bundles buttons
m_ui->generateBundlesButton->setEnabled(false);
@@ -197,9 +212,11 @@ namespace AssetBundler
if (AZ::IO::FileIOBase::GetInstance()->Exists(bundleSettingsAbsolutePath.c_str()))
{
QString messageBoxText = QString(tr("Bundle Settings ( %1 ) already exists on-disk. Saving the current settings will override the existing settings. \n\nDo you wish to continue?")).arg(bundleSettingsAbsolutePath.c_str());
QString messageBoxText = QString(tr(
"Bundle Settings ( %1 ) already exists on-disk. Saving the current settings will override the existing settings. \n\nDo you wish to continue?")).arg(bundleSettingsAbsolutePath.c_str());
QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Settings")), messageBoxText);
QMessageBox::StandardButton confirmDeleteFileResult =
QMessageBox::question(this, QString(tr("Replace Existing Settings")), messageBoxText);
if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes)
{
// User canceled out of the operation
@@ -237,9 +254,11 @@ namespace AssetBundler
if (AZ::IO::FileIOBase::GetInstance()->Exists(m_bundleSettings.m_bundleFilePath.c_str()))
{
QString messageBoxText = QString(tr("Asset Bundle ( %1 ) already exists on-disk. Generating a new Bundle will override the existing Bundle. \n\nDo you wish to permanently delete the existing Bundle?")).arg(m_bundleSettings.m_bundleFilePath.c_str());
QString messageBoxText = QString(tr(
"Asset Bundle ( %1 ) already exists on-disk. Generating a new Bundle will override the existing Bundle. \n\nDo you wish to permanently delete the existing Bundle?")).arg(m_bundleSettings.m_bundleFilePath.c_str());
QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Bundle")), messageBoxText);
QMessageBox::StandardButton confirmDeleteFileResult =
QMessageBox::question(this, QString(tr("Replace Existing Bundle")), messageBoxText);
if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes)
{
// User canceled out of the operation
@@ -259,10 +278,14 @@ namespace AssetBundler
if (result)
{
m_assetListTabWidget->AddScanPathToAssetBundlerSettings(AssetBundlingFileType::BundleFileType, m_bundleSettings.m_bundleFilePath);
m_assetListTabWidget->AddScanPathToAssetBundlerSettings(
AssetBundlingFileType::BundleFileType,
m_bundleSettings.m_bundleFilePath);
// The watched files list was updated after the files were created, so we need to force-reload them
m_assetListTabWidget->GetGUIApplicationManager()->UpdateFiles(AssetBundlingFileType::BundleFileType, { m_bundleSettings.m_bundleFilePath });
m_assetListTabWidget->GetGUIApplicationManager()->UpdateFiles(
AssetBundlingFileType::BundleFileType,
{ m_bundleSettings.m_bundleFilePath });
}
AZStd::vector<AZStd::string> generatedFilePaths = { m_bundleSettings.m_bundleFilePath };
@@ -63,7 +63,10 @@ namespace AssetBundler
// Set up Tabs
AssetBundlerTabWidget::InitAssetBundlerSettings(m_guiApplicationManager->GetCurrentProjectFolder().c_str());
m_seedListTab.reset(new SeedTabWidget(this, m_guiApplicationManager, QString(m_guiApplicationManager->GetAssetBundlingFolder().c_str())));
m_seedListTab.reset(new SeedTabWidget(
this,
m_guiApplicationManager,
QString(m_guiApplicationManager->GetAssetBundlingFolder().c_str())));
m_ui->tabWidget->addTab(m_seedListTab.data(), m_seedListTab->GetTabTitle());
m_assetListTab.reset(new AssetListTabWidget(this, m_guiApplicationManager));
@@ -51,7 +51,8 @@ namespace AssetBundler
m_newFileDialog.setNameFilter(fileNameFilter);
m_newFileDialog.setViewMode(QFileDialog::Detail);
m_newFileDialog.setDirectory(m_startingPath);
// We are not creating a new file when Qt thinks we are, so we need to block signals or else the file watcher will be triggered too soon
// We are not creating a new file when Qt thinks we are, so we need to block signals or else the file watcher will be
// triggered too soon
m_newFileDialog.blockSignals(true);
// Set up Platform selection
@@ -61,7 +62,10 @@ namespace AssetBundler
disabledPatformMessageOverride = tr("This platform is not valid for all input Asset Lists.");
}
m_ui->platformSelectionWidget->Init(enabledPlatforms, disabledPatformMessageOverride);
connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &NewFileDialog::OnPlatformSelectionChanged);
connect(m_ui->platformSelectionWidget,
&PlatformSelectionWidget::PlatformsSelected,
this,
&NewFileDialog::OnPlatformSelectionChanged);
// Set up Cancel and Create New File buttons
m_ui->createFileButton->setEnabled(false);
@@ -112,7 +116,8 @@ namespace AssetBundler
{
// Check to see if any of the selected platform-specific files already exist on-disk
QString overwriteExistingFilesList;
AZStd::fixed_vector<AZStd::string, AzFramework::NumPlatforms> selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(GetPlatformFlags());
AZStd::fixed_vector<AZStd::string, AzFramework::NumPlatforms> selectedPlatformNames =
AzFramework::PlatformHelper::GetPlatforms(GetPlatformFlags());
for (const AZStd::string& platformName : selectedPlatformNames)
{
FilePath platformSpecificFilePath(GetAbsoluteFilePath(), platformName);
@@ -126,9 +131,11 @@ namespace AssetBundler
// Ask the user if they are sure they want to overwrite existing files
if (!overwriteExistingFilesList.isEmpty())
{
QString messageBoxText = QString(tr("The following files already exist on-disk. Generating new files will overwrite the existing ones.\n\n%1\n\nDo you wish to permanently delete the existing files?")).arg(overwriteExistingFilesList);
QString messageBoxText = QString(tr(
"The following files already exist on-disk. Generating new files will overwrite the existing ones.\n\n%1\n\nDo you wish to permanently delete the existing files?")).arg(overwriteExistingFilesList);
QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Files")), messageBoxText);
QMessageBox::StandardButton confirmDeleteFileResult =
QMessageBox::question(this, QString(tr("Replace Existing Files")), messageBoxText);
if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes)
{
// User canceled out of the operation
@@ -139,7 +146,11 @@ namespace AssetBundler
emit QDialog::accept();
}
AZStd::string NewFileDialog::OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory)
AZStd::string NewFileDialog::OSNewFileDialog(
QWidget* parent,
const char* fileExtension,
const char* fileTypeDisplayName,
const AZStd::string& startingDirectory)
{
QFileDialog filePathDialog(parent);
filePathDialog.setFileMode(QFileDialog::AnyFile);
@@ -160,13 +171,17 @@ namespace AssetBundler
AZStd::string absoluteFilePath(filePathDialog.selectedFiles()[0].toUtf8().data());
if (!AzFramework::StringFunc::Path::HasExtension(absoluteFilePath.c_str()))
{
absoluteFilePath = AZStd::string::format("%s%c%s", absoluteFilePath.c_str(), AZ_FILESYSTEM_EXTENSION_SEPARATOR, fileExtension);
absoluteFilePath =
AZStd::string::format("%s%c%s", absoluteFilePath.c_str(), AZ_FILESYSTEM_EXTENSION_SEPARATOR, fileExtension);
}
return absoluteFilePath;
}
int NewFileDialog::FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector<AZStd::string>& generatedFiles, bool generatedWithErrors)
int NewFileDialog::FileGenerationResultMessageBox(
QWidget* parent,
const AZStd::vector<AZStd::string>& generatedFiles,
bool generatedWithErrors)
{
QMessageBox messageBox(parent);
messageBox.setStandardButtons(QMessageBox::Ok);
@@ -51,9 +51,16 @@ namespace AssetBundler
//! A standard OS-specific New File Dialog, but blocks all Qt signals from the dialog and does NOT create a new file.
//! Use in place of the static QFileDialog functions to avoid unexpected file watcher updates.
//! Returns the absolute path of the file the user either selected or attempted to create, or an empty string if the user canceled out of the dialog.
static AZStd::string OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory);
static AZStd::string OSNewFileDialog(
QWidget* parent,
const char* fileExtension,
const char* fileTypeDisplayName,
const AZStd::string& startingDirectory);
static int FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector<AZStd::string>& generatedFiles, bool generatedWithErrors);
static int FileGenerationResultMessageBox(
QWidget* parent,
const AZStd::vector<AZStd::string>& generatedFiles,
bool generatedWithErrors);
private:
void OnBrowseButtonPressed();
@@ -66,7 +66,9 @@ namespace AssetBundler
}
}
void PlatformSelectionWidget::SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms)
void PlatformSelectionWidget::SetSelectedPlatforms(
const AzFramework::PlatformFlags& selectedPlatforms,
const AzFramework::PlatformFlags& partiallySelectedPlatforms)
{
m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE;
m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE;
@@ -39,7 +39,9 @@ namespace AssetBundler
void Init(const AzFramework::PlatformFlags& enabledPlatforms, const QString& disabledPatformMessageOverride = "");
void SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms);
void SetSelectedPlatforms(
const AzFramework::PlatformFlags& selectedPlatforms,
const AzFramework::PlatformFlags& partiallySelectedPlatforms);
AzFramework::PlatformFlags GetSelectedPlatforms();
AzFramework::PlatformFlags GetPartiallySelectedPlatforms();
@@ -45,14 +45,22 @@ namespace AssetBundler
m_ui->fileTableView->setModel(m_fileTableModel.data());
// Table View of all Rules files
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(
this,
m_fileTableModel->GetFileNameColumnIndex(),
m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel->setSourceModel(m_fileTableModel.data());
m_ui->fileTableView->setModel(m_fileTableFilterModel.data());
connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RulesTabWidget::FileSelectionChanged);
connect(m_ui->fileTableView->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&RulesTabWidget::FileSelectionChanged);
m_ui->fileTableView->setIndentation(0);
@@ -76,7 +84,10 @@ namespace AssetBundler
void RulesTabWidget::Reload()
{
m_fileTableModel->Reload(AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(), m_watchedFolders, m_watchedFiles);
m_fileTableModel->Reload(
AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(),
m_watchedFolders,
m_watchedFiles);
FileSelectionChanged();
}
@@ -223,7 +234,8 @@ namespace AssetBundler
AZStd::vector<AZStd::string> outputFilePaths;
bool hasFileGenerationErrors = false;
AZStd::fixed_vector<AZStd::string, AzFramework::NumPlatforms> selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(runRuleDialog.GetPlatformFlags());
AZStd::fixed_vector<AZStd::string, AzFramework::NumPlatforms> selectedPlatformNames =
AzFramework::PlatformHelper::GetPlatforms(runRuleDialog.GetPlatformFlags());
for (const AZStd::string& platformName : selectedPlatformNames)
{
// We do not want to modify the original Rules file, as we do not save Asset List file paths to disk
@@ -238,7 +250,8 @@ namespace AssetBundler
{
if (comparisonStep.m_cachedFirstInputPath.empty())
{
AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified first input.", comparisonStepIndex);
AZ_Error("AssetBundler", false,
"Unable to run Rule: Comparison Step #%u has no specified first input.", comparisonStepIndex);
return;
}
@@ -251,7 +264,8 @@ namespace AssetBundler
{
if (comparisonStep.m_cachedSecondInputPath.empty())
{
AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified second input.", comparisonStepIndex);
AZ_Error("AssetBundler", false,
"Unable to run Rule: Comparison Step #%u has no specified second input.", comparisonStepIndex);
return;
}
@@ -313,17 +327,28 @@ namespace AssetBundler
}
}
void RulesTabWidget::CreateComparisonDataCard(AZStd::shared_ptr<AzToolsFramework::AssetFileInfoListComparison> comparisonList, size_t comparisonDataIndex)
void RulesTabWidget::CreateComparisonDataCard(
AZStd::shared_ptr<AzToolsFramework::AssetFileInfoListComparison> comparisonList,
size_t comparisonDataIndex)
{
ComparisonDataCard* comparisonDataCard = new ComparisonDataCard(comparisonList, comparisonDataIndex, m_guiApplicationManager->GetAssetListsFolder());
ComparisonDataCard* comparisonDataCard = new ComparisonDataCard(
comparisonList,
comparisonDataIndex,
m_guiApplicationManager->GetAssetListsFolder());
comparisonDataCard->setTitle(tr("Step %1").arg(static_cast<int>(comparisonDataIndex) + 1));
m_ui->comparisonDataListLayout->addWidget(comparisonDataCard);
m_comparisonDataCardList.push_back(comparisonDataCard);
ComparisonDataWidget* comparisonDataWidget = comparisonDataCard->GetComparisonDataWidget();
connect(comparisonDataCard, &ComparisonDataCard::comparisonDataCardContextMenuRequested, this, &RulesTabWidget::OnComparisonDataCardContextMenuRequested);
connect(comparisonDataCard,
&ComparisonDataCard::comparisonDataCardContextMenuRequested,
this,
&RulesTabWidget::OnComparisonDataCardContextMenuRequested);
connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataChanged, this, &RulesTabWidget::MarkFileChanged);
connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataTokenNameChanged, this, &RulesTabWidget::OnAnyTokenNameChanged);
connect(comparisonDataWidget,
&ComparisonDataWidget::comparisonDataTokenNameChanged,
this,
&RulesTabWidget::OnAnyTokenNameChanged);
comparisonDataCard->show();
}
@@ -81,7 +81,9 @@ namespace AssetBundler
void ApplyConfig() override;
void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override;
void FileSelectionChanged(
const QItemSelection& /*selected*/ = QItemSelection(),
const QItemSelection& /*deselected*/ = QItemSelection()) override;
private:
void OnNewFileButtonPressed();
@@ -94,7 +96,9 @@ namespace AssetBundler
void PopulateComparisonDataCardList();
void CreateComparisonDataCard(AZStd::shared_ptr<AzToolsFramework::AssetFileInfoListComparison> comparisonList, size_t comparisonDataIndex);
void CreateComparisonDataCard(
AZStd::shared_ptr<AzToolsFramework::AssetFileInfoListComparison> comparisonList,
size_t comparisonDataIndex);
void RemoveAllComparisonDataCards();
@@ -56,14 +56,22 @@ namespace AssetBundler
AZ::Debug::TraceMessageBus::Handler::BusConnect();
// File view of all Seed List Files
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(
this,
m_fileTableModel->GetFileNameColumnIndex(),
m_fileTableModel->GetTimeStampColumnIndex()));
m_fileTableFilterModel->setSourceModel(m_fileTableModel.data());
m_ui->fileTableView->setModel(m_fileTableFilterModel.data());
connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_fileTableFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SeedTabWidget::FileSelectionChanged);
connect(m_ui->fileTableView->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&SeedTabWidget::FileSelectionChanged);
m_ui->fileTableView->setIndentation(CheckBoxTableIndentationSize);
@@ -82,11 +90,16 @@ namespace AssetBundler
m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data());
m_ui->seedFileContentsTable->setModel(m_seedListContentsFilterModel.data());
connect(m_ui->seedListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_seedListContentsFilterModel.data(), static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
connect(m_ui->seedListContentsFilteredSearchWidget,
&AzQtComponents::FilteredSearchWidget::TextFilterChanged,
m_seedListContentsFilterModel.data(),
static_cast<void (QSortFilterProxyModel::*)(const QString&)>(&AssetBundlerFileTableFilterModel::FilterChanged));
m_ui->seedFileContentsTable->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->seedFileContentsTable, &QTreeView::customContextMenuRequested, this, &SeedTabWidget::OnSeedListContentsTableContextMenuRequested);
connect(m_ui->seedFileContentsTable,
&QTreeView::customContextMenuRequested,
this,
&SeedTabWidget::OnSeedListContentsTableContextMenuRequested);
m_ui->seedFileContentsTable->setIndentation(0);
@@ -112,7 +125,11 @@ namespace AssetBundler
void SeedTabWidget::Reload()
{
// Reload all the seed list files
m_fileTableModel->Reload(AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), m_watchedFolders, m_watchedFiles, m_filePathToGemNameMap);
m_fileTableModel->Reload(
AzToolsFramework::AssetSeedManager::GetSeedFileExtension(),
m_watchedFolders,
m_watchedFiles,
m_filePathToGemNameMap);
// Update the selected row
FileSelectionChanged();
@@ -138,12 +155,18 @@ namespace AssetBundler
m_watchedFolders.insert(m_guiApplicationManager->GetSeedListsFolder().c_str());
// Get the list of default Seed List files
m_filePathToGemNameMap = AssetBundler::GetDefaultSeedListFiles(AZStd::string_view{ AZ::Utils::GetEnginePath() }, m_guiApplicationManager->GetCurrentProjectName(),
m_filePathToGemNameMap = AssetBundler::GetDefaultSeedListFiles(
AZStd::string_view{ AZ::Utils::GetEnginePath() },
m_guiApplicationManager->GetCurrentProjectName(),
m_guiApplicationManager->GetGemInfoList(), m_guiApplicationManager->GetEnabledPlatforms());
// Get the list of default Seeds that are not stored in a Seed List file on-disk
AZStd::vector<AZStd::string> defaultSeeds = GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_guiApplicationManager->GetCurrentProjectName());
m_fileTableModel->AddDefaultSeedsToInMemoryList(defaultSeeds, m_guiApplicationManager->GetCurrentProjectName().c_str(), m_guiApplicationManager->GetEnabledPlatforms());
AZStd::vector<AZStd::string> defaultSeeds =
GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_guiApplicationManager->GetCurrentProjectName());
m_fileTableModel->AddDefaultSeedsToInMemoryList(
defaultSeeds,
m_guiApplicationManager->GetCurrentProjectName().c_str(),
m_guiApplicationManager->GetEnabledPlatforms());
// Set the new watched filess for the model
m_watchedFiles.clear();
@@ -185,7 +208,9 @@ namespace AssetBundler
m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnCheckBox, config.checkBoxColumnWidth);
m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnProject, config.projectNameColumnWidth);
m_ui->seedFileContentsTable->header()->resizeSection(SeedListTableModel::Column::ColumnRelativePath, config.seedListContentsNameColumnWidth);
m_ui->seedFileContentsTable->header()->resizeSection(
SeedListTableModel::Column::ColumnRelativePath,
config.seedListContentsNameColumnWidth);
}
void SeedTabWidget::UncheckSelectDefaultSeedListsCheckBox()
@@ -198,15 +223,25 @@ namespace AssetBundler
m_ui->generateAssetListsButton->setEnabled(isEnabled);
}
bool SeedTabWidget::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/)
bool SeedTabWidget::OnPreError(
const char* /*window*/,
const char* /*fileName*/,
int /*line*/,
const char* /*func*/,
const char* /*message*/)
{
m_hasWarnings = true;
m_hasWarningsOrErrors = true;
return false;
}
bool SeedTabWidget::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/)
bool SeedTabWidget::OnPreWarning(
const char* /*window*/,
const char* /*fileName*/,
int /*line*/,
const char* /*func*/,
const char* /*message*/)
{
m_hasWarnings = true;
m_hasWarningsOrErrors = true;
return false;
}
@@ -275,11 +310,13 @@ namespace AssetBundler
return;
}
m_hasWarnings = false;
auto createdFiles = m_fileTableModel->GenerateAssetLists(m_generateAssetListsDialog->GetAbsoluteFilePath(), m_generateAssetListsDialog->GetPlatformFlags());
m_hasWarningsOrErrors = false;
auto createdFiles = m_fileTableModel->GenerateAssetLists(
m_generateAssetListsDialog->GetAbsoluteFilePath(),
m_generateAssetListsDialog->GetPlatformFlags());
// Warnings will not prevent the generation of Asset List files, we must track them separately
NewFileDialog::FileGenerationResultMessageBox(this, createdFiles, m_hasWarnings);
NewFileDialog::FileGenerationResultMessageBox(this, createdFiles, m_hasWarningsOrErrors);
if (createdFiles.empty())
{
@@ -306,7 +343,8 @@ namespace AssetBundler
}
// Get the current platforms of the selected Seed so we can display them as already checked
QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
QModelIndex currentSeedIndex =
m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex);
if (!getPlatformOutcome.IsSuccess())
{
@@ -375,7 +413,8 @@ namespace AssetBundler
AzFramework::PlatformFlags checkedPlatforms = m_editSeedDialog->GetPlatformFlags();
AzFramework::PlatformFlags partiallyCheckedPlatforms = m_editSeedDialog->GetPartiallySelectedPlatformFlags();
// If the platform is partially checked, we want to keep its original status when saving the changes
AzFramework::PlatformFlags platformFlags = indexToPlatformFlagsMap[currentSeedIndex] & partiallyCheckedPlatforms | checkedPlatforms;
AzFramework::PlatformFlags platformFlags =
indexToPlatformFlagsMap[currentSeedIndex] & partiallyCheckedPlatforms | checkedPlatforms;
m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, platformFlags);
}
@@ -391,8 +430,10 @@ namespace AssetBundler
// Get path to the platform-specific cache folder of one of the enabled platforms
AzFramework::PlatformFlags enabledPlatforms = m_guiApplicationManager->GetEnabledPlatforms();
AZStd::fixed_vector<AzFramework::PlatformId, AzFramework::PlatformId::NumPlatformIds> enabledPlatformIndices = AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(enabledPlatforms);
AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(enabledPlatformIndices[0]);
AZStd::fixed_vector<AzFramework::PlatformId, AzFramework::PlatformId::NumPlatformIds> enabledPlatformIndices =
AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(enabledPlatforms);
AZStd::string platformSpecificCachePath =
AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(enabledPlatformIndices[0]);
// Create and display the Add Seed Dialog
m_addSeedDialog.reset(new AddSeedDialog(this, enabledPlatforms, platformSpecificCachePath));
@@ -416,7 +457,8 @@ namespace AssetBundler
}
// Set the data in the model
QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
QModelIndex currentSeedIndex =
m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex());
m_fileTableModel->RemoveSeed(m_selectedFileTableIndex, currentSeedIndex);
}
@@ -82,7 +82,9 @@ namespace AssetBundler
void ApplyConfig() override;
void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override;
void FileSelectionChanged(
const QItemSelection& /*selected*/ = QItemSelection(),
const QItemSelection& /*deselected*/ = QItemSelection()) override;
void UncheckSelectDefaultSeedListsCheckBox();
@@ -124,6 +126,6 @@ namespace AssetBundler
QSharedPointer<EditSeedDialog> m_editSeedDialog;
QSharedPointer<AddSeedDialog> m_addSeedDialog;
bool m_hasWarnings = false;
bool m_hasWarningsOrErrors = false;
};
} // namespace AssetBundler
@@ -83,7 +83,8 @@ namespace AssetBundler
ConfigHelpers::read<int>(settings, QStringLiteral("AssetListFileNameColumnWidth"), config.assetListFileNameColumnWidth);
ConfigHelpers::read<int>(settings, QStringLiteral("AssetListPlatformColumnWidth"), config.assetListPlatformColumnWidth);
ConfigHelpers::read<int>(settings, QStringLiteral("ProductAssetNameColumnWidth"), config.productAssetNameColumnWidth);
ConfigHelpers::read<int>(settings, QStringLiteral("ProductAssetRelativePathColumnWidth"), config.productAssetRelativePathColumnWidth);
ConfigHelpers::read<int>(
settings, QStringLiteral("ProductAssetRelativePathColumnWidth"), config.productAssetRelativePathColumnWidth);
}
return config;
@@ -159,8 +160,7 @@ namespace AssetBundler
m_platformCatalogManager = AZStd::make_unique<AzToolsFramework::PlatformAddressedAssetCatalogManager>();
// Define some application-level settings
QApplication::setOrganizationName("Amazon");
QApplication::setOrganizationDomain("amazon.com");
QApplication::setOrganizationName("O3DE");
QApplication::setApplicationName("Asset Bundler");
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
@@ -194,7 +194,12 @@ namespace AssetBundler
engineRoot);
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:AssetBundler.qss"));
AzQtComponents::ConfigHelpers::loadConfig<Config, GUIApplicationManager>(&m_fileWatcher, &m_config, QStringLiteral("style:AssetBundlerConfig.ini"), this, std::bind(&GUIApplicationManager::ApplyConfig, this));
AzQtComponents::ConfigHelpers::loadConfig<Config, GUIApplicationManager>(
&m_fileWatcher,
&m_config,
QStringLiteral("style:AssetBundlerConfig.ini"),
this,
std::bind(&GUIApplicationManager::ApplyConfig, this));
ApplyConfig();
qApp->setWindowIcon(QIcon("style:AssetBundler-Icon-256x256@x2.ico"));
@@ -238,7 +243,12 @@ namespace AssetBundler
m_fileWatcher.removePaths(paths.values());
}
bool GUIApplicationManager::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message)
bool GUIApplicationManager::OnPreError(
const char* /*window*/,
const char* /*fileName*/,
int /*line*/,
const char* /*func*/,
const char* message)
{
// We want to display errors during initialization, then let the MainWindow handle errors during runtime
if (m_isInitializing)
@@ -258,7 +268,12 @@ namespace AssetBundler
return false;
}
bool GUIApplicationManager::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/)
bool GUIApplicationManager::OnPreWarning(
const char* /*window*/,
const char* /*fileName*/,
int /*line*/,
const char* /*func*/,
const char* /*message*/)
{
// Don't handle warnings, let the MainWindow print them
return false;
+34 -38
View File
@@ -155,8 +155,10 @@ namespace AssetBundler
if (fileIO->Exists(platformDirectory.c_str()))
{
bool recurse = true;
AZ::Outcome<AZStd::list<AZStd::string>, AZStd::string> result = AzFramework::FileFunc::FindFileList(platformDirectory.String(),
AZStd::string::format("*.%s", AzToolsFramework::AssetSeedManager::GetSeedFileExtension()).c_str(), recurse);
AZ::Outcome<AZStd::list<AZStd::string>, AZStd::string> result = AzFramework::FileFunc::FindFileList(
platformDirectory.String(),
AZStd::string::format("*.%s", AzToolsFramework::AssetSeedManager::GetSeedFileExtension()).c_str(),
recurse);
if (result.IsSuccess())
{
@@ -233,8 +235,11 @@ namespace AssetBundler
return platformFlags;
}
AZStd::unordered_map<AZStd::string, AZStd::string> GetDefaultSeedListFiles(AZStd::string_view enginePath, AZStd::string_view projectPath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlag)
AZStd::unordered_map<AZStd::string, AZStd::string> GetDefaultSeedListFiles(
AZStd::string_view enginePath,
AZStd::string_view projectPath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlag)
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "AZ::IO::FileIOBase must be ready for use.\n");
@@ -299,7 +304,9 @@ namespace AssetBundler
return relativeProductPath;
}
AZStd::unordered_map<AZStd::string, AZStd::string> GetGemSeedListFilePathToGemNameMap(const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlags)
AZStd::unordered_map<AZStd::string, AZStd::string> GetGemSeedListFilePathToGemNameMap(
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlags)
{
AZStd::unordered_map<AZStd::string, AZStd::string> filePathToGemNameMap;
for (const AzFramework::GemInfo& gemInfo : gemInfoList)
@@ -325,7 +332,11 @@ namespace AssetBundler
return filePathToGemNameMap;
}
bool IsGemSeedFilePathValid(AZStd::string_view engineRoot, AZStd::string seedAbsoluteFilePath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlags)
bool IsGemSeedFilePathValid(
AZStd::string_view engineRoot,
AZStd::string seedAbsoluteFilePath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlags)
{
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "AZ::IO::FileIOBase must be ready for use.\n");
@@ -369,7 +380,10 @@ namespace AssetBundler
return false;
}
AzFramework::PlatformFlags GetEnabledPlatformFlags(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath)
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view engineRoot,
AZStd::string_view assetRoot,
AZStd::string_view projectPath)
{
auto settingsRegistry = AZ::SettingsRegistry::Get();
if (settingsRegistry == nullptr)
@@ -391,7 +405,8 @@ namespace AssetBundler
}
else
{
AZ_Warning(AssetBundler::AppWindowName, false, "Platform Helper is not aware of the platform (%s).\n ", enabledPlatform.c_str());
AZ_Warning(AssetBundler::AppWindowName, false,
"Platform Helper is not aware of the platform (%s).\n ", enabledPlatform.c_str());
}
}
@@ -457,31 +472,6 @@ namespace AssetBundler
AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder));
}
AZ::Outcome<void, AZStd::string> GetPlatformNamesFromCacheFolder(AZStd::vector<AZStd::string>& platformNames)
{
AZ::Outcome<AZ::IO::Path, AZStd::string> projectCacheRootFolder = GetProjectCacheFolderPath();
if (!projectCacheRootFolder)
{
return AZ::Failure(projectCacheRootFolder.TakeError());
}
const AZStd::string& projectCacheRootPath = projectCacheRootFolder.GetValue().Native();
QDir projectCacheDir(QString::fromUtf8(projectCacheRootPath.c_str(), aznumeric_cast<int>(projectCacheRootPath.size())));
auto tempPlatformList = projectCacheDir.entryList(QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot);
if (tempPlatformList.empty())
{
return AZ::Failure(AZStd::string("Cache is empty. Please run the Open 3D Engine Asset Processor to generate a Cache and build assets."));
}
for (const QString& platform : tempPlatformList)
{
platformNames.push_back(AZStd::string(platform.toUtf8().data()));
}
return AZ::Success();
}
AZ::Outcome<AZ::IO::Path, AZStd::string> GetAssetCatalogFilePath()
{
AZ::IO::Path assetCatalogFilePath = GetPlatformSpecificCacheFolderPath();
@@ -501,7 +491,9 @@ namespace AssetBundler
AZ::IO::Path platformSpecificCacheFolderPath;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(platformSpecificCacheFolderPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder);
settingsRegistry->Get(
platformSpecificCacheFolderPath.Native(),
AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder);
}
return platformSpecificCacheFolderPath;
}
@@ -701,7 +693,8 @@ namespace AssetBundler
m_errors.swap(AZStd::vector<AZStd::string>());
}
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::ComparisonType, AZStd::string> ParseComparisonType(const AZStd::string& comparisonType)
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::ComparisonType, AZStd::string> ParseComparisonType(
const AZStd::string& comparisonType)
{
using namespace AzToolsFramework;
@@ -729,7 +722,8 @@ namespace AssetBundler
}
// Failure case
AZStd::string failureMessage = AZStd::string::format("Invalid Comparison Type ( %s ). Valid types are: ", comparisonType.c_str());
AZStd::string failureMessage = AZStd::string::format(
"Invalid Comparison Type ( %s ). Valid types are: ", comparisonType.c_str());
for (size_t i = 0; i < numTypes - 1; ++i)
{
failureMessage.append(AZStd::string::format("%s, ", AssetFileInfoListComparison::ComparisonTypeNames[i]));
@@ -738,7 +732,8 @@ namespace AssetBundler
return AZ::Failure(failureMessage);
}
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::FilePatternType, AZStd::string> ParseFilePatternType(const AZStd::string& filePatternType)
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::FilePatternType, AZStd::string> ParseFilePatternType(
const AZStd::string& filePatternType)
{
using namespace AzToolsFramework;
@@ -766,7 +761,8 @@ namespace AssetBundler
}
// Failure case
AZStd::string failureMessage = AZStd::string::format("Invalid File Pattern Type ( %s ). Valid types are: ", filePatternType.c_str());
AZStd::string failureMessage = AZStd::string::format(
"Invalid File Pattern Type ( %s ). Valid types are: ", filePatternType.c_str());
for (size_t i = 0; i < numTypes - 1; ++i)
{
failureMessage.append(AZStd::string::format("%s, ", AssetFileInfoListComparison::FilePatternTypeNames[i]));
+26 -19
View File
@@ -158,17 +158,6 @@ namespace AssetBundler
*/
AZ::Outcome<AZ::IO::Path, AZStd::string> GetProjectCacheFolderPath();
/**
* Calculates the list of enabled platforms for the input project by reading the folder names inside the project-specific cache folder.
* If the Asset Processor has not been run yet, or has not been run since the enabled platform list inside AssetProcessorPlatformConfig.setreg
* was changed, the output of this function will be incorrect.
*
* @param projectCacheFolder The directory of a project-specific cache folder: /ProjectPath/Cache
* @param platformNames [out] The list of platforms enabled in the project
* @return void on success, error message on failure
*/
AZ::Outcome<void, AZStd::string> GetPlatformNamesFromCacheFolder(AZStd::vector<AZStd::string>& platformNames);
/**
* Computes the absolute path to the Asset Catalog file for a specified project and platform.
* With platform set as "pc" and project as "ProjectName", the path will resemble: C:/ProjectPath/Cache/pc/assetcatalog.xml
@@ -204,8 +193,11 @@ namespace AssetBundler
AzFramework::PlatformFlags GetPlatformsOnDiskForPlatformSpecificFile(const AZStd::string& platformIndependentAbsolutePath);
//! Returns a map of <absolute file path, source folder display name> of all default Seed List files for the current game project.
AZStd::unordered_map<AZStd::string, AZStd::string> GetDefaultSeedListFiles(AZStd::string_view enginePath, AZStd::string_view projectPath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlags);
AZStd::unordered_map<AZStd::string, AZStd::string> GetDefaultSeedListFiles(
AZStd::string_view enginePath,
AZStd::string_view projectPath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlags);
//! Returns a vector of relative paths to Assets that should be included as default Seeds, but are not already in a Seed List file.
AZStd::vector<AZStd::string> GetDefaultSeeds(AZStd::string_view projectPath, AZStd::string_view projectName);
@@ -217,15 +209,24 @@ namespace AssetBundler
AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view projectPath, AZStd::string_view projectName);
//! Returns the map from gem seed list file path to gem name
AZStd::unordered_map<AZStd::string, AZStd::string> GetGemSeedListFilePathToGemNameMap(const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlags);
AZStd::unordered_map<AZStd::string, AZStd::string> GetGemSeedListFilePathToGemNameMap(
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlags);
//! Given an absolute gem seed file path determines whether the file is valid for the current game project.
//! This method is for validating gem seed list files only.
bool IsGemSeedFilePathValid(AZStd::string_view enginePath, AZStd::string seedAbsoluteFilePath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AzFramework::PlatformFlags platformFlags);
bool IsGemSeedFilePathValid(
AZStd::string_view enginePath,
AZStd::string seedAbsoluteFilePath,
const AZStd::vector<AzFramework::GemInfo>& gemInfoList,
AzFramework::PlatformFlags platformFlags);
//! Returns platformFlags of all enabled platforms by parsing all the asset processor config files.
//! Please note that the game project could be in a different location to the engine therefore we need the assetRoot param.
AzFramework::PlatformFlags GetEnabledPlatformFlags(AZStd::string_view enginePath, AZStd::string_view assetRoot, AZStd::string_view projectPath);
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view enginePath,
AZStd::string_view assetRoot,
AZStd::string_view projectPath);
QJsonObject ReadJson(const AZStd::string& filePath);
void SaveJson(const AZStd::string& filePath, const QJsonObject& jsonObject);
@@ -239,7 +240,11 @@ namespace AssetBundler
{
public:
AZ_CLASS_ALLOCATOR(FilePath, AZ::SystemAllocator, 0);
explicit FilePath(const AZStd::string& filePath, AZStd::string platformIdentifier = AZStd::string(), bool checkFileCase = false, bool ignoreFileCase = false);
explicit FilePath(
const AZStd::string& filePath,
AZStd::string platformIdentifier = AZStd::string(),
bool checkFileCase = false,
bool ignoreFileCase = false);
explicit FilePath(const AZStd::string& filePath, bool checkFileCase, bool ignoreFileCase);
FilePath() = default;
const AZStd::string& AbsolutePath() const;
@@ -279,8 +284,10 @@ namespace AssetBundler
bool m_reportingError = false;
};
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::ComparisonType, AZStd::string> ParseComparisonType(const AZStd::string& comparisonType);
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::FilePatternType, AZStd::string> ParseFilePatternType(const AZStd::string& filePatternType);
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::ComparisonType, AZStd::string> ParseComparisonType(
const AZStd::string& comparisonType);
AZ::Outcome<AzToolsFramework::AssetFileInfoListComparison::FilePatternType, AZStd::string> ParseFilePatternType(
const AZStd::string& filePatternType);
bool LooksLikePath(const AZStd::string& inputString);
bool LooksLikeWildcardPattern(const AZStd::string& inputPattern);
}
@@ -1,47 +0,0 @@
/*
* 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 <GemCatalog.h>
#include <Source/ui_GemCatalog.h>
namespace O3DE::ProjectManager
{
GemCatalog::GemCatalog(ProjectManagerWindow* window)
: ScreenWidget(window)
, m_ui(new Ui::GemCatalogClass())
{
m_ui->setupUi(this);
ConnectSlotsAndSignals();
}
GemCatalog::~GemCatalog()
{
}
void GemCatalog::ConnectSlotsAndSignals()
{
QObject::connect(m_ui->backButton, &QPushButton::pressed, this, &GemCatalog::HandleBackButton);
QObject::connect(m_ui->confirmButton, &QPushButton::pressed, this, &GemCatalog::HandleConfirmButton);
}
void GemCatalog::HandleBackButton()
{
m_projectManagerWindow->ChangeToScreen(ProjectManagerScreen::NewProjectSettings);
}
void GemCatalog::HandleConfirmButton()
{
m_projectManagerWindow->ChangeToScreen(ProjectManagerScreen::ProjectsHome);
}
} // namespace O3DE::ProjectManager
@@ -1,231 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GemCatalogClass</class>
<widget class="QWidget" name="GemCatalogClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>806</width>
<height>566</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Gem Catalog</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="toolButton">
<property name="text">
<string>Cart</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_2">
<property name="text">
<string>Hamburger Menu</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_2">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_3">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_3">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="listWidget_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Atom</string>
</property>
</item>
<item>
<property name="text">
<string>Audio</string>
</property>
</item>
<item>
<property name="text">
<string>Camera</string>
</property>
</item>
<item>
<property name="text">
<string>PhysX</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="backButton">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="confirmButton">
<property name="text">
<string>Create Project</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,103 @@
/*
* 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 <GemCatalog/GemCatalog.h>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
namespace O3DE::ProjectManager
{
GemCatalog::GemCatalog(ProjectManagerWindow* window)
: ScreenWidget(window)
{
ConnectSlotsAndSignals();
m_gemModel = new GemModel(this);
QVBoxLayout* vLayout = new QVBoxLayout();
setLayout(vLayout);
QHBoxLayout* hLayout = new QHBoxLayout();
vLayout->addLayout(hLayout);
QWidget* filterPlaceholderWidget = new QWidget();
filterPlaceholderWidget->setFixedWidth(250);
hLayout->addWidget(filterPlaceholderWidget);
m_gemListView = new GemListView(m_gemModel, this);
hLayout->addWidget(m_gemListView);
QWidget* inspectorPlaceholderWidget = new QWidget();
inspectorPlaceholderWidget->setFixedWidth(250);
hLayout->addWidget(inspectorPlaceholderWidget);
// Temporary back and next buttons until they are centralized and shared.
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
vLayout->addWidget(backNextButtons);
QPushButton* tempBackButton = backNextButtons->addButton("Back", QDialogButtonBox::RejectRole);
QPushButton* tempNextButton = backNextButtons->addButton("Next", QDialogButtonBox::AcceptRole);
connect(tempBackButton, &QPushButton::pressed, this, &GemCatalog::HandleBackButton);
connect(tempNextButton, &QPushButton::pressed, this, &GemCatalog::HandleConfirmButton);
// Start: Temporary gem test data
{
m_gemModel->AddGem(GemInfo("EMotion FX",
"O3DE Foundation",
"EMFX is a real-time character animation system. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
(GemInfo::Android | GemInfo::iOS | GemInfo::Windows | GemInfo::Linux),
true));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Atom",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
true));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("PhysX",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Android | GemInfo::Linux,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Certificate Manager",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Windows,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Cloud Gem Framework",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::iOS | GemInfo::Linux,
false));
m_gemModel->AddGem(O3DE::ProjectManager::GemInfo("Achievements",
"O3DE Foundation",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
GemInfo::Android | GemInfo::Windows | GemInfo::Linux,
false));
}
// End: Temporary gem test data
}
void GemCatalog::HandleBackButton()
{
m_projectManagerWindow->ChangeToScreen(ProjectManagerScreen::NewProjectSettings);
}
void GemCatalog::HandleConfirmButton()
{
m_projectManagerWindow->ChangeToScreen(ProjectManagerScreen::ProjectsHome);
}
} // namespace O3DE::ProjectManager
@@ -13,32 +13,25 @@
#if !defined(Q_MOC_RUN)
#include <ScreenWidget.h>
#include <GemCatalog/GemListView.h>
#include <GemCatalog/GemModel.h>
#endif
namespace Ui
{
class GemCatalogClass;
}
namespace O3DE::ProjectManager
{
class GemCatalog
: public ScreenWidget
{
public:
explicit GemCatalog(ProjectManagerWindow* window);
~GemCatalog();
protected:
void ConnectSlotsAndSignals() override;
~GemCatalog() = default;
protected slots:
void HandleBackButton();
void HandleConfirmButton();
private:
QScopedPointer<Ui::GemCatalogClass> m_ui;
GemListView* m_gemListView = nullptr;
GemModel* m_gemModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,25 @@
/*
* 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 "GemInfo.h"
namespace O3DE::ProjectManager
{
GemInfo::GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded)
: m_name(name)
, m_creator(creator)
, m_summary(summary)
, m_platforms(platforms)
, m_isAdded(isAdded)
{
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,55 @@
/*
* 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
#if !defined(Q_MOC_RUN)
#include <AzCore/Math/Uuid.h>
#include <QString>
#include <QStringList>
#include <QVector>
#endif
namespace O3DE::ProjectManager
{
class GemInfo
{
public:
enum Platform
{
Android = 0x0,
iOS = 0x1,
Linux = 0x2,
macOS = 0x3,
Windows = 0x4
};
Q_DECLARE_FLAGS(Platforms, Platform)
GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded);
QString m_name;
QString m_displayName;
AZ::Uuid m_uuid;
QString m_creator;
bool m_isAdded = false; //! Is the gem currently added and enabled in the project?
QString m_summary;
Platforms m_platforms;
QStringList m_features;
QString m_version;
QString m_lastUpdatedDate;
QString m_documentationUrl;
QVector<AZ::Uuid> m_dependingGemUuids;
QVector<AZ::Uuid> m_conflictingGemUuids;
};
} // namespace O3DE::ProjectManager
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::Platforms)
@@ -0,0 +1,135 @@
/*
* 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 "GemItemDelegate.h"
#include "GemModel.h"
#include <QEvent>
#include <QPainter>
#include <QMouseEvent>
namespace O3DE::ProjectManager
{
GemItemDelegate::GemItemDelegate(GemModel* gemModel, QObject* parent)
: QStyledItemDelegate(parent)
, m_gemModel(gemModel)
{
}
void GemItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
{
if (!modelIndex.isValid())
{
return;
}
QStyleOptionViewItem options(option);
initStyleOption(&options, modelIndex);
painter->setRenderHint(QPainter::Antialiasing);
QRect fullRect, itemRect, contentRect;
CalcRects(options, modelIndex, fullRect, itemRect, contentRect);
QFont standardFont(options.font);
standardFont.setPixelSize(s_fontSize);
painter->save();
painter->setClipping(true);
painter->setClipRect(fullRect);
painter->setFont(options.font);
// Draw background
painter->fillRect(fullRect, m_backgroundColor);
// Draw item background
const QColor itemBackgroundColor = options.state & QStyle::State_MouseOver ? m_itemBackgroundColor.lighter(120) : m_itemBackgroundColor;
painter->fillRect(itemRect, itemBackgroundColor);
// Draw border
if (options.state & QStyle::State_Selected)
{
painter->save();
QPen borderPen(m_borderColor);
borderPen.setWidth(s_borderWidth);
painter->setPen(borderPen);
painter->drawRect(itemRect);
painter->restore();
}
// Gem name
const QString gemName = m_gemModel->GetName(modelIndex);
QFont gemNameFont(options.font);
gemNameFont.setPixelSize(s_gemNameFontSize);
gemNameFont.setBold(true);
QRect gemNameRect = GetTextRect(gemNameFont, gemName, s_gemNameFontSize);
gemNameRect.moveTo(contentRect.left(), contentRect.top());
painter->setFont(gemNameFont);
painter->setPen(m_textColor);
painter->drawText(gemNameRect, Qt::TextSingleLine, gemName);
// Gem creator
const QString gemCreator = m_gemModel->GetCreator(modelIndex);
QRect gemCreatorRect = GetTextRect(standardFont, gemCreator, s_fontSize);
gemCreatorRect.moveTo(contentRect.left(), contentRect.top() + gemNameRect.height());
painter->setFont(standardFont);
painter->setPen(m_linkColor);
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right() * 4, contentRect.height());
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
painter->setPen(m_textColor);
const QString summary = m_gemModel->GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
painter->restore();
}
QSize GemItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const
{
QStyleOptionViewItem options(option);
initStyleOption(&options, modelIndex);
int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right();
return QSize(marginsHorizontal + s_summaryStartX, s_height);
}
bool GemItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex)
{
if (!modelIndex.isValid())
{
return false;
}
return QStyledItemDelegate::editorEvent(event, model, option, modelIndex);
}
void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const
{
const bool isFirst = modelIndex.row() == 0;
outFullRect = QRect(option.rect);
outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), isFirst ? s_itemMargins.top() * 2 : s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom()));
outContentRect = QRect(outItemRect.adjusted(s_contentMargins.left(), s_contentMargins.top(), -s_contentMargins.right(), -s_contentMargins.bottom()));
}
QRect GemItemDelegate::GetTextRect(QFont& font, const QString& text, qreal fontSize) const
{
font.setPixelSize(fontSize);
return QFontMetrics(font).boundingRect(text);
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,62 @@
/*
* 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
#if !defined(Q_MOC_RUN)
#include <QStyledItemDelegate>
#include "GemInfo.h"
#include "GemModel.h"
#endif
QT_FORWARD_DECLARE_CLASS(QEvent)
namespace O3DE::ProjectManager
{
class GemItemDelegate
: public QStyledItemDelegate
{
Q_OBJECT // AUTOMOC
public:
explicit GemItemDelegate(GemModel* gemModel, QObject* parent = nullptr);
~GemItemDelegate() = default;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
private:
void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
GemModel* m_gemModel = nullptr;
// Colors
const QColor m_textColor = QColor("#FFFFFF");
const QColor m_linkColor = QColor("#94D2FF");
const QColor m_backgroundColor = QColor("#333333"); // Outside of the actual gem item
const QColor m_itemBackgroundColor = QColor("#404040"); // Background color of the gem item
const QColor m_borderColor = QColor("#1E70EB");
// Item
inline constexpr static int s_height = 140; // Gem item total height
inline constexpr static qreal s_gemNameFontSize = 16.0;
inline constexpr static qreal s_fontSize = 15.0;
inline constexpr static int s_summaryStartX = 200;
// Margin and borders
inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/20, /*top=*/10, /*right=*/20, /*bottom=*/10); // Item border distances
inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/15, /*top=*/12, /*right=*/12, /*bottom=*/12); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,34 @@
/*
* 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 "GemListView.h"
#include "GemItemDelegate.h"
#include <QStandardItemModel>
#include <QDateTime>
#include <QPalette>
namespace O3DE::ProjectManager
{
GemListView::GemListView(GemModel* model, QWidget *parent) :
QListView(parent)
{
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPalette palette;
palette.setColor(QPalette::Window, QColor("#333333"));
setPalette(palette);
setModel(model);
setSelectionModel(model->GetSelectionModel());
setItemDelegate(new GemItemDelegate(model, this));
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,31 @@
/*
* 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
#if !defined(Q_MOC_RUN)
#include "GemInfo.h"
#include "GemModel.h"
#include <QListView>
#endif
namespace O3DE::ProjectManager
{
class GemListView
: public QListView
{
Q_OBJECT // AUTOMOC
public:
explicit GemListView(GemModel* model, QWidget *parent = nullptr);
~GemListView() = default;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,72 @@
/*
* 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 "GemModel.h"
namespace O3DE::ProjectManager
{
GemModel::GemModel(QObject* parent)
: QStandardItemModel(parent)
{
m_selectionModel = new QItemSelectionModel(this, parent);
}
QItemSelectionModel* GemModel::GetSelectionModel() const
{
return m_selectionModel;
}
void GemModel::AddGem(const GemInfo& gemInfo)
{
QStandardItem* item = new QStandardItem();
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
item->setData(gemInfo.m_name, RoleName);
item->setData(gemInfo.m_creator, RoleCreator);
item->setData(static_cast<int>(gemInfo.m_platforms), RolePlatforms);
item->setData(gemInfo.m_summary, RoleSummary);
item->setData(gemInfo.m_isAdded, RoleIsAdded);
appendRow(item);
}
void GemModel::Clear()
{
clear();
}
QString GemModel::GetName(const QModelIndex& modelIndex) const
{
return modelIndex.data(RoleName).toString();
}
QString GemModel::GetCreator(const QModelIndex& modelIndex) const
{
return modelIndex.data(RoleCreator).toString();
}
int GemModel::GetPlatforms(const QModelIndex& modelIndex) const
{
return static_cast<GemInfo::Platforms>(modelIndex.data(RolePlatforms).toInt());
}
QString GemModel::GetSummary(const QModelIndex& modelIndex) const
{
return modelIndex.data(RoleSummary).toString();
}
bool GemModel::IsAdded(const QModelIndex& modelIndex) const
{
return modelIndex.data(RoleIsAdded).toBool();
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,53 @@
/*
* 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
#if !defined(Q_MOC_RUN)
#include "GemInfo.h"
#include <QStandardItemModel>
#include <QItemSelectionModel>
#endif
namespace O3DE::ProjectManager
{
class GemModel
: public QStandardItemModel
{
Q_OBJECT // AUTOMOC
public:
explicit GemModel(QObject* parent = nullptr);
QItemSelectionModel* GetSelectionModel() const;
void AddGem(const GemInfo& gemInfo);
void Clear();
QString GetName(const QModelIndex& modelIndex) const;
QString GetCreator(const QModelIndex& modelIndex) const;
int GetPlatforms(const QModelIndex& modelIndex) const;
QString GetSummary(const QModelIndex& modelIndex) const;
bool IsAdded(const QModelIndex& modelIndex) const;
private:
enum UserRole
{
RoleName = Qt::UserRole,
RoleCreator,
RolePlatforms,
RoleSummary,
RoleIsAdded
};
QItemSelectionModel* m_selectionModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -13,7 +13,7 @@
#include <FirstTimeUse.h>
#include <NewProjectSettings.h>
#include <GemCatalog.h>
#include <GemCatalog/GemCatalog.h>
#include <ProjectsHome.h>
#include <ProjectSettings.h>
#include <EngineSettings.h>

Some files were not shown because too many files have changed in this diff Show More