Merge branch 'main' into sceneapi_script_regression
This commit is contained in:
@@ -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
|
||||
+2
-2
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
@@ -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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2 check if the engine_path key has been supplied
|
||||
if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty())
|
||||
{
|
||||
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())
|
||||
{
|
||||
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.
|
||||
|
||||
@@ -607,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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+3
-3
@@ -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());
|
||||
}
|
||||
|
||||
+24
-21
@@ -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,
|
||||
@@ -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)
|
||||
[&cameraView, &cameraProjection, &screenOffset]
|
||||
(const AZ::Vector3& axis)
|
||||
{
|
||||
return AZ::Vector2ToVector3(AzFramework::Vector2FromScreenPoint(
|
||||
AzFramework::WorldToScreen(
|
||||
position, cameraView, cameraProjection, gizmoCameraState.m_viewportSize))) + screenPosition;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+50
-19
@@ -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
|
||||
|
||||
+20
-2
@@ -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
|
||||
|
||||
+103
@@ -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
|
||||
{
|
||||
|
||||
+9
-2
@@ -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
|
||||
|
||||
+37
-12
@@ -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", &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);
|
||||
"PasswordGrantSingleFactorSignInAsync",
|
||||
&AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantSingleFactorSignInAsync)
|
||||
->Event(
|
||||
"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(
|
||||
|
||||
+1
-1
@@ -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
|
||||
+261
@@ -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
-38
@@ -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
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ set(FILES
|
||||
Tests/AWSClientAuthGemTest.cpp
|
||||
|
||||
Tests/AWSClientAuthSystemComponentTest.cpp
|
||||
Tests/Authentication/AuthenticationProviderManagerMock.h
|
||||
Tests/Authentication/AuthenticationProviderManagerTest.cpp
|
||||
Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp
|
||||
Tests/Authentication/AWSCognitoAuthenticationProviderTest.cpp
|
||||
Tests/Authentication/LWAAuthenticationProviderTest.cpp
|
||||
Tests/Authentication/GoogleAuthenticationProviderTest.cpp
|
||||
|
||||
@@ -56,8 +56,7 @@ class CognitoIdentityPoolRole:
|
||||
# basic permissions
|
||||
stack_statement = iam.PolicyStatement(
|
||||
actions=[
|
||||
's3:Get*',
|
||||
's3:List*'
|
||||
's3:ListBuckets'
|
||||
],
|
||||
effect=iam.Effect.ALLOW,
|
||||
resources=[
|
||||
|
||||
@@ -49,11 +49,6 @@
|
||||
"IsArray": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "DepthStencilInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
},
|
||||
{
|
||||
"Name": "TileLightData",
|
||||
"SlotType": "Input",
|
||||
@@ -66,6 +61,13 @@
|
||||
"ShaderInputName": "m_lightListRemapped",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
// Input/Outputs...
|
||||
{
|
||||
"Name": "DepthStencilInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
},
|
||||
// Outputs...
|
||||
{
|
||||
"Name": "DiffuseOutput",
|
||||
"SlotType": "Output",
|
||||
@@ -222,11 +224,12 @@
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
"MultisampleSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "DepthStencilInputOutput"
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R8G8B8A8_UNORM",
|
||||
"MultisampleState": {
|
||||
"samples": 4
|
||||
},
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "Output",
|
||||
"SlotType": 2
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
}
|
||||
],
|
||||
"PassRequests": [
|
||||
@@ -101,13 +102,8 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DepthMSAAPass",
|
||||
"TemplateName": "EnvironmentCubeMapDepthMSAAPassTemplate",
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "depth",
|
||||
"PipelineViewTag": "MainCamera"
|
||||
},
|
||||
"Name": "DepthPrePass",
|
||||
"TemplateName": "DepthMSAAParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
@@ -115,70 +111,11 @@
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
// The light culling system can do highly accurate culling of transparent objects but it needs
|
||||
// more depth information than the opaque geometry pass can provide
|
||||
// Specifically the minimum and maximum depth of transparent objects
|
||||
{
|
||||
"Name": "DepthTransparentMinPass",
|
||||
"TemplateName": "DepthPassTemplate",
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "depthTransparentMin",
|
||||
"PipelineViewTag": "MainCamera"
|
||||
},
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DepthTransparentMaxPass",
|
||||
"TemplateName": "DepthMaxPassTemplate",
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "depthTransparentMax",
|
||||
"PipelineViewTag": "MainCamera"
|
||||
},
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LightCullingTilePreparePass",
|
||||
"TemplateName": "LightCullingTilePrepareMSAATemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Depth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthMSAAPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthTransparentMin",
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthTransparentMinPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthTransparentMax",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthTransparentMaxPass",
|
||||
"Pass": "Parent",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
@@ -186,40 +123,27 @@
|
||||
},
|
||||
{
|
||||
"Name": "LightCullingPass",
|
||||
"TemplateName": "LightCullingTemplate",
|
||||
"TemplateName": "LightCullingParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingTilePreparePass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LightCullingRemapPass",
|
||||
"TemplateName": "LightCullingRemapTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingTilePreparePass",
|
||||
"Attachment": "TileLightData"
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightCount",
|
||||
"LocalSlot": "DepthMSAA",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightCount"
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightList",
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightList"
|
||||
"Pass": "Parent",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -259,21 +183,21 @@
|
||||
{
|
||||
"LocalSlot": "DepthStencilInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthMSAAPass",
|
||||
"Attachment": "Output"
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingRemapPass",
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightListRemapped",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingRemapPass",
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightListRemapped"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@
|
||||
"Attachment": "SpecularInputOutput"
|
||||
}
|
||||
},
|
||||
"MultisampleSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "SpecularInputOutput"
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"MultisampleState": {
|
||||
"samples": 4
|
||||
},
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace AZ
|
||||
void AuxGeomDrawQueue::DrawQuad(
|
||||
float width,
|
||||
float height,
|
||||
const AZ::Transform& transform,
|
||||
const AZ::Matrix3x4& transform,
|
||||
const AZ::Color& color,
|
||||
DrawStyle style,
|
||||
DepthTest depthTest,
|
||||
@@ -302,8 +302,8 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
Transform noScaleTransform = transform;
|
||||
noScaleTransform.ExtractScale();
|
||||
AZ::Matrix3x4 noScaleTransform = transform;
|
||||
AZ::Vector3 scale = noScaleTransform.ExtractScale();
|
||||
|
||||
ShapeBufferEntry shape;
|
||||
shape.m_shapeType = ShapeType_Quad;
|
||||
@@ -311,9 +311,9 @@ namespace AZ
|
||||
shape.m_depthWrite = ConvertRPIDepthWriteFlag(depthWrite);
|
||||
shape.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull);
|
||||
shape.m_color = color;
|
||||
shape.m_rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
|
||||
shape.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleTransform);
|
||||
shape.m_position = transform.GetTranslation();
|
||||
shape.m_scale = transform.GetScale() * Vector3(width, 1.0f, height);
|
||||
shape.m_scale = scale * Vector3(width, 1.0f, height);
|
||||
shape.m_pointSize = m_pointSize;
|
||||
shape.m_viewProjOverrideIndex = viewProjOverrideIndex;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
void DrawTriangles(const AuxGeomDynamicIndexedDrawArguments& args, FaceCullMode faceCull = FaceCullMode::None) override;
|
||||
|
||||
// Fixed shape draws
|
||||
void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override;
|
||||
void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override;
|
||||
void DrawSphere(const AZ::Vector3& center, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override;
|
||||
void DrawDisk(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override;
|
||||
void DrawCone(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, float height, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override;
|
||||
|
||||
@@ -131,8 +131,13 @@ namespace AZ
|
||||
AZ_Assert(m_blendedLut.m_lutImage != nullptr, "BlendColorGradingLutsPass unable to acquire LUT image");
|
||||
|
||||
AZ::RHI::AttachmentId imageAttachmentId = AZ::RHI::AttachmentId("BlendColorGradingLutImageAttachmentId");
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage);
|
||||
AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import compute buffer with error %d", result);
|
||||
|
||||
// import this attachment if it wasn't imported
|
||||
if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(imageAttachmentId))
|
||||
{
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage);
|
||||
AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import BlendColorGradingLutImageAttachmentId with error %d", result);
|
||||
}
|
||||
|
||||
RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = imageAttachmentId;
|
||||
|
||||
@@ -248,6 +248,9 @@ namespace AZ
|
||||
|
||||
AZ::RPI::RenderPipelineDescriptor environmentCubeMapPipelineDesc;
|
||||
environmentCubeMapPipelineDesc.m_mainViewTagName = "MainCamera";
|
||||
environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4;
|
||||
environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_width = RPI::EnvironmentCubeMapPass::CubeMapFaceSize;
|
||||
environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_height = RPI::EnvironmentCubeMapPass::CubeMapFaceSize;
|
||||
|
||||
// create a unique name for the pipeline
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
|
||||
@@ -16,6 +16,6 @@ namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
bool Validation::s_isEnabled = BuildOptions::IsDebugBuild;
|
||||
bool Validation::s_isEnabled = BuildOptions::IsDebugBuild || BuildOptions::IsProfileBuild;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +404,12 @@ namespace AZ
|
||||
Buffer& buffer = static_cast<Buffer&>(*bufferFrameAttachment.GetBuffer());
|
||||
RHI::BufferScopeAttachment* scopeAttachment = bufferFrameAttachment.GetFirstScopeAttachment();
|
||||
|
||||
if (scopeAttachment == nullptr)
|
||||
{
|
||||
AZ_WarningOnce("RHI", false, "Imported BufferFrameAttachment isn't used in any Scope");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_TRANSITION_BARRIER transition;
|
||||
transition.pResource = buffer.GetMemoryView().GetMemory();
|
||||
transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
@@ -471,6 +477,12 @@ namespace AZ
|
||||
Image& image = static_cast<Image&>(*imageFrameAttachment.GetImage());
|
||||
RHI::ImageScopeAttachment* scopeAttachment = imageFrameAttachment.GetFirstScopeAttachment();
|
||||
|
||||
if (scopeAttachment == nullptr)
|
||||
{
|
||||
AZ_WarningOnce("RHI", false, "Imported ImageFrameAttachment isn't used in any Scope");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_TRANSITION_BARRIER transition;
|
||||
transition.pResource = image.GetMemoryView().GetMemory();
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace AZ
|
||||
//! @param depthWrite If depth writing should be enabled
|
||||
//! @param faceCull Which (if any) facing triangles should be culled
|
||||
//! @param viewProjOverrideIndex Which view projection override entry to use, -1 if unused
|
||||
virtual void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0;
|
||||
virtual void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0;
|
||||
|
||||
//! Draw a sphere.
|
||||
//! @param center The center of the sphere.
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace AZ
|
||||
PassConnection childInputConnection;
|
||||
childInputConnection.m_localSlot = "Output";
|
||||
childInputConnection.m_attachmentRef.m_pass = "Parent";
|
||||
childInputConnection.m_attachmentRef.m_attachment = "CubeMapOutput";
|
||||
childInputConnection.m_attachmentRef.m_attachment = "Output";
|
||||
childRequest.m_connections.emplace_back(childInputConnection);
|
||||
|
||||
PassSystemInterface* passSystem = PassSystemInterface::Get();
|
||||
@@ -120,15 +120,16 @@ namespace AZ
|
||||
|
||||
// create output PassAttachment
|
||||
m_passAttachment = aznew PassAttachment();
|
||||
m_passAttachment->m_name = "CubeMapOutput";
|
||||
m_passAttachment->m_path = "CubeMapOutput";
|
||||
m_passAttachment->m_name = "Output";
|
||||
AZ::Name attachmentPath(AZStd::string::format("%s.%s", GetPathName().GetCStr(), m_passAttachment->m_name.GetCStr()));
|
||||
m_passAttachment->m_path = attachmentPath;
|
||||
m_passAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient;
|
||||
m_passAttachment->m_descriptor = m_outputImageDesc;
|
||||
|
||||
// create pass attachment binding
|
||||
PassAttachmentBinding outputAttachment;
|
||||
outputAttachment.m_name = "CubeMapOutput";
|
||||
outputAttachment.m_slotType = PassSlotType::Output;
|
||||
outputAttachment.m_name = "Output";
|
||||
outputAttachment.m_slotType = PassSlotType::InputOutput;
|
||||
outputAttachment.m_attachment = m_passAttachment;
|
||||
outputAttachment.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::RenderTarget;
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ namespace AZ
|
||||
{
|
||||
namespace RPI
|
||||
{
|
||||
bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild;
|
||||
bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild || RHI::BuildOptions::IsProfileBuild;
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -53,6 +53,9 @@ namespace MaterialEditor
|
||||
//! Modify camera's field of view
|
||||
//! @param value field of view in degrees
|
||||
virtual void SetFieldOfView(float value) = 0;
|
||||
|
||||
//! Check if camera is looking directly at a model
|
||||
virtual bool IsCameraCentered() const = 0;
|
||||
};
|
||||
|
||||
using MaterialEditorViewportInputControllerRequestBus = AZ::EBus<MaterialEditorViewportInputControllerRequests>;
|
||||
|
||||
@@ -76,11 +76,35 @@ namespace MaterialEditor
|
||||
void Behavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z)
|
||||
{
|
||||
m_distanceToTarget = m_distanceToTarget - z;
|
||||
|
||||
bool isCameraCentered = false;
|
||||
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
|
||||
isCameraCentered,
|
||||
&MaterialEditorViewportInputControllerRequestBus::Handler::IsCameraCentered);
|
||||
|
||||
// if camera is looking at the model (locked to the model) we don't want to zoom past the model's center
|
||||
if (isCameraCentered)
|
||||
{
|
||||
m_distanceToTarget = AZ::GetMax(m_distanceToTarget, 0.0f);
|
||||
}
|
||||
|
||||
AZ::Transform transform = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
|
||||
AZ::Vector3 position = m_targetPosition -
|
||||
transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget));
|
||||
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position);
|
||||
|
||||
// if camera is not locked to the model, move its focal point so we can free look
|
||||
if (!isCameraCentered)
|
||||
{
|
||||
m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z));
|
||||
MaterialEditorViewportInputControllerRequestBus::Broadcast(
|
||||
&MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition,
|
||||
m_targetPosition);
|
||||
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
|
||||
m_distanceToTarget,
|
||||
&MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget);
|
||||
}
|
||||
}
|
||||
|
||||
float Behavior::GetSensitivityX()
|
||||
|
||||
+13
@@ -96,6 +96,7 @@ namespace MaterialEditor
|
||||
void MaterialEditorViewportInputController::SetTargetPosition(const AZ::Vector3& targetPosition)
|
||||
{
|
||||
m_targetPosition = targetPosition;
|
||||
m_isCameraCentered = false;
|
||||
}
|
||||
|
||||
float MaterialEditorViewportInputController::GetDistanceToTarget() const
|
||||
@@ -246,6 +247,7 @@ namespace MaterialEditor
|
||||
cameraPosition = cameraRotation.TransformVector(cameraPosition);
|
||||
AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition);
|
||||
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, cameraTransform);
|
||||
m_isCameraCentered = true;
|
||||
|
||||
// reset model
|
||||
AZ::Transform modelTransform = AZ::Transform::CreateIdentity();
|
||||
@@ -258,6 +260,12 @@ namespace MaterialEditor
|
||||
AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
|
||||
auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor<AZ::Render::SkyBoxFeatureProcessorInterface>();
|
||||
skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix);
|
||||
|
||||
if (m_behavior)
|
||||
{
|
||||
m_behavior->End();
|
||||
m_behavior->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEditorViewportInputController::SetFieldOfView(float value)
|
||||
@@ -265,6 +273,11 @@ namespace MaterialEditor
|
||||
Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value);
|
||||
}
|
||||
|
||||
bool MaterialEditorViewportInputController::IsCameraCentered() const
|
||||
{
|
||||
return m_isCameraCentered;
|
||||
}
|
||||
|
||||
void MaterialEditorViewportInputController::CalculateExtents()
|
||||
{
|
||||
AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation);
|
||||
|
||||
+3
@@ -45,6 +45,7 @@ namespace MaterialEditor
|
||||
void GetExtents(float& distanceMin, float& distanceMax) const override;
|
||||
void Reset() override;
|
||||
void SetFieldOfView(float value) override;
|
||||
bool IsCameraCentered() const override;
|
||||
|
||||
// AzFramework::ViewportControllerInstance interface overrides...
|
||||
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
|
||||
@@ -95,6 +96,8 @@ namespace MaterialEditor
|
||||
float m_distanceMin = 1.0f;
|
||||
//! Maximum distance from camera to target
|
||||
float m_distanceMax = 10.0f;
|
||||
//! True if camera is centered on a model
|
||||
bool m_isCameraCentered = true;
|
||||
|
||||
static constexpr float MaxDistanceMultiplier = 2.5f;
|
||||
static constexpr float StartingDistanceMultiplier = 2.0f;
|
||||
|
||||
+1
-3
@@ -34,10 +34,8 @@ namespace MaterialEditor
|
||||
targetPosition);
|
||||
}
|
||||
|
||||
void PanCameraBehavior::TickInternal(float x, float y, float z)
|
||||
void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z)
|
||||
{
|
||||
Behavior::TickInternal(x, y, z);
|
||||
|
||||
AZ::Transform transform = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM);
|
||||
AZ::Quaternion rotation = transform.GetRotation();
|
||||
|
||||
+21
-8
@@ -60,13 +60,17 @@ namespace MaterialEditor
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, enumerateCB, nullptr);
|
||||
|
||||
//Update the material type file info whenever the combo box selection changes
|
||||
QObject::connect(m_ui->m_materialTypeComboBox, static_cast<void(QComboBox::*)(const int)>(&QComboBox::currentIndexChanged), m_ui->m_materialTypeComboBox, [this](int index) {
|
||||
QVariant data = m_ui->m_materialTypeComboBox->itemData(index);
|
||||
m_materialTypeFileInfo = QFileInfo(data.toString());
|
||||
});
|
||||
QObject::connect(m_ui->m_materialTypeComboBox, static_cast<void (QComboBox::*)(const int)>(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); });
|
||||
QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); });
|
||||
|
||||
//Select StandardPBR by default but we will later data drive this with editor settings
|
||||
m_ui->m_materialTypeComboBox->setCurrentText("StandardPBR");
|
||||
// Select StandardPBR by default but we will later data drive this with editor settings
|
||||
const int index = m_ui->m_materialTypeComboBox->findText("StandardPBR");
|
||||
if (index >= 0)
|
||||
{
|
||||
m_ui->m_materialTypeComboBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
UpdateMaterialTypeSelection();
|
||||
}
|
||||
|
||||
void CreateMaterialDialog::InitMaterialFileSelection()
|
||||
@@ -88,15 +92,24 @@ namespace MaterialEditor
|
||||
m_materialFileInfo.absoluteFilePath(),
|
||||
QString("Material (*.material)"));
|
||||
|
||||
//Reject empty or invalid filenames which indicate user cancellation
|
||||
// Reject empty or invalid filenames which indicate user cancellation
|
||||
if (!fileInfo.absoluteFilePath().isEmpty())
|
||||
{
|
||||
m_materialFileInfo = fileInfo;
|
||||
m_ui->m_materialFilePicker->setText(m_materialFileInfo.fileName());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void CreateMaterialDialog::UpdateMaterialTypeSelection()
|
||||
{
|
||||
const int index = m_ui->m_materialTypeComboBox->currentIndex();
|
||||
if (index >= 0)
|
||||
{
|
||||
const QVariant itemData = m_ui->m_materialTypeComboBox->itemData(index);
|
||||
m_materialTypeFileInfo = QFileInfo(itemData.toString());
|
||||
}
|
||||
}
|
||||
} // namespace MaterialEditor
|
||||
|
||||
#include <Window/CreateMaterialDialog/moc_CreateMaterialDialog.cpp>
|
||||
|
||||
+1
@@ -36,5 +36,6 @@ namespace MaterialEditor
|
||||
QScopedPointer<Ui::CreateMaterialDialog> m_ui;
|
||||
void InitMaterialTypeSelection();
|
||||
void InitMaterialFileSelection();
|
||||
void UpdateMaterialTypeSelection();
|
||||
};
|
||||
} // namespace MaterialEditor
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace AZ
|
||||
bool m_showTimeline = false;
|
||||
|
||||
// Controls how often the timestamp data is refreshed
|
||||
RefreshType m_refreshType = RefreshType::OncePerSecond;
|
||||
RefreshType m_refreshType = RefreshType::Realtime;
|
||||
AZStd::sys_time_t m_lastUpdateTimeMicroSecond;
|
||||
|
||||
};
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
@@ -725,7 +727,7 @@ namespace AZ
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Name: %s", passEntry->m_name.GetCStr());
|
||||
ImGui::Text("Path: %s", passEntry->m_path.GetCStr());
|
||||
ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks());
|
||||
ImGui::Text("Duration in ticks: %" PRIu64, passEntry->m_timestampResult.GetDurationInTicks());
|
||||
ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
+1408
-895
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,10 @@ namespace AZ::AtomBridge
|
||||
AZ::RPI::AuxGeomDraw::DepthWrite m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On;
|
||||
AZ::RPI::AuxGeomDraw::FaceCullMode m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back;
|
||||
int32_t m_viewProjOverrideIndex = -1; // will be used to implement SetDrawInFrontMode & 2D mode
|
||||
|
||||
// separate tracking for Cry only state
|
||||
bool m_drawInFront = false;
|
||||
bool m_2dMode = false;
|
||||
};
|
||||
|
||||
//! Utility class to collect line segments when the number of segments is known at compile time.
|
||||
@@ -77,6 +81,24 @@ namespace AZ::AtomBridge
|
||||
}
|
||||
}
|
||||
|
||||
void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const
|
||||
{
|
||||
if (auxGeomDrawPtr && !m_points.empty())
|
||||
{
|
||||
AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
|
||||
drawArgs.m_verts = m_points.data();
|
||||
drawArgs.m_vertCount = aznumeric_cast<uint32_t>(m_points.size());
|
||||
drawArgs.m_colors = &rendState.m_color;
|
||||
drawArgs.m_colorCount = 1;
|
||||
drawArgs.m_size = rendState.m_lineWidth;
|
||||
drawArgs.m_opacityType = rendState.m_opacityType;
|
||||
drawArgs.m_depthTest = rendState.m_depthTest;
|
||||
drawArgs.m_depthWrite = rendState.m_depthWrite;
|
||||
drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride();
|
||||
auxGeomDrawPtr->DrawLines( drawArgs );
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_points.clear();
|
||||
@@ -91,6 +113,7 @@ namespace AZ::AtomBridge
|
||||
SingleColorDynamicSizeLineHelper(int estimatedNumLineSegments);
|
||||
void AddLineSegment(const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd);
|
||||
void Draw(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const;
|
||||
void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const;
|
||||
void Reset();
|
||||
|
||||
AZStd::vector<AZ::Vector3> m_points;
|
||||
@@ -119,9 +142,9 @@ namespace AZ::AtomBridge
|
||||
void SetColor(const AZ::Vector4& color) override;
|
||||
void SetAlpha(float a) override;
|
||||
void DrawQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override;
|
||||
// void DrawQuad(float width, float height) overr
|
||||
// void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override;
|
||||
// void DrawWireQuad(float width, float height) override;
|
||||
void DrawQuad(float width, float height) override;
|
||||
void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override;
|
||||
void DrawWireQuad(float width, float height) override;
|
||||
void DrawQuadGradient(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override;
|
||||
void DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) override;
|
||||
void DrawTriangles(const AZStd::vector<AZ::Vector3>& vertices, const AZ::Color& color) override;
|
||||
@@ -134,10 +157,10 @@ namespace AZ::AtomBridge
|
||||
void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) override;
|
||||
void DrawLines(const AZStd::vector<AZ::Vector3>& lines, const AZ::Color& color) override;
|
||||
void DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled = true) override;
|
||||
// void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
|
||||
// void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
|
||||
// void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override;
|
||||
// void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override;
|
||||
void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
|
||||
void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
|
||||
void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override;
|
||||
void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override;
|
||||
void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2) override;
|
||||
void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) override;
|
||||
void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) override;
|
||||
@@ -152,13 +175,13 @@ namespace AZ::AtomBridge
|
||||
void DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) override;
|
||||
void DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) override;
|
||||
void DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale = 1.0f, bool dualEndedArrow = false) override;
|
||||
// void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override;
|
||||
// void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override;
|
||||
// void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override;
|
||||
void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override;
|
||||
void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override;
|
||||
void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override;
|
||||
// unhandled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
|
||||
// void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
|
||||
void SetLineWidth(float width) override;
|
||||
// bool IsVisible(const AZ::Aabb& bounds) override;
|
||||
bool IsVisible(const AZ::Aabb& bounds) override;
|
||||
// int SetFillMode(int nFillMode) override;
|
||||
float GetLineWidth() override;
|
||||
float GetAspectRatio() override;
|
||||
@@ -169,10 +192,8 @@ namespace AZ::AtomBridge
|
||||
void CullOff() override;
|
||||
void CullOn() override;
|
||||
bool SetDrawInFrontMode(bool on) 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;
|
||||
AZ::u32 GetState() override;
|
||||
AZ::u32 SetState(AZ::u32 state) override;
|
||||
void PushMatrix(const AZ::Transform& tm) override;
|
||||
void PopMatrix() override;
|
||||
|
||||
@@ -226,6 +247,10 @@ namespace AZ::AtomBridge
|
||||
|
||||
void InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr);
|
||||
|
||||
AZ::RPI::ViewportContextPtr GetViewportContext() const;
|
||||
|
||||
uint32_t ConvertRenderStateToCry() const;
|
||||
|
||||
RenderState m_rendState;
|
||||
|
||||
AZ::RPI::AuxGeomDrawPtr m_auxGeomPtr;
|
||||
|
||||
@@ -20,8 +20,14 @@
|
||||
#include <IXml.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/smart_ptr/weak_ptr.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
#include <map>
|
||||
|
||||
#include <AzFramework/Font/FontInterface.h>
|
||||
#include <AzFramework/Scene/SceneSystemBus.h>
|
||||
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class FFont;
|
||||
@@ -33,6 +39,8 @@ namespace AZ
|
||||
//! and manages their loading & saving together.
|
||||
class AtomFont
|
||||
: public ICryFont
|
||||
, public AzFramework::FontQueryInterface
|
||||
, public AzFramework::SceneSystemNotificationBus::Handler
|
||||
{
|
||||
friend class FFont;
|
||||
|
||||
@@ -79,16 +87,31 @@ namespace AZ
|
||||
void ReloadAllFonts() override;
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// FontQueryInterface implementation
|
||||
AzFramework::FontDrawInterface* GetFontDrawInterface(AzFramework::FontId fontId) const override;
|
||||
AzFramework::FontDrawInterface* GetDefaultFontDrawInterface() const override;
|
||||
|
||||
// SceneSystemNotificationBus handlers
|
||||
void SceneAboutToBeRemoved(AzFramework::Scene& scene) override;
|
||||
|
||||
|
||||
// Atom DynamicDraw interface management
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene);
|
||||
|
||||
|
||||
public:
|
||||
void UnregisterFont(const char* fontName);
|
||||
|
||||
private:
|
||||
typedef std::map<string, FFont*> FontMap;
|
||||
typedef FontMap::iterator FontMapItor;
|
||||
typedef FontMap::const_iterator FontMapConstItor;
|
||||
using FontMap = std::unordered_map<AzFramework::FontId, FFont*>;
|
||||
using FontMapItor = FontMap::iterator;
|
||||
using FontMapConstItor = FontMap::const_iterator;
|
||||
|
||||
typedef AZStd::map<AZStd::string, AZStd::weak_ptr<FontFamily>> FontFamilyMap;
|
||||
typedef AZStd::map<FontFamily*, FontFamilyMap::iterator> FontFamilyReverseLookupMap;
|
||||
using FontFamilyMap = AZStd::unordered_map<AZStd::string, AZStd::weak_ptr<FontFamily>>;
|
||||
using FontFamilyReverseLookupMap = AZStd::unordered_map<FontFamily*, FontFamilyMap::iterator>;
|
||||
|
||||
using SceneToDynamicDrawMap = AZStd::unordered_map<AZ::RPI::Scene*, AZ::RPI::Ptr<AZ::RPI::DynamicDrawContext>>;
|
||||
|
||||
private:
|
||||
//! Convenience method for loading fonts
|
||||
@@ -119,9 +142,13 @@ namespace AZ
|
||||
FontFamilyReverseLookupMap m_fontFamilyReverseLookup; //<! FontFamily pointer reverse-lookup for quick removal
|
||||
ISystem* m_system;
|
||||
|
||||
AzFramework::FontDrawInterface* m_defaultFontDrawInterface = nullptr;
|
||||
|
||||
int r_persistFontFamilies = 1; //!< Persist fonts for application lifetime to prevent unnecessary work; enabled by default.
|
||||
AZStd::vector<FontFamilyPtr> m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled)
|
||||
|
||||
SceneToDynamicDrawMap m_sceneToDynamicDrawMap;
|
||||
AZStd::shared_mutex m_sceneToDynamicDrawMutex;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzFramework/Font/FontInterface.h>
|
||||
|
||||
#include <Atom/RHI.Reflect/Base.h>
|
||||
#include <Atom/RHI/StreamBufferView.h>
|
||||
@@ -57,6 +58,8 @@ namespace AZ
|
||||
void operator () (const AZStd::intrusive_refcount<AZStd::atomic_uint, FontDeleter>* ptr) const;
|
||||
};
|
||||
|
||||
using TextDrawContext = STextDrawContext;
|
||||
|
||||
//! FFont is the implementation of IFFont used to draw text with a particular font (e.g. Consolas Italic)
|
||||
//! FFont manages creation of a gpu texture to cache the font and generates draw commands that use that texture.
|
||||
//! FFont's are managed by AtomFont as either individual font instances or a font family
|
||||
@@ -64,12 +67,12 @@ namespace AZ
|
||||
class FFont
|
||||
: public IFFont
|
||||
, public AZStd::intrusive_refcount<AZStd::atomic_uint, FontDeleter>
|
||||
, public AzFramework::FontDrawInterface
|
||||
, private AZ::Render::Bootstrap::NotificationBus::Handler
|
||||
{
|
||||
using ref_count = AZStd::intrusive_refcount<AZStd::atomic_uint, FontDeleter>;
|
||||
friend FontDeleter;
|
||||
public:
|
||||
using TextDrawContext = STextDrawContext;
|
||||
//! Determines how characters of different sizes should be handled during render.
|
||||
enum class SizeBehavior
|
||||
{
|
||||
@@ -201,6 +204,14 @@ namespace AZ
|
||||
uint32_t GetFontTextureVersion() override;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// AzFramework::FontDrawInterface implementation
|
||||
void DrawScreenAlignedText2d(
|
||||
const AzFramework::TextDrawParameters& params,
|
||||
const AZStd::string_view& string) override;
|
||||
|
||||
void DrawScreenAlignedText3d(
|
||||
const AzFramework::TextDrawParameters& params,
|
||||
const AZStd::string_view& string) override;
|
||||
|
||||
public:
|
||||
FFont(AtomFont* atomFont, const char* fontName);
|
||||
@@ -220,8 +231,18 @@ namespace AZ
|
||||
bool InitCache();
|
||||
|
||||
void Prepare(const char* str, bool updateTexture, const AtomFont::GlyphSize& glyphSize = AtomFont::defaultGlyphSize);
|
||||
void DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx);
|
||||
Vec2 GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx);
|
||||
void DrawStringUInternal(
|
||||
const RHI::Viewport& viewport,
|
||||
RPI::ViewportContext* viewportContext,
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
const char* str,
|
||||
const bool asciiMultiLine,
|
||||
const TextDrawContext& ctx);
|
||||
Vec2 GetTextSizeUInternal(const RHI::Viewport& viewport, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx);
|
||||
Vec2 GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const;
|
||||
float GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const;
|
||||
|
||||
// returns true if add operation was successful, false otherwise
|
||||
using AddFunction = AZStd::function<bool(const Vec3&, const Vec3&, const Vec3&, const Vec3&, const Vec2&, const Vec2&, const Vec2&, const Vec2&, uint32_t)>;
|
||||
@@ -229,6 +250,7 @@ namespace AZ
|
||||
//! This function is used by both DrawStringUInternal and WriteTextQuadsToBuffers
|
||||
//! To do this is takes a function pointer that implement the appropriate AddQuad behavior
|
||||
int CreateQuadsForText(
|
||||
const RHI::Viewport& viewport,
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
@@ -247,16 +269,16 @@ namespace AZ
|
||||
float rcpCellWidth;
|
||||
};
|
||||
|
||||
TextScaleInfoInternal CalculateScaleInternal(const TextDrawContext& ctx) const;
|
||||
TextScaleInfoInternal CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const;
|
||||
|
||||
Vec2 GetRestoredFontSize(const TextDrawContext& ctx) const;
|
||||
|
||||
bool UpdateTexture();
|
||||
|
||||
void ScaleCoord(float& x, float& y) const;
|
||||
void ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const;
|
||||
|
||||
void InitWindowContext();
|
||||
void InitViewportContext();
|
||||
void InitDefaultWindowContext();
|
||||
void InitDefaultViewportContext();
|
||||
|
||||
void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override;
|
||||
|
||||
@@ -272,8 +294,8 @@ namespace AZ
|
||||
size_t m_fontBufferSize = 0;
|
||||
unsigned char* m_fontBuffer = nullptr;
|
||||
|
||||
AZStd::shared_ptr<RPI::WindowContext> m_windowContext;
|
||||
AZStd::shared_ptr<AZ::RPI::ViewportContext> m_viewportContext;
|
||||
AZStd::shared_ptr<RPI::WindowContext> m_defaultWindowContext;
|
||||
AZStd::shared_ptr<AZ::RPI::ViewportContext> m_defaultViewportContext;
|
||||
|
||||
AZ::Data::Instance<AZ::RPI::StreamingImage> m_fontStreamingImage;
|
||||
AZ::RHI::Ptr<AZ::RHI::Image> m_fontImage;
|
||||
@@ -296,8 +318,6 @@ namespace AZ
|
||||
|
||||
FontShaderData m_fontShaderData;
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> m_dynamicDraw;
|
||||
|
||||
bool m_monospacedFont = false; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType)
|
||||
|
||||
float m_sizeRatio = IFFontConstants::defaultSizeRatio;
|
||||
@@ -325,25 +345,25 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
inline void AZ::FFont::InitWindowContext()
|
||||
inline void AZ::FFont::InitDefaultWindowContext()
|
||||
{
|
||||
if (!m_windowContext)
|
||||
if (!m_defaultWindowContext)
|
||||
{
|
||||
// font is created before window & viewport in the editor so need to do late init
|
||||
// TODO need to deal with multiple windows, such as the editor
|
||||
AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext);
|
||||
AZ_Assert(m_windowContext, "Unable to get the main window context");
|
||||
AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_defaultWindowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext);
|
||||
AZ_Assert(m_defaultWindowContext, "Unable to get the main window context");
|
||||
}
|
||||
}
|
||||
|
||||
inline void AZ::FFont::InitViewportContext()
|
||||
inline void AZ::FFont::InitDefaultViewportContext()
|
||||
{
|
||||
if (!m_viewportContext)
|
||||
if (!m_defaultViewportContext)
|
||||
{
|
||||
// font is created before window & viewport in the editor so need to do late init
|
||||
auto viewContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
|
||||
m_viewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName());
|
||||
AZ_Assert(m_viewportContext, "Unable to get the viewport context");
|
||||
m_defaultViewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName());
|
||||
AZ_Assert(m_defaultViewportContext, "Unable to get the viewport context");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,12 @@
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/std/parallel/lock.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
|
||||
#include <Atom/RPI.Public/RPIUtils.h>
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
|
||||
|
||||
// Static member definitions
|
||||
const AZ::AtomFont::GlyphSize AZ::AtomFont::defaultGlyphSize = AZ::AtomFont::GlyphSize(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY);
|
||||
@@ -348,10 +352,14 @@ AZ::AtomFont::AtomFont(ISystem* system)
|
||||
REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL,
|
||||
"Reload all fonts");
|
||||
#endif
|
||||
AZ::Interface<AzFramework::FontQueryInterface>::Register(this);
|
||||
}
|
||||
|
||||
AZ::AtomFont::~AtomFont()
|
||||
{
|
||||
AZ::Interface<AzFramework::FontQueryInterface>::Unregister(this);
|
||||
m_defaultFontDrawInterface = nullptr;
|
||||
|
||||
// Persist fonts for application lifetime to prevent unnecessary work
|
||||
m_persistedFontFamilies.clear();
|
||||
|
||||
@@ -372,24 +380,41 @@ IFFont* AZ::AtomFont::NewFont(const char* fontName)
|
||||
{
|
||||
string name = fontName;
|
||||
name.MakeLower();
|
||||
AzFramework::FontId fontId = GetFontId(name.c_str());
|
||||
|
||||
FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str()));
|
||||
FontMapItor it = m_fonts.find(fontId);
|
||||
if (it != m_fonts.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
FFont* font = new FFont(this, name.c_str());
|
||||
m_fonts.insert(FontMapItor::value_type(name, font));
|
||||
m_fonts.insert(FontMapItor::value_type(fontId, font));
|
||||
if(!m_defaultFontDrawInterface)
|
||||
{
|
||||
m_defaultFontDrawInterface = static_cast<AzFramework::FontDrawInterface*>(font);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
IFFont* AZ::AtomFont::GetFont(const char* fontName) const
|
||||
{
|
||||
FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(fontName).MakeLower()));
|
||||
AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str());
|
||||
FontMapConstItor it = m_fonts.find(fontId);
|
||||
return it != m_fonts.end() ? it->second : 0;
|
||||
}
|
||||
|
||||
AzFramework::FontDrawInterface* AZ::AtomFont::GetFontDrawInterface(AzFramework::FontId fontId) const
|
||||
{
|
||||
FontMapConstItor it = m_fonts.find(fontId);
|
||||
return (it != m_fonts.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
AzFramework::FontDrawInterface* AZ::AtomFont::GetDefaultFontDrawInterface() const
|
||||
{
|
||||
return m_defaultFontDrawInterface;
|
||||
}
|
||||
|
||||
FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName)
|
||||
{
|
||||
FontFamilyPtr fontFamily(nullptr);
|
||||
@@ -648,7 +673,8 @@ void AZ::AtomFont::ReloadAllFonts()
|
||||
|
||||
void AZ::AtomFont::UnregisterFont(const char* fontName)
|
||||
{
|
||||
FontMapItor it = m_fonts.find(CONST_TEMP_STRING(fontName));
|
||||
AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str());
|
||||
FontMapItor it = m_fonts.find(fontId);
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
IFFont* fontPtr = it->second;
|
||||
@@ -823,5 +849,49 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o
|
||||
return root;
|
||||
}
|
||||
|
||||
void AZ::AtomFont::SceneAboutToBeRemoved(AzFramework::Scene& scene)
|
||||
{
|
||||
AZ::RPI::Scene* rpiScene = scene.GetSubsystem<AZ::RPI::Scene>();
|
||||
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sceneToDynamicDrawMutex);
|
||||
if ( auto it = m_sceneToDynamicDrawMap.find(rpiScene); it != m_sceneToDynamicDrawMap.end())
|
||||
{
|
||||
m_sceneToDynamicDrawMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> AZ::AtomFont::GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene)
|
||||
{
|
||||
static const char* shaderFilepath = "Shaders/SimpleTextured.azshader";
|
||||
|
||||
{
|
||||
// shared lock while reading
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sceneToDynamicDrawMutex);
|
||||
|
||||
if (auto it = m_sceneToDynamicDrawMap.find(scene); it != m_sceneToDynamicDrawMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Create and initialize DynamicDrawContext for font draw
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene);
|
||||
|
||||
Data::Instance<RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath);
|
||||
AZ::RPI::ShaderOptionList shaderOptions;
|
||||
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false")));
|
||||
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true")));
|
||||
dynamicDraw->InitShaderWithVariant(shader, &shaderOptions);
|
||||
dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}});
|
||||
dynamicDraw->EndInit();
|
||||
|
||||
// exclusive lock while writing
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sceneToDynamicDrawMutex);
|
||||
m_sceneToDynamicDrawMap.insert(AZStd::make_pair(scene, dynamicDraw));
|
||||
|
||||
return dynamicDraw;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
|
||||
#include <AtomLyIntegration/AtomFont/FFont.h>
|
||||
@@ -42,6 +45,8 @@
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Image/StreamingImagePool.h>
|
||||
#include <Atom/RPI.Public/ViewportContextManager.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/RHI/DrawPacket.h>
|
||||
@@ -49,6 +54,7 @@
|
||||
|
||||
#include <Atom/RHI.Reflect/InputStreamLayoutBuilder.h>
|
||||
|
||||
static const AZ::Vector2 UiDraw_TextSizeFactor = AZ::Vector2(12.0f, 12.0f);
|
||||
static const int TabCharCount = 4;
|
||||
// set buffer sizes to hold max characters that can be drawn in 1 DrawString call
|
||||
static const size_t MaxVerts = 8 * 1024; // 2048 quads
|
||||
@@ -78,6 +84,7 @@ AZ::FFont::FFont(AtomFont* atomFont, const char* fontName)
|
||||
AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
|
||||
bool AZ::FFont::InitFont()
|
||||
{
|
||||
if (m_fontInitialized)
|
||||
@@ -85,24 +92,14 @@ bool AZ::FFont::InitFont()
|
||||
return true;
|
||||
}
|
||||
|
||||
InitWindowContext();
|
||||
InitViewportContext();
|
||||
|
||||
const char* shaderFilepath = "Shaders/SimpleTextured.azshader";
|
||||
InitDefaultWindowContext();
|
||||
InitDefaultViewportContext();
|
||||
|
||||
// Create and initialize DynamicDrawContext for font draw
|
||||
m_dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(m_viewportContext->GetRenderScene().get());
|
||||
|
||||
Data::Instance<RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath);
|
||||
AZ::RPI::ShaderOptionList shaderOptions;
|
||||
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false")));
|
||||
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true")));
|
||||
m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions);
|
||||
m_dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}});
|
||||
m_dynamicDraw->EndInit();
|
||||
AZ::RPI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(m_defaultViewportContext->GetRenderScene().get());
|
||||
|
||||
// Save draw srg input indices for later use
|
||||
Data::Instance<RPI::ShaderResourceGroup> drawSrg = m_dynamicDraw->NewDrawSrg();
|
||||
Data::Instance<RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg();
|
||||
const RHI::ShaderResourceGroupLayout* layout = drawSrg->GetAsset()->GetLayout();
|
||||
|
||||
m_fontShaderData.m_imageInputIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::TextureIndexName));
|
||||
@@ -257,27 +254,39 @@ void AZ::FFont::Free()
|
||||
|
||||
void AZ::FFont::DrawString(float x, float y, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx)
|
||||
{
|
||||
if (!str || !m_vertexBuffer)
|
||||
if (!str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DrawStringUInternal(x, y, 1.0f, str, asciiMultiLine, ctx);
|
||||
DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, 1.0f, str, asciiMultiLine, ctx);
|
||||
}
|
||||
|
||||
void AZ::FFont::DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx)
|
||||
{
|
||||
if (!str || !m_vertexBuffer)
|
||||
if (!str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DrawStringUInternal(x, y, z, str, asciiMultiLine, ctx);
|
||||
DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, z, str, asciiMultiLine, ctx);
|
||||
}
|
||||
|
||||
void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx)
|
||||
void AZ::FFont::DrawStringUInternal(
|
||||
const RHI::Viewport& viewport,
|
||||
RPI::ViewportContext* viewportContext,
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
const char* str,
|
||||
const bool asciiMultiLine,
|
||||
const TextDrawContext& ctx)
|
||||
{
|
||||
if (!str || !m_fontTexture || ctx.m_fxIdx >= m_effects.size() || m_effects[ctx.m_fxIdx].m_passes.empty())
|
||||
if (!str
|
||||
|| !m_vertexBuffer // vertex buffer isn't created until BootstrapScene is ready, Editor tries to render text before that.
|
||||
|| !m_fontTexture
|
||||
|| ctx.m_fxIdx >= m_effects.size()
|
||||
|| m_effects[ctx.m_fxIdx].m_passes.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -296,7 +305,6 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str,
|
||||
|
||||
const bool orthoMode = ctx.m_overrideViewProjMatrices;
|
||||
|
||||
const RHI::Viewport& viewport = m_windowContext->GetViewport();
|
||||
const float viewX = viewport.m_minX;
|
||||
const float viewY = viewport.m_minY;
|
||||
const float viewWidth = viewport.m_maxX - viewport.m_minX;
|
||||
@@ -307,7 +315,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str,
|
||||
Matrix4x4 modelViewProjMat;
|
||||
if (!orthoMode)
|
||||
{
|
||||
AZ::RPI::ViewPtr view = m_viewportContext->GetDefaultView();
|
||||
AZ::RPI::ViewPtr view = viewportContext->GetDefaultView();
|
||||
modelViewProjMat = view->GetWorldToClipMatrix();
|
||||
}
|
||||
else
|
||||
@@ -322,7 +330,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str,
|
||||
size_t startingVertexCount = m_vertexCount;
|
||||
|
||||
// Local function that is passed into CreateQuadsForText as the AddQuad function
|
||||
AddFunction AddQuad = [this, startingVertexCount]
|
||||
AZ::FFont::AddFunction AddQuad = [this, startingVertexCount]
|
||||
(const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32_t packedColor)
|
||||
{
|
||||
const bool vertexSpaceLeft = m_vertexCount + 4 < MaxVerts;
|
||||
@@ -367,18 +375,19 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str,
|
||||
int numQuads = 0;
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_vertexDataMutex);
|
||||
numQuads = CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad);
|
||||
numQuads = CreateQuadsForText(viewport, x, y, z, str, asciiMultiLine, ctx, AddQuad);
|
||||
}
|
||||
|
||||
if (numQuads)
|
||||
{
|
||||
auto dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(viewportContext->GetRenderScene().get());
|
||||
//setup per draw srg
|
||||
auto drawSrg = m_dynamicDraw->NewDrawSrg();
|
||||
auto drawSrg = dynamicDraw->NewDrawSrg();
|
||||
drawSrg->SetConstant(m_fontShaderData.m_viewProjInputIndex, modelViewProjMat);
|
||||
drawSrg->SetImageView(m_fontShaderData.m_imageInputIndex, m_fontStreamingImage->GetImageView());
|
||||
drawSrg->Compile();
|
||||
|
||||
m_dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg);
|
||||
dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg);
|
||||
m_indexCount = 0;
|
||||
m_vertexCount = 0;
|
||||
}
|
||||
@@ -391,10 +400,14 @@ Vec2 AZ::FFont::GetTextSize(const char* str, const bool asciiMultiLine, const Te
|
||||
return Vec2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
return GetTextSizeUInternal(str, asciiMultiLine, ctx);
|
||||
return GetTextSizeUInternal(m_defaultWindowContext->GetViewport(), str, asciiMultiLine, ctx);
|
||||
}
|
||||
|
||||
Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx)
|
||||
Vec2 AZ::FFont::GetTextSizeUInternal(
|
||||
const RHI::Viewport& viewport,
|
||||
const char* str,
|
||||
const bool asciiMultiLine,
|
||||
const TextDrawContext& ctx)
|
||||
{
|
||||
const size_t fxSize = m_effects.size();
|
||||
|
||||
@@ -411,12 +424,12 @@ Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine,
|
||||
Vec2 size = ctx.m_size;
|
||||
if (ctx.m_sizeIn800x600)
|
||||
{
|
||||
ScaleCoord(size.x, size.y);
|
||||
ScaleCoord(viewport, size.x, size.y);
|
||||
}
|
||||
|
||||
// This scaling takes into account the logical size of the font relative
|
||||
// to any additional scaling applied (such as from "size ratio").
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx));
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx));
|
||||
|
||||
float maxW = 0;
|
||||
float maxH = 0;
|
||||
@@ -733,7 +746,7 @@ uint32_t AZ::FFont::WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16_t
|
||||
return true;
|
||||
};
|
||||
|
||||
CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad);
|
||||
CreateQuadsForText(m_defaultWindowContext->GetViewport(), x, y, z, str, asciiMultiLine, ctx, AddQuad);
|
||||
|
||||
return numQuadsWritten;
|
||||
}
|
||||
@@ -743,7 +756,7 @@ uint32_t AZ::FFont::GetFontTextureVersion()
|
||||
return m_fontImageVersion;
|
||||
}
|
||||
|
||||
int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx,
|
||||
int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx,
|
||||
AddFunction AddQuad)
|
||||
{
|
||||
int numQuads = 0;
|
||||
@@ -768,17 +781,17 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co
|
||||
Vec2 size = ctx.m_size;
|
||||
if (ctx.m_sizeIn800x600)
|
||||
{
|
||||
ScaleCoord(size.x, size.y);
|
||||
ScaleCoord(viewport, size.x, size.y);
|
||||
}
|
||||
|
||||
// This scaling takes into account the logical size of the font relative
|
||||
// to any additional scaling applied (such as from "size ratio").
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx));
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx));
|
||||
|
||||
Vec2 baseXY = Vec2(x, y); // in pixels
|
||||
if (ctx.m_sizeIn800x600)
|
||||
{
|
||||
ScaleCoord(baseXY.x, baseXY.y);
|
||||
ScaleCoord(viewport, baseXY.x, baseXY.y);
|
||||
}
|
||||
|
||||
// snap for pixel perfect rendering (better quality for text)
|
||||
@@ -826,7 +839,7 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co
|
||||
ColorB tempColor(255, 255, 255, 255);
|
||||
uint32_t frameColor = tempColor.pack_abgr8888(); //note: this ends up in r,g,b,a order on little-endian machines
|
||||
|
||||
Vec2 textSize = GetTextSizeUInternal(str, asciiMultiLine, ctx);
|
||||
Vec2 textSize = GetTextSizeUInternal(viewport, str, asciiMultiLine, ctx);
|
||||
|
||||
float x0 = baseXY.x - 12;
|
||||
float y0 = baseXY.y - 6;
|
||||
@@ -1107,13 +1120,13 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co
|
||||
return numQuads;
|
||||
}
|
||||
|
||||
AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const TextDrawContext& ctx) const
|
||||
AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const
|
||||
{
|
||||
Vec2 size = GetRestoredFontSize(ctx); // in pixel
|
||||
|
||||
if (ctx.m_sizeIn800x600)
|
||||
{
|
||||
ScaleCoord(size.x, size.y);
|
||||
ScaleCoord(viewport, size.x, size.y);
|
||||
}
|
||||
|
||||
float rcpCellWidth;
|
||||
@@ -1196,7 +1209,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const
|
||||
maxWidth = gEnv->pRenderer->ScaleCoordX(maxWidth);
|
||||
}
|
||||
|
||||
Vec2 strSize = GetTextSizeUInternal(result.c_str(), true, ctx);
|
||||
Vec2 strSize = GetTextSize(result.c_str(), true, ctx);
|
||||
|
||||
if (strSize.x <= maxWidth)
|
||||
{
|
||||
@@ -1245,7 +1258,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const
|
||||
// Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc)
|
||||
char codepoint[5];
|
||||
Unicode::Convert(codepoint, ch);
|
||||
curCharWidth = GetTextSizeUInternal(codepoint, true, ctx).x;
|
||||
curCharWidth = GetTextSize(codepoint, true, ctx).x;
|
||||
|
||||
// keep track of spaces
|
||||
// they are good for splitting the string
|
||||
@@ -1425,7 +1438,12 @@ void AZ::FFont::AddCharsToFontTexture(const char* chars, int glyphSizeX, int gly
|
||||
|
||||
Vec2 AZ::FFont::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const
|
||||
{
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx));
|
||||
return GetKerningInternal(m_defaultWindowContext->GetViewport(), leftGlyph, rightGlyph, ctx);
|
||||
}
|
||||
|
||||
Vec2 AZ::FFont::GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const
|
||||
{
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx));
|
||||
return m_fontTexture->GetKerning(leftGlyph, rightGlyph) * scaleInfo.scale.x;
|
||||
}
|
||||
|
||||
@@ -1436,12 +1454,18 @@ float AZ::FFont::GetAscender(const TextDrawContext& ctx) const
|
||||
|
||||
float AZ::FFont::GetBaseline(const TextDrawContext& ctx) const
|
||||
{
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx));
|
||||
return GetBaselineInternal(m_defaultWindowContext->GetViewport(), ctx);
|
||||
}
|
||||
|
||||
float AZ::FFont::GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const
|
||||
{
|
||||
const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx));
|
||||
// Calculate baseline the same way as the font renderer which uses the glyph height * size ratio.
|
||||
// Adding 1 because FontTexture always adds 1 to the char height in GetTextureCoord
|
||||
return (round(m_fontTexture->GetCellHeight() * GetSizeRatio()) + 1.0f) * scaleInfo.scale.y;
|
||||
}
|
||||
|
||||
|
||||
bool AZ::FFont::InitTexture()
|
||||
{
|
||||
using namespace AZ;
|
||||
@@ -1565,14 +1589,8 @@ Vec2 AZ::FFont::GetRestoredFontSize(const TextDrawContext& ctx) const
|
||||
return Vec2(ctx.m_size.x * restoringScale, ctx.m_size.y * restoringScale);
|
||||
}
|
||||
|
||||
void AZ::FFont::ScaleCoord(float& x, float& y) const
|
||||
void AZ::FFont::ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const
|
||||
{
|
||||
if (!m_windowContext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const RHI::Viewport& viewport = m_windowContext->GetViewport();
|
||||
float width = viewport.m_maxX - viewport.m_minX;
|
||||
float height = viewport.m_maxY - viewport.m_minY;
|
||||
|
||||
@@ -1580,11 +1598,161 @@ void AZ::FFont::ScaleCoord(float& x, float& y) const
|
||||
y *= height / WindowScaleHeight;
|
||||
}
|
||||
|
||||
|
||||
void AZ::FFont::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene)
|
||||
{
|
||||
InitFont();
|
||||
}
|
||||
|
||||
static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::TextDrawParameters& params)
|
||||
{
|
||||
if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_Center;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_Right;
|
||||
}
|
||||
|
||||
if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_CenterV;
|
||||
}
|
||||
|
||||
if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_Bottom;
|
||||
}
|
||||
|
||||
if (params.m_monospace)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_Monospace;
|
||||
}
|
||||
|
||||
if (params.m_depthTest)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_DepthTest;
|
||||
}
|
||||
|
||||
if (params.m_virtual800x600ScreenSize)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_800x600;
|
||||
}
|
||||
|
||||
if (!params.m_scaleWithWindow)
|
||||
{
|
||||
ctx.m_drawTextFlags |= eDrawText_FixedSize;
|
||||
}
|
||||
}
|
||||
|
||||
void AZ::FFont::DrawScreenAlignedText2d(
|
||||
const AzFramework::TextDrawParameters& params,
|
||||
const AZStd::string_view& string)
|
||||
{
|
||||
if (params.m_drawViewportId == AzFramework::InvalidViewportId ||
|
||||
string.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Code mostly duplicated from CRenderer::Draw2dTextWithDepth
|
||||
float posX = params.m_position.GetX();
|
||||
float posY = params.m_position.GetY();
|
||||
AZ::RPI::ViewportContext* viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextById(params.m_drawViewportId).get();
|
||||
const AZ::RHI::Viewport& viewport = viewportContext->GetWindowContext()->GetViewport();
|
||||
if (params.m_virtual800x600ScreenSize)
|
||||
{
|
||||
posX *= WindowScaleWidth / (viewport.m_maxX - viewport.m_minX);
|
||||
posY *= WindowScaleHeight / (viewport.m_maxY - viewport.m_minY);
|
||||
}
|
||||
TextDrawContext ctx;
|
||||
ctx.SetBaseState(GS_NODEPTHTEST);
|
||||
ctx.SetColor(AZColorToLYColorF(params.m_color));
|
||||
ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f);
|
||||
ctx.EnableFrame(false);
|
||||
ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow);
|
||||
ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize);
|
||||
ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale));
|
||||
if (params.m_monospace || !params.m_scaleWithWindow)
|
||||
{
|
||||
ScaleCoord(viewport, posX, posY);
|
||||
}
|
||||
|
||||
if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left ||
|
||||
params.m_vAlign != AzFramework::TextVerticalAlignment::Top)
|
||||
{
|
||||
Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, ctx);
|
||||
|
||||
// If we're using virtual 800x600 coordinates, convert the text size from
|
||||
// pixels to that before using it as an offset.
|
||||
if (ctx.m_sizeIn800x600)
|
||||
{
|
||||
float width = 1.0f;
|
||||
float height = 1.0f;
|
||||
ScaleCoord(viewport, width, height);
|
||||
textSize.x /= width;
|
||||
textSize.y /= height;
|
||||
}
|
||||
|
||||
if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center)
|
||||
{
|
||||
posX -= textSize.x * 0.5f;
|
||||
}
|
||||
else if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right)
|
||||
{
|
||||
posX -= textSize.x;
|
||||
}
|
||||
|
||||
if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center)
|
||||
{
|
||||
posY -= textSize.y * 0.5f;
|
||||
}
|
||||
else if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom)
|
||||
{
|
||||
posY -= textSize.y;
|
||||
}
|
||||
}
|
||||
SetCommonContextFlags(ctx, params);
|
||||
ctx.m_drawTextFlags |= eDrawText_2D;
|
||||
|
||||
DrawStringUInternal(
|
||||
viewport,
|
||||
viewportContext,
|
||||
posX,
|
||||
posY,
|
||||
params.m_position.GetZ(), // Z
|
||||
string.data(),
|
||||
params.m_multiline,
|
||||
ctx
|
||||
);
|
||||
}
|
||||
|
||||
void AZ::FFont::DrawScreenAlignedText3d(
|
||||
const AzFramework::TextDrawParameters& params,
|
||||
const AZStd::string_view& string)
|
||||
{
|
||||
if (params.m_drawViewportId == AzFramework::InvalidViewportId ||
|
||||
string.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
AZ::RPI::ViewportContext* viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextById(params.m_drawViewportId).get();
|
||||
AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView();
|
||||
if (!currentView)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AZ::Vector3 positionNDC = AzFramework::WorldToScreenNDC(
|
||||
params.m_position,
|
||||
currentView->GetViewToWorldMatrix(),
|
||||
currentView->GetViewToClipMatrix()
|
||||
);
|
||||
AzFramework::TextDrawParameters param2d = params;
|
||||
param2d.m_position = positionNDC;
|
||||
DrawScreenAlignedText2d(param2d, string);
|
||||
}
|
||||
|
||||
#endif //USE_NULLFONT_ALWAYS
|
||||
|
||||
|
||||
+3
@@ -73,6 +73,9 @@ namespace AZ
|
||||
|
||||
bool RequiresShapeComponent() const;
|
||||
|
||||
//! Returns true if the light type is anything other than unknown.
|
||||
bool LightTypeIsSelected() const;
|
||||
|
||||
//! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic
|
||||
bool IsAttenuationRadiusModeAutomatic() const;
|
||||
|
||||
|
||||
+5
@@ -73,6 +73,11 @@ namespace AZ
|
||||
|| m_lightType == LightType::Polygon;
|
||||
}
|
||||
|
||||
bool AreaLightComponentConfig::LightTypeIsSelected() const
|
||||
{
|
||||
return m_lightType != LightType::Unknown;
|
||||
}
|
||||
|
||||
bool AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic() const
|
||||
{
|
||||
return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic;
|
||||
|
||||
+9
@@ -234,6 +234,11 @@ namespace AZ::Render
|
||||
!(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Polygon && m_configuration.m_shapeType != PoylgonShapeTypeId),
|
||||
"The light type is a polygon, but the shape component is not.");
|
||||
}
|
||||
|
||||
if (m_configuration.m_lightType == AreaLightComponentConfig::LightType::SimpleSpot)
|
||||
{
|
||||
m_configuration.m_enableShutters = true; // Simple spot always has shutters.
|
||||
}
|
||||
}
|
||||
|
||||
void AreaLightComponentController::ConfigurationChanged()
|
||||
@@ -620,6 +625,10 @@ namespace AZ::Render
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_lightShapeDelegate)
|
||||
{
|
||||
m_lightShapeDelegate->SetConfig(&m_configuration);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ::Render
|
||||
|
||||
@@ -51,14 +51,52 @@ namespace AZ::Render
|
||||
return m_shapeBus->GetRadius() * GetTransform().GetScale().GetMaxElement();
|
||||
}
|
||||
|
||||
void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
{
|
||||
if (isSelected)
|
||||
{
|
||||
debugDisplay.SetColor(color);
|
||||
debugDisplay.PushMatrix(transform);
|
||||
float radius = GetConfig()->m_attenuationRadius;
|
||||
|
||||
// Draw a disk for the attenuation radius
|
||||
debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity));
|
||||
if (GetConfig()->m_enableShutters)
|
||||
{
|
||||
|
||||
float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees);
|
||||
float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees);
|
||||
|
||||
// Draw a cone using the cone angle and attenuation radius
|
||||
innerRadians = GetMin(innerRadians, outerRadians);
|
||||
float coneRadiusInner = sin(innerRadians) * radius;
|
||||
float coneHeightInner = cos(innerRadians) * radius;
|
||||
float coneRadiusOuter = sin(outerRadians) * radius;
|
||||
float coneHeightOuter = cos(outerRadians) * radius;
|
||||
|
||||
auto DrawConicalFrustum = [&debugDisplay](uint32_t numRadiusLines, float topRadius, float bottomRadius, float height, float brightness)
|
||||
{
|
||||
debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f));
|
||||
debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), bottomRadius);
|
||||
|
||||
for (uint32_t i = 0; i < numRadiusLines; ++i)
|
||||
{
|
||||
float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi;
|
||||
debugDisplay.DrawLine(
|
||||
Vector3(cos(radiusLineAngle) * topRadius, sin(radiusLineAngle) * topRadius, 0),
|
||||
Vector3(cos(radiusLineAngle) * bottomRadius, sin(radiusLineAngle) * bottomRadius, height)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusInner, coneHeightInner, 1.0f);
|
||||
DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusOuter, coneHeightOuter, 0.65f);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
debugDisplay.DrawWireDisk(Vector3::CreateZero(), Vector3::CreateAxisZ(), radius);
|
||||
debugDisplay.DrawArc(Vector3::CreateZero(), radius, 90.0f, 180.0f, -3.0f, 0);
|
||||
debugDisplay.DrawArc(Vector3::CreateZero(), radius, 0.0f, 180.0f, 3.0f, 1);
|
||||
}
|
||||
debugDisplay.PopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-25
@@ -67,50 +67,56 @@ namespace AZ
|
||||
editContext->Class<AreaLightComponentConfig>(
|
||||
"AreaLightComponentConfig", "")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light Type", "Which type of light this component represents.")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a Light Type")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (Sphere)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (Simple)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (Disk)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (Simple)")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light type", "Which type of light this component represents.")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a light type")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (sphere)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (simple punctual)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (disk)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (simple punctual)")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Capsule, "Capsule")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Quad, "Quad")
|
||||
->EnumAttribute(AreaLightComponentConfig::LightType::Polygon, "Polygon")
|
||||
->DataElement(Edit::UIHandlers::Color, &AreaLightComponentConfig::m_color, "Color", "Color of the light")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
->Attribute("ColorEditorConfiguration", RPI::ColorUtils::GetLinearRgbEditorConfig())
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying which photometric unit to work in.")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity mode", "Allows specifying which photometric unit to work in.")
|
||||
->Attribute(AZ::Edit::Attributes::EnumValues, &AreaLightComponentConfig::GetValidPhotometricUnits)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_intensity, "Intensity", "Intensity of the light in the set photometric unit.")
|
||||
->Attribute(Edit::Attributes::Min, &AreaLightComponentConfig::GetIntensityMin)
|
||||
->Attribute(Edit::Attributes::Max, &AreaLightComponentConfig::GetIntensityMax)
|
||||
->Attribute(Edit::Attributes::SoftMin, &AreaLightComponentConfig::GetIntensitySoftMin)
|
||||
->Attribute(Edit::Attributes::SoftMax, &AreaLightComponentConfig::GetIntensitySoftMax)
|
||||
->Attribute(Edit::Attributes::Suffix, &AreaLightComponentConfig::GetIntensitySuffix)
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both Directions", "Whether light should emit from both sides of the surface or just the front")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both directions", "Whether light should emit from both sides of the surface or just the front")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsBothDirections)
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast Approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsFastApproximation)
|
||||
->ClassElement(Edit::ClassElements::Group, "Attenuation Radius")
|
||||
->ClassElement(Edit::ClassElements::Group, "Attenuation radius")
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.")
|
||||
->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic")
|
||||
->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.")
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected)
|
||||
|
||||
->ClassElement(Edit::ClassElements::Group, "Shutters")
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters)
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable Shutters", "Restrict the light to a specific beam angle depending on shape.")
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable shutters", "Restrict the light to a specific beam angle depending on shape.")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner Angle", "The inner angle of the shutters where the light beam begins to be occluded.")
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner angle", "The inner angle of the shutters where the light beam begins to be occluded.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 180.0f)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer Angle", "The outer angle of the shutters where the light beam is completely occluded.")
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer angle", "The outer angle of the shutters where the light beam is completely occluded.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 180.0f)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters)
|
||||
@@ -119,9 +125,9 @@ namespace AZ
|
||||
->ClassElement(Edit::ClassElements::Group, "Shadows")
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable Shadow", "Enable shadow for the light")
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable shadow", "Enable shadow for the light")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap Size", "Width/Height of shadowmap")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap size", "Width and height of shadowmap")
|
||||
->EnumAttribute(ShadowmapSize::Size256, " 256")
|
||||
->EnumAttribute(ShadowmapSize::Size512, " 512")
|
||||
->EnumAttribute(ShadowmapSize::Size1024, "1024")
|
||||
@@ -129,13 +135,13 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled)
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow Filter Method",
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow filter method",
|
||||
"Filtering method of edge-softening of shadows.\n"
|
||||
" None: no filtering\n"
|
||||
" PCF: Percentage-Closer Filtering\n"
|
||||
" ESM: Exponential Shadow Maps\n"
|
||||
" PCF: Percentage-closer Filtering\n"
|
||||
" ESM: Exponential shadow maps\n"
|
||||
" ESM+PCF: ESM with a PCF fallback\n"
|
||||
"For BehaviorContext (or TrackView), None=0, PCF=1, ESM=2, ESM+PCF=3")
|
||||
"For BehaviorContext (or track view), None=0, PCF=1, ESM=2, ESM+PCF=3")
|
||||
->EnumAttribute(ShadowFilterMethod::None, "None")
|
||||
->EnumAttribute(ShadowFilterMethod::Pcf, "PCF")
|
||||
->EnumAttribute(ShadowFilterMethod::Esm, "ESM")
|
||||
@@ -143,7 +149,7 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening Boundary Width",
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening boundary width",
|
||||
"Width of the boundary between shadowed area and lit one. "
|
||||
"Units are in degrees. "
|
||||
"If this is 0, softening edge is disabled.")
|
||||
@@ -152,26 +158,27 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::Suffix, " deg")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count",
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction sample count",
|
||||
"Sample Count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.")
|
||||
->Attribute(Edit::Attributes::Min, 4)
|
||||
->Attribute(Edit::Attributes::Max, 16)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count",
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering sample count",
|
||||
"It is used only when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.")
|
||||
->Attribute(Edit::Attributes::Min, 4)
|
||||
->Attribute(Edit::Attributes::Max, 64)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled)
|
||||
->DataElement(
|
||||
Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf Method",
|
||||
"Type of Pcf to use.\n"
|
||||
Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf method",
|
||||
"Type of PCF to use.\n"
|
||||
" Boundary search: do several taps to first determine if we are on a shadow boundary\n"
|
||||
" Bicubic: a smooth, fixed-size kernel \n")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search")
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search")
|
||||
->EnumAttribute(PcfMethod::Bicubic, "Bicubic")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled);
|
||||
;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <Atom/Feature/CoreLights/PhotometricValue.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h>
|
||||
#include <LmbrCentral/Shape/SphereShapeComponentBus.h>
|
||||
#include <CoreLights/LightDelegateInterface.h>
|
||||
|
||||
@@ -40,6 +41,8 @@ namespace AZ
|
||||
LightDelegateBase(EntityId entityId, bool isVisible);
|
||||
virtual ~LightDelegateBase();
|
||||
|
||||
void SetConfig(const AreaLightComponentConfig* config) override;
|
||||
|
||||
// LightDelegateInterface overrides...
|
||||
void SetChroma(const AZ::Color& chroma) override;
|
||||
void SetIntensity(float intensity) override;
|
||||
@@ -66,6 +69,7 @@ namespace AZ
|
||||
|
||||
// Trivial getters
|
||||
FeatureProcessorType* GetFeatureProcessor() const { return m_featureProcessor; };
|
||||
const AreaLightComponentConfig* GetConfig() const { return m_componentConfig; };
|
||||
typename FeatureProcessorType::LightHandle GetLightHandle() const { return m_lightHandle; };
|
||||
const AZ::Transform& GetTransform() const { return m_transform; };
|
||||
bool GetShuttersEnabled() { return m_shuttersEnabled; };
|
||||
@@ -81,6 +85,7 @@ namespace AZ
|
||||
private:
|
||||
FeatureProcessorType* m_featureProcessor = nullptr;
|
||||
typename FeatureProcessorType::LightHandle m_lightHandle;
|
||||
const AreaLightComponentConfig* m_componentConfig = nullptr;
|
||||
|
||||
LmbrCentral::ShapeComponentRequests* m_shapeBus;
|
||||
AZ::Transform m_transform;
|
||||
|
||||
@@ -59,6 +59,12 @@ namespace AZ
|
||||
m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb<FeatureProcessorType::PhotometricUnitType>());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FeatureProcessorType>
|
||||
void LightDelegateBase<FeatureProcessorType>::SetConfig(const AreaLightComponentConfig* config)
|
||||
{
|
||||
m_componentConfig = config;
|
||||
}
|
||||
|
||||
template <typename FeatureProcessorType>
|
||||
void LightDelegateBase<FeatureProcessorType>::SetChroma(const AZ::Color& color)
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
virtual ~LightDelegateInterface() {};
|
||||
|
||||
//! Sets the area light component config so delegates don't have to cache the same data locally.
|
||||
virtual void SetConfig(const AreaLightComponentConfig* config) = 0;
|
||||
//! Sets the color of the light independent of light intensity. The color is a mask on the total light intensity.
|
||||
virtual void SetChroma(const AZ::Color& chroma) = 0;
|
||||
//! Sets the light intensity
|
||||
|
||||
+30
-5
@@ -44,15 +44,40 @@ namespace AZ::Render
|
||||
{
|
||||
GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees));
|
||||
}
|
||||
|
||||
void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
|
||||
void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const
|
||||
{
|
||||
if (isSelected)
|
||||
{
|
||||
debugDisplay.SetColor(color);
|
||||
float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees);
|
||||
float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees);
|
||||
float radius = GetConfig()->m_attenuationRadius;
|
||||
|
||||
// Draw a cone for the cone angle and attenuation radius
|
||||
debugDisplay.DrawCone(transform.GetTranslation(), transform.GetBasisX(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity), false);
|
||||
// Draw a cone using the cone angle and attenuation radius
|
||||
innerRadians = GetMin(innerRadians, outerRadians);
|
||||
float coneRadiusInner = sin(innerRadians) * radius;
|
||||
float coneHeightInner = cos(innerRadians) * radius;
|
||||
float coneRadiusOuter = sin(outerRadians) * radius;
|
||||
float coneHeightOuter = cos(outerRadians) * radius;
|
||||
|
||||
debugDisplay.PushMatrix(transform);
|
||||
|
||||
auto DrawCone = [&debugDisplay](uint32_t numRadiusLines, float radius, float height, float brightness)
|
||||
{
|
||||
debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f));
|
||||
debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), radius);
|
||||
|
||||
for (uint32_t i = 0; i < numRadiusLines; ++i)
|
||||
{
|
||||
float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi;
|
||||
debugDisplay.DrawLine(Vector3::CreateZero(), Vector3(cos(radiusLineAngle) * radius, sin(radiusLineAngle) * radius, height));
|
||||
}
|
||||
};
|
||||
|
||||
DrawCone(16, coneRadiusInner, coneHeightInner, 1.0f);
|
||||
DrawCone(16, coneRadiusOuter, coneHeightOuter, 0.65f);
|
||||
|
||||
debugDisplay.PopMatrix();
|
||||
}
|
||||
}
|
||||
} // namespace AZ::Render
|
||||
|
||||
+3
-1
@@ -25,6 +25,8 @@ namespace AZ
|
||||
class SimpleSpotLightDelegate final
|
||||
: public LightDelegateBase<SimpleSpotLightFeatureProcessorInterface>
|
||||
{
|
||||
using Base = LightDelegateBase<SimpleSpotLightFeatureProcessorInterface>;
|
||||
|
||||
public:
|
||||
SimpleSpotLightDelegate(EntityId entityId, bool isVisible);
|
||||
|
||||
@@ -34,9 +36,9 @@ namespace AZ
|
||||
float GetSurfaceArea() const override;
|
||||
float GetEffectiveSolidAngle() const override { return PhotometricValue::DirectionalEffectiveSteradians; }
|
||||
void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override;
|
||||
|
||||
private:
|
||||
virtual void HandleShapeChanged();
|
||||
|
||||
};
|
||||
|
||||
} // namespace Render
|
||||
|
||||
+2
@@ -269,6 +269,8 @@ namespace AZ
|
||||
|
||||
QAction* action = nullptr;
|
||||
|
||||
menu.addAction("Open Material Editor", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); });
|
||||
|
||||
action = menu.addAction("Clear", [this]() { Clear(); });
|
||||
action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty());
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ namespace AZ
|
||||
struct ThumbnailRendererData final
|
||||
{
|
||||
static constexpr const char* LightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset";
|
||||
static constexpr const char* DefaultModelPath = "materialeditor/viewportmodels/quadsphere.azmodel";
|
||||
static constexpr const char* DefaultModelPath = "models/sphere.azmodel";
|
||||
static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial";
|
||||
|
||||
RPI::ScenePtr m_scene;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user