Merge pull request #5052 from aws-lumberyard-dev/daimini/gitflow_211027_o3de
GitFlow 10/27/21 (stabilization2110 to development) - O3DE
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
#import <AppKit/NSEvent.h>
|
||||
|
||||
#include "EditorDefs.h"
|
||||
#include "QtEditorApplication.h"
|
||||
#include "QtEditorApplication_mac.h"
|
||||
|
||||
// AzFramework
|
||||
#include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
|
||||
|
||||
@@ -1788,6 +1788,11 @@ AZStd::string SandboxIntegrationManager::GetComponentEditorIcon(const AZ::Uuid&
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
AZStd::string SandboxIntegrationManager::GetComponentTypeEditorIcon(const AZ::Uuid& componentType)
|
||||
{
|
||||
return GetComponentEditorIcon(componentType, nullptr);
|
||||
}
|
||||
|
||||
AZStd::string SandboxIntegrationManager::GetComponentIconPath(const AZ::Uuid& componentType,
|
||||
AZ::Crc32 componentIconAttrib, AZ::Component* component)
|
||||
{
|
||||
|
||||
@@ -233,6 +233,7 @@ private:
|
||||
}
|
||||
|
||||
AZStd::string GetComponentEditorIcon(const AZ::Uuid& componentType, AZ::Component* component) override;
|
||||
AZStd::string GetComponentTypeEditorIcon(const AZ::Uuid& componentType) override;
|
||||
AZStd::string GetComponentIconPath(const AZ::Uuid& componentType, AZ::Crc32 componentIconAttrib, AZ::Component* component) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ ComponentDataModel::ComponentDataModel(QObject* parent)
|
||||
if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, classData->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentIcons[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
|
||||
@@ -408,7 +408,7 @@ CTrackViewNodesCtrl::CTrackViewNodesCtrl(QWidget* hParentWnd, CTrackViewDialog*
|
||||
serializeContext->EnumerateDerived<AZ::Component>([this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, classData->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentTypeToIconMap[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
|
||||
@@ -258,10 +258,17 @@ namespace AzFramework
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void XcbNativeWindow::SetWindowTitle(const AZStd::string& title)
|
||||
{
|
||||
// Set the title of both the window and the task bar by using
|
||||
// a buffer to hold the title twice, separated by a null-terminator
|
||||
auto doubleTitleSize = (title.size() + 1) * 2;
|
||||
AZStd::string doubleTitle(doubleTitleSize, '\0');
|
||||
azstrncpy(doubleTitle.data(), doubleTitleSize, title.c_str(), title.size());
|
||||
azstrncpy(&doubleTitle.data()[title.size() + 1], title.size(), title.c_str(), title.size());
|
||||
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
xcbCheckResult = xcb_change_property(
|
||||
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast<uint32_t>(title.size()),
|
||||
title.c_str());
|
||||
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, static_cast<uint32_t>(doubleTitle.size()),
|
||||
doubleTitle.c_str());
|
||||
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title.");
|
||||
}
|
||||
|
||||
|
||||
@@ -826,6 +826,10 @@ namespace AzToolsFramework
|
||||
/// Path will be empty if component should have no icon.
|
||||
virtual AZStd::string GetComponentEditorIcon(const AZ::Uuid& /*componentType*/, AZ::Component* /*component*/) { return AZStd::string(); }
|
||||
|
||||
//! Return path to icon for component type.
|
||||
//! Path will be empty if component type should have no icon.
|
||||
virtual AZStd::string GetComponentTypeEditorIcon(const AZ::Uuid& /*componentType*/) { return AZStd::string(); }
|
||||
|
||||
/**
|
||||
* Return the icon image path based on the component type and where it is used.
|
||||
* \param componentType component type
|
||||
|
||||
+2
@@ -43,6 +43,8 @@ namespace AzToolsFramework
|
||||
};
|
||||
|
||||
//! Provides a bus to notify when the different editor modes are entered/exit.
|
||||
//! @note The editor modes are not discrete states but rather each progression of mode retain the active the parent
|
||||
//! mode that the new mode progressed from.
|
||||
class ViewportEditorModeNotifications : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace AzToolsFramework
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
AZ_EBUS_BEHAVIOR_BINDER(ToolsApplicationNotificationBusHandler, "{7EB67956-FF86-461A-91E2-7B08279CFACF}", AZ::SystemAllocator,
|
||||
EntityRegistered, EntityDeregistered);
|
||||
EntityRegistered, EntityDeregistered, AfterEntitySelectionChanged);
|
||||
|
||||
void EntityRegistered(AZ::EntityId entityId) override
|
||||
{
|
||||
@@ -187,6 +187,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
Call(FN_EntityDeregistered, entityId);
|
||||
}
|
||||
|
||||
void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override
|
||||
{
|
||||
Call(FN_AfterEntitySelectionChanged, newlySelectedEntities, newlyDeselectedEntities);
|
||||
}
|
||||
};
|
||||
|
||||
struct ViewPaneCallbackBusHandler final
|
||||
@@ -410,6 +415,7 @@ namespace AzToolsFramework
|
||||
->Handler<Internal::ToolsApplicationNotificationBusHandler>()
|
||||
->Event("EntityRegistered", &ToolsApplicationEvents::EntityRegistered)
|
||||
->Event("EntityDeregistered", &ToolsApplicationEvents::EntityDeregistered)
|
||||
->Event("AfterEntitySelectionChanged", &ToolsApplicationEvents::AfterEntitySelectionChanged)
|
||||
;
|
||||
|
||||
behaviorContext->Class<ViewPaneOptions>()
|
||||
@@ -428,6 +434,7 @@ namespace AzToolsFramework
|
||||
->Attribute(AZ::Script::Attributes::Module, "editor")
|
||||
->Event("RegisterCustomViewPane", &EditorRequests::RegisterCustomViewPane)
|
||||
->Event("UnregisterViewPane", &EditorRequests::UnregisterViewPane)
|
||||
->Event("GetComponentTypeEditorIcon", &EditorRequests::GetComponentTypeEditorIcon)
|
||||
;
|
||||
|
||||
behaviorContext->EBus<EditorEventsBus>("EditorEventBus")
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZStd::string componentIconPath;
|
||||
EBUS_EVENT_RESULT(componentIconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, componentClass->m_typeId, nullptr);
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(componentIconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, componentClass->m_typeId);
|
||||
componentIconTable[componentClass] = QString::fromUtf8(componentIconPath.c_str());
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -72,7 +72,7 @@ namespace AzToolsFramework
|
||||
|
||||
void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event)
|
||||
{
|
||||
m_mousePosition = QPoint();
|
||||
m_mousePosition = QPoint(-1, -1);
|
||||
m_currentHoveredIndex = QModelIndex();
|
||||
update();
|
||||
}
|
||||
@@ -200,7 +200,7 @@ namespace AzToolsFramework
|
||||
const bool isEnabled = (this->model()->flags(index) & Qt::ItemIsEnabled);
|
||||
|
||||
const bool isSelected = selectionModel()->isSelected(index);
|
||||
const bool isHovered = (index == indexAt(m_mousePosition)) && isEnabled;
|
||||
const bool isHovered = (index == indexAt(m_mousePosition).siblingAtColumn(0)) && isEnabled;
|
||||
|
||||
// Paint the branch Selection/Hover Rect
|
||||
PaintBranchSelectionHoverRect(painter, rect, isSelected, isHovered);
|
||||
|
||||
+3
-6
@@ -153,6 +153,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
initEntityOutlinerWidgetResources();
|
||||
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
AZ_Assert(m_editorEntityUiInterface != nullptr, "EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
m_gui = new Ui::EntityOutlinerWidgetUI();
|
||||
m_gui->setupUi(this);
|
||||
|
||||
@@ -282,12 +285,6 @@ namespace AzToolsFramework
|
||||
|
||||
m_listModel->Initialize();
|
||||
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
|
||||
AZ_Assert(
|
||||
m_editorEntityUiInterface != nullptr,
|
||||
"EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
EditorPickModeNotificationBus::Handler::BusConnect(GetEntityContextId());
|
||||
EntityHighlightMessages::Bus::Handler::BusConnect();
|
||||
EntityOutlinerModelNotificationBus::Handler::BusConnect();
|
||||
|
||||
+1
-1
@@ -583,7 +583,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZStd::string iconPath;
|
||||
EBUS_EVENT_RESULT(iconPath, AzToolsFramework::EditorRequests::Bus, GetComponentEditorIcon, componentType, const_cast<AZ::Component*>(&componentInstance));
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentEditorIcon, componentType, const_cast<AZ::Component*>(&componentInstance));
|
||||
GetHeader()->SetIcon(QIcon(iconPath.c_str()));
|
||||
|
||||
bool isExpanded = true;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
|
||||
@@ -187,10 +188,13 @@ namespace UnitTest
|
||||
ASSERT_NE(m_viewportEditorModeTracker, nullptr);
|
||||
m_viewportEditorModes = m_viewportEditorModeTracker->GetViewportEditorModes({AzToolsFramework::GetEntityContextId()});
|
||||
ASSERT_NE(m_viewportEditorModes, nullptr);
|
||||
m_focusModeInterface = AZ::Interface<AzToolsFramework::FocusModeInterface>::Get();
|
||||
ASSERT_NE(m_focusModeInterface, nullptr);
|
||||
}
|
||||
|
||||
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
|
||||
const ViewportEditorModesInterface* m_viewportEditorModes = nullptr;
|
||||
AzToolsFramework::FocusModeInterface* m_focusModeInterface = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(ViewportEditorModesTestsFixture, NumberOfEditorModesIsEqualTo4)
|
||||
@@ -522,32 +526,48 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture, EnteringComponentModeAfterInitialStateHasViewportEditorModesDefaultAndComponentModeActive)
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringComponentModeAfterInitialStateHasViewportEditorModesDefaultAndComponentModeActive)
|
||||
{
|
||||
// When component mode is entered
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
bool inComponentMode = false;
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::BroadcastResult(
|
||||
inComponentMode, &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::InComponentMode);
|
||||
|
||||
// Expect to be in component mode
|
||||
EXPECT_TRUE(inComponentMode);
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default and component viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
|
||||
// Do not expect the pick and focus viewport editor modes to be active
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorPickEntitySelectionAfterInitialStateHasOnlyViewportEditorModePickModeActive)
|
||||
ExitingComponentModeAfterEnteringFrominitialStateHasViewportEditorModesDefaultActive)
|
||||
{
|
||||
// When component mode is entered and exited
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::EndComponentMode);
|
||||
|
||||
// Expect to not be in component mode
|
||||
EXPECT_FALSE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect only the default viewport editor mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorPickEntitySelectionAfterInitialStateHasOnlyViewportEditorModePickActive)
|
||||
{
|
||||
// When entering pick mode
|
||||
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
@@ -563,6 +583,96 @@ namespace UnitTest
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Pick);
|
||||
}
|
||||
|
||||
// FocusMode integration tests will follow (LYN-6995)
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
EnteringEditorDefaultEntitySelectionFromEditorPickEntitySelectionHasOnlyViewportEditorModeDefaultActive)
|
||||
{
|
||||
// When pick mode is entered and exited
|
||||
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
|
||||
EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
|
||||
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
|
||||
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
|
||||
{
|
||||
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
|
||||
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
|
||||
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
|
||||
{
|
||||
return AZStd::make_unique<AzToolsFramework::EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);
|
||||
});
|
||||
|
||||
// Expect only the default viewport editor mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(ViewportEditorModeTrackerIntegrationTestFixture, EnteringFocusModeAfterInitialStateHasViewportEditorModeDefaultAndPickActive)
|
||||
{
|
||||
// When entering focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
|
||||
// Expect the default and focus viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
ExitingFocusModeAfterEnteringFromInitialStateHasOnlyViewportEditorModeDefaultActive)
|
||||
{
|
||||
// When entering and leaving focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId());
|
||||
|
||||
// Expect only the default mode to be active
|
||||
ExpectOnlyModeActive(*m_viewportEditorModes, ViewportEditorMode::Default);
|
||||
}
|
||||
|
||||
TEST_F(ViewportEditorModeTrackerIntegrationTestFixture, EnteringComponentModeFromFocusModeStateHasViewportEditorModeDefaultAndFocusAndComponentActive)
|
||||
{
|
||||
// When entering component mode from focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
// Expect to be in component mode
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default, focus and component viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ViewportEditorModeTrackerIntegrationTestFixture,
|
||||
ExitingComponentModeAfterEnteringFromFocusModeHasViewportEditorModeDefaultAndFocusActive)
|
||||
{
|
||||
// When entering and leaving component mode from focus mode
|
||||
m_focusModeInterface->SetFocusRoot(AZ::EntityId{ 1 });
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::BeginComponentMode,
|
||||
AZStd::vector<AzToolsFramework::ComponentModeFramework::EntityAndComponentModeBuilders>{});
|
||||
|
||||
EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::EndComponentMode);
|
||||
|
||||
// Expect to not be in component mode
|
||||
EXPECT_FALSE(AzToolsFramework::ComponentModeFramework::InComponentMode());
|
||||
|
||||
// Expect the default and focus viewport editor modes to be active
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Default));
|
||||
EXPECT_TRUE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Focus));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Component));
|
||||
EXPECT_FALSE(m_viewportEditorModes->IsModeActive(ViewportEditorMode::Pick));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -691,6 +691,12 @@ QProgressBar::chunk {
|
||||
|
||||
#gemRepoAddDialogInstructionTitleLabel {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
#gemRepoAddDialogWarningLabel {
|
||||
font-size:12px;
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
#addGemRepoDialog #formFrame {
|
||||
|
||||
@@ -167,6 +167,10 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
notification += " " + tr("and") + " ";
|
||||
}
|
||||
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
|
||||
{
|
||||
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
|
||||
}
|
||||
}
|
||||
|
||||
if (numChangedDependencies == 1 )
|
||||
|
||||
@@ -225,21 +225,22 @@ namespace O3DE::ProjectManager
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
const int selectedGemTotal = m_gemModel->GatherGemsToBeAdded(/*includeDependencies=*/true).size();
|
||||
const int unselectedGemTotal = m_gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true).size();
|
||||
const int enabledGemTotal = m_gemModel->TotalAddedGems(/*includeDependencies=*/true);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemSelectedString(GemSortFilterProxyModel::GemSelected::Unselected));
|
||||
elementCounts.push_back(unselectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Active));
|
||||
elementCounts.push_back(enabledGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
|
||||
elementCounts.push_back(totalGems - enabledGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
@@ -262,44 +263,51 @@ namespace O3DE::ProjectManager
|
||||
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
|
||||
QAbstractButton* unselectedButton = buttons[0];
|
||||
QAbstractButton* selectedButton = buttons[1];
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
QAbstractButton* selectedButton = buttons[0];
|
||||
QAbstractButton* unselectedButton = buttons[1];
|
||||
selectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Selected);
|
||||
unselectedButton->setChecked(m_filterProxyModel->GetGemSelected() == GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
|
||||
auto updateGemSelection = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
if (!unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Selected);
|
||||
}
|
||||
else if (unselectedButton->isChecked() && !selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Unselected);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
if (unselectedButton->isChecked() && selectedButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::Both);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemSelected(GemSortFilterProxyModel::GemSelected::NoFilter);
|
||||
}
|
||||
}
|
||||
};
|
||||
connect(unselectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
connect(selectedButton, &QAbstractButton::toggled, this, updateGemSelection);
|
||||
|
||||
QAbstractButton* inactiveButton = buttons[2];
|
||||
QAbstractButton* activeButton = buttons[3];
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
QAbstractButton* activeButton = buttons[2];
|
||||
QAbstractButton* inactiveButton = buttons[3];
|
||||
activeButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Active);
|
||||
inactiveButton->setChecked(m_filterProxyModel->GetGemActive() == GemSortFilterProxyModel::GemActive::Inactive);
|
||||
|
||||
auto updateGemActive = [=]([[maybe_unused]] bool checked)
|
||||
{
|
||||
if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
if (!inactiveButton->isChecked() && activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Active);
|
||||
}
|
||||
else if (inactiveButton->isChecked() && !activeButton->isChecked())
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::Inactive);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterProxyModel->SetGemActive(GemSortFilterProxyModel::GemActive::NoFilter);
|
||||
|
||||
@@ -50,11 +50,26 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter != GemSelected::NoFilter)
|
||||
// Gem selected
|
||||
if (m_gemSelectedFilter == GemSelected::Selected)
|
||||
{
|
||||
const GemSelected sourceGemStatus = static_cast<GemSelected>(GemModel::IsAdded(sourceIndex));
|
||||
if (m_gemSelectedFilter != sourceGemStatus)
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Unselected)
|
||||
{
|
||||
if (!GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Gem selected or unselected
|
||||
else if (m_gemSelectedFilter == GemSelected::Both)
|
||||
{
|
||||
if (!GemModel::NeedsToBeAdded(sourceIndex, true) && !GemModel::NeedsToBeRemoved(sourceIndex, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
NoFilter = -1,
|
||||
Unselected,
|
||||
Selected
|
||||
Selected,
|
||||
Both
|
||||
};
|
||||
enum class GemActive
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace O3DE::ProjectManager
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(30, 30, 25, 10);
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
setLayout(vLayout);
|
||||
|
||||
QLabel* instructionTitleLabel = new QLabel(tr("Enter a valid path to add a new user repository"));
|
||||
@@ -41,9 +42,18 @@ namespace O3DE::ProjectManager
|
||||
vLayout->addWidget(instructionContextLabel);
|
||||
|
||||
m_repoPath = new FormFolderBrowseEditWidget(tr("Repository Path"), "", this);
|
||||
m_repoPath->setFixedWidth(600);
|
||||
m_repoPath->setFixedSize(QSize(600, 100));
|
||||
vLayout->addWidget(m_repoPath);
|
||||
|
||||
vLayout->addSpacing(10);
|
||||
|
||||
QLabel* warningLabel = new QLabel(tr("Online repositories may contain files that could potentially harm your computer,"
|
||||
" please ensure you understand the risks before downloading Gems from third-party sources."));
|
||||
warningLabel->setObjectName("gemRepoAddDialogWarningLabel");
|
||||
warningLabel->setWordWrap(true);
|
||||
warningLabel->setAlignment(Qt::AlignLeft);
|
||||
vLayout->addWidget(warningLabel);
|
||||
|
||||
vLayout->addSpacing(40);
|
||||
|
||||
QDialogButtonBox* dialogButtons = new QDialogButtonBox();
|
||||
|
||||
@@ -133,6 +133,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are already on this screen still notify we are on this screen to refresh it
|
||||
newScreen->NotifyCurrentScreen();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
+4
-4
@@ -108,7 +108,7 @@ TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_CallWithoutClientSe
|
||||
MatchmakingNotificationsHandlerMock matchmakingHandlerMock;
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_gameliftClientTicketTracker->StartPolling("ticket1", "player1");
|
||||
WaitForProcessFinish([](){ return ::UnitTest::TestRunner::Instance().m_numAssertsFailed == 1; });
|
||||
WaitForProcessFinish([&](){ return matchmakingHandlerMock.m_numMatchError == 1; });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
ASSERT_TRUE(matchmakingHandlerMock.m_numMatchError == 1);
|
||||
ASSERT_FALSE(m_gameliftClientTicketTracker->IsTrackerIdle());
|
||||
@@ -122,7 +122,7 @@ TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_MultipleCallsWithou
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_gameliftClientTicketTracker->StartPolling("ticket1", "player1");
|
||||
m_gameliftClientTicketTracker->StartPolling("ticket1", "player1");
|
||||
WaitForProcessFinish([](){ return ::UnitTest::TestRunner::Instance().m_numAssertsFailed == 1; });
|
||||
WaitForProcessFinish([&](){ return matchmakingHandlerMock.m_numMatchError == 1; });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
ASSERT_TRUE(matchmakingHandlerMock.m_numMatchError == 1);
|
||||
ASSERT_FALSE(m_gameliftClientTicketTracker->IsTrackerIdle());
|
||||
@@ -140,7 +140,7 @@ TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_CallButWithFailedOu
|
||||
MatchmakingNotificationsHandlerMock matchmakingHandlerMock;
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_gameliftClientTicketTracker->StartPolling("ticket1", "player1");
|
||||
WaitForProcessFinish([](){ return ::UnitTest::TestRunner::Instance().m_numAssertsFailed == 1; });
|
||||
WaitForProcessFinish([&](){ return matchmakingHandlerMock.m_numMatchError == 1; });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
ASSERT_TRUE(matchmakingHandlerMock.m_numMatchError == 1);
|
||||
ASSERT_FALSE(m_gameliftClientTicketTracker->IsTrackerIdle());
|
||||
@@ -160,7 +160,7 @@ TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_CallWithMoreThanOne
|
||||
MatchmakingNotificationsHandlerMock matchmakingHandlerMock;
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
m_gameliftClientTicketTracker->StartPolling("ticket1", "player1");
|
||||
WaitForProcessFinish([](){ return ::UnitTest::TestRunner::Instance().m_numAssertsFailed == 1; });
|
||||
WaitForProcessFinish([&](){ return matchmakingHandlerMock.m_numMatchError == 1; });
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
ASSERT_TRUE(matchmakingHandlerMock.m_numMatchError == 1);
|
||||
ASSERT_FALSE(m_gameliftClientTicketTracker->IsTrackerIdle());
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
|
||||
#include <CommonFiles/Preprocessor.h>
|
||||
#include <CommonFiles/GlobalBuildOptions.h>
|
||||
@@ -91,19 +92,31 @@ namespace AZ
|
||||
m_shaderAssetBuilder.BusConnect(shaderAssetBuilderDescriptor.m_busId);
|
||||
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBus::Handler::RegisterBuilderInformation, shaderAssetBuilderDescriptor);
|
||||
|
||||
// Register Shader Variant Asset Builder
|
||||
AssetBuilderSDK::AssetBuilderDesc shaderVariantAssetBuilderDescriptor;
|
||||
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
|
||||
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
|
||||
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
|
||||
shaderVariantAssetBuilderDescriptor.m_version = 26; // [AZSL] Changing inlineConstant to rootConstant keyword work.
|
||||
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
|
||||
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>();
|
||||
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
shaderVariantAssetBuilderDescriptor.m_processJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::ProcessJob, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
// If, either the SettingsRegistry doesn't exist, or the property @EnableShaderVariantAssetBuilderRegistryKey is not found,
|
||||
// the default is to enable the ShaderVariantAssetBuilder.
|
||||
m_enableShaderVariantAssetBuilder = true;
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry)
|
||||
{
|
||||
settingsRegistry->Get(m_enableShaderVariantAssetBuilder, EnableShaderVariantAssetBuilderRegistryKey);
|
||||
}
|
||||
|
||||
m_shaderVariantAssetBuilder.BusConnect(shaderVariantAssetBuilderDescriptor.m_busId);
|
||||
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBus::Handler::RegisterBuilderInformation, shaderVariantAssetBuilderDescriptor);
|
||||
if (m_enableShaderVariantAssetBuilder)
|
||||
{
|
||||
// Register Shader Variant Asset Builder
|
||||
AssetBuilderSDK::AssetBuilderDesc shaderVariantAssetBuilderDescriptor;
|
||||
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
|
||||
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
|
||||
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
|
||||
shaderVariantAssetBuilderDescriptor.m_version = 26; // [AZSL] Changing inlineConstant to rootConstant keyword work.
|
||||
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
|
||||
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>();
|
||||
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
shaderVariantAssetBuilderDescriptor.m_processJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::ProcessJob, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
|
||||
m_shaderVariantAssetBuilder.BusConnect(shaderVariantAssetBuilderDescriptor.m_busId);
|
||||
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBus::Handler::RegisterBuilderInformation, shaderVariantAssetBuilderDescriptor);
|
||||
}
|
||||
|
||||
// Register Precompiled Shader Builder
|
||||
AssetBuilderSDK::AssetBuilderDesc precompiledShaderBuilderDescriptor;
|
||||
@@ -121,7 +134,10 @@ namespace AZ
|
||||
void AzslShaderBuilderSystemComponent::Deactivate()
|
||||
{
|
||||
m_shaderAssetBuilder.BusDisconnect();
|
||||
m_shaderVariantAssetBuilder.BusDisconnect();
|
||||
if (m_enableShaderVariantAssetBuilder)
|
||||
{
|
||||
m_shaderVariantAssetBuilder.BusDisconnect();
|
||||
}
|
||||
m_precompiledShaderBuilder.BusDisconnect();
|
||||
|
||||
RHI::ShaderPlatformInterfaceRegisterBus::Handler::BusDisconnect();
|
||||
|
||||
@@ -61,7 +61,17 @@ namespace AZ
|
||||
|
||||
private:
|
||||
ShaderAssetBuilder m_shaderAssetBuilder;
|
||||
|
||||
// The ShaderVariantAssetBuilder can be disabled with this registry key.
|
||||
// By default it is enabled. A user might want to disable it when doing look development
|
||||
// work with shaders or doing lots of iterative changes to shaders. In these cases
|
||||
// GPU performance doesn't matter at all so it is important to not waste time
|
||||
// building ShaderVariantAssets (Other than the Root ShaderVariantAsset, of course.).
|
||||
static constexpr char EnableShaderVariantAssetBuilderRegistryKey[] = "/O3DE/Atom/Shaders/BuildVariants";
|
||||
bool m_enableShaderVariantAssetBuilder = true;
|
||||
|
||||
ShaderVariantAssetBuilder m_shaderVariantAssetBuilder;
|
||||
|
||||
PrecompiledShaderBuilder m_precompiledShaderBuilder;
|
||||
|
||||
/// Contains the ShaderPlatformInterface for all registered RHIs
|
||||
|
||||
@@ -477,8 +477,8 @@ namespace AZ
|
||||
preprocessorOptions.m_predefinedMacros.end(), macroDefinitionsToAdd.begin(), macroDefinitionsToAdd.end());
|
||||
// Run the preprocessor.
|
||||
PreprocessorData output;
|
||||
PreprocessFile(prependedAzslFilePath, output, preprocessorOptions, true, true);
|
||||
RHI::ReportErrorMessages(ShaderAssetBuilderName, output.diagnostics);
|
||||
const bool preprocessorSuccess = PreprocessFile(prependedAzslFilePath, output, preprocessorOptions, true, true);
|
||||
RHI::ReportMessages(ShaderAssetBuilderName, output.diagnostics, !preprocessorSuccess);
|
||||
// Dump the preprocessed string as a flat AZSL file with extension .azslin, which will be given to AZSLc to generate the HLSL file.
|
||||
AZStd::string superVariantAzslinStemName = shaderFileName;
|
||||
if (!supervariantInfo.m_name.IsEmpty())
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"O3DE": {
|
||||
"Atom": {
|
||||
"Shaders": {
|
||||
"BuildVariants": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
@@ -115,7 +116,9 @@ namespace AZ
|
||||
{
|
||||
// GFX TODO - investigate window creation being part of the GameApplication.
|
||||
|
||||
m_nativeWindow = AZStd::make_unique<AzFramework::NativeWindow>("O3DELauncher", AzFramework::WindowGeometry(0, 0, 1920, 1080));
|
||||
auto projectTitle = AZ::Utils::GetProjectName();
|
||||
|
||||
m_nativeWindow = AZStd::make_unique<AzFramework::NativeWindow>(projectTitle.c_str(), AzFramework::WindowGeometry(0, 0, 1920, 1080));
|
||||
AZ_Assert(m_nativeWindow, "Failed to create the game window\n");
|
||||
|
||||
m_nativeWindow->Activate();
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
{
|
||||
"description": "Material Type with properties used to define Enhanced PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model, with advanced features like subsurface scattering, transmission, and anisotropy.",
|
||||
"version": 3,
|
||||
"version": 4,
|
||||
"versionUpdates": [
|
||||
{
|
||||
"toVersion": 4,
|
||||
"actions": [
|
||||
{"op": "rename", "from": "opacity.doubleSided", "to": "general.doubleSided"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"propertyLayout": {
|
||||
"groups": [
|
||||
{
|
||||
@@ -92,6 +100,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"general": [
|
||||
{
|
||||
"name": "doubleSided",
|
||||
"displayName": "Double-sided",
|
||||
"description": "Whether to render back-faces or just front-faces.",
|
||||
"type": "Bool"
|
||||
},
|
||||
{
|
||||
"name": "applySpecularAA",
|
||||
"displayName": "Apply Specular AA",
|
||||
@@ -709,12 +723,6 @@
|
||||
"name": "m_opacityFactor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "doubleSided",
|
||||
"displayName": "Double-sided",
|
||||
"description": "Whether to render back-faces or just front-faces.",
|
||||
"type": "Bool"
|
||||
},
|
||||
{
|
||||
"name": "alphaAffectsSpecular",
|
||||
"displayName": "Alpha affects specular",
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
{
|
||||
"description": "Material Type with properties used to define Standard PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model.",
|
||||
"version": 3,
|
||||
"version": 4,
|
||||
"versionUpdates": [
|
||||
{
|
||||
"toVersion": 4,
|
||||
"actions": [
|
||||
{"op": "rename", "from": "opacity.doubleSided", "to": "general.doubleSided"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"propertyLayout": {
|
||||
"groups": [
|
||||
{
|
||||
@@ -72,6 +80,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"general": [
|
||||
{
|
||||
"name": "doubleSided",
|
||||
"displayName": "Double-sided",
|
||||
"description": "Whether to render back-faces or just front-faces.",
|
||||
"type": "Bool"
|
||||
},
|
||||
{
|
||||
"name": "applySpecularAA",
|
||||
"displayName": "Apply Specular AA",
|
||||
@@ -650,12 +664,6 @@
|
||||
"name": "m_opacityFactor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "doubleSided",
|
||||
"displayName": "Double-sided",
|
||||
"description": "Whether to render back-faces or just front-faces.",
|
||||
"type": "Bool"
|
||||
},
|
||||
{
|
||||
"name": "alphaAffectsSpecular",
|
||||
"displayName": "Alpha affects specular",
|
||||
|
||||
+2
-2
@@ -10,14 +10,14 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
function GetMaterialPropertyDependencies()
|
||||
return {"opacity.doubleSided"}
|
||||
return {"general.doubleSided"}
|
||||
end
|
||||
|
||||
ForwardPassIndex = 0
|
||||
ForwardPassEdsIndex = 1
|
||||
|
||||
function Process(context)
|
||||
local doubleSided = context:GetMaterialPropertyValue_bool("opacity.doubleSided")
|
||||
local doubleSided = context:GetMaterialPropertyValue_bool("general.doubleSided")
|
||||
local lastShader = context:GetShaderCount() - 1;
|
||||
|
||||
if(doubleSided) then
|
||||
|
||||
@@ -81,7 +81,6 @@ function ProcessEditor(context)
|
||||
context:SetMaterialPropertyVisibility("opacity.textureMap", mainVisibility)
|
||||
context:SetMaterialPropertyVisibility("opacity.textureMapUv", mainVisibility)
|
||||
context:SetMaterialPropertyVisibility("opacity.factor", mainVisibility)
|
||||
context:SetMaterialPropertyVisibility("opacity.doubleSided", mainVisibility)
|
||||
|
||||
if(opacityMode == OpacityMode_Blended or opacityMode == OpacityMode_TintedTransparent) then
|
||||
context:SetMaterialPropertyVisibility("opacity.alphaAffectsSpecular", MaterialPropertyVisibility_Enabled)
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
"DrawList" : "forward",
|
||||
|
||||
"CompilerHints" : {
|
||||
"DxcDisableOptimizations" : false,
|
||||
"DxcGenerateDebugInfo" : false
|
||||
"DisableOptimizations" : false,
|
||||
"GenerateDebugInfo" : false
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:57d6744696768f9fb8a5fe5fee9aa36fee1eb87a9dbc1e60d4a35ed3c39d68e6
|
||||
size 810620
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:513f47f6fea5105f603170a8881b7e3b1cd2c4258636d64a6399c725032b500d
|
||||
size 38689
|
||||
@@ -5,12 +5,3 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
if(LY_MONOLITHIC_GAME) # Do not use OpenImageIO in monolithic game
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(LY_BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::ilmbase
|
||||
)
|
||||
|
||||
@@ -57,12 +57,19 @@ namespace AZ
|
||||
AZStd::string m_azslcAdditionalFreeArguments;
|
||||
// note: if you add new sort of arguments here, don't forget to update HasDifferentAzslcArguments()
|
||||
|
||||
//! DXC
|
||||
bool m_dxcDisableWarnings = false;
|
||||
bool m_dxcWarningAsError = false;
|
||||
bool m_dxcDisableOptimizations = false;
|
||||
bool m_dxcGenerateDebugInfo = false;
|
||||
uint8_t m_dxcOptimizationLevel = LevelUnset;
|
||||
//! Remark: To the user, the following parameters are exposed without the
|
||||
//! "Dxc" prefix because these are common options for the "main" compiler
|
||||
//! for the given RHI. At the moment the only "main" compiler is Dxc, but in
|
||||
//! the future AZSLc may transpile from AZSL to some other proprietary language
|
||||
//! and in that case the "main" compiler won't be DXC
|
||||
bool m_disableWarnings = false;
|
||||
bool m_warningAsError = false;
|
||||
bool m_disableOptimizations = false;
|
||||
bool m_generateDebugInfo = false;
|
||||
uint8_t m_optimizationLevel = LevelUnset;
|
||||
//! "DxcAdditionalFreeArguments" keeps the "Dxc" prefix because these arguments
|
||||
//! are specific to DXC, and it will be relevant only if DXC is the "main" compiler
|
||||
//! for a given RHI, otherwise this parameter won't matter.
|
||||
AZStd::string m_dxcAdditionalFreeArguments;
|
||||
|
||||
//! both
|
||||
|
||||
@@ -83,11 +83,12 @@ namespace AZ
|
||||
const AZStd::string& shaderSourcePathForDebug,
|
||||
const char* toolNameForLog);
|
||||
|
||||
//! Reports error messages to AZ_Error and/or AZ_Warning, given a text blob that potentially contains many lines of errors and warnings.
|
||||
//! @param window Debug window name used for AZ Trace functions
|
||||
//! @param errorMessages String that may contain many lines of errors and warnings
|
||||
//! @param return true if Errors were detected and reported (Warnings don't count)
|
||||
bool ReportErrorMessages(AZStd::string_view window, AZStd::string_view errorMessages);
|
||||
//! Reports messages with AZ_Error or AZ_Warning (See @reportAsErrors).
|
||||
//! @param window Debug window name used for AZ Trace functions.
|
||||
//! @param errorMessages Message string.
|
||||
//! @param reportAsErrors If true, messages are traced with AZ_Error, otherwise AZ_Warning is used.
|
||||
//! @returns true If the input text blob contains at least one line with the "error" string.
|
||||
bool ReportMessages(AZStd::string_view window, AZStd::string_view errorMessages, bool reportAsErrors);
|
||||
|
||||
//! Converts from a RHI::ShaderHardwareStage to an RHI::ShaderStage
|
||||
ShaderStage ToRHIShaderStage(ShaderHardwareStage stageType);
|
||||
|
||||
@@ -33,17 +33,17 @@ namespace AZ
|
||||
RegisterEnumerators<MatrixOrder>(serializeContext);
|
||||
|
||||
serializeContext->Class<ShaderCompilerArguments>()
|
||||
->Version(2)
|
||||
->Version(3)
|
||||
->Field("AzslcWarningLevel", &ShaderCompilerArguments::m_azslcWarningLevel)
|
||||
->Field("AzslcWarningAsError", &ShaderCompilerArguments::m_azslcWarningAsError)
|
||||
->Field("AzslcAdditionalFreeArguments", &ShaderCompilerArguments::m_azslcAdditionalFreeArguments)
|
||||
->Field("DxcDisableWarnings", &ShaderCompilerArguments::m_dxcDisableWarnings)
|
||||
->Field("DxcWarningAsError", &ShaderCompilerArguments::m_dxcWarningAsError)
|
||||
->Field("DxcDisableOptimizations", &ShaderCompilerArguments::m_dxcDisableOptimizations)
|
||||
->Field("DxcGenerateDebugInfo", &ShaderCompilerArguments::m_dxcGenerateDebugInfo)
|
||||
->Field("DxcOptimizationLevel", &ShaderCompilerArguments::m_dxcOptimizationLevel)
|
||||
->Field("DxcAdditionalFreeArguments", &ShaderCompilerArguments::m_dxcAdditionalFreeArguments)
|
||||
->Field("DisableWarnings", &ShaderCompilerArguments::m_disableWarnings)
|
||||
->Field("WarningAsError", &ShaderCompilerArguments::m_warningAsError)
|
||||
->Field("DisableOptimizations", &ShaderCompilerArguments::m_disableOptimizations)
|
||||
->Field("GenerateDebugInfo", &ShaderCompilerArguments::m_generateDebugInfo)
|
||||
->Field("OptimizationLevel", &ShaderCompilerArguments::m_optimizationLevel)
|
||||
->Field("DefaultMatrixOrder", &ShaderCompilerArguments::m_defaultMatrixOrder)
|
||||
->Field("DxcAdditionalFreeArguments", &ShaderCompilerArguments::m_dxcAdditionalFreeArguments)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -62,13 +62,13 @@ namespace AZ
|
||||
}
|
||||
m_azslcWarningAsError = m_azslcWarningAsError || right.m_azslcWarningAsError;
|
||||
m_azslcAdditionalFreeArguments = CommandLineArgumentUtils::MergeCommandLineArguments(m_azslcAdditionalFreeArguments, right.m_azslcAdditionalFreeArguments);
|
||||
m_dxcDisableWarnings = m_dxcDisableWarnings || right.m_dxcDisableWarnings;
|
||||
m_dxcWarningAsError = m_dxcWarningAsError || right.m_dxcWarningAsError;
|
||||
m_dxcDisableOptimizations = m_dxcDisableOptimizations || right.m_dxcDisableOptimizations;
|
||||
m_dxcGenerateDebugInfo = m_dxcGenerateDebugInfo || right.m_dxcGenerateDebugInfo;
|
||||
if (right.m_dxcOptimizationLevel != LevelUnset)
|
||||
m_disableWarnings = m_disableWarnings || right.m_disableWarnings;
|
||||
m_warningAsError = m_warningAsError || right.m_warningAsError;
|
||||
m_disableOptimizations = m_disableOptimizations || right.m_disableOptimizations;
|
||||
m_generateDebugInfo = m_generateDebugInfo || right.m_generateDebugInfo;
|
||||
if (right.m_optimizationLevel != LevelUnset)
|
||||
{
|
||||
m_dxcOptimizationLevel = right.m_dxcOptimizationLevel;
|
||||
m_optimizationLevel = right.m_optimizationLevel;
|
||||
}
|
||||
m_dxcAdditionalFreeArguments = CommandLineArgumentUtils::MergeCommandLineArguments(m_dxcAdditionalFreeArguments, right.m_dxcAdditionalFreeArguments);
|
||||
if (right.m_defaultMatrixOrder != MatrixOrder::Default)
|
||||
@@ -131,21 +131,21 @@ namespace AZ
|
||||
AZStd::string ShaderCompilerArguments::MakeAdditionalDxcCommandLineString() const
|
||||
{
|
||||
AZStd::string arguments;
|
||||
if (m_dxcDisableWarnings)
|
||||
if (m_disableWarnings)
|
||||
{
|
||||
arguments += " -no-warnings";
|
||||
}
|
||||
else if (m_dxcWarningAsError)
|
||||
else if (m_warningAsError)
|
||||
{
|
||||
arguments += " -WX";
|
||||
}
|
||||
if (m_dxcDisableOptimizations)
|
||||
if (m_disableOptimizations)
|
||||
{
|
||||
arguments += " -Od";
|
||||
}
|
||||
else if (m_dxcOptimizationLevel <= 3)
|
||||
else if (m_optimizationLevel <= 3)
|
||||
{
|
||||
arguments = " -O" + AZStd::to_string(m_dxcOptimizationLevel);
|
||||
arguments = " -O" + AZStd::to_string(m_optimizationLevel);
|
||||
}
|
||||
if (m_defaultMatrixOrder == MatrixOrder::Column)
|
||||
{
|
||||
|
||||
@@ -330,7 +330,7 @@ namespace AZ
|
||||
// Pump one last time to make sure the streams have been flushed
|
||||
pumpOuputStreams();
|
||||
|
||||
const bool reportedErrors = ReportErrorMessages(toolNameForLog, errorMessages);
|
||||
const bool reportedErrors = ReportMessages(toolNameForLog, errorMessages, exitCode != 0);
|
||||
|
||||
if (timedOut)
|
||||
{
|
||||
@@ -367,32 +367,20 @@ namespace AZ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReportErrorMessages([[maybe_unused]] AZStd::string_view window, AZStd::string_view errorMessages)
|
||||
bool ReportMessages([[maybe_unused]] AZStd::string_view window, AZStd::string_view errorMessages, bool reportAsErrors)
|
||||
{
|
||||
// There are more efficient ways to do this, but this approach is simple and gets us moving for now.
|
||||
AZStd::vector<AZStd::string> lines;
|
||||
AzFramework::StringFunc::Tokenize(errorMessages.data(), lines, "\n\r");
|
||||
|
||||
bool foundErrors = false;
|
||||
|
||||
for (auto& line : lines)
|
||||
if (reportAsErrors)
|
||||
{
|
||||
if (AZStd::string::npos != AzFramework::StringFunc::Find(line, "error"))
|
||||
{
|
||||
AZ_Error(window.data(), false, "%s", line.data());
|
||||
foundErrors = true;
|
||||
}
|
||||
else if (AZStd::string::npos != AzFramework::StringFunc::Find(line, "warning"))
|
||||
{
|
||||
AZ_Warning(window.data(), false, "%s", line.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(window.data(), "%s", line.data());
|
||||
}
|
||||
AZ_Error(window.data(), false, "%.*s", aznumeric_cast<int>(errorMessages.size()), errorMessages.data());
|
||||
}
|
||||
|
||||
return foundErrors;
|
||||
else
|
||||
{
|
||||
// Using AZ_Warning instead of AZ_TracePrintf because this function is commonly
|
||||
// used to report messages from stderr when executing applications. Applications
|
||||
// when ran successfully, only output to stderr for errors or warnings.
|
||||
AZ_Warning(window.data(), false, "%.*s", aznumeric_cast<int>(errorMessages.size()), errorMessages.data());
|
||||
}
|
||||
return AZStd::string::npos != AzFramework::StringFunc::Find(errorMessages, "error");
|
||||
}
|
||||
|
||||
ShaderStage ToRHIShaderStage(ShaderHardwareStage stageType)
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
if (shaderCompilerArguments.m_dxcDisableOptimizations)
|
||||
if (shaderCompilerArguments.m_disableOptimizations)
|
||||
{
|
||||
// When optimizations are disabled (-Od), all resources declared in the source file are available to all stages
|
||||
// (when enabled only the resources which are referenced in a stage are bound to the stage)
|
||||
@@ -195,7 +195,7 @@ namespace AZ
|
||||
|
||||
bool ShaderPlatformInterface::BuildHasDebugInfo(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const
|
||||
{
|
||||
return shaderCompilerArguments.m_dxcGenerateDebugInfo;
|
||||
return shaderCompilerArguments.m_generateDebugInfo;
|
||||
}
|
||||
|
||||
const char* ShaderPlatformInterface::GetAzslHeader(const AssetBuilderSDK::PlatformInfo& platform) const
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace AZ
|
||||
|
||||
bool ShaderPlatformInterface::BuildHasDebugInfo(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const
|
||||
{
|
||||
return shaderCompilerArguments.m_dxcGenerateDebugInfo;
|
||||
return shaderCompilerArguments.m_generateDebugInfo;
|
||||
}
|
||||
|
||||
const char* ShaderPlatformInterface::GetAzslHeader(const AssetBuilderSDK::PlatformInfo& platform) const
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace AZ
|
||||
|
||||
bool ShaderPlatformInterface::BuildHasDebugInfo(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const
|
||||
{
|
||||
return shaderCompilerArguments.m_dxcGenerateDebugInfo;
|
||||
return shaderCompilerArguments.m_generateDebugInfo;
|
||||
}
|
||||
|
||||
const char* ShaderPlatformInterface::GetAzslHeader(const AssetBuilderSDK::PlatformInfo& platform) const
|
||||
|
||||
@@ -93,31 +93,28 @@ namespace AZ
|
||||
|
||||
// Note that the only kind of property update currently supported is rename...
|
||||
|
||||
PropertyGroupMap newPropertyGroups;
|
||||
for (auto& groupPair : m_properties)
|
||||
{
|
||||
PropertyMap& propertyMap = groupPair.second;
|
||||
|
||||
PropertyMap newPropertyMap;
|
||||
|
||||
for (auto& propertyPair : propertyMap)
|
||||
{
|
||||
MaterialPropertyId propertyId{groupPair.first, propertyPair.first};
|
||||
|
||||
if (materialTypeSourceData.ApplyPropertyRenames(propertyId, m_materialTypeVersion))
|
||||
{
|
||||
newPropertyMap[propertyId.GetPropertyName().GetStringView()] = propertyPair.second;
|
||||
changesWereApplied = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newPropertyMap[propertyPair.first] = propertyPair.second;
|
||||
}
|
||||
|
||||
newPropertyGroups[propertyId.GetGroupName().GetStringView()][propertyId.GetPropertyName().GetStringView()] = propertyPair.second;
|
||||
}
|
||||
|
||||
propertyMap = newPropertyMap;
|
||||
}
|
||||
|
||||
if (changesWereApplied)
|
||||
{
|
||||
m_properties = AZStd::move(newPropertyGroups);
|
||||
|
||||
AZ_Warning("MaterialSourceData", false,
|
||||
"This material is based on version '%u' of '%s', but the material type is now at version '%u'. "
|
||||
"Automatic updates are available. Consider updating the .material source file.",
|
||||
|
||||
@@ -164,16 +164,14 @@ namespace AZ
|
||||
const MaterialTypeSourceData::PropertyDefinition* MaterialTypeSourceData::FindProperty(AZStd::string_view groupName, AZStd::string_view propertyName, uint32_t materialTypeVersion) const
|
||||
{
|
||||
auto groupIter = m_propertyLayout.m_properties.find(groupName);
|
||||
if (groupIter == m_propertyLayout.m_properties.end())
|
||||
if (groupIter != m_propertyLayout.m_properties.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const PropertyDefinition& property : groupIter->second)
|
||||
{
|
||||
if (property.m_name == propertyName)
|
||||
for (const PropertyDefinition& property : groupIter->second)
|
||||
{
|
||||
return &property;
|
||||
if (property.m_name == propertyName)
|
||||
{
|
||||
return &property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,16 +183,14 @@ namespace AZ
|
||||
// Do the search again with the new names
|
||||
|
||||
groupIter = m_propertyLayout.m_properties.find(propertyId.GetGroupName().GetStringView());
|
||||
if (groupIter == m_propertyLayout.m_properties.end())
|
||||
if (groupIter != m_propertyLayout.m_properties.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const PropertyDefinition& property : groupIter->second)
|
||||
{
|
||||
if (property.m_name == propertyId.GetPropertyName().GetStringView())
|
||||
for (const PropertyDefinition& property : groupIter->second)
|
||||
{
|
||||
return &property;
|
||||
if (property.m_name == propertyId.GetPropertyName().GetStringView())
|
||||
{
|
||||
return &property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +264,6 @@ namespace AZ
|
||||
{
|
||||
// When rebuilding shaders we may be in a state where the ShaderAsset and root ShaderVariantAsset have been rebuilt and reloaded, but some (or all)
|
||||
// shader variants haven't been built yet. Since we want to use the latest version of the shader code, ignore the old variants and fall back to the newer root variant instead.
|
||||
AZ_Warning("ShaderAsset", false, "ShaderAsset and ShaderVariantAsset are out of sync; defaulting to root shader variant. (This is common while reloading shaders).");
|
||||
return GetRootVariant(supervariantIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,13 @@ namespace UnitTest
|
||||
{"op": "rename", "from": "general.testColorNameB", "to": "general.testColorNameC"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"toVersion": 6,
|
||||
"actions": [
|
||||
{"op": "rename", "from": "oldGroup.MyFloat", "to": "general.MyFloat"},
|
||||
{"op": "rename", "from": "oldGroup.MyIntOldName", "to": "general.MyInt"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"toVersion": 10,
|
||||
"actions": [
|
||||
@@ -751,6 +758,72 @@ namespace UnitTest
|
||||
material.ApplyVersionUpdates();
|
||||
}
|
||||
|
||||
TEST_F(MaterialSourceDataTests, Load_MaterialTypeVersionUpdate_MovePropertiesToAnotherGroup)
|
||||
{
|
||||
const AZStd::string inputJson = R"(
|
||||
{
|
||||
"materialType": "@exefolder@/Temp/test.materialtype",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"oldGroup": {
|
||||
"MyFloat": 1.2,
|
||||
"MyIntOldName": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
MaterialSourceData material;
|
||||
JsonTestResult loadResult = LoadTestDataFromJson(material, inputJson);
|
||||
|
||||
EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask());
|
||||
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
|
||||
|
||||
// Initially, the loaded material data will match the .material file exactly. This gives us the accurate representation of
|
||||
// what's actually saved on disk.
|
||||
|
||||
EXPECT_NE(material.m_properties["oldGroup"].find("MyFloat"), material.m_properties["oldGroup"].end());
|
||||
EXPECT_NE(material.m_properties["oldGroup"].find("MyIntOldName"), material.m_properties["oldGroup"].end());
|
||||
EXPECT_EQ(material.m_properties["general"].find("MyFloat"), material.m_properties["general"].end());
|
||||
EXPECT_EQ(material.m_properties["general"].find("MyInt"), material.m_properties["general"].end());
|
||||
|
||||
float myFloat = material.m_properties["oldGroup"]["MyFloat"].m_value.GetValue<float>();
|
||||
EXPECT_EQ(myFloat, 1.2f);
|
||||
|
||||
int32_t myInt = material.m_properties["oldGroup"]["MyIntOldName"].m_value.GetValue<int32_t>();
|
||||
EXPECT_EQ(myInt, 5);
|
||||
|
||||
EXPECT_EQ(3, material.m_materialTypeVersion);
|
||||
|
||||
// Then we force the material data to update to the latest material type version specification
|
||||
ErrorMessageFinder warningFinder; // Note this finds errors and warnings, and we're looking for a warning.
|
||||
warningFinder.AddExpectedErrorMessage("Automatic updates are available. Consider updating the .material source file");
|
||||
warningFinder.AddExpectedErrorMessage("This material is based on version '3'");
|
||||
warningFinder.AddExpectedErrorMessage("material type is now at version '10'");
|
||||
material.ApplyVersionUpdates();
|
||||
warningFinder.CheckExpectedErrorsFound();
|
||||
|
||||
// Now the material data should match the latest material type.
|
||||
// Look for the property under the latest name in the material type, not the name used in the .material file.
|
||||
|
||||
EXPECT_EQ(material.m_properties["oldGroup"].find("MyFloat"), material.m_properties["oldGroup"].end());
|
||||
EXPECT_EQ(material.m_properties["oldGroup"].find("MyIntOldName"), material.m_properties["oldGroup"].end());
|
||||
EXPECT_NE(material.m_properties["general"].find("MyFloat"), material.m_properties["general"].end());
|
||||
EXPECT_NE(material.m_properties["general"].find("MyInt"), material.m_properties["general"].end());
|
||||
|
||||
myFloat = material.m_properties["general"]["MyFloat"].m_value.GetValue<float>();
|
||||
EXPECT_EQ(myFloat, 1.2f);
|
||||
|
||||
myInt = material.m_properties["general"]["MyInt"].m_value.GetValue<int32_t>();
|
||||
EXPECT_EQ(myInt, 5);
|
||||
|
||||
EXPECT_EQ(10, material.m_materialTypeVersion);
|
||||
|
||||
// Calling ApplyVersionUpdates() again should not report the warning again, since the material has already been updated.
|
||||
warningFinder.Reset();
|
||||
material.ApplyVersionUpdates();
|
||||
}
|
||||
|
||||
TEST_F(MaterialSourceDataTests, Load_MaterialTypeVersionPartialUpdate)
|
||||
{
|
||||
// This case is similar to Load_MaterialTypeVersionUpdate but we start at a later
|
||||
|
||||
@@ -1346,7 +1346,8 @@ namespace UnitTest
|
||||
{
|
||||
"toVersion": 7,
|
||||
"actions": [
|
||||
{ "op": "rename", "from": "general.bazA", "to": "otherGroup.bazB" }
|
||||
{ "op": "rename", "from": "general.bazA", "to": "otherGroup.bazB" },
|
||||
{ "op": "rename", "from": "onlyOneProperty.bopA", "to": "otherGroup.bopB" } // This tests a group 'onlyOneProperty' that no longer exists in the material type
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1370,6 +1371,10 @@ namespace UnitTest
|
||||
{
|
||||
"name": "bazB",
|
||||
"type": "Float"
|
||||
},
|
||||
{
|
||||
"name": "bopB",
|
||||
"type": "Float"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1386,13 +1391,16 @@ namespace UnitTest
|
||||
const MaterialTypeSourceData::PropertyDefinition* foo = materialType.FindProperty("general", "fooC");
|
||||
const MaterialTypeSourceData::PropertyDefinition* bar = materialType.FindProperty("general", "barC");
|
||||
const MaterialTypeSourceData::PropertyDefinition* baz = materialType.FindProperty("otherGroup", "bazB");
|
||||
const MaterialTypeSourceData::PropertyDefinition* bop = materialType.FindProperty("otherGroup", "bopB");
|
||||
|
||||
EXPECT_TRUE(foo);
|
||||
EXPECT_TRUE(bar);
|
||||
EXPECT_TRUE(baz);
|
||||
EXPECT_TRUE(bop);
|
||||
EXPECT_EQ(foo->m_name, "fooC");
|
||||
EXPECT_EQ(bar->m_name, "barC");
|
||||
EXPECT_EQ(baz->m_name, "bazB");
|
||||
EXPECT_EQ(bop->m_name, "bopB");
|
||||
|
||||
// Now try doing the property lookup using old versions of the name and make sure the same property can be found
|
||||
|
||||
@@ -1401,12 +1409,15 @@ namespace UnitTest
|
||||
EXPECT_EQ(bar, materialType.FindProperty("general", "barA"));
|
||||
EXPECT_EQ(bar, materialType.FindProperty("general", "barB"));
|
||||
EXPECT_EQ(baz, materialType.FindProperty("general", "bazA"));
|
||||
EXPECT_EQ(bop, materialType.FindProperty("onlyOneProperty", "bopA"));
|
||||
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("general", "fooX"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("general", "barX"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("general", "bazX"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("general", "bazB"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("otherGroup", "bazA"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("onlyOneProperty", "bopB"));
|
||||
EXPECT_EQ(nullptr, materialType.FindProperty("otherGroup", "bopA"));
|
||||
}
|
||||
|
||||
TEST_F(MaterialTypeSourceDataTests, FindPropertyUsingOldName_Error_UnsupportedVersionUpdate)
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"propertyLayoutVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "Textures/Default/checker_uv_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"doubleSided": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
|
||||
"CompilerHints" : {
|
||||
"DxcDisableOptimizations" : false
|
||||
"DisableOptimizations" : false
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
|
||||
"CompilerHints" : {
|
||||
"DxcDisableOptimizations" : false
|
||||
"DisableOptimizations" : false
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b2ecc32cd3052f3cb5836c8be7bf5cba54d98f46e6a0eeac95aaef00a123411a
|
||||
size 27340
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:93a7e033d9fb0fcac221647322bde03716643d789390f79078c4fcc37ecfd005
|
||||
size 68327
|
||||
oid sha256:513f47f6fea5105f603170a8881b7e3b1cd2c4258636d64a6399c725032b500d
|
||||
size 38689
|
||||
|
||||
@@ -86,6 +86,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
FILES_CMAKE
|
||||
atomlyintegration_commonfeatures_editor_files.cmake
|
||||
${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
PLATFORM_INCLUDE_FILES
|
||||
${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
.
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
if(NOT LY_MONOLITHIC_GAME) # Do not use OpenImageIO in monolithic game
|
||||
set(LY_RUNTIME_DEPENDENCIES
|
||||
3rdParty::OpenImageIO
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
@@ -739,14 +739,32 @@ void ViewportInteraction::MouseWheelEvent(QWheelEvent* ev)
|
||||
|
||||
bool ViewportInteraction::KeyPressEvent(QKeyEvent* ev)
|
||||
{
|
||||
if (ev->key() == Qt::Key_Space)
|
||||
switch (ev->key())
|
||||
{
|
||||
case Qt::Key_Space:
|
||||
if (!ev->isAutoRepeat())
|
||||
{
|
||||
ActivateSpaceBar();
|
||||
}
|
||||
|
||||
return true;
|
||||
case Qt::Key_Up:
|
||||
Nudge(ViewportInteraction::NudgeDirection::Up,
|
||||
(ev->modifiers() & Qt::ShiftModifier) ? ViewportInteraction::NudgeSpeed::Fast : ViewportInteraction::NudgeSpeed::Slow);
|
||||
return true;
|
||||
case Qt::Key_Down:
|
||||
Nudge(ViewportInteraction::NudgeDirection::Down,
|
||||
(ev->modifiers() & Qt::ShiftModifier) ? ViewportInteraction::NudgeSpeed::Fast : ViewportInteraction::NudgeSpeed::Slow);
|
||||
return true;
|
||||
case Qt::Key_Left:
|
||||
Nudge(ViewportInteraction::NudgeDirection::Left,
|
||||
(ev->modifiers() & Qt::ShiftModifier) ? ViewportInteraction::NudgeSpeed::Fast : ViewportInteraction::NudgeSpeed::Slow);
|
||||
return true;
|
||||
case Qt::Key_Right:
|
||||
Nudge(ViewportInteraction::NudgeDirection::Right,
|
||||
(ev->modifiers() & Qt::ShiftModifier) ? ViewportInteraction::NudgeSpeed::Fast : ViewportInteraction::NudgeSpeed::Slow);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -220,6 +220,7 @@ ViewportWidget::ViewportWidget(EditorWindow* parent)
|
||||
InitUiRenderer();
|
||||
|
||||
SetupShortcuts();
|
||||
installEventFilter(m_editorWindow);
|
||||
|
||||
// Setup a timer for the maximum refresh rate we want.
|
||||
// Refresh is actually triggered by interaction events and by the IdleUpdate. This avoids the UI
|
||||
@@ -258,6 +259,8 @@ ViewportWidget::~ViewportWidget()
|
||||
LyShinePassDataRequestBus::Handler::BusDisconnect();
|
||||
AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
removeEventFilter(m_editorWindow);
|
||||
|
||||
m_uiRenderer.reset();
|
||||
|
||||
// Notify LyShine that this is no longer a valid UiRenderer.
|
||||
@@ -688,9 +691,9 @@ void ViewportWidget::wheelEvent(QWheelEvent* ev)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool ViewportWidget::event(QEvent* ev)
|
||||
bool ViewportWidget::eventFilter([[maybe_unused]] QObject* watched, QEvent* event)
|
||||
{
|
||||
if (ev->type() == QEvent::ShortcutOverride)
|
||||
if (event->type() == QEvent::ShortcutOverride)
|
||||
{
|
||||
// When a shortcut is matched, Qt's event processing sends out a shortcut override event
|
||||
// to allow other systems to override it. If it's not overridden, then the key events
|
||||
@@ -698,40 +701,48 @@ bool ViewportWidget::event(QEvent* ev)
|
||||
// handler. In our case this causes a problem in preview mode for the Key_Delete event.
|
||||
// So, if we are preview mode avoid treating Key_Delete as a shortcut.
|
||||
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
int key = keyEvent->key();
|
||||
|
||||
// Override the space bar shortcut so that the key gets handled by the viewport's KeyPress/KeyRelease
|
||||
// events when the viewport has the focus. The space bar is set up as a shortcut in order to give the
|
||||
// viewport the focus and activate the space bar when another widget has the focus. Once the shortcut
|
||||
// is pressed and focus is given to the viewport, the viewport takes over handling the space bar via
|
||||
// the KeyPress/KeyRelease events
|
||||
if (key == Qt::Key_Space)
|
||||
// the KeyPress/KeyRelease events.
|
||||
// Also ignore nudge shortcuts in edit/preview mode so that the KeyPressEvent will be sent.
|
||||
switch (key)
|
||||
{
|
||||
ev->accept();
|
||||
case Qt::Key_Space:
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
{
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UiEditorMode editorMode = m_editorWindow->GetEditorMode();
|
||||
if (editorMode == UiEditorMode::Preview)
|
||||
{
|
||||
switch (key)
|
||||
if (key == Qt::Key_Delete)
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
// Ignore nudge shortcuts in preview mode so that the KeyPressEvent will be sent
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
{
|
||||
ev->accept();
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewportWidget::event(QEvent* ev)
|
||||
{
|
||||
bool result = RenderViewportWidget::event(ev);
|
||||
return result;
|
||||
}
|
||||
@@ -742,8 +753,7 @@ void ViewportWidget::keyPressEvent(QKeyEvent* event)
|
||||
if (editorMode == UiEditorMode::Edit)
|
||||
{
|
||||
// in Edit mode just send input to ViewportInteraction
|
||||
bool handled = m_viewportInteraction->KeyPressEvent(event);
|
||||
if (!handled)
|
||||
if (!m_viewportInteraction->KeyPressEvent(event))
|
||||
{
|
||||
RenderViewportWidget::keyPressEvent(event);
|
||||
}
|
||||
@@ -1246,115 +1256,6 @@ void ViewportWidget::SetupShortcuts()
|
||||
{
|
||||
// Actions with shortcuts are created instead of direct shortcuts because the shortcut dispatcher only looks for matching actions
|
||||
|
||||
// Create nudge shortcuts that are active across the entire UI Editor window. Any widgets (such as the spin box widget) that
|
||||
// handle the same keys and want the shortcut to be ignored need to handle that with a shortcut override event.
|
||||
// In preview mode, the nudge shortcuts are ignored via the shortcut override event. KeyPressEvents are sent instead,
|
||||
// and passed along to the canvas
|
||||
|
||||
// Nudge up
|
||||
{
|
||||
QAction* action = new QAction("Up", this);
|
||||
action->setShortcut(QKeySequence(Qt::Key_Up));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Up, ViewportInteraction::NudgeSpeed::Slow);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge up fast
|
||||
{
|
||||
QAction* action = new QAction("Up Fast", this);
|
||||
action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Up));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Up, ViewportInteraction::NudgeSpeed::Fast);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge down
|
||||
{
|
||||
QAction* action = new QAction("Down", this);
|
||||
action->setShortcut(QKeySequence(Qt::Key_Down));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Down, ViewportInteraction::NudgeSpeed::Slow);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge down fast
|
||||
{
|
||||
QAction* action = new QAction("Down Fast", this);
|
||||
action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Down));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Down, ViewportInteraction::NudgeSpeed::Fast);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge left
|
||||
{
|
||||
QAction* action = new QAction("Left", this);
|
||||
action->setShortcut(QKeySequence(Qt::Key_Left));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Left, ViewportInteraction::NudgeSpeed::Slow);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge left fast
|
||||
{
|
||||
QAction* action = new QAction("Left Fast", this);
|
||||
action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Left));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Left, ViewportInteraction::NudgeSpeed::Fast);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge right
|
||||
{
|
||||
QAction* action = new QAction("Right", this);
|
||||
action->setShortcut(QKeySequence(Qt::Key_Right));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Right, ViewportInteraction::NudgeSpeed::Slow);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Nudge right fast
|
||||
{
|
||||
QAction* action = new QAction("Right Fast", this);
|
||||
action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Right));
|
||||
QObject::connect(action,
|
||||
&QAction::triggered,
|
||||
[this]()
|
||||
{
|
||||
m_viewportInteraction->Nudge(ViewportInteraction::NudgeDirection::Right, ViewportInteraction::NudgeSpeed::Fast);
|
||||
});
|
||||
addAction(action);
|
||||
}
|
||||
|
||||
// Give the viewport focus and activate the space bar
|
||||
{
|
||||
QAction* action = new QAction("Viewport Focus", this);
|
||||
|
||||
@@ -122,12 +122,15 @@ protected:
|
||||
void wheelEvent(QWheelEvent* ev) override;
|
||||
|
||||
//! Prevents shortcuts from interfering with preview mode.
|
||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
|
||||
//! Handle events from Qt.
|
||||
bool event(QEvent* ev) override;
|
||||
|
||||
//! Key press event from Qt
|
||||
//! Key press event from Qt.
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
//! Key release event from Qt
|
||||
//! Key release event from Qt.
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
|
||||
void focusOutEvent(QFocusEvent* ev) override;
|
||||
|
||||
@@ -348,19 +348,7 @@ namespace PhysX
|
||||
LmbrCentral::BoxShapeComponentRequestsBus::EventResult(boxDimensions, GetEntityId(),
|
||||
&LmbrCentral::BoxShapeComponentRequests::GetBoxDimensions);
|
||||
|
||||
if (m_shapeType != ShapeType::Box)
|
||||
{
|
||||
m_shapeConfigs.clear();
|
||||
m_shapeConfigs.emplace_back(AZStd::make_shared<Physics::BoxShapeConfiguration>(boxDimensions));
|
||||
|
||||
m_shapeType = ShapeType::Box;
|
||||
}
|
||||
else
|
||||
{
|
||||
Physics::BoxShapeConfiguration& configuration =
|
||||
static_cast<Physics::BoxShapeConfiguration&>(*m_shapeConfigs.back());
|
||||
configuration = Physics::BoxShapeConfiguration(boxDimensions);
|
||||
}
|
||||
SetShapeConfig(ShapeType::Box, Physics::BoxShapeConfiguration(boxDimensions));
|
||||
|
||||
m_shapeConfigs.back()->m_scale = scale;
|
||||
m_geometryCache.m_boxDimensions = scale * boxDimensions;
|
||||
@@ -374,19 +362,7 @@ namespace PhysX
|
||||
const Physics::CapsuleShapeConfiguration& capsuleShapeConfig =
|
||||
Utils::ConvertFromLmbrCentralCapsuleConfig(lmbrCentralCapsuleShapeConfig);
|
||||
|
||||
if (m_shapeType != ShapeType::Capsule)
|
||||
{
|
||||
m_shapeConfigs.clear();
|
||||
m_shapeConfigs.emplace_back(AZStd::make_shared<Physics::CapsuleShapeConfiguration>(capsuleShapeConfig));
|
||||
|
||||
m_shapeType = ShapeType::Capsule;
|
||||
}
|
||||
else
|
||||
{
|
||||
Physics::CapsuleShapeConfiguration& configuration =
|
||||
static_cast<Physics::CapsuleShapeConfiguration&>(*m_shapeConfigs.back());
|
||||
configuration = capsuleShapeConfig;
|
||||
}
|
||||
SetShapeConfig(ShapeType::Capsule, capsuleShapeConfig);
|
||||
|
||||
m_shapeConfigs.back()->m_scale = scale;
|
||||
const float scalarScale = scale.GetMaxElement();
|
||||
@@ -400,19 +376,7 @@ namespace PhysX
|
||||
LmbrCentral::SphereShapeComponentRequestsBus::EventResult(radius, GetEntityId(),
|
||||
&LmbrCentral::SphereShapeComponentRequests::GetRadius);
|
||||
|
||||
if (m_shapeType != ShapeType::Sphere)
|
||||
{
|
||||
m_shapeConfigs.clear();
|
||||
m_shapeConfigs.emplace_back(AZStd::make_shared<Physics::SphereShapeConfiguration>(radius));
|
||||
|
||||
m_shapeType = ShapeType::Sphere;
|
||||
}
|
||||
else
|
||||
{
|
||||
Physics::SphereShapeConfiguration& configuration =
|
||||
static_cast<Physics::SphereShapeConfiguration&>(*m_shapeConfigs.back());
|
||||
configuration = Physics::SphereShapeConfiguration(radius);
|
||||
}
|
||||
SetShapeConfig(ShapeType::Sphere, Physics::SphereShapeConfiguration(radius));
|
||||
|
||||
m_shapeConfigs.back()->m_scale = scale;
|
||||
m_geometryCache.m_radius = scale.GetMaxElement() * radius;
|
||||
@@ -455,19 +419,7 @@ namespace PhysX
|
||||
|
||||
if (shapeConfig.has_value())
|
||||
{
|
||||
if (m_shapeType != ShapeType::Cylinder)
|
||||
{
|
||||
m_shapeConfigs.clear();
|
||||
m_shapeConfigs.push_back(AZStd::make_shared<Physics::CookedMeshShapeConfiguration>(shapeConfig.value()));
|
||||
|
||||
m_shapeType = ShapeType::Cylinder;
|
||||
}
|
||||
else
|
||||
{
|
||||
Physics::CookedMeshShapeConfiguration& configuration =
|
||||
static_cast<Physics::CookedMeshShapeConfiguration&>(*m_shapeConfigs.back());
|
||||
configuration = Physics::CookedMeshShapeConfiguration(shapeConfig.value());
|
||||
}
|
||||
SetShapeConfig(ShapeType::Cylinder, shapeConfig.value());
|
||||
|
||||
CreateStaticEditorCollider();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
@@ -90,12 +91,15 @@ namespace PhysX
|
||||
void UpdateBoxConfig(const AZ::Vector3& scale);
|
||||
void UpdateCapsuleConfig(const AZ::Vector3& scale);
|
||||
void UpdateSphereConfig(const AZ::Vector3& scale);
|
||||
void UpdateCylinderConfig(const AZ::Vector3& scale);
|
||||
void UpdatePolygonPrismDecomposition();
|
||||
void UpdatePolygonPrismDecomposition(const AZ::PolygonPrismPtr polygonPrismPtr);
|
||||
|
||||
void RefreshUiProperties();
|
||||
// Helper function to set a specific shape configuration
|
||||
template<typename ConfigType>
|
||||
void SetShapeConfig(ShapeType shapeType, const ConfigType& shapeConfig);
|
||||
|
||||
void UpdateCylinderConfig(const AZ::Vector3& scale);
|
||||
void RefreshUiProperties();
|
||||
|
||||
AZ::u32 OnSubdivisionCountChange();
|
||||
AZ::Crc32 SubdivisionCountVisibility();
|
||||
@@ -154,4 +158,28 @@ namespace PhysX
|
||||
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; //!< Responds to changes in non-uniform scale.
|
||||
AZ::Vector3 m_currentNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale.
|
||||
};
|
||||
|
||||
template<typename ConfigType>
|
||||
void EditorShapeColliderComponent::SetShapeConfig(ShapeType shapeType, const ConfigType& shapeConfig)
|
||||
{
|
||||
if (m_shapeType != shapeType)
|
||||
{
|
||||
m_shapeConfigs.clear();
|
||||
m_shapeType = shapeType;
|
||||
}
|
||||
|
||||
if (m_shapeConfigs.empty())
|
||||
{
|
||||
m_shapeConfigs.emplace_back(AZStd::make_shared<ConfigType>(shapeConfig));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(m_shapeConfigs.back()->GetShapeType() == shapeConfig.GetShapeType(),
|
||||
"Expected Physics shape configuration with shape type %d but found one with shape type %d.",
|
||||
static_cast<int>(shapeConfig.GetShapeType()), static_cast<int>(m_shapeConfigs.back()->GetShapeType()));
|
||||
ConfigType& configuration =
|
||||
static_cast<ConfigType&>(*m_shapeConfigs.back());
|
||||
configuration = shapeConfig;
|
||||
}
|
||||
}
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace PhysX
|
||||
const float scaleFactor = (maxHeightBounds <= minHeightBounds) ? 1.0f : AZStd::numeric_limits<int16_t>::max() / halfBounds;
|
||||
const float heightScale{ 1.0f / scaleFactor };
|
||||
|
||||
const uint8_t physxMaximumMaterialIndex = 0x7f;
|
||||
[[maybe_unused]] const uint8_t physxMaximumMaterialIndex = 0x7f;
|
||||
|
||||
// Delete the cached heightfield object if it is there, and create a new one and save in the shape configuration
|
||||
heightfieldConfig.SetCachedNativeHeightfield(nullptr);
|
||||
|
||||
@@ -320,7 +320,7 @@ namespace PhysXEditorTests
|
||||
|
||||
TEST_F(PhysXEditorFixture, EditorShapeColliderComponent_ShapeColliderWithCylinderWithNullHeight_HandledGracefully)
|
||||
{
|
||||
ValidateInvalidEditorShapeColliderComponentParams(0.f, 1.f);
|
||||
ValidateInvalidEditorShapeColliderComponentParams(1.f, 0.f);
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorFixture, EditorShapeColliderComponent_ShapeColliderWithCylinderWithNullRadiusAndNullHeight_HandledGracefully)
|
||||
@@ -338,6 +338,44 @@ namespace PhysXEditorTests
|
||||
ValidateInvalidEditorShapeColliderComponentParams(0.f, -1.f);
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorFixture, EditorShapeColliderComponent_ShapeColliderWithCylinderSwitchingFromNullHeightToValidHeight_HandledGracefully)
|
||||
{
|
||||
// create an editor entity with a shape collider component and a cylinder shape component
|
||||
EntityPtr editorEntity = CreateInactiveEditorEntity("ShapeColliderComponentEditorEntity");
|
||||
editorEntity->CreateComponent<PhysX::EditorShapeColliderComponent>();
|
||||
editorEntity->CreateComponent(LmbrCentral::EditorCylinderShapeComponentTypeId);
|
||||
editorEntity->Activate();
|
||||
|
||||
const float validRadius = 1.0f;
|
||||
const float nullHeight = 0.0f;
|
||||
const float validHeight = 1.0f;
|
||||
|
||||
LmbrCentral::CylinderShapeComponentRequestsBus::Event(editorEntity->GetId(),
|
||||
&LmbrCentral::CylinderShapeComponentRequests::SetRadius, validRadius);
|
||||
|
||||
{
|
||||
UnitTest::ErrorHandler dimensionWarningHandler("Negative or zero cylinder dimensions are invalid");
|
||||
UnitTest::ErrorHandler colliderWarningHandler("No Collider or Shape information found when creating Rigid body");
|
||||
|
||||
LmbrCentral::CylinderShapeComponentRequestsBus::Event(editorEntity->GetId(),
|
||||
&LmbrCentral::CylinderShapeComponentRequests::SetHeight, nullHeight);
|
||||
|
||||
EXPECT_EQ(dimensionWarningHandler.GetExpectedWarningCount(), 1);
|
||||
EXPECT_EQ(colliderWarningHandler.GetExpectedWarningCount(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
UnitTest::ErrorHandler dimensionWarningHandler("Negative or zero cylinder dimensions are invalid");
|
||||
UnitTest::ErrorHandler colliderWarningHandler("No Collider or Shape information found when creating Rigid body");
|
||||
|
||||
LmbrCentral::CylinderShapeComponentRequestsBus::Event(editorEntity->GetId(),
|
||||
&LmbrCentral::CylinderShapeComponentRequests::SetHeight, validHeight);
|
||||
|
||||
EXPECT_EQ(dimensionWarningHandler.GetExpectedWarningCount(), 0);
|
||||
EXPECT_EQ(colliderWarningHandler.GetExpectedWarningCount(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorFixture, EditorShapeColliderComponent_ShapeColliderWithBoxAndRigidBody_CorrectRuntimeComponents)
|
||||
{
|
||||
// create an editor entity with a shape collider component and a box shape component
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Terrain
|
||||
WorldSizeCount,
|
||||
};
|
||||
|
||||
WorldSize m_worldSize;
|
||||
WorldSize m_worldSize = WorldSize::_1024Meters;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux
|
||||
ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b)
|
||||
ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-linux TARGETS GoogleBenchmark PACKAGE_HASH 4038878f337fc7e0274f0230f71851b385b2e0327c495fc3dd3d1c18a807928d)
|
||||
ly_associate_package(PACKAGE_NAME unwind-1.2.1-linux TARGETS unwind PACKAGE_HASH 3453265fb056e25432f611a61546a25f60388e315515ad39007b5925dd054a77)
|
||||
ly_associate_package(PACKAGE_NAME qt-5.15.2-rev5-linux TARGETS Qt PACKAGE_HASH 76b395897b941a173002845c7219a5f8a799e44b269ffefe8091acc048130f28)
|
||||
ly_associate_package(PACKAGE_NAME qt-5.15.2-rev6-linux TARGETS Qt PACKAGE_HASH a37bd9989f1e8fe57d94b98cbf9bd5c3caaea740e2f314e5162fa77300551531)
|
||||
ly_associate_package(PACKAGE_NAME libpng-1.6.37-rev1-linux TARGETS libpng PACKAGE_HASH 896451999f1de76375599aec4b34ae0573d8d34620d9ab29cc30b8739c265ba6)
|
||||
ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-linux TARGETS libsamplerate PACKAGE_HASH 41643c31bc6b7d037f895f89d8d8d6369e906b92eff42b0fe05ee6a100f06261)
|
||||
ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-linux TARGETS OpenSSL PACKAGE_HASH b779426d1e9c5ddf71160d5ae2e639c3b956e0fb5e9fcaf9ce97c4526024e3bc)
|
||||
|
||||
@@ -115,14 +115,14 @@ def get_gem_json_paths_from_cached_repo(repo_uri: str) -> set:
|
||||
file_name = pathlib.Path(cache_filename).resolve()
|
||||
if not file_name.is_file():
|
||||
logger.error(f'Could not find cached repo json file for {repo_uri}')
|
||||
return gem_list
|
||||
return gem_set
|
||||
|
||||
with file_name.open('r') as f:
|
||||
try:
|
||||
repo_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'{file_name} failed to load: {str(e)}')
|
||||
return gem_list
|
||||
return gem_set
|
||||
|
||||
# Get list of gems, then add all json paths to the list if they exist in the cache
|
||||
repo_gems = []
|
||||
|
||||
Reference in New Issue
Block a user