Merge remote-tracking branch 'upstream/development' into hultonha_LYN-2348_tube_render_crash
Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
@@ -83,9 +83,9 @@ AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportC
|
||||
}
|
||||
|
||||
bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos)
|
||||
int dx, int dy)
|
||||
{
|
||||
if (previousMousePos == currentMousePos)
|
||||
if (dx == 0 && dy == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
|
||||
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
|
||||
{
|
||||
m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength();
|
||||
m_totalMouseMoveDelta += AZStd::abs(dx) + AZStd::abs(dy);
|
||||
}
|
||||
|
||||
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
|
||||
@@ -115,7 +115,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
Vec3 ydir = m.GetColumn1().GetNormalized();
|
||||
Vec3 pos = m.GetTranslation();
|
||||
|
||||
const float posDelta = 0.2f * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
|
||||
const float posDelta = 0.2f * dy * speedScale;
|
||||
pos = pos - ydir * posDelta;
|
||||
m_orbitDistance = m_orbitDistance + posDelta;
|
||||
m_orbitDistance = fabs(m_orbitDistance);
|
||||
@@ -126,7 +126,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
else if (m_inRotateMode)
|
||||
{
|
||||
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
|
||||
Ang3 angles(dy, 0, dx);
|
||||
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
|
||||
if (gSettings.invertYRotation)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
|
||||
Vec3 pos = m.GetTranslation();
|
||||
pos += 0.1f * xdir * (currentMousePos.m_x - previousMousePos.m_x) * speedScale + 0.1f * zdir * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
|
||||
pos += 0.1f * xdir * dx * speedScale + 0.1f * zdir * dy * speedScale;
|
||||
m.SetTranslation(pos);
|
||||
|
||||
AZ::Transform transform = viewportContext->GetCameraTransform();
|
||||
@@ -168,7 +168,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
else if (m_inOrbitMode)
|
||||
{
|
||||
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
|
||||
Ang3 angles(dy, 0, dx);
|
||||
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
|
||||
|
||||
if (gSettings.invertPan)
|
||||
@@ -302,20 +302,19 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
|
||||
bool shouldCaptureCursor = m_capturingCursor;
|
||||
bool shouldConsumeEvent = false;
|
||||
|
||||
if (id == AzFramework::InputDeviceMouse::SystemCursorPosition)
|
||||
if (id == AzFramework::InputDeviceMouse::Movement::X || id == AzFramework::InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
bool result = false;
|
||||
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
|
||||
GetViewportId(),
|
||||
[this, &result](AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequests* mouseRequests)
|
||||
{
|
||||
if (auto previousMousePosition = mouseRequests->PreviousViewportCursorScreenPosition();
|
||||
previousMousePosition.has_value())
|
||||
{
|
||||
result = HandleMouseMove(mouseRequests->ViewportCursorScreenPosition(), previousMousePosition.value());
|
||||
}
|
||||
});
|
||||
return result;
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
if (id == AzFramework::InputDeviceMouse::Movement::X)
|
||||
{
|
||||
dx = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
dy = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
|
||||
}
|
||||
return HandleMouseMove(dx, dy);
|
||||
}
|
||||
else if (id == MouseButton::Left)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace SandboxEditor
|
||||
|
||||
AZ::RPI::ViewportContextPtr GetViewportContext();
|
||||
|
||||
bool HandleMouseMove(const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos);
|
||||
bool HandleMouseMove(int dx, int dy);
|
||||
bool HandleMouseWheel(float zDelta);
|
||||
bool IsKeyDown(Qt::Key key) const;
|
||||
void UpdateCursorCapture(bool shouldCaptureCursor);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationSettings.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <Tests/Serialization/Json/JsonSerializationTests.h>
|
||||
|
||||
@@ -43,7 +44,9 @@ namespace JsonSerializationTests
|
||||
}
|
||||
|
||||
void CheckApplyPatchOutcome(const char* target, const char* patch,
|
||||
AZ::JsonSerializationResult::Outcomes outcome, AZ::JsonSerializationResult::Processing processing)
|
||||
AZ::JsonSerializationResult::Outcomes outcome,
|
||||
AZ::JsonSerializationResult::Processing processing,
|
||||
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
|
||||
{
|
||||
m_jsonDocument->Parse(target);
|
||||
ASSERT_FALSE(m_jsonDocument->HasParseError());
|
||||
@@ -53,12 +56,24 @@ namespace JsonSerializationTests
|
||||
ASSERT_FALSE(patchDocument.HasParseError());
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(*m_jsonDocument,
|
||||
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch);
|
||||
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch, settings);
|
||||
EXPECT_EQ(result.GetTask(), AZ::JsonSerializationResult::Tasks::Merge);
|
||||
EXPECT_EQ(result.GetOutcome(), outcome);
|
||||
EXPECT_EQ(result.GetProcessing(), processing);
|
||||
}
|
||||
|
||||
void CheckApplyPatchOutcome(
|
||||
const char* target,
|
||||
const char* patch,
|
||||
const char* expectedPatchedResult,
|
||||
AZ::JsonSerializationResult::Outcomes outcome,
|
||||
AZ::JsonSerializationResult::Processing processing,
|
||||
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
|
||||
{
|
||||
CheckApplyPatchOutcome(target, patch, outcome, processing, settings);
|
||||
Expect_DocStrEq(expectedPatchedResult);
|
||||
}
|
||||
|
||||
void CheckCreatePatch_Core(const char* source, AZStd::string_view patch, const char* target,
|
||||
AZ::JsonMergeApproach approach)
|
||||
{
|
||||
@@ -262,6 +277,36 @@ namespace JsonSerializationTests
|
||||
Outcomes::TypeMismatch, Processing::Halted);
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchWithCustomReportingCallback_ReportPartialSkip)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
if (result.GetProcessing() == Processing::Halted)
|
||||
{
|
||||
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
AZ::JsonApplyPatchSettings applyPatchSettings;
|
||||
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
CheckApplyPatchOutcome(
|
||||
R"({})",
|
||||
R"([
|
||||
{ "op": "add", "path": "/nonexistent_key/new_member", "value": "someValue" },
|
||||
{ "op": "add", "path": "/test", "value": "someValue" }
|
||||
])",
|
||||
R"(
|
||||
{ "test": "someValue" }
|
||||
)",
|
||||
Outcomes::PartialSkip,
|
||||
Processing::Completed,
|
||||
AZStd::move(applyPatchSettings));
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchAddUnnamedMember_ReportsSuccess)
|
||||
{
|
||||
CheckApplyPatch(
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace AzFramework
|
||||
|
||||
//! This is called when the window is deactivated from code or if the user closes the window.
|
||||
virtual void OnWindowClosed() {};
|
||||
|
||||
//! This is called when vsync interval is changed.
|
||||
virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); };
|
||||
};
|
||||
using WindowNotificationBus = AZ::EBus<WindowNotifications>;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AzNetworking
|
||||
|
||||
void TcpSocketManager::ProcessEvents(AZ::TimeMs maxBlockMs, const SocketEventCallback& readCallback, const SocketEventCallback& writeCallback)
|
||||
{
|
||||
if(static_cast<int32_t>(m_maxFd) <= 0 && m_socketFds.empty())
|
||||
if(static_cast<int32_t>(m_maxFd) <= 0 || m_socketFds.empty())
|
||||
{
|
||||
// There are no available sockets to process
|
||||
return;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <AzFramework/Input/Buses/Notifications/InputChannelNotificationBus.h>
|
||||
#include <AzFramework/Input/Buses/Requests/InputChannelRequestBus.h>
|
||||
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCursor>
|
||||
@@ -187,12 +188,6 @@ namespace AzToolsFramework
|
||||
|
||||
bool QtEventToAzInputMapper::HandlesInputEvent(const AzFramework::InputChannel& channel) const
|
||||
{
|
||||
const AzFramework::InputChannelId& channelId = channel.GetInputChannelId();
|
||||
if (channelId == AzFramework::InputDeviceMouse::Movement::X || channelId == AzFramework::InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We map keyboard and mouse events from Qt, so flag all events coming from those devices
|
||||
// as handled by our synthetic event system.
|
||||
const AzFramework::InputDeviceId& deviceId = channel.GetInputDevice().GetInputDeviceId();
|
||||
@@ -210,6 +205,22 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::SetCursorCaptureEnabled(bool enabled)
|
||||
{
|
||||
if (m_capturingCursor != enabled)
|
||||
{
|
||||
m_capturingCursor = enabled;
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
qApp->setOverrideCursor(Qt::BlankCursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
qApp->restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QtEventToAzInputMapper::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
// Abort if processing isn't enabled.
|
||||
@@ -284,13 +295,25 @@ namespace AzToolsFramework
|
||||
{
|
||||
auto systemCursorChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::SystemCursorPosition);
|
||||
auto movementXChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::X);
|
||||
auto movementYChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Y);
|
||||
auto mouseWheelChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Z);
|
||||
|
||||
systemCursorChannel->ProcessRawInputEvent(m_cursorPosition->m_normalizedPositionDelta.GetLength());
|
||||
// Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation
|
||||
// of cursor movement velocity.
|
||||
movementXChannel->ProcessRawInputEvent(
|
||||
m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast<float>(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF());
|
||||
movementYChannel->ProcessRawInputEvent(
|
||||
m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast<float>(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF());
|
||||
mouseWheelChannel->ProcessRawInputEvent(0.f);
|
||||
|
||||
NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(movementXChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(movementYChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(mouseWheelChannel, nullptr);
|
||||
}
|
||||
|
||||
@@ -318,16 +341,42 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Vector2 QtEventToAzInputMapper::WidgetPositionToNormalizedPosition(QPoint position)
|
||||
{
|
||||
const float normalizedX = aznumeric_cast<float>(position.x()) / aznumeric_cast<float>(m_sourceWidget->width());
|
||||
const float normalizedY = aznumeric_cast<float>(position.y()) / aznumeric_cast<float>(m_sourceWidget->height());
|
||||
return AZ::Vector2{normalizedX, normalizedY};
|
||||
}
|
||||
|
||||
QPoint QtEventToAzInputMapper::NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition)
|
||||
{
|
||||
const int denormalizedX = aznumeric_cast<int>(normalizedPosition.GetX() * m_sourceWidget->width());
|
||||
const int denormalizedY = aznumeric_cast<int>(normalizedPosition.GetY() * m_sourceWidget->height());
|
||||
return QPoint{denormalizedX, denormalizedY};
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
AZ::Vector2 lastCursorPosition = m_cursorPosition->m_normalizedPosition;
|
||||
|
||||
const QPoint mousePos = mouseEvent->pos();
|
||||
const float normalizedX = aznumeric_cast<float>(mousePos.x()) / aznumeric_cast<float>(m_sourceWidget->width());
|
||||
const float normalizedY = aznumeric_cast<float>(mousePos.y()) / aznumeric_cast<float>(m_sourceWidget->height());
|
||||
const AZ::Vector2 normalizedPosition(normalizedX, normalizedY);
|
||||
const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos);
|
||||
m_cursorPosition->m_normalizedPositionDelta = normalizedPosition - m_cursorPosition->m_normalizedPosition;
|
||||
m_cursorPosition->m_normalizedPosition = normalizedPosition;
|
||||
ProcessPendingMouseEvents();
|
||||
m_mouseChannelsNeedUpdate = true;
|
||||
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
// Reset our cursor position to the previous point.
|
||||
QPoint targetScreenPosition = m_sourceWidget->mapToGlobal(NormalizedPositionToWidgetPosition(lastCursorPosition));
|
||||
AzQtComponents::SetCursorPos(targetScreenPosition);
|
||||
|
||||
// Even though we just set the cursor position, there are edge cases such as remote desktop that will leave
|
||||
// the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation.
|
||||
QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos());
|
||||
m_cursorPosition->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleKeyEvent(QKeyEvent* keyEvent)
|
||||
|
||||
@@ -47,6 +47,12 @@ namespace AzToolsFramework
|
||||
//! Sets whether or not this input mapper should be updating its input channels from Qt events.
|
||||
void SetEnabled(bool enabled);
|
||||
|
||||
//! Sets whether or not the cursor should be constrained to the source widget and invisible.
|
||||
//! Internally, this will reset the cursor position after each move event to ensure movement
|
||||
//! events don't allow the cursor to escape. This can be used for typical camera controls
|
||||
//! like a dolly or rotation, where mouse movement is important but cursor location is not.
|
||||
void SetCursorCaptureEnabled(bool enabled);
|
||||
|
||||
// QObject overrides...
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
@@ -106,6 +112,11 @@ namespace AzToolsFramework
|
||||
// Processes any pending mouse movement events, this allows mouse movement channels to close themselves.
|
||||
void ProcessPendingMouseEvents();
|
||||
|
||||
// Converts a point in logical source widget space [0..m_sourceWidget->size()] to normalized [0..1] space.
|
||||
AZ::Vector2 WidgetPositionToNormalizedPosition(QPoint position);
|
||||
// Converts a point in normalized [0..1] space to logical source widget space [0..m_sourceWidget->size()].
|
||||
QPoint NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition);
|
||||
|
||||
// Handle mouse click events.
|
||||
void HandleMouseButtonEvent(QMouseEvent* mouseEvent);
|
||||
// Handle mouse move events.
|
||||
@@ -144,6 +155,8 @@ namespace AzToolsFramework
|
||||
bool m_mouseChannelsNeedUpdate = false;
|
||||
// Flags whether or not Qt events should currently be processed.
|
||||
bool m_enabled = true;
|
||||
// Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement).
|
||||
bool m_capturingCursor = false;
|
||||
|
||||
// Our viewport-specific AZ devices. We control their internal input channel states.
|
||||
AZStd::unique_ptr<EditorQtMouseDevice> m_mouseDevice;
|
||||
|
||||
+11
-8
@@ -172,20 +172,23 @@ namespace AzToolsFramework
|
||||
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
|
||||
|
||||
//apply patch to template
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
|
||||
templateDomReference.GetAllocator(), providedPatch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), providedPatch);
|
||||
|
||||
//trigger propagation
|
||||
if (result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success)
|
||||
if (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Success)
|
||||
{
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
|
||||
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
|
||||
return true;
|
||||
AZ_Error("Prefab", false, "Patch was not successfully applied.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Prefab", false, "Patch was not successfully applied");
|
||||
return false;
|
||||
AZ_Error(
|
||||
"Prefab", result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip,
|
||||
"Some of the patches are not successfully applied.");
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
|
||||
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,12 +176,17 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::JsonSerializationResult::ResultCode applyPatchResult = AZ::JsonSerialization::ApplyPatch(
|
||||
sourceTemplateDomCopy,
|
||||
targetTemplatePrefabDom.GetAllocator(),
|
||||
patchesReference->get(),
|
||||
AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode applyPatchResult =
|
||||
PrefabDomUtils::ApplyPatches(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator(), patchesReference->get());
|
||||
linkedInstanceDom.CopyFrom(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator());
|
||||
|
||||
PrefabDomValueReference sourceTemplateName =
|
||||
PrefabDomUtils::FindPrefabDomValue(sourceTemplateDomCopy, PrefabDomUtils::SourceName);
|
||||
AZ_Assert(sourceTemplateName && sourceTemplateName->get().IsString(), "A valid source template name couldn't be found");
|
||||
PrefabDomValueReference targetTemplateName =
|
||||
PrefabDomUtils::FindPrefabDomValue(targetTemplatePrefabDom, PrefabDomUtils::SourceName);
|
||||
AZ_Assert(targetTemplateName && targetTemplateName->get().IsString(), "A valid target template name couldn't be found");
|
||||
|
||||
if (applyPatchResult.GetProcessing() != AZ::JsonSerializationResult::Processing::Completed)
|
||||
{
|
||||
AZ_Error(
|
||||
@@ -190,6 +195,14 @@ namespace AzToolsFramework
|
||||
m_sourceTemplateId, m_targetTemplateId);
|
||||
return false;
|
||||
}
|
||||
if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"Link::UpdateTarget - Some of the patches couldn't be applied on the source template '%s' present under the "
|
||||
"target Template '%s'.",
|
||||
sourceTemplateName->get().GetString(), targetTemplateName->get().GetString());
|
||||
}
|
||||
}
|
||||
|
||||
// This is a guardrail to ensure the linked instance dom always has the LinkId value
|
||||
|
||||
@@ -236,6 +236,26 @@ namespace AzToolsFramework
|
||||
return findInstancesResult->get();
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode ApplyPatches(
|
||||
PrefabDomValue& prefabDomToApplyPatchesOn, PrefabDom::AllocatorType& allocator, const PrefabDomValue& patches)
|
||||
{
|
||||
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
if (result.GetProcessing() == Processing::Halted)
|
||||
{
|
||||
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
AZ::JsonApplyPatchSettings applyPatchSettings;
|
||||
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
return AZ::JsonSerialization::ApplyPatch(
|
||||
prefabDomToApplyPatchesOn, allocator, patches, AZ::JsonMergeApproach::JsonPatch, applyPatchSettings);
|
||||
}
|
||||
|
||||
void PrintPrefabDomValue(
|
||||
[[maybe_unused]] const AZStd::string_view printMessage,
|
||||
[[maybe_unused]] const PrefabDomValue& prefabDomValue)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
@@ -122,6 +123,11 @@ namespace AzToolsFramework
|
||||
*/
|
||||
PrefabDomValueConstReference GetInstancesValue(const PrefabDomValue& prefabDom);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode ApplyPatches(
|
||||
PrefabDomValue& prefabDomToApplyPatchesOn,
|
||||
PrefabDom::AllocatorType& allocator,
|
||||
const PrefabDomValue& patches);
|
||||
|
||||
/**
|
||||
* Prints the contents of the given prefab DOM value to the debug output console in a readable format.
|
||||
* @param printMessage The message that will be printed before printing the PrefabDomValue
|
||||
|
||||
@@ -261,8 +261,13 @@ namespace AzToolsFramework
|
||||
instanceDom.CopyFrom(instanceDomRef->get(), instanceDom.GetAllocator());
|
||||
|
||||
//apply the patch to the template within the target
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(instanceDom,
|
||||
instanceDom.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(instanceDom, instanceDom.GetAllocator(), patch);
|
||||
|
||||
AZ_Error(
|
||||
"Prefab",
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip ||
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
|
||||
"Some of the patches are not successfully applied.");
|
||||
|
||||
//remove the link id placed into the instance
|
||||
auto linkIdIter = instanceDom.FindMember(PrefabDomUtils::LinkIdName);
|
||||
|
||||
@@ -276,11 +276,6 @@ namespace AzToolsFramework
|
||||
virtual void EndCursorCapture() = 0;
|
||||
//! Gets the most recent recorded cursor position in the viewport in screen space coordinates.
|
||||
virtual AzFramework::ScreenPoint ViewportCursorScreenPosition() = 0;
|
||||
//! Gets the cursor position recorded prior to the most recent cursor position.
|
||||
//! Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
|
||||
//! from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
|
||||
//! position delta.
|
||||
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
|
||||
//! Is mouse over viewport.
|
||||
virtual bool IsMouseOver() const = 0;
|
||||
|
||||
|
||||
@@ -96,8 +96,8 @@ namespace UnitTest
|
||||
|
||||
//apply the patch
|
||||
PrefabDom& templateDomReference = m_prefabSystemComponent->FindTemplateDom(nestedTemplateId);
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
|
||||
templateDomReference.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), patch);
|
||||
|
||||
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
|
||||
"Patch was not successfully applied");
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace AWSNativeSDKInit
|
||||
#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK)
|
||||
void CustomizeSDKOptions(Aws::SDKOptions& options);
|
||||
void CustomizeShutdown();
|
||||
|
||||
void CopyCaCertBundle();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -44,6 +46,8 @@ namespace AWSNativeSDKInit
|
||||
void InitializationManager::InitAwsApi()
|
||||
{
|
||||
s_initManager = AZ::Environment::CreateVariable<InitializationManager>(initializationManagerTag);
|
||||
|
||||
Platform::CopyCaCertBundle();
|
||||
}
|
||||
|
||||
void InitializationManager::Shutdown()
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
|
||||
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
|
||||
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
|
||||
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
|
||||
// this warning.
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
||||
#include <aws/core/utils/memory/stl/AWSString.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AWSNativeSDKInit
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
void CopyCaCertBundle()
|
||||
{
|
||||
AZStd::vector<char> contents;
|
||||
AZStd::string certificatePath = "@assets@/certificates/aws/cacert.pem";
|
||||
AZStd::string publicStoragePath = AZ::Android::Utils::GetAppPublicStoragePath();
|
||||
publicStoragePath.append("/certificates/aws/cacert.pem");
|
||||
|
||||
AZ::IO::FileIOBase* fileBase = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
if (!fileBase->Exists(certificatePath.c_str()))
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Certificate File(%s) does not exist.\n", certificatePath.c_str());
|
||||
}
|
||||
|
||||
AZ::IO::HandleType fileHandle;
|
||||
AZ::IO::Result fileResult = fileBase->Open(certificatePath.c_str(), AZ::IO::OpenMode::ModeRead, fileHandle);
|
||||
|
||||
if (!fileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to open certificate file with result %i\n", fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ::u64 fileSize = 0;
|
||||
fileBase->Size(fileHandle, fileSize);
|
||||
|
||||
if (fileSize == 0)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Given empty file(%s) as the certificate bundle.\n", certificatePath.c_str());
|
||||
}
|
||||
|
||||
contents.resize(fileSize + 1);
|
||||
fileResult = fileBase->Read(fileHandle, contents.data(), fileSize);
|
||||
|
||||
if (!fileResult)
|
||||
{
|
||||
AZ_Error(
|
||||
"AWSNativeSDKInit", false, "Failed to read from the certificate bundle(%s) with result code(%i).\n", certificatePath.c_str(),
|
||||
fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ_Printf("AWSNativeSDKInit", "Certificate bundle is read successfully from %s", certificatePath.c_str());
|
||||
|
||||
AZ::IO::HandleType outFileHandle;
|
||||
|
||||
AZ::IO::Result outFileResult = fileBase->Open(publicStoragePath.c_str(), AZ::IO::OpenMode::ModeWrite, outFileHandle);
|
||||
|
||||
if (!outFileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to open the certificate bundle with result %i\n", fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ::IO::Result writeFileResult = fileBase->Write(outFileHandle, contents.data(), fileSize);
|
||||
if (!writeFileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to write the certificate bundle with result %i\n", writeFileResult.GetResultCode());
|
||||
}
|
||||
|
||||
fileBase->Close(fileHandle);
|
||||
fileBase->Close(outFileHandle);
|
||||
|
||||
AZ_Printf("AWSNativeSDKInit", "Certificate bundle successfully copied to %s", publicStoragePath.c_str());
|
||||
}
|
||||
} // namespace Platform
|
||||
}
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
InitializeCerts_Android.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
namespace AWSNativeSDKInit
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
void CopyCaCertBundle()
|
||||
{
|
||||
}
|
||||
} // namespace Platform
|
||||
} // namespace AWSCore
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
../Common/Default/InitializeCerts_Null.cpp
|
||||
)
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
../Common/Default/InitializeCerts_Null.cpp
|
||||
)
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
../Common/Default/InitializeCerts_Null.cpp
|
||||
)
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
../Common/Default/InitializeCerts_Null.cpp
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <Authorization/AWSCognitoAuthorizationController.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <ResourceMapping/AWSResourceMappingBus.h>
|
||||
#include <Framework/AWSApiJobConfig.h>
|
||||
|
||||
#include <aws/cognito-identity/CognitoIdentityClient.h>
|
||||
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
|
||||
@@ -163,7 +164,11 @@ namespace AWSClientAuth
|
||||
|
||||
void AWSClientAuthSystemComponent::OnSDKInitialized()
|
||||
{
|
||||
Aws::Client::ClientConfiguration clientConfiguration;
|
||||
AWSCore::AwsApiJobConfig* defaultConfig;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(defaultConfig, &AWSCore::AWSCoreRequests::GetDefaultConfig);
|
||||
Aws::Client::ClientConfiguration clientConfiguration =
|
||||
defaultConfig ? defaultConfig->GetClientConfiguration() : Aws::Client::ClientConfiguration();
|
||||
|
||||
AZStd::string region;
|
||||
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(region, &AWSCore::AWSResourceMappingRequests::GetDefaultRegion);
|
||||
|
||||
|
||||
@@ -113,6 +113,27 @@ namespace AWSClientAuthUnitTest
|
||||
MOCK_METHOD1(ReloadConfigFile, void(bool isReloadingConfigFileName));
|
||||
};
|
||||
|
||||
class AWSCoreRequestBusMock
|
||||
: public AWSCore::AWSCoreRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AWSCoreRequestBusMock()
|
||||
{
|
||||
AWSCore::AWSCoreRequestBus::Handler::BusConnect();
|
||||
|
||||
ON_CALL(*this, GetDefaultJobContext).WillByDefault(testing::Return(nullptr));
|
||||
ON_CALL(*this, GetDefaultConfig).WillByDefault(testing::Return(nullptr));
|
||||
}
|
||||
|
||||
~AWSCoreRequestBusMock()
|
||||
{
|
||||
AWSCore::AWSCoreRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
MOCK_METHOD0(GetDefaultJobContext, AZ::JobContext*());
|
||||
MOCK_METHOD0(GetDefaultConfig, AWSCore::AwsApiJobConfig*());
|
||||
};
|
||||
|
||||
class HttpRequestorRequestBusMock
|
||||
: public HttpRequestor::HttpRequestorRequestBus::Handler
|
||||
{
|
||||
|
||||
@@ -161,6 +161,7 @@ public:
|
||||
testing::NiceMock<AWSClientAuthUnitTest::AWSClientAuthSystemComponentMock> *m_awsClientAuthSystemsComponent;
|
||||
testing::NiceMock<AWSClientAuthUnitTest::AWSCoreSystemComponentMock> *m_awsCoreSystemsComponent;
|
||||
testing::NiceMock<AWSClientAuthUnitTest::AWSResourceMappingRequestBusMock> m_awsResourceMappingRequestBusMock;
|
||||
testing::NiceMock<AWSClientAuthUnitTest::AWSCoreRequestBusMock> m_awsCoreRequestBusMock;
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
};
|
||||
|
||||
@@ -176,6 +177,7 @@ TEST_F(AWSClientAuthSystemComponentTest, ActivateDeactivate_Success)
|
||||
EXPECT_CALL(*m_awsCoreSystemsComponent, Init()).Times(1).InSequence(s1);
|
||||
EXPECT_CALL(*m_awsClientAuthSystemsComponent, Init()).Times(1).InSequence(s1);
|
||||
EXPECT_CALL(*m_awsCoreSystemsComponent, Activate()).Times(1).InSequence(s1);
|
||||
EXPECT_CALL(m_awsCoreRequestBusMock, GetDefaultConfig()).Times(1).InSequence(s1);
|
||||
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultRegion()).Times(1).InSequence(s1);
|
||||
EXPECT_CALL(*m_awsClientAuthSystemsComponent, Activate()).Times(1).InSequence(s1);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,12 +6,14 @@
|
||||
#
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_editor_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Private/Editor/Platform/${PAL_PLATFORM_NAME})
|
||||
ly_get_list_relative_pal_filename(pal_cafile_include_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Framework/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
ly_add_target(
|
||||
NAME AWSCore.Static STATIC
|
||||
NAMESPACE Gem
|
||||
FILES_CMAKE
|
||||
awscore_files.cmake
|
||||
${pal_cafile_include_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
Include/Public
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
Aws::String GetCaCertBundlePath();
|
||||
}
|
||||
|
||||
const char* AwsApiJob::COMPONENT_DISPLAY_NAME = "AWSCoreFramework";
|
||||
|
||||
@@ -29,6 +33,14 @@ namespace AWSCore
|
||||
config.userAgent = "/O3DE_AwsApiJob";
|
||||
config.requestTimeoutMs = 30000;
|
||||
config.connectTimeoutMs = 30000;
|
||||
|
||||
// Instructs the HTTP client where to find the SSL certificate trust store.
|
||||
// It is required to copy the cacert.pem to the expected file path for running the Android client.
|
||||
Aws::String caFilePath = Platform::GetCaCertBundlePath();
|
||||
if (!caFilePath.empty())
|
||||
{
|
||||
config.caFile = caFilePath;
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
|
||||
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
|
||||
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
|
||||
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
|
||||
// this warning.
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
||||
#include <aws/core/utils/memory/stl/AWSString.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
Aws::String GetCaCertBundlePath()
|
||||
{
|
||||
AZStd::string publicStoragePath = AZ::Android::Utils::GetAppPublicStoragePath();
|
||||
publicStoragePath.append("/certificates/aws/cacert.pem");
|
||||
|
||||
return publicStoragePath.c_str();
|
||||
}
|
||||
} // namespace Platform
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
GetCertsPath_Android.cpp
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
|
||||
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
|
||||
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
|
||||
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
|
||||
// this warning.
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
||||
#include <aws/core/utils/memory/stl/AWSString.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
Aws::String GetCaCertBundlePath()
|
||||
{
|
||||
return ""; // no-op
|
||||
}
|
||||
} // namespace Platform
|
||||
} // namespace GridMate
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/GetCertsPath_Null.cpp
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/GetCertsPath_Null.cpp
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/GetCertsPath_Null.cpp
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/GetCertsPath_Null.cpp
|
||||
)
|
||||
@@ -123,6 +123,11 @@ namespace AZ
|
||||
/// Returns the index of the current image after the swap.
|
||||
virtual uint32_t PresentInternal() = 0;
|
||||
|
||||
virtual void SetVerticalSyncIntervalInternal(uint32_t previousVerticalSyncInterval)
|
||||
{
|
||||
AZ_UNUSED(previousVerticalSyncInterval);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SwapChainDescriptor m_descriptor;
|
||||
|
||||
@@ -168,7 +168,11 @@ namespace AZ
|
||||
|
||||
void SwapChain::SetVerticalSyncInterval(uint32_t verticalSyncInterval)
|
||||
{
|
||||
uint32_t previousVsyncInterval = m_descriptor.m_verticalSyncInterval;
|
||||
|
||||
m_descriptor.m_verticalSyncInterval = verticalSyncInterval;
|
||||
|
||||
SetVerticalSyncIntervalInternal(previousVsyncInterval);
|
||||
}
|
||||
|
||||
const AttachmentId& SwapChain::GetAttachmentId() const
|
||||
|
||||
@@ -56,6 +56,18 @@ namespace AZ
|
||||
m_swapChainBarrier.m_isValid = true;
|
||||
}
|
||||
|
||||
void SwapChain::SetVerticalSyncIntervalInternal(uint32_t previousVsyncInterval)
|
||||
{
|
||||
uint32_t verticalSyncInterval = GetDescriptor().m_verticalSyncInterval;
|
||||
if (verticalSyncInterval == 0 || previousVsyncInterval == 0)
|
||||
{
|
||||
// The presentation mode may change when transitioning to or from a vsynced presentation mode
|
||||
// In this case, the swapchain must be recreated.
|
||||
InvalidateNativeSwapChain();
|
||||
BuildNativeSwapChain(GetDescriptor().m_dimensions, verticalSyncInterval);
|
||||
}
|
||||
}
|
||||
|
||||
void SwapChain::SetNameInternal(const AZStd::string_view& name)
|
||||
{
|
||||
if (IsInitialized() && !name.empty())
|
||||
@@ -84,7 +96,7 @@ namespace AZ
|
||||
|
||||
auto& presentationQueue = device.GetCommandQueueContext().GetOrCreatePresentationCommandQueue(*this);
|
||||
m_presentationQueue = &presentationQueue;
|
||||
result = BuildNativeSwapChain(swapchainDimensions);
|
||||
result = BuildNativeSwapChain(swapchainDimensions, descriptor.m_verticalSyncInterval);
|
||||
RETURN_RESULT_IF_UNSUCCESSFUL(result);
|
||||
uint32_t imageCount = 0;
|
||||
VkResult vkResult = vkGetSwapchainImagesKHR(device.GetNativeDevice(), m_nativeSwapChain, &imageCount, nullptr);
|
||||
@@ -166,7 +178,7 @@ namespace AZ
|
||||
|
||||
auto& presentationQueue = device.GetCommandQueueContext().GetOrCreatePresentationCommandQueue(*this);
|
||||
m_presentationQueue = &presentationQueue;
|
||||
BuildNativeSwapChain(resizeDimensions);
|
||||
BuildNativeSwapChain(resizeDimensions, GetDescriptor().m_verticalSyncInterval);
|
||||
|
||||
resizeDimensions.m_imageCount = 0;
|
||||
VkResult vkResult = vkGetSwapchainImagesKHR(device.GetNativeDevice(), m_nativeSwapChain, &resizeDimensions.m_imageCount, nullptr);
|
||||
@@ -256,7 +268,8 @@ namespace AZ
|
||||
info.pImageIndices = &imageIndex;
|
||||
info.pResults = nullptr;
|
||||
|
||||
const VkResult result = vkQueuePresentKHR(vulkanQueue->GetNativeQueue(), &info);
|
||||
VkResult result = vkQueuePresentKHR(vulkanQueue->GetNativeQueue(), &info);
|
||||
|
||||
// Resizing window cause recreation of SwapChain after calling this method,
|
||||
// so VK_SUBOPTIMAL_KHR or VK_ERROR_OUT_OF_DATE_KHR should not happen at this point.
|
||||
AZ_Assert(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR, "Failed to present swapchain %s", GetName().GetCStr());
|
||||
@@ -321,9 +334,17 @@ namespace AZ
|
||||
return surfaceFormats[0];
|
||||
}
|
||||
|
||||
VkPresentModeKHR SwapChain::GetSupportedPresentMode() const
|
||||
VkPresentModeKHR SwapChain::GetSupportedPresentMode(uint32_t verticalSyncInterval) const
|
||||
{
|
||||
AZ_Assert(m_surface, "Surface has not been initialized.");
|
||||
|
||||
if (verticalSyncInterval > 0)
|
||||
{
|
||||
// When a non-zero vsync interval is requested, the FIFO presentation mode (always available)
|
||||
// is usable without needing to query available presentation modes.
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
auto& device = static_cast<Device&>(GetDevice());
|
||||
const auto& physicalDevice = static_cast<const PhysicalDevice&>(device.GetPhysicalDevice());
|
||||
|
||||
@@ -335,12 +356,12 @@ namespace AZ
|
||||
AZStd::vector<VkPresentModeKHR> supportedModes(modeCount);
|
||||
AssertSuccess(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice.GetNativePhysicalDevice(), m_surface->GetNativeSurface(), &modeCount, supportedModes.data()));
|
||||
|
||||
VkPresentModeKHR preferedModes[] = {VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR};
|
||||
for (VkPresentModeKHR preferedMode : preferedModes)
|
||||
VkPresentModeKHR preferredModes[] = {VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR};
|
||||
for (VkPresentModeKHR preferredMode : preferredModes)
|
||||
{
|
||||
for (VkPresentModeKHR supportedMode : supportedModes)
|
||||
{
|
||||
if (supportedMode == preferedMode)
|
||||
if (supportedMode == preferredMode)
|
||||
{
|
||||
return supportedMode;
|
||||
}
|
||||
@@ -370,7 +391,7 @@ namespace AZ
|
||||
return VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
}
|
||||
|
||||
RHI::ResultCode SwapChain::BuildNativeSwapChain(const RHI::SwapChainDimensions& dimensions)
|
||||
RHI::ResultCode SwapChain::BuildNativeSwapChain(const RHI::SwapChainDimensions& dimensions, uint32_t verticalSyncInterval)
|
||||
{
|
||||
AZ_Assert(m_nativeSwapChain == VK_NULL_HANDLE, "Vulkan's native SwapChain has been initialized already.");
|
||||
auto& device = static_cast<Device&>(GetDevice());
|
||||
@@ -421,7 +442,7 @@ namespace AZ
|
||||
createInfo.pQueueFamilyIndices = familyIndices.empty() ? nullptr : familyIndices.data();
|
||||
createInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
createInfo.compositeAlpha = GetSupportedCompositeAlpha();
|
||||
createInfo.presentMode = GetSupportedPresentMode();
|
||||
createInfo.presentMode = GetSupportedPresentMode(verticalSyncInterval);
|
||||
createInfo.clipped = VK_FALSE;
|
||||
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||
|
||||
@@ -442,6 +463,7 @@ namespace AZ
|
||||
imageAvailableSemaphore->GetNativeSemaphore(),
|
||||
VK_NULL_HANDLE,
|
||||
acquiredImageIndex);
|
||||
|
||||
// Resizing window cause recreation of SwapChain before calling this method,
|
||||
// so VK_SUBOPTIMAL_KHR or VK_ERROR_OUT_OF_DATE_KHR should not happen.
|
||||
AssertSuccess(vkResult);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace AZ
|
||||
const CommandQueue& GetPresentationQueue() const;
|
||||
|
||||
void QueueBarrier(const VkPipelineStageFlags src, const VkPipelineStageFlags dst, const VkImageMemoryBarrier& imageBarrier);
|
||||
|
||||
|
||||
private:
|
||||
SwapChain() = default;
|
||||
|
||||
@@ -65,14 +65,15 @@ namespace AZ
|
||||
RHI::ResultCode InitImageInternal(const RHI::SwapChain::InitImageRequest& request) override;
|
||||
RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override;
|
||||
uint32_t PresentInternal() override;
|
||||
void SetVerticalSyncIntervalInternal(uint32_t previousVsyncInterval) override;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
RHI::ResultCode BuildSurface(const RHI::SwapChainDescriptor& descriptor);
|
||||
bool ValidateSurfaceDimensions(const RHI::SwapChainDimensions& dimensions);
|
||||
VkSurfaceFormatKHR GetSupportedSurfaceFormat(const RHI::Format format) const;
|
||||
VkPresentModeKHR GetSupportedPresentMode() const;
|
||||
VkPresentModeKHR GetSupportedPresentMode(uint32_t verticalSyncInterval) const;
|
||||
VkCompositeAlphaFlagBitsKHR GetSupportedCompositeAlpha() const;
|
||||
RHI::ResultCode BuildNativeSwapChain(const RHI::SwapChainDimensions& dimensions);
|
||||
RHI::ResultCode BuildNativeSwapChain(const RHI::SwapChainDimensions& dimensions, uint32_t verticalSyncInterval);
|
||||
RHI::ResultCode AcquireNewImage(uint32_t* acquiredImageIndex);
|
||||
|
||||
void InvalidateSurface();
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace AZ
|
||||
// WindowNotificationBus::Handler overrides ...
|
||||
void OnWindowResized(uint32_t width, uint32_t height) override;
|
||||
void OnWindowClosed() override;
|
||||
void OnVsyncIntervalChanged(uint32_t interval) override;
|
||||
|
||||
// ExclusiveFullScreenRequestBus::Handler overrides ...
|
||||
bool IsExclusiveFullScreenPreferred() const override;
|
||||
|
||||
@@ -13,6 +13,22 @@
|
||||
|
||||
#include <Atom/RHI/Factory.h>
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
|
||||
void OnVsyncIntervalChanged(uint32_t const& interval)
|
||||
{
|
||||
AzFramework::WindowNotificationBus::Broadcast(
|
||||
&AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged,
|
||||
AZ::GetClamp(interval, 0u, 4u));
|
||||
}
|
||||
|
||||
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
|
||||
// The value of the vsync interval is constrained between 0 and 4
|
||||
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
|
||||
AZ_CVAR(uint32_t, rpi_vsync_interval, 0, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RPI
|
||||
@@ -103,6 +119,14 @@ namespace AZ
|
||||
AzFramework::WindowNotificationBus::Handler::BusDisconnect(m_windowHandle);
|
||||
}
|
||||
|
||||
void WindowContext::OnVsyncIntervalChanged(uint32_t interval)
|
||||
{
|
||||
if (m_swapChain->GetDescriptor().m_verticalSyncInterval != interval)
|
||||
{
|
||||
m_swapChain->SetVerticalSyncInterval(interval);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowContext::IsExclusiveFullScreenPreferred() const
|
||||
{
|
||||
return m_swapChain->IsExclusiveFullScreenPreferred();
|
||||
@@ -135,7 +159,7 @@ namespace AZ
|
||||
|
||||
RHI::SwapChainDescriptor descriptor;
|
||||
descriptor.m_window = windowHandle;
|
||||
descriptor.m_verticalSyncInterval = 0;
|
||||
descriptor.m_verticalSyncInterval = rpi_vsync_interval;
|
||||
descriptor.m_dimensions.m_imageWidth = width;
|
||||
descriptor.m_dimensions.m_imageHeight = height;
|
||||
descriptor.m_dimensions.m_imageCount = 3;
|
||||
|
||||
-3
@@ -109,7 +109,6 @@ namespace AtomToolsFramework
|
||||
void BeginCursorCapture() override;
|
||||
void EndCursorCapture() override;
|
||||
AzFramework::ScreenPoint ViewportCursorScreenPosition() override;
|
||||
AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() override;
|
||||
bool IsMouseOver() const override;
|
||||
|
||||
// AzFramework::WindowRequestBus::Handler ...
|
||||
@@ -160,8 +159,6 @@ namespace AtomToolsFramework
|
||||
AZ::ScriptTimePoint m_time;
|
||||
// Whether the Viewport is currently hiding and capturing the cursor position.
|
||||
bool m_capturingCursor = false;
|
||||
// The last known position of the mouse cursor, if one is available.
|
||||
AZStd::optional<QPoint> m_lastCursorPosition;
|
||||
// The viewport settings (e.g. grid snapping, grid size) for this viewport.
|
||||
const AzToolsFramework::ViewportInteraction::ViewportSettings* m_viewportSettings = nullptr;
|
||||
// Maps our internal Qt events into AzFramework InputChannels for our ViewportControllerList.
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/Bootstrap/BootstrapRequestBus.h>
|
||||
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCursor>
|
||||
@@ -234,18 +233,6 @@ namespace AtomToolsFramework
|
||||
void RenderViewportWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
m_mousePosition = event->localPos();
|
||||
|
||||
if (m_capturingCursor && m_lastCursorPosition.has_value())
|
||||
{
|
||||
AzQtComponents::SetCursorPos(m_lastCursorPosition.value());
|
||||
// Even though we just set the cursor position, there are edge cases such as remote desktop that will leave
|
||||
// the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation.
|
||||
m_lastCursorPosition = QCursor::pos();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastCursorPosition = event->globalPos();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderViewportWidget::SendWindowResizeEvent()
|
||||
@@ -420,13 +407,6 @@ namespace AtomToolsFramework
|
||||
return AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(m_mousePosition.toPoint());
|
||||
}
|
||||
|
||||
AZStd::optional<AzFramework::ScreenPoint> RenderViewportWidget::PreviousViewportCursorScreenPosition()
|
||||
{
|
||||
using AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint;
|
||||
return m_lastCursorPosition.has_value() ? ScreenPointFromQPoint(mapFromGlobal(m_lastCursorPosition.value()))
|
||||
: AZStd::optional<AzFramework::ScreenPoint>{};
|
||||
}
|
||||
|
||||
bool RenderViewportWidget::IsMouseOver() const
|
||||
{
|
||||
return m_mouseOver;
|
||||
@@ -434,24 +414,12 @@ namespace AtomToolsFramework
|
||||
|
||||
void RenderViewportWidget::BeginCursorCapture()
|
||||
{
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
qApp->setOverrideCursor(Qt::BlankCursor);
|
||||
m_capturingCursor = true;
|
||||
m_inputChannelMapper->SetCursorCaptureEnabled(true);
|
||||
}
|
||||
|
||||
void RenderViewportWidget::EndCursorCapture()
|
||||
{
|
||||
if (!m_capturingCursor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
qApp->restoreOverrideCursor();
|
||||
m_capturingCursor = false;
|
||||
m_inputChannelMapper->SetCursorCaptureEnabled(false);
|
||||
}
|
||||
|
||||
void RenderViewportWidget::SetWindowTitle(const AZStd::string& title)
|
||||
|
||||
@@ -412,25 +412,24 @@ namespace EMotionFX
|
||||
|
||||
void NonUniformMotionData::UpdateDuration()
|
||||
{
|
||||
m_duration = 0.0f;
|
||||
|
||||
for (const JointData& jointData : m_jointData)
|
||||
{
|
||||
if (!jointData.m_positionTrack.m_times.empty())
|
||||
{
|
||||
m_duration = jointData.m_positionTrack.m_times.back();
|
||||
return;
|
||||
m_duration = AZ::GetMax(m_duration, jointData.m_positionTrack.m_times.back());
|
||||
}
|
||||
|
||||
if (!jointData.m_rotationTrack.m_times.empty())
|
||||
{
|
||||
m_duration = jointData.m_rotationTrack.m_times.back();
|
||||
return;
|
||||
m_duration = AZ::GetMax(m_duration, jointData.m_rotationTrack.m_times.back());
|
||||
}
|
||||
|
||||
#ifndef EMFX_SCALE_DISABLED
|
||||
if (!jointData.m_scaleTrack.m_times.empty())
|
||||
{
|
||||
m_duration = jointData.m_scaleTrack.m_times.back();
|
||||
return;
|
||||
m_duration = AZ::GetMax(m_duration, jointData.m_scaleTrack.m_times.back());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -439,8 +438,7 @@ namespace EMotionFX
|
||||
{
|
||||
if (!morphData.m_track.m_times.empty())
|
||||
{
|
||||
m_duration = morphData.m_track.m_times.back();
|
||||
return;
|
||||
m_duration = AZ::GetMax(m_duration, morphData.m_track.m_times.back());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,12 +446,9 @@ namespace EMotionFX
|
||||
{
|
||||
if (!floatData.m_track.m_times.empty())
|
||||
{
|
||||
m_duration = floatData.m_track.m_times.back();
|
||||
return;
|
||||
m_duration = AZ::GetMax(m_duration, floatData.m_track.m_times.back());
|
||||
}
|
||||
}
|
||||
|
||||
m_duration = 0.0f;
|
||||
}
|
||||
|
||||
void NonUniformMotionData::AllocateJointPositionSamples(size_t jointDataIndex, size_t numSamples)
|
||||
|
||||
@@ -178,6 +178,18 @@ namespace Multiplayer
|
||||
|
||||
void MultiplayerEditorConnection::OnDisconnect([[maybe_unused]] AzNetworking::IConnection* connection, [[maybe_unused]] DisconnectReason reason, [[maybe_unused]] TerminationEndpoint endpoint)
|
||||
{
|
||||
;
|
||||
bool editorLaunch = false;
|
||||
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console)
|
||||
{
|
||||
console->GetCvarValue("editorsv_launch", editorLaunch);
|
||||
}
|
||||
|
||||
if (editorsv_isDedicated && editorLaunch && m_networkEditorInterface->GetConnectionSet().GetConnectionCount() == 1)
|
||||
{
|
||||
if (m_networkEditorInterface->GetPort() != 0)
|
||||
{
|
||||
m_networkEditorInterface->StopListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace Multiplayer
|
||||
AZStd::queue<AZStd::string> m_pendingConnectionTickets;
|
||||
|
||||
AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 };
|
||||
HostFrameId m_lastReplicatedHostFrameId = InvalidHostFrameId;
|
||||
HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0);
|
||||
|
||||
double m_serverSendAccumulator = 0.0;
|
||||
float m_renderBlendFactor = 0.0f;
|
||||
|
||||
+14
-11
@@ -123,20 +123,23 @@ namespace Multiplayer
|
||||
|
||||
bool PropertyPublisher::PrepareUpdateEntityRecord()
|
||||
{
|
||||
// If we reach the maximum outstanding records, reset the replication state
|
||||
bool didPrepare = true;
|
||||
if (m_sentRecords.size() >= net_EntityReplicatorRecordsMax)
|
||||
{
|
||||
return PrepareAddEntityRecord();
|
||||
// If we reach the maximum outstanding records, reset the replication state
|
||||
didPrepare = PrepareAddEntityRecord();
|
||||
}
|
||||
|
||||
// We need to clear out old records, and build up a list of everything that has changed since the last acked packet
|
||||
m_sentRecords.push_front(m_pendingRecord);
|
||||
auto iter = m_sentRecords.begin();
|
||||
++iter; // Consider everything after the record we are going to send
|
||||
for (; iter != m_sentRecords.end(); ++iter)
|
||||
else
|
||||
{
|
||||
// Sequence wasn't acked, so we need to send these bits again
|
||||
m_pendingRecord.Append(*iter);
|
||||
// We need to clear out old records, and build up a list of everything that has changed since the last acked packet
|
||||
m_sentRecords.push_front(m_pendingRecord);
|
||||
auto iter = m_sentRecords.begin();
|
||||
++iter; // Consider everything after the record we are going to send
|
||||
for (; iter != m_sentRecords.end(); ++iter)
|
||||
{
|
||||
// Sequence wasn't acked, so we need to send these bits again
|
||||
m_pendingRecord.Append(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't send predictable properties back to the Autonomous unless we correct them
|
||||
@@ -145,7 +148,7 @@ namespace Multiplayer
|
||||
m_pendingRecord.Subtract(m_netBindComponent->GetPredictableRecord());
|
||||
}
|
||||
|
||||
return true;
|
||||
return didPrepare;
|
||||
}
|
||||
|
||||
bool PropertyPublisher::PrepareDeleteEntityRecord()
|
||||
|
||||
@@ -191,6 +191,8 @@ namespace Multiplayer
|
||||
|
||||
bool ReplicationRecord::ContainsAuthorityToClientBits() const
|
||||
{
|
||||
// Check != Authority here since several modes require information about client updates
|
||||
// (i.e. Autonomous when performing corrections)
|
||||
return (m_remoteNetEntityRole != NetEntityRole::Authority)
|
||||
|| (m_remoteNetEntityRole == NetEntityRole::InvalidRole);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace StartingPointInput
|
||||
editContext->Class<InputEventGroup>("InputEventGroup", "Groups input bindings by the event they generate")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputEventGroup::GetEditorText)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(0, &InputEventGroup::m_eventName, "Event Name", "The event generated by the collection of Input Bindings")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ_CRC("RefreshAttributesAndValues"))
|
||||
->DataElement(0, &InputEventGroup::m_inputHandlers, "Event Generators", "Handlers that generate named events")
|
||||
|
||||
Reference in New Issue
Block a user