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

main
greerdv 5 years ago
commit e497b7ac33

1
.gitignore vendored

@ -18,3 +18,4 @@ _savebackup/
#Output folder for test results when running Automated Tests
TestResults/**
*.swatches
/imgui.ini

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:171f38d536d7b805cc644513d22dae5552a4eef2bffb88e97e089898cf769530
size 2126

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6388466c97009fd3993e5d3b59a2b0961f623c6becbd0a12a0a5eb7bd8da5d4e
size 12302

@ -12,4 +12,5 @@
set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Private
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_Null.Private
)

@ -15,5 +15,7 @@ set(GEM_DEPENDENCIES
Gem::Atom_RHI_Vulkan.Builders
Gem::Atom_RHI_DX12.Private
Gem::Atom_RHI_DX12.Builders
Gem::Atom_RHI_Null.Private
Gem::Atom_RHI_Null.Builders
Gem::Atom_RHI_Metal.Builders
)

@ -42,7 +42,6 @@ set(GEM_DEPENDENCIES
Gem::SurfaceData
Gem::GradientSignal
Gem::Vegetation
Gem::Atom_RHI.Private
Gem::Atom_RPI.Private
Gem::Atom_Feature_Common
@ -54,4 +53,5 @@ set(GEM_DEPENDENCIES
Gem::ImguiAtom
Gem::Atom_AtomBridge
Gem::AtomFont
Gem::Blast
)

@ -68,4 +68,5 @@ set(GEM_DEPENDENCIES
Gem::ImguiAtom
Gem::AtomFont
Gem::AtomToolsFramework.Editor
Gem::Blast.Editor
)

@ -27,28 +27,28 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def test_ActorSplitsAfterCollision(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterCollision as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterRadialDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterRadialDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterCapsuleDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterCapsuleDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterImpactSpreadDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterImpactSpreadDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterShearDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterShearDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterTriangleDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterTriangleDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterStressDamage(self, request, workspace, editor, launcher_platform):
from . import ActorSplitsAfterStressDamage as test_module
self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"])
self._run_test(request, workspace, editor, test_module)

@ -135,20 +135,19 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
endif()
## Blast ##
# Disabled until AutomatedTesting runs with Atom.
# if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
# ly_add_pytest(
# NAME AutomatedTesting::BlastTests
# TEST_SERIAL TRUE
# PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
# TIMEOUT 500
# RUNTIME_DEPENDENCIES
# Legacy::Editor
# Legacy::CryRenderNULL
# AZ::AssetProcessor
# AutomatedTesting.Assets
# )
# endif()
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::BlastTests
TEST_SUITE sandbox
TEST_SERIAL TRUE
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
TIMEOUT 3600
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
)
endif()
#############

@ -77,13 +77,13 @@ class TestImageGradient(EditorTestHelper):
# 3) Assign the processed gradient signal image as the Image Gradient's image asset and verify success
# First, check for the base image in the workspace
base_image = "lumberyard_gsi.png"
base_image = "image_grad_test_gsi.png"
base_image_path = os.path.join("AutomatedTesting", "Assets", "ImageGradients", base_image)
if os.path.isfile(base_image_path):
print(f"{base_image} was found in the workspace")
# Next, assign the processed image to the Image Gradient's Image Asset property
processed_image_path = os.path.join("Assets", "ImageGradients", "lumberyard_gsi.gradimage")
processed_image_path = os.path.join("Assets", "ImageGradients", "image_grad_test_gsi.gradimage")
asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", processed_image_path, math.Uuid(),
False)
hydra.get_set_test(image_gradient_entity, 0, "Configuration|Image Asset", asset_id)

@ -57,7 +57,7 @@ class TestImageGradientRequiresShape(object):
"Entity has a Image Gradient component",
"Entity has a Gradient Transform Modifier component",
"Entity has a Box Shape component",
"lumberyard_gsi.png was found in the workspace",
"image_grad_test_gsi.png was found in the workspace",
"Entity Configuration|Image Asset: SUCCESS",
"ImageGradient_ProcessedImageAssignedSucessfully: result=SUCCESS",
]

@ -1,6 +1,6 @@
<ObjectStream version="3">
<Class name="BlastGlobalConfiguration" version="1" type="{0B9DB6DD-0008-4EF6-9D75-141061144353}">
<Class name="Asset" field="BlastMaterialLibrary" value="id={251AC171-6B9C-562D-A235-4EF5E1AE6871}:0,type={55F38C86-0767-4E7F-830A-A4BF624BE4DA},hint={assets/destruction/automated_testing.blastmaterial}" version="1" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
<Class name="Asset" field="BlastMaterialLibrary" value="id={251AC171-6B9C-562D-A235-4EF5E1AE6871}:0,type={55F38C86-0767-4E7F-830A-A4BF624BE4DA},hint={assets/destruction/automated_testing.blastmaterial},loadBehavior=1" version="2" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
<Class name="unsigned int" field="StressSolverIterations" value="180" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
</ObjectStream>

@ -23,15 +23,11 @@ endif()
include(cmake/Version.cmake)
set(INSTALLED_ENGINE TRUE)
if(NOT PROJECT_NAME)
project(O3DE
LANGUAGES C CXX
VERSION ${LY_VERSION_STRING}
)
set(INSTALLED_ENGINE FALSE)
endif()
include(cmake/Initialize.cmake)

@ -19,6 +19,7 @@
#include <AzCore/Component/EntityId.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <Range.h>
#include <AnimKey.h>
@ -914,9 +915,18 @@ struct IAnimStringTable
*/
struct IAnimSequence
{
AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}")
AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}");
AZ_CLASS_ALLOCATOR(IAnimSequence, AZ::SystemAllocator, 0);
static const int kSequenceVersion = 4;
static const int kSequenceVersion = 5;
static void Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
{
serializeContext->Class<IAnimSequence>();
}
}
//! Flags used for SetFlags(),GetFlags(),SetParentFlags(),GetParentFlags() methods.
enum EAnimSequenceFlags

@ -274,6 +274,10 @@ void PerInstanceConstantBufferPool::SetConstantBuffer(SRendItem* renderItem)
deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex);
deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex);
#else
AZ::u32 itemIndex = directId % SPI_NUM_INSTS_PER_CB;
AZ::u32 first[1] = {itemIndex * static_cast<AZ::u32>(sizeof(HLSL_PerInstanceConstantBuffer))};
AZ::u32 count[1] = {static_cast<AZ::u32>(sizeof(HLSL_PerInstanceConstantBuffer))};
deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]);
deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]);
#endif

@ -755,6 +755,7 @@ lSysUpdate:
buffer_handle_t nVB = ~0u;
# if BUFFER_ENABLE_DIRECT_ACCESS && !defined(NULL_RENDERER)
nVB = MS->m_nID;
int nFrame = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nFillThreadID].m_nFrameUpdateID;
if ((nVB != ~0u && (MS->m_nFrameCreate != nFrame || MS->m_nElements != m_nVerts)) || !CRenderer::CV_r_buffer_enable_lockless_updates)
# endif
goto lSysCreate;

@ -178,14 +178,16 @@ namespace AZ
//! on an update to '/Amazon/AzCore/Bootstrap/project_path' key.
struct UpdateProjectSettingsEventHandler
{
UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry)
UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
: m_registry{ registry }
, m_commandLine{ commandLine }
{
}
void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
// #1 Update the project settings when the project path is set
const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
AZ::IO::FixedMaxPath newProjectPath;
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path)
@ -194,6 +196,7 @@ namespace AZ
UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath));
}
// #2 Update the project specialization when the project name is set
const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name";
FixedValueString newProjectName;
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path)
@ -201,6 +204,12 @@ namespace AZ
{
UpdateProjectSpecializationFromProjectName(newProjectName);
}
// #3 Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry
if (path == AZ::SettingsRegistryMergeUtils::CommandLineValueChangedKey)
{
UpdateCommandLine();
}
}
//! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path
@ -233,10 +242,16 @@ namespace AZ
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
}
void UpdateCommandLine()
{
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine);
}
private:
AZ::IO::FixedMaxPath m_oldProjectPath;
AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName;
AZ::SettingsRegistryInterface& m_registry;
AZ::CommandLine& m_commandLine;
};
void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app)
@ -415,6 +430,12 @@ namespace AZ
// Add the Command Line arguments into the SettingsRegistry
SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine);
// Add a notifier to update the project_settings when
// 1. The 'project_path' key changes
// 2. The project specialization when the 'project-name' key changes
// 3. The ComponentApplication command line when the command line is stored to the registry
m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry, m_commandLine });
// Merge Command Line arguments
constexpr bool executeRegDumpCommands = false;
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
@ -429,10 +450,6 @@ namespace AZ
// for the application root.
CalculateAppRoot();
// Add a notifier to update the /Amazon/AzCore/Settings/Specializations
// when the 'project_path' property changes within the SettingsRegistry
m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry });
// Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
@ -909,6 +926,8 @@ namespace AZ
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
#endif
// Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
}
void ComponentApplication::SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations)

@ -19,9 +19,6 @@ namespace AZ
{
class Vector3;
//! Do not allow the scale to be zero to avoid problems with inverting scale.
static constexpr float MinNonUniformScale = 1e-3f;
using NonUniformScaleChangedEvent = AZ::Event<const AZ::Vector3&>;
//! Requests for working with non-uniform scale.

@ -26,7 +26,7 @@ namespace AZ
{
class Transform;
using TransformChangedEvent = Event<Transform, Transform>;
using TransformChangedEvent = Event<const Transform&, const Transform&>;
using ParentChangedEvent = Event<EntityId, EntityId>;

@ -38,6 +38,13 @@ namespace AZ
bool CompareValueData(const void* lhs, const void* rhs) override;
};
//! Limits for transform scale values.
//! The scale should not be zero to avoid problems with inverting.
//! @{
static constexpr float MinTransformScale = 1e-2f;
static constexpr float MaxTransformScale = 1e9f;
//! @}
//! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation.
//! By design, cannot represent skew transformations.
class Transform

@ -167,14 +167,14 @@ namespace AZ
}
}
AZ_MATH_INLINE Vector2::Vector2(const Vector3& source)
Vector2::Vector2(const Vector3& source)
: m_x(source.GetX())
, m_y(source.GetY())
{
}
AZ_MATH_INLINE Vector2::Vector2(const Vector4& source)
Vector2::Vector2(const Vector4& source)
: m_x(source.GetX())
, m_y(source.GetY())
{

@ -0,0 +1,340 @@
/*
* 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/PlatformId/PlatformDefaults.h>
#include <AzCore/StringFunc/StringFunc.h>
namespace AZ
{
inline namespace PlatformDefaults
{
static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient };
const char* PlatformIdToPalFolder(AZ::PlatformId platform)
{
#ifdef IOS
#define AZ_REDEFINE_IOS_AT_END IOS
#undef IOS
#endif
switch (platform)
{
case AZ::PC:
return "PC";
case AZ::ES3:
return "Android";
case AZ::IOS:
return "iOS";
case AZ::OSX:
return "Mac";
case AZ::PROVO:
return "Provo";
case AZ::SALEM:
return "Salem";
case AZ::JASPER:
return "Jasper";
case AZ::SERVER:
return "Server";
case AZ::ALL:
case AZ::ALL_CLIENT:
case AZ::NumPlatformIds:
case AZ::Invalid:
default:
return "";
}
#ifdef AZ_REDEFINE_IOS_AT_END
#define IOS AZ_REDEFINE_IOS_AT_END
#endif
}
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform)
{
if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux)
{
return PlatformPC;
}
else if (osPlatform == PlatformCodeNameMac)
{
return PlatformOSX;
}
else if (osPlatform == PlatformCodeNameAndroid)
{
return PlatformES3;
}
else if (osPlatform == PlatformCodeNameiOS)
{
return PlatformIOS;
}
else if (osPlatform == PlatformCodeNameProvo)
{
return PlatformProvo;
}
else if (osPlatform == PlatformCodeNameSalem)
{
return PlatformSalem;
}
else if (osPlatform == PlatformCodeNameJasper)
{
return PlatformJasper;
}
AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)",
aznumeric_cast<int>(osPlatform.size()), osPlatform.data());
return "";
}
PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex)
{
if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds)
{
return PlatformFlags::Platform_NONE;
}
if (platformIndex == PlatformId::ALL)
{
return PlatformFlags::Platform_ALL;
}
if (platformIndex == PlatformId::ALL_CLIENT)
{
return PlatformFlags::Platform_ALL_CLIENT;
}
return static_cast<PlatformFlags>(1 << platformIndex);
}
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatforms(PlatformFlags platformFlags)
{
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platforms;
for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum)
{
const bool isAllPlatforms = PlatformId::ALL == static_cast<PlatformId>(platformNum)
&& ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE);
const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast<PlatformId>(platformNum)
&& ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE);
if (isAllPlatforms || isAllClientPlatforms
|| (platformFlags & static_cast<PlatformFlags>(1 << platformNum)) != PlatformFlags::Platform_NONE)
{
platforms.push_back(PlatformNames[platformNum]);
}
}
return platforms;
}
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags)
{
return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags));
}
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags)
{
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> platformIndices;
for (int i = 0; i < PlatformId::NumPlatformIds; i++)
{
PlatformId index = static_cast<PlatformId>(i);
if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE)
{
platformIndices.emplace_back(index);
}
}
return platformIndices;
}
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags)
{
return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags));
}
PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform)
{
int platformIndex = GetPlatformIndexFromName(platform);
if (platformIndex == PlatformId::Invalid)
{
AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast<int>(platform.length()), platform.data());
return PlatformFlags::Platform_NONE;
}
if (platformIndex == PlatformId::ALL)
{
return PlatformFlags::Platform_ALL;
}
if (platformIndex == PlatformId::ALL_CLIENT)
{
return PlatformFlags::Platform_ALL_CLIENT;
}
return static_cast<PlatformFlags>(1 << platformIndex);
}
const char* PlatformHelper::GetPlatformName(PlatformId platform)
{
if (platform < 0 || platform > PlatformId::NumPlatformIds)
{
return "invalid";
}
return PlatformNames[platform];
}
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformId)
{
PlatformId platform = GetPlatformIdFromName(platformId);
AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast<int>(platformId.length()), platformId.data());
AppendPlatformCodeNames(platformCodes, platform);
}
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId)
{
// The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1".
#pragma push_macro("IOS")
#undef IOS
// To reduce work the Asset Processor groups assets that can be shared between hardware platforms together. For this
// reason "PC" can for instance cover both the Windows and Linux platforms and "IOS" can cover AppleTV and iOS.
switch (platformId)
{
case PlatformId::PC:
platformCodes.emplace_back(PlatformCodeNameWindows);
platformCodes.emplace_back(PlatformCodeNameLinux);
break;
case PlatformId::ES3:
platformCodes.emplace_back(PlatformCodeNameAndroid);
break;
case PlatformId::IOS:
platformCodes.emplace_back(PlatformCodeNameiOS);
break;
case PlatformId::OSX:
platformCodes.emplace_back(PlatformCodeNameMac);
break;
case PlatformId::PROVO:
platformCodes.emplace_back(PlatformCodeNameProvo);
break;
case PlatformId::SALEM:
platformCodes.emplace_back(PlatformCodeNameSalem);
break;
case PlatformId::JASPER:
platformCodes.emplace_back(PlatformCodeNameJasper);
break;
case PlatformId::SERVER:
// Server is not a hardware platform
break;
default:
AZ_Assert(false, "Unsupported Platform ID: %i", platformId);
break;
}
#pragma pop_macro("IOS")
}
int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName)
{
for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++)
{
if (platformName == PlatformNames[idx])
{
return idx;
}
}
return PlatformId::Invalid;
}
PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName)
{
return aznumeric_caster(GetPlatformIndexFromName(platformName));
}
AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags)
{
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platformNames = GetPlatforms(platformFlags);
AssetPlatformCombinedString platformsString;
AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", ");
return platformsString;
}
PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags)
{
PlatformFlags returnFlags = PlatformFlags::Platform_NONE;
if ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE)
{
for (int i = 0; i < NumPlatforms; ++i)
{
auto platformId = static_cast<PlatformId>(i);
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT)
{
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
}
}
}
else if ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE)
{
for (int i = 0; i < NumPlatforms; ++i)
{
auto platformId = static_cast<PlatformId>(i);
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER)
{
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
}
}
}
else
{
returnFlags = platformFlags;
}
return returnFlags;
}
bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags)
{
return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE
|| (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE;
}
bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform)
{
return (flags & checkPlatform) == checkPlatform;
}
bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform)
{
// If checkPlatform contains any kind of invalid id, just exit out here
if (checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms)
{
return false;
}
// ALL_CLIENT + SERVER = ALL
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER))
{
flags = PlatformFlags::Platform_ALL;
}
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL))
{
// It doesn't matter what checkPlatform is set to in this case, just return true
return true;
}
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT))
{
return checkPlatform != PlatformId::SERVER;
}
return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform));
}
}
}

@ -0,0 +1,157 @@
/*
* 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/Preprocessor/Enum.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/fixed_string.h>
#include <AzCore/std/string/string_view.h>
// On IOS builds IOS will be defined and interfere with the below enums
#pragma push_macro("IOS")
#undef IOS
namespace AZ
{
inline namespace PlatformDefaults
{
constexpr char PlatformPC[] = "pc";
constexpr char PlatformES3[] = "es3";
constexpr char PlatformIOS[] = "ios";
constexpr char PlatformOSX[] = "osx_gl";
constexpr char PlatformProvo[] = "provo";
constexpr char PlatformSalem[] = "salem";
constexpr char PlatformJasper[] = "jasper";
constexpr char PlatformServer[] = "server";
constexpr char PlatformCodeNameWindows[] = "Windows";
constexpr char PlatformCodeNameLinux[] = "Linux";
constexpr char PlatformCodeNameAndroid[] = "Android";
constexpr char PlatformCodeNameiOS[] = "iOS";
constexpr char PlatformCodeNameMac[] = "Mac";
constexpr char PlatformCodeNameProvo[] = "Provo";
constexpr char PlatformCodeNameSalem[] = "Salem";
constexpr char PlatformCodeNameJasper[] = "Jasper";
constexpr char PlatformAll[] = "all";
constexpr char PlatformAllClient[] = "all_client";
// Used for the capacity of a fixed vector to store the code names of platforms
// The value needs to be higher than the number of unique OS platforms that are supported(at this time 8)
constexpr size_t MaxPlatformCodeNames = 16;
//! This platform enum have platform values in sequence and can also be used to get the platform count.
AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int,
(Invalid, -1),
PC,
ES3,
IOS,
OSX,
PROVO,
SALEM,
JASPER,
SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc
ALL,
ALL_CLIENT,
// Add new platforms above this
NumPlatformIds
);
constexpr int NumClientPlatforms = 7;
constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently
enum class PlatformFlags : AZ::u32
{
Platform_NONE = 0x00,
Platform_PC = 1 << PlatformId::PC,
Platform_ES3 = 1 << PlatformId::ES3,
Platform_IOS = 1 << PlatformId::IOS,
Platform_OSX = 1 << PlatformId::OSX,
Platform_PROVO = 1 << PlatformId::PROVO,
Platform_SALEM = 1 << PlatformId::SALEM,
Platform_JASPER = 1 << PlatformId::JASPER,
Platform_SERVER = 1 << PlatformId::SERVER,
// A special platform that will always correspond to all platforms, even if new ones are added
Platform_ALL = 1ULL << 30,
// A special platform that will always correspond to all non-server platforms, even if new ones are added
Platform_ALL_CLIENT = 1ULL << 31,
AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER,
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags);
// 32 characters should be more than enough to store a platform name
using AssetPlatformFixedString = AZStd::fixed_string<32>;
// Fixed string which can store a comma separated list of platforms names
// Additional byte is added to take into account the comma
using AssetPlatformCombinedString = AZStd::fixed_string < (AssetPlatformFixedString{}.max_size() + 1)* PlatformId::NumPlatformIds > ;
const char* PlatformIdToPalFolder(PlatformId platform);
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform);
//! Platform Helper is an utility class that can be used to retrieve platform related information
class PlatformHelper
{
public:
//! Given a platformIndex returns the platform name
static const char* GetPlatformName(PlatformId platform);
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformName);
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId);
//! Given a platform name returns a platform index.
//! If the platform is not found, the method returns -1.
static int GetPlatformIndexFromName(AZStd::string_view platformName);
//! Given a platform name returns a platform id.
//! If the platform is not found, the method returns -1.
static PlatformId GetPlatformIdFromName(AZStd::string_view platformName);
//! Given a platformIndex returns the platformFlags
static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform);
//! Given a platformFlags returns all the platform identifiers that are set.
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatforms(PlatformFlags platformFlags);
//! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatformsInterpreted(PlatformFlags platformFlags);
//! Given a platformFlags return a list of PlatformId indices
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndices(PlatformFlags platformFlags);
//! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndicesInterpreted(PlatformFlags platformFlags);
//! Given a platform identifier returns its corresponding platform flag.
static PlatformFlags GetPlatformFlag(AZStd::string_view platform);
//! Given any platformFlags returns a string listing the input platforms
static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags);
//! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent
static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags);
//! Returns true if platformFlags contains any special flags
static bool IsSpecialPlatform(PlatformFlags platformFlags);
//! Returns true if platformFlags has checkPlatform flag set.
static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform);
};
}
}
#pragma pop_macro("IOS")

@ -0,0 +1,100 @@
/*
* 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 "ByteStreamSerializer.h"
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/StringFunc/StringFunc.h>
namespace AZ
{
namespace ByteSerializerInternal
{
static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
switch (inputValue.GetType())
{
case rapidjson::kStringType: {
JsonByteStream buffer;
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
{
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
*valAsByteStream = AZStd::move(buffer);
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
}
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
}
case rapidjson::kArrayType:
case rapidjson::kObjectType:
case rapidjson::kNullType:
case rapidjson::kFalseType:
case rapidjson::kTrueType:
case rapidjson::kNumberType:
return context.Report(
Tasks::ReadField, Outcomes::Unsupported,
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
default:
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
}
}
static JsonSerializationResult::Result StoreWithDefault(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
{
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
}
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
}
} // namespace ByteSerializerInternal
AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonByteStreamSerializer::Load(
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == outputValueTypeId,
"Unable to deserialize AZStd::vector<AZ::u8>> to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::Load(outputValue, inputValue, context);
}
JsonSerializationResult::Result JsonByteStreamSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
JsonSerializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == valueTypeId,
"Unable to serialize AZStd::vector<AZ::u8> to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context);
}
} // namespace AZ

@ -0,0 +1,38 @@
/*
* 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>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
using JsonByteStream = AZStd::vector<AZ::u8>; //!< Alias for AZStd::vector<AZ::u8>.
//! Serialize a stream of bytes (usually binary data) as a json string value.
//! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo<AZStd::vector<AZ::u8>> - see AZStdContainers.inl for more
//! details).
class JsonByteStreamSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", 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;
};
} // namespace AZ

@ -14,6 +14,7 @@
#include <AzCore/Serialization/Json/ArraySerializer.h>
#include <AzCore/Serialization/Json/BasicContainerSerializer.h>
#include <AzCore/Serialization/Json/BoolSerializer.h>
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
#include <AzCore/Serialization/Json/DoubleSerializer.h>
#include <AzCore/Serialization/Json/IntSerializer.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
@ -68,6 +69,8 @@ namespace AZ
jsonContext->Serializer<JsonStringSerializer>()->HandlesType<AZStd::string>();
jsonContext->Serializer<JsonOSStringSerializer>()->HandlesType<OSString>();
jsonContext->Serializer<JsonByteStreamSerializer>()->HandlesType<JsonByteStream>();
jsonContext->Serializer<JsonBasicContainerSerializer>()
->HandlesType<AZStd::fixed_vector>()
->HandlesType<AZStd::forward_list>()

@ -17,6 +17,7 @@
#include <AzCore/JSON/pointer.h>
#include <AzCore/JSON/prettywriter.h>
#include <AzCore/JSON/writer.h>
#include <AzCore/PlatformId/PlatformDefaults.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Settings/CommandLine.h>
#include <AzCore/std/string/conversions.h>
@ -132,23 +133,14 @@ namespace AZ::Internal
AZ::IO::FixedMaxPath ScanUpRootLocator(AZStd::string_view rootFileToLocate)
{
AZStd::fixed_string<AZ::IO::MaxPathLength> executableDir;
if (AZ::Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity()) == Utils::ExecutablePathResult::Success)
{
// Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string
// stored within it
executableDir.resize_no_construct(AZStd::char_traits<char>::length(executableDir.data()));
}
AZ::IO::FixedMaxPath engineRootCandidate{ executableDir };
AZ::IO::FixedMaxPath rootCandidate{ AZ::Utils::GetExecutableDirectory() };
bool rootPathVisited = false;
do
{
if (AZ::IO::SystemFile::Exists((engineRootCandidate / rootFileToLocate).c_str()))
if (AZ::IO::SystemFile::Exists((rootCandidate / rootFileToLocate).c_str()))
{
return engineRootCandidate;
return rootCandidate;
}
// Note for posix filesystems the parent directory of '/' is '/' and for windows
@ -156,38 +148,69 @@ namespace AZ::Internal
// Validate that the parent directory isn't itself, that would imply
// that it is the filesystem root path
AZ::IO::PathView parentPath = engineRootCandidate.ParentPath();
rootPathVisited = (engineRootCandidate == parentPath);
AZ::IO::PathView parentPath = rootCandidate.ParentPath();
rootPathVisited = (rootCandidate == parentPath);
// Recurse upwards one directory
engineRootCandidate = AZStd::move(parentPath);
rootCandidate = AZStd::move(parentPath);
} while (!rootPathVisited);
return {};
}
void InjectSettingToCommandLineFront(AZ::SettingsRegistryInterface& settingsRegistry,
AZStd::string_view path, AZStd::string_view value)
{
AZ::CommandLine commandLine;
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine);
AZ::CommandLine::ParamContainer paramContainer;
commandLine.Dump(paramContainer);
auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")",
aznumeric_cast<int>(path.size()), path.data(), aznumeric_cast<int>(value.size()), value.data());
paramContainer.emplace(paramContainer.begin(), AZStd::move(projectPathOverride));
commandLine.Parse(paramContainer);
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
}
} // namespace AZ::Internal
namespace AZ::SettingsRegistryMergeUtils
{
constexpr AZStd::string_view InternalScanUpEngineRootKey{ "/O3DE/Settings/Internal/engine_root_scan_up_path" };
constexpr AZStd::string_view InternalScanUpProjectRootKey{ "/O3DE/Settings/Internal/project_root_scan_up_path" };
AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry)
{
AZ::IO::FixedMaxPath engineRoot;
// This is the 'external' engine root key, as in passed from command-line or .setreg files.
auto engineRootKey = SettingsRegistryInterface::FixedValueString::format("%s/engine_path", BootstrapSettingsRootKey);
if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty())
// Step 1 Run the scan upwards logic once to find the location of the engine.json if it exist
// Once this step is run the {InternalScanUpEngineRootKey} is set in the Settings Registry
// to have this scan logic only run once InternalScanUpEngineRootKey the supplied registry
if (settingsRegistry.GetType(InternalScanUpEngineRootKey) == SettingsRegistryInterface::Type::NoType)
{
return engineRoot;
// We can scan up from exe directory to find engine.json, use that for engine root if it exists.
engineRoot = Internal::ScanUpRootLocator("engine.json");
// Set the {InternalScanUpEngineRootKey} to make sure this code path isn't called again for this settings registry
settingsRegistry.Set(InternalScanUpEngineRootKey, engineRoot.Native());
if (!engineRoot.empty())
{
settingsRegistry.Set(engineRootKey, engineRoot.Native());
// Inject the engine root into the front of the command line settings
Internal::InjectSettingToCommandLineFront(settingsRegistry, engineRootKey, engineRoot.Native());
return engineRoot;
}
}
// We can scan up from exe directory to find engine.json, use that for engine root if it exists.
if (engineRoot = Internal::ScanUpRootLocator("engine.json"); !engineRoot.empty())
// Step 2 check if the engine_path key has been supplied
if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty())
{
settingsRegistry.Set(engineRootKey, engineRoot.c_str());
return engineRoot;
}
// Step 3 locate the project root and attempt to find the engine root using the registered engine
// for the project in the project.json file
AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry);
if (projectRoot.empty())
{
@ -207,16 +230,30 @@ namespace AZ::SettingsRegistryMergeUtils
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
{
AZ::IO::FixedMaxPath projectRoot;
// This is the 'external' project root key, as in passed from command-line or .setreg files.
auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
if (settingsRegistry.Get(projectRoot.Native(), projectRootKey))
const auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
// Step 1 Run the scan upwards logic once to find the location of the project.json if it exist
// Once this step is run the {InternalScanUpProjectRootKey} is set in the Settings Registry
// to have this scan logic only run once for the supplied registry
// SettingsRegistryInterface::GetType is used to check if a key is set
if (settingsRegistry.GetType(InternalScanUpProjectRootKey) == SettingsRegistryInterface::Type::NoType)
{
return projectRoot;
projectRoot = Internal::ScanUpRootLocator("project.json");
// Set the {InternalScanUpProjectRootKey} to make sure this code path isn't called again for this settings registry
settingsRegistry.Set(InternalScanUpProjectRootKey, projectRoot.Native());
if (!projectRoot.empty())
{
settingsRegistry.Set(projectRootKey, projectRoot.c_str());
// Inject the project root into the front of the command line settings
Internal::InjectSettingToCommandLineFront(settingsRegistry, projectRootKey, projectRoot.Native());
return projectRoot;
}
}
if (projectRoot = Internal::ScanUpRootLocator("project.json"); !projectRoot.empty())
// Step 2 Check the project-path key
// This is the project path root key, as in passed from command-line or .setreg files.
if (settingsRegistry.Get(projectRoot.Native(), projectRootKey))
{
settingsRegistry.Set(projectRootKey, projectRoot.c_str());
return projectRoot;
}
@ -463,18 +500,6 @@ namespace AZ::SettingsRegistryMergeUtils
void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry)
{
ConfigParserSettings parserSettings;
parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view
{
constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" };
for (AZStd::string_view commentPrefix : commentPrefixes)
{
if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos)
{
return line.substr(0, commentOffset);
}
}
return line;
};
parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey;
MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings);
}
@ -501,9 +526,10 @@ namespace AZ::SettingsRegistryMergeUtils
// and if that's missing just get "assets".
constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER;
SettingsRegistryInterface::FixedValueString assetPlatform;
buffer = AZStd::fixed_string<bufferSize>::format("%s/%s_assets", BootstrapSettingsRootKey, platformName);
AZStd::string_view assetPlatformKey(buffer);
// Use the platform codename to retrieve the default asset platform value
SettingsRegistryInterface::FixedValueString assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
if (!registry.Get(assetPlatform, assetPlatformKey))
{
buffer = AZStd::fixed_string<bufferSize>::format("%s/assets", BootstrapSettingsRootKey);
@ -807,6 +833,11 @@ namespace AZ::SettingsRegistryMergeUtils
++argumentIndex;
commandLinePath.resize(commandLineRootSize);
}
// This key is used allow Notification Handlers to know when the command line has been updated within the
// registry. The value itself is meaningless. The JSON path of {CommandLineValueChangedKey}
// being passed to the Notification Event Handler indicates that the command line has be updated
registry.Set(CommandLineValueChangedKey, true);
}
bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
@ -823,10 +854,16 @@ namespace AZ::SettingsRegistryMergeUtils
}
else if (valueName == "Value" && !value.empty())
{
m_arguments.push_back(value);
// Make sure value types are in quotes in case they start with a command option prefix
m_arguments.push_back(QuoteArgument(value));
}
}
AZStd::string QuoteArgument(AZStd::string_view arg)
{
return !arg.empty() ? AZStd::string::format(R"("%.*s")", aznumeric_cast<int>(arg.size()), arg.data()) : AZStd::string{ arg };
}
// The first parameter is skipped by the ComamndLine::Parse function so initialize
// the container with one empty element
AZ::CommandLine::ParamContainer m_arguments{ 1 };

@ -57,6 +57,9 @@ namespace AZ::SettingsRegistryMergeUtils
//! Root key for where command line are stored at within the settings registry
inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine";
//! Key set to trigger a notification that the CommandLine has been stored within the settings registry
//! The value of the key has no meaning. Notification Handlers only need to check if the key was supplied
inline static constexpr char CommandLineValueChangedKey[] = "/Amazon/AzCore/Runtime/CommandLineChanged";
//! Root key where raw project settings (project.json) file is merged to settings registry
inline static constexpr char ProjectSettingsRootKey[] = "/Amazon/Project/Settings";
@ -74,6 +77,20 @@ namespace AZ::SettingsRegistryMergeUtils
//! If it's still not found, attempt to find the project (by similar means) then reconcile the
//! engine root by inspecting project.json and the engine manifest file.
AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry);
//! The algorithm that is used to find the project root is as follows
//! 1. The first time this function is it performs a upward scan for a project.json file from
//! the executable directory and if found stores that path to an internal key.
//! In the same step it injects the path into the front of list of command line parameters
//! using the --regset="{BootstrapSettingsRootKey}/project_path=<path>" value
//! 2. Next the "{BootstrapSettingsRootKey}/project_path" is checked to see if it has a project path set
//!
//! The order in which the project path settings are overridden proceeds in the following order
//! 1. project_path set in the <engine-root>/bootstrap.cfg file
//! 2. project_path set in a *.setreg/*.setregpatch file
//! 3. project_path found by scanning upwards from the executable directory to the project.json path
//! 4. project_path set on the Command line via either --regset="{BootstrapSettingsRootKey}/project_path=<path>"
//! or --project_path=<path>
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry);
//! Query the specializations that will be used when loading the Settings Registry.

@ -505,6 +505,8 @@ set(FILES
Serialization/Json/BasicContainerSerializer.cpp
Serialization/Json/BoolSerializer.h
Serialization/Json/BoolSerializer.cpp
Serialization/Json/ByteStreamSerializer.h
Serialization/Json/ByteStreamSerializer.cpp
Serialization/Json/CastingHelpers.h
Serialization/Json/DoubleSerializer.h
Serialization/Json/DoubleSerializer.cpp
@ -605,6 +607,8 @@ set(FILES
Utils/Utils.h
Script/lua/lua.h
Memory/HeapSchema.cpp
PlatformId/PlatformDefaults.h
PlatformId/PlatformDefaults.cpp
PlatformId/PlatformId.h
PlatformId/PlatformId.cpp
Socket/AzSocket_fwd.h

@ -0,0 +1,59 @@
/*
* 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/Serialization/Json/ByteStreamSerializer.h>
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
namespace JsonSerializationTests
{
class ByteStreamSerializerTestDescription : public JsonSerializerConformityTestDescriptor<AZ::JsonByteStream>
{
public:
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
{
return AZStd::make_shared<AZ::JsonByteStreamSerializer>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateDefaultInstance() override
{
return AZStd::make_shared<AZ::JsonByteStream>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateFullySetInstance() override
{
// create a JsonByteStream (AZStd::vector<u8>) with ten 'a's
return AZStd::make_shared<AZ::JsonByteStream>(10, 'a');
}
AZStd::string_view GetJsonForFullySetInstance() override
{
// Base64 encoded version of 'aaaaaaaaaa' (see CreateFullySetInstance)
return R"("YWFhYWFhYWFhYQ==")";
}
void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
{
features.EnableJsonType(rapidjson::kStringType);
features.m_supportsPartialInitialization = false;
features.m_supportsInjection = false;
}
bool AreEqual(const AZ::JsonByteStream& lhs, const AZ::JsonByteStream& rhs) override
{
return lhs == rhs;
}
};
using ByteStreamConformityTestTypes = ::testing::Types<ByteStreamSerializerTestDescription>;
INSTANTIATE_TYPED_TEST_CASE_P(JsonByteStreamSerialzier, JsonSerializerConformityTests, ByteStreamConformityTestTypes);
} // namespace JsonSerializationTests

@ -98,6 +98,7 @@ set(FILES
Serialization/Json/BaseJsonSerializerTests.cpp
Serialization/Json/BasicContainerSerializerTests.cpp
Serialization/Json/BoolSerializerTests.cpp
Serialization/Json/ByteStreamSerializerTests.cpp
Serialization/Json/ColorSerializerTests.cpp
Serialization/Json/DoubleSerializerTests.cpp
Serialization/Json/IntSerializerTests.cpp

@ -12,6 +12,7 @@
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/ToString.h>
#include <AzCore/Component/Entity.h>
@ -81,13 +82,13 @@ namespace AzFramework
void NonUniformScaleComponent::SetScale(const AZ::Vector3& scale)
{
if (scale.GetMinElement() >= AZ::MinNonUniformScale)
if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale)
{
m_scale = scale;
}
else
{
AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale));
AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale));
AZ_Warning("Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s",
AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str());
m_scale = clampedScale;

@ -105,8 +105,6 @@ namespace AzFramework
virtual bool SetDrawInFrontMode(bool bOn) { (void)bOn; return false; }
virtual AZ::u32 GetState() { return 0; }
virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; }
virtual AZ::u32 SetStateFlag(AZ::u32 state) { (void)state; return 0; }
virtual AZ::u32 ClearStateFlag(AZ::u32 state) { (void)state; return 0; }
virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; }
virtual void PopMatrix() {}

@ -0,0 +1,85 @@
/*
* 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/RTTI/RTTI.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Color.h>
#include <AzCore/std/string/string_view.h>
#include <AzFramework/Viewport/ViewportId.h>
namespace AzFramework
{
using FontId = uint32_t;
static constexpr FontId InvalidFontId = 0xffffffffu;
enum class TextHorizontalAlignment : uint16_t
{
Left,
Right,
Center
};
enum class TextVerticalAlignment : uint16_t
{
Top,
Bottom,
Center,
};
//! Standard parameters for drawing text on screen
struct TextDrawParameters
{
ViewportId m_drawViewportId = InvalidViewportId; //! Viewport to draw into
AZ::Vector3 m_position; //! world space position for 3d draws, screen space x,y,depth for 2d.
AZ::Color m_color = AZ::Colors::White; //! Color to draw the text
AZ::Vector2 m_scale = AZ::Vector2(1.0f); //! font scale
TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //! Horizontal text alignment
TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //! Vertical text alignment
bool m_monospace = false; //! disable character proportional spacing
bool m_depthTest = false; //! Test character against the depth buffer
bool m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution
bool m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger
bool m_multiline = true; //! text respects ascii newline characters
};
class FontDrawInterface
{
public:
AZ_RTTI(FontDrawInterface, "{545A7C14-CB3E-4A5B-B435-13EA606708EE}");
FontDrawInterface() = default;
virtual ~FontDrawInterface() = default;
virtual void DrawScreenAlignedText2d(
const TextDrawParameters& params,
const AZStd::string_view& string) = 0;
virtual void DrawScreenAlignedText3d(
const TextDrawParameters& params,
const AZStd::string_view& string) = 0;
};
class FontQueryInterface
{
public:
AZ_RTTI(FontQueryInterface, "{4BDD8520-EBC1-4680-B25E-421BDF31750F}");
FontQueryInterface() = default;
virtual ~FontQueryInterface() = default;
FontId GetFontId(const AZStd::string_view& fontName) const {return FontId(AZ::Crc32(fontName));}
virtual FontDrawInterface* GetFontDrawInterface(FontId) const = 0;
virtual FontDrawInterface* GetDefaultFontDrawInterface() const = 0;
};
} // namespace AzFramework

@ -142,6 +142,7 @@ namespace Physics
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
if (auto editContext = serializeContext->GetEditContext())

@ -141,6 +141,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
bool m_useMaterialsFromAsset = true;
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
class NativeShapeConfiguration : public ShapeConfiguration

@ -142,13 +142,6 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
/// Adds an appropriate collider component to the entity based on the provided shape configuration.
/// @param entity Entity where the component should be added to.
/// @param colliderConfiguration Configuration of the collider.
/// @param shapeConfiguration Configuration of the shape of the collider.
/// @param addEditorComponents Tells whether to add the Editor version of the collider component or the Game one.
virtual void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) = 0;
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;

@ -1,338 +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 <AzCore/Casting/numeric_cast.h>
#include <AzFramework/Platform/PlatformDefaults.h>
#include <AzCore/StringFunc/StringFunc.h>
namespace AzFramework
{
static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient };
const char* PlatformIdToPalFolder(AzFramework::PlatformId platform)
{
#ifdef IOS
#define AZ_REDEFINE_IOS_AT_END IOS
#undef IOS
#endif
switch (platform)
{
case AzFramework::PC:
return "PC";
case AzFramework::ES3:
return "Android";
case AzFramework::IOS:
return "iOS";
case AzFramework::OSX:
return "Mac";
case AzFramework::PROVO:
return "Provo";
case AzFramework::SALEM:
return "Salem";
case AzFramework::JASPER:
return "Jasper";
case AzFramework::SERVER:
return "Server";
case AzFramework::ALL:
case AzFramework::ALL_CLIENT:
case AzFramework::NumPlatformIds:
case AzFramework::Invalid:
default:
return "";
}
#ifdef AZ_REDEFINE_IOS_AT_END
#define IOS AZ_REDEFINE_IOS_AT_END
#endif
}
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform)
{
if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux)
{
return PlatformPC;
}
else if (osPlatform == PlatformCodeNameMac)
{
return PlatformOSX;
}
else if (osPlatform == PlatformCodeNameAndroid)
{
return PlatformES3;
}
else if (osPlatform == PlatformCodeNameiOS)
{
return PlatformIOS;
}
else if (osPlatform == PlatformCodeNameProvo)
{
return PlatformProvo;
}
else if (osPlatform == PlatformCodeNameSalem)
{
return PlatformSalem;
}
else if (osPlatform == PlatformCodeNameJasper)
{
return PlatformJasper;
}
AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)",
aznumeric_cast<int>(osPlatform.size()), osPlatform.data());
return "";
}
PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex)
{
if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds)
{
return PlatformFlags::Platform_NONE;
}
if (platformIndex == PlatformId::ALL)
{
return PlatformFlags::Platform_ALL;
}
if (platformIndex == PlatformId::ALL_CLIENT)
{
return PlatformFlags::Platform_ALL_CLIENT;
}
return static_cast<PlatformFlags>(1 << platformIndex);
}
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatforms(PlatformFlags platformFlags)
{
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platforms;
for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum)
{
const bool isAllPlatforms = PlatformId::ALL == static_cast<PlatformId>(platformNum)
&& ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE);
const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast<PlatformId>(platformNum)
&& ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE);
if (isAllPlatforms || isAllClientPlatforms
|| (platformFlags & static_cast<PlatformFlags>(1 << platformNum)) != PlatformFlags::Platform_NONE)
{
platforms.push_back(PlatformNames[platformNum]);
}
}
return platforms;
}
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags)
{
return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags));
}
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags)
{
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> platformIndices;
for (int i = 0; i < PlatformId::NumPlatformIds; i++)
{
PlatformId index = static_cast<PlatformId>(i);
if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE)
{
platformIndices.emplace_back(index);
}
}
return platformIndices;
}
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags)
{
return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags));
}
PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform)
{
int platformIndex = GetPlatformIndexFromName(platform);
if (platformIndex == PlatformId::Invalid)
{
AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast<int>(platform.length()), platform.data());
return PlatformFlags::Platform_NONE;
}
if(platformIndex == PlatformId::ALL)
{
return PlatformFlags::Platform_ALL;
}
if (platformIndex == PlatformId::ALL_CLIENT)
{
return PlatformFlags::Platform_ALL_CLIENT;
}
return static_cast<PlatformFlags>(1 << platformIndex);
}
const char* PlatformHelper::GetPlatformName(PlatformId platform)
{
if (platform < 0 || platform > PlatformId::NumPlatformIds)
{
return "invalid";
}
return PlatformNames[platform];
}
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformId)
{
PlatformId platform = GetPlatformIdFromName(platformId);
AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast<int>(platformId.length()), platformId.data());
AppendPlatformCodeNames(platformCodes, platform);
}
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId)
{
// The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1".
#pragma push_macro("IOS")
#undef IOS
// To reduce work the Asset Processor groups assets that can be shared between hardware platforms together. For this
// reason "PC" can for instance cover both the Windows and Linux platforms and "IOS" can cover AppleTV and iOS.
switch (platformId)
{
case PlatformId::PC:
platformCodes.emplace_back(PlatformCodeNameWindows);
platformCodes.emplace_back(PlatformCodeNameLinux);
break;
case PlatformId::ES3:
platformCodes.emplace_back(PlatformCodeNameAndroid);
break;
case PlatformId::IOS:
platformCodes.emplace_back(PlatformCodeNameiOS);
break;
case PlatformId::OSX:
platformCodes.emplace_back(PlatformCodeNameMac);
break;
case PlatformId::PROVO:
platformCodes.emplace_back(PlatformCodeNameProvo);
break;
case PlatformId::SALEM:
platformCodes.emplace_back(PlatformCodeNameSalem);
break;
case PlatformId::JASPER:
platformCodes.emplace_back(PlatformCodeNameJasper);
break;
case PlatformId::SERVER:
// Server is not a hardware platform
break;
default:
AZ_Assert(false, "Unsupported Platform ID: %i", platformId);
break;
}
#pragma pop_macro("IOS")
}
int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName)
{
for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++)
{
if (platformName == PlatformNames[idx])
{
return idx;
}
}
return PlatformId::Invalid;
}
PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName)
{
return aznumeric_caster(GetPlatformIndexFromName(platformName));
}
AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags)
{
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platformNames = GetPlatforms(platformFlags);
AssetPlatformCombinedString platformsString;
AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", ");
return platformsString;
}
PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags)
{
PlatformFlags returnFlags = PlatformFlags::Platform_NONE;
if((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE)
{
for (int i = 0; i < NumPlatforms; ++i)
{
auto platformId = static_cast<PlatformId>(i);
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT)
{
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
}
}
}
else if((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE)
{
for (int i = 0; i < NumPlatforms; ++i)
{
auto platformId = static_cast<PlatformId>(i);
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER)
{
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
}
}
}
else
{
returnFlags = platformFlags;
}
return returnFlags;
}
bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags)
{
return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE
|| (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE;
}
bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform)
{
return (flags & checkPlatform) == checkPlatform;
}
bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform)
{
// If checkPlatform contains any kind of invalid id, just exit out here
if(checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms)
{
return false;
}
// ALL_CLIENT + SERVER = ALL
if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER))
{
flags = PlatformFlags::Platform_ALL;
}
if(HasFlagHelper(flags, PlatformFlags::Platform_ALL))
{
// It doesn't matter what checkPlatform is set to in this case, just return true
return true;
}
if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT))
{
return checkPlatform != PlatformId::SERVER;
}
return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform));
}
}

@ -12,144 +12,12 @@
#pragma once
#include <AzCore/Preprocessor/Enum.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/fixed_string.h>
#include <AzCore/std/string/string_view.h>
// On IOS builds IOS will be defined and interfere with the below enums
#pragma push_macro("IOS")
#undef IOS
#include <AzCore/PlatformId/PlatformDefaults.h>
// As the Platform defaults is needed within AzCore,
// those structures have been moved to AzCore and brought into
// The AzFramework namespace for backwards compatibility
namespace AzFramework
{
constexpr char PlatformPC[] = "pc";
constexpr char PlatformES3[] = "es3";
constexpr char PlatformIOS[] = "ios";
constexpr char PlatformOSX[] = "osx_gl";
constexpr char PlatformProvo[] = "provo";
constexpr char PlatformSalem[] = "salem";
constexpr char PlatformJasper[] = "jasper";
constexpr char PlatformServer[] = "server";
constexpr char PlatformCodeNameWindows[] = "Windows";
constexpr char PlatformCodeNameLinux[] = "Linux";
constexpr char PlatformCodeNameAndroid[] = "Android";
constexpr char PlatformCodeNameiOS[] = "iOS";
constexpr char PlatformCodeNameMac[] = "Mac";
constexpr char PlatformCodeNameProvo[] = "Provo";
constexpr char PlatformCodeNameSalem[] = "Salem";
constexpr char PlatformCodeNameJasper[] = "Jasper";
constexpr char PlatformAll[] = "all";
constexpr char PlatformAllClient[] = "all_client";
// Used for the capacity of a fixed vector to store the code names of platforms
// The value needs to be higher than the number of unique OS platforms that are supported(at this time 8)
constexpr size_t MaxPlatformCodeNames = 16;
//! This platform enum have platform values in sequence and can also be used to get the platform count.
AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int,
(Invalid, -1),
PC,
ES3,
IOS,
OSX,
PROVO,
SALEM,
JASPER,
SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc
ALL,
ALL_CLIENT,
// Add new platforms above this
NumPlatformIds
);
constexpr int NumClientPlatforms = 7;
constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently
enum class PlatformFlags : AZ::u32
{
Platform_NONE = 0x00,
Platform_PC = 1 << PlatformId::PC,
Platform_ES3 = 1 << PlatformId::ES3,
Platform_IOS = 1 << PlatformId::IOS,
Platform_OSX = 1 << PlatformId::OSX,
Platform_PROVO = 1 << PlatformId::PROVO,
Platform_SALEM = 1 << PlatformId::SALEM,
Platform_JASPER = 1 << PlatformId::JASPER,
Platform_SERVER = 1 << PlatformId::SERVER,
// A special platform that will always correspond to all platforms, even if new ones are added
Platform_ALL = 1ULL << 30,
// A special platform that will always correspond to all non-server platforms, even if new ones are added
Platform_ALL_CLIENT = 1ULL << 31,
AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER,
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags);
// 32 characters should be more than enough to store a platform name
using AssetPlatformFixedString = AZStd::fixed_string<32>;
// Fixed string which can store a comma separated list of platforms names
// Additional byte is added to take into account the comma
using AssetPlatformCombinedString = AZStd::fixed_string<(AssetPlatformFixedString{}.max_size() + 1) * PlatformId::NumPlatformIds>;
const char* PlatformIdToPalFolder(AzFramework::PlatformId platform);
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform);
//! Platform Helper is an utility class that can be used to retrieve platform related information
class PlatformHelper
{
public:
//! Given a platformIndex returns the platform name
static const char* GetPlatformName(PlatformId platform);
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformName);
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId);
//! Given a platform name returns a platform index.
//! If the platform is not found, the method returns -1.
static int GetPlatformIndexFromName(AZStd::string_view platformName);
//! Given a platform name returns a platform id.
//! If the platform is not found, the method returns -1.
static PlatformId GetPlatformIdFromName(AZStd::string_view platformName);
//! Given a platformIndex returns the platformFlags
static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform);
//! Given a platformFlags returns all the platform identifiers that are set.
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatforms(PlatformFlags platformFlags);
//! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatformsInterpreted(PlatformFlags platformFlags);
//! Given a platformFlags return a list of PlatformId indices
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndices(PlatformFlags platformFlags);
//! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndicesInterpreted(PlatformFlags platformFlags);
//! Given a platform identifier returns its corresponding platform flag.
static PlatformFlags GetPlatformFlag(AZStd::string_view platform);
//! Given any platformFlags returns a string listing the input platforms
static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags);
//! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent
static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags);
//! Returns true if platformFlags contains any special flags
static bool IsSpecialPlatform(PlatformFlags platformFlags);
//! Returns true if platformFlags has checkPlatform flag set.
static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform);
};
using namespace AZ::PlatformDefaults;
}
#pragma pop_macro("IOS")

@ -42,8 +42,14 @@ namespace AzFramework::ProjectManager
AZ::CommandLine commandLine;
commandLine.Parse(argc, argv);
AZ::SettingsRegistryImpl settingsRegistry;
// Store the Command line to the Setting Registry
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
// Retrieve Command Line from Settings Registry, it may have been updated by the call to FindEngineRoot()
// in MergeSettingstoRegistry_ConfigFile
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(settingsRegistry, commandLine, false);
engineRootPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(settingsRegistry);
projectRootPath = AZ::SettingsRegistryMergeUtils::FindProjectRoot(settingsRegistry);

@ -14,6 +14,7 @@
#include <AzCore/base.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/RTTI/TypeInfo.h>
namespace AZ
@ -133,6 +134,18 @@ namespace AzFramework
return !operator==(lhs, rhs);
}
inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize)
{
return ScreenPoint(
aznumeric_caster(std::round(screenNDC.GetX() * viewportSize.GetX())),
aznumeric_caster(std::round((1.0f - screenNDC.GetY()) * viewportSize.GetY())));
}
inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize)
{
return AZ::Vector2(aznumeric_cast<float>(screenPoint.m_x), viewportSize.GetY() - aznumeric_cast<float>(screenPoint.m_y)) / viewportSize;
}
//! Return an AZ::Vector2 from a ScreenPoint.
inline AZ::Vector2 Vector2FromScreenPoint(const ScreenPoint& screenPoint)
{

@ -101,20 +101,25 @@ namespace AzFramework
cameraState.m_nearClip, cameraState.m_farClip);
}
ScreenPoint WorldToScreen(
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize)
AZ::Vector3 WorldToScreenNDC(
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection)
{
// transform the world space position to clip space
const auto clipSpacePosition = cameraProjection * cameraView * AZ::Vector3ToVector4(worldPosition, 1.0f);
// transform the clip space position to ndc space (perspective divide)
const auto ndcPosition = clipSpacePosition / clipSpacePosition.GetW();
// transform ndc space from <-1,1> to <0, 1> range
const auto ndcNormalizedPosition = (AZ::Vector4ToVector2(ndcPosition) + AZ::Vector2::CreateOne()) * 0.5f;
return (AZ::Vector4ToVector3(ndcPosition) + AZ::Vector3::CreateOne()) * 0.5f;
}
ScreenPoint WorldToScreen(
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection,
const AZ::Vector2& viewportSize)
{
const auto ndcNormalizedPosition = WorldToScreenNDC(worldPosition, cameraView, cameraProjection);
// scale ndc position by screen dimensions to return screen position
return ScreenPoint(
aznumeric_caster(std::round(ndcNormalizedPosition.GetX() * viewportSize.GetX())),
aznumeric_caster(std::round(viewportSize.GetY() - (ndcNormalizedPosition.GetY() * viewportSize.GetY()))));
return ScreenPointFromNDC(ndcNormalizedPosition, viewportSize);
}
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState)
@ -127,12 +132,8 @@ namespace AzFramework
const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView,
const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize)
{
const auto screenHeight = viewportSize.GetY();
const auto flippedScreenPosition =
AZ::Vector2(aznumeric_caster(screenPosition.m_x), aznumeric_caster(screenHeight - screenPosition.m_y));
// convert screen space coordinates to <-1,1> range
const auto ndcPosition = (flippedScreenPosition / viewportSize) * 2.0f - AZ::Vector2::CreateOne();
// convert screen space coordinates from <0, 1> to <-1,1> range
const auto ndcPosition = NDCFromScreenPoint(screenPosition, viewportSize) * 2.0f - AZ::Vector2::CreateOne();
// transform ndc space position to clip space
const auto clipSpacePosition = inverseCameraProjection * Vector2ToVector4(ndcPosition, -1.0f, 1.0f);

@ -28,6 +28,11 @@ namespace AzFramework
struct ScreenPoint;
struct ViewportInfo;
//! Projects a position in world space to screen space normalized device coordinates for the given camera.
AZ::Vector3 WorldToScreenNDC(
const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection);
//! Projects a position in world space to screen space for the given camera.
ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState);

@ -145,6 +145,7 @@ set(FILES
Components/NonUniformScaleComponent.cpp
FileFunc/FileFunc.h
FileFunc/FileFunc.cpp
Font/FontInterface.h
Gem/GemInfo.cpp
Gem/GemInfo.h
StringFunc/StringFunc.h
@ -316,7 +317,6 @@ set(FILES
Terrain/TerrainDataRequestBus.h
Terrain/TerrainDataRequestBus.cpp
Platform/PlatformDefaults.h
Platform/PlatformDefaults.cpp
Windowing/WindowBus.h
Windowing/NativeWindow.cpp
Windowing/NativeWindow.h

@ -80,6 +80,8 @@ namespace AzGameFramework
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
#endif
// Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
}
AZ::ComponentTypeList GameApplication::GetRequiredSystemComponents() const

@ -114,6 +114,9 @@ namespace AzNetworking
void ClearUnusedBits();
ContainerType m_container;
template <AZStd::size_t, typename>
friend class FixedSizeVectorBitset;
};
}

@ -192,19 +192,11 @@ namespace AzNetworking
template <AZStd::size_t CAPACITY, typename ElementType>
inline void FixedSizeVectorBitset<CAPACITY, ElementType>::ClearUnusedBits()
{
constexpr ElementType AllOnes = static_cast<ElementType>(~0);
const ElementType LastUsedBits = (GetSize() % BitsetType::ElementTypeBits);
#pragma warning(push)
#pragma warning(disable : 4293) // shift count negative or too big, undefined behaviour
#pragma warning(disable : 6326) // constant constant comparison
const ElementType ShiftAmount = (LastUsedBits == 0) ? 0 : BitsetType::ElementTypeBits - LastUsedBits;
const ElementType ClearBitMask = AllOnes >> ShiftAmount;
#pragma warning(pop)
uint32_t usedElementSize = (GetSize() + BitsetType::ElementTypeBits - 1) / BitsetType::ElementTypeBits;
for (uint32_t i = usedElementSize + 1; i < CAPACITY; ++i)
for (uint32_t i = usedElementSize + 1; i < BitsetType::ElementCount; ++i)
{
m_bitset.GetContainer()[i] = 0;
}
m_bitset.GetContainer()[m_bitset.GetContainer().size() - 1] &= ClearBitMask;
m_bitset.ClearUnusedBits();
}
}

@ -270,7 +270,7 @@ namespace AzNetworking
value.StoreToFloat3(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[2], "zValue");
value = AZ::Vector3::CreateFromFloat3(values);
return serializer.IsValid();
}
@ -285,8 +285,8 @@ namespace AzNetworking
value.StoreToFloat4(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[1], "wValue");
serializer.Serialize(values[2], "zValue");
serializer.Serialize(values[3], "wValue");
value = AZ::Vector4::CreateFromFloat4(values);
return serializer.IsValid();
}
@ -301,8 +301,8 @@ namespace AzNetworking
value.StoreToFloat4(values);
serializer.Serialize(values[0], "xValue");
serializer.Serialize(values[1], "yValue");
serializer.Serialize(values[1], "zValue");
serializer.Serialize(values[1], "wValue");
serializer.Serialize(values[2], "zValue");
serializer.Serialize(values[3], "wValue");
value = AZ::Quaternion::CreateFromFloat4(values);
return serializer.IsValid();
}

@ -578,16 +578,6 @@ namespace AzToolsFramework
*/
virtual bool IsEditorInIsolationMode() = 0;
/*!
* Get the engine root path that the current tool is running under.
*/
virtual const char* GetEngineRootPath() const = 0;
/**
* Get the version of the engine the current tools application is running under
*/
virtual const char* GetEngineVersion() const = 0;
/**
* Creates and adds a new entity to the tools application from components which match at least one of the requiredTags
* The tag matching occurs on AZ::Edit::SystemComponentTags attribute from the reflected class data in the serialization context

@ -224,112 +224,6 @@ namespace AzToolsFramework
} // Internal
#define AZ_MAX_ENGINE_VERSION_LEN 64
// Private Implementation class to manage the engine root and version
// Note: We are not using any AzCore classes because the ToolsApplication
// initialization happens early on, before the Allocators get instantiated,
// so we are using Qt privately instead
class ToolsApplication::EngineConfigImpl
{
private:
friend class ToolsApplication;
typedef QMap<QString, QString> EngineJsonMap;
EngineConfigImpl(const char* logWindow, const char* fileName)
: m_logWindow(logWindow)
, m_fileName(fileName)
{
m_engineRoot[0] = '\0';
m_engineVersion[0] = '\0';
}
char m_engineRoot[AZ_MAX_PATH_LEN];
char m_engineVersion[AZ_MAX_ENGINE_VERSION_LEN];
EngineJsonMap m_engineConfigMap;
const char* m_logWindow;
const char* m_fileName;
// Read an engine configuration into a map of key/value pairs
bool ReadEngineConfigIntoMap(QString engineJsonPath, EngineJsonMap& engineJsonMap)
{
QFile engineJsonFile(engineJsonPath);
if (!engineJsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
AZ_Warning(m_logWindow, false, "Unable to open file '%s' in the current root directory", engineJsonPath.toUtf8().data());
return false;
}
QByteArray engineJsonData = engineJsonFile.readAll();
engineJsonFile.close();
QJsonDocument engineJsonDoc(QJsonDocument::fromJson(engineJsonData));
if (engineJsonDoc.isNull())
{
AZ_Warning(m_logWindow, false, "Unable to read file '%s' in the current root directory", engineJsonPath.toUtf8().data());
return false;
}
QJsonObject engineJsonRoot = engineJsonDoc.object();
for (const QString& configKey : engineJsonRoot.keys())
{
QJsonValue configValue = engineJsonRoot[configKey];
if (configValue.isString() || configValue.isDouble())
{
// Only map strings and numbers, ignore every other type
engineJsonMap[configKey] = configValue.toString();
}
else
{
AZ_Warning(m_logWindow, false, "Ignoring key '%s' from '%s', unsupported type.", configKey.toUtf8().data(), engineJsonPath.toUtf8().data());
}
}
return true;
}
// Initialize the engine config object based on the current
bool Initialize(const char* currentEngineRoot)
{
// Start with the app root as the engine root (legacy), but check to see if the engine root
// is external to the app root
azstrncpy(m_engineRoot, AZ_ARRAY_SIZE(m_engineRoot), currentEngineRoot, strlen(currentEngineRoot) + 1);
// From the appRoot, check and see if we can read any external engine reference in engine.json
QString engineJsonFileName = QString(m_fileName);
QString engineJsonFilePath = QDir(currentEngineRoot).absoluteFilePath(engineJsonFileName);
// From the appRoot, check and see if we can read any external engine reference in engine.json
if (!QFile::exists(engineJsonFilePath))
{
AZ_Warning(m_logWindow, false, "Unable to find '%s' in the current app root directory.", m_fileName);
return false;
}
if (!ReadEngineConfigIntoMap(engineJsonFilePath, m_engineConfigMap))
{
AZ_Warning(m_logWindow, false, "Defaulting root engine path to '%s'", currentEngineRoot);
return false;
}
// Read in the local engine version value
auto localEngineVersionValue = m_engineConfigMap.find(QString(AzToolsFramework::Internal::s_engineConfigEngineVersionKey));
QString localEngineVersion(localEngineVersionValue.value());
azstrncpy(m_engineVersion, AZ_ARRAY_SIZE(m_engineVersion), localEngineVersion.toUtf8().data(), localEngineVersion.length() + 1);
return true;
}
const char* GetEngineRoot() const
{
return m_engineRoot;
}
const char* GetEngineVersion() const
{
return m_engineVersion;
}
};
ToolsApplication::ToolsApplication(int* argc, char*** argv)
: AzFramework::Application(argc, argv)
, m_selectionBounds(AZ::Aabb())
@ -339,7 +233,6 @@ namespace AzToolsFramework
, m_isInIsolationMode(false)
{
ToolsApplicationRequests::Bus::Handler::BusConnect();
m_engineConfigImpl.reset(new ToolsApplication::EngineConfigImpl(AzToolsFramework::Internal::s_startupLogWindow, AzToolsFramework::Internal::s_engineConfigFileName));
m_undoCache.RegisterToUndoCacheInterface();
}
@ -391,7 +284,6 @@ namespace AzToolsFramework
void ToolsApplication::Start(const Descriptor& descriptor, const StartupParameters& startupParameters/* = StartupParameters()*/)
{
Application::Start(descriptor, startupParameters);
InitializeEngineConfig();
m_editorEntityManager.Start();
@ -399,14 +291,6 @@ namespace AzToolsFramework
AZ_Assert(m_editorEntityAPI, "ToolsApplication - Could not retrieve instance of EditorEntityAPI");
}
void ToolsApplication::InitializeEngineConfig()
{
if (!m_engineConfigImpl->Initialize(GetEngineRoot()))
{
AZ_Warning(AzToolsFramework::Internal::s_startupLogWindow, false, "Defaulting engine root path to '%s'", GetEngineRoot());
}
}
void ToolsApplication::StartCommon(AZ::Entity* systemEntity)
{
Application::StartCommon(systemEntity);
@ -1832,16 +1716,6 @@ namespace AzToolsFramework
return m_isInIsolationMode;
}
const char* ToolsApplication::GetEngineRootPath() const
{
return m_engineConfigImpl->GetEngineRoot();
}
const char* ToolsApplication::GetEngineVersion() const
{
return m_engineConfigImpl->GetEngineVersion();
}
void ToolsApplication::CreateAndAddEntityFromComponentTags(const AZStd::vector<AZ::Crc32>& requiredTags, const char* entityName)
{
if (!entityName || !entityName[0])

@ -150,8 +150,6 @@ namespace AzToolsFramework
void EnterEditorIsolationMode() override;
void ExitEditorIsolationMode() override;
bool IsEditorInIsolationMode() override;
const char* GetEngineRootPath() const override;
const char* GetEngineVersion() const override;
void CreateAndAddEntityFromComponentTags(const AZStd::vector<AZ::Crc32>& requiredTags, const char* entityName) override;
@ -174,7 +172,6 @@ namespace AzToolsFramework
void CreateUndosForDirtyEntities();
void ConsistencyCheckUndoCache();
void InitializeEngineConfig();
AZ::Aabb m_selectionBounds;
EntityIdList m_selectedEntities;
EntityIdList m_highlightedEntities;
@ -186,9 +183,6 @@ namespace AzToolsFramework
bool m_isInIsolationMode;
EntityIdSet m_isolatedEntityIdSet;
class EngineConfigImpl;
AZStd::unique_ptr<EngineConfigImpl> m_engineConfigImpl;
EditorEntityAPI* m_editorEntityAPI = nullptr;
EditorEntityManager m_editorEntityManager;

@ -256,6 +256,8 @@ namespace AzToolsFramework
m_userSettings = AZ::UserSettings::CreateFind<AssetEditorWidgetUserSettings>(k_assetEditorWidgetSettings, AZ::UserSettings::CT_LOCAL);
UpdateRecentFileListState();
QObject::connect(m_recentFileMenu, &QMenu::aboutToShow, this, &AssetEditorWidget::PopulateRecentMenu);
}
@ -952,7 +954,8 @@ namespace AzToolsFramework
void AssetEditorWidget::AddRecentPath(const AZStd::string& recentPath)
{
m_userSettings->AddRecentPath(recentPath);
m_userSettings->AddRecentPath(recentPath);
UpdateRecentFileListState();
}
void AssetEditorWidget::PopulateRecentMenu()
@ -989,6 +992,21 @@ namespace AzToolsFramework
m_saveAsAssetAction->setEnabled(true);
}
void AssetEditorWidget::UpdateRecentFileListState()
{
if (m_recentFileMenu)
{
if (!m_userSettings || m_userSettings->m_recentPaths.empty())
{
m_recentFileMenu->setEnabled(false);
}
else
{
m_recentFileMenu->setEnabled(true);
}
}
}
} // namespace AssetEditor
} // namespace AzToolsFramework

@ -122,6 +122,8 @@ namespace AzToolsFramework
void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override;
void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override;
void UpdateRecentFileListState();
private:
void DirtyAsset();

@ -58,7 +58,7 @@ namespace AzToolsFramework
m_prefabUndoCache.Destroy();
}
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath)
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
{
// Retrieve entityList from entityIds
EntityList inputEntityList;

@ -42,7 +42,7 @@ namespace AzToolsFramework
void UnregisterPrefabPublicHandlerInterface();
// PrefabPublicInterface...
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath) override;
PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) override;
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;

@ -49,7 +49,7 @@ namespace AzToolsFramework
* @param filePath The path for the new prefab file.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZStd::string_view filePath) = 0;
virtual PrefabOperationResult CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath) = 0;
/**
* Instantiate a prefab from a prefab file.

@ -13,6 +13,7 @@
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/ToString.h>
namespace AzToolsFramework
@ -44,7 +45,9 @@ namespace AzToolsFramework
->DataElement(
AZ::Edit::UIHandlers::Default, &EditorNonUniformScaleComponent::m_scale, "Non-uniform Scale",
"Non-uniform scale for this entity only (does not propagate through hierarchy)")
->Attribute(AZ::Edit::Attributes::Min, AZ::MinNonUniformScale)
->Attribute(AZ::Edit::Attributes::Min, AZ::MinTransformScale)
->Attribute(AZ::Edit::Attributes::Max, AZ::MaxTransformScale)
->Attribute(AZ::Edit::Attributes::Step, 0.1f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorNonUniformScaleComponent::OnScaleChanged)
;
}
@ -106,13 +109,13 @@ namespace AzToolsFramework
void EditorNonUniformScaleComponent::SetScale(const AZ::Vector3& scale)
{
if (scale.GetMinElement() >= AZ::MinNonUniformScale)
if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale)
{
m_scale = scale;
}
else
{
AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale));
AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale));
AZ_Warning("Editor Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s",
AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str());
m_scale = clampedScale;

@ -1276,7 +1276,6 @@ namespace AzToolsFramework
Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)->
DataElement(TransformScaleHandler, &EditorTransform::m_scale, "Scale", "Local Scale")->
Attribute(AZ::Edit::Attributes::Step, 0.1f)->
Attribute(AZ::Edit::Attributes::Min, 0.01f)->
Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked)
;
}

@ -12,6 +12,7 @@
#include "AzToolsFramework_precompiled.h"
#include <ToolsComponents/TransformScalePropertyHandler.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Vector3.h>
namespace AzToolsFramework
@ -36,8 +37,8 @@ namespace AzToolsFramework
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestWrite, newCtrl);
});
newCtrl->setMinimum(0.01f);
newCtrl->setMaximum(std::numeric_limits<float>::max());
newCtrl->setMinimum(AZ::MinTransformScale);
newCtrl->setMaximum(AZ::MaxTransformScale);
return newCtrl;
}

@ -24,6 +24,7 @@
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiInterface.h>
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
@ -39,9 +40,12 @@ namespace AzToolsFramework
{
namespace Prefab
{
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr;
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab";
void PrefabUserSettings::Reflect(AZ::ReflectContext* context)
@ -79,6 +83,13 @@ namespace AzToolsFramework
return;
}
s_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
if (s_prefabLoaderInterface == nullptr)
{
AZ_Assert(false, "Prefab - could not get PrefabLoaderInterface on PrefabIntegrationManager construction.");
return;
}
EditorContextMenuBus::Handler::BusConnect();
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
AZ::Interface<PrefabIntegrationInterface>::Register(this);
@ -320,14 +331,15 @@ namespace AzToolsFramework
GenerateSuggestedFilenameFromEntities(prefabRootEntities, suggestedName);
if (!QueryUserForPrefabSaveLocation(suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
if (!QueryUserForPrefabSaveLocation(
suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath))
{
// User canceled prefab creation, or error prevented continuation.
return;
}
}
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath);
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
if (!createPrefabOutcome.IsSuccess())
{

@ -29,6 +29,9 @@ namespace AzToolsFramework
{
namespace Prefab
{
class PrefabLoaderInterface;
//! Structure for saving/retrieving user settings related to prefab workflows.
class PrefabUserSettings
: public AZ::UserSettings
@ -129,6 +132,7 @@ namespace AzToolsFramework
static EditorEntityUiInterface* s_editorEntityUiInterface;
static PrefabPublicInterface* s_prefabPublicInterface;
static PrefabEditInterface* s_prefabEditInterface;
static PrefabLoaderInterface* s_prefabLoaderInterface;
};
}
}

@ -38,6 +38,7 @@ AZ_POP_DISABLE_WARNING
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Asset/AssetTypeInfoBus.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/Asset/SimpleAsset.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
@ -1212,9 +1213,8 @@ namespace AzToolsFramework
if (!QFile::exists(path))
{
const char* engineRoot = nullptr;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath);
QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current();
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
path = engineDir.absoluteFilePath(iconPath.c_str());
}

@ -53,7 +53,7 @@ namespace AzToolsFramework
float, cl_viewportGizmoAxisLabelOffset, 1.15f, nullptr, AZ::ConsoleFunctorFlags::Null,
"The offset of the label for the viewport axis gizmo");
AZ_CVAR(
float, cl_viewportGizmoAxisLabelSize, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
float, cl_viewportGizmoAxisLabelSize, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
"The size of each label for the viewport axis gizmo");
AZ_CVAR(
AZ::Vector2, cl_viewportGizmoAxisScreenPosition, AZ::Vector2(0.045f, 0.9f), nullptr,
@ -1603,7 +1603,7 @@ namespace AzToolsFramework
const AZ::Vector3 uniformScale = AZ::Vector3(action.m_start.m_sign * sumVectorElements(action.LocalScaleOffset()));
const AZ::Vector3 scale = (AZ::Vector3::CreateOne() +
(uniformScale / initialScale)).GetMax(AZ::Vector3(0.01f));
(uniformScale / initialScale)).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale));
const AZ::Transform scaleTransform = AZ::Transform::CreateScale(scale);
if (action.m_modifiers.Alt())
@ -3434,19 +3434,22 @@ namespace AzToolsFramework
const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState);
// screen space offset to move the 2d gizmo around
const AZ::Vector3 screenPosition =
(AZ::Vector2ToVector3(cl_viewportGizmoAxisScreenPosition) - AZ::Vector3(0.5f, 0.5f, 0.0f)) *
AZ::Vector2ToVector3(gizmoCameraState.m_viewportSize);
const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f);
// map from a position in world space (relative to the the gizmo camera near the origin) to a position in
// screen space
const auto calculateGizmoAxis =
[&cameraView, &cameraProjection, &gizmoCameraState, &screenPosition]
(const AZ::Vector3& position)
{
return AZ::Vector2ToVector3(AzFramework::Vector2FromScreenPoint(
AzFramework::WorldToScreen(
position, cameraView, cameraProjection, gizmoCameraState.m_viewportSize))) + screenPosition;
[&cameraView, &cameraProjection, &screenOffset]
(const AZ::Vector3& axis)
{
auto result = AZ::Vector2(
AzFramework::WorldToScreenNDC(
axis,
cameraView,
cameraProjection)
);
result.SetY(1.0f - result.GetY());
return result + screenOffset;
};
// get all important axis positions in screen space
@ -3456,31 +3459,31 @@ namespace AzToolsFramework
const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength);
const auto gizmoEndAxisZ = calculateGizmoAxis(-AZ::Vector3::CreateAxisZ() * lineLength);
const AZ::Vector3 gizmoAxisX = gizmoEndAxisX - gizmoStart;
const AZ::Vector3 gizmoAxisY = gizmoEndAxisY - gizmoStart;
const AZ::Vector3 gizmoAxisZ = gizmoEndAxisZ - gizmoStart;
const AZ::Vector2 gizmoAxisX = gizmoEndAxisX - gizmoStart;
const AZ::Vector2 gizmoAxisY = gizmoEndAxisY - gizmoStart;
const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart;
// draw the axes of the gizmo
debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth);
debugDisplay.SetColor(AZ::Colors::Red);
debugDisplay.DrawLine(gizmoStart, gizmoEndAxisX);
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f);
debugDisplay.SetColor(AZ::Colors::Lime);
debugDisplay.DrawLine(gizmoStart, gizmoEndAxisY);
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisY, 1.0f);
debugDisplay.SetColor(AZ::Colors::Blue);
debugDisplay.DrawLine(gizmoStart, gizmoEndAxisZ);
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f);
debugDisplay.SetLineWidth(1.0f);
const float labelOffset = cl_viewportGizmoAxisLabelOffset;
const auto labelOffsetX = gizmoStart + gizmoAxisX * labelOffset;
const auto labelOffsetY = gizmoStart + gizmoAxisY * labelOffset;
const auto labelOffsetZ = gizmoStart + gizmoAxisZ * labelOffset;
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize;
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize;
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize;
// draw the label of of each axis for the gizmo
const float labelSize = cl_viewportGizmoAxisLabelSize;
debugDisplay.SetColor(AZ::Colors::White);
debugDisplay.Draw2dTextLabel(labelOffsetX.GetX(), labelOffsetX.GetY(), labelSize, "X", true);
debugDisplay.Draw2dTextLabel(labelOffsetY.GetX(), labelOffsetY.GetY(), labelSize, "Y", true);
debugDisplay.Draw2dTextLabel(labelOffsetZ.GetX(), labelOffsetZ.GetY(), labelSize, "Z", true);
debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true);
debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true);
debugDisplay.Draw2dTextLabel(labelZScreenPosition.GetX(), labelZScreenPosition.GetY(), labelSize, "Z", true);
}
void EditorTransformComponentSelection::DisplayViewportSelection2d(

@ -68,7 +68,7 @@ namespace UnitTest
{
assets[idx] = AssetId(AZ::Uuid::CreateRandom(), 0);
AZ::Data::AssetInfo info;
info.m_relativePath = AZStd::string::format("Asset%d.txt", idx);
info.m_relativePath = AZStd::string::format("asset%d.txt", idx);
m_assetsPath[idx] = info.m_relativePath;
info.m_assetId = assets[idx];
m_assetRegistry->RegisterAsset(assets[idx], info);
@ -623,7 +623,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList1, assets[fileIndex]));
if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath))
{
AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex);
AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex);
m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str());
m_fileStreams[0][fileIndex].Close();
}
@ -654,7 +654,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList1, assets[fileIndex]));
if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath))
{
AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex + 1);// changing file content
AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex + 1);// changing file content
m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str());
m_fileStreams[0][fileIndex].Close();
}
@ -987,7 +987,7 @@ namespace UnitTest
m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList();
EXPECT_EQ(secondSeedList.size(), 0);
}
@ -1003,7 +1003,7 @@ namespace UnitTest
m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC);
m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC);
const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList();
EXPECT_EQ(secondSeedList.size(), 1);
}
@ -1017,7 +1017,7 @@ namespace UnitTest
EXPECT_EQ(seedList.size(), 1);
m_assetSeedManager->RemoveSeedAsset("Asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
m_assetSeedManager->RemoveSeedAsset("asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX);
const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList();
EXPECT_EQ(secondSeedList.size(), 1);
}

@ -56,7 +56,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
// Prevent re-sizing
setFixedSize(m_enforcedWidth, m_enforcedHeight);

@ -60,35 +60,35 @@
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="m_transparentVersion">
<property name="text">
@ -251,6 +251,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QSvgWidget</class>
<extends>QWidget</extends>
<header>qsvgwidget.h</header>
</customwidget>
<customwidget>
<class>ClickableLabel</class>
<extends>QLabel</extends>

@ -20,6 +20,7 @@
// AzCore
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/Utils/Utils.h>
// AzToolsFramework
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
@ -104,13 +105,9 @@ void AssetEditorWindow::SaveAssetAs(const AZStd::string_view assetPath)
return;
}
const char* engineRoot;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath);
auto absoluteAssetPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / assetPath;
AZStd::string absoluteAssetPath;
AzFramework::StringFunc::Path::Join(engineRoot, assetPath.data(), absoluteAssetPath);
if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath))
if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath.Native()))
{
AZ_Warning("Asset Editor", false, "File was not saved correctly via SaveAssetAs.");
}

@ -1617,11 +1617,6 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event)
// because we want the movement to be butter smooth.
if (!event->isAutoRepeat())
{
if (m_keyDown.isEmpty())
{
grabKeyboard();
}
m_keyDown.insert(event->key());
}

@ -96,6 +96,11 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
speedScale *= gSettings.cameraFastMoveSpeed;
}
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
{
m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength();
}
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
{
Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform());
@ -343,11 +348,15 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
}
shouldCaptureCursor = true;
// Record how much the cursor has been moved to see if we should own the mouse up event.
m_totalMouseMoveDelta = 0;
}
else if (state == InputChannel::State::Ended)
{
m_inZoomMode = false;
m_inRotateMode = false;
// If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it.
shouldConsumeEvent = m_totalMouseMoveDelta > 2;
shouldCaptureCursor = false;
}
}

@ -58,6 +58,7 @@ namespace SandboxEditor
bool m_inMoveMode = false;
bool m_inOrbitMode = false;
bool m_inZoomMode = false;
int m_totalMouseMoveDelta = 0;
float m_orbitDistance = 10.f;
float m_moveSpeed = 1.f;
AZ::Vector3 m_orbitTarget = {};

@ -1245,28 +1245,6 @@ uint32 DisplayContext::SetState(uint32 state)
return old;
}
//! Set a new render state flags.
//! @param returns previous render state.
uint32 DisplayContext::SetStateFlag(uint32 state)
{
uint32 old = m_renderState;
m_renderState |= state;
m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags;
pRenderAuxGeom->SetRenderFlags(m_renderState);
return old;
}
//! Clear specified flags in render state.
//! @param returns previous render state.
uint32 DisplayContext::ClearStateFlag(uint32 state)
{
uint32 old = m_renderState;
m_renderState &= ~state;
m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags;
pRenderAuxGeom->SetRenderFlags(m_renderState);
return old;
}
//////////////////////////////////////////////////////////////////////////
void DisplayContext::DepthTestOff()
{

@ -19,6 +19,8 @@
#include <QMessageBox>
#include <QFileDialog>
#include <AzCore/Utils/Utils.h>
// AzToolsFramework
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
@ -293,9 +295,8 @@ namespace
// If not found try editor folder
if (!CFileUtil::FileExists(path))
{
const char* engineRoot = nullptr;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath);
QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current();
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
QString scriptFolder = engineDir.absoluteFilePath("Editor/Scripts/");
Path::ConvertBackSlashToSlash(scriptFolder);

@ -49,7 +49,7 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
m_ui->m_TransparentConfidential->setObjectName("copyrightNotice");
m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText);

@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/StartupLogoDialog">
<file>lumberyard_logo.svg</file>
<file>o3de_logo.svg</file>
<file>splashscreen_1_27.png</file>
</qresource>
</RCC>

@ -42,14 +42,14 @@
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>50</height>
</size>
</property>
</widget>

@ -18,6 +18,8 @@
#include "ToolBox.h"
#include <AzCore/Utils/Utils.h>
// AzToolsFramework
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
@ -419,9 +421,8 @@ void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolb
}
}
const char* engineRoot = nullptr;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath);
QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current();
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
string enginePath = PathUtil::AddSlash(engineDir.absolutePath().toUtf8().data());

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 27 KiB

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="323px" height="98px" viewBox="0 0 323 98" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Group 12</title>
<defs>
<polygon id="path-1" points="0 97.741 322.084 97.741 322.084 0 0 0"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-12" transform="translate(0.000000, 0.000000)">
<path d="M99.7068,20.425 C91.1008,11.686 79.6658,6.841 67.5068,6.782 L67.2838,6.781 C62.9678,6.781 58.7408,7.396 54.6908,8.566 L54.6908,25.339 C58.5158,23.54 62.6988,22.563 67.0218,22.517 C67.1388,22.516 67.2538,22.515 67.3698,22.515 C75.1318,22.515 82.4608,25.519 88.0388,30.996 C93.7828,36.635 96.9708,44.124 97.0168,52.084 C97.0628,60.037 93.9658,67.554 88.2968,73.251 C82.6908,78.884 75.2578,82 67.3558,82.025 L67.2718,82.025 C59.4228,82.025 51.9878,78.959 46.3368,73.393 C40.6918,67.833 37.5578,60.397 37.5108,52.453 C37.4888,48.659 38.1798,44.975 39.5088,41.546 L23.0748,41.546 C19.4908,56.362 23.4348,72.648 34.9328,84.219 C43.5408,92.882 54.9608,97.683 67.0878,97.738 L67.3028,97.738 L67.3058,97.738 C79.3458,97.738 90.7008,93.045 99.2768,84.524 C107.8718,75.984 112.6488,64.62 112.7288,52.524 C112.8088,40.435 108.1838,29.035 99.7068,20.425" id="Fill-1" fill="#FFFFFF"></path>
<path d="M175.6326,27.8629 C175.6326,33.3889 173.9586,38.0879 170.6116,41.9599 C167.2646,45.8319 162.5656,48.4939 156.5146,49.9459 L156.5146,50.3089 C163.6536,51.1969 169.0586,53.3629 172.7296,56.8129 C176.3996,60.2619 178.2356,64.9099 178.2356,70.7579 C178.2356,79.2689 175.1496,85.8939 168.9786,90.6319 C162.8076,95.3719 153.9936,97.7409 142.5386,97.7409 C132.9386,97.7409 124.4286,96.1489 117.0076,92.9609 L117.0076,77.0489 C120.4356,78.7839 124.2076,80.1959 128.3216,81.2839 C132.4356,82.3729 136.5096,82.9179 140.5426,82.9179 C146.7146,82.9179 151.2716,81.8699 154.2156,79.7719 C157.1596,77.6749 158.6326,74.3079 158.6326,69.6679 C158.6326,65.5139 156.9386,62.5699 153.5506,60.8349 C150.1626,59.1009 144.7576,58.2329 137.3366,58.2329 L130.6206,58.2329 L130.6206,43.8939 L137.4576,43.8939 C144.3146,43.8939 149.3246,42.9979 152.4916,41.2019 C155.6576,39.4079 157.2406,36.3319 157.2406,31.9759 C157.2406,25.2809 153.0456,21.9329 144.6566,21.9329 C141.7526,21.9329 138.7986,22.4169 135.7936,23.3849 C132.7886,24.3529 129.4506,26.0279 125.7806,28.4069 L117.1306,15.5199 C125.1956,9.7119 134.8166,6.8079 145.9886,6.8079 C155.1446,6.8079 162.3736,8.6639 167.6786,12.3739 C172.9806,16.0869 175.6326,21.2499 175.6326,27.8629" id="Fill-3" fill="#FFFFFF"></path>
<path d="M241.8563,51.9425 C241.8563,32.9455 233.4653,23.4465 216.6883,23.4465 L206.7053,23.4465 L206.7053,81.0435 L214.7523,81.0435 C232.8213,81.0435 241.8563,71.3435 241.8563,51.9425 M261.3363,51.4595 C261.3363,66.0195 257.1933,77.1715 248.9043,84.9165 C240.6153,92.6605 228.6463,96.5325 212.9973,96.5325 L187.9503,96.5325 L187.9503,8.0815 L215.7193,8.0815 C230.1593,8.0815 241.3723,11.8925 249.3583,19.5155 C257.3433,27.1365 261.3363,37.7855 261.3363,51.4595" id="Fill-5" fill="#FFFFFF"></path>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-8"></g>
<polygon id="Fill-7" fill="#FFFFFF" mask="url(#mask-2)" points="23.185 30.421 45.046 30.421 45.046 8.56 23.185 8.56"></polygon>
<polygon id="Fill-9" fill="#FFFFFF" mask="url(#mask-2)" points="5.251 9.038 14.289 9.038 14.289 0 5.251 0"></polygon>
<polygon id="Fill-10" fill="#FFFFFF" mask="url(#mask-2)" points="0 36.195 14.18 36.195 14.18 22.015 0 22.015"></polygon>
<polygon id="Fill-11" fill="#FFFFFF" mask="url(#mask-2)" points="322.0838 96.4337 271.0538 96.4337 271.0538 7.8287 322.0838 7.8287 322.0838 23.2227 289.8418 23.2227 289.8418 42.6767 319.8418 42.6767 319.8418 58.0707 289.8418 58.0707 289.8418 80.9187 322.0838 80.9187"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@ -2777,26 +2777,6 @@ AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state)
return 0;
}
AZ::u32 SandboxIntegrationManager::SetStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->SetStateFlag(state);
}
return 0;
}
AZ::u32 SandboxIntegrationManager::ClearStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->ClearStateFlag(state);
}
return 0;
}
void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm)
{
if (m_dc)

@ -268,8 +268,6 @@ private:
bool SetDrawInFrontMode(bool bOn) override;
AZ::u32 GetState() override;
AZ::u32 SetState(AZ::u32 state) override;
AZ::u32 SetStateFlag(AZ::u32 state) override;
AZ::u32 ClearStateFlag(AZ::u32 state) override;
void PushMatrix(const AZ::Transform& tm) override;
void PopMatrix() override;

@ -12,6 +12,7 @@
#pragma once
#include <Authentication/AuthenticationProviderBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@ -28,74 +29,104 @@ namespace AWSClientAuth
OnPasswordGrantMultiFactorConfirmSignInSuccess, OnPasswordGrantMultiFactorConfirmSignInFail,
OnDeviceCodeGrantSignInSuccess, OnDeviceCodeGrantSignInFail,
OnDeviceCodeGrantConfirmSignInSuccess, OnDeviceCodeGrantConfirmSignInFail,
OnRefreshTokensSuccess, OnRefreshTokensFail,
OnSignOut
OnRefreshTokensSuccess, OnRefreshTokensFail
);
void OnPasswordGrantSingleFactorSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantSingleFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorSignInSuccess() override
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
AZ::TickBus::QueueFunction([this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
});
}
void OnPasswordGrantMultiFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantMultiFactorConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
});
}
void OnDeviceCodeGrantSignInSuccess(
const AZStd::string& userCode, const AZStd::string& verificationUrl, const int codeExpiresInSeconds) override
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
AZ::TickBus::QueueFunction([userCode, verificationUrl, codeExpiresInSeconds, this]()
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
});
}
void OnDeviceCodeGrantSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
});
}
void OnDeviceCodeGrantConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
});
}
void OnDeviceCodeGrantConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
});
}
void OnRefreshTokensSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
});
}
void OnRefreshTokensFail(const AZStd::string& error) override
{
Call(FN_OnRefreshTokensFail, error);
}
void OnSignOut(const ProviderNameEnum& provideName) override
{
Call(FN_OnSignOut, provideName);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRefreshTokensFail, error);
});
}
};
} // namespace AWSClientAuth

@ -16,6 +16,7 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <Authentication/AuthenticationProviderBus.h>
#include <Authentication/AuthenticationProviderScriptCanvasBus.h>
#include <Authentication/AuthenticationProviderInterface.h>
#include <Authentication/AuthenticationTokens.h>
@ -23,7 +24,8 @@ namespace AWSClientAuth
{
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
class AuthenticationProviderManager
: AuthenticationProviderRequestBus::Handler
: public AuthenticationProviderRequestBus::Handler
, public AuthenticationProviderScriptCanvasRequestBus::Handler
{
public:
AZ_RTTI(AuthenticationProviderManager, "{45813BA5-9A46-4A2A-A923-C79CFBA0E63D}", IAuthenticationProviderRequests);
@ -43,6 +45,22 @@ namespace AWSClientAuth
bool IsSignedIn(const ProviderNameEnum& providerName) override;
bool SignOut(const ProviderNameEnum& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override;
// AuthenticationProviderScriptCanvasRequest interface
bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) override;
void PasswordGrantSingleFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override;
void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) override;
void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) override;
void RefreshTokensAsync(const AZStd::string& providerName) override;
void GetTokensWithRefreshAsync(const AZStd::string& providerName) override;
bool IsSignedIn(const AZStd::string& providerName) override;
bool SignOut(const AZStd::string& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) override;
virtual AZStd::unique_ptr<AuthenticationProviderInterface> CreateAuthenticationProviderObject(const ProviderNameEnum& providerName);
AZStd::map<ProviderNameEnum, AZStd::unique_ptr<AuthenticationProviderInterface>> m_authenticationProvidersMap;
@ -50,9 +68,9 @@ namespace AWSClientAuth
private:
bool IsProviderInitialized(const ProviderNameEnum& providerName);
void ResetProviders();
ProviderNameEnum GetProviderNameEnum(AZStd::string name);
AZStd::shared_ptr<AZ::SettingsRegistryInterface> m_settingsRegistry;
};
} // namespace AWSClientAuth

@ -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.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <Authentication/AuthenticationTokens.h>
namespace AWSClientAuth
{
//! Abstract class for authentication provider script canvas requests.
//! Private class to allow provide names to be string type instead of an enum as behavior context does not work well with enum's.
class IAuthenticationProviderScriptCanvasRequests
{
public:
AZ_TYPE_INFO(IAuthenticationProviderRequests, "{A8FD915F-9FF2-4BA3-8AA0-8CF7A94A323B}");
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.
//! @param providerName Provider to check signed in for
//! @return bool True if valid access token available, else False
virtual bool IsSignedIn(const AZStd::string& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const AZStd::string& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.
//! @param providerName Provider to get access token for.
//! events: OnRefreshTokensSuccess, OnRefreshTokensFail
virtual void GetTokensWithRefreshAsync(const AZStd::string& providerName) = 0;
//! Signs user out.
//! Clears all cached tokens.
//! @param providerName Provider to sign out.
//! @return bool True: Successfully sign out.
virtual bool SignOut(const AZStd::string& providerName) = 0;
//////////////////////////////////////////////////////////////////////////
};
//! Authentication Request bus for different supported providers.
class AuthenticationProviderScriptCanvasRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
using MutexType = AZ::NullMutex;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
};
using AuthenticationProviderScriptCanvasRequestBus = AZ::EBus<IAuthenticationProviderScriptCanvasRequests, AuthenticationProviderScriptCanvasRequests>;
} // namespace AWSClientAuth

@ -15,6 +15,14 @@
namespace AWSClientAuth
{
constexpr char ProvideNameEnumStringNone[] = "None";
constexpr char ProvideNameEnumStringAWSCognitoIDP[] = "AWSCognitoIDP";
constexpr char ProvideNameEnumStringLoginWithAmazon[] = "LoginWithAmazon";
constexpr char ProvideNameEnumStringGoogle[] = "Google";
constexpr char ProvideNameEnumStringApple[] = "Apple";
constexpr char ProvideNameEnumStringFacebook[] = "Facebook";
constexpr char ProvideNameEnumStringTwitch[] = "Twitch";
//! Holds Login with Amazon provider serialized settings
class LWAProviderSetting
{

@ -12,6 +12,7 @@
#pragma once
#include <Authorization/AWSCognitoAuthorizationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AWSClientAuth
@ -28,12 +29,18 @@ namespace AWSClientAuth
void OnRequestAWSCredentialsSuccess(const ClientAuthAWSCredentials& awsCredentials) override
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
AZ::TickBus::QueueFunction([awsCredentials, this]()
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
});
}
void OnRequestAWSCredentialsFail(const AZStd::string& error) override
{
Call(FN_OnRequestAWSCredentialsFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRequestAWSCredentialsFail, error);
});
}
};
} // namespace AWSClientAuth

@ -12,6 +12,7 @@
#pragma once
#include <UserManagement/AWSCognitoUserManagementBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@ -32,62 +33,86 @@ namespace AWSClientAuth
void OnEmailSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnEmailSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnEmailSignUpSuccess, uuid);
});
}
void OnEmailSignUpFail(const AZStd::string& error) override
{
Call(FN_OnEmailSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEmailSignUpFail, error);
});
}
void OnPhoneSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnPhoneSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnPhoneSignUpSuccess, uuid);
});
}
void OnPhoneSignUpFail(const AZStd::string& error) override
{
Call(FN_OnPhoneSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnPhoneSignUpFail, error);
});
}
void OnConfirmSignUpSuccess() override
{
Call(FN_OnConfirmSignUpSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmSignUpSuccess);
});
}
void OnConfirmSignUpFail(const AZStd::string& error) override
{
Call(FN_OnConfirmSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmSignUpFail, error);
});
}
void OnForgotPasswordSuccess() override
{
Call(FN_OnForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnForgotPasswordSuccess);
});
}
void OnForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnForgotPasswordFail, error);
});
}
void OnConfirmForgotPasswordSuccess() override
{
Call(FN_OnConfirmForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmForgotPasswordSuccess);
});
}
void OnConfirmForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnConfirmForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmForgotPasswordFail, error);
});
}
void OnEnableMFASuccess() override
{
Call(FN_OnEnableMFASuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnEnableMFASuccess);
});
}
void OnEnableMFAFail(const AZStd::string& error) override
{
Call(FN_OnEnableMFAFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEnableMFAFail, error);
});
}
};
} // namespace AWSClientAuth

@ -16,7 +16,7 @@
namespace AWSClientAuth
{
//@ Abstract class for authentication provider requests.
//! Abstract class for authentication provider requests.
class IAuthenticationProviderRequests
{
public:
@ -35,32 +35,40 @@ namespace AWSClientAuth
virtual bool IsSignedIn(const ProviderNameEnum& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens.
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.

@ -11,20 +11,15 @@
*/
#pragma once
#include <AzCore/Preprocessor/Enum.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/chrono/clocks.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AWSClientAuth
{
enum class ProviderNameEnum
{
None,
AWSCognitoIDP,
LoginWithAmazon,
Google,
Apple,
Facebook
};
AZ_ENUM_CLASS(ProviderNameEnum, None, AWSCognitoIDP, LoginWithAmazon, Twitch, Google, Apple, Facebook);
//! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController.
class AuthenticationTokens
@ -55,6 +50,8 @@ namespace AWSClientAuth
//! @return Expiration time in seconds.
int GetTokensExpireTimeSeconds() const;
static void Reflect(AZ::ReflectContext* context);
private:
int m_tokensExpireTimeSeconds = 0;
AZStd::string m_accessToken;

@ -12,7 +12,7 @@
#pragma once
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/string/string.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
@ -24,6 +24,14 @@ namespace AWSClientAuth
{
public:
AZ_TYPE_INFO(ClientAuthAWSCredentials, "{02FB32C4-B94E-4084-9049-3DF32F87BD76}");
ClientAuthAWSCredentials() = default;
ClientAuthAWSCredentials(const ClientAuthAWSCredentials& other)
: m_accessKeyId(other.m_accessKeyId)
, m_secretKey(other.m_secretKey)
, m_sessionToken(other.m_sessionToken)
{
}
ClientAuthAWSCredentials(const AZStd::string& accessKeyId, const AZStd::string& secretKey, const AZStd::string& sessionToken)
{
@ -50,6 +58,32 @@ namespace AWSClientAuth
return m_sessionToken;
}
static void Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ClientAuthAWSCredentials>()
->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId)
->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey)
->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<ClientAuthAWSCredentials>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const ClientAuthAWSCredentials&>()
->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId))
->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey))
->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken));
}
}
private:
AZStd::string m_accessKeyId;
AZStd::string m_secretKey;

@ -22,11 +22,12 @@ namespace AWSClientAuth
public:
AZ_TYPE_INFO(IAWSCognitoUserManagementRequests, "{A4C90F21-7056-4827-8C6B-401E6945697D}");
//! Initialize Cognito User pool.
//! Initialize Cognito User pool using settings from resource mappings.
//! @param settingsRegistryPath settingsRegistryPath Path for the settings registry file to use.
virtual bool Initialize() = 0;
// Requests interface
//! Cognito user pool email sign up start.
//! @param username User name to use for sign up.
//! @param password Password to use for sign up.
@ -59,7 +60,7 @@ namespace AWSClientAuth
virtual void EnableMFAAsync(const AZStd::string& accessToken) = 0;
};
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
//! Implements AWS Cognito user pool user management requests.
class AWSCognitoUserManagementRequests
: public AZ::EBusTraits
{

@ -22,6 +22,11 @@
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}");
}
namespace AWSClientAuth
{
constexpr char SerializeComponentName[] = "AWSClientAuth";
@ -44,20 +49,35 @@ namespace AWSClientAuth
AWSClientAuth::GoogleProviderSetting::Reflect(*serialize);
}
AWSClientAuth::AuthenticationTokens::Reflect(context);
AWSClientAuth::ClientAuthAWSCredentials::Reflect(context);
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AuthenticationProviderRequestBus>("AuthenticationProviderRequestBus")
behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None")
->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP")
->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon")
->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google");
behaviorContext->EBus<AuthenticationProviderScriptCanvasRequestBus>("AuthenticationProviderRequestBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens)
->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens)
->Event(
"PasswordGrantSingleFactorSignInAsync",
&AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantSingleFactorSignInAsync)
->Event(
"PasswordGrantSingleFactorSignInAsync", &AuthenticationProviderRequestBus::Events::PasswordGrantSingleFactorSignInAsync)
->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantSignInAsync)
->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantConfirmSignInAsync)
->Event("RefreshTokensAsync", &AuthenticationProviderRequestBus::Events::RefreshTokensAsync)
->Event("GetTokensWithRefreshAsync", &AuthenticationProviderRequestBus::Events::GetTokensWithRefreshAsync)
->Event("SignOut", &AuthenticationProviderRequestBus::Events::SignOut);
"PasswordGrantMultiFactorSignInAsync",
&AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorSignInAsync)
->Event(
"PasswordGrantMultiFactorConfirmSignInAsync",
&AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorConfirmSignInAsync)
->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantSignInAsync)
->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantConfirmSignInAsync)
->Event("RefreshTokensAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::RefreshTokensAsync)
->Event("GetTokensWithRefreshAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::GetTokensWithRefreshAsync)
->Event("SignOut", &AuthenticationProviderScriptCanvasRequestBus::Events::SignOut);
behaviorContext->EBus<AWSCognitoAuthorizationRequestBus>("AWSCognitoAuthorizationRequestBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
@ -77,11 +97,15 @@ namespace AWSClientAuth
->Event("ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync)
->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync);
behaviorContext->EBus<AuthenticationProviderNotificationBus>("AuthenticationProviderNotificationBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Handler<AuthenticationNotificationBusBehaviorHandler>();
behaviorContext->EBus<AWSCognitoUserManagementNotificationBus>("AWSCognitoUserManagementNotificationBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Handler<UserManagementNotificationBusBehaviorHandler>();
behaviorContext->EBus<AWSCognitoAuthorizationNotificationBus>("AWSCognitoAuthorizationNotificationBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Handler<AWSCognitoAuthorizationNotificationBusBehaviorHandler>();
}
}

@ -40,7 +40,7 @@ namespace AWSClientAuth
AZ_UNUSED(settingsRegistry);
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey);
AZ_Warning("AWSCognitoAuthenticationProvider", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
AZ_Warning("AWSCognitoAuthenticationProvider", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
return !m_cognitoAppClientId.empty();
}

@ -12,6 +12,7 @@
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/IO/FileIO.h>
#include <Authentication/AuthenticationProviderTypes.h>
#include <Authentication/AWSCognitoAuthenticationProvider.h>
@ -25,12 +26,14 @@ namespace AWSClientAuth
{
AZ::Interface<IAuthenticationProviderRequests>::Register(this);
AuthenticationProviderRequestBus::Handler::BusConnect();
AuthenticationProviderScriptCanvasRequestBus::Handler::BusConnect();
}
AuthenticationProviderManager::~AuthenticationProviderManager()
{
ResetProviders();
m_settingsRegistry.reset();
AuthenticationProviderScriptCanvasRequestBus::Handler::BusDisconnect();
AuthenticationProviderRequestBus::Handler::BusDisconnect();
AZ::Interface<IAuthenticationProviderRequests>::Unregister(this);
}
@ -38,12 +41,19 @@ namespace AWSClientAuth
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath)
{
ResetProviders();
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
AZ_Assert(fileIO, "File IO is not initialized.");
m_settingsRegistry.reset();
m_settingsRegistry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
if (!m_settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
AZStd::array<char, AZ::IO::MaxPathLength> resolvedPath{};
AZ::IO::FileIOBase::GetInstance()->ResolvePath(settingsRegistryPath.data(), resolvedPath.data(), resolvedPath.size());
if (!m_settingsRegistry->MergeSettingsFile(resolvedPath.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch))
{
AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", settingsRegistryPath.c_str());
AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", resolvedPath.data());
return false;
}
@ -112,6 +122,7 @@ namespace AWSClientAuth
{
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
, "Provider is not initialized");
return;
}
AuthenticationTokens tokens = m_authenticationProvidersMap[providerName]->GetAuthenticationTokens();
@ -181,5 +192,77 @@ namespace AWSClientAuth
}
}
ProviderNameEnum AuthenticationProviderManager::GetProviderNameEnum(AZStd::string name)
{
auto enumValue = ProviderNameEnumNamespace::FromStringToProviderNameEnum(name);
if (enumValue.has_value())
{
return enumValue.value();
}
AZ_Warning("AuthenticationProviderManager", true, "Incorrect string value for enum: %s", name.c_str());
return ProviderNameEnum::None;
}
bool AuthenticationProviderManager::Initialize(
const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath)
{
AZStd::vector<ProviderNameEnum> providerNamesEnum;
for (auto name : providerNames)
{
providerNamesEnum.push_back(GetProviderNameEnum(name));
}
return Initialize(providerNamesEnum, settingsRegistryPath);
}
void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password)
{
PasswordGrantSingleFactorSignInAsync(GetProviderNameEnum(providerName), username, password);
}
void AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password)
{
PasswordGrantMultiFactorSignInAsync(GetProviderNameEnum(providerName), username, password);
}
void AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode)
{
PasswordGrantMultiFactorConfirmSignInAsync(GetProviderNameEnum(providerName), username, confirmationCode);
}
void AuthenticationProviderManager::DeviceCodeGrantSignInAsync(const AZStd::string& providerName)
{
DeviceCodeGrantSignInAsync(GetProviderNameEnum(providerName));
}
void AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName)
{
DeviceCodeGrantConfirmSignInAsync(GetProviderNameEnum(providerName));
}
void AuthenticationProviderManager::RefreshTokensAsync(const AZStd::string& providerName)
{
RefreshTokensAsync(GetProviderNameEnum(providerName));
}
void AuthenticationProviderManager::GetTokensWithRefreshAsync(const AZStd::string& providerName)
{
GetTokensWithRefreshAsync(GetProviderNameEnum(providerName));
}
bool AuthenticationProviderManager::IsSignedIn(const AZStd::string& providerName)
{
return IsSignedIn(GetProviderNameEnum(providerName));
}
bool AuthenticationProviderManager::SignOut(const AZStd::string& providerName)
{
return SignOut(GetProviderNameEnum(providerName));
}
AuthenticationTokens AuthenticationProviderManager::GetAuthenticationTokens(const AZStd::string& providerName)
{
return GetAuthenticationTokens(GetProviderNameEnum(providerName));
}
} // namespace AWSClientAuth

@ -79,4 +79,30 @@ namespace AWSClientAuth
{
return m_tokensExpireTimeSeconds;
}
void AuthenticationTokens::Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<AuthenticationTokens>()
->Field("AccessToken", &AuthenticationTokens::m_accessToken)
->Field("OpenIdToken", &AuthenticationTokens::m_openIdToken)
->Field("RefreshToken", &AuthenticationTokens::m_refreshToken);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<AuthenticationTokens>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const AuthenticationTokens&>()
->Property("AccessToken", BehaviorValueGetter(&AuthenticationTokens::m_accessToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken))
->Property("OpenIdToken", BehaviorValueGetter(&AuthenticationTokens::m_openIdToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken))
->Property("RefreshToken", BehaviorValueGetter(&AuthenticationTokens::m_refreshToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken));
}
}
} // namespace AWSClientAuth

@ -71,15 +71,15 @@ namespace AWSClientAuth
if (m_awsAccountId.empty() || m_cognitoIdentityPoolId.empty())
{
AZ_Warning("AWSCognitoUserManagementController", m_awsAccountId.empty(), "Missing AWS account id in resource mappings.");
AZ_Warning("AWSCognitoUserManagementController", m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings.");
AZ_Warning("AWSCognitoAuthorizationController", !m_awsAccountId.empty(), "Missing AWS account id not configured.");
AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings.");
return false;
}
AZStd::string userPoolId;
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
userPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoUserPoolIdResourceMappingKey);
AZ_Warning("AWSCognitoUserManagementController", userPoolId.empty(), "Missing Cognito USer pool id in resource mappings. Cognito IDP authenticated identities will no work.");
AZ_Warning("AWSCognitoAuthorizationController", !userPoolId.empty(), "Missing Cognito User pool id in resource mappings. Cognito IDP authenticated identities will no work.");
AZStd::string defaultRegion;
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(

@ -54,7 +54,7 @@ namespace AWSClientAuth
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey);
AZ_Warning(
"AWSCognitoUserManagementController", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
"AWSCognitoUserManagementController", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
return !m_cognitoAppClientId.empty();
}

@ -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
#include <AWSClientAuthGemMock.h>
#include <Authentication/AuthenticationProviderManager.h>
namespace AWSClientAuthUnitTest
{
class AuthenticationProviderManagerLocalMock
: public AWSClientAuth::AuthenticationProviderManager
{
public:
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens;
using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync;
using AWSClientAuth::AuthenticationProviderManager::Initialize;
using AWSClientAuth::AuthenticationProviderManager::IsSignedIn;
using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync;
using AWSClientAuth::AuthenticationProviderManager::SignOut;
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface> CreateAuthenticationProviderObjectMock(
const AWSClientAuth::ProviderNameEnum& providerName)
{
auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName);
providerObject.reset();
return AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>>();
}
AuthenticationProviderManagerLocalMock()
{
ON_CALL(*this, CreateAuthenticationProviderObject(testing::_))
.WillByDefault(testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock));
}
MOCK_METHOD1(
CreateAuthenticationProviderObject,
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface>(const AWSClientAuth::ProviderNameEnum&));
};
} // namespace AWSClientAuthUnitTest

@ -0,0 +1,261 @@
/*
* 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/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/std/utils.h>
#include <Authentication/AuthenticationProviderManager.h>
#include <Authentication/AWSCognitoAuthenticationProvider.h>
#include <Authentication/LWAAuthenticationProvider.h>
#include <Authentication/AuthenticationTokens.h>
#include <Authentication/AuthenticationProviderTypes.h>
#include <AWSClientAuthGemMock.h>
#include <Authentication/AuthenticationProviderManagerMock.h>
class AuthenticationProviderManagerScriptCanvasTest
: public AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture
{
protected:
void SetUp() override
{
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp();
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
"AWS":
{
"LoginWithAmazon":
{
"AppClientId": "TestLWAClientId",
"GrantType": "device_code",
"Scope": "profile",
"ResponseType": "device_code",
"OAuthCodeURL": "https://api.amazon.com/auth/o2/create/codepair",
"OAuthTokensURL": "https://oauth2.googleapis.com/token"
},
"Google":
{
"AppClientId": "TestGoogleClientId",
"ClientSecret": "123",
"GrantType": "urn:ietf:params:oauth:grant-type:device_code",
"Scope": "profile",
"OAuthCodeURL": "https://oauth2.googleapis.com/device/code",
"OAuthTokensURL": "https://oauth2.googleapis.com/token"
}
}
})");
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
void TearDown() override
{
m_mockController.reset();
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::TearDown();
}
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AZStd::string> m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP,
AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle};
};
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Fail_NonConfiguredProviderError)
{
AZ_TEST_START_TRACE_SUPPRESSION;
m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringApple, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 600);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail)
{
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
m_mockController->GetAuthenticationTokens(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
m_mockController->IsSignedIn(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnSignOut(testing::_)).Times(1);
m_mockController->SignOut(AWSClientAuth::ProvideNameEnumStringGoogle);
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}

@ -10,8 +10,6 @@
*
*/
#include <AzTest/AzTest.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/std/utils.h>
@ -20,42 +18,7 @@
#include <Authentication/LWAAuthenticationProvider.h>
#include <Authentication/AuthenticationTokens.h>
#include <AWSClientAuthGemMock.h>
namespace AWSClientAuthUnitTest
{
class AuthenticationProviderManagerLocalMock
: public AWSClientAuth::AuthenticationProviderManager
{
public:
using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap;
using AWSClientAuth::AuthenticationProviderManager::Initialize;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync;
using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync;
using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens;
using AWSClientAuth::AuthenticationProviderManager::SignOut;
using AWSClientAuth::AuthenticationProviderManager::IsSignedIn;
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface> CreateAuthenticationProviderObjectMock(const AWSClientAuth::ProviderNameEnum& providerName)
{
auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName);
providerObject.reset();
return AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>>();
}
AuthenticationProviderManagerLocalMock()
{
ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)).WillByDefault(
testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock));
}
MOCK_METHOD1(CreateAuthenticationProviderObject, AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface>(const AWSClientAuth::ProviderNameEnum&));
};
}
#include <Authentication/AuthenticationProviderManagerMock.h>
class AuthenticationProviderManagerTest
@ -239,6 +202,15 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail)
{
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProviderNameEnum::AWSCognitoIDP);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);

@ -20,6 +20,7 @@ set(FILES
Include/Private/AWSClientAuthBus.h
Include/Private/AWSClientAuthResourceMappingConstants.h
Include/Private/Authentication/AuthenticationProviderTypes.h
Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h
Include/Private/Authentication/AuthenticationProviderManager.h
Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h

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

Loading…
Cancel
Save