Merge branch 'main' into LYN-2893

This commit is contained in:
amzn-sj
2021-04-16 16:21:36 -07:00
126 changed files with 3577 additions and 1500 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)
@@ -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;
@@ -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,100 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ByteStreamSerializer.h"
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/StringFunc/StringFunc.h>
namespace AZ
{
namespace ByteSerializerInternal
{
static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
switch (inputValue.GetType())
{
case rapidjson::kStringType: {
JsonByteStream buffer;
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
{
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
*valAsByteStream = AZStd::move(buffer);
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
}
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
}
case rapidjson::kArrayType:
case rapidjson::kObjectType:
case rapidjson::kNullType:
case rapidjson::kFalseType:
case rapidjson::kTrueType:
case rapidjson::kNumberType:
return context.Report(
Tasks::ReadField, Outcomes::Unsupported,
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
default:
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
}
}
static JsonSerializationResult::Result StoreWithDefault(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context)
{
using JsonSerializationResult::Outcomes;
using JsonSerializationResult::Tasks;
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
{
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
}
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
}
} // namespace ByteSerializerInternal
AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonByteStreamSerializer::Load(
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == outputValueTypeId,
"Unable to deserialize AZStd::vector<AZ::u8>> to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::Load(outputValue, inputValue, context);
}
JsonSerializationResult::Result JsonByteStreamSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
JsonSerializerContext& context)
{
AZ_Assert(
azrtti_typeid<JsonByteStream>() == valueTypeId,
"Unable to serialize AZStd::vector<AZ::u8> to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context);
}
} // namespace AZ
@@ -0,0 +1,38 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
using JsonByteStream = AZStd::vector<AZ::u8>; //!< Alias for AZStd::vector<AZ::u8>.
//! Serialize a stream of bytes (usually binary data) as a json string value.
//! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo<AZStd::vector<AZ::u8>> - see AZStdContainers.inl for more
//! details).
class JsonByteStreamSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
JsonSerializerContext& context) override;
};
} // namespace AZ
@@ -14,6 +14,7 @@
#include <AzCore/Serialization/Json/ArraySerializer.h>
#include <AzCore/Serialization/Json/BasicContainerSerializer.h>
#include <AzCore/Serialization/Json/BoolSerializer.h>
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
#include <AzCore/Serialization/Json/DoubleSerializer.h>
#include <AzCore/Serialization/Json/IntSerializer.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
@@ -68,6 +69,8 @@ namespace AZ
jsonContext->Serializer<JsonStringSerializer>()->HandlesType<AZStd::string>();
jsonContext->Serializer<JsonOSStringSerializer>()->HandlesType<OSString>();
jsonContext->Serializer<JsonByteStreamSerializer>()->HandlesType<JsonByteStream>();
jsonContext->Serializer<JsonBasicContainerSerializer>()
->HandlesType<AZStd::fixed_vector>()
->HandlesType<AZStd::forward_list>()
@@ -505,6 +505,8 @@ set(FILES
Serialization/Json/BasicContainerSerializer.cpp
Serialization/Json/BoolSerializer.h
Serialization/Json/BoolSerializer.cpp
Serialization/Json/ByteStreamSerializer.h
Serialization/Json/ByteStreamSerializer.cpp
Serialization/Json/CastingHelpers.h
Serialization/Json/DoubleSerializer.h
Serialization/Json/DoubleSerializer.cpp
@@ -0,0 +1,59 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
#include <Tests/Serialization/Json/BaseJsonSerializerFixture.h>
#include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
namespace JsonSerializationTests
{
class ByteStreamSerializerTestDescription : public JsonSerializerConformityTestDescriptor<AZ::JsonByteStream>
{
public:
AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
{
return AZStd::make_shared<AZ::JsonByteStreamSerializer>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateDefaultInstance() override
{
return AZStd::make_shared<AZ::JsonByteStream>();
}
AZStd::shared_ptr<AZ::JsonByteStream> CreateFullySetInstance() override
{
// create a JsonByteStream (AZStd::vector<u8>) with ten 'a's
return AZStd::make_shared<AZ::JsonByteStream>(10, 'a');
}
AZStd::string_view GetJsonForFullySetInstance() override
{
// Base64 encoded version of 'aaaaaaaaaa' (see CreateFullySetInstance)
return R"("YWFhYWFhYWFhYQ==")";
}
void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
{
features.EnableJsonType(rapidjson::kStringType);
features.m_supportsPartialInitialization = false;
features.m_supportsInjection = false;
}
bool AreEqual(const AZ::JsonByteStream& lhs, const AZ::JsonByteStream& rhs) override
{
return lhs == rhs;
}
};
using ByteStreamConformityTestTypes = ::testing::Types<ByteStreamSerializerTestDescription>;
INSTANTIATE_TYPED_TEST_CASE_P(JsonByteStreamSerialzier, JsonSerializerConformityTests, ByteStreamConformityTestTypes);
} // namespace JsonSerializationTests
@@ -98,6 +98,7 @@ set(FILES
Serialization/Json/BaseJsonSerializerTests.cpp
Serialization/Json/BasicContainerSerializerTests.cpp
Serialization/Json/BoolSerializerTests.cpp
Serialization/Json/ByteStreamSerializerTests.cpp
Serialization/Json/ColorSerializerTests.cpp
Serialization/Json/DoubleSerializerTests.cpp
Serialization/Json/IntSerializerTests.cpp
@@ -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
@@ -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
@@ -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);
}
+1 -1
View File
@@ -56,7 +56,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
// Prevent re-sizing
setFixedSize(m_enforcedWidth, m_enforcedHeight);
+34 -29
View File
@@ -60,35 +60,35 @@
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_42">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>161</width>
<height>49</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="m_transparentVersion">
<property name="text">
@@ -251,6 +251,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QSvgWidget</class>
<extends>QWidget</extends>
<header>qsvgwidget.h</header>
</customwidget>
<customwidget>
<class>ClickableLabel</class>
<extends>QLabel</extends>
@@ -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()
{
+1 -1
View File
@@ -49,7 +49,7 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg"));
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
m_ui->m_TransparentConfidential->setObjectName("copyrightNotice");
m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText);
+1 -1
View File
@@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/StartupLogoDialog">
<file>lumberyard_logo.svg</file>
<file>o3de_logo.svg</file>
<file>splashscreen_1_27.png</file>
</qresource>
</RCC>
+4 -4
View File
@@ -42,14 +42,14 @@
<widget class="QSvgWidget" name="m_logo" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>49</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>60</height>
<width>161</width>
<height>50</height>
</size>
</property>
</widget>
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 27 KiB

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

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -2777,26 +2777,6 @@ AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state)
return 0;
}
AZ::u32 SandboxIntegrationManager::SetStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->SetStateFlag(state);
}
return 0;
}
AZ::u32 SandboxIntegrationManager::ClearStateFlag(AZ::u32 state)
{
if (m_dc)
{
return m_dc->ClearStateFlag(state);
}
return 0;
}
void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm)
{
if (m_dc)
@@ -268,8 +268,6 @@ private:
bool SetDrawInFrontMode(bool bOn) override;
AZ::u32 GetState() override;
AZ::u32 SetState(AZ::u32 state) override;
AZ::u32 SetStateFlag(AZ::u32 state) override;
AZ::u32 ClearStateFlag(AZ::u32 state) override;
void PushMatrix(const AZ::Transform& tm) override;
void PopMatrix() override;
@@ -12,6 +12,7 @@
#pragma once
#include <Authentication/AuthenticationProviderBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@@ -28,74 +29,104 @@ namespace AWSClientAuth
OnPasswordGrantMultiFactorConfirmSignInSuccess, OnPasswordGrantMultiFactorConfirmSignInFail,
OnDeviceCodeGrantSignInSuccess, OnDeviceCodeGrantSignInFail,
OnDeviceCodeGrantConfirmSignInSuccess, OnDeviceCodeGrantConfirmSignInFail,
OnRefreshTokensSuccess, OnRefreshTokensFail,
OnSignOut
OnRefreshTokensSuccess, OnRefreshTokensFail
);
void OnPasswordGrantSingleFactorSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantSingleFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantSingleFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorSignInSuccess() override
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
AZ::TickBus::QueueFunction([this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInSuccess);
});
}
void OnPasswordGrantMultiFactorSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorSignInFail, error);
});
}
void OnPasswordGrantMultiFactorConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken);
});
}
void OnPasswordGrantMultiFactorConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error);
});
}
void OnDeviceCodeGrantSignInSuccess(
const AZStd::string& userCode, const AZStd::string& verificationUrl, const int codeExpiresInSeconds) override
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
AZ::TickBus::QueueFunction([userCode, verificationUrl, codeExpiresInSeconds, this]()
{
Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds);
});
}
void OnDeviceCodeGrantSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantSignInFail, error);
});
}
void OnDeviceCodeGrantConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken);
});
}
void OnDeviceCodeGrantConfirmSignInFail(const AZStd::string& error) override
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnDeviceCodeGrantConfirmSignInFail, error);
});
}
void OnRefreshTokensSuccess(const AuthenticationTokens& authenticationToken) override
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
AZ::TickBus::QueueFunction([authenticationToken, this]()
{
Call(FN_OnRefreshTokensSuccess, authenticationToken);
});
}
void OnRefreshTokensFail(const AZStd::string& error) override
{
Call(FN_OnRefreshTokensFail, error);
}
void OnSignOut(const ProviderNameEnum& provideName) override
{
Call(FN_OnSignOut, provideName);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRefreshTokensFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -16,6 +16,7 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <Authentication/AuthenticationProviderBus.h>
#include <Authentication/AuthenticationProviderScriptCanvasBus.h>
#include <Authentication/AuthenticationProviderInterface.h>
#include <Authentication/AuthenticationTokens.h>
@@ -23,7 +24,8 @@ namespace AWSClientAuth
{
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
class AuthenticationProviderManager
: AuthenticationProviderRequestBus::Handler
: public AuthenticationProviderRequestBus::Handler
, public AuthenticationProviderScriptCanvasRequestBus::Handler
{
public:
AZ_RTTI(AuthenticationProviderManager, "{45813BA5-9A46-4A2A-A923-C79CFBA0E63D}", IAuthenticationProviderRequests);
@@ -43,6 +45,22 @@ namespace AWSClientAuth
bool IsSignedIn(const ProviderNameEnum& providerName) override;
bool SignOut(const ProviderNameEnum& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override;
// AuthenticationProviderScriptCanvasRequest interface
bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) override;
void PasswordGrantSingleFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override;
void PasswordGrantMultiFactorConfirmSignInAsync(
const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override;
void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) override;
void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) override;
void RefreshTokensAsync(const AZStd::string& providerName) override;
void GetTokensWithRefreshAsync(const AZStd::string& providerName) override;
bool IsSignedIn(const AZStd::string& providerName) override;
bool SignOut(const AZStd::string& providerName) override;
AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) override;
virtual AZStd::unique_ptr<AuthenticationProviderInterface> CreateAuthenticationProviderObject(const ProviderNameEnum& providerName);
AZStd::map<ProviderNameEnum, AZStd::unique_ptr<AuthenticationProviderInterface>> m_authenticationProvidersMap;
@@ -50,9 +68,9 @@ namespace AWSClientAuth
private:
bool IsProviderInitialized(const ProviderNameEnum& providerName);
void ResetProviders();
ProviderNameEnum GetProviderNameEnum(AZStd::string name);
AZStd::shared_ptr<AZ::SettingsRegistryInterface> m_settingsRegistry;
};
} // namespace AWSClientAuth
@@ -0,0 +1,103 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <Authentication/AuthenticationTokens.h>
namespace AWSClientAuth
{
//! Abstract class for authentication provider script canvas requests.
//! Private class to allow provide names to be string type instead of an enum as behavior context does not work well with enum's.
class IAuthenticationProviderScriptCanvasRequests
{
public:
AZ_TYPE_INFO(IAuthenticationProviderRequests, "{A8FD915F-9FF2-4BA3-8AA0-8CF7A94A323B}");
//! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers
//! @param providerNames List of provider names to instantiate and initialize for Authentication.
//! @param settingsRegistryPath Path for the settings registry file to use to configure providers.
//! @return bool True: if all providers initialized successfully. False: If any provider fails initialization.
virtual bool Initialize(const AZStd::vector<AZStd::string>& providerNames, const AZStd::string& settingsRegistryPath) = 0;
//! Checks if user is signed in.
//! If access tokens are available and not expired.
//! @param providerName Provider to check signed in for
//! @return bool True if valid access token available, else False
virtual bool IsSignedIn(const AZStd::string& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const AZStd::string& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.
//! @param providerName Provider to get access token for.
//! events: OnRefreshTokensSuccess, OnRefreshTokensFail
virtual void GetTokensWithRefreshAsync(const AZStd::string& providerName) = 0;
//! Signs user out.
//! Clears all cached tokens.
//! @param providerName Provider to sign out.
//! @return bool True: Successfully sign out.
virtual bool SignOut(const AZStd::string& providerName) = 0;
//////////////////////////////////////////////////////////////////////////
};
//! Authentication Request bus for different supported providers.
class AuthenticationProviderScriptCanvasRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
using MutexType = AZ::NullMutex;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
};
using AuthenticationProviderScriptCanvasRequestBus = AZ::EBus<IAuthenticationProviderScriptCanvasRequests, AuthenticationProviderScriptCanvasRequests>;
} // namespace AWSClientAuth
@@ -15,6 +15,14 @@
namespace AWSClientAuth
{
constexpr char ProvideNameEnumStringNone[] = "None";
constexpr char ProvideNameEnumStringAWSCognitoIDP[] = "AWSCognitoIDP";
constexpr char ProvideNameEnumStringLoginWithAmazon[] = "LoginWithAmazon";
constexpr char ProvideNameEnumStringGoogle[] = "Google";
constexpr char ProvideNameEnumStringApple[] = "Apple";
constexpr char ProvideNameEnumStringFacebook[] = "Facebook";
constexpr char ProvideNameEnumStringTwitch[] = "Twitch";
//! Holds Login with Amazon provider serialized settings
class LWAProviderSetting
{
@@ -12,6 +12,7 @@
#pragma once
#include <Authorization/AWSCognitoAuthorizationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AWSClientAuth
@@ -28,12 +29,18 @@ namespace AWSClientAuth
void OnRequestAWSCredentialsSuccess(const ClientAuthAWSCredentials& awsCredentials) override
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
AZ::TickBus::QueueFunction([awsCredentials, this]()
{
Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials);
});
}
void OnRequestAWSCredentialsFail(const AZStd::string& error) override
{
Call(FN_OnRequestAWSCredentialsFail, error);
AZ::TickBus::QueueFunction([error, this]()
{
Call(FN_OnRequestAWSCredentialsFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -12,6 +12,7 @@
#pragma once
#include <UserManagement/AWSCognitoUserManagementBus.h>
#include <AzCore/Component/TickBus.h>
namespace AWSClientAuth
{
@@ -32,62 +33,86 @@ namespace AWSClientAuth
void OnEmailSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnEmailSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnEmailSignUpSuccess, uuid);
});
}
void OnEmailSignUpFail(const AZStd::string& error) override
{
Call(FN_OnEmailSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEmailSignUpFail, error);
});
}
void OnPhoneSignUpSuccess(const AZStd::string& uuid) override
{
Call(FN_OnPhoneSignUpSuccess, uuid);
AZ::TickBus::QueueFunction([uuid, this]() {
Call(FN_OnPhoneSignUpSuccess, uuid);
});
}
void OnPhoneSignUpFail(const AZStd::string& error) override
{
Call(FN_OnPhoneSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnPhoneSignUpFail, error);
});
}
void OnConfirmSignUpSuccess() override
{
Call(FN_OnConfirmSignUpSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmSignUpSuccess);
});
}
void OnConfirmSignUpFail(const AZStd::string& error) override
{
Call(FN_OnConfirmSignUpFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmSignUpFail, error);
});
}
void OnForgotPasswordSuccess() override
{
Call(FN_OnForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnForgotPasswordSuccess);
});
}
void OnForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnForgotPasswordFail, error);
});
}
void OnConfirmForgotPasswordSuccess() override
{
Call(FN_OnConfirmForgotPasswordSuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnConfirmForgotPasswordSuccess);
});
}
void OnConfirmForgotPasswordFail(const AZStd::string& error) override
{
Call(FN_OnConfirmForgotPasswordFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnConfirmForgotPasswordFail, error);
});
}
void OnEnableMFASuccess() override
{
Call(FN_OnEnableMFASuccess);
AZ::TickBus::QueueFunction([this]() {
Call(FN_OnEnableMFASuccess);
});
}
void OnEnableMFAFail(const AZStd::string& error) override
{
Call(FN_OnEnableMFAFail, error);
AZ::TickBus::QueueFunction([error, this]() {
Call(FN_OnEnableMFAFail, error);
});
}
};
} // namespace AWSClientAuth
@@ -16,7 +16,7 @@
namespace AWSClientAuth
{
//@ Abstract class for authentication provider requests.
//! Abstract class for authentication provider requests.
class IAuthenticationProviderRequests
{
public:
@@ -35,32 +35,40 @@ namespace AWSClientAuth
virtual bool IsSignedIn(const ProviderNameEnum& providerName) = 0;
//! Get cached tokens from last last successful sign-in for the provider.
//! @param providerName Provider to get authentication tokens.
//! @return AuthenticationTokens tokens from successful authentication.
virtual AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) = 0;
// Below methods have corresponding notifications for success and failures.
//! Call sign in endpoint for provider password grant flow.
//! @param providerName Provider to call sign in.
//! @param username Username to use to for sign in.
//! @param password Password to use to for sign in.
virtual void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call sign in endpoint for provider password grant multi factor authentication flow.
//! @param providerName Provider to call MFA sign in.
//! @param username Username to use for MFA sign in.
//! @param password Password to use for MFA sign in.
virtual void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0;
//! Call confirm endpoint for provider password grant multi factor authentication flow .
//! @param providerName Provider to call MFA confirm sign in.
//! @param username Username to use for MFA confirm.
//! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm.
virtual void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0;
//! Call code-pair endpoint for provider device grant flow.
//! @param providerName Provider to call device sign in.
virtual void DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call tokens endpoint for provider device grant flow.
//! @param providerName Provider to call device confirm sign in.
virtual void DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh endpoint for provider refresh grant flow.
//! @param providerName Provider to call refresh tokens.
virtual void RefreshTokensAsync(const ProviderNameEnum& providerName) = 0;
//! Call refresh token if token not valid. If token valid, fires corresponding event.
@@ -11,20 +11,15 @@
*/
#pragma once
#include <AzCore/Preprocessor/Enum.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/chrono/clocks.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AWSClientAuth
{
enum class ProviderNameEnum
{
None,
AWSCognitoIDP,
LoginWithAmazon,
Google,
Apple,
Facebook
};
AZ_ENUM_CLASS(ProviderNameEnum, None, AWSCognitoIDP, LoginWithAmazon, Twitch, Google, Apple, Facebook);
//! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController.
class AuthenticationTokens
@@ -55,6 +50,8 @@ namespace AWSClientAuth
//! @return Expiration time in seconds.
int GetTokensExpireTimeSeconds() const;
static void Reflect(AZ::ReflectContext* context);
private:
int m_tokensExpireTimeSeconds = 0;
AZStd::string m_accessToken;
@@ -12,7 +12,7 @@
#pragma once
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/string/string.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
@@ -24,6 +24,14 @@ namespace AWSClientAuth
{
public:
AZ_TYPE_INFO(ClientAuthAWSCredentials, "{02FB32C4-B94E-4084-9049-3DF32F87BD76}");
ClientAuthAWSCredentials() = default;
ClientAuthAWSCredentials(const ClientAuthAWSCredentials& other)
: m_accessKeyId(other.m_accessKeyId)
, m_secretKey(other.m_secretKey)
, m_sessionToken(other.m_sessionToken)
{
}
ClientAuthAWSCredentials(const AZStd::string& accessKeyId, const AZStd::string& secretKey, const AZStd::string& sessionToken)
{
@@ -50,6 +58,32 @@ namespace AWSClientAuth
return m_sessionToken;
}
static void Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ClientAuthAWSCredentials>()
->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId)
->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey)
->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<ClientAuthAWSCredentials>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const ClientAuthAWSCredentials&>()
->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId))
->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey))
->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken));
}
}
private:
AZStd::string m_accessKeyId;
AZStd::string m_secretKey;
@@ -22,11 +22,12 @@ namespace AWSClientAuth
public:
AZ_TYPE_INFO(IAWSCognitoUserManagementRequests, "{A4C90F21-7056-4827-8C6B-401E6945697D}");
//! Initialize Cognito User pool.
//! Initialize Cognito User pool using settings from resource mappings.
//! @param settingsRegistryPath settingsRegistryPath Path for the settings registry file to use.
virtual bool Initialize() = 0;
// Requests interface
//! Cognito user pool email sign up start.
//! @param username User name to use for sign up.
//! @param password Password to use for sign up.
@@ -59,7 +60,7 @@ namespace AWSClientAuth
virtual void EnableMFAAsync(const AZStd::string& accessToken) = 0;
};
//! Manages various authentication provider implementations and implements AuthenticationProvider Request bus.
//! Implements AWS Cognito user pool user management requests.
class AWSCognitoUserManagementRequests
: public AZ::EBusTraits
{
@@ -22,6 +22,11 @@
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}");
}
namespace AWSClientAuth
{
constexpr char SerializeComponentName[] = "AWSClientAuth";
@@ -44,20 +49,35 @@ namespace AWSClientAuth
AWSClientAuth::GoogleProviderSetting::Reflect(*serialize);
}
AWSClientAuth::AuthenticationTokens::Reflect(context);
AWSClientAuth::ClientAuthAWSCredentials::Reflect(context);
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AuthenticationProviderRequestBus>("AuthenticationProviderRequestBus")
behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None")
->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP")
->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon")
->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google");
behaviorContext->EBus<AuthenticationProviderScriptCanvasRequestBus>("AuthenticationProviderRequestBus")
->Attribute(AZ::Script::Attributes::Category, SerializeComponentName)
->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens)
->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize)
->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn)
->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens)
->Event(
"PasswordGrantSingleFactorSignInAsync", &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=[
@@ -162,7 +162,7 @@ namespace AZ
AZStd::string expectedHigherPrecedenceFileFullPath;
AzFramework::StringFunc::Path::Join(gameProjectPath, RPI::ShaderVariantTreeAsset::CommonSubFolder, expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */);
AzFramework::StringFunc::Path::Join(expectedHigherPrecedenceFileFullPath.c_str(), shaderProductFileRelativePath.c_str(), expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */);
AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantAsset::Extension);
AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantListSourceData::Extension);
AzFramework::StringFunc::Path::Normalize(expectedHigherPrecedenceFileFullPath);
AZStd::string normalizedShaderVariantListFileFullPath = shaderVariantListFileFullPath;
@@ -21,6 +21,7 @@
#include <RayTracing/RayTracingFeatureProcessor.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AtomCore/std/parallel/concurrency_checker.h>
#include <AzCore/Console/Console.h>
namespace AZ
{
@@ -160,8 +161,14 @@ namespace AZ
// called when reflection probes are modified in the editor so that meshes can re-evaluate their probes
void UpdateMeshReflectionProbes();
private:
void ForceRebuildDrawPackets(const AZ::ConsoleCommandContainer& arguments);
AZ_CONSOLEFUNC(MeshFeatureProcessor,
ForceRebuildDrawPackets,
AZ::ConsoleFunctorFlags::Null,
"(For Testing) Invalidates all mesh draw packets, causing them to rebuild on the next frame."
);
MeshFeatureProcessor(const MeshFeatureProcessor&) = delete;
// RPI::SceneNotificationBus::Handler overrides...
@@ -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;
@@ -387,6 +387,11 @@ namespace AZ
}
}
void MeshFeatureProcessor::ForceRebuildDrawPackets([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
m_forceRebuildDrawPackets = true;
}
void MeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline)
{
m_forceRebuildDrawPackets = true;;
@@ -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.
@@ -17,11 +17,20 @@
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
#include <Atom/RHI/DrawPacketBuilder.h>
#include <AzCore/Console/Console.h>
namespace AZ
{
namespace RPI
{
AZ_CVAR(bool,
r_forceRootShaderVariantUsage,
false,
[](const bool&) { AZ::Interface<AZ::IConsole>::Get()->PerformCommand("MeshFeatureProcessor.ForceRebuildDrawPackets"); },
ConsoleFunctorFlags::Null,
"(For Testing) Forces usage of root shader variant in the mesh draw packet level, ignoring any other shader variants that may exist."
);
MeshDrawPacket::MeshDrawPacket(
ModelLod& modelLod,
size_t modelLodMeshIndex,
@@ -187,7 +196,7 @@ namespace AZ
}
const ShaderVariantId finalVariantId = shaderOptions.GetShaderVariantId();
const ShaderVariant& variant = shader->GetVariant(finalVariantId);
const ShaderVariant& variant = r_forceRootShaderVariantUsage ? shader->GetRootVariant() : shader->GetVariant(finalVariantId);
Data::Instance<ShaderResourceGroup> drawSrg;
if (drawSrgAsset)
@@ -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();
@@ -37,6 +37,8 @@ namespace MaterialEditor
//Connect ok and cancel buttons
QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
setModal(true);
}
void CreateMaterialDialog::InitMaterialTypeSelection()
@@ -58,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()
@@ -86,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
@@ -11,6 +11,7 @@
*/
#include <QApplication>
#include <QClipboard>
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
@@ -61,6 +62,8 @@ namespace MaterialEditor
m_caller = nullptr;
});
AddGenericContextMenuActions(caller, menu, entry);
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry);
@@ -84,6 +87,18 @@ namespace MaterialEditor
}
}
void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetName().c_str());
});
menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetFullPath().c_str());
});
}
void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry)
{
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
@@ -44,6 +44,7 @@ namespace MaterialEditor
//! AssetBrowserInteractionNotificationBus::Handler overrides...
void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries) override;
void AddGenericContextMenuActions(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);
void AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);
void AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry);
@@ -35,6 +35,7 @@ namespace MaterialEditor
SetupPresetList();
SetupSearchWidget();
SetupDialogButtons();
setModal(true);
}
void PresetBrowserDialog::SetupPresetList()
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
@@ -25,6 +25,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QHeaderView>
@@ -215,19 +216,10 @@ namespace AZ
tableWidget->sortItems(MaterialSlotColumn);
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
QWidget* buttonRow = new QWidget(&dialog);
buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
QPushButton* confirmButton = new QPushButton("Confirm", buttonRow);
QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { dialog.accept(); });
QPushButton* cancelButton = new QPushButton("Cancel", buttonRow);
QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [&dialog] { dialog.reject(); });
QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow);
buttonLayout->addStretch();
buttonLayout->addWidget(confirmButton);
buttonLayout->addWidget(cancelButton);
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
// Create a heading label for the top of the dialog
QLabel* labelWidget = new QLabel("\nSelect the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.\n", &dialog);
@@ -236,8 +228,9 @@ namespace AZ
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(labelWidget);
dialogLayout->addWidget(tableWidget);
dialogLayout->addWidget(buttonRow);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.
@@ -37,6 +37,7 @@
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QLabel>
@@ -534,7 +535,7 @@ namespace AZ
inspector->Populate();
inspector->SetOverrides(propertyOverrideMap);
// Create the menu bottom row with actions for exporting or canceling the operation
// Create the menu button
QToolButton* menuButton = new QToolButton(&dialog);
menuButton->setAutoRaise(true);
menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg"));
@@ -546,10 +547,6 @@ namespace AZ
action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); });
action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); });
menu.addSeparator();
action = menu.addAction("Confirm Changes", [&] { dialog.accept(); });
action = menu.addAction("Cancel Changes", [&] { dialog.reject(); });
menu.addSeparator();
action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); });
action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); });
@@ -563,12 +560,19 @@ namespace AZ
menu.exec(QCursor::pos());
});
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); });
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(menuButton);
dialogLayout->addWidget(inspector);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.
@@ -269,6 +269,8 @@ namespace AZ
QAction* action = nullptr;
menu.addAction("Open Material Editor", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); });
action = menu.addAction("Clear", [this]() { Clear(); });
action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty());
@@ -32,8 +32,11 @@
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QApplication>
#include <QDialog>
#include <QPushButton>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QMenu>
#include <QPushButton>
#include <QToolButton>
#include <QVBoxLayout>
AZ_POP_DISABLE_WARNING
@@ -286,42 +289,31 @@ namespace AZ
MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog);
inspector->Populate();
// Create the bottom row of the dialog with action buttons for exporting or canceling the operation
QWidget* buttonRow = new QWidget(&dialog);
buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
// Create the menu button
QToolButton* menuButton = new QToolButton(&dialog);
menuButton->setAutoRaise(true);
menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg"));
menuButton->setVisible(true);
QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() {
QAction* action = nullptr;
QPushButton* revertButton = new QPushButton("Revert", buttonRow);
QObject::connect(revertButton, &QPushButton::clicked, revertButton, [inspector, matModUvOverrides] {
inspector->SetUvNameMap(matModUvOverrides);
});
QMenu menu(&dialog);
action = menu.addAction("Clear", [&] { inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); });
action = menu.addAction("Revert", [&] { inspector->SetUvNameMap(matModUvOverrides);; });
menu.exec(QCursor::pos());
});
QPushButton* clearButton = new QPushButton("Clear", buttonRow);
QObject::connect(clearButton, &QPushButton::clicked, clearButton, [inspector] {
inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap());
});
QPushButton* confirmButton = new QPushButton("Confirm", buttonRow);
QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] {
dialog.accept();
});
QPushButton* cancelButton = new QPushButton("Cancel", buttonRow);
QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [inspector, matModUvOverrides, &dialog] {
inspector->SetUvNameMap(matModUvOverrides);
dialog.reject();
});
QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow);
buttonLayout->addStretch();
buttonLayout->addWidget(revertButton);
buttonLayout->addWidget(clearButton);
buttonLayout->addWidget(confirmButton);
buttonLayout->addWidget(cancelButton);
QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog);
dialogLayout->addWidget(menuButton);
dialogLayout->addWidget(inspector);
dialogLayout->addWidget(buttonRow);
dialogLayout->addWidget(buttonBox);
dialog.setLayout(dialogLayout);
dialog.setModal(true);
// Forcing the initial dialog size to accomodate typical content.
// Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent.
@@ -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);
}
}
@@ -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);

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