Merge remote-tracking branch 'upstream/main' into LYN-2726-ProjectRoot

This commit is contained in:
mcgarrah
2021-04-16 21:12:55 -05:00
109 changed files with 3772 additions and 1946 deletions
-4
View File
@@ -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)
+12 -2
View File
@@ -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;
@@ -926,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>
@@ -525,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);
@@ -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")
@@ -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
@@ -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);
}
@@ -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()
{
@@ -2777,26 +2777,6 @@ AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state)
return 0;
}
AZ::u32 SandboxIntegrationManager::SetStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->SetStateFlag(state);
}
return 0;
}
AZ::u32 SandboxIntegrationManager::ClearStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->ClearStateFlag(state);
}
return 0;
}
void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm)
{
if (m_dc)
@@ -268,8 +268,6 @@ private:
bool SetDrawInFrontMode(bool bOn) override;
AZ::u32 GetState() override;
AZ::u32 SetState(AZ::u32 state) override;
AZ::u32 SetStateFlag(AZ::u32 state) override;
AZ::u32 ClearStateFlag(AZ::u32 state) override;
void PushMatrix(const AZ::Transform& tm) override;
void PopMatrix() override;
@@ -12,6 +12,7 @@
#pragma once
#include <Authentication/AuthenticationProviderBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@@ -28,74 +29,104 @@ namespace AWSClientAuth
OnPasswordGrantMultiFactorConfirmSignInSuccess, OnPasswordGrantMultiFactorConfirmSignInFail,
OnDeviceCodeGrantSignInSuccess, OnDeviceCodeGrantSignInFail,
OnDeviceCodeGrantConfirmSignInSuccess, OnDeviceCodeGrantConfirmSignInFail,
OnRefreshTokensSuccess, OnRefreshTokensFail,
OnSignOut
OnRefreshTokensSuccess, OnRefreshTokensFail
);
void OnPasswordGrantSingleFactorSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantSingleFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorSignInSuccess() override
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
AZ::TickBus::QueueFunction([this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
});
}
void OnPasswordGrantMultiFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantMultiFactorConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
});
}
void OnDeviceCodeGrantSignInSuccess(
const AZStd::string& userCode, const AZStd::string& verificationUrl, const int codeExpiresInSeconds) override
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
AZ::TickBus::QueueFunction([userCode, verificationUrl, codeExpiresInSeconds, this]()
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
});
}
void OnDeviceCodeGrantSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
});
}
void OnDeviceCodeGrantConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
});
}
void OnDeviceCodeGrantConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
});
}
void OnRefreshTokensSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
});
}
void OnRefreshTokensFail(const AZStd::string& error) override
{
Call(FN_OnRefreshTokensFail, error);
}
void OnSignOut(const ProviderNameEnum& provideName) override
{
Call(FN_OnSignOut, provideName);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRefreshTokensFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -16,6 +16,7 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <Authentication/AuthenticationProviderBus.h>
#include <Authentication/AuthenticationProviderScriptCanvasBus.h>
#include <Authentication/AuthenticationProviderInterface.h>
#include <Authentication/AuthenticationTokens.h>
@@ -23,7 +24,8 @@ namespace AWSClientAuth
{
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
class AuthenticationProviderManager
: AuthenticationProviderRequestBus::Handler
: public AuthenticationProviderRequestBus::Handler
, public AuthenticationProviderScriptCanvasRequestBus::Handler
{
public:
AZ_RTTI(AuthenticationProviderManager, "{45813BA5-9A46-4A2A-A923-C79CFBA0E63D}", IAuthenticationProviderRequests);
@@ -43,6 +45,22 @@ namespace AWSClientAuth
bool IsSignedIn(const ProviderNameEnum& providerName) override;
bool SignOut(const ProviderNameEnum& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override;
// AuthenticationProviderScriptCanvasRequest interface
bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) override;
void PasswordGrantSingleFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override;
void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) override;
void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) override;
void RefreshTokensAsync(const AZStd::string& providerName) override;
void GetTokensWithRefreshAsync(const AZStd::string& providerName) override;
bool IsSignedIn(const AZStd::string& providerName) override;
bool SignOut(const AZStd::string& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) override;
virtual AZStd::unique_ptr<AuthenticationProviderInterface> CreateAuthenticationProviderObject(const ProviderNameEnum& providerName);
AZStd::map<ProviderNameEnum, AZStd::unique_ptr<AuthenticationProviderInterface>> m_authenticationProvidersMap;
@@ -50,9 +68,9 @@ namespace AWSClientAuth
private:
bool IsProviderInitialized(const ProviderNameEnum& providerName);
void ResetProviders();
ProviderNameEnum GetProviderNameEnum(AZStd::string name);
AZStd::shared_ptr<AZ::SettingsRegistryInterface> m_settingsRegistry;
};
} // namespace AWSClientAuth
@@ -0,0 +1,103 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <Authentication/AuthenticationTokens.h>
namespace AWSClientAuth
{
//! Abstract class for authentication provider script canvas requests.
//! Private class to allow provide names to be string type instead of an enum as behavior context does not work well with enum's.
class IAuthenticationProviderScriptCanvasRequests
{
public:
AZ_TYPE_INFO(IAuthenticationProviderRequests, "{A8FD915F-9FF2-4BA3-8AA0-8CF7A94A323B}");
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.
//! @param providerName Provider to check signed in for
//! @return bool True if valid access token available, else False
virtual bool IsSignedIn(const AZStd::string& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const AZStd::string& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.
//! @param providerName Provider to get access token for.
//! events: OnRefreshTokensSuccess, OnRefreshTokensFail
virtual void GetTokensWithRefreshAsync(const AZStd::string& providerName) = 0;
//! Signs user out.
//! Clears all cached tokens.
//! @param providerName Provider to sign out.
//! @return bool True: Successfully sign out.
virtual bool SignOut(const AZStd::string& providerName) = 0;
//////////////////////////////////////////////////////////////////////////
};
//! Authentication Request bus for different supported providers.
class AuthenticationProviderScriptCanvasRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
using MutexType = AZ::NullMutex;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
};
using AuthenticationProviderScriptCanvasRequestBus = AZ::EBus<IAuthenticationProviderScriptCanvasRequests, AuthenticationProviderScriptCanvasRequests>;
} // namespace AWSClientAuth
@@ -15,6 +15,14 @@
namespace AWSClientAuth
{
constexpr char ProvideNameEnumStringNone[] = "None";
constexpr char ProvideNameEnumStringAWSCognitoIDP[] = "AWSCognitoIDP";
constexpr char ProvideNameEnumStringLoginWithAmazon[] = "LoginWithAmazon";
constexpr char ProvideNameEnumStringGoogle[] = "Google";
constexpr char ProvideNameEnumStringApple[] = "Apple";
constexpr char ProvideNameEnumStringFacebook[] = "Facebook";
constexpr char ProvideNameEnumStringTwitch[] = "Twitch";
//! Holds Login with Amazon provider serialized settings
class LWAProviderSetting
{
@@ -12,6 +12,7 @@
#pragma once
#include <Authorization/AWSCognitoAuthorizationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AWSClientAuth
@@ -28,12 +29,18 @@ namespace AWSClientAuth
void OnRequestAWSCredentialsSuccess(const ClientAuthAWSCredentials& awsCredentials) override
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
AZ::TickBus::QueueFunction([awsCredentials, this]()
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
});
}
void OnRequestAWSCredentialsFail(const AZStd::string& error) override
{
Call(FN_OnRequestAWSCredentialsFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRequestAWSCredentialsFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -12,6 +12,7 @@
#pragma once
#include <UserManagement/AWSCognitoUserManagementBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@@ -32,62 +33,86 @@ namespace AWSClientAuth
void OnEmailSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnEmailSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnEmailSignUpSuccess, uuid);
});
}
void OnEmailSignUpFail(const AZStd::string& error) override
{
Call(FN_OnEmailSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEmailSignUpFail, error);
});
}
void OnPhoneSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnPhoneSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnPhoneSignUpSuccess, uuid);
});
}
void OnPhoneSignUpFail(const AZStd::string& error) override
{
Call(FN_OnPhoneSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnPhoneSignUpFail, error);
});
}
void OnConfirmSignUpSuccess() override
{
Call(FN_OnConfirmSignUpSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmSignUpSuccess);
});
}
void OnConfirmSignUpFail(const AZStd::string& error) override
{
Call(FN_OnConfirmSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmSignUpFail, error);
});
}
void OnForgotPasswordSuccess() override
{
Call(FN_OnForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnForgotPasswordSuccess);
});
}
void OnForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnForgotPasswordFail, error);
});
}
void OnConfirmForgotPasswordSuccess() override
{
Call(FN_OnConfirmForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmForgotPasswordSuccess);
});
}
void OnConfirmForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnConfirmForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmForgotPasswordFail, error);
});
}
void OnEnableMFASuccess() override
{
Call(FN_OnEnableMFASuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnEnableMFASuccess);
});
}
void OnEnableMFAFail(const AZStd::string& error) override
{
Call(FN_OnEnableMFAFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEnableMFAFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -16,7 +16,7 @@
namespace AWSClientAuth
{
//@ Abstract class for authentication provider requests.
//! Abstract class for authentication provider requests.
class IAuthenticationProviderRequests
{
public:
@@ -35,32 +35,40 @@ namespace AWSClientAuth
virtual bool IsSignedIn(const ProviderNameEnum& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens.
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.
@@ -11,20 +11,15 @@
*/
#pragma once
#include <AzCore/Preprocessor/Enum.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/chrono/clocks.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AWSClientAuth
{
enum class ProviderNameEnum
{
None,
AWSCognitoIDP,
LoginWithAmazon,
Google,
Apple,
Facebook
};
AZ_ENUM_CLASS(ProviderNameEnum, None, AWSCognitoIDP, LoginWithAmazon, Twitch, Google, Apple, Facebook);
//! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController.
class AuthenticationTokens
@@ -55,6 +50,8 @@ namespace AWSClientAuth
//! @return Expiration time in seconds.
int GetTokensExpireTimeSeconds() const;
static void Reflect(AZ::ReflectContext* context);
private:
int m_tokensExpireTimeSeconds = 0;
AZStd::string m_accessToken;
@@ -12,7 +12,7 @@
#pragma once
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/string/string.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
@@ -24,6 +24,14 @@ namespace AWSClientAuth
{
public:
AZ_TYPE_INFO(ClientAuthAWSCredentials, "{02FB32C4-B94E-4084-9049-3DF32F87BD76}");
ClientAuthAWSCredentials() = default;
ClientAuthAWSCredentials(const ClientAuthAWSCredentials& other)
: m_accessKeyId(other.m_accessKeyId)
, m_secretKey(other.m_secretKey)
, m_sessionToken(other.m_sessionToken)
{
}
ClientAuthAWSCredentials(const AZStd::string& accessKeyId, const AZStd::string& secretKey, const AZStd::string& sessionToken)
{
@@ -50,6 +58,32 @@ namespace AWSClientAuth
return m_sessionToken;
}
static void Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ClientAuthAWSCredentials>()
->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId)
->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey)
->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<ClientAuthAWSCredentials>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const ClientAuthAWSCredentials&>()
->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId))
->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey))
->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken));
}
}
private:
AZStd::string m_accessKeyId;
AZStd::string m_secretKey;
@@ -22,11 +22,12 @@ namespace AWSClientAuth
public:
AZ_TYPE_INFO(IAWSCognitoUserManagementRequests, "{A4C90F21-7056-4827-8C6B-401E6945697D}");
//! Initialize Cognito User pool.
//! Initialize Cognito User pool using settings from resource mappings.
//! @param settingsRegistryPath settingsRegistryPath Path for the settings registry file to use.
virtual bool Initialize() = 0;
// Requests interface
//! Cognito user pool email sign up start.
//! @param username User name to use for sign up.
//! @param password Password to use for sign up.
@@ -59,7 +60,7 @@ namespace AWSClientAuth
virtual void EnableMFAAsync(const AZStd::string& accessToken) = 0;
};
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
//! Implements AWS Cognito user pool user management requests.
class AWSCognitoUserManagementRequests
: public AZ::EBusTraits
{
@@ -22,6 +22,11 @@
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}");
}
namespace AWSClientAuth
{
constexpr char SerializeComponentName[] = "AWSClientAuth";
@@ -44,20 +49,35 @@ namespace AWSClientAuth
AWSClientAuth::GoogleProviderSetting::Reflect(*serialize);
}
AWSClientAuth::AuthenticationTokens::Reflect(context);
AWSClientAuth::ClientAuthAWSCredentials::Reflect(context);
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AuthenticationProviderRequestBus>("AuthenticationProviderRequestBus")
behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None")
->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP")
->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon")
->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google");
behaviorContext->EBus<AuthenticationProviderScriptCanvasRequestBus>("AuthenticationProviderRequestBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens)
->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens)
->Event(
"PasswordGrantSingleFactorSignInAsync", &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(
@@ -54,7 +54,7 @@ namespace AWSClientAuth
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey);
AZ_Warning(
"AWSCognitoUserManagementController", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
"AWSCognitoUserManagementController", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail.");
return !m_cognitoAppClientId.empty();
}
@@ -0,0 +1,55 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AWSClientAuthGemMock.h>
#include <Authentication/AuthenticationProviderManager.h>
namespace AWSClientAuthUnitTest
{
class AuthenticationProviderManagerLocalMock
: public AWSClientAuth::AuthenticationProviderManager
{
public:
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens;
using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync;
using AWSClientAuth::AuthenticationProviderManager::Initialize;
using AWSClientAuth::AuthenticationProviderManager::IsSignedIn;
using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync;
using AWSClientAuth::AuthenticationProviderManager::SignOut;
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface> CreateAuthenticationProviderObjectMock(
const AWSClientAuth::ProviderNameEnum& providerName)
{
auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName);
providerObject.reset();
return AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>>();
}
AuthenticationProviderManagerLocalMock()
{
ON_CALL(*this, CreateAuthenticationProviderObject(testing::_))
.WillByDefault(testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock));
}
MOCK_METHOD1(
CreateAuthenticationProviderObject,
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface>(const AWSClientAuth::ProviderNameEnum&));
};
} // namespace AWSClientAuthUnitTest
@@ -0,0 +1,261 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/std/utils.h>
#include <Authentication/AuthenticationProviderManager.h>
#include <Authentication/AWSCognitoAuthenticationProvider.h>
#include <Authentication/LWAAuthenticationProvider.h>
#include <Authentication/AuthenticationTokens.h>
#include <Authentication/AuthenticationProviderTypes.h>
#include <AWSClientAuthGemMock.h>
#include <Authentication/AuthenticationProviderManagerMock.h>
class AuthenticationProviderManagerScriptCanvasTest
: public AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture
{
protected:
void SetUp() override
{
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp();
AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext);
AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext);
m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg",
m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder);
CreateTestFile("authenticationProvider.setreg"
, R"({
"AWS":
{
"LoginWithAmazon":
{
"AppClientId": "TestLWAClientId",
"GrantType": "device_code",
"Scope": "profile",
"ResponseType": "device_code",
"OAuthCodeURL": "https://api.amazon.com/auth/o2/create/codepair",
"OAuthTokensURL": "https://oauth2.googleapis.com/token"
},
"Google":
{
"AppClientId": "TestGoogleClientId",
"ClientSecret": "123",
"GrantType": "urn:ietf:params:oauth:grant-type:device_code",
"Scope": "profile",
"OAuthCodeURL": "https://oauth2.googleapis.com/device/code",
"OAuthTokensURL": "https://oauth2.googleapis.com/token"
}
}
})");
m_mockController = AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>>();
}
void TearDown() override
{
m_mockController.reset();
AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::TearDown();
}
public:
AZStd::unique_ptr<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderManagerLocalMock>> m_mockController;
AZStd::string m_settingspath;
AZStd::vector<AZStd::string> m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP,
AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle};
};
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success)
{
ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath));
ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Fail_NonConfiguredProviderError)
{
AZ_TEST_START_TRACE_SUPPRESSION;
m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringApple, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1);
m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1);
m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock> *lwaProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get();
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
EXPECT_CALL(*lwaProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 600);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens;
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail)
{
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
m_mockController->GetAuthenticationTokens(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* cognitoProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get();
AWSClientAuth::AuthenticationTokens tokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60);
EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens));
m_mockController->IsSignedIn(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP);
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>* googleProviderMock = (testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get();
EXPECT_CALL(*googleProviderMock, SignOut()).Times(1);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnSignOut(testing::_)).Times(1);
m_mockController->SignOut(AWSClientAuth::ProvideNameEnumStringGoogle);
googleProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath)
{
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, ""));
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
@@ -10,8 +10,6 @@
*
*/
#include <AzTest/AzTest.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/std/utils.h>
@@ -20,42 +18,7 @@
#include <Authentication/LWAAuthenticationProvider.h>
#include <Authentication/AuthenticationTokens.h>
#include <AWSClientAuthGemMock.h>
namespace AWSClientAuthUnitTest
{
class AuthenticationProviderManagerLocalMock
: public AWSClientAuth::AuthenticationProviderManager
{
public:
using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap;
using AWSClientAuth::AuthenticationProviderManager::Initialize;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync;
using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync;
using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync;
using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens;
using AWSClientAuth::AuthenticationProviderManager::SignOut;
using AWSClientAuth::AuthenticationProviderManager::IsSignedIn;
AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface> CreateAuthenticationProviderObjectMock(const AWSClientAuth::ProviderNameEnum& providerName)
{
auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName);
providerObject.reset();
return AZStd::make_unique<testing::NiceMock<AWSClientAuthUnitTest::AuthenticationProviderMock>>();
}
AuthenticationProviderManagerLocalMock()
{
ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)).WillByDefault(
testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock));
}
MOCK_METHOD1(CreateAuthenticationProviderObject, AZStd::unique_ptr<AWSClientAuth::AuthenticationProviderInterface>(const AWSClientAuth::ProviderNameEnum&));
};
}
#include <Authentication/AuthenticationProviderManagerMock.h>
class AuthenticationProviderManagerTest
@@ -239,6 +202,15 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken
cognitoProviderMock = nullptr;
}
TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail)
{
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0);
EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1);
m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProviderNameEnum::AWSCognitoIDP);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(AuthenticationProviderManagerTest, GetTokens_Success)
{
m_mockController->Initialize(m_enabledProviderNames, m_settingspath);
@@ -20,6 +20,7 @@ set(FILES
Include/Private/AWSClientAuthBus.h
Include/Private/AWSClientAuthResourceMappingConstants.h
Include/Private/Authentication/AuthenticationProviderTypes.h
Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h
Include/Private/Authentication/AuthenticationProviderManager.h
Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h
@@ -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=[
@@ -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;
@@ -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.
@@ -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;
}
}
@@ -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()
@@ -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);
@@ -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;
@@ -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();
@@ -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>
@@ -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();
}
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
@@ -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;
@@ -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;
@@ -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();
}
}
@@ -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
@@ -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
@@ -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
@@ -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;
@@ -519,8 +519,8 @@ void CAtomShimRenderAuxGeom::DrawQuad(float width, float height, const Matrix34&
if (auto auxGeom = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(defaultScene))
{
AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid;
AZ::Transform transform = LYTransformToAZTransform(matWorld);
auxGeom->DrawQuad(width, height, transform, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest);
AZ::Matrix3x4 local2World = LYTransformToAZMatrix3x4(matWorld);
auxGeom->DrawQuad(width, height, local2World, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest);
}
}
-6
View File
@@ -68,12 +68,6 @@ ly_add_target(
)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
find_package(OpenGL QUIET REQUIRED)
# Imported targets (like OpenGL::GL) are scoped to a directory. Add a
# a global scope
add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL)
target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL)
ly_add_target(
NAME EMotionFX.Editor.Static STATIC
@@ -131,8 +131,14 @@ namespace RenderGL
void GLRenderUtil::Validate()
{
mLineShader->Validate();
mMeshShader->Validate();
if (mLineShader)
{
mLineShader->Validate();
}
if (mMeshShader)
{
mMeshShader->Validate();
}
}
// destroy the allocated memory
@@ -116,12 +116,12 @@ namespace RenderGL
}
bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, const char* filename)
bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename)
{
QFile file(filename);
QFile file(QString::fromUtf8(filename.Native().data(), aznumeric_caster(filename.Native().size())));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%s'.", filename);
AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%.*s'.", AZ_STRING_ARG(filename.Native()));
return false;
}
@@ -156,7 +156,7 @@ namespace RenderGL
if (success == false)
{
MCore::LogError("[GLSL] Failed to compile shader '%s'.", filename);
MCore::LogError("[GLSL] Failed to compile shader '%.*s'.", AZ_STRING_ARG(filename.Native()));
return false;
}
@@ -212,7 +212,7 @@ namespace RenderGL
// Init
bool GLSLShader::Init(const char* vFile, const char* pFile, MCore::Array<AZStd::string>& defines)
bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines)
{
initializeOpenGLFunctions();
/*const char* args[] = { "unroll all",
@@ -225,24 +225,24 @@ namespace RenderGL
glUseProgram(0);
// compile shaders
if (vFile && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vFile) == false)
if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vertexFileName) == false)
{
return false;
}
if (pFile && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pFile) == false)
if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pixelFileName) == false)
{
return false;
}
// create program
mProgram = glCreateProgram();
if (vFile)
if (!vertexFileName.empty())
{
glAttachShader(mProgram, mVertexShader);
}
if (pFile)
if (!pixelFileName.empty())
{
glAttachShader(mProgram, mPixelShader);
}
@@ -256,7 +256,7 @@ namespace RenderGL
if (!success)
{
MCore::LogInfo("[OpenGL] Failed to link shaders '%s' and '%s' ", vFile, pFile);
MCore::LogInfo("[OpenGL] Failed to link shaders '%.*s' and '%.*s' ", AZ_STRING_ARG(vertexFileName.Native()), AZ_STRING_ARG(pixelFileName.Native()));
InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog);
return false;
}
@@ -14,6 +14,7 @@
#define __RENDERGL_GLSLSHADER_H
#include <AzCore/std/string/string.h>
#include <AzCore/IO/Path/Path.h>
#include "Shader.h"
// include OpenGL
@@ -45,7 +46,7 @@ namespace RenderGL
MCORE_INLINE unsigned int GetProgram() const { return mProgram; }
bool CheckIfIsDefined(const char* attributeName);
bool Init(const char* vertexFileName, const char* pixelFileName, MCore::Array<AZStd::string>& defines);
bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines);
void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override;
void SetUniform(const char* name, float value) override;
@@ -81,11 +82,11 @@ namespace RenderGL
ShaderParameter* FindAttribute(const char* name);
ShaderParameter* FindUniform(const char* name);
bool CompileShader(const GLenum type, unsigned int* outShader, const char* filename);
bool CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename);
template<class T>
void InfoLog(GLuint object, T func);
AZStd::string mFileName;
AZ::IO::Path mFileName;
MCore::Array<uint32> mActivatedAttribs;
MCore::Array<uint32> mActivatedTextures;
@@ -203,7 +203,7 @@ namespace RenderGL
// try to initialize the graphics system
bool GraphicsManager::Init(const char* shaderPath)
bool GraphicsManager::Init(AZ::IO::PathView shaderPath)
{
initializeOpenGLFunctions();
@@ -364,7 +364,7 @@ namespace RenderGL
// try to load a texture
Texture* GraphicsManager::LoadTexture([[maybe_unused]] const char* filename, [[maybe_unused]] bool createMipMaps)
Texture* GraphicsManager::LoadTexture([[maybe_unused]] AZ::IO::PathView filename, [[maybe_unused]] bool createMipMaps)
{
//Texture Library is no longer used
//temporarily blank
@@ -373,19 +373,19 @@ namespace RenderGL
// try to load a texture
Texture* GraphicsManager::LoadTexture(const char* filename)
Texture* GraphicsManager::LoadTexture(AZ::IO::PathView filename)
{
return LoadTexture(filename, mCreateMipMaps);
}
// LoadPostProcessShader
PostProcessShader* GraphicsManager::LoadPostProcessShader(const char* cFileName)
PostProcessShader* GraphicsManager::LoadPostProcessShader(AZ::IO::PathView cFileName)
{
AZStd::string filename = mShaderPath + AZStd::string(cFileName);
AZ::IO::PathView filename = mShaderPath / cFileName;
// check if the shader is already in the cache
Shader* s = mShaderCache.FindShader(filename.c_str());
Shader* s = mShaderCache.FindShader(filename.Native());
if (s)
{
return (PostProcessShader*)s;
@@ -393,19 +393,19 @@ namespace RenderGL
// load the shader from disk
PostProcessShader* shader = new PostProcessShader();
if (!shader->Init(filename.c_str()))
if (!shader->Init(filename))
{
delete shader;
return nullptr;
}
mShaderCache.AddShader(filename.c_str(), shader);
mShaderCache.AddShader(filename.Native(), shader);
return shader;
}
// LoadShader
GLSLShader* GraphicsManager::LoadShader(const char* vertexFileName, const char* pixelFileName)
GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName)
{
MCore::Array<AZStd::string> defines;
return LoadShader(vertexFileName, pixelFileName, defines);
@@ -413,34 +413,21 @@ namespace RenderGL
// LoadShader
GLSLShader* GraphicsManager::LoadShader(const char* vFile, const char* pFile, MCore::Array<AZStd::string>& defines)
GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines)
{
AZStd::string vStr;
AZStd::string pStr;
if (vFile)
{
vStr = AZStd::string::format("%s%s", mShaderPath.c_str(), vFile);
}
if (pFile)
{
pStr = AZStd::string::format("%s%s", mShaderPath.c_str(), pFile);
}
const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName};
const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName};
// construct the lookup string for the shader cache
AZStd::string dStr;
AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native();
const uint32 numDefines = defines.GetLength();
for (uint32 n = 0; n < numDefines; n++)
{
dStr += AZStd::string::format("#%s", defines[n].c_str());
cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str());
}
AZStd::string cStr;
cStr = AZStd::string::format("%s%s%s", vStr.c_str(), pStr.c_str(), dStr.c_str());
// check if the shader is already in the cache
Shader* cShader = mShaderCache.FindShader(cStr.c_str());
Shader* cShader = mShaderCache.FindShader(cacheLookupStr);
if (cShader)
{
return (GLSLShader*)cShader;
@@ -448,13 +435,13 @@ namespace RenderGL
// load the shader from disk
GLSLShader* shader = new GLSLShader();
if (!shader->Init(vFile ? vStr.c_str() : nullptr, pFile ? pStr.c_str() : nullptr, defines))
if (!shader->Init(vertexPath, pixelPath, defines))
{
delete shader;
return nullptr;
}
mShaderCache.AddShader(cStr.c_str(), shader);
mShaderCache.AddShader(cacheLookupStr, shader);
return shader;
}
@@ -13,6 +13,7 @@
#ifndef __RENDERGL_GRAPHICSMANAGER__H
#define __RENDERGL_GRAPHICSMANAGER__H
#include <AzCore/IO/Path/Path.h>
#include <MCore/Source/StandardHeaders.h>
#include <MCore/Source/Vector.h>
#include <MCore/Source/Color.h>
@@ -57,21 +58,21 @@ namespace RenderGL
const char* GetDeviceName();
const char* GetDeviceVendor();
MCORE_INLINE RenderTexture* GetRenderTexture() { return mRenderTexture; }
MCORE_INLINE const char* GetShaderPath() const { return mShaderPath.c_str(); }
MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return mShaderPath; }
MCORE_INLINE TextureCache* GetTextureCache() { return &mTextureCache; }
bool Init(const char* shaderPath = "Shaders/");
bool Init(AZ::IO::PathView shaderPath = "Shaders");
bool GetIsPostProcessingEnabled() const { return mPostProcessing; }
PostProcessShader* LoadPostProcessShader(const char* filename);
GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName);
GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName, MCore::Array<AZStd::string>& defines);
PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename);
GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName);
GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array<AZStd::string>& defines);
MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; }
MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; }
Texture* LoadTexture(const char* filename, bool createMipMaps);
Texture* LoadTexture(const char* filename);
Texture* LoadTexture(AZ::IO::PathView filename, bool createMipMaps);
Texture* LoadTexture(AZ::IO::PathView filename);
void SetCreateMipMaps(bool createMipMaps) { mCreateMipMaps = createMipMaps; }
MCORE_INLINE bool GetCreateMipMaps() const { return mCreateMipMaps; }
@@ -96,7 +97,7 @@ namespace RenderGL
void SetShader(Shader* shader);
MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { mRenderTexture = texture; }
MCORE_INLINE void SetShaderPath(const char* shaderPath) { mShaderPath = shaderPath; }
MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { mShaderPath = shaderPath; }
MCORE_INLINE void SetBloomEnabled(bool enabled) { mBloomEnabled = enabled; }
MCORE_INLINE void SetBloomThreshold(float threshold) { mBloomThreshold = threshold; }
@@ -154,7 +155,7 @@ namespace RenderGL
MCommon::Camera* mCamera; /**< The camera used for rendering. */
ShaderCache mShaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */
AZStd::string mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */
AZ::IO::Path mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */
MCore::RGBAColor mClearColor; /**< The scene background color. */
MCore::RGBAColor mGradientSourceColor; /**< The background gradient source color. */
MCore::RGBAColor mGradientTargetColor; /**< The background gradient target color. */
@@ -11,6 +11,7 @@
*/
#include <AzCore/Math/Vector2.h>
#include <AzCore/IO/Path/Path.h>
#include "PostProcessShader.h"
#include "GraphicsManager.h"
@@ -82,7 +83,7 @@ namespace RenderGL
// Init
bool PostProcessShader::Init(const char* filename)
bool PostProcessShader::Init(AZ::IO::PathView filename)
{
MCore::Array<AZStd::string> defines;
return GLSLShader::Init(nullptr, filename, defines);
@@ -13,6 +13,7 @@
#ifndef __RENDERGL_POSTPROCESS_SHADER_H
#define __RENDERGL_POSTPROCESS_SHADER_H
#include <AzCore/IO/Path/Path_fwd.h>
#include "GLSLShader.h"
#include "RenderTexture.h"
@@ -34,7 +35,7 @@ namespace RenderGL
void Deactivate() override;
bool Init(const char* filename);
bool Init(AZ::IO::PathView filename);
void Render();
private:
@@ -48,7 +48,7 @@ namespace RenderGL
// add the shader to the cache (assume there are no duplicate names)
void ShaderCache::AddShader(const char* filename, Shader* shader)
void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader)
{
mEntries.AddEmpty();
mEntries.GetLast().mName = filename;
@@ -57,12 +57,12 @@ namespace RenderGL
// try to locate a shader based on its name
Shader* ShaderCache::FindShader(const char* filename) const
Shader* ShaderCache::FindShader(AZStd::string_view filename) const
{
const uint32 numEntries = mEntries.GetLength();
for (uint32 i = 0; i < numEntries; ++i)
{
if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare
if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare
{
return mEntries[i].mShader;
}
@@ -33,8 +33,8 @@ namespace RenderGL
~ShaderCache(); // automatically calls Release
void Release();
void AddShader(const char* filename, Shader* shader);
Shader* FindShader(const char* filename) const;
void AddShader(AZStd::string_view filename, Shader* shader);
Shader* FindShader(AZStd::string_view filename) const;
bool CheckIfHasShader(Shader* shader) const;
private:
@@ -64,7 +64,7 @@ namespace EMStudio
// create graphics manager and initialize it
mGraphicsManager = new RenderGL::GraphicsManager();
if (mGraphicsManager->Init(shaderPath.c_str()) == false)
if (mGraphicsManager->Init(shaderPath) == false)
{
MCore::LogError("Could not initialize OpenGL graphics manager.");
return false;
@@ -13,10 +13,4 @@
# based on the active platform
# NOTE: functions in cmake are global, therefore adding functions to this file
# is being avoided to prevent overriding functions declared in other targets platfrom
# specific cmake files
target_compile_definitions(3rdParty::OpenGLInterface
INTERFACE
# MacOS 10.14 deprecates OpenGL. This silences the warnings for now.
GL_SILENCE_DEPRECATION
)
# specific cmake files
@@ -823,20 +823,37 @@ void CAnimSequence::SetId(uint32 newId)
}
//////////////////////////////////////////////////////////////////////////
void CAnimSequence::Reflect(AZ::SerializeContext* serializeContext)
static bool AnimSequenceVersionConverter(
AZ::SerializeContext& serializeContext,
AZ::SerializeContext::DataElementNode& rootElement)
{
serializeContext->Class<CAnimSequence>()
->Version(4)
->Field("Name", &CAnimSequence::m_name)
->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId)
->Field("Flags", &CAnimSequence::m_flags)
->Field("TimeRange", &CAnimSequence::m_timeRange)
->Field("ID", &CAnimSequence::m_id)
->Field("Nodes", &CAnimSequence::m_nodes)
->Field("SequenceType", &CAnimSequence::m_sequenceType)
->Field("Events", &CAnimSequence::m_events)
->Field("Expanded", &CAnimSequence::m_expanded)
->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId);
if (rootElement.GetVersion() < 5)
{
rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimSequence>());
}
return true;
}
void CAnimSequence::Reflect(AZ::ReflectContext* context)
{
IAnimSequence::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
{
serializeContext->Class<CAnimSequence, IAnimSequence>()
->Version(IAnimSequence::kSequenceVersion, &AnimSequenceVersionConverter)
->Field("Name", &CAnimSequence::m_name)
->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId)
->Field("Flags", &CAnimSequence::m_flags)
->Field("TimeRange", &CAnimSequence::m_timeRange)
->Field("ID", &CAnimSequence::m_id)
->Field("Nodes", &CAnimSequence::m_nodes)
->Field("SequenceType", &CAnimSequence::m_sequenceType)
->Field("Events", &CAnimSequence::m_events)
->Field("Expanded", &CAnimSequence::m_expanded)
->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId);
}
}
//////////////////////////////////////////////////////////////////////////
@@ -154,7 +154,7 @@ public:
return m_nextTrackId++;
}
static void Reflect(AZ::SerializeContext* serializeContext);
static void Reflect(AZ::ReflectContext* context);
private:
void ComputeTimeRange();
+9 -81
View File
@@ -1,84 +1,12 @@
-- When you see an option that does not have a platform preceeding it, that is the default
-- value for anything not specificly set per platform. So if remote_filesystem=0 and you have
-- ios_remote_file_system=1 then remote filesystem will be off for all platforms except ios
-- Any of the settings in this file can be prefixed with a platform name:
-- android, ios, mac, linux, windows, etc...
-- or left unprefixed, to set all platforms not specified. The rules apply in the order they're declared
; This file is deprecated and is only use currently for setting the path when running O3DE in an engine-centric manner
; By engine-centric, what is meant is using CMake to configure from the <engine-root> directory and passing in the LY_PROJECTS value
project_path=AutomatedTesting
-- remote_filesystem - enable Virtual File System (VFS)
-- This feature allows a remote instance of the game to run off assets
-- on the asset processor computers cache instead of deploying them the remote device
-- By default it is off and can be overridden for any platform
remote_filesystem=0
provo_remote_filesystem=0
android_remote_filesystem=0
ios_remote_filesystem=0
mac_remote_filesystem=0
-- What type of assets are we going to load?
-- We need to know this before we establish VFS because different platform assets
-- are stored in different root folders in the cache. These correspond to the names
-- In the asset processor config file. This value also controls what config file is read
-- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_es3.cfg)
-- by default, pc assets (in the 'pc' folder) are used, with RC being fed 'pc' as the platform
-- by default on console we use the default assets=pc for better iteration times
-- we should turn on console specific assets only when in release and/or testing assets and/or loading performance
-- that way most people will not need to have 3 different caches taking up disk space
assets = pc
-- provo_assets = provo
-- salem_assets = salem
-- jasper_assets = jasper
android_assets = es3
ios_assets = ios
mac_assets = osx_gl
-- Add the IP address of your console to the allowed list that will connect to the asset processor here
-- You can list addresses or CIDR's. CIDR's are helpful if you are using DHCP. A CIDR looks like an ip address with
-- a /n on the end means how many bits are significant. 8bits.8bits.8bits.8bits = /32
-- Example: 192.168.1.3
-- Example: 192.168.1.3, 192.168.1.15
-- Example: 192.168.1.0/24 will allow any address starting with 192.168.1.
-- Example: 192.168.0.0/16 will allow any address starting with 192.168.
-- Example: 192.168.0.0/8 will allow any address starting with 192.
-- allowed_list =
-- IP address and optionally port of the asset processor.
-- Set your PC IP here: (and uncomment the next line)
-- If you are running your asset processor on a windows machine you
-- can find out your ip address by opening a cmd prompt and typing in ipconfig
-- remote_ip = 127.0.0.1
-- remote_port = 45643
-- Which way do you want to connect the asset processor to the game: 1=game connects to AP "connect", 0=AP connects to game "listen"
-- Note: android and IOS over USB port forwarding may need to listen instead of connect
connect_to_remote=0
windows_connect_to_remote=1
provo_connect_to_remote=1
salem_connect_to_remote=0
jasper_connect_to_remote=0
android_connect_to_remote=0
ios_connect_to_remote=0
mac_connect_to_remote=0
-- Should we tell the game to wait and not proceed unless we have a connection to the AP or
-- do we allow it to continue to try to connect in the background without waiting
-- Note: Certain options REQUIRE that we do not proceed unless we have a connection, and will override this option to 1 when set
-- Since remote_filesystem=1 requires a connection to proceed it will override our option to 1
wait_for_connect=0
provo_wait_for_connect=0
salem_wait_for_connect=0
jasper_wait_for_connect=0
windows_wait_for_connect=1
android_wait_for_connect=0
ios_wait_for_connect=0
mac_wait_for_connect=0
-- How long applications should wait while attempting to connect to an already launched AP(in seconds)
-- connect_ap_timeout=3
-- How long application should wait when launching the AP and wait for the AP to connect back to it(in seconds)
-- This time is dependent on Machine load as well as how long it takes for the new AP instance to initialize
-- A debug AP takes longer to start up than a profile AP
-- launch_ap_timeout=15
; The Asset Processor Specific settings are now the <engine-root>/Engine/Registry/bootstrap.setreg settings
; The Engine specific settings can be overridden in order of least precedence to most
; 1. Override the settings in a "<gem-root>/Registry/*.setreg(patch)" file (Shared per Gem Settings)
; 2. Override the settings in a "<project-root>/Registry/*.setreg(patch)" file (Shared per Project Settings)
; 3. Override the settings in a "<project-root>/Registry/*.setreg(patch)" file (User per Project Settings)
; 4. Override the settings in a "~/.o3de/Registry/*.setreg(patch)" file (User Global Settings)
; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms
-4
View File
@@ -116,10 +116,6 @@ function(ly_add_external_target)
# Setting BASE_PATH variable in the parent scope to allow for the Find<3rdParty>.cmake scripts to use them
set(BASE_PATH ${BASE_PATH} PARENT_SCOPE)
if(NOT EXISTS ${BASE_PATH})
message(FATAL_ERROR "Cannot find 3rdParty library ${ly_add_external_target_NAME} on path ${BASE_PATH}")
endif()
add_library(3rdParty::${NAME_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL)
if(ly_add_external_target_INCLUDE_DIRECTORIES)
+19
View File
@@ -0,0 +1,19 @@
#
# 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.
#
find_package(OpenGL)
ly_add_external_target(
NAME OpenGLInterface
VERSION ""
BUILD_DEPENDENCIES
OpenGL::GL
)
+13
View File
@@ -0,0 +1,13 @@
#
# 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.
#
# MacOS 10.14 deprecates OpenGL. This silences the warnings for now.
set(OPENGLINTERFACE_COMPILE_DEFINITIONS GL_SILENCE_DEPRECATION)

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