From 4245bf7ac97b01a97f43806cb4f68873bbd677ed Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Tue, 7 Dec 2021 17:00:52 +0800 Subject: [PATCH 01/36] Notify relative component to acquire wind information when the tag of global wind and local wind in PhysX configuration changes. Signed-off-by: T.J. McGrath-Daly --- Gems/PhysX/Code/Source/WindProvider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/PhysX/Code/Source/WindProvider.cpp b/Gems/PhysX/Code/Source/WindProvider.cpp index 3090cea062..c7d5d0863b 100644 --- a/Gems/PhysX/Code/Source/WindProvider.cpp +++ b/Gems/PhysX/Code/Source/WindProvider.cpp @@ -177,7 +177,7 @@ namespace PhysX AZStd::vector m_entityTransformHandlers; AZStd::vector m_pendingAabbUpdates; ChangeCallback m_changeCallback; - bool m_changed = false; + bool m_changed = true; }; WindProvider::WindProvider() From 4f746fddac6a2f82e4172a961ac3a8aa5ddfd113 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Fri, 24 Dec 2021 16:56:39 -0800 Subject: [PATCH 02/36] chore: Rename Graph to EditorGraph Signed-off-by: Michael Pollind --- .../Builder/ScriptCanvasBuilderWorker.cpp | 2 +- .../Code/Builder/ScriptCanvasBuilderWorker.h | 4 +- .../ScriptCanvasBuilderWorkerUtility.cpp | 6 +- .../Assets/ScriptCanvasFileHandling.cpp | 4 +- .../Editor/Assets/ScriptCanvasUndoHelper.cpp | 4 +- .../Editor/Assets/ScriptCanvasUndoHelper.h | 6 +- .../Code/Editor/Components/EditorGraph.cpp | 264 +++++++++--------- .../Code/Editor/Components/EditorUtils.cpp | 2 +- .../Code/Editor/Components/GraphUpgrade.cpp | 4 +- .../ScriptCanvas/Components/EditorGraph.h | 22 +- .../ScriptCanvas/Components/EditorUtils.h | 4 +- .../ScriptCanvas/Components/GraphUpgrade.h | 6 +- .../Code/Editor/ScriptCanvasEditorGem.cpp | 2 +- .../Code/Editor/SystemComponent.cpp | 2 +- .../Editor/Undo/ScriptCanvasGraphCommand.cpp | 8 +- .../Editor/Undo/ScriptCanvasGraphCommand.h | 8 +- .../Code/Editor/View/Windows/MainWindow.cpp | 2 +- .../Windows/Tools/UpgradeTool/Controller.cpp | 2 +- .../Code/Include/ScriptCanvas/Core/Core.cpp | 8 +- .../Code/Include/ScriptCanvas/Core/Core.h | 10 +- 20 files changed, 184 insertions(+), 186 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp index a1a2d1d20f..2f44dfe090 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp @@ -44,7 +44,7 @@ namespace ScriptCanvasBuilder AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullPath, false); AzFramework::StringFunc::Path::Normalize(fullPath); - const ScriptCanvasEditor::Graph* sourceGraph = nullptr; + const ScriptCanvasEditor::EditorGraph* sourceGraph = nullptr; const ScriptCanvas::GraphData* graphData = nullptr; ScriptCanvasEditor::SourceHandle sourceHandle; diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h index 142886f98c..42cc958a07 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.h @@ -35,7 +35,7 @@ namespace ScriptCanvas namespace ScriptCanvasEditor { - class Graph; + class EditorGraph; class SourceHandle; } @@ -135,7 +135,7 @@ namespace ScriptCanvasBuilder AZ::Outcome ProcessTranslationJob(ProcessTranslationJobInput& input); - ScriptCanvasEditor::Graph* PrepareSourceGraph(AZ::Entity* const buildEntity); + ScriptCanvasEditor::EditorGraph* PrepareSourceGraph(AZ::Entity* const buildEntity); AZ::Outcome SaveSubgraphInterface(ProcessTranslationJobInput& input, ScriptCanvas::SubgraphInterfaceData& subgraphInterface); diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index 64e73de9b9..110f8c5164 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -153,7 +153,7 @@ namespace ScriptCanvasBuilder return AZ::Failure(AZStd::string("Cannot compile graph data from a nullptr Script Canvas Entity")); } - auto sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent(scriptCanvasEntity); + auto sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent(scriptCanvasEntity); if (!sourceGraph) { return AZ::Failure(AZStd::string("Failed to find Script Canvas Graph Component")); @@ -385,9 +385,9 @@ namespace ScriptCanvasBuilder ; } - ScriptCanvasEditor::Graph* PrepareSourceGraph(AZ::Entity* const buildEntity) + ScriptCanvasEditor::EditorGraph* PrepareSourceGraph(AZ::Entity* const buildEntity) { - auto sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent(buildEntity); + auto sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent(buildEntity); if (!sourceGraph) { return nullptr; diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp index c4579c9042..bea3cdfe21 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasFileHandling.cpp @@ -180,7 +180,7 @@ namespace ScriptCanvasEditor AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); AZ_Assert(serializeContext, "LoadEditorAssetTree() ailed to retrieve serialize context!"); - const ScriptCanvasEditor::Graph* graph = handle.Get(); + const ScriptCanvasEditor::EditorGraph* graph = handle.Get(); serializeContext->EnumerateObject(graph, beginElementCB, nullptr, AZ::SerializeContext::ENUM_ACCESS_FOR_READ); EditorAssetTree result; @@ -253,7 +253,7 @@ namespace ScriptCanvasEditor aznumeric_caster(ScriptCanvas::MathNodeUtilities::GetRandomIntegral(1, std::numeric_limits::max())); entity->SetId(AZ::EntityId(entityId)); - auto graph = entity->FindComponent(); + auto graph = entity->FindComponent(); graph->MarkOwnership(*scriptCanvasData); entity->Init(); diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.cpp index a067bf411e..35c2f9a11a 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.cpp @@ -17,7 +17,7 @@ namespace ScriptCanvasEditor { } - UndoHelper::UndoHelper(Graph* graph) + UndoHelper::UndoHelper(EditorGraph* graph) : m_undoState(this) { SetSource(graph); @@ -28,7 +28,7 @@ namespace ScriptCanvasEditor UndoRequestBus::Handler::BusDisconnect(); } - void UndoHelper::SetSource(Graph* graph) + void UndoHelper::SetSource(EditorGraph* graph) { m_graph = graph; UndoRequestBus::Handler::BusConnect(graph->GetScriptCanvasId()); diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.h b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.h index e2d4f008fa..4765468ee7 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.h +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasUndoHelper.h @@ -21,13 +21,13 @@ namespace ScriptCanvasEditor public: UndoHelper(); - UndoHelper(Graph* source); + UndoHelper(EditorGraph* source); ~UndoHelper(); UndoCache* GetSceneUndoCache() override; UndoData CreateUndoData() override; - void SetSource(Graph* source); + void SetSource(EditorGraph* source); void BeginUndoBatch(AZStd::string_view label) override; void EndUndoBatch() override; @@ -58,6 +58,6 @@ namespace ScriptCanvasEditor Status m_status = Status::Idle; SceneUndoState m_undoState; - Graph* m_graph = nullptr; + EditorGraph* m_graph = nullptr; }; } diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index d713bc09a6..2a610cd44f 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -100,20 +100,8 @@ namespace EditorGraphCpp } namespace ScriptCanvasEditor { - namespace EditorGraph - { - static const char* GetMimeType() - { - return "application/x-o3de-scriptcanvas"; - } - static const char* GetWrappedNodeGroupingMimeType() - { - return "application/x-03de-scriptcanvas-wrappednodegrouping"; - } - } - - Graph::~Graph() + EditorGraph::~EditorGraph() { for (auto& entry : m_graphCanvasSaveData) { @@ -152,7 +140,7 @@ namespace ScriptCanvasEditor return true; } - void Graph::ConvertToGetVariableNode(Graph* graph, ScriptCanvas::VariableId variableId, const AZ::EntityId& nodeId, AZStd::unordered_map< AZ::EntityId, AZ::EntityId >& setVariableRemapping) + void EditorGraph::ConvertToGetVariableNode(EditorGraph* graph, ScriptCanvas::VariableId variableId, const AZ::EntityId& nodeId, AZStd::unordered_map< AZ::EntityId, AZ::EntityId >& setVariableRemapping) { ScriptCanvas::ScriptCanvasId scriptCanvasId = graph->GetScriptCanvasId(); GraphCanvas::GraphId graphId = graph->GetGraphCanvasGraphId(); @@ -440,7 +428,7 @@ namespace ScriptCanvasEditor } } - void Graph::Reflect(AZ::ReflectContext* context) + void EditorGraph::Reflect(AZ::ReflectContext* context) { GraphStatisticsHelper::Reflect(context); @@ -453,19 +441,19 @@ namespace ScriptCanvasEditor ->Field("Count", &CRCCache::m_cacheCount) ; - serializeContext->Class() + serializeContext->Class() ->Version(EditorGraphCpp::Version::Current, &GraphVersionConverter) - ->Field("m_variableCounter", &Graph::m_variableCounter) - ->Field("m_saveFormatConverted", &Graph::m_saveFormatConverted) - ->Field("GraphCanvasData", &Graph::m_graphCanvasSaveData) - ->Field("CRCCacheMap", &Graph::m_crcCacheMap) - ->Field("StatisticsHelper", &Graph::m_statisticsHelper) - ->Field("GraphCanvasSaveVersion", &Graph::m_graphCanvasSaveVersion) + ->Field("m_variableCounter", &EditorGraph::m_variableCounter) + ->Field("m_saveFormatConverted", &EditorGraph::m_saveFormatConverted) + ->Field("GraphCanvasData", &EditorGraph::m_graphCanvasSaveData) + ->Field("CRCCacheMap", &EditorGraph::m_crcCacheMap) + ->Field("StatisticsHelper", &EditorGraph::m_statisticsHelper) + ->Field("GraphCanvasSaveVersion", &EditorGraph::m_graphCanvasSaveVersion) ; } } - void Graph::Activate() + void EditorGraph::Activate() { const ScriptCanvas::ScriptCanvasId& scriptCanvasId = GetScriptCanvasId(); @@ -483,7 +471,7 @@ namespace ScriptCanvasEditor m_undoHelper.SetSource(this); } - void Graph::Deactivate() + void EditorGraph::Deactivate() { GraphItemCommandNotificationBus::Handler::BusDisconnect(); ScriptCanvas::GraphRequestBus::Handler::BusDisconnect(); @@ -499,7 +487,7 @@ namespace ScriptCanvasEditor m_graphCanvasSceneEntity = nullptr; } - void Graph::OnViewRegistered() + void EditorGraph::OnViewRegistered() { if (!m_saveFormatConverted) { @@ -507,7 +495,7 @@ namespace ScriptCanvasEditor } } - bool Graph::SanityCheckNodeReplacement(ScriptCanvas::Node* oldNode, ScriptCanvas::Node* newNode, ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport) + bool EditorGraph::SanityCheckNodeReplacement(ScriptCanvas::Node* oldNode, ScriptCanvas::Node* newNode, ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport) { auto findReplacementMatch = [](const ScriptCanvas::Slot* oldSlot, const AZStd::vector& newSlots)->ScriptCanvas::SlotId { @@ -623,7 +611,7 @@ namespace ScriptCanvasEditor return true; } - void Graph::HandleFunctionDefinitionExtension(ScriptCanvas::Node* node, GraphCanvas::SlotId graphCanvasSlotId, const GraphCanvas::NodeId& nodeId) + void EditorGraph::HandleFunctionDefinitionExtension(ScriptCanvas::Node* node, GraphCanvas::SlotId graphCanvasSlotId, const GraphCanvas::NodeId& nodeId) { // Special-case for the execution nodeling extensions, which are adding input/output data slots. // We want to automatically promote them to variables so that the user can refer to them more easily @@ -690,7 +678,7 @@ namespace ScriptCanvasEditor } } - AZ::Outcome Graph::ReplaceNodeByConfig + AZ::Outcome EditorGraph::ReplaceNodeByConfig ( ScriptCanvas::Node* oldNode , const ScriptCanvas::NodeConfiguration& nodeConfig , ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport) @@ -809,7 +797,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnEntitiesSerialized(GraphCanvas::GraphSerialization& serializationTarget) + void EditorGraph::OnEntitiesSerialized(GraphCanvas::GraphSerialization& serializationTarget) { const GraphCanvas::GraphData& graphCanvasGraphData = serializationTarget.GetGraphData(); @@ -939,7 +927,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnEntitiesDeserialized(const GraphCanvas::GraphSerialization& serializationSource) + void EditorGraph::OnEntitiesDeserialized(const GraphCanvas::GraphSerialization& serializationSource) { const auto& userDataMap = serializationSource.GetUserDataMapRef(); @@ -1026,7 +1014,7 @@ namespace ScriptCanvasEditor } } - void Graph::DisconnectConnection(const GraphCanvas::ConnectionId& connectionId) + void EditorGraph::DisconnectConnection(const GraphCanvas::ConnectionId& connectionId) { AZStd::any* connectionUserData = nullptr; GraphCanvas::ConnectionRequestBus::EventResult(connectionUserData, connectionId, &GraphCanvas::ConnectionRequests::GetUserData); @@ -1044,11 +1032,11 @@ namespace ScriptCanvasEditor } } - ScriptCanvas::DataPtr Graph::Create() + ScriptCanvas::DataPtr EditorGraph::Create() { if (AZ::Entity* entity = aznew AZ::Entity("Script Canvas Graph")) { - auto graph = entity->CreateComponent(); + auto graph = entity->CreateComponent(); entity->CreateComponent(graph->GetScriptCanvasId()); if (ScriptCanvas::DataPtr data = aznew ScriptCanvas::ScriptCanvasData()) @@ -1064,17 +1052,17 @@ namespace ScriptCanvasEditor return nullptr; } - void Graph::MarkOwnership(ScriptCanvas::ScriptCanvasData& owner) + void EditorGraph::MarkOwnership(ScriptCanvas::ScriptCanvasData& owner) { m_owner = &owner; } - ScriptCanvas::DataPtr Graph::GetOwnership() const + ScriptCanvas::DataPtr EditorGraph::GetOwnership() const { - return const_cast(this)->m_owner; + return const_cast(this)->m_owner; } - bool Graph::CreateConnection(const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint) + bool EditorGraph::CreateConnection(const GraphCanvas::ConnectionId& connectionId, const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint) { if (!sourcePoint.IsValid() || !targetPoint.IsValid()) { @@ -1103,7 +1091,7 @@ namespace ScriptCanvasEditor return scConnected; } - bool Graph::IsValidConnection(const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint) const + bool EditorGraph::IsValidConnection(const GraphCanvas::Endpoint& sourcePoint, const GraphCanvas::Endpoint& targetPoint) const { ScriptCanvas::Endpoint scSourceEndpoint = ConvertToScriptCanvasEndpoint(sourcePoint); ScriptCanvas::Endpoint scTargetEndpoint = ConvertToScriptCanvasEndpoint(targetPoint); @@ -1111,23 +1099,23 @@ namespace ScriptCanvasEditor return CanCreateConnectionBetween(scSourceEndpoint, scTargetEndpoint).IsSuccess(); } - AZStd::string Graph::GetDataTypeString(const AZ::Uuid&) + AZStd::string EditorGraph::GetDataTypeString(const AZ::Uuid&) { // This is used by the default tooltip setting in GraphCanvas, returning an empty string // in order for tooltips to be fully controlled by ScriptCanvas return {}; } - void Graph::OnRemoveUnusedNodes() + void EditorGraph::OnRemoveUnusedNodes() { } - void Graph::OnRemoveUnusedElements() + void EditorGraph::OnRemoveUnusedElements() { RemoveUnusedVariables(); } - bool Graph::AllowReset(const GraphCanvas::Endpoint& endpoint) const + bool EditorGraph::AllowReset(const GraphCanvas::Endpoint& endpoint) const { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); @@ -1159,7 +1147,7 @@ namespace ScriptCanvasEditor return false; } - GraphCanvas::NodePropertyDisplay* Graph::CreateDataSlotPropertyDisplay(const AZ::Uuid& dataType, const GraphCanvas::NodeId& nodeId, const GraphCanvas::SlotId& slotId) const + GraphCanvas::NodePropertyDisplay* EditorGraph::CreateDataSlotPropertyDisplay(const AZ::Uuid& dataType, const GraphCanvas::NodeId& nodeId, const GraphCanvas::SlotId& slotId) const { (void)dataType; @@ -1174,7 +1162,7 @@ namespace ScriptCanvasEditor return CreateDisplayPropertyForSlot(scriptCanvasNodeId, scriptCanvasSlotId); } - GraphCanvas::NodePropertyDisplay* Graph::CreatePropertySlotPropertyDisplay(const AZ::Crc32& propertyId, const GraphCanvas::NodeId& nodeId, const GraphCanvas::NodeId& slotId) const + GraphCanvas::NodePropertyDisplay* EditorGraph::CreatePropertySlotPropertyDisplay(const AZ::Crc32& propertyId, const GraphCanvas::NodeId& nodeId, const GraphCanvas::NodeId& slotId) const { (void)slotId; @@ -1234,7 +1222,7 @@ namespace ScriptCanvasEditor return nullptr; } - AZ::EntityId Graph::ConvertToScriptCanvasNodeId(const GraphCanvas::NodeId& nodeId) const + AZ::EntityId EditorGraph::ConvertToScriptCanvasNodeId(const GraphCanvas::NodeId& nodeId) const { AZStd::any* userData = nullptr; @@ -1243,7 +1231,7 @@ namespace ScriptCanvasEditor return (userData && userData->is()) ? *AZStd::any_cast(userData) : AZ::EntityId(); } - GraphCanvas::NodePropertyDisplay* Graph::CreateDisplayPropertyForSlot(const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId) const + GraphCanvas::NodePropertyDisplay* EditorGraph::CreateDisplayPropertyForSlot(const AZ::EntityId& scriptCanvasNodeId, const ScriptCanvas::SlotId& scriptCanvasSlotId) const { ScriptCanvas::Slot* slot = nullptr; ScriptCanvas::NodeRequestBus::EventResult(slot, scriptCanvasNodeId, &ScriptCanvas::NodeRequests::GetSlot, scriptCanvasSlotId); @@ -1354,13 +1342,13 @@ namespace ScriptCanvasEditor return nullptr; } - void Graph::SignalDirty() + void EditorGraph::SignalDirty() { SourceHandle handle(m_owner, {}, {}); GeneralRequestBus::Broadcast(&GeneralRequests::SignalSceneDirty, handle); } - void Graph::HighlightNodesByType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier) + void EditorGraph::HighlightNodesByType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier) { for (const auto& nodePair : GetNodeMapping()) { @@ -1371,7 +1359,7 @@ namespace ScriptCanvasEditor } } - void Graph::HighlightEBusNodes(const ScriptCanvas::EBusBusId& busId, const ScriptCanvas::EBusEventId& eventId) + void EditorGraph::HighlightEBusNodes(const ScriptCanvas::EBusBusId& busId, const ScriptCanvas::EBusEventId& eventId) { ScriptCanvas::NodeTypeIdentifier ebusIdentifier = ScriptCanvas::NodeUtils::ConstructEBusIdentifier(busId); @@ -1394,7 +1382,7 @@ namespace ScriptCanvasEditor } } - void Graph::HighlightScriptEventNodes(const ScriptCanvas::EBusBusId& busId, const ScriptCanvas::EBusEventId& eventId) + void EditorGraph::HighlightScriptEventNodes(const ScriptCanvas::EBusBusId& busId, const ScriptCanvas::EBusEventId& eventId) { ScriptCanvas::NodeTypeIdentifier sendScriptEventIdentifier = ScriptCanvas::NodeUtils::ConstructSendScriptEventIdentifier(busId, eventId); ScriptCanvas::NodeTypeIdentifier receiveScriptEventIdentifier = ScriptCanvas::NodeUtils::ConstructScriptEventIdentifier(busId); @@ -1422,7 +1410,7 @@ namespace ScriptCanvasEditor } } - void Graph::HighlightScriptCanvasEntity(const AZ::EntityId& scriptCanvasId) + void EditorGraph::HighlightScriptCanvasEntity(const AZ::EntityId& scriptCanvasId) { GraphCanvas::SceneMemberGlowOutlineConfiguration glowConfiguration; @@ -1446,7 +1434,7 @@ namespace ScriptCanvasEditor } } - AZ::EntityId Graph::FindGraphCanvasSlotId(const AZ::EntityId& graphCanvasNodeId, const ScriptCanvas::SlotId& slotId) + AZ::EntityId EditorGraph::FindGraphCanvasSlotId(const AZ::EntityId& graphCanvasNodeId, const ScriptCanvas::SlotId& slotId) { AZ::EntityId graphCanvasSlotId; SlotMappingRequestBus::EventResult(graphCanvasSlotId, graphCanvasNodeId, &SlotMappingRequests::MapToGraphCanvasId, slotId); @@ -1467,7 +1455,7 @@ namespace ScriptCanvasEditor return graphCanvasSlotId; } - bool Graph::ConfigureConnectionUserData(const ScriptCanvas::Endpoint& sourceEndpoint, const ScriptCanvas::Endpoint& targetEndpoint, GraphCanvas::ConnectionId connectionId) + bool EditorGraph::ConfigureConnectionUserData(const ScriptCanvas::Endpoint& sourceEndpoint, const ScriptCanvas::Endpoint& targetEndpoint, GraphCanvas::ConnectionId connectionId) { bool isConfigured = true; @@ -1493,7 +1481,7 @@ namespace ScriptCanvasEditor return isConfigured; } - void Graph::HandleQueuedUpdates() + void EditorGraph::HandleQueuedUpdates() { bool signalDirty = false; @@ -1573,7 +1561,7 @@ namespace ScriptCanvasEditor } } - bool Graph::IsNodeVersionConverting(const AZ::EntityId& graphCanvasNodeId) const + bool EditorGraph::IsNodeVersionConverting(const AZ::EntityId& graphCanvasNodeId) const { bool isConverting = false; @@ -1598,7 +1586,7 @@ namespace ScriptCanvasEditor return isConverting; } - void Graph::OnPreNodeDeleted(const AZ::EntityId& nodeId) + void EditorGraph::OnPreNodeDeleted(const AZ::EntityId& nodeId) { // If we are cdeleteing a HandlerEventNode we don't need to do anything since they are purely visual. // And the underlying ScriptCanvas nodes will persist and maintain all of their state. @@ -1630,7 +1618,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnPreConnectionDeleted(const AZ::EntityId& connectionId) + void EditorGraph::OnPreConnectionDeleted(const AZ::EntityId& connectionId) { AZStd::any* userData = nullptr; GraphCanvas::ConnectionRequestBus::EventResult(userData, connectionId, &GraphCanvas::ConnectionRequests::GetUserData); @@ -1671,22 +1659,22 @@ namespace ScriptCanvasEditor DisconnectConnection(connectionId); } - void Graph::OnUnknownPaste([[maybe_unused]] const QPointF& scenePos) + void EditorGraph::OnUnknownPaste([[maybe_unused]] const QPointF& scenePos) { GraphVariablesTableView::HandleVariablePaste(GetScriptCanvasId()); } - void Graph::OnSelectionChanged() + void EditorGraph::OnSelectionChanged() { ClearHighlights(); } - AZ::u32 Graph::GetNewVariableCounter() + AZ::u32 EditorGraph::GetNewVariableCounter() { return ++m_variableCounter; } - void Graph::ReleaseVariableCounter(AZ::u32 variableCounter) + void EditorGraph::ReleaseVariableCounter(AZ::u32 variableCounter) { if (m_variableCounter == variableCounter) { @@ -1694,32 +1682,32 @@ namespace ScriptCanvasEditor } } - void Graph::RequestUndoPoint() + void EditorGraph::RequestUndoPoint() { GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId()); } - void Graph::RequestPushPreventUndoStateUpdate() + void EditorGraph::RequestPushPreventUndoStateUpdate() { GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate); } - void Graph::RequestPopPreventUndoStateUpdate() + void EditorGraph::RequestPopPreventUndoStateUpdate() { GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate); } - void Graph::TriggerUndo() + void EditorGraph::TriggerUndo() { GeneralRequestBus::Broadcast(&GeneralRequests::TriggerUndo); } - void Graph::TriggerRedo() + void EditorGraph::TriggerRedo() { GeneralRequestBus::Broadcast(&GeneralRequests::TriggerRedo); } - void Graph::EnableNodes(const AZStd::unordered_set< GraphCanvas::NodeId >& nodeIds) + void EditorGraph::EnableNodes(const AZStd::unordered_set< GraphCanvas::NodeId >& nodeIds) { bool enabledNodes = false; for (auto graphCanvasNodeId : nodeIds) @@ -1745,7 +1733,7 @@ namespace ScriptCanvasEditor } } - void Graph::DisableNodes(const AZStd::unordered_set< GraphCanvas::NodeId >& nodeIds) + void EditorGraph::DisableNodes(const AZStd::unordered_set< GraphCanvas::NodeId >& nodeIds) { bool disabledNodes = false; for (auto graphCanvasNodeId : nodeIds) @@ -1766,12 +1754,12 @@ namespace ScriptCanvasEditor } } - void Graph::PostDeletionEvent() + void EditorGraph::PostDeletionEvent() { GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId()); } - void Graph::PostCreationEvent() + void EditorGraph::PostCreationEvent() { GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate); if (m_wrapperNodeDropTarget.IsValid()) @@ -1979,7 +1967,7 @@ namespace ScriptCanvasEditor GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId()); } - void Graph::PostRestore(const UndoData&) + void EditorGraph::PostRestore(const UndoData&) { AZStd::vector graphCanvasNodeIds; GraphCanvas::SceneRequestBus::EventResult(graphCanvasNodeIds, GetGraphCanvasGraphId(), &GraphCanvas::SceneRequests::GetNodes); @@ -1995,23 +1983,23 @@ namespace ScriptCanvasEditor GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::RefreshView); } - void Graph::OnPasteBegin() + void EditorGraph::OnPasteBegin() { GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate); } - void Graph::OnPasteEnd() + void EditorGraph::OnPasteEnd() { GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate); GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, GetScriptCanvasId()); } - void Graph::OnGraphCanvasNodeCreated(const AZ::EntityId& nodeId) + void EditorGraph::OnGraphCanvasNodeCreated(const AZ::EntityId& nodeId) { m_lastGraphCanvasCreationGroup.emplace_back(nodeId); } - void Graph::ResetSlotToDefaultValue(const GraphCanvas::Endpoint& endpoint) + void EditorGraph::ResetSlotToDefaultValue(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); @@ -2023,13 +2011,13 @@ namespace ScriptCanvasEditor } } - void Graph::ResetReference(const GraphCanvas::Endpoint& endpoint) + void EditorGraph::ResetReference(const GraphCanvas::Endpoint& endpoint) { // ResetSlotToDefault deals with resetting the reference internal to the function call on the node. ResetSlotToDefaultValue(endpoint); } - void Graph::ResetProperty(const GraphCanvas::NodeId& nodeId, const AZ::Crc32& propertyId) + void EditorGraph::ResetProperty(const GraphCanvas::NodeId& nodeId, const AZ::Crc32& propertyId) { AZ::EntityId scriptCanvasNodeId = ConvertToScriptCanvasNodeId(nodeId); ScriptCanvas::Node* canvasNode = FindNode(scriptCanvasNodeId); @@ -2040,7 +2028,7 @@ namespace ScriptCanvasEditor } } - void Graph::RemoveSlot(const GraphCanvas::Endpoint& endpoint) + void EditorGraph::RemoveSlot(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); @@ -2067,7 +2055,7 @@ namespace ScriptCanvasEditor } } - bool Graph::IsSlotRemovable(const GraphCanvas::Endpoint& endpoint) const + bool EditorGraph::IsSlotRemovable(const GraphCanvas::Endpoint& endpoint) const { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); @@ -2081,7 +2069,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2094,7 +2082,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2111,7 +2099,7 @@ namespace ScriptCanvasEditor return false; } - GraphCanvas::CanHandleMimeEventOutcome Graph::CanHandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) + GraphCanvas::CanHandleMimeEventOutcome EditorGraph::CanHandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2144,7 +2132,7 @@ namespace ScriptCanvasEditor return AZ::Failure(AZStd::string("Unable to find Node")); } - bool Graph::HandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) + bool EditorGraph::HandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) { bool handledEvent = false; @@ -2170,7 +2158,7 @@ namespace ScriptCanvasEditor return handledEvent; } - bool Graph::CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint) const + bool EditorGraph::CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint) const { ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(endpoint); auto activeSlot = FindSlot(scriptCanvasEndpoint); @@ -2189,7 +2177,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(endpoint); @@ -2296,7 +2284,7 @@ namespace ScriptCanvasEditor return addOutcome.IsSuccess(); } - bool Graph::SynchronizeReferences(const GraphCanvas::Endpoint& referenceSource, const GraphCanvas::Endpoint& referenceTarget) + bool EditorGraph::SynchronizeReferences(const GraphCanvas::Endpoint& referenceSource, const GraphCanvas::Endpoint& referenceTarget) { ScriptCanvas::Endpoint scriptCanvasSourceEndpoint = ConvertToScriptCanvasEndpoint(referenceSource); ScriptCanvas::Endpoint scriptCanvasTargetEndpoint = ConvertToScriptCanvasEndpoint(referenceTarget); @@ -2334,7 +2322,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::ConvertSlotToValue(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::ConvertSlotToValue(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2347,7 +2335,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::CanConvertSlotToValue(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::CanConvertSlotToValue(const GraphCanvas::Endpoint& endpoint) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2361,7 +2349,7 @@ namespace ScriptCanvasEditor return false; } - GraphCanvas::CanHandleMimeEventOutcome Graph::CanHandleValueMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) + GraphCanvas::CanHandleMimeEventOutcome EditorGraph::CanHandleValueMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) { AZ_UNUSED(endpoint); AZ_UNUSED(mimeData); @@ -2371,7 +2359,7 @@ namespace ScriptCanvasEditor return AZ::Failure(AZStd::string("Unimplemented drag and drop flow")); } - bool Graph::HandleValueMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) + bool EditorGraph::HandleValueMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) { AZ_UNUSED(endpoint); AZ_UNUSED(mimeData); @@ -2379,7 +2367,7 @@ namespace ScriptCanvasEditor return false; } - GraphCanvas::SlotId Graph::RequestExtension(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId, GraphModelRequests::ExtensionRequestReason reason) + GraphCanvas::SlotId EditorGraph::RequestExtension(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId, GraphModelRequests::ExtensionRequestReason reason) { GraphCanvas::SlotId graphCanvasSlotId; @@ -2414,7 +2402,7 @@ namespace ScriptCanvasEditor return graphCanvasSlotId; } - void Graph::ExtensionCancelled(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId) + void EditorGraph::ExtensionCancelled(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId) { AZ::EntityId scNodeId = ConvertToScriptCanvasNodeId(nodeId); @@ -2429,7 +2417,7 @@ namespace ScriptCanvasEditor } } - void Graph::FinalizeExtension(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId) + void EditorGraph::FinalizeExtension(const GraphCanvas::NodeId& nodeId, const GraphCanvas::ExtenderId& extenderId) { AZ::EntityId scNodeId = ConvertToScriptCanvasNodeId(nodeId); @@ -2444,7 +2432,7 @@ namespace ScriptCanvasEditor } } - bool Graph::ShouldWrapperAcceptDrop(const AZ::EntityId& wrapperNode, const QMimeData* mimeData) const + bool EditorGraph::ShouldWrapperAcceptDrop(const AZ::EntityId& wrapperNode, const QMimeData* mimeData) const { if (!mimeData->hasFormat(Widget::NodePaletteDockWidget::GetMimeType())) { @@ -2492,7 +2480,7 @@ namespace ScriptCanvasEditor return true; } - void Graph::AddWrapperDropTarget(const AZ::EntityId& wrapperNode) + void EditorGraph::AddWrapperDropTarget(const AZ::EntityId& wrapperNode) { if (!m_wrapperNodeDropTarget.IsValid()) { @@ -2500,7 +2488,7 @@ namespace ScriptCanvasEditor } } - void Graph::RemoveWrapperDropTarget(const AZ::EntityId& wrapperNode) + void EditorGraph::RemoveWrapperDropTarget(const AZ::EntityId& wrapperNode) { if (m_wrapperNodeDropTarget == wrapperNode) { @@ -2508,7 +2496,7 @@ namespace ScriptCanvasEditor } } - GraphCanvas::GraphId Graph::GetGraphCanvasGraphId() const + GraphCanvas::GraphId EditorGraph::GetGraphCanvasGraphId() const { if (m_saveFormatConverted) { @@ -2525,7 +2513,7 @@ namespace ScriptCanvasEditor } } - NodeIdPair Graph::CreateCustomNode(const AZ::Uuid& typeId, const AZ::Vector2& position) + NodeIdPair EditorGraph::CreateCustomNode(const AZ::Uuid& typeId, const AZ::Vector2& position) { CreateCustomNodeMimeEvent mimeEvent(typeId); @@ -2539,7 +2527,7 @@ namespace ScriptCanvasEditor return NodeIdPair(); } - void Graph::AddCrcCache(const AZ::Crc32& crcValue, const AZStd::string& cacheString) + void EditorGraph::AddCrcCache(const AZ::Crc32& crcValue, const AZStd::string& cacheString) { auto mapIter = m_crcCacheMap.find(crcValue); @@ -2553,7 +2541,7 @@ namespace ScriptCanvasEditor } } - void Graph::RemoveCrcCache(const AZ::Crc32& crcValue) + void EditorGraph::RemoveCrcCache(const AZ::Crc32& crcValue) { auto mapIter = m_crcCacheMap.find(crcValue); @@ -2568,7 +2556,7 @@ namespace ScriptCanvasEditor } } - AZStd::string Graph::DecodeCrc(const AZ::Crc32& crcValue) + AZStd::string EditorGraph::DecodeCrc(const AZ::Crc32& crcValue) { auto mapIter = m_crcCacheMap.find(crcValue); @@ -2580,7 +2568,7 @@ namespace ScriptCanvasEditor return ""; } - void Graph::ClearHighlights() + void EditorGraph::ClearHighlights() { for (const GraphCanvas::GraphicsEffectId& effectId : m_highlights) { @@ -2590,7 +2578,7 @@ namespace ScriptCanvasEditor m_highlights.clear(); } - void Graph::HighlightMembersFromTreeItem(const GraphCanvas::GraphCanvasTreeItem* treeItem) + void EditorGraph::HighlightMembersFromTreeItem(const GraphCanvas::GraphCanvasTreeItem* treeItem) { ClearHighlights(); @@ -2608,7 +2596,7 @@ namespace ScriptCanvasEditor } } - void Graph::HighlightVariables(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds) + void EditorGraph::HighlightVariables(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds) { ClearHighlights(); @@ -2623,7 +2611,7 @@ namespace ScriptCanvasEditor } } - void Graph::HighlightNodes(const AZStd::vector& nodes) + void EditorGraph::HighlightNodes(const AZStd::vector& nodes) { ClearHighlights(); @@ -2633,7 +2621,7 @@ namespace ScriptCanvasEditor } } - void Graph::RemoveUnusedVariables() + void EditorGraph::RemoveUnusedVariables() { RequestPushPreventUndoStateUpdate(); auto variableData = GetVariableData(); @@ -2679,7 +2667,7 @@ namespace ScriptCanvasEditor } } - bool Graph::CanConvertVariableNodeToReference(const GraphCanvas::NodeId& nodeId) + bool EditorGraph::CanConvertVariableNodeToReference(const GraphCanvas::NodeId& nodeId) { AZ::EntityId scriptCanvasNodeId = ConvertToScriptCanvasNodeId(nodeId); @@ -2725,7 +2713,7 @@ namespace ScriptCanvasEditor return false; } - bool Graph::ConvertVariableNodeToReference(const GraphCanvas::NodeId& nodeId) + bool EditorGraph::ConvertVariableNodeToReference(const GraphCanvas::NodeId& nodeId) { AZ::EntityId scriptCanvasNodeId = ConvertToScriptCanvasNodeId(nodeId); @@ -2899,12 +2887,12 @@ namespace ScriptCanvasEditor return true; } - bool Graph::ConvertReferenceToVariableNode([[maybe_unused]] const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::ConvertReferenceToVariableNode([[maybe_unused]] const GraphCanvas::Endpoint& endpoint) { return false; } - bool Graph::OnVersionConversionBegin(ScriptCanvas::Node& scriptCanvasNode) + bool EditorGraph::OnVersionConversionBegin(ScriptCanvas::Node& scriptCanvasNode) { auto insertResult = m_convertingNodes.insert(scriptCanvasNode.GetEntityId()); @@ -2923,7 +2911,7 @@ namespace ScriptCanvasEditor return true; } - void Graph::OnVersionConversionEnd(ScriptCanvas::Node& scriptCanvasNode) + void EditorGraph::OnVersionConversionEnd(ScriptCanvas::Node& scriptCanvasNode) { EditorNodeNotificationBus::Event(scriptCanvasNode.GetEntityId(), &EditorNodeNotifications::OnVersionConversionEnd); @@ -3041,7 +3029,7 @@ namespace ScriptCanvasEditor } } - AZStd::vector Graph::GetNodesOfType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier) + AZStd::vector EditorGraph::GetNodesOfType(const ScriptCanvas::NodeTypeIdentifier& nodeTypeIdentifier) { AZStd::vector nodeIdPairs; @@ -3120,7 +3108,7 @@ namespace ScriptCanvasEditor return nodeIdPairs; } - AZStd::vector Graph::GetVariableNodes(const ScriptCanvas::VariableId& variableId) + AZStd::vector EditorGraph::GetVariableNodes(const ScriptCanvas::VariableId& variableId) { AZStd::vector variableNodes; @@ -3143,7 +3131,7 @@ namespace ScriptCanvasEditor return variableNodes; } - void Graph::QueueVersionUpdate(const AZ::EntityId& graphCanvasNodeId) + void EditorGraph::QueueVersionUpdate(const AZ::EntityId& graphCanvasNodeId) { bool queueUpdate = m_queuedConvertingNodes.empty(); auto insertResult = m_queuedConvertingNodes.insert(graphCanvasNodeId); @@ -3155,7 +3143,7 @@ namespace ScriptCanvasEditor } } - bool Graph::CanExposeEndpoint(const GraphCanvas::Endpoint& endpoint) + bool EditorGraph::CanExposeEndpoint(const GraphCanvas::Endpoint& endpoint) { bool isEnabled = false; @@ -3213,7 +3201,7 @@ namespace ScriptCanvasEditor return isEnabled && !isNodeling; } - ScriptCanvas::Endpoint Graph::ConvertToScriptCanvasEndpoint(const GraphCanvas::Endpoint& endpoint) const + ScriptCanvas::Endpoint EditorGraph::ConvertToScriptCanvasEndpoint(const GraphCanvas::Endpoint& endpoint) const { AZStd::any* userData = nullptr; @@ -3230,7 +3218,7 @@ namespace ScriptCanvasEditor return scriptCanvasEndpoint; } - GraphCanvas::Endpoint Graph::ConvertToGraphCanvasEndpoint(const ScriptCanvas::Endpoint& endpoint) const + GraphCanvas::Endpoint EditorGraph::ConvertToGraphCanvasEndpoint(const ScriptCanvas::Endpoint& endpoint) const { GraphCanvas::Endpoint graphCanvasEndpoint; @@ -3240,7 +3228,7 @@ namespace ScriptCanvasEditor return graphCanvasEndpoint; } - void Graph::OnSaveDataDirtied(const AZ::EntityId& savedElement) + void EditorGraph::OnSaveDataDirtied(const AZ::EntityId& savedElement) { // The EbusHandlerEvent's are a visual only representation of alternative data, and should not be saved. if (EBusHandlerEventNodeDescriptorRequestBus::FindFirstHandler(savedElement) != nullptr @@ -3292,12 +3280,12 @@ namespace ScriptCanvasEditor } } - bool Graph::NeedsSaveConversion() const + bool EditorGraph::NeedsSaveConversion() const { return !m_saveFormatConverted; } - void Graph::ConvertSaveFormat() + void EditorGraph::ConvertSaveFormat() { if (!m_saveFormatConverted) { @@ -3326,7 +3314,7 @@ namespace ScriptCanvasEditor } } - void Graph::ConstructSaveData() + void EditorGraph::ConstructSaveData() { // Save out the SceneData // @@ -3345,7 +3333,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnToastInteraction() + void EditorGraph::OnToastInteraction() { const AzToolsFramework::ToastId* toastId = AzToolsFramework::ToastNotificationBus::GetCurrentBusId(); @@ -3370,7 +3358,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnToastDismissed() + void EditorGraph::OnToastDismissed() { const AzToolsFramework::ToastId* toastId = AzToolsFramework::ToastNotificationBus::GetCurrentBusId(); @@ -3380,7 +3368,7 @@ namespace ScriptCanvasEditor } } - void Graph::OnUndoRedoEnd() + void EditorGraph::OnUndoRedoEnd() { for (const auto& nodePair : GetNodeMapping()) { @@ -3388,7 +3376,7 @@ namespace ScriptCanvasEditor } } - void Graph::ReportError(const ScriptCanvas::Node& node, const AZStd::string& errorSource, const AZStd::string& errorMessage) + void EditorGraph::ReportError(const ScriptCanvas::Node& node, const AZStd::string& errorSource, const AZStd::string& errorMessage) { AzQtComponents::ToastConfiguration toastConfiguration(AzQtComponents::ToastType::Error, errorSource.c_str(), errorMessage.c_str()); @@ -3402,13 +3390,13 @@ namespace ScriptCanvasEditor m_toastNodeIds[toastId] = node.GetEntityId(); } - void Graph::UnregisterToast(const AzToolsFramework::ToastId& toastId) + void EditorGraph::UnregisterToast(const AzToolsFramework::ToastId& toastId) { AzToolsFramework::ToastNotificationBus::MultiHandler::BusDisconnect(toastId); m_toastNodeIds.erase(toastId); } - void Graph::DisplayUpdateToast() + void EditorGraph::DisplayUpdateToast() { GraphCanvas::ViewId viewId; GraphCanvas::SceneRequestBus::EventResult(viewId, GetGraphCanvasGraphId(), &GraphCanvas::SceneRequests::GetViewId); @@ -3442,12 +3430,12 @@ namespace ScriptCanvasEditor } } - const GraphStatisticsHelper& Graph::GetNodeUsageStatistics() const + const GraphStatisticsHelper& EditorGraph::GetNodeUsageStatistics() const { return m_statisticsHelper; } - void Graph::CreateGraphCanvasScene() + void EditorGraph::CreateGraphCanvasScene() { if (!m_saveFormatConverted) { @@ -3492,7 +3480,7 @@ namespace ScriptCanvasEditor m_focusHelper.SetActiveGraph(GetGraphCanvasGraphId()); } - bool Graph::UpgradeGraph(SourceHandle& asset, UpgradeRequest request, bool isVerbose) + bool EditorGraph::UpgradeGraph(SourceHandle& asset, UpgradeRequest request, bool isVerbose) { m_upgradeSM.SetAsset(asset); m_upgradeSM.SetVerbose(isVerbose); @@ -3509,7 +3497,7 @@ namespace ScriptCanvasEditor } } - void Graph::ConnectGraphCanvasBuses() + void EditorGraph::ConnectGraphCanvasBuses() { GraphCanvas::GraphId graphCanvasGraphId = GetGraphCanvasGraphId(); @@ -3517,14 +3505,14 @@ namespace ScriptCanvasEditor GraphCanvas::SceneNotificationBus::Handler::BusConnect(graphCanvasGraphId); } - void Graph::DisconnectGraphCanvasBuses() + void EditorGraph::DisconnectGraphCanvasBuses() { GraphCanvas::GraphModelRequestBus::Handler::BusDisconnect(); GraphCanvas::SceneNotificationBus::Handler::BusDisconnect(); } - void Graph::OnSystemTick() + void EditorGraph::OnSystemTick() { if (!m_allowVersionUpdate) { @@ -3539,7 +3527,7 @@ namespace ScriptCanvasEditor } } - void Graph::DisplayGraphCanvasScene() + void EditorGraph::DisplayGraphCanvasScene() { m_variableDataModel.Activate(GetScriptCanvasId()); @@ -3839,17 +3827,17 @@ namespace ScriptCanvasEditor MarkVersion(); } - void Graph::OnGraphCanvasSceneVisible() + void EditorGraph::OnGraphCanvasSceneVisible() { DisplayUpdateToast(); } - AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* > Graph::GetGraphCanvasSaveData() + AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* > EditorGraph::GetGraphCanvasSaveData() { return m_graphCanvasSaveData; } - void Graph::UpdateGraphCanvasSaveData(const AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* >& saveData) + void EditorGraph::UpdateGraphCanvasSaveData(const AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* >& saveData) { QScopedValueRollback ignoreRequests(m_ignoreSaveRequests, true); @@ -3868,7 +3856,7 @@ namespace ScriptCanvasEditor DisplayGraphCanvasScene(); } - void Graph::ClearGraphCanvasScene() + void EditorGraph::ClearGraphCanvasScene() { GraphCanvas::GraphId graphCanvasGraphId = GetGraphCanvasGraphId(); diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorUtils.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorUtils.cpp index 2cd2dda89e..4e512a3678 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorUtils.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorUtils.cpp @@ -171,7 +171,7 @@ namespace ScriptCanvasEditor } } - void GraphStatisticsHelper::PopulateStatisticData(const Graph* editorGraph) + void GraphStatisticsHelper::PopulateStatisticData(const EditorGraph* editorGraph) { // Opportunistically use this time to refresh out node count array. m_nodeIdentifierCount.clear(); diff --git a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp index fec813b0c1..d23c371096 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp @@ -25,7 +25,7 @@ namespace ScriptCanvasEditor namespace Helpers { - static AZStd::string ConnectionToText(ScriptCanvasEditor::Graph* graph, ScriptCanvas::Endpoint& from, ScriptCanvas::Endpoint& to) + static AZStd::string ConnectionToText(ScriptCanvasEditor::EditorGraph* graph, ScriptCanvas::Endpoint& from, ScriptCanvas::Endpoint& to) { AZ_Assert(graph, "A valid graph must be provided"); @@ -653,7 +653,7 @@ namespace ScriptCanvasEditor #define RegisterState(stateName) m_states.emplace_back(new stateName(this)); - EditorGraphUpgradeMachine::EditorGraphUpgradeMachine(Graph* graph) + EditorGraphUpgradeMachine::EditorGraphUpgradeMachine(EditorGraph* graph) : m_graph(graph) { RegisterState(Start); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index 9157aaeac9..aff47222e1 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -45,7 +45,7 @@ namespace ScriptCanvas namespace ScriptCanvasEditor { //! EditorGraph is the editor version of the ScriptCanvas::Graph component that is activated when executing the script canvas engine - class Graph + class EditorGraph : public ScriptCanvas::Graph , private NodeCreationNotificationBus::Handler , private SceneCounterRequestBus::Handler @@ -77,7 +77,7 @@ namespace ScriptCanvasEditor typedef AZStd::unordered_map< AZ::EntityId, AZ::EntityId > WrappedNodeGroupingMap; - static void ConvertToGetVariableNode(Graph* graph, ScriptCanvas::VariableId variableId, const AZ::EntityId& nodeId, AZStd::unordered_map& setVariableRemapping); + static void ConvertToGetVariableNode(EditorGraph* graph, ScriptCanvas::VariableId variableId, const AZ::EntityId& nodeId, AZStd::unordered_map& setVariableRemapping); struct CRCCache { @@ -100,13 +100,13 @@ namespace ScriptCanvasEditor }; public: - AZ_COMPONENT(Graph, "{4D755CA9-AB92-462C-B24F-0B3376F19967}", ScriptCanvas::Graph); + AZ_COMPONENT(EditorGraph, "{4D755CA9-AB92-462C-B24F-0B3376F19967}", ScriptCanvas::Graph); static ScriptCanvas::DataPtr Create(); static void Reflect(AZ::ReflectContext* context); - Graph(const ScriptCanvas::ScriptCanvasId& scriptCanvasId = AZ::Entity::MakeId()) + EditorGraph(const ScriptCanvas::ScriptCanvasId& scriptCanvasId = AZ::Entity::MakeId()) : ScriptCanvas::Graph(scriptCanvasId) , m_variableCounter(0) , m_graphCanvasSceneEntity(nullptr) @@ -115,11 +115,21 @@ namespace ScriptCanvasEditor , m_upgradeSM(this) {} - ~Graph() override; + ~EditorGraph() override; void Activate() override; void Deactivate() override; + static const char* GetMimeType() + { + return "application/x-o3de-scriptcanvas"; + } + + static const char* GetWrappedNodeGroupingMimeType() + { + return "application/x-03de-scriptcanvas-wrappednodegrouping"; + } + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { ScriptCanvas::Graph::GetProvidedServices(provided); @@ -326,7 +336,7 @@ namespace ScriptCanvasEditor void UnregisterToast(const AzToolsFramework::ToastId& toastId); - Graph(const Graph&) = delete; + EditorGraph(const EditorGraph&) = delete; void DisplayUpdateToast(); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorUtils.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorUtils.h index a4522198b7..d99da61d8d 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorUtils.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorUtils.h @@ -28,7 +28,7 @@ namespace ScriptCanvasEditor // if CompleteDescription() succeeds, sets the handle to the result, else does nothing bool CompleteDescriptionInPlace(SourceHandle& source); - class Graph; + class EditorGraph; class NodePaletteModel; class NodeIdentifierFactory @@ -48,7 +48,7 @@ namespace ScriptCanvasEditor virtual ~GraphStatisticsHelper() = default; - void PopulateStatisticData(const Graph* editorGraph); + void PopulateStatisticData(const EditorGraph* editorGraph); AZStd::unordered_map< ScriptCanvas::NodeTypeIdentifier, int > m_nodeIdentifierCount; diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h index 9fedc2d1f3..78b59e48d1 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h @@ -20,7 +20,7 @@ namespace ScriptCanvas namespace ScriptCanvasEditor { - class Graph; + class EditorGraph; class StateMachine; //! StateTraits provides each state the ability to provide its own compile time ID @@ -158,7 +158,7 @@ namespace ScriptCanvasEditor public: AZ_RTTI(EditorGraphUpgradeMachine, "{C7EABC22-A3DD-4ABE-8303-418EA3CD1246}", StateMachine); - EditorGraphUpgradeMachine(Graph* graph); + EditorGraphUpgradeMachine(EditorGraph* graph); AZStd::unordered_set m_allNodes; AZStd::unordered_set m_outOfDateNodes; @@ -180,7 +180,7 @@ namespace ScriptCanvasEditor bool m_graphNeedsDirtying = false; - Graph* m_graph = nullptr; + EditorGraph* m_graph = nullptr; SourceHandle m_asset; void SetAsset(SourceHandle& assetasset); diff --git a/Gems/ScriptCanvas/Code/Editor/ScriptCanvasEditorGem.cpp b/Gems/ScriptCanvas/Code/Editor/ScriptCanvasEditorGem.cpp index 7c204e8790..1a3bb0e4f9 100644 --- a/Gems/ScriptCanvas/Code/Editor/ScriptCanvasEditorGem.cpp +++ b/Gems/ScriptCanvas/Code/Editor/ScriptCanvasEditorGem.cpp @@ -81,7 +81,7 @@ namespace ScriptCanvas ScriptCanvasEditor::EditorAssetSystemComponent::CreateDescriptor(), ScriptCanvasEditor::EditorScriptCanvasComponent::CreateDescriptor(), ScriptCanvasEditor::EntityMimeDataHandler::CreateDescriptor(), - ScriptCanvasEditor::Graph::CreateDescriptor(), + ScriptCanvasEditor::EditorGraph::CreateDescriptor(), ScriptCanvasEditor::IconComponent::CreateDescriptor(), ScriptCanvasEditor::ReflectComponent::CreateDescriptor(), ScriptCanvasEditor::SystemComponent::CreateDescriptor(), diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index 9bbdddfedb..a79cf2d6cf 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -183,7 +183,7 @@ namespace ScriptCanvasEditor { if (entity) { - auto graph = entity->CreateComponent(); + auto graph = entity->CreateComponent(); entity->CreateComponent(graph->GetScriptCanvasId()); } } diff --git a/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.cpp b/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.cpp index f497b83b08..eb42daa3d8 100644 --- a/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.cpp @@ -35,7 +35,7 @@ namespace ScriptCanvasEditor { } - void GraphItemCommand::Capture(Graph*, bool) + void GraphItemCommand::Capture(EditorGraph*, bool) { } @@ -104,7 +104,7 @@ namespace ScriptCanvasEditor RestoreItem(m_redoState); } - void GraphItemChangeCommand::Capture(Graph* graph, bool captureUndo) + void GraphItemChangeCommand::Capture(EditorGraph* graph, bool captureUndo) { m_scriptCanvasId = graph->GetScriptCanvasId(); m_graphCanvasGraphId = graph->GetGraphCanvasGraphId(); @@ -203,7 +203,7 @@ namespace ScriptCanvasEditor RestoreItem(m_redoState); } - void GraphItemAddCommand::Capture(Graph* graph, bool) + void GraphItemAddCommand::Capture(EditorGraph* graph, bool) { GraphItemChangeCommand::Capture(graph, false); } @@ -224,7 +224,7 @@ namespace ScriptCanvasEditor RestoreItem(m_redoState); } - void GraphItemRemovalCommand::Capture(Graph* graph, bool) + void GraphItemRemovalCommand::Capture(EditorGraph* graph, bool) { GraphItemChangeCommand::Capture(graph, true); } diff --git a/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.h b/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.h index 9b36a7beb0..38eb1099ac 100644 --- a/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.h +++ b/Gems/ScriptCanvas/Code/Editor/Undo/ScriptCanvasGraphCommand.h @@ -44,7 +44,7 @@ namespace ScriptCanvasEditor void Undo() override; void Redo() override; - virtual void Capture(Graph* graph, bool captureUndo); + virtual void Capture(EditorGraph* graph, bool captureUndo); bool Changed() const override; @@ -74,7 +74,7 @@ namespace ScriptCanvasEditor void Undo() override; void Redo() override; - void Capture(Graph* graph, bool captureUndo) override; + void Capture(EditorGraph* graph, bool captureUndo) override; void RestoreItem(const AZStd::vector& restoreBuffer) override; @@ -101,7 +101,7 @@ namespace ScriptCanvasEditor void Undo() override; void Redo() override; - void Capture(Graph* graph, bool captureUndo) override; + void Capture(EditorGraph* graph, bool captureUndo) override; protected: GraphItemAddCommand(const GraphItemAddCommand&) = delete; @@ -122,7 +122,7 @@ namespace ScriptCanvasEditor void Undo() override; void Redo() override; - void Capture(Graph* graph, bool captureUndo) override; + void Capture(EditorGraph* graph, bool captureUndo) override; protected: GraphItemRemovalCommand(const GraphItemRemovalCommand&) = delete; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index f0bee2171a..f51467971d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -1541,7 +1541,7 @@ namespace ScriptCanvasEditor { int outTabIndex = -1; - ScriptCanvas::DataPtr graph = Graph::Create(); + ScriptCanvas::DataPtr graph = EditorGraph::Create(); AZ::Uuid assetId = AZ::Uuid::CreateRandom(); ScriptCanvasEditor::SourceHandle handle = ScriptCanvasEditor::SourceHandle(graph, assetId, assetPath); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp index 39cd6f565e..7646ef9dcd 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/Controller.cpp @@ -154,7 +154,7 @@ namespace ScriptCanvasEditor { asset.Mod()->UpgradeGraph ( asset - , m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_view->forceUpgrade->isChecked() ? EditorGraph::UpgradeRequest::Forced : EditorGraph::UpgradeRequest::IfOutOfDate , m_view->verbose->isChecked()); } }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp index 1e00e70075..7f659952e8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp @@ -328,9 +328,9 @@ namespace ScriptCanvas return AZ::EntityUtils::FindFirstDerivedComponent(m_scriptCanvasEntity.get()); } - const ScriptCanvasEditor::Graph* ScriptCanvasData::GetEditorGraph() const + const ScriptCanvasEditor::EditorGraph* ScriptCanvasData::GetEditorGraph() const { - return reinterpret_cast(GetGraph()); + return reinterpret_cast(GetGraph()); } Graph* ScriptCanvasData::ModGraph() @@ -338,8 +338,8 @@ namespace ScriptCanvas return AZ::EntityUtils::FindFirstDerivedComponent(m_scriptCanvasEntity.get()); } - ScriptCanvasEditor::Graph* ScriptCanvasData::ModEditorGraph() + ScriptCanvasEditor::EditorGraph* ScriptCanvasData::ModEditorGraph() { - return reinterpret_cast(ModGraph()); + return reinterpret_cast(ModGraph()); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h index c29a648eca..5de5c7adb8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h @@ -316,10 +316,10 @@ namespace ScriptCanvas namespace ScriptCanvasEditor { - class Graph; + class EditorGraph; - using GraphPtr = Graph*; - using GraphPtrConst = const Graph*; + using GraphPtr = EditorGraph*; + using GraphPtrConst = const EditorGraph*; class SourceDescription { @@ -411,11 +411,11 @@ namespace ScriptCanvas const Graph* GetGraph() const; - const ScriptCanvasEditor::Graph* GetEditorGraph() const; + const ScriptCanvasEditor::EditorGraph* GetEditorGraph() const; Graph* ModGraph(); - ScriptCanvasEditor::Graph* ModEditorGraph(); + ScriptCanvasEditor::EditorGraph* ModEditorGraph(); AZStd::unique_ptr m_scriptCanvasEntity; private: From aefe1aa8b9e82f3fccb86cb053d2656d70d35fc2 Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Thu, 16 Dec 2021 11:43:24 +0800 Subject: [PATCH 03/36] Fix: Tube spline Signed-off-by: T.J. McGrath-Daly --- Gems/LmbrCentral/Code/Source/Shape/TubeShapeComponent.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Gems/LmbrCentral/Code/Source/Shape/TubeShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/TubeShapeComponent.cpp index d96fc8c9ce..194204dd93 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/TubeShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/TubeShapeComponent.cpp @@ -124,8 +124,14 @@ namespace LmbrCentral void TubeShapeDebugDisplayComponent::GenerateVertices() { + if (!m_spline) + { + AZ_Error("TubeShapeComponent", false, "A TubeShape must have a Spline to work"); + return; + } + const AZ::u32 endSegments = m_spline->IsClosed() ? 0 : m_tubeShapeMeshConfig.m_endSegments; GenerateTubeMesh( - m_spline, m_radiusAttribute, m_radius, m_tubeShapeMeshConfig.m_endSegments, + m_spline, m_radiusAttribute, m_radius, endSegments, m_tubeShapeMeshConfig.m_sides, m_tubeShapeMesh.m_vertexBuffer, m_tubeShapeMesh.m_indexBuffer, m_tubeShapeMesh.m_lineBuffer); } From 71732c1f4539914b4ff8533deeb4b31c7ddca0a7 Mon Sep 17 00:00:00 2001 From: windbagjacket Date: Tue, 11 Jan 2022 13:21:12 +0000 Subject: [PATCH 04/36] Adding ray tracing toggle to mesh component UI Adding ray tracing toggle to mesh component UI Signed-off-by: windbagjacket --- .../CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp | 3 +++ .../Code/Source/Mesh/MeshComponentController.cpp | 4 +++- .../CommonFeatures/Code/Source/Mesh/MeshComponentController.h | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index c89546264a..423145f838 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -79,6 +79,9 @@ namespace AZ ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular", "Renders IBL specular reflections in the forward pass, using only the most influential probe (based on the position of the entity) and the global IBL cubemap. Can reduce rendering costs, but only recommended for static objects that are affected by at most one reflection probe.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_isRayTracingEnabled, "Use ray tracing", + "Includes this mesh in ray tracing calculations.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodType, "Lod Type", "Lod Method.") ->EnumAttribute(RPI::Cullable::LodType::Default, "Default") ->EnumAttribute(RPI::Cullable::LodType::ScreenCoverage, "Screen Coverage") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 517ba90f89..b08670113b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -76,6 +76,7 @@ namespace AZ ->Field("SortKey", &MeshComponentConfig::m_sortKey) ->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps) ->Field("UseForwardPassIBLSpecular", &MeshComponentConfig::m_useForwardPassIblSpecular) + ->Field("IsRayTracingEnabled", &MeshComponentConfig::m_isRayTracingEnabled) ->Field("LodType", &MeshComponentConfig::m_lodType) ->Field("LodOverride", &MeshComponentConfig::m_lodOverride) ->Field("MinimumScreenCoverage", &MeshComponentConfig::m_minimumScreenCoverage) @@ -382,6 +383,7 @@ namespace AZ meshDescriptor.m_modelAsset = m_configuration.m_modelAsset; meshDescriptor.m_useForwardPassIblSpecular = m_configuration.m_useForwardPassIblSpecular; meshDescriptor.m_requiresCloneCallback = RequiresCloning; + meshDescriptor.m_isRayTracingEnabled = m_configuration.m_isRayTracingEnabled; m_meshHandle = m_meshFeatureProcessor->AcquireMesh(meshDescriptor, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); @@ -392,7 +394,7 @@ namespace AZ m_meshFeatureProcessor->SetMeshLodConfiguration(m_meshHandle, GetMeshLodConfiguration()); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps); m_meshFeatureProcessor->SetVisible(m_meshHandle, m_isVisible); - + m_meshFeatureProcessor->SetRayTracingEnabled(m_meshHandle, meshDescriptor.m_isRayTracingEnabled); // [GFX TODO] This should happen automatically. m_changeEventHandler should be passed to AcquireMesh // If the model instance or asset already exists, announce a model change to let others know it's loaded. HandleModelChange(m_meshFeatureProcessor->GetModel(m_meshHandle)); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 6b0731fbf7..4d09b0b7b6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -50,7 +50,7 @@ namespace AZ RHI::DrawItemSortKey m_sortKey = 0; bool m_excludeFromReflectionCubeMaps = false; bool m_useForwardPassIblSpecular = false; - + bool m_isRayTracingEnabled = true; RPI::Cullable::LodType m_lodType = RPI::Cullable::LodType::Default; RPI::Cullable::LodOverride m_lodOverride = aznumeric_cast(0); float m_minimumScreenCoverage = 1.0f / 1080.0f; From 5c52df721142fb23bb316ef6704cb3ef360116c9 Mon Sep 17 00:00:00 2001 From: windbagjacket Date: Fri, 14 Jan 2022 10:48:13 +0000 Subject: [PATCH 05/36] Change property refresh to ValuesOnly instead of EntireTree Signed-off-by: windbagjacket --- .../CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 423145f838..5c8d2d6116 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -81,7 +81,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_isRayTracingEnabled, "Use ray tracing", "Includes this mesh in ray tracing calculations.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::EntireTree) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodType, "Lod Type", "Lod Method.") ->EnumAttribute(RPI::Cullable::LodType::Default, "Default") ->EnumAttribute(RPI::Cullable::LodType::ScreenCoverage, "Screen Coverage") From 7474c5480e5ed3435d078efa75fb260f6f162296 Mon Sep 17 00:00:00 2001 From: windbagjacket Date: Fri, 14 Jan 2022 17:07:13 +0000 Subject: [PATCH 06/36] Adding ray tracing toggle to behavior context so it can be used with scripting. Signed-off-by: windbagjacket --- .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 1 + .../Mesh/MeshFeatureProcessorInterface.h | 2 ++ .../Code/Mocks/MockMeshFeatureProcessor.h | 1 + .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 13 +++++++++++ .../CommonFeatures/Mesh/MeshComponentBus.h | 3 +++ .../Source/Mesh/MeshComponentController.cpp | 22 +++++++++++++++++++ .../Source/Mesh/MeshComponentController.h | 3 +++ .../Code/Source/AtomActorInstance.cpp | 20 ++++++++++++++++- .../Code/Source/AtomActorInstance.h | 2 ++ Gems/Vegetation/Code/Tests/VegetationMocks.h | 9 ++++++++ 10 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index 23cd76ca20..92e9c1e88a 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -176,6 +176,7 @@ namespace AZ void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) override; void SetRayTracingEnabled(const MeshHandle& meshHandle, bool rayTracingEnabled) override; + bool GetRayTracingEnabled(const MeshHandle& meshHandle) const override; void SetVisible(const MeshHandle& meshHandle, bool visible) override; void SetUseForwardPassIblSpecular(const MeshHandle& meshHandle, bool useForwardPassIblSpecular) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 356b1936ca..f616c06e92 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -105,6 +105,8 @@ namespace AZ virtual void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) = 0; //! Sets the option to exclude this mesh from raytracing virtual void SetRayTracingEnabled(const MeshHandle& meshHandle, bool rayTracingEnabled) = 0; + //! Gets whether this mesh is excluded from raytracing + virtual bool GetRayTracingEnabled(const MeshHandle& meshHandle) const = 0; //! Sets the mesh as visible or hidden. When the mesh is hidden it will not be rendered by the feature processor. virtual void SetVisible(const MeshHandle& meshHandle, bool visible) = 0; //! Sets the mesh to render IBL specular in the forward pass. diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 2c818d3c9b..af1e23aa19 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -38,6 +38,7 @@ namespace UnitTest MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Render::MaterialAssignmentMap&)); MOCK_METHOD2(AcquireMesh, MeshHandle (const AZ::Render::MeshHandleDescriptor&, const AZ::Data::Instance&)); MOCK_METHOD2(SetRayTracingEnabled, void (const MeshHandle&, bool)); + MOCK_CONST_METHOD1(GetRayTracingEnabled, bool(const MeshHandle&)); MOCK_METHOD2(SetVisible, void (const MeshHandle&, bool)); MOCK_METHOD2(SetUseForwardPassIblSpecular, void (const MeshHandle&, bool)); }; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index dfb2b3fe6b..6b9a3fc698 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -435,6 +435,19 @@ namespace AZ } } + bool MeshFeatureProcessor::GetRayTracingEnabled(const MeshHandle& meshHandle) const + { + if (meshHandle.IsValid()) + { + return meshHandle->m_descriptor.m_isRayTracingEnabled; + } + else + { + AZ_Assert(false, "Invalid mesh handle"); + return false; + } + } + void MeshFeatureProcessor::SetVisible(const MeshHandle& meshHandle, bool visible) { if (meshHandle.IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h index cc9c78d356..989cbcffb2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h @@ -51,6 +51,9 @@ namespace AZ virtual void SetVisibility(bool visible) = 0; virtual bool GetVisibility() const = 0; + virtual void SetRayTracingEnabled(bool enabled) = 0; + virtual bool GetRayTracingEnabled() const = 0; + virtual AZ::Aabb GetWorldBounds() = 0; virtual AZ::Aabb GetLocalBounds() = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index b08670113b..a68ad24adf 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -182,6 +182,8 @@ namespace AZ ->Event("GetMinimumScreenCoverage", &MeshComponentRequestBus::Events::GetMinimumScreenCoverage) ->Event("SetQualityDecayRate", &MeshComponentRequestBus::Events::SetQualityDecayRate) ->Event("GetQualityDecayRate", &MeshComponentRequestBus::Events::GetQualityDecayRate) + ->Event("SetRayTracingEnabled", &MeshComponentRequestBus::Events::SetRayTracingEnabled) + ->Event("GetRayTracingEnabled", &MeshComponentRequestBus::Events::GetRayTracingEnabled) ->VirtualProperty("ModelAssetId", "GetModelAssetId", "SetModelAssetId") ->VirtualProperty("ModelAssetPath", "GetModelAssetPath", "SetModelAssetPath") ->VirtualProperty("SortKey", "GetSortKey", "SetSortKey") @@ -189,6 +191,7 @@ namespace AZ ->VirtualProperty("LodOverride", "GetLodOverride", "SetLodOverride") ->VirtualProperty("MinimumScreenCoverage", "GetMinimumScreenCoverage", "SetMinimumScreenCoverage") ->VirtualProperty("QualityDecayRate", "GetQualityDecayRate", "SetQualityDecayRate") + ->VirtualProperty("RayTracingEnabled", "GetRayTracingEnabled", "SetRayTracingEnabled") ; behaviorContext->EBus("MeshComponentNotificationBus") @@ -561,6 +564,25 @@ namespace AZ return m_isVisible; } + void MeshComponentController::SetRayTracingEnabled(bool enabled) + { + if (m_meshHandle.IsValid() && m_meshFeatureProcessor) + { + m_meshFeatureProcessor->SetRayTracingEnabled(m_meshHandle, enabled); + m_configuration.m_isRayTracingEnabled = enabled; + } + } + + bool MeshComponentController::GetRayTracingEnabled() const + { + if (m_meshHandle.IsValid() && m_meshFeatureProcessor) + { + return m_meshFeatureProcessor->GetRayTracingEnabled(m_meshHandle); + } + + return false; + } + Aabb MeshComponentController::GetWorldBounds() { if (const AZ::Aabb localBounds = GetLocalBounds(); localBounds.IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 4d09b0b7b6..76cf6a1b39 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -116,6 +116,9 @@ namespace AZ void SetVisibility(bool visible) override; bool GetVisibility() const override; + void SetRayTracingEnabled(bool enabled) override; + bool GetRayTracingEnabled() const override; + // BoundsRequestBus and MeshComponentRequestBus overrides ... AZ::Aabb GetWorldBounds() override; AZ::Aabb GetLocalBounds() override; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 58b3d8b56e..bb467b2259 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -376,7 +376,25 @@ namespace AZ::Render bool AtomActorInstance::GetVisibility() const { - return IsVisible(); + return IsVisible(); + } + + void AtomActorInstance::SetRayTracingEnabled(bool enabled) + { + if (m_meshHandle->IsValid() && m_meshFeatureProcessor) + { + m_meshFeatureProcessor->SetRayTracingEnabled(*m_meshHandle, enabled); + } + } + + bool AtomActorInstance::GetRayTracingEnabled() const + { + if (m_meshHandle->IsValid() && m_meshFeatureProcessor) + { + return m_meshFeatureProcessor->GetRayTracingEnabled(*m_meshHandle); + } + + return false; } AZ::u32 AtomActorInstance::GetJointCount() diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index 7f646466a5..73d428216c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -152,6 +152,8 @@ namespace AZ float GetQualityDecayRate() const override; void SetVisibility(bool visible) override; bool GetVisibility() const override; + void SetRayTracingEnabled(bool enabled) override; + bool GetRayTracingEnabled() const override; // GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Vegetation/Code/Tests/VegetationMocks.h b/Gems/Vegetation/Code/Tests/VegetationMocks.h index ece0833433..3361afa177 100644 --- a/Gems/Vegetation/Code/Tests/VegetationMocks.h +++ b/Gems/Vegetation/Code/Tests/VegetationMocks.h @@ -444,6 +444,15 @@ namespace UnitTest m_GetVisibilityOutput = visibility; } + void SetRayTracingEnabled([[maybe_unused]] bool enabled) override + { + } + + bool GetRayTracingEnabled() const override + { + return false; + } + AZ::Data::AssetId m_assetIdOutput; void SetModelAssetId(AZ::Data::AssetId modelAssetId) override { From a6feef3563a6731c15ecb4090855027a0aae26b8 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 14 Jan 2022 16:51:46 -0600 Subject: [PATCH 07/36] Atom Tools: Created base class for document-based applications Moving some duplicated code to a common base class Signed-off-by: Guthrie Adams --- .../Document/AtomToolsDocumentApplication.h | 28 ++++++++++++++++ .../Document/AtomToolsDocumentApplication.cpp | 33 +++++++++++++++++++ .../Code/atomtoolsframework_files.cmake | 2 ++ .../Code/Source/MaterialEditorApplication.cpp | 18 +--------- .../Code/Source/MaterialEditorApplication.h | 13 +++----- .../ShaderManagementConsoleApplication.cpp | 19 +---------- .../ShaderManagementConsoleApplication.h | 13 +++----- 7 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h new file mode 100644 index 0000000000..7b9327337c --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h @@ -0,0 +1,28 @@ +/* + * 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 + * + */ + +#pragma once + +#include + +namespace AtomToolsFramework +{ + class AtomToolsDocumentApplication + : public AtomToolsApplication + { + public: + AZ_TYPE_INFO(AtomToolsDocumentApplication, "{F4B43677-EB95-4CBB-8B8E-9EF4247E6F0D}"); + + using Base = AtomToolsApplication; + + AtomToolsDocumentApplication(int* argc, char*** argv); + + // AtomToolsApplication overrides... + void ProcessCommandLine(const AZ::CommandLine& commandLine) override; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp new file mode 100644 index 0000000000..beb414bb6c --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentApplication.cpp @@ -0,0 +1,33 @@ +/* + * 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 +#include + +namespace AtomToolsFramework +{ + AtomToolsDocumentApplication::AtomToolsDocumentApplication(int* argc, char*** argv) + : Base(argc, argv) + { + } + + void AtomToolsDocumentApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) + { + // Process command line options for opening documents on startup + size_t openDocumentCount = commandLine.GetNumMiscValues(); + for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) + { + const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); + + AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); + AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); + } + + Base::ProcessCommandLine(commandLine); + } +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 3ddcc05245..4f0e0d34e7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -12,6 +12,7 @@ set(FILES Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/Document/AtomToolsDocument.h + Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h @@ -40,6 +41,7 @@ set(FILES Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp Source/Document/AtomToolsDocument.cpp + Source/Document/AtomToolsDocumentApplication.cpp Source/Document/AtomToolsDocumentMainWindow.cpp Source/Document/AtomToolsDocumentSystemSettings.cpp Source/Document/AtomToolsDocumentSystemComponent.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index cec882cabb..15a5ff1715 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ namespace MaterialEditor } MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv) - : AtomToolsApplication(argc, argv) + : Base(argc, argv) { QApplication::setApplicationName("O3DE Material Editor"); @@ -58,19 +57,4 @@ namespace MaterialEditor { return AZStd::vector({ "passes/", "config/", "MaterialEditor/" }); } - - void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) - { - // Process command line options for opening one or more material documents on startup - size_t openDocumentCount = commandLine.GetNumMiscValues(); - for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) - { - const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); - - AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); - } - - Base::ProcessCommandLine(commandLine); - } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index e91bce48f0..bf2e6f6ca1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -8,30 +8,27 @@ #pragma once -#include -#include +#include namespace MaterialEditor { class MaterialThumbnailRenderer; class MaterialEditorApplication - : public AtomToolsFramework::AtomToolsApplication + : public AtomToolsFramework::AtomToolsDocumentApplication { public: AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}"); - using Base = AtomToolsFramework::AtomToolsApplication; + using Base = AtomToolsFramework::AtomToolsDocumentApplication; MaterialEditorApplication(int* argc, char*** argv); - ////////////////////////////////////////////////////////////////////////// - // AzFramework::Application + // AzFramework::Application overrides... void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - private: - void ProcessCommandLine(const AZ::CommandLine& commandLine) override; + // AtomToolsFramework::AtomToolsApplication overrides... AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; }; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index 3d07a0de15..a242716b52 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -36,7 +35,7 @@ namespace ShaderManagementConsole } ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv) - : AtomToolsApplication(argc, argv) + : Base(argc, argv) { QApplication::setApplicationName("O3DE Shader Management Console"); @@ -56,20 +55,4 @@ namespace ShaderManagementConsole { return AZStd::vector({ "passes/", "config/" }); } - - void ShaderManagementConsoleApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) - { - // Process command line options for opening one or more documents on startup - size_t openDocumentCount = commandLine.GetNumMiscValues(); - for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) - { - const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); - - AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str()); - AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( - &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); - } - - Base::ProcessCommandLine(commandLine); - } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h index 6596429577..6b0365e6bd 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.h @@ -8,28 +8,25 @@ #pragma once -#include -#include +#include namespace ShaderManagementConsole { class ShaderManagementConsoleApplication - : public AtomToolsFramework::AtomToolsApplication + : public AtomToolsFramework::AtomToolsDocumentApplication { public: AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}"); - using Base = AtomToolsFramework::AtomToolsApplication; + using Base = AtomToolsFramework::AtomToolsDocumentApplication; ShaderManagementConsoleApplication(int* argc, char*** argv); - ////////////////////////////////////////////////////////////////////////// - // AzFramework::Application + // AzFramework::Application overrides... void CreateStaticModules(AZStd::vector& outModules) override; const char* GetCurrentConfigurationName() const override; - private: - void ProcessCommandLine(const AZ::CommandLine& commandLine); + // AtomToolsFramework::AtomToolsApplication overrides... AZStd::string GetBuildTargetName() const override; AZStd::vector GetCriticalAssetFilters() const override; }; From 75a582972c7d2263dd4cac1ef684de12b7be575e Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 14 Jan 2022 18:27:11 -0600 Subject: [PATCH 08/36] Atom Tools: added function to get the number of active documents Signed-off-by: Guthrie Adams --- .../Document/AtomToolsDocumentSystemRequestBus.h | 3 +++ .../Source/Document/AtomToolsDocumentSystemComponent.cpp | 6 ++++++ .../Code/Source/Document/AtomToolsDocumentSystemComponent.h | 1 + 3 files changed, 10 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h index f751915a9a..b12cf5e580 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h @@ -71,6 +71,9 @@ namespace AtomToolsFramework //! Save all documents virtual bool SaveAllDocuments() = 0; + + //! Get number of allocated documents + virtual AZ::u32 GetDocumentCount() const = 0; }; using AtomToolsDocumentSystemRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 3b27c9cd0f..d554c68451 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -69,6 +69,7 @@ namespace AtomToolsFramework ->Event("SaveDocumentAsCopy", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsCopy) ->Event("SaveDocumentAsChild", &AtomToolsDocumentSystemRequestBus::Events::SaveDocumentAsChild) ->Event("SaveAllDocuments", &AtomToolsDocumentSystemRequestBus::Events::SaveAllDocuments) + ->Event("GetDocumentCount", &AtomToolsDocumentSystemRequestBus::Events::GetDocumentCount) ; behaviorContext->EBus("AtomToolsDocumentRequestBus") @@ -457,6 +458,11 @@ namespace AtomToolsFramework return result; } + AZ::u32 AtomToolsDocumentSystemComponent::GetDocumentCount() const + { + return aznumeric_cast(m_documentMap.size()); + } + AZ::Uuid AtomToolsDocumentSystemComponent::OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen) { AZStd::string requestedPath = sourcePath; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h index 532271974c..58470e3582 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -74,6 +74,7 @@ namespace AtomToolsFramework bool SaveDocumentAsCopy(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; bool SaveDocumentAsChild(const AZ::Uuid& documentId, AZStd::string_view targetPath) override; bool SaveAllDocuments() override; + AZ::u32 GetDocumentCount() const override; //////////////////////////////////////////////////////////////////////// AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen); From ced7d1ef542f1e1fe58c7c0577151db7aea0461e Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 17 Jan 2022 01:29:23 -0600 Subject: [PATCH 09/36] Atom Tools: Bind exit function for python tests Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.h | 1 + .../Code/Source/Application/AtomToolsApplication.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 9eaacbfa4f..35d8302b49 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -111,6 +111,7 @@ namespace AtomToolsFramework virtual void ProcessCommandLine(const AZ::CommandLine& commandLine); static void PyIdleWaitFrames(uint32_t frames); + static void PyExit(); AzToolsFramework::TraceLogger m_traceLogger; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 02248fffd4..5d17e758f9 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -130,10 +130,13 @@ namespace AtomToolsFramework ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "atomtools.general"); }; - // The reflection here is based on patterns in CryEditPythonHandler::Reflect + addGeneral(behaviorContext->Method( "idle_wait_frames", &AtomToolsApplication::PyIdleWaitFrames, nullptr, "Waits idling for a frames. Primarily used for auto-testing.")); + addGeneral(behaviorContext->Method( + "exit", &AtomToolsApplication::PyExit, nullptr, + "Exit application. Primarily used for auto-testing.")); } } @@ -564,4 +567,9 @@ namespace AtomToolsFramework Ticker ticker(&loop, frames); loop.exec(); } + + void AtomToolsApplication::PyExit() + { + AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop); + } } // namespace AtomToolsFramework From 1cfa4a9bd5677bd65d39353d0e69f23edfb5eb22 Mon Sep 17 00:00:00 2001 From: windbagjacket Date: Mon, 17 Jan 2022 10:00:07 +0000 Subject: [PATCH 10/36] Removed tab usage. Signed-off-by: windbagjacket --- .../EMotionFXAtom/Code/Source/AtomActorInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index bb467b2259..742031c84f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -376,7 +376,7 @@ namespace AZ::Render bool AtomActorInstance::GetVisibility() const { - return IsVisible(); + return IsVisible(); } void AtomActorInstance::SetRayTracingEnabled(bool enabled) From 74623bb1d7c56f5a91ccaa40b8b1de1538aaa462 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 18 Jan 2022 10:21:54 -0600 Subject: [PATCH 11/36] Removed some more unused Editor code and images Signed-off-by: Chris Galvan --- .../PropertyGenericCtrl.cpp | 1 - Code/Editor/CrtDebug.cpp | 170 ------- Code/Editor/CryEdit.cpp | 16 - Code/Editor/CryEdit.h | 1 - Code/Editor/CryEditDoc.cpp | 26 +- Code/Editor/CryEditDoc.h | 3 - Code/Editor/CryEditLiveCreate.rc | 213 -------- Code/Editor/DimensionsDialog.cpp | 71 --- Code/Editor/DimensionsDialog.h | 47 -- Code/Editor/DimensionsDialog.ui | 120 ----- Code/Editor/GameEngine.cpp | 2 - Code/Editor/MainWindow.qrc | 30 -- Code/Editor/NewLevelDialog.cpp | 3 - Code/Editor/NewTerrainDialog.cpp | 168 ------- Code/Editor/NewTerrainDialog.h | 71 --- Code/Editor/NewTerrainDialog.ui | 112 ----- Code/Editor/PakManagerDlg.qrc | 6 - Code/Editor/PakManagerDlg.ui | 202 -------- Code/Editor/SelectEAXPresetDlg.cpp | 67 --- Code/Editor/SelectEAXPresetDlg.h | 43 -- Code/Editor/SelectEAXPresetDlg.ui | 67 --- Code/Editor/SurfaceTypeValidator.cpp | 23 - Code/Editor/SurfaceTypeValidator.h | 24 - Code/Editor/UndoViewPosition.cpp | 67 --- Code/Editor/UndoViewPosition.h | 36 -- Code/Editor/UndoViewRotation.cpp | 78 --- Code/Editor/UndoViewRotation.h | 39 -- Code/Editor/UserMessageDefines.h | 60 --- Code/Editor/ViewPane.cpp | 1 - Code/Editor/WipFeatureManager.cpp | 454 ------------------ Code/Editor/WipFeatureManager.h | 162 ------- Code/Editor/WipFeaturesDlg.cpp | 239 --------- Code/Editor/WipFeaturesDlg.h | 58 --- Code/Editor/WipFeaturesDlg.qrc | 5 - Code/Editor/WipFeaturesDlg.ui | 184 ------- Code/Editor/arhitype_tree_00.png | 3 - Code/Editor/arhitype_tree_01.png | 3 - Code/Editor/arhitype_tree_02.png | 3 - Code/Editor/arhitype_tree_03.png | 3 - Code/Editor/bmp00005_00.png | 3 - Code/Editor/bmp00005_01.png | 3 - Code/Editor/bmp00005_02.png | 3 - Code/Editor/bmp00005_03.png | 3 - Code/Editor/bmp00005_04.png | 3 - Code/Editor/bmp00005_05.png | 3 - Code/Editor/bmp00005_06.png | 3 - Code/Editor/bmp00005_07.png | 3 - Code/Editor/bmp00005_08.png | 3 - Code/Editor/bmp00005_09.png | 3 - Code/Editor/bmp00006_00.png | 3 - Code/Editor/bmp00006_01.png | 3 - Code/Editor/bmp00006_02.png | 3 - Code/Editor/bmp00006_03.png | 3 - Code/Editor/bmp00006_04.png | 3 - Code/Editor/bmp00006_05.png | 3 - Code/Editor/bmp00006_06.png | 3 - Code/Editor/bmp00006_07.png | 3 - Code/Editor/editor_lib_files.cmake | 20 - Code/Editor/particles_tree_00.png | 3 - Code/Editor/particles_tree_01.png | 3 - Code/Editor/particles_tree_02.png | 3 - Code/Editor/particles_tree_03.png | 3 - Code/Editor/particles_tree_04.png | 3 - Code/Editor/particles_tree_05.png | 3 - Code/Editor/particles_tree_06.png | 3 - Code/Editor/particles_tree_07.png | 3 - 66 files changed, 1 insertion(+), 2978 deletions(-) delete mode 100644 Code/Editor/CrtDebug.cpp delete mode 100644 Code/Editor/CryEditLiveCreate.rc delete mode 100644 Code/Editor/DimensionsDialog.cpp delete mode 100644 Code/Editor/DimensionsDialog.h delete mode 100644 Code/Editor/DimensionsDialog.ui delete mode 100644 Code/Editor/NewTerrainDialog.cpp delete mode 100644 Code/Editor/NewTerrainDialog.h delete mode 100644 Code/Editor/NewTerrainDialog.ui delete mode 100644 Code/Editor/PakManagerDlg.qrc delete mode 100644 Code/Editor/PakManagerDlg.ui delete mode 100644 Code/Editor/SelectEAXPresetDlg.cpp delete mode 100644 Code/Editor/SelectEAXPresetDlg.h delete mode 100644 Code/Editor/SelectEAXPresetDlg.ui delete mode 100644 Code/Editor/SurfaceTypeValidator.cpp delete mode 100644 Code/Editor/SurfaceTypeValidator.h delete mode 100644 Code/Editor/UndoViewPosition.cpp delete mode 100644 Code/Editor/UndoViewPosition.h delete mode 100644 Code/Editor/UndoViewRotation.cpp delete mode 100644 Code/Editor/UndoViewRotation.h delete mode 100644 Code/Editor/UserMessageDefines.h delete mode 100644 Code/Editor/WipFeatureManager.cpp delete mode 100644 Code/Editor/WipFeatureManager.h delete mode 100644 Code/Editor/WipFeaturesDlg.cpp delete mode 100644 Code/Editor/WipFeaturesDlg.h delete mode 100644 Code/Editor/WipFeaturesDlg.qrc delete mode 100644 Code/Editor/WipFeaturesDlg.ui delete mode 100644 Code/Editor/arhitype_tree_00.png delete mode 100644 Code/Editor/arhitype_tree_01.png delete mode 100644 Code/Editor/arhitype_tree_02.png delete mode 100644 Code/Editor/arhitype_tree_03.png delete mode 100644 Code/Editor/bmp00005_00.png delete mode 100644 Code/Editor/bmp00005_01.png delete mode 100644 Code/Editor/bmp00005_02.png delete mode 100644 Code/Editor/bmp00005_03.png delete mode 100644 Code/Editor/bmp00005_04.png delete mode 100644 Code/Editor/bmp00005_05.png delete mode 100644 Code/Editor/bmp00005_06.png delete mode 100644 Code/Editor/bmp00005_07.png delete mode 100644 Code/Editor/bmp00005_08.png delete mode 100644 Code/Editor/bmp00005_09.png delete mode 100644 Code/Editor/bmp00006_00.png delete mode 100644 Code/Editor/bmp00006_01.png delete mode 100644 Code/Editor/bmp00006_02.png delete mode 100644 Code/Editor/bmp00006_03.png delete mode 100644 Code/Editor/bmp00006_04.png delete mode 100644 Code/Editor/bmp00006_05.png delete mode 100644 Code/Editor/bmp00006_06.png delete mode 100644 Code/Editor/bmp00006_07.png delete mode 100644 Code/Editor/particles_tree_00.png delete mode 100644 Code/Editor/particles_tree_01.png delete mode 100644 Code/Editor/particles_tree_02.png delete mode 100644 Code/Editor/particles_tree_03.png delete mode 100644 Code/Editor/particles_tree_04.png delete mode 100644 Code/Editor/particles_tree_05.png delete mode 100644 Code/Editor/particles_tree_06.png delete mode 100644 Code/Editor/particles_tree_07.png diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp index 8ff83dd894..9609fb5014 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp @@ -24,7 +24,6 @@ // Editor #include "SelectLightAnimationDialog.h" #include "SelectSequenceDialog.h" -#include "SelectEAXPresetDlg.h" #include "QtViewPaneManager.h" AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING diff --git a/Code/Editor/CrtDebug.cpp b/Code/Editor/CrtDebug.cpp deleted file mode 100644 index f9335373da..0000000000 --- a/Code/Editor/CrtDebug.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 "EditorDefs.h" - - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -//#ifdef _CRTDBG_MAP_ALLOC -#ifdef CRTDBG_MAP_ALLOC -#pragma pack (push,1) -#define nNoMansLandSize 4 -typedef struct MyCrtMemBlockHeader -{ - struct MyCrtMemBlockHeader* pBlockHeaderNext; - struct MyCrtMemBlockHeader* pBlockHeaderPrev; - char* szFileName; - int nLine; - size_t nDataSize; - int nBlockUse; - long lRequest; - unsigned char gap[nNoMansLandSize]; - /* followed by: - * unsigned char data[nDataSize]; - * unsigned char anotherGap[nNoMansLandSize]; - */ -} MyCrtMemBlockHeader; -#pragma pack (pop) - -#define pbData(pblock) ((unsigned char*)((MyCrtMemBlockHeader*)pblock + 1)) -#define pHdr(pbData) (((MyCrtMemBlockHeader*)pbData) - 1) - - -void crtdebug(const char* s, ...) -{ - char str[32768]; - va_list arg_ptr; - va_start(arg_ptr, s); - vsprintf(str, s, arg_ptr); - va_end(arg_ptr); - - FILE* l = nullptr; - azfopen(&l, "crtdump.txt", "a+t"); - if (l) - { - fprintf(l, "%s", str); - fclose(l); - } -} - -int crtAllocHook(int nAllocType, void* pvData, - size_t nSize, int nBlockUse, long lRequest, - const unsigned char* szFileName, int nLine) -{ - if (nBlockUse == _CRT_BLOCK) - { - return TRUE; - } - - static int total_cnt = 0; - static int total_mem = 0; - if (nAllocType == _HOOK_ALLOC) - { - //total_mem += nSize; - //total_cnt++; - //_CrtMemState mem_state; - //_CrtMemCheckpoint( &mem_state ); - //total_cnt = mem_state.lCounts[_NORMAL_BLOCK]; - //total_mem = mem_state.lTotalCount; - if ((total_cnt & 0xF) == 0) - { - //_CrtCheckMemory(); - } - - total_cnt++; - total_mem += nSize; - - //crtdebug( " Alloc %d,size=%d,in: %s %d (total size=%d,num=%d)\n",lRequest,nSize,szFileName,nLine,total_mem,total_cnt ); - crtdebug("Size=%d, [Total=%d,N=%d] [%s:%d]\n", nSize, total_mem, total_cnt, szFileName, nLine); - } - else if (nAllocType == _HOOK_FREE) - { - MyCrtMemBlockHeader* pHead; - pHead = pHdr(pvData); - - total_cnt--; - total_mem -= pHead->nDataSize; - - crtdebug("Size=%d, [Total=%d,N=%d] [%s:%d]\n", pHead->nDataSize, total_mem, total_cnt, pHead->szFileName, pHead->nLine); - //crtdebug( " Free size=%d,in: %s %d (total size=%d,num=%d)\n",pHead->nDataSize,pHead->szFileName,pHead->nLine,total_mem,total_cnt ); - //total_mem -= nSize; - //total_cnt--; - } - return TRUE; -} - -int crtReportHook(int nRptType, char* szMsg, int* retVal) -{ - static int gl_num_asserts = 0; - if (gl_num_asserts != 0) - { - return TRUE; - } - gl_num_asserts++; - switch (nRptType) - { - case _CRT_WARN: - crtdebug(" %s\n", szMsg); - break; - case _CRT_ERROR: - crtdebug(" %s\n", szMsg); - break; - case _CRT_ASSERT: - crtdebug(" %s\n", szMsg); - break; - } - gl_num_asserts--; - return TRUE; -} - -void InitCrt() -{ - FILE* l = nullptr; - azfopen(&l, "crtdump.txt", "w"); - if (l) - { - fclose(l); - } - - //_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG ); - //_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG ); - //_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG ); - - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW); - - //_CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF|_CRTDBG_DELAY_FREE_MEM_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) ); - //_CrtSetDbgFlag( _CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF/*|_CRTDBG_DELAY_FREE_MEM_DF*/ | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) ); - int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flags &= ~_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_CRT_DF; - - _CrtSetDbgFlag(flags); - - _CrtSetAllocHook (crtAllocHook); - _CrtSetReportHook(crtReportHook); -} - -void DoneCrt() -{ - //_CrtCheckMemory(); - //_CrtDumpMemoryLeaks(); -} - -// Autoinit CRT. -//struct __autoinit_crt { __autoinit_crt() { InitCrt(); }; ~__autoinit_crt() { DoneCrt(); } } __autoinit_crt_var; -#endif - - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 1c4e22b99e..3beaf4d438 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -124,9 +124,6 @@ AZ_POP_DISABLE_WARNING #include "ScopedVariableSetter.h" #include "Util/3DConnexionDriver.h" - -#include "DimensionsDialog.h" - #include "Util/AutoDirectoryRestoreFileDialog.h" #include "Util/EditorAutoLevelLoadTest.h" #include "AboutDialog.h" @@ -1806,12 +1803,6 @@ bool CCryEditApp::InitInstance() InitLevel(cmdInfo); }); -#ifdef USE_WIP_FEATURES_MANAGER - // load the WIP features file - CWipFeatureManager::Instance()->EnableManager(!cmdInfo.m_bDeveloperMode); - CWipFeatureManager::Init(); -#endif - if (!m_bConsoleMode && !m_bPreviewMode) { GetIEditor()->UpdateViews(); @@ -2142,13 +2133,6 @@ int CCryEditApp::ExitInstance(int exitCode) } qobject_cast(qApp)->UnloadSettings(); - #ifdef USE_WIP_FEATURES_MANAGER - // - // close wip features manager - // - CWipFeatureManager::Shutdown(); - #endif - if (IsInRegularEditorMode()) { if (GetIEditor()) diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h index 97fcde8f34..48f362003c 100644 --- a/Code/Editor/CryEdit.h +++ b/Code/Editor/CryEdit.h @@ -14,7 +14,6 @@ #if !defined(Q_MOC_RUN) #include #include -#include "WipFeatureManager.h" #include "CryEditDoc.h" #include "ViewPane.h" diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 3bcba4d5e0..9d93fd5f5b 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -45,7 +45,6 @@ #include "ActionManager.h" #include "Include/IObjectManager.h" #include "ErrorReportDialog.h" -#include "SurfaceTypeValidator.h" #include "Util/AutoLogTime.h" #include "CheckOutDialog.h" #include "GameExporter.h" @@ -99,8 +98,7 @@ namespace Internal // CCryEditDoc construction/destruction CCryEditDoc::CCryEditDoc() - : doc_validate_surface_types(nullptr) - , m_modifiedModuleFlags(eModifiedNothing) + : m_modifiedModuleFlags(eModifiedNothing) { //////////////////////////////////////////////////////////////////////// // Set member variables to initial values @@ -120,7 +118,6 @@ CCryEditDoc::CCryEditDoc() GetIEditor()->SetDocument(this); CLogFile::WriteLine("Document created"); - RegisterConsoleVariables(); MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_AS, this, &CCryEditDoc::OnFileSaveAs); bool isPrefabSystemEnabled = false; @@ -459,8 +456,6 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) } } - CSurfaceTypeValidator().Validate(); - LogLoadTime(GetTickCount() - t0); // Loaded with success, remove event from log file GetIEditor()->GetSettingsManager()->UnregisterEvent(loadEvent); @@ -1910,25 +1905,6 @@ void CCryEditDoc::SetDocumentReady(bool bReady) m_bDocumentReady = bReady; } -void CCryEditDoc::RegisterConsoleVariables() -{ - doc_validate_surface_types = gEnv->pConsole->GetCVar("doc_validate_surface_types"); - - if (!doc_validate_surface_types) - { - doc_validate_surface_types = REGISTER_INT_CB("doc_validate_surface_types", 0, 0, - "Flag indicating whether icons are displayed on the animation graph.\n" - "Default is 1.\n", - OnValidateSurfaceTypesChanged); - } -} - -void CCryEditDoc::OnValidateSurfaceTypesChanged(ICVar*) -{ - CErrorsRecorder errorsRecorder(GetIEditor()); - CSurfaceTypeValidator().Validate(); -} - void CCryEditDoc::OnStartLevelResourceList() { // after loading another level we clear the RFOM_Level list, the first time the list should be empty diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h index f7e97d308e..5d20bddf45 100644 --- a/Code/Editor/CryEditDoc.h +++ b/Code/Editor/CryEditDoc.h @@ -176,9 +176,7 @@ protected: virtual void OnFileSaveAs(); //! called immediately after saving the level. void AfterSave(); - void RegisterConsoleVariables(); void OnStartLevelResourceList(); - static void OnValidateSurfaceTypesChanged(ICVar*); QString GetCryIndexPath(const char* levelFilePath) const; @@ -194,7 +192,6 @@ protected: XmlNodeRef m_environmentTemplate; std::list m_listeners; bool m_bDocumentReady = false; - ICVar* doc_validate_surface_types = nullptr; int m_modifiedModuleFlags; // On construction, it assumes loaded levels have already been exported. Can be a big fat lie, though. // The right way would require us to save to the level folder the export status of the level. diff --git a/Code/Editor/CryEditLiveCreate.rc b/Code/Editor/CryEditLiveCreate.rc deleted file mode 100644 index 3dac96d682..0000000000 --- a/Code/Editor/CryEditLiveCreate.rc +++ /dev/null @@ -1,213 +0,0 @@ -ÿþ// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "#include ""resource.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU_LIVECREATE MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "Save settings", ID_FILE_SAVESETTINGS - MENUITEM "Close", ID_FILE_CLOSE_LIVECREATE_VIEW - END - POPUP "&View" - BEGIN - MENUITEM "LiveCreate Logger", ID_VIEW_LIVECREATELOGGER, CHECKED - MENUITEM "LiveCreate Profile Editor", ID_VIEW_LIVECREATEPROFILEEDITOR, CHECKED - MENUITEM "LiveCreate File Sync Settings", ID_VIEW_LIVECREATEFILESYNCSETTINGS, CHECKED - END -END - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_LIVECREATE_PICKER DIALOGEX 0, 0, 316, 259 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Select game build directory" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,200,238,50,14 - PUSHBUTTON "Cancel",IDCANCEL,259,238,50,14 - CONTROL "",IDC_DIRECTORY_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,7,302,227 -END - -IDD_LIVECREATE_ADD_TARGETS DIALOGEX 0, 0, 500, 400 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Discover LiveCreate targets" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - PUSHBUTTON "Refresh",IDC_REFRESH,8,8,70,18 - PUSHBUTTON "Add custom...",IDC_BUTTON_ADD_PEER,82,8,70,18 - CONTROL "Use wider search (broadcast)",IDC_CHECK_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,233,12,200,10 - CONTROL "",IDC_LIST_PEERS,"XTPReport",WS_TABSTOP,8,32,484,342,WS_EX_STATICEDGE - DEFPUSHBUTTON "Use selected",IDOK,180,379,70,18 - PUSHBUTTON "Cancel",IDCANCEL,259,379,70,18 - PUSHBUTTON "Add by IP...",IDC_BUTTON_ADD_MATERIAL,157,8,70,18 -END - -IDD_LIVECREATE_PEER_LIST DIALOGEX 0, 0, 395, 213 -STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_SYSMENU -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - LTEXT "Peers:",IDC_STATIC,17,27,22,8 - PUSHBUTTON "Add...",IDC_BUTTON_ADD_PEER,56,24,56,16 - PUSHBUTTON "Edit...",IDC_BUTTON_EDIT_PEER,116,24,56,16 - PUSHBUTTON "Remove",IDC_BUTTON_DELETE_PEER,176,24,52,16 - DEFPUSHBUTTON "Start All",IDC_BUTTON_START_ALL,4,4,48,16 - PUSHBUTTON "Reset All",IDC_BUTTON_RESET_ALL,176,4,52,16 - PUSHBUTTON "Force Sync All",IDC_BUTTON_FORCE_SYNC_ALL,56,4,56,16 - PUSHBUTTON "Clean All",IDC_BUTTON_CLEAN_ALL,232,4,52,16 - PUSHBUTTON "Screenshot All",IDC_BUTTON_SCREENSHOT_ALL,116,4,56,16 - CONTROL "",IDC_LIST_PEERS,"XTPReport",WS_TABSTOP,4,44,386,164,WS_EX_STATICEDGE - CHECKBOX "LiveCreate",IDC_BUTTON_ENABLE_LIVECREATE,288,4,52,36,BS_PUSHLIKE | BS_MULTILINE - CHECKBOX "Sync\nCamera",IDC_BUTTON_CAMERA_SYNC,345,4,52,36,BS_PUSHLIKE | BS_MULTILINE - PUSHBUTTON "Discover",IDC_BUTTON_DISCOVER_PEERS,232,24,52,16 -END - -IDD_IDD_LIVECREATE_SETTINGS_PANEL DIALOGEX 0, 0, 156, 204 -STYLE DS_SETFONT | WS_CHILD -FONT 8, "MS Shell Dlg 2", 400, 0, 0x1 -BEGIN - PUSHBUTTON "Add targets...",IDC_BUTTON_DISCOVER_PEERS,4,4,80,16 -END - -IDD_LIVECREATE_EDIT_CONNECTION DIALOGEX 0, 0, 288, 183 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "LiveCreate host settings" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,158,154,58,20 - PUSHBUTTON "Cancel",IDCANCEL,221,154,58,20 - LTEXT "Name:",IDC_STATIC,16,46,22,8 - EDITTEXT IDC_EDIT_TARGET_NAME,44,44,100,14,ES_AUTOHSCROLL - LTEXT "IP:",IDC_STATIC,152,46,10,8 - CONTROL "",IDC_TARGET_IPADDRESS,"SysIPAddress32",WS_TABSTOP,168,44,100,15 - LTEXT "Platform:",IDC_STATIC,8,26,30,8 - LTEXT "Build path (automatic):",IDC_STATIC,19,120,74,8 - PUSHBUTTON "Test IP",IDC_BUTTON_TEST_CONNECTION,168,60,100,16 - COMBOBOX IDC_COMBO_PLATFORM,44,24,100,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Resovle name to IP",IDC_BUTTON_REFRESH_IP,44,60,100,16 - CONTROL "Enable this peer",IDC_CHECK_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,8,67,10 - GROUPBOX "Build settings",IDC_STATIC,7,80,272,71 - LTEXT "Build executable:",IDC_STATIC,19,92,56,8 - PUSHBUTTON "...",IDC_BUTTON_PICK_GAME_DIRECTORY,249,104,22,14 - EDITTEXT IDC_EDIT_BUILD_ROOT_PATH,20,104,226,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT_BUILD_EXECUTABLE,20,131,249,14,ES_AUTOHSCROLL -END - -IDD_LIVECREATE_TASK_WAIT DIALOGEX 0, 0, 238, 41 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Dialog" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - PUSHBUTTON "Cancel",IDCANCEL,94,20,50,14 - LTEXT "Static",IDC_TASK_PROGRESS_TEXT,7,7,224,8 -END - -IDD_LIVECREATE_ADD_BY_IP DIALOGEX 0, 0, 137, 75 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Add LiveCreate by IP" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,7,48,58,20 - PUSHBUTTON "Cancel",IDCANCEL,71,48,58,20 - LTEXT "IP:",-1,9,12,10,8 - EDITTEXT IDC_TARGET_IPADDRESS,25,10,100,15,WS_TABSTOP - PUSHBUTTON "Test IP",IDC_BUTTON_TEST_CONNECTION,25,27,100,16 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_LIVECREATE_ADD_TARGETS, DIALOG - BEGIN - END - - IDD_LIVECREATE_EDIT_CONNECTION, DIALOG - BEGIN - END - - IDD_LIVECREATE_TASK_WAIT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 231 - TOPMARGIN, 7 - BOTTOMMARGIN, 34 - END - - IDD_LIVECREATE_ADD_BY_IP, DIALOG - BEGIN - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED \ No newline at end of file diff --git a/Code/Editor/DimensionsDialog.cpp b/Code/Editor/DimensionsDialog.cpp deleted file mode 100644 index 6c8e6a616b..0000000000 --- a/Code/Editor/DimensionsDialog.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "DimensionsDialog.h" - -// Qt -#include - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - - -///////////////////////////////////////////////////////////////////////////// -CDimensionsDialog::CDimensionsDialog(QWidget* pParent /*=nullptr*/) - : QDialog(pParent) - , m_group(new QButtonGroup(this)) - , ui(new Ui::CDimensionsDialog) -{ - ui->setupUi(this); - - setWindowTitle(tr("Generate Terrain Texture")); - - m_group->addButton(ui->Dim512, 512); - m_group->addButton(ui->Dim1024, 1024); - m_group->addButton(ui->Dim2048, 2048); - m_group->addButton(ui->Dim4096, 4096); - m_group->addButton(ui->Dim8192, 8192); - m_group->addButton(ui->Dim16384, 16384); -} - - -////////////////////////////////////////////////////////////////////////// -CDimensionsDialog::~CDimensionsDialog() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CDimensionsDialog::SetDimensions(unsigned int iWidth) -{ - //////////////////////////////////////////////////////////////////////// - // Select a dimension option button in the dialog - //////////////////////////////////////////////////////////////////////// - - QAbstractButton* button = m_group->button(iWidth); - assert(button); - - button->setChecked(true); -} - -UINT CDimensionsDialog::GetDimensions() -{ - //////////////////////////////////////////////////////////////////////// - // Get the currently selected dimension option button in the dialog - //////////////////////////////////////////////////////////////////////// - - assert(m_group->checkedId() != -1); - - return m_group->checkedId(); -} - -#include diff --git a/Code/Editor/DimensionsDialog.h b/Code/Editor/DimensionsDialog.h deleted file mode 100644 index b94c58bf95..0000000000 --- a/Code/Editor/DimensionsDialog.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 - * - */ - - -#pragma once -#ifndef CRYINCLUDE_EDITOR_DIMENSIONSDIALOG_H -#define CRYINCLUDE_EDITOR_DIMENSIONSDIALOG_H - -#if !defined(Q_MOC_RUN) -#include - -#include -#endif - -class QButtonGroup; - -namespace Ui { - class CDimensionsDialog; -} - -class CDimensionsDialog - : public QDialog -{ - Q_OBJECT - -public: - CDimensionsDialog(QWidget* pParent = nullptr); // standard constructor - ~CDimensionsDialog(); - - UINT GetDimensions(); - void SetDimensions(unsigned int iWidth); - -protected: - void UpdateData(bool fromUi = true); // DDX/DDV support - -private: - QButtonGroup* m_group; - - QScopedPointer ui; -}; - -#endif // CRYINCLUDE_EDITOR_DIMENSIONSDIALOG_H diff --git a/Code/Editor/DimensionsDialog.ui b/Code/Editor/DimensionsDialog.ui deleted file mode 100644 index 316a060c92..0000000000 --- a/Code/Editor/DimensionsDialog.ui +++ /dev/null @@ -1,120 +0,0 @@ - - - CDimensionsDialog - - - - 0 - 0 - 465 - 237 - - - - Qt::StrongFocus - - - - - - Texture Dimensions (Texture Dimensions divided by Terrain Size = Texels per meter) - - - - - - Qt::StrongFocus - - - 512 x 512 - - - true - - - - - - - Qt::StrongFocus - - - 1024 x 1024 - - - - - - - Qt::StrongFocus - - - 2048 x 2048 - - - - - - - Qt::StrongFocus - - - 4096 x 4096 - - - - - - - Qt::StrongFocus - - - 8192 x 8192 - - - - - - - Qt::StrongFocus - - - 16384 x 16384 - - - - - - - - - - Qt::StrongFocus - - - QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - CDimensionsDialog - accept() - - - 77 - 294 - - - 7 - 296 - - - - - diff --git a/Code/Editor/GameEngine.cpp b/Code/Editor/GameEngine.cpp index db4c587f54..9786dcf1b8 100644 --- a/Code/Editor/GameEngine.cpp +++ b/Code/Editor/GameEngine.cpp @@ -42,8 +42,6 @@ #include "ViewManager.h" #include "AnimationContext.h" -#include "UndoViewPosition.h" -#include "UndoViewRotation.h" #include "MainWindow.h" #include "Include/IObjectManager.h" #include "ActionManager.h" diff --git a/Code/Editor/MainWindow.qrc b/Code/Editor/MainWindow.qrc index c68e05ef41..57afc596bb 100644 --- a/Code/Editor/MainWindow.qrc +++ b/Code/Editor/MainWindow.qrc @@ -154,36 +154,6 @@ res/error_report_warning.svg res/error_report_comment.svg res/error_report_helper.svg - particles_tree_00.png - particles_tree_01.png - particles_tree_02.png - particles_tree_03.png - particles_tree_04.png - particles_tree_05.png - particles_tree_06.png - particles_tree_07.png - arhitype_tree_00.png - arhitype_tree_01.png - arhitype_tree_02.png - arhitype_tree_03.png - bmp00005_00.png - bmp00005_01.png - bmp00005_02.png - bmp00005_03.png - bmp00005_04.png - bmp00005_05.png - bmp00005_06.png - bmp00005_07.png - bmp00005_08.png - bmp00005_09.png - bmp00006_00.png - bmp00006_01.png - bmp00006_02.png - bmp00006_03.png - bmp00006_04.png - bmp00006_05.png - bmp00006_06.png - bmp00006_07.png res/arr_addkey.cur diff --git a/Code/Editor/NewLevelDialog.cpp b/Code/Editor/NewLevelDialog.cpp index a97eb30f57..b22d9dbaf3 100644 --- a/Code/Editor/NewLevelDialog.cpp +++ b/Code/Editor/NewLevelDialog.cpp @@ -18,9 +18,6 @@ #include #include -// Editor -#include "NewTerrainDialog.h" - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING diff --git a/Code/Editor/NewTerrainDialog.cpp b/Code/Editor/NewTerrainDialog.cpp deleted file mode 100644 index 0e66482eb4..0000000000 --- a/Code/Editor/NewTerrainDialog.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 - * - */ -// NewTerrainDialog.cpp : implementation file -// - -#include "EditorDefs.h" - -#include "NewTerrainDialog.h" - - -AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") -#include -AZ_POP_DISABLE_WARNING - - - -CNewTerrainDialog::CNewTerrainDialog(QWidget* pParent /*=nullptr*/) - : QDialog(pParent) - , m_terrainResolutionIndex(0) - , m_terrainUnitsIndex(0) - , m_bUpdate(false) - , ui(new Ui::CNewTerrainDialog) - , m_initialized(false) -{ - ui->setupUi(this); - - setWindowTitle(tr("Terrain options")); - - // Default is 1024x1024, and m_terrainResolution holds an index to the combo box - m_terrainResolutionIndex = 3; - - connect(ui->TERRAIN_RESOLUTION, SIGNAL(activated(int)), this, SLOT(OnComboBoxSelectionTerrainResolution())); - connect(ui->TERRAIN_UNITS, SIGNAL(activated(int)), this, SLOT(OnComboBoxSelectionTerrainUnits())); -} - - -CNewTerrainDialog::~CNewTerrainDialog() -{ -} - - -void CNewTerrainDialog::UpdateData(bool fromUi) -{ - if (fromUi) - { - m_terrainResolutionIndex = ui->TERRAIN_RESOLUTION->currentIndex(); - m_terrainUnitsIndex = ui->TERRAIN_UNITS->currentIndex(); - } - else - { - ui->TERRAIN_RESOLUTION->setCurrentIndex(m_terrainResolutionIndex); - ui->TERRAIN_UNITS->setCurrentIndex(m_terrainUnitsIndex); - } -} - - -void CNewTerrainDialog::OnInitDialog() -{ - // Initialize terrain values. - int resolution = Ui::START_TERRAIN_RESOLUTION; - - // Fill terrain resolution combo box - for (int i = 0; i < 6; i++) - { - ui->TERRAIN_RESOLUTION->addItem(QString("%1x%1").arg(resolution)); - resolution *= 2; - } - - UpdateTerrainUnits(); - UpdateTerrainInfo(); - - // Save data. - UpdateData(false); -} - - -void CNewTerrainDialog::UpdateTerrainUnits() -{ - uint32 terrainRes = GetTerrainResolution(); - int size = terrainRes * GetTerrainUnits(); - int maxUnit = IntegerLog2(Ui::MAXIMUM_TERRAIN_RESOLUTION / terrainRes); - int units = Ui::START_TERRAIN_UNITS; - - ui->TERRAIN_UNITS->clear(); - for (int i = 0; i <= maxUnit; i++) - { - ui->TERRAIN_UNITS->addItem(QString::number(units)); - units *= 2; - } - if (size > Ui::MAXIMUM_TERRAIN_RESOLUTION) - { - m_terrainUnitsIndex = 0; - } - ui->TERRAIN_UNITS->setCurrentText(QString::number(m_terrainUnitsIndex)); -} - - -void CNewTerrainDialog::UpdateTerrainInfo() -{ - int sizeX = GetTerrainResolution() * GetTerrainUnits(); - int sizeY = GetTerrainResolution() * GetTerrainUnits(); - - QString str; - if (sizeX >= 1000) - { - str = tr("Terrain Size: %1 x %2 Kilometers").arg((float)sizeX / 1000.0f, 0, 'f', 3).arg((float)sizeY / 1000.0f, 0, 'f', 3); - } - else if (sizeX > 0) - { - str = tr("Terrain Size: %1 x %2 Meters").arg(sizeX).arg(sizeY); - } - else - { - str = tr("Level will have no terrain"); - } - - ui->TERRAIN_INFO->setText(str); -} - - -int CNewTerrainDialog::GetTerrainResolution() const -{ - // convert combo box index into resolution value - return Ui::START_TERRAIN_RESOLUTION * (1 << m_terrainResolutionIndex); -} - - -int CNewTerrainDialog::GetTerrainUnits() const -{ - // convert combo box index into units value - return Ui::START_TERRAIN_UNITS * (1 << m_terrainUnitsIndex); -} - - -void CNewTerrainDialog::OnComboBoxSelectionTerrainResolution() -{ - UpdateData(); - - UpdateTerrainUnits(); - - UpdateTerrainInfo(); -} - - -void CNewTerrainDialog::OnComboBoxSelectionTerrainUnits() -{ - UpdateData(); - - UpdateTerrainInfo(); -} - - -void CNewTerrainDialog::showEvent(QShowEvent* event) -{ - if (!m_initialized) - { - OnInitDialog(); - m_initialized = true; - } - QDialog::showEvent(event); -} - -#include diff --git a/Code/Editor/NewTerrainDialog.h b/Code/Editor/NewTerrainDialog.h deleted file mode 100644 index 8905a8c123..0000000000 --- a/Code/Editor/NewTerrainDialog.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 - * - */ -#pragma once -#ifndef CRYINCLUDE_EDITOR_NEWTERRAINDIALOG_H -#define CRYINCLUDE_EDITOR_NEWTERRAINDIALOG_H - -#if !defined(Q_MOC_RUN) -#include - -#include - -#include -#endif - -namespace Ui -{ - class CNewTerrainDialog; - - enum TerrainDialogConstants - { - START_TERRAIN_RESOLUTION_POWER_OF_TWO = 7, - START_TERRAIN_RESOLUTION = 1 << START_TERRAIN_RESOLUTION_POWER_OF_TWO, - MAXIMUM_TERRAIN_POWER_OF_TWO = 16, - MAXIMUM_TERRAIN_RESOLUTION = 1 << MAXIMUM_TERRAIN_POWER_OF_TWO, - POWER_OFFSET = (MAXIMUM_TERRAIN_POWER_OF_TWO - START_TERRAIN_RESOLUTION_POWER_OF_TWO), - START_TERRAIN_UNITS = 1 - }; -} - -class CNewTerrainDialog - : public QDialog -{ - Q_OBJECT - -public: - CNewTerrainDialog(QWidget* pParent = nullptr); // standard constructor - ~CNewTerrainDialog(); - - int GetTerrainResolution() const; - int GetTerrainUnits() const; - - void IsResize(bool bIsResize); - - -protected: - void UpdateData(bool fromUi = true); - void OnInitDialog(); - - void UpdateTerrainUnits(); - void UpdateTerrainInfo(); - - void showEvent(QShowEvent* event) override; - -protected slots: - void OnComboBoxSelectionTerrainResolution(); - void OnComboBoxSelectionTerrainUnits(); - -public: - int m_terrainResolutionIndex; - int m_terrainUnitsIndex; - bool m_bUpdate; - - QScopedPointer ui; - bool m_initialized; -}; -#endif // CRYINCLUDE_EDITOR_NEWTERRAINDIALOG_H diff --git a/Code/Editor/NewTerrainDialog.ui b/Code/Editor/NewTerrainDialog.ui deleted file mode 100644 index 977db11918..0000000000 --- a/Code/Editor/NewTerrainDialog.ui +++ /dev/null @@ -1,112 +0,0 @@ - - - CNewTerrainDialog - - - - 0 - 0 - 292 - 160 - - - - false - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Heightmap Resolution: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - TERRAIN_RESOLUTION - - - - - - - - - - Meters Per Texel: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - TERRAIN_UNITS - - - - - - - - - - Terrain Size: 32x32 Km - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - - - buttonBox - accepted() - CNewTerrainDialog - accept() - - - 164 - 176 - - - 169 - 1 - - - - - buttonBox - rejected() - CNewTerrainDialog - reject() - - - 245 - 172 - - - 247 - -1 - - - - - diff --git a/Code/Editor/PakManagerDlg.qrc b/Code/Editor/PakManagerDlg.qrc deleted file mode 100644 index bea8f8aafd..0000000000 --- a/Code/Editor/PakManagerDlg.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - res/pakmanager_file.png - res/pakmanager_folder.png - - diff --git a/Code/Editor/PakManagerDlg.ui b/Code/Editor/PakManagerDlg.ui deleted file mode 100644 index 087e5379da..0000000000 --- a/Code/Editor/PakManagerDlg.ui +++ /dev/null @@ -1,202 +0,0 @@ - - - CPakManagerDlg - - - - 0 - 0 - 661 - 494 - - - - - - - - - - 0 - 45 - - - - Open PAK... - - - - - - - - 0 - 45 - - - - Create PAK... - - - - - - - - 0 - 45 - - - - Add files... - - - - - - - - 0 - 45 - - - - Add folder... - - - - - - - - 0 - 45 - - - - Extract... - - - - - - - - 0 - 45 - - - - Delete entries - - - - - - - - 0 - 45 - - - - &Close - - - - - - - - - - - Path: - - - - - - - - 0 - 0 - - - - QFrame::Panel - - - QFrame::Sunken - - - <none> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - QFrame::Box - - - Qt::ScrollBarAlwaysOn - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::SelectItems - - - 120 - - - false - - - - Filename - - - - - Size - - - - - Modified - - - - - - - - Ready - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - Qt::AlignCenter - - - - - - - - - - diff --git a/Code/Editor/SelectEAXPresetDlg.cpp b/Code/Editor/SelectEAXPresetDlg.cpp deleted file mode 100644 index 733de8b9cf..0000000000 --- a/Code/Editor/SelectEAXPresetDlg.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "SelectEAXPresetDlg.h" - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include "ui_SelectEAXPresetDlg.h" -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - -CSelectEAXPresetDlg::CSelectEAXPresetDlg(QWidget* pParent) - : QDialog(pParent) - , m_ui(new Ui_CSelectEAXPresetDlg) -{ - m_ui->setupUi(this); -} - -CSelectEAXPresetDlg::~CSelectEAXPresetDlg() -{ -} - -void CSelectEAXPresetDlg::SetCurrPreset(const QString& sPreset) -{ - QAbstractListModel* model = Model(); - if (!model) - { - return; - } - - QModelIndexList indexes = model->match(QModelIndex(), Qt::DisplayRole, sPreset, 1, Qt::MatchExactly); - - if (!indexes.isEmpty()) - { - m_ui->listView->setCurrentIndex(indexes.at(0)); - } -} - -QString CSelectEAXPresetDlg::GetCurrPreset() const -{ - if (m_ui->listView->currentIndex().isValid()) - { - return m_ui->listView->currentIndex().data().toString(); - } - // EXCEPTION: OCX Property Pages should return false - return QString(); -} - - -void CSelectEAXPresetDlg::SetModel(QAbstractListModel* model) -{ - m_ui->listView->setModel(model); -} - -QAbstractListModel* CSelectEAXPresetDlg::Model() const -{ - return static_cast(m_ui->listView->model()); -} - -#include "moc_SelectEAXPresetDlg.cpp" diff --git a/Code/Editor/SelectEAXPresetDlg.h b/Code/Editor/SelectEAXPresetDlg.h deleted file mode 100644 index 9943585987..0000000000 --- a/Code/Editor/SelectEAXPresetDlg.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 - * - */ - - -#pragma once - -// CSelectEAXPresetDlg dialog -#ifndef CRYINCLUDE_EDITOR_SELECTEAXPRESETDLG_H -#define CRYINCLUDE_EDITOR_SELECTEAXPRESETDLG_H - -#if !defined(Q_MOC_RUN) -#include -#endif - -class QAbstractListModel; -class Ui_CSelectEAXPresetDlg; - -class CSelectEAXPresetDlg - : public QDialog -{ - Q_OBJECT - -public: - CSelectEAXPresetDlg(QWidget* pParent = nullptr); // standard constructor - ~CSelectEAXPresetDlg(); - - void SetCurrPreset(const QString& sPreset); - QString GetCurrPreset() const; - -protected: - void SetModel(QAbstractListModel* model); - QAbstractListModel* Model() const; - -private: - Ui_CSelectEAXPresetDlg* m_ui; -}; - -#endif // CRYINCLUDE_EDITOR_SELECTEAXPRESETDLG_H diff --git a/Code/Editor/SelectEAXPresetDlg.ui b/Code/Editor/SelectEAXPresetDlg.ui deleted file mode 100644 index 3177b66c38..0000000000 --- a/Code/Editor/SelectEAXPresetDlg.ui +++ /dev/null @@ -1,67 +0,0 @@ - - - CSelectEAXPresetDlg - - - - 0 - 0 - 197 - 233 - - - - Select Preset... - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - listView - - - - - buttonBox - accepted() - CSelectEAXPresetDlg - accept() - - - 51 - 207 - - - 49 - 199 - - - - - buttonBox - rejected() - CSelectEAXPresetDlg - reject() - - - 148 - 213 - - - 131 - 199 - - - - - diff --git a/Code/Editor/SurfaceTypeValidator.cpp b/Code/Editor/SurfaceTypeValidator.cpp deleted file mode 100644 index 9f246cd453..0000000000 --- a/Code/Editor/SurfaceTypeValidator.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "SurfaceTypeValidator.h" - -// Editor -#include "Include/IObjectManager.h" -#include "Objects/BaseObject.h" -#include "ErrorReport.h" - - -void CSurfaceTypeValidator::Validate() -{ -} - diff --git a/Code/Editor/SurfaceTypeValidator.h b/Code/Editor/SurfaceTypeValidator.h deleted file mode 100644 index 6b1a3fbed7..0000000000 --- a/Code/Editor/SurfaceTypeValidator.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_SURFACETYPEVALIDATOR_H -#define CRYINCLUDE_EDITOR_SURFACETYPEVALIDATOR_H -#pragma once - - - -class CSurfaceTypeValidator -{ -public: - void Validate(); - -private: -}; - -#endif // CRYINCLUDE_EDITOR_SURFACETYPEVALIDATOR_H diff --git a/Code/Editor/UndoViewPosition.cpp b/Code/Editor/UndoViewPosition.cpp deleted file mode 100644 index 1934d255d3..0000000000 --- a/Code/Editor/UndoViewPosition.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Undo for Python function (PySetCurrentViewPosition) - - -#include "EditorDefs.h" - -#include "UndoViewPosition.h" - -// Editor -#include "ViewManager.h" - -CUndoViewPosition::CUndoViewPosition(const QString& pUndoDescription) -{ - m_undoDescription = pUndoDescription; - - CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport(); - if (pRenderViewport) - { - Matrix34 tm = pRenderViewport->GetViewTM(); - m_undo = tm.GetTranslation(); - } -} - -int CUndoViewPosition::GetSize() -{ - return sizeof(*this); -} - -QString CUndoViewPosition::GetDescription() -{ - return m_undoDescription; -} - -void CUndoViewPosition::Undo(bool bUndo) -{ - CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport(); - if (pRenderViewport) - { - Matrix34 tm = pRenderViewport->GetViewTM(); - if (bUndo) - { - m_redo = tm.GetTranslation(); - } - - tm.SetTranslation(m_undo); - pRenderViewport->SetViewTM(tm); - } -} - -void CUndoViewPosition::Redo() -{ - CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport(); - if (pRenderViewport) - { - Matrix34 tm = pRenderViewport->GetViewTM(); - tm.SetTranslation(m_redo); - pRenderViewport->SetViewTM(tm); - } -} diff --git a/Code/Editor/UndoViewPosition.h b/Code/Editor/UndoViewPosition.h deleted file mode 100644 index e0c6c145e8..0000000000 --- a/Code/Editor/UndoViewPosition.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Undo for Python function (PySetCurrentViewPosition) - -#ifndef CRYINCLUDE_EDITOR_UNDOVIEWPOSITION_H -#define CRYINCLUDE_EDITOR_UNDOVIEWPOSITION_H -#pragma once - -#include "Undo/IUndoObject.h" - -class CUndoViewPosition - : public IUndoObject -{ -public: - CUndoViewPosition(const QString& pUndoDescription = "Set Current View Position"); - -protected: - int GetSize(); - QString GetDescription(); - void Undo(bool bUndo); - void Redo(); - -private: - Vec3 m_undo; - Vec3 m_redo; - QString m_undoDescription; -}; - -#endif // CRYINCLUDE_EDITOR_UNDOVIEWPOSITION_H diff --git a/Code/Editor/UndoViewRotation.cpp b/Code/Editor/UndoViewRotation.cpp deleted file mode 100644 index a305641d3b..0000000000 --- a/Code/Editor/UndoViewRotation.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Undo for Python function (PySetCurrentViewPosition) - - -#include "EditorDefs.h" - -#include "UndoViewRotation.h" - -// Editor -#include "ViewManager.h" - -#include -#include -#include -#include - -Ang3 CUndoViewRotation::GetActiveCameraRotation() -{ - AZ::Transform activeCameraTm = AZ::Transform::CreateIdentity(); - Camera::ActiveCameraRequestBus::BroadcastResult( - activeCameraTm, - &Camera::ActiveCameraRequestBus::Events::GetActiveCameraTransform - ); - const AZ::Matrix3x4 cameraMatrix = AZ::Matrix3x4::CreateFromTransform(activeCameraTm); - const Matrix33 cameraMatrixCry = AZMatrix3x3ToLYMatrix3x3(AZ::Matrix3x3::CreateFromMatrix3x4(cameraMatrix)); - return RAD2DEG(Ang3::GetAnglesXYZ(cameraMatrixCry)); -} - -CUndoViewRotation::CUndoViewRotation(const QString& pUndoDescription) -{ - m_undoDescription = pUndoDescription; - m_undo = GetActiveCameraRotation(); -} - -int CUndoViewRotation::GetSize() -{ - return sizeof(*this); -} - -QString CUndoViewRotation::GetDescription() -{ - return m_undoDescription; -} - -void CUndoViewRotation::Undo(bool bUndo) -{ - CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport(); - if (pRenderViewport) - { - if (bUndo) - { - m_redo = GetActiveCameraRotation(); - } - - Matrix34 tm = pRenderViewport->GetViewTM(); - tm.SetRotationXYZ(Ang3(DEG2RAD(m_undo.x), DEG2RAD(m_undo.y), DEG2RAD(m_undo.z)), tm.GetTranslation()); - pRenderViewport->SetViewTM(tm); - } -} - -void CUndoViewRotation::Redo() -{ - CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport(); - if (pRenderViewport) - { - Matrix34 tm = pRenderViewport->GetViewTM(); - tm.SetRotationXYZ(Ang3(DEG2RAD(m_redo.x), DEG2RAD(m_redo.y), DEG2RAD(m_redo.z)), tm.GetTranslation()); - pRenderViewport->SetViewTM(tm); - } -} diff --git a/Code/Editor/UndoViewRotation.h b/Code/Editor/UndoViewRotation.h deleted file mode 100644 index 2e086a3f05..0000000000 --- a/Code/Editor/UndoViewRotation.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 - * - */ - - -// Description : Undo for Python function (PySetCurrentViewRotation) - - -#ifndef CRYINCLUDE_EDITOR_UNDOVIEWROTATION_H -#define CRYINCLUDE_EDITOR_UNDOVIEWROTATION_H -#pragma once -#include "Undo/IUndoObject.h" - - -class CUndoViewRotation - : public IUndoObject -{ -public: - CUndoViewRotation(const QString& pUndoDescription = "Set Current View Rotation"); - -protected: - int GetSize(); - QString GetDescription(); - void Undo(bool bUndo); - void Redo(); - -private: - static Ang3 GetActiveCameraRotation(); - - Ang3 m_undo; - Ang3 m_redo; - QString m_undoDescription; -}; - -#endif // CRYINCLUDE_EDITOR_UNDOVIEWROTATION_H diff --git a/Code/Editor/UserMessageDefines.h b/Code/Editor/UserMessageDefines.h deleted file mode 100644 index 0b13d2819f..0000000000 --- a/Code/Editor/UserMessageDefines.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_USERMESSAGEDEFINES_H -#define CRYINCLUDE_EDITOR_USERMESSAGEDEFINES_H -#pragma once - - -enum ESandboxUserMessages -{ - // InPlaceComboBox - WM_USER_ON_SELECTION_CANCEL = WM_USER + 1, - WM_USER_ON_SELECTION_OK, - WM_USER_ON_NEW_SELECTION, - WM_USER_ON_EDITCHANGE, - WM_USER_ON_OPENDROPDOWN, - WM_USER_ON_EDITKEYDOWN, - WM_USER_ON_EDITCLICK, - // ACListWnd - ENAC_UPDATE, - // EditWithButton - WM_USER_EDITWITHBUTTON_CLICKED, - // FillSliderCtrl - WMU_FS_CHANGED, - WMU_FS_LBUTTONDOWN, - WMU_FS_LBUTTONUP, - FLM_EDITTEXTCHANGED, - FLM_FILTERTEXTCHANGED, - // NumberCtrlEdit - WMU_LBUTTONDOWN, - WMU_LBUTTONUP, - WM_ONWINDOWFOCUSCHANGES, - // SelectObjectDialog - IDT_TIMER_0, - IDT_TIMER_1, - // LensFlareEditor - WM_FLAREEDITOR_UPDATETREECONTROL, - // EquipPackDialog - UM_EQUIPLIST_CHECKSTATECHANGE, - // MaterialSender/MatEditMainDlg - WM_MATEDITPICK, - // GridMapWindow - WM_USER_ON_DBL_CLICK, - // LMCompDialog - WM_UPDATE_LIGHTMAP_GENERATION_PROGRESS, - WM_UPDATE_LIGHTMAP_GENERATION_MEMUSAGE, - WM_UPDATE_LIGHTMAP_GENERATION_MEMUSAGE_STATIC, - WM_UPDATE_GLM_NAME_EDIT, - // Viewport - WM_VIEWPORT_ON_TITLE_CHANGE, - // VisualLogControls - UWM_BUTTON_CLICKED, -}; -#endif // CRYINCLUDE_EDITOR_USERMESSAGEDEFINES_H diff --git a/Code/Editor/ViewPane.cpp b/Code/Editor/ViewPane.cpp index 421db8394e..e3494a4049 100644 --- a/Code/Editor/ViewPane.cpp +++ b/Code/Editor/ViewPane.cpp @@ -38,7 +38,6 @@ #include "Viewport.h" #include "LayoutConfigDialog.h" #include "TopRendererWnd.h" -#include "UserMessageDefines.h" #include "MainWindow.h" #include "QtViewPaneManager.h" #include "EditorViewportWidget.h" diff --git a/Code/Editor/WipFeatureManager.cpp b/Code/Editor/WipFeatureManager.cpp deleted file mode 100644 index 4fb9ed1d93..0000000000 --- a/Code/Editor/WipFeatureManager.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "WipFeatureManager.h" - -#ifdef USE_WIP_FEATURES_MANAGER -#include "WipFeaturesDlg.h" - -#if defined(AZ_PLATFORM_WINDOWS) -const char* CWipFeatureManager::kWipFeaturesFilename = "@user@\\Editor\\UI\\WipFeatures.xml"; -#else -const char* CWipFeatureManager::kWipFeaturesFilename = "@user@/Editor/UI/WipFeatures.xml"; -#endif -CWipFeatureManager* CWipFeatureManager::s_pInstance = nullptr; - -static void WipFeatureVarChange(ICVar* pVar) -{ - QString strParams = pVar->GetString(); - QStringList params; - - SplitString(strParams, params, ' '); - - if (strParams == "edit") - { - static CWipFeaturesDlg dlg; - - dlg.show(); - - return; - } - - if (params.size() >= 2) - { - QString featName = params[0].trimmed(); - QString attr = params[1].trimmed(); - - if (featName.isEmpty()) - { - return; - } - - int id = featName.toInt(); - - // if all features - if (featName == "*") - { - if (attr == "enable") - { - CWipFeatureManager::Instance()->EnableAllFeatures(true); - } - else - if (attr == "disable") - { - CWipFeatureManager::Instance()->EnableAllFeatures(false); - } - else - if (attr == "hide") - { - CWipFeatureManager::Instance()->ShowAllFeatures(false); - } - else - if (attr == "show") - { - CWipFeatureManager::Instance()->ShowAllFeatures(true); - } - else - if (attr == "safemode") - { - CWipFeatureManager::Instance()->SetAllFeaturesSafeMode(true); - } - else - if (attr == "fullmode") - { - CWipFeatureManager::Instance()->SetAllFeaturesSafeMode(false); - } - else - { - CWipFeatureManager::Instance()->SetAllFeaturesParams(attr.toUtf8().data()); - } - - return; - } - - if (attr == "enable") - { - CWipFeatureManager::Instance()->EnableFeature(id, true); - } - else - if (attr == "disable") - { - CWipFeatureManager::Instance()->EnableFeature(id, false); - } - else - if (attr == "hide") - { - CWipFeatureManager::Instance()->ShowFeature(id, false); - } - else - if (attr == "show") - { - CWipFeatureManager::Instance()->ShowFeature(id, true); - } - else - if (attr == "safemode") - { - CWipFeatureManager::Instance()->SetFeatureSafeMode(id, true); - } - else - if (attr == "fullmode") - { - CWipFeatureManager::Instance()->SetFeatureSafeMode(id, false); - } - else - { - CWipFeatureManager::Instance()->SetFeatureParams(id, attr.toUtf8().data()); - } - } -} - -CWipFeatureManager::CWipFeatureManager() -{ - m_bEnabled = true; -} - -CWipFeatureManager::~CWipFeatureManager() -{ -} - -bool CWipFeatureManager::Init(bool bLoadXml) -{ - if (!gEnv) - { - return false; - } - - IConsole* pConsole = gEnv->pConsole; - - if (!pConsole) - { - return false; - } - - REGISTER_CVAR2_CB("e_wipfeature", (const char**)&CWipFeatureManager::Instance()->m_consoleCmdParams, "", VF_ALWAYSONCHANGE | VF_CHEAT, "wipfeature enable|disable|hide|show|safemode|fullmode", WipFeatureVarChange); - - if (bLoadXml) - { - CWipFeatureManager::Instance()->Load(); - } - - return true; -} - -void CWipFeatureManager::Shutdown() -{ - CWipFeatureManager::Instance()->Save(); - delete s_pInstance; - s_pInstance = nullptr; -} - -bool CWipFeatureManager::Load(const char* pFilename, bool bClearExisting) -{ - if (!GetISystem()) - { - return false; - } - - XmlNodeRef root = GetISystem()->LoadXmlFromFile(pFilename); - - if (!root) - { - return false; - } - - if (bClearExisting) - { - m_features.clear(); - } - - Log("Loading WIP features file: '%s'...", pFilename); - - for (size_t i = 0, iCount = root->getChildCount(); i < iCount; ++i) - { - SWipFeatureInfo wf; - XmlNodeRef node = root->getChild(static_cast(i)); - XmlString str; - - node->getAttr("id", wf.m_id); - node->getAttr("displayName", str); - wf.m_displayName = str; - node->getAttr("visible", wf.m_bVisible); - node->getAttr("enabled", wf.m_bEnabled); - node->getAttr("safeMode", wf.m_bSafeMode); - node->getAttr("params", str); - wf.m_params = str; - wf.m_bLoadedFromXml = true; - - TWipFeatures::iterator iter = m_features.find(wf.m_id); - - if (iter == m_features.end()) - { - m_features[wf.m_id] = wf; - } - else - { - m_features[wf.m_id].m_bVisible = wf.m_bVisible; - m_features[wf.m_id].m_bEnabled = wf.m_bEnabled; - m_features[wf.m_id].m_bSafeMode = wf.m_bSafeMode; - m_features[wf.m_id].m_params = wf.m_params; - } - } - - Log("Loaded %d WIP features.", m_features.size()); - - return true; -} - -bool CWipFeatureManager::Save(const char* pFilename) -{ - if (!gEnv) - { - return false; - } - - if (!GetISystem()) - { - return false; - } - - ISystem* pISystem = GetISystem(); - - XmlNodeRef root = pISystem->CreateXmlNode("features"); - - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - SWipFeatureInfo& wf = iter->second; - XmlNodeRef node = root->createNode("feature"); - - node->setAttr("id", wf.m_id); - node->setAttr("displayName", wf.m_displayName.c_str()); - node->setAttr("visible", wf.m_bVisible); - node->setAttr("enabled", wf.m_bEnabled); - node->setAttr("safeMode", wf.m_bSafeMode); - node->setAttr("params", wf.m_params.c_str()); - - root->addChild(node); - } - - root->saveToFile(pFilename); - - return true; -} - -int CWipFeatureManager::RegisterFeature(const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams, bool bSaveToXml) -{ - int aMaxId = -1; - - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - if (iter->first > aMaxId) - { - aMaxId = iter->first; - } - } - - ++aMaxId; - SetFeature(aMaxId, pDisplayName, bVisible, bEnabled, bSafeMode, pParams, bSaveToXml); - - return aMaxId; -} - -void CWipFeatureManager::SetFeature(int aFeatureId, const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams, bool bSaveToXml) -{ - m_features[aFeatureId].m_id = aFeatureId; - m_features[aFeatureId].m_displayName = pDisplayName; - m_features[aFeatureId].m_bVisible = bVisible; - m_features[aFeatureId].m_bEnabled = bEnabled; - m_features[aFeatureId].m_bSafeMode = bSafeMode; - m_features[aFeatureId].m_bSaveToXml = bSaveToXml; - m_features[aFeatureId].m_params = pParams; - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, &bVisible, &bEnabled, &bSafeMode, pParams); - } -} - -void CWipFeatureManager::SetDefaultFeatureStates(int aFeatureId, const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams) -{ - TWipFeatures::iterator iter = m_features.find(aFeatureId); - - // set feature if not existing - if (iter == m_features.end() || (iter != m_features.end() && !iter->second.m_bLoadedFromXml)) - { - m_features[aFeatureId].m_id = aFeatureId; - m_features[aFeatureId].m_displayName = pDisplayName; - m_features[aFeatureId].m_bVisible = bVisible; - m_features[aFeatureId].m_bEnabled = bEnabled; - m_features[aFeatureId].m_bSafeMode = bSafeMode; - m_features[aFeatureId].m_params = pParams; - } - else - if (iter != m_features.end() && iter->second.m_bLoadedFromXml) - { - m_features[aFeatureId].m_id = aFeatureId; - m_features[aFeatureId].m_displayName = pDisplayName; - } - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, &bVisible, &bEnabled, &bSafeMode, pParams); - } -} - -bool CWipFeatureManager::IsFeatureVisible(int aFeatureId) -{ - return m_features[aFeatureId].m_bVisible || !m_bEnabled; -} - -bool CWipFeatureManager::IsFeatureEnabled(int aFeatureId) -{ - return m_features[aFeatureId].m_bEnabled || !m_bEnabled; -} - -bool CWipFeatureManager::IsFeatureInSafeMode(int aFeatureId) -{ - if (!m_bEnabled) - { - return false; - } - - return m_features[aFeatureId].m_bSafeMode; -} - -const char* CWipFeatureManager::GetFeatureParams(int aFeatureId) -{ - return m_features[aFeatureId].m_params.c_str(); -} - -void CWipFeatureManager::ShowFeature(int aFeatureId, bool bShow) -{ - m_features[aFeatureId].m_bVisible = bShow; - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, &bShow, nullptr, nullptr, nullptr); - } -} - -void CWipFeatureManager::EnableFeature(int aFeatureId, bool bEnable) -{ - m_features[aFeatureId].m_bEnabled = bEnable; - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, nullptr, &bEnable, nullptr, nullptr); - } -} - -void CWipFeatureManager::SetFeatureSafeMode(int aFeatureId, bool bSafeMode) -{ - m_features[aFeatureId].m_bSafeMode = bSafeMode; - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, nullptr, nullptr, &bSafeMode, nullptr); - } -} - -void CWipFeatureManager::SetFeatureParams(int aFeatureId, const char* pParams) -{ - m_features[aFeatureId].m_params = pParams; - - if (m_features[aFeatureId].m_pfnUpdateFeature) - { - m_features[aFeatureId].m_pfnUpdateFeature(aFeatureId, nullptr, nullptr, nullptr, pParams); - } -} - -void CWipFeatureManager::ShowAllFeatures(bool bShow) -{ - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - iter->second.m_bVisible = bShow; - - if (iter->second.m_pfnUpdateFeature) - { - iter->second.m_pfnUpdateFeature(iter->first, &bShow, nullptr, nullptr, nullptr); - } - } -} - -void CWipFeatureManager::EnableAllFeatures(bool bEnable) -{ - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - iter->second.m_bEnabled = bEnable; - - if (iter->second.m_pfnUpdateFeature) - { - iter->second.m_pfnUpdateFeature(iter->first, nullptr, &bEnable, nullptr, nullptr); - } - } -} - -void CWipFeatureManager::SetAllFeaturesSafeMode(bool bSafeMode) -{ - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - iter->second.m_bSafeMode = bSafeMode; - - if (iter->second.m_pfnUpdateFeature) - { - iter->second.m_pfnUpdateFeature(iter->first, nullptr, nullptr, &bSafeMode, nullptr); - } - } -} - -void CWipFeatureManager::SetAllFeaturesParams(const char* pParams) -{ - for (TWipFeatures::iterator iter = m_features.begin(), iterEnd = m_features.end(); iter != iterEnd; ++iter) - { - iter->second.m_params = pParams; - - if (iter->second.m_pfnUpdateFeature) - { - iter->second.m_pfnUpdateFeature(iter->first, nullptr, nullptr, nullptr, pParams); - } - } -} - -void CWipFeatureManager::EnableManager(bool bEnable) -{ - m_bEnabled = bEnable; -} - -void CWipFeatureManager::SetFeatureUpdateCallback(int aFeatureId, TWipFeatureUpdateCallback pfnUpdate) -{ - m_features[aFeatureId].m_pfnUpdateFeature = pfnUpdate; -} - -AZStd::map& CWipFeatureManager::GetFeatures() -{ - return m_features; -} - -#endif diff --git a/Code/Editor/WipFeatureManager.h b/Code/Editor/WipFeatureManager.h deleted file mode 100644 index cd20f6d591..0000000000 --- a/Code/Editor/WipFeatureManager.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 - * - */ - - -#ifndef CRYINCLUDE_EDITOR_WIPFEATUREMANAGER_H -#define CRYINCLUDE_EDITOR_WIPFEATUREMANAGER_H -#pragma once - -#include -#include - -/* - This class is used to control work in progress features at runtime, so QA can test even if the end user will not see those features - You can use the console command: e_wipfeature enable|disable|hide|show|safemode|fullmode - ****************************************************************************************************************************************** - *** GOOD TO KNOW: "e_wipfeature edit" console command will display the WIP dialog and you can control the features from there - ****************************************************************************************************************************************** -*/ - -// undef this define to spot all wip feature usages within the editor at compile time -#define USE_WIP_FEATURES_MANAGER - -#ifdef USE_WIP_FEATURES_MANAGER - -// use this to register new wip features, usage from inside functions -// @param id is the numeric unique id of the feature, its good to have all feature ids in an enum in one file -// @param bVisible is the feature visible by default -// @param bEnabled is the feature enabled (usually visual enable like non-grayed) by default -// @param bSafeMode is the feature operating in some sort of safe mode (the safe mode behavior defined by the feature itself) -// @param pTWipFeatureUpdateCallback callback of type TWipFeatureUpdateCallback for when a feature state (visible,enabled and so on) was modified -#define REGISTER_WIP_FEATURE(id, bVisible, bEnabled, bSafeMode, pTWipFeatureUpdateCallback) \ - static CWipFeatureManager::CWipFeatureRegisterer s_wipFeatureRegisterer_##id(id, ""#id, bVisible, bEnabled, bSafeMode, pTWipFeatureUpdateCallback); - -#define IS_WIP_FEATURE_VISIBLE(id) CWipFeatureManager::Instance()->IsFeatureVisible(id) -#define IS_WIP_FEATURE_ENABLED(id) CWipFeatureManager::Instance()->IsFeatureEnabled(id) -#define IS_WIP_FEATURE_SAFEMODE(id) CWipFeatureManager::Instance()->IsFeatureInSafeMode(id) - -// The feature manager singleton itself -class CWipFeatureManager -{ -public: - - static const char* kWipFeaturesFilename; - - // Used to register a callback function to update the state of features whitin the editor - // pbVisible, pbEnabled, pbSafeMode, pParams - if the pointer is nullptr, then that attribute was not changed - typedef void (* TWipFeatureUpdateCallback)(int aFeatureId, const bool* const pbVisible, const bool* const pbEnabled, const bool* const pbSafeMode, const char* pParams); - - // wip feature registerer auto create object, used for static auto feature creation with the REGISTER_WIP_FEATURE macro - class CWipFeatureRegisterer - { - public: - - CWipFeatureRegisterer(int id, const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, TWipFeatureUpdateCallback pTWipFeatureUpdateCallback) - { - CWipFeatureManager::Instance()->SetFeatureUpdateCallback(id, pTWipFeatureUpdateCallback); - CWipFeatureManager::Instance()->SetDefaultFeatureStates(id, pDisplayName, bVisible, bEnabled, bSafeMode); - } - }; - - struct SWipFeatureInfo - { - SWipFeatureInfo() - : m_id(0) - , m_displayName("") - , m_bVisible(true) - , m_bEnabled(true) - , m_bSafeMode(false) - , m_pfnUpdateFeature(nullptr) - , m_bLoadedFromXml(false) - {} - - int m_id; - AZStd::string m_displayName, m_params; - bool m_bVisible, m_bEnabled, m_bSafeMode, - // if true, this feature will be saved into the xml file when Save(...) will be called - m_bSaveToXml, m_bLoadedFromXml; - TWipFeatureUpdateCallback m_pfnUpdateFeature; - }; - - typedef AZStd::map TWipFeatures; - -private: - - CWipFeatureManager(); - ~CWipFeatureManager(); - - static CWipFeatureManager* s_pInstance; - -public: - - static CWipFeatureManager* Instance() - { - if (!s_pInstance) - { - s_pInstance = new CWipFeatureManager(); - AZ_Assert(s_pInstance, "Could not construct CWipFeatureManager"); - } - - return s_pInstance; - } - - static bool Init(bool bLoadXml = true); - static void Shutdown(); - - bool Load(const char* pFilename = kWipFeaturesFilename, bool bClearExisting = true); - bool Save(const char* pFilename = kWipFeaturesFilename); - - // Register a new feature - // @return a new feature ID - int RegisterFeature(const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams = "", bool bSaveToXml = true); - // Set an existing feature - void SetFeature(int aFeatureId, const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams = "", bool bSaveToXml = true); - // Create a new feature, but it will take into account the existing feature info from the loaded XML file, with persistent settings, if any - void SetDefaultFeatureStates(int aFeatureId, const char* pDisplayName, bool bVisible, bool bEnabled, bool bSafeMode, const char* pParams = ""); - bool IsFeatureVisible(int aFeatureId); - bool IsFeatureEnabled(int aFeatureId); - bool IsFeatureInSafeMode(int aFeatureId); - const char* GetFeatureParams(int aFeatureId); - - void ShowFeature(int aFeatureId, bool bShow = true); - void EnableFeature(int aFeatureId, bool bEnable = true); - void SetFeatureSafeMode(int aFeatureId, bool bSafeMode); - void SetFeatureParams(int aFeatureId, const char* pParams); - - void ShowAllFeatures(bool bShow = true); - void EnableAllFeatures(bool bEnable = true); - void SetAllFeaturesSafeMode(bool bSafeMode); - void SetAllFeaturesParams(const char* pParams); - - // if manager is disabled, then all queries about feature enable/visible/fullmode states will return true always - void EnableManager(bool bEnable = true); - - void SetFeatureUpdateCallback(int aFeatureId, TWipFeatureUpdateCallback pfnUpdate); - TWipFeatures& GetFeatures(); - -private: - - static const int kMaxWipCmdSize = 200; - - TWipFeatures m_features; - char m_consoleCmdParams[kMaxWipCmdSize]; - bool m_bEnabled; -}; - -#else - -// -// no WIP feature manager in production build -// -#define REGISTER_WIP_FEATURE -#define IS_WIP_FEATURE_VISIBLE(id) true -#define IS_WIP_FEATURE_ENABLED(id) true -#define IS_WIP_FEATURE_SAFEMODE(id) true - -#endif //USE_WIP_FEATURES_MANAGER -#endif // CRYINCLUDE_EDITOR_WIPFEATUREMANAGER_H diff --git a/Code/Editor/WipFeaturesDlg.cpp b/Code/Editor/WipFeaturesDlg.cpp deleted file mode 100644 index bc4372d7fb..0000000000 --- a/Code/Editor/WipFeaturesDlg.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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 "EditorDefs.h" - -#include "WipFeatureManager.h" - -#include "WipFeaturesDlg.h" - -// Qt -#include - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include "ui_WipFeaturesDlg.h" -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -#ifdef USE_WIP_FEATURES_MANAGER - -// CWipFeaturesDlg dialog - -class WipFeaturesModel - : public QAbstractTableModel -{ -public: - WipFeaturesModel(QObject* parent = nullptr) - : QAbstractTableModel(parent) - { - } - - int rowCount(const QModelIndex& parent = QModelIndex()) const override - { - return parent.isValid() ? 0 : static_cast(CWipFeatureManager::Instance()->GetFeatures().size()); - } - - int columnCount(const QModelIndex& parent = QModelIndex()) const override - { - return parent.isValid() ? 0 : 5; - } - - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override - { - if (orientation != Qt::Horizontal || section >= columnCount()) - { - return QVariant(); - } - - - switch (role) - { - case Qt::TextAlignmentRole: - return section == 0 ? Qt::AlignLeft : Qt::AlignCenter; - case Qt::DisplayRole: - switch (section) - { - case 0: - return tr("Name"); - case 1: - return tr("Id"); - case 2: - return tr("Visible"); - case 3: - return tr("Enabled"); - case 4: - return tr("SafeMode"); - default: - return QVariant(); - } - default: - return QVariant(); - } - } - - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override - { - if (!index.isValid() || index.column() >= columnCount(index.parent()) || index.row() >= rowCount(index.parent())) - { - return false; - } - - if (role != Qt::EditRole || !value.canConvert()) - { - return false; - } - - auto it = CWipFeatureManager::Instance()->GetFeatures().begin(); - std::advance(it, index.row()); - - auto id = it->first; - - switch (index.column()) - { - case 2: - CWipFeatureManager::Instance()->ShowFeature(id, value.toBool()); - break; - case 3: - CWipFeatureManager::Instance()->EnableFeature(id, value.toBool()); - break; - case 4: - CWipFeatureManager::Instance()->SetFeatureSafeMode(id, value.toBool()); - break; - default: - return false; - } - - emit dataChanged(index, index); - return true; - } - - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override - { - if (!index.isValid() || index.column() >= columnCount(index.parent()) || index.row() >= rowCount(index.parent())) - { - return QVariant(); - } - - if (role == Qt::TextAlignmentRole) - { - return headerData(index.column(), Qt::Horizontal, role); - } - - if (role != Qt::DisplayRole) - { - return QVariant(); - } - - auto it = CWipFeatureManager::Instance()->GetFeatures().begin(); - std::advance(it, index.row()); - - auto feature = it->second; - - switch (index.column()) - { - case 0: - return QString(feature.m_displayName.c_str()); - case 1: - return feature.m_id; - case 2: - return feature.m_bVisible ? tr("X") : QString(); - case 3: - return feature.m_bEnabled ? tr("X") : QString(); - case 4: - return feature.m_bSafeMode ? tr("X") : QString(); - default: - return QVariant(); - } - } -}; - -CWipFeaturesDlg::CWipFeaturesDlg(QWidget* pParent /*=nullptr*/) - : QDialog(pParent) - , m_ui(new Ui::WipFeaturesDlg) -{ - m_ui->setupUi(this); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setFixedSize(size()); - - OnInitDialog(); - - connect(m_ui->buttonShow, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonShow); - connect(m_ui->buttonHide, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonHide); - connect(m_ui->buttonEnable, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonEnable); - connect(m_ui->buttonDisable, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonDisable); - connect(m_ui->buttonSafeMode, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonSafemode); - connect(m_ui->buttonNormalMode, &QPushButton::clicked, this, &CWipFeaturesDlg::OnBnClickedButtonNormalmode); -} - -CWipFeaturesDlg::~CWipFeaturesDlg() -{ -} - -// CWipFeaturesDlg message handlers - -void CWipFeaturesDlg::OnInitDialog() -{ - m_ui->m_lstFeatures->setModel(new WipFeaturesModel(this)); - m_ui->m_lstFeatures->horizontalHeader()->resizeSection(0, 300); - m_ui->m_lstFeatures->horizontalHeader()->resizeSection(1, 70); - m_ui->m_lstFeatures->horizontalHeader()->resizeSection(2, 70); - m_ui->m_lstFeatures->horizontalHeader()->resizeSection(3, 70); - m_ui->m_lstFeatures->horizontalHeader()->resizeSection(4, 70); -} - -void CWipFeaturesDlg::OnBnClickedButtonShow() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 2), true); - } -} - -void CWipFeaturesDlg::OnBnClickedButtonHide() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 2), false); - } -} - -void CWipFeaturesDlg::OnBnClickedButtonEnable() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 3), true); - } -} - -void CWipFeaturesDlg::OnBnClickedButtonDisable() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 3), false); - } -} - -void CWipFeaturesDlg::OnBnClickedButtonSafemode() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 4), true); - } -} - -void CWipFeaturesDlg::OnBnClickedButtonNormalmode() -{ - for (auto index : m_ui->m_lstFeatures->selectionModel()->selectedRows()) - { - m_ui->m_lstFeatures->model()->setData(index.sibling(index.row(), 4), false); - } -} - -#include - -#endif // USE_WIP_FEATURES_MANAGER diff --git a/Code/Editor/WipFeaturesDlg.h b/Code/Editor/WipFeaturesDlg.h deleted file mode 100644 index 28f4f43958..0000000000 --- a/Code/Editor/WipFeaturesDlg.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 - * - */ - - -#pragma once -#ifndef CRYINCLUDE_EDITOR_WIPFEATURESDLG_H -#define CRYINCLUDE_EDITOR_WIPFEATURESDLG_H - -#if !defined(Q_MOC_RUN) -#include -#endif - -#ifdef USE_WIP_FEATURES_MANAGER - -// CWipFeaturesDlg dialog - -namespace Ui -{ - class WipFeaturesDlg; -} - -class CWipFeaturesDlg - : public QDialog -{ - Q_OBJECT -public: - CWipFeaturesDlg(QWidget* pParent = nullptr); // standard constructor - virtual ~CWipFeaturesDlg(); - -private: - void OnInitDialog(); - void OnBnClickedButtonShow(); - void OnBnClickedButtonHide(); - void OnBnClickedButtonEnable(); - void OnBnClickedButtonDisable(); - void OnBnClickedButtonSafemode(); - void OnBnClickedButtonNormalmode(); - -private: - QScopedPointer m_ui; -}; - -#else - -class CWipFeaturesDlg - : public QDialog -{ - Q_OBJECT -}; - -#endif // USE_WIP_FEATURES_MANAGER - -#endif // CRYINCLUDE_EDITOR_WIPFEATURESDLG_H diff --git a/Code/Editor/WipFeaturesDlg.qrc b/Code/Editor/WipFeaturesDlg.qrc deleted file mode 100644 index 1205b1063e..0000000000 --- a/Code/Editor/WipFeaturesDlg.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - res/work_in_progress_icon.png - - diff --git a/Code/Editor/WipFeaturesDlg.ui b/Code/Editor/WipFeaturesDlg.ui deleted file mode 100644 index b4bf95e2c5..0000000000 --- a/Code/Editor/WipFeaturesDlg.ui +++ /dev/null @@ -1,184 +0,0 @@ - - - WipFeaturesDlg - - - - 0 - 0 - 620 - 342 - - - - Work in Progress Features - - - - - - Work in progress features: - - - - - - Qt::ScrollBarAlwaysOff - - - QAbstractItemView::SelectRows - - - true - - - false - - - 19 - - - - - - - Show - - - - - - - Hide - - - - - - - Qt::Horizontal - - - QSizePolicy::Ignored - - - - 74 - 20 - - - - - - - - Enable - - - - - - - Disable - - - - - - - Qt::Horizontal - - - QSizePolicy::Ignored - - - - 74 - 20 - - - - - - - - Normal Mode - - - - - - - Safe Mode - - - - - - - - - - - 64 - 64 - - - - - 64 - 64 - - - - :/res/work_in_progress_icon.png - - - - - - - - 0 - 0 - - - - NOTE:<br/>The states of the WIP features will be saved in the Editor/UI/WipFeatures.xml file when the editor exits successfuly - - - true - - - - - - - QDialogButtonBox::Close - - - - - - - - - - - buttonBox - rejected() - WipFeaturesDlg - close() - - - 647 - 339 - - - 674 - 314 - - - - - diff --git a/Code/Editor/arhitype_tree_00.png b/Code/Editor/arhitype_tree_00.png deleted file mode 100644 index 274b2b0667..0000000000 --- a/Code/Editor/arhitype_tree_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9cc3783ba8ccc940e89039455f2a8617a67520400ce74c9ce4c3d16d942ead8 -size 208 diff --git a/Code/Editor/arhitype_tree_01.png b/Code/Editor/arhitype_tree_01.png deleted file mode 100644 index 274b2b0667..0000000000 --- a/Code/Editor/arhitype_tree_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9cc3783ba8ccc940e89039455f2a8617a67520400ce74c9ce4c3d16d942ead8 -size 208 diff --git a/Code/Editor/arhitype_tree_02.png b/Code/Editor/arhitype_tree_02.png deleted file mode 100644 index f29a502de1..0000000000 --- a/Code/Editor/arhitype_tree_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1f8b26d30e8c00514648cf72bb80fe8be3f665eb7473b6565b31a4b078816bfd -size 208 diff --git a/Code/Editor/arhitype_tree_03.png b/Code/Editor/arhitype_tree_03.png deleted file mode 100644 index f29a502de1..0000000000 --- a/Code/Editor/arhitype_tree_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1f8b26d30e8c00514648cf72bb80fe8be3f665eb7473b6565b31a4b078816bfd -size 208 diff --git a/Code/Editor/bmp00005_00.png b/Code/Editor/bmp00005_00.png deleted file mode 100644 index 345abfaf01..0000000000 --- a/Code/Editor/bmp00005_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5e4a0284f8d3b2625c3f27d6505b19a0babb7af0825f08b4e08f40e647d10873 -size 388 diff --git a/Code/Editor/bmp00005_01.png b/Code/Editor/bmp00005_01.png deleted file mode 100644 index abeba83277..0000000000 --- a/Code/Editor/bmp00005_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43f64ba8198c197f2dd91f00947df808fa41274411934d3d1f81e3eb44f78e7a -size 532 diff --git a/Code/Editor/bmp00005_02.png b/Code/Editor/bmp00005_02.png deleted file mode 100644 index 45439597e2..0000000000 --- a/Code/Editor/bmp00005_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:556929870bb8c26fe8ebf4e94536e74c2eb1084e6f566007ec3a5f2e6303fa53 -size 392 diff --git a/Code/Editor/bmp00005_03.png b/Code/Editor/bmp00005_03.png deleted file mode 100644 index b67ec062ff..0000000000 --- a/Code/Editor/bmp00005_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:239843fcd5a08e260106ee6eb3f69d3606321267e94df1e64ab25573d14980e1 -size 486 diff --git a/Code/Editor/bmp00005_04.png b/Code/Editor/bmp00005_04.png deleted file mode 100644 index 565730be66..0000000000 --- a/Code/Editor/bmp00005_04.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98baf372c91fe63c423237a2a3ae5a043a4da41095698035ce86fd13f2051e44 -size 514 diff --git a/Code/Editor/bmp00005_05.png b/Code/Editor/bmp00005_05.png deleted file mode 100644 index 232c374515..0000000000 --- a/Code/Editor/bmp00005_05.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a570ae986b5f0b7e573094a7e75a8cfcc42f88b4766c47785bab26a9e8b1c2bb -size 239 diff --git a/Code/Editor/bmp00005_06.png b/Code/Editor/bmp00005_06.png deleted file mode 100644 index 3de6336a89..0000000000 --- a/Code/Editor/bmp00005_06.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c527f2b8c883c73aebba0b5f0df6215f73b7259db61b13fa5ff7aa7b96a7b9b -size 779 diff --git a/Code/Editor/bmp00005_07.png b/Code/Editor/bmp00005_07.png deleted file mode 100644 index a813c0ad0b..0000000000 --- a/Code/Editor/bmp00005_07.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f7f84cb48b2f9031b3a23abeddaed95d54601de33c58057d6677073b3e083aa -size 501 diff --git a/Code/Editor/bmp00005_08.png b/Code/Editor/bmp00005_08.png deleted file mode 100644 index b9f98ffe1c..0000000000 --- a/Code/Editor/bmp00005_08.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:804491b4251adfe017f8c52e00324dd74f00ebec445eedd947dea9356865cd56 -size 682 diff --git a/Code/Editor/bmp00005_09.png b/Code/Editor/bmp00005_09.png deleted file mode 100644 index 8650cc6a9e..0000000000 --- a/Code/Editor/bmp00005_09.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ecf6333b6b402e1834f3047b13e58e4f80e17a8eed3750017219b5694d1b6f67 -size 625 diff --git a/Code/Editor/bmp00006_00.png b/Code/Editor/bmp00006_00.png deleted file mode 100644 index c48f7ede09..0000000000 --- a/Code/Editor/bmp00006_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:70724fdada9cecd5a8d7ee5211ee713accc8f9642415e5dd93b6d621ed7273cf -size 139 diff --git a/Code/Editor/bmp00006_01.png b/Code/Editor/bmp00006_01.png deleted file mode 100644 index 7fb55bc8a5..0000000000 --- a/Code/Editor/bmp00006_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d12de5789fb345c5ffe4b76246ec0ba4d7972fb14d15db3f36886f3beaed3ff -size 166 diff --git a/Code/Editor/bmp00006_02.png b/Code/Editor/bmp00006_02.png deleted file mode 100644 index 7b1ab690a3..0000000000 --- a/Code/Editor/bmp00006_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fffdbe9b4e1630f4158c4a00985e713ddb6fae50bc71e8c100255bab04054c0a -size 235 diff --git a/Code/Editor/bmp00006_03.png b/Code/Editor/bmp00006_03.png deleted file mode 100644 index 4829767efd..0000000000 --- a/Code/Editor/bmp00006_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d5e4092107dbc45863abe1cbecb30c48135e17155b5a85afa07a4a90b3eb1221 -size 274 diff --git a/Code/Editor/bmp00006_04.png b/Code/Editor/bmp00006_04.png deleted file mode 100644 index dc809b8a65..0000000000 --- a/Code/Editor/bmp00006_04.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bc454d6cf883b78ae4cc32bfe4a81a6d5ee64e5e1bade9f2069e7e1b405ad9b1 -size 373 diff --git a/Code/Editor/bmp00006_05.png b/Code/Editor/bmp00006_05.png deleted file mode 100644 index 2f3c67fff6..0000000000 --- a/Code/Editor/bmp00006_05.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:359236f395259b21b75f8f3fa250dfeea9ef82b9d541c7344954cf93db5c9d47 -size 616 diff --git a/Code/Editor/bmp00006_06.png b/Code/Editor/bmp00006_06.png deleted file mode 100644 index 86c43264ea..0000000000 --- a/Code/Editor/bmp00006_06.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bc8e5dd88bb78f4f63ba8618e2bf0c1fd74d2dbdcf48261cfa57883c476619fe -size 1101 diff --git a/Code/Editor/bmp00006_07.png b/Code/Editor/bmp00006_07.png deleted file mode 100644 index 067b20a5fb..0000000000 --- a/Code/Editor/bmp00006_07.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1fbfb749ecfec92f461979d15642dfb940cc7895db3d27c47d040b0a7e2a1ae4 -size 1288 diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 345a8e15e1..5d45bbd853 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -347,7 +347,6 @@ set(FILES MainStatusBar.cpp MainStatusBar.h MainStatusBarItems.h - CrtDebug.cpp CryEdit.rc CryEditDoc.cpp CryEditDoc.h @@ -358,7 +357,6 @@ set(FILES LogFile.cpp LogFile.h Resource.h - UserMessageDefines.h ActionManager.cpp ActionManager.h ShortcutDispatcher.cpp @@ -397,9 +395,6 @@ set(FILES ResizeResolutionDialog.cpp ResizeResolutionDialog.h ResizeResolutionDialog.ui - SelectEAXPresetDlg.cpp - SelectEAXPresetDlg.h - SelectEAXPresetDlg.ui SelectLightAnimationDialog.cpp SelectLightAnimationDialog.h SelectSequenceDialog.cpp @@ -421,9 +416,6 @@ set(FILES IconListDialog.ui UndoDropDown.cpp UndoDropDown.h - DimensionsDialog.cpp - DimensionsDialog.h - DimensionsDialog.ui NewLevelDialog.cpp NewLevelDialog.h NewLevelDialog.ui @@ -456,12 +448,7 @@ set(FILES ToolBox.h TrackViewNewSequenceDialog.h UndoConfigSpec.h - UndoViewPosition.h - UndoViewRotation.h Util/GeometryUtil.h - WipFeaturesDlg.h - WipFeaturesDlg.ui - WipFeaturesDlg.qrc LevelIndependentFileMan.cpp LevelIndependentFileMan.h LogFileImpl.cpp @@ -550,11 +537,6 @@ set(FILES TrackViewNewSequenceDialog.cpp TrackViewNewSequenceDialog.ui UndoConfigSpec.cpp - UndoViewPosition.cpp - UndoViewRotation.cpp - WipFeatureManager.cpp - WipFeatureManager.h - WipFeaturesDlg.cpp Dialogs/ErrorsDlg.cpp Dialogs/ErrorsDlg.h Dialogs/ErrorsDlg.ui @@ -571,8 +553,6 @@ set(FILES ProcessInfo.cpp ProcessInfo.h Report.h - SurfaceTypeValidator.cpp - SurfaceTypeValidator.h TrackView/AtomOutputFrameCapture.cpp TrackView/AtomOutputFrameCapture.h TrackView/TrackViewDialog.qrc diff --git a/Code/Editor/particles_tree_00.png b/Code/Editor/particles_tree_00.png deleted file mode 100644 index 274b2b0667..0000000000 --- a/Code/Editor/particles_tree_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9cc3783ba8ccc940e89039455f2a8617a67520400ce74c9ce4c3d16d942ead8 -size 208 diff --git a/Code/Editor/particles_tree_01.png b/Code/Editor/particles_tree_01.png deleted file mode 100644 index 274b2b0667..0000000000 --- a/Code/Editor/particles_tree_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9cc3783ba8ccc940e89039455f2a8617a67520400ce74c9ce4c3d16d942ead8 -size 208 diff --git a/Code/Editor/particles_tree_02.png b/Code/Editor/particles_tree_02.png deleted file mode 100644 index 96f4bec585..0000000000 --- a/Code/Editor/particles_tree_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19b1ee36ba28ede080ef34bd13d37a8b579ad8e106089cd1b800b15aef1b58df -size 252 diff --git a/Code/Editor/particles_tree_03.png b/Code/Editor/particles_tree_03.png deleted file mode 100644 index 3ead10b3b4..0000000000 --- a/Code/Editor/particles_tree_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e6ef5e26d5d1566f51824c3bfa0ed3d2653cb49e38111aaf0572590b2fd15be -size 261 diff --git a/Code/Editor/particles_tree_04.png b/Code/Editor/particles_tree_04.png deleted file mode 100644 index 0920a2667d..0000000000 --- a/Code/Editor/particles_tree_04.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:acbeaa97474bd203ac35bf87fdea49d8b3d60f18db62d64dd47c3b1b50e54816 -size 303 diff --git a/Code/Editor/particles_tree_05.png b/Code/Editor/particles_tree_05.png deleted file mode 100644 index 0a4ce61ba0..0000000000 --- a/Code/Editor/particles_tree_05.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d92fc6ec4afc582ff5d019f5b26c48e3dbe6c5f3c753271d7918cd5ca95b8b32 -size 254 diff --git a/Code/Editor/particles_tree_06.png b/Code/Editor/particles_tree_06.png deleted file mode 100644 index e0ab042cb3..0000000000 --- a/Code/Editor/particles_tree_06.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02066aed1d53c3ffc53c0f844a88ba8870b6c2c9c846c47ef6443c21ce4b7d0c -size 224 diff --git a/Code/Editor/particles_tree_07.png b/Code/Editor/particles_tree_07.png deleted file mode 100644 index 2ab767a7e9..0000000000 --- a/Code/Editor/particles_tree_07.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:67668cc830b553605d2f9ccad57f2fcd422da6a7515cfc4e9af0f43aa8591543 -size 213 From 7694a29fa1f4cd4d4872d8c1ccc1fc83ea9cdc63 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 18 Jan 2022 10:16:33 -0800 Subject: [PATCH 12/36] Material Editor tests for window pane function Signed-off-by: Scott Murray --- .../Gem/PythonTests/Atom/TestSuite_Main.py | 4 +++- .../Atom/atom_utils/material_editor_utils.py | 4 ++-- .../hydra_AtomMaterialEditor_BasicTests.py | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index 7051b9983c..f1e66ac492 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py @@ -173,9 +173,11 @@ class TestMaterialEditorBasicTests(object): "Document saved as copy is saved with changes: True", "Document saved as child is saved with changes: True", "Save All worked as expected: True", + "P1: Asset Browser visibility working as expected: True", + "P1: Inspector visibility working as expected: True", ] unexpected_lines = [ - "Traceback (most recent call last):" + # Including any lines in unexpected_lines will cause the test to run for the duration of the timeout ] hydra.launch_and_validate_results( diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py index f7ff970541..96eeb4279e 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py @@ -125,11 +125,11 @@ def is_pane_visible(pane_name): """ :return: bool """ - return atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name) + return atomtools.AtomToolsMainWindowRequestBus(bus.Broadcast, "IsDockWidgetVisible", pane_name) def set_pane_visibility(pane_name, value): - atomtools.AtomToolsWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value) + atomtools.AtomToolsMainWindowRequestBus(bus.Broadcast, "SetDockWidgetVisible", pane_name, value) def select_lighting_config(config_name): diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py index baad02318d..bd00a84919 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py @@ -36,6 +36,19 @@ MATERIAL_TYPE_PATH = os.path.join( CACHE_FILE_EXTENSION = ".azmaterial" +def verify_pane_visibility(pane_name: str): + """ + print log lines indicating Material Editor pane visibility function + :param pane_name: Name of the pane to be tested + """ + initial_value = material_editor.is_pane_visible(pane_name) + material_editor.set_pane_visibility(pane_name, not initial_value) + result = (material_editor.is_pane_visible(pane_name) is not initial_value) + material_editor.set_pane_visibility(pane_name, initial_value) + result = result and (initial_value is material_editor.is_pane_visible(pane_name)) + print(f"P1: {pane_name} visibility working as expected: {result}") + + def run(): """ Summary: @@ -49,9 +62,12 @@ def run(): 7. Saving as a New Material 8. Saving as a Child Material 9. Saving all Open Materials + 10. Verify Asset Browser pane visibility + 11. Verify Material Inspector pane visibility Expected Result: All the above functions work as expected in Material Editor. + Pane visibility functions as expected :return: None """ @@ -186,6 +202,14 @@ def run(): material_editor.set_property(document2_id, property2_name, initial_color) material_editor.save_all() material_editor.close_all_documents() + + # 10) Verify Asset Browser pane visibility + verify_pane_visibility("Asset Browser") + + # 11) Verify Material Inspector pane visibility + verify_pane_visibility("Inspector") + + # Confirm documents closed and exit Material Editor material_editor.wait_for_condition(lambda: (not material_editor.is_open(document1_id)) and (not material_editor.is_open(document2_id)) and From 626b16dbaeeb40594303fa49ad473d37684eb9b1 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 18 Jan 2022 10:27:10 -0800 Subject: [PATCH 13/36] Updating NetworkingSpawnableLibrary to only store network spawnables, instead of all spawnables Signed-off-by: Gene Walters --- .../Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp | 4 ++-- .../Code/Source/NetworkEntity/NetworkSpawnableLibrary.h | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp index f60778dbb4..7fb7bfdc39 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include namespace Multiplayer @@ -42,7 +41,8 @@ namespace Multiplayer auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info) { - if (info.m_assetType == AZ::AzTypeInfo::Uuid()) + if (info.m_assetType == AZ::AzTypeInfo::Uuid() && + info.m_relativePath.ends_with(".network.spawnable")) { ProcessSpawnableAsset(info.m_relativePath, id); } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h index 0fc3ae07cc..469086f4cb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h @@ -23,12 +23,15 @@ namespace Multiplayer NetworkSpawnableLibrary(); ~NetworkSpawnableLibrary(); - /// INetworkSpawnableLibrary overrides. + //! INetworkSpawnableLibrary overrides. + //! @{ + // Iterates over all assets (on-disk and in-memory) and stores any spawnables that are "network.spawnables" + // This allows us to look up network spawnable assets by name or id for later use void BuildSpawnablesList() override; void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id) override; AZ::Name GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId) override; AZ::Data::AssetId GetAssetIdByName(AZ::Name name) override; - + //! @} private: AZStd::unordered_map m_spawnables; From c5b128bec422a9ac716ac4f9164b204daabd29c3 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 17 Dec 2021 00:46:40 -0800 Subject: [PATCH 14/36] First pass at reworking and formalizing the way deferred material asset baking works. The feature basically works but needs more testing. Before, the material builder was loading the MaterialTypeAsset and doing some processing with it, but was avoiding declaring job dependencies that would cause reprocessing lots of assets when a shader or .materialtype file changes. Reading the asset data isn't safe when not declaring a job dependency (or when declaring a weak job dependency like OrderOnce which is the case here). This caused to several known bugs. The main change here is it no longer loads the MaterialTypeAsset at all; all other changes flow from there. The biggest changes (when deferred material processing is enabled) are ... 1) MaterialSourceData no longer loads MaterialTypeAsset. All it really needs is to determine whether a string is an image file reference or an enum value, which is easy to do by just looking for the "." for the extension. 2) MaterialAssetCreator no longer produces a finalized material asset. It no longer uses MaterialAssetCreatorCommon because that only produces a non-finalized MaterialAsset, which has very different needs for the SetPropertyValue function. (We could consider merging MaterialAssetCreatorCommon into MaterialTypeAssetCreator since that's the only subclass at this point). And it doesn't do any validation against the properties layout since that can be done at runtime. 3) Moved processing of enum property values from MaterialSourceData to MaterialAsset::Finalize (this was the only thing being done in the builder that actually needed to read the material type asset data). Also... - Updated the MaterialAsset class mostly to clarify and formalize the two different modes it can be in: whether it is finalized or not. - Merged the separate "IncludeMaterialPropertyNames" registry settings from MaterialConverterSystemComponent and MaterialBuilder into one "FinalizeMaterialAssets" setting used for both. - Removed MaterialSourceData::ApplyVersionUpdates. Now the flow of data is the same regardless of whether the materials are finalized by the AP or at runtime. Version updates are always applied on the MaterialAsset. - Added a validation check to MaterialTypeAssetCreator ensuring that once a property is renamed, the old name can never be used again for a new property. This assumption was already made previously, but not formalized, in that Material::FindPropertyIndex does not expect every caller to provide a version number for the material property name, also the material asset's list of raw property names was never versioned. The only way for this to be a safe assumption is to prevent reuse of old names. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../MaterialConverterSystemComponent.cpp | 8 +- .../MaterialConverterSystemComponent.h | 6 - .../RPI.Edit/Material/MaterialConverterBus.h | 4 - .../RPI.Edit/Material/MaterialSourceData.h | 21 +- .../Atom/RPI.Edit/Material/MaterialUtils.h | 5 + .../Atom/RPI.Reflect/Material/MaterialAsset.h | 53 +++-- .../Material/MaterialAssetCreator.h | 19 +- .../Material/MaterialPropertyValue.h | 4 + .../RPI.Builders/Material/MaterialBuilder.cpp | 62 ++--- .../Model/MaterialAssetBuilderComponent.cpp | 25 +- .../RPI.Edit/Material/MaterialSourceData.cpp | 220 ++++++++---------- .../RPI.Edit/Material/MaterialUtils.cpp | 15 ++ .../RPI.Reflect/Material/MaterialAsset.cpp | 139 +++++++---- .../Material/MaterialAssetCreator.cpp | 115 +++------ .../Material/MaterialTypeAssetCreator.cpp | 15 ++ .../Material/MaterialVersionUpdate.cpp | 12 +- .../Code/Source/Document/MaterialDocument.cpp | 6 - 17 files changed, 368 insertions(+), 361 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp index fd1c836b96..d5096d7a0b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.cpp @@ -28,8 +28,7 @@ namespace AZ serializeContext->Class() ->Version(2) ->Field("Enable", &MaterialConverterSettings::m_enable) - ->Field("DefaultMaterial", &MaterialConverterSettings::m_defaultMaterial) - ->Field("IncludeMaterialPropertyNames", &MaterialConverterSettings::m_includeMaterialPropertyNames); + ->Field("DefaultMaterial", &MaterialConverterSettings::m_defaultMaterial); } } @@ -70,11 +69,6 @@ namespace AZ return m_settings.m_enable; } - bool MaterialConverterSystemComponent::ShouldIncludeMaterialPropertyNames() const - { - return m_settings.m_includeMaterialPropertyNames; - } - bool MaterialConverterSystemComponent::ConvertMaterial( const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& sourceData) { diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h index 150529b474..7d95024759 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialConverterSystemComponent.h @@ -26,11 +26,6 @@ namespace AZ bool m_enable = true; AZStd::string m_defaultMaterial; - //! Sets whether to include material property names when generating material assets. If this - //! setting is true, material property name resolution and validation is deferred into load - //! time rather than at build time, allowing to break some dependencies (e.g. fbx files will no - //! longer need to be dependent on materialtype files). - bool m_includeMaterialPropertyNames = true; }; //! Atom's implementation of converting SceneAPI data into Atom's default material: StandardPBR @@ -50,7 +45,6 @@ namespace AZ // MaterialConverterBus overrides ... bool IsEnabled() const override; - bool ShouldIncludeMaterialPropertyNames() const override; bool ConvertMaterial(const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& out) override; AZStd::string GetMaterialTypePath() const override; AZStd::string GetDefaultMaterialPath() const override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h index 1807fca15e..8052fc4feb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialConverterBus.h @@ -32,10 +32,6 @@ namespace AZ virtual bool IsEnabled() const = 0; - //! Returns true if material property names should be included in azmaterials. This allows unlinking of dependencies for some - //! file types to materialtype files (e.g. fbx). - virtual bool ShouldIncludeMaterialPropertyNames() const = 0; - //! Converts data from a IMaterialData object to an Atom MaterialSourceData. //! Only works when IsEnabled() is true. //! @return true if the MaterialSourceData output was populated with converted material data. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 53d3072370..a5fb0214e6 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -33,6 +33,12 @@ namespace AZ class MaterialAsset; class MaterialAssetCreator; + enum MaterialAssetProcessingMode + { + PreBake, //!< all material asset processing is done in the Asset Processor, producing a finalized material asset + DeferredBake //!< some material asset processing is deferred, and the material asset is finalized at runtime after loading + }; + //! This is a simple data structure for serializing in/out material source files. class MaterialSourceData final { @@ -72,35 +78,28 @@ namespace AZ UpdatesApplied }; - //! Checks the material type version and potentially applies a series of property changes (most common are simple property renames) - //! based on the MaterialTypeAsset's version update procedure. - //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for resolving file-relative paths. - ApplyVersionUpdatesResult ApplyVersionUpdates(AZStd::string_view materialSourceFilePath = ""); - //! Creates a MaterialAsset from the MaterialSourceData content. //! @param assetId ID for the MaterialAsset //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for //! resolving file-relative paths. + //! @param processingMode Indicates whether to finalize the material asset using data from the MaterialTypeAsset. //! @param elevateWarnings Indicates whether to treat warnings as errors - //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file Outcome> CreateMaterialAsset( Data::AssetId assetId, - AZStd::string_view materialSourceFilePath = "", - bool elevateWarnings = true, - bool includeMaterialPropertyNames = true) const; + AZStd::string_view materialSourceFilePath, + MaterialAssetProcessingMode processingMode, + bool elevateWarnings = true) const; //! Creates a MaterialAsset from the MaterialSourceData content. //! @param assetId ID for the MaterialAsset //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for //! resolving file-relative paths. //! @param elevateWarnings Indicates whether to treat warnings as errors - //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file //! @param sourceDependencies if not null, will be populated with a set of all of the loaded material and material type paths Outcome> CreateMaterialAssetFromSourceData( Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", bool elevateWarnings = true, - bool includeMaterialPropertyNames = true, AZStd::unordered_set* sourceDependencies = nullptr) const; private: diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index c1183c7aa1..2fb55e5f40 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -64,6 +64,11 @@ namespace AZ void CheckForUnrecognizedJsonFields( const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode& result); + + //! Materials assets can either be finalized during asset-processing time or when materials are loaded at runtime. + //! Finalizing during asset processing reduces load times and obfuscates the material data. + //! Waiting to finalize at load time reduces dependencies on the material type data, resulting in fewer asset rebuilds and less time spent processing assets. + bool BuildersShouldFinalizeMaterialAssets(); } } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 2a1de6debd..34e51b40af 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -105,6 +105,16 @@ namespace AZ //! Returns a layout that includes a list of MaterialPropertyDescriptors for each material property. const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const; + //! Returns whether the material's properties are fully processed or not. + //! If true, property values can be accessed through GetPropertyValues(). + //! If false, property values can be accessed through GetRawPropertyValues(). + bool IsFinalized() const; + + //! If the material asset is not finalized yet, this does the final processing of m_rawPropertyValues to + //! get the material asset ready to be used. + //! Note m_materialTypeAsset must be valid before this is called. + void Finalize(); + //! Returns the list of values for all properties in this material. //! The entries in this list align with the entries in the MaterialPropertiesLayout. Each AZStd::any is guaranteed //! to have a value of type that matches the corresponding MaterialPropertyDescriptor. @@ -112,16 +122,13 @@ namespace AZ //! //! Note that even though material source data files contain only override values and inherit the rest from //! their parent material, they all get flattened at build time so every MaterialAsset has the full set of values. - AZStd::array_view GetPropertyValues() const; + const AZStd::vector& GetPropertyValues() const; + + const AZStd::vector>& GetRawPropertyValues() const; private: bool PostLoadInit() override; - //! Realigns property value and name indices with MaterialProperiesLayout by using m_propertyNames. Property names not found in the - //! MaterialPropertiesLayout are discarded, while property names not included in m_propertyNames will use the default value - //! from m_materialTypeAsset. - void RealignPropertyValuesAndNames(); - //! Checks the material type version and potentially applies a series of property changes (most common are simple property renames) //! based on the MaterialTypeAsset's version update procedure. void ApplyVersionUpdates(); @@ -146,17 +153,33 @@ namespace AZ //! Holds values for each material property, used to initialize Material instances. //! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout. AZStd::vector m_propertyValues; - //! This is used to realign m_propertyValues as well as itself with MaterialPropertiesLayout when not empty. - //! If empty, this implies that m_propertyValues is aligned with the entries in m_materialPropertiesLayout. - AZStd::vector m_propertyNames; - //! The materialTypeVersion this materialAsset was based of. If the versions do not match at runtime when a - //! materialTypeAsset is loaded, an update will be performed on m_propertyNames if populated. + //! The MaterialAsset can be created in a "half-baked" state where minimal processing has been done because it does + //! not yet have access to the MaterialTypeAsset. In that case, this list will be populated with values copied from + //! the source .material file with little or no validation or other processing, and the m_propertyValues list will be empty. + //! Once a MaterialTypeAsset is available, Finalize() must be called to finish processing these values into the + //! final m_propertyValues list. + //! Note that the content of this list will remain after finalizing in order to support hot-reload of the MaterialTypeAsset. + //! The reason we use a vector instead of a map is to ensure inherited property values are applied in the right order; + //! if the material has a parent, and that parent uses an older material type version with renamed properties, then + //! m_rawPropertyValues could be holding two values for the same property under different names. The auto-rename process + //! can't be applied until the MaterialTypeAsset is available, so we have to keep the properties in the same order they + //! were originally encountered. + AZStd::vector> m_rawPropertyValues; + + //! Tracks whether Finalize() has been called, meaning m_propertyValues is populated with data matching the material type's property layout. + bool m_isFinalized = false; + + //! Tracks whether the MaterialAsset was already in a finalized state when it was loaded. + //! (This value is intentionally not serialized) + bool m_wasPreFinalized = false; + + //! The materialTypeVersion this materialAsset was based off. If the versions do not match at runtime when a + //! materialTypeAsset is loaded, automatic updates will be attempted at runtime. Note this is not needed to + //! determine which updates to apply, but simply as an optimization to ignore the update procedure when the + //! version numbers match. (We determine which updates to apply by simply checking the property name, and not + //! allowing the same name to ever be used for two different properties, see MaterialTypeAssetCreator::ValidateMaterialVersion) uint32_t m_materialTypeVersion = 1; - - //! A flag to determine if m_propertyValues needs to be aligned with MaterialPropertiesLayout. Set to true whenever - //! m_materialTypeAsset is reinitializing. - bool m_isDirty = true; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h index 862d98ce0c..b7b1f9705f 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h @@ -9,7 +9,6 @@ #include #include -#include namespace AZ { @@ -19,21 +18,21 @@ namespace AZ //! The MaterialAsset will be based on a MaterialTypeAsset or another MaterialAsset. //! Either way, the base provides the necessary data to define the layout //! and behavior of the material. The MaterialAsset only provides property value overrides. - class MaterialAssetCreator + //! Note however that the MaterialTypeAsset does not have to be loaded and available yet; + //! only the AssetId is required. The resulting MaterialAsset will be in a non-finalized state; + //! it must be finalized afterwards when the MaterialTypeAsset is available before it can be used. + class MaterialAssetCreator : public AssetCreator - , public MaterialAssetCreatorCommon { public: friend class MaterialSourceData; - - void Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial, bool includeMaterialPropertyNames = true); - void Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType, bool includeMaterialPropertyNames = true); + + void Begin(const Data::AssetId& assetId, const Data::Asset& materialType); bool End(Data::Asset& result); - private: - void PopulatePropertyNameList(); - - const MaterialPropertiesLayout* m_materialPropertiesLayout = nullptr; + void SetMaterialTypeVersion(uint32_t version); + + void SetPropertyValue(const Name& name, const MaterialPropertyValue& value); }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyValue.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyValue.h index 718615eb9f..79dda1d80a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyValue.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyValue.h @@ -30,6 +30,10 @@ namespace AZ { namespace RPI { + //! This is a variant data type that represents the value of a material property. + //! For convenience, it supports all the types necessary for *both* the runtime data (MaterialAsset) as well as .material file data (MaterialSourceData). + //! For example, Instance is exclusive to the runtime data and AZStd::string is primarily for image file paths in .material files. Most other + //! data types are relevant in both contexts. class MaterialPropertyValue final { public: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index f11b2f94ac..1b5635a1c1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -43,17 +43,24 @@ namespace AZ const char* MaterialBuilder::JobKey = "Atom Material Builder"; + AZStd::string GetBuilderSettingsFingerprint() + { + return AZStd::string::format("[BuildersShouldFinalizeMaterialAssets=%d]", MaterialUtils::BuildersShouldFinalizeMaterialAssets()); + } + void MaterialBuilder::RegisterBuilder() { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 110; // Material version auto update feature + materialBuilderDescriptor.m_version = 111; // material dependency improvements materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); materialBuilderDescriptor.m_createJobFunction = AZStd::bind(&MaterialBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); materialBuilderDescriptor.m_processJobFunction = AZStd::bind(&MaterialBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); + materialBuilderDescriptor.m_analysisFingerprint = GetBuilderSettingsFingerprint(); + BusConnect(materialBuilderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBus::Handler::RegisterBuilderInformation, materialBuilderDescriptor); @@ -63,7 +70,7 @@ namespace AZ { BusDisconnect(); } - + bool MaterialBuilder::ReportMaterialAssetWarningsAsErrors() const { bool warningsAsErrors = false; @@ -77,15 +84,18 @@ namespace AZ //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back - //! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a .materialtype file, the job dependency type - //! will be set to JobDependencyType::OrderOnce. - void AddPossibleDependencies(AZStd::string_view currentFilePath, - AZStd::string_view referencedParentPath, + //! to the AssetBuilderSDK::CreateJobsResponse. + void AddPossibleDependencies( + const AZStd::string& currentFilePath, + const AZStd::string& referencedParentPath, const char* jobKey, - AZStd::vector& jobDependencies, - bool isOrderedOnceForMaterialTypes = false) + AZStd::vector& jobDependencies) { bool dependencyFileFound = false; + + const bool currentFileIsMaterial = AzFramework::StringFunc::Path::IsExtension(currentFilePath.c_str(), MaterialSourceData::Extension); + const bool referencedFileIsMaterialType = AzFramework::StringFunc::Path::IsExtension(referencedParentPath.c_str(), MaterialTypeSourceData::Extension); + const bool ShouldFinalizeMaterialAssets = MaterialUtils::BuildersShouldFinalizeMaterialAssets(); AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); for (auto& file : possibleDependencies) @@ -103,9 +113,15 @@ namespace AZ AssetBuilderSDK::JobDependency jobDependency; jobDependency.m_jobKey = jobKey; jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - - const bool isMaterialTypeFile = AzFramework::StringFunc::Path::IsExtension(file.c_str(), MaterialTypeSourceData::Extension); - jobDependency.m_type = (isMaterialTypeFile && isOrderedOnceForMaterialTypes) ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + + // If we aren't finalizing material assets, then a normal job dependency isn't needed because the MaterialTypeAsset data won't be used. + // However, we do still need at least an OrderOnce dependency to ensure the Asset Processor knows about the material type asset so the builder can get it's AssetId. + // This can significantly reduce AP processing time when a material type or its shaders are edited. + if (currentFileIsMaterial && referencedFileIsMaterialType && !ShouldFinalizeMaterialAssets) + { + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::OrderOnce; + } jobDependencies.push_back(jobDependency); } @@ -156,7 +172,8 @@ namespace AZ // We'll build up this one JobDescriptor and reuse it to register each of the platforms AssetBuilderSDK::JobDescriptor outputJobDescriptor; outputJobDescriptor.m_jobKey = JobKey; - + outputJobDescriptor.m_additionalFingerprintInfo = GetBuilderSettingsFingerprint(); + // Load the file so we can detect and report dependencies. // If the file is a .materialtype, report dependencies on the .shader files. // If the file is a .material, report a dependency on the .materialtype and parent .material file @@ -233,24 +250,12 @@ namespace AZ parentMaterialPath = materialTypePath; } - // If includeMaterialPropertyNames is false, then a job dependency is needed so the material builder can validate MaterialAsset properties - // against the MaterialTypeAsset at asset build time. - // If includeMaterialPropertyNames is true, the material properties will be validated at runtime when the material is loaded, so the job dependency - // is needed only for first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file - // is edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s). - bool includeMaterialPropertyNames = true; - if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) - { - settingsRegistry->Get(includeMaterialPropertyNames, "/O3DE/Atom/RPI/MaterialBuilder/IncludeMaterialPropertyNames"); - } - // Register dependency on the parent material source file so we can load it and use it's data to build this variant material. // Note, we don't need a direct dependency on the material type because the parent material will depend on it. AddPossibleDependencies(request.m_sourceFile, parentMaterialPath, JobKey, - outputJobDescriptor.m_jobDependencyList, - includeMaterialPropertyNames); + outputJobDescriptor.m_jobDependencyList); } } @@ -297,12 +302,9 @@ namespace AZ return {}; } - if (MaterialSourceData::ApplyVersionUpdatesResult::Failed == material.GetValue().ApplyVersionUpdates(materialSourceFilePath)) - { - return {}; - } + MaterialAssetProcessingMode processingMode = MaterialUtils::BuildersShouldFinalizeMaterialAssets() ? MaterialAssetProcessingMode::PreBake : MaterialAssetProcessingMode::DeferredBake; - auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, ReportMaterialAssetWarningsAsErrors()); + auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, processingMode, ReportMaterialAssetWarningsAsErrors()); if (!materialAssetOutcome.IsSuccess()) { return {}; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index c83761cf8e..ef251b6848 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -44,7 +45,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(5) // Set materialtype dependency to OrderOnce + ->Version(5) // <<<<< This probably is NOT the version number you want to bump. What you're looking for is MaterialAssetBuilderComponent::Reflect below ->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })); } } @@ -93,9 +94,11 @@ namespace AZ // material properties will be validated at runtime when the material is loaded, so the job dependency is needed only for // first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file is // edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s). - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); - jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; + + // If we aren't finalizing material assets, then a normal job dependency isn't needed because the MaterialTypeAsset data won't be used. + // However, we do still need at least an OrderOnce dependency to ensure the Asset Processor knows about the material type asset so the builder can get it's AssetId. + // This can significantly reduce AP processing time when a material type or its shaders are edited. + jobDependency.m_type = MaterialUtils::BuildersShouldFinalizeMaterialAssets() ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; jobDependencyList.push_back(jobDependency); } @@ -108,10 +111,8 @@ namespace AZ bool conversionEnabled = false; RPI::MaterialConverterBus::BroadcastResult(conversionEnabled, &RPI::MaterialConverterBus::Events::IsEnabled); fingerprintInfo.insert(AZStd::string::format("[MaterialConverter enabled=%d]", conversionEnabled)); - - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); - fingerprintInfo.insert(AZStd::string::format("[MaterialConverter includeMaterialPropertyNames=%d]", includeMaterialPropertyNames)); + + fingerprintInfo.insert(AZStd::string::format("[BuildersShouldFinalizeMaterialAssets=%d]", MaterialUtils::BuildersShouldFinalizeMaterialAssets())); if (!conversionEnabled) { @@ -126,7 +127,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(16); // Optional material conversion + ->Version(17); // Optional material conversion } } @@ -230,9 +231,9 @@ namespace AZ } } } + + MaterialAssetProcessingMode processingMode = MaterialUtils::BuildersShouldFinalizeMaterialAssets() ? MaterialAssetProcessingMode::PreBake : MaterialAssetProcessingMode::DeferredBake; - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); // Build material assets. for (auto& itr : materialSourceDataByUid) { @@ -240,7 +241,7 @@ namespace AZ Data::AssetId assetId(sourceSceneUuid, GetMaterialAssetSubId(materialUid)); auto materialSourceData = itr.second; - Outcome> result = materialSourceData.m_data.CreateMaterialAsset(assetId, "", false, includeMaterialPropertyNames); + Outcome> result = materialSourceData.m_data.CreateMaterialAsset(assetId, "", processingMode, false); if (result.IsSuccess()) { context.m_outputMaterialsByUid[materialUid] = { result.GetValue(), materialSourceData.m_name }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 4351213c22..cd01544bfa 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -74,77 +74,49 @@ namespace AZ } } - MaterialSourceData::ApplyVersionUpdatesResult MaterialSourceData::ApplyVersionUpdates(AZStd::string_view materialSourceFilePath) - { - AZStd::string materialTypeFullPath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); - auto materialTypeSourceDataOutcome = MaterialUtils::LoadMaterialTypeSourceData(materialTypeFullPath); - if (!materialTypeSourceDataOutcome.IsSuccess()) - { - return ApplyVersionUpdatesResult::Failed; - } - - MaterialTypeSourceData materialTypeSourceData = materialTypeSourceDataOutcome.TakeValue(); - - if (m_materialTypeVersion == materialTypeSourceData.m_version) - { - return ApplyVersionUpdatesResult::NoUpdates; - } - - bool changesWereApplied = false; - - // Note that the only kind of property update currently supported is rename... - - PropertyGroupMap newPropertyGroups; - for (auto& groupPair : m_properties) - { - PropertyMap& propertyMap = groupPair.second; - - for (auto& propertyPair : propertyMap) - { - MaterialPropertyId propertyId{groupPair.first, propertyPair.first}; - - if (materialTypeSourceData.ApplyPropertyRenames(propertyId, m_materialTypeVersion)) - { - changesWereApplied = true; - } - - newPropertyGroups[propertyId.GetGroupName().GetStringView()][propertyId.GetPropertyName().GetStringView()] = propertyPair.second; - } - } - - 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: '%s'.", - m_materialTypeVersion, materialTypeFullPath.c_str(), materialTypeSourceData.m_version, materialSourceFilePath.data()); - } - - m_materialTypeVersion = materialTypeSourceData.m_version; - - return changesWereApplied ? ApplyVersionUpdatesResult::UpdatesApplied : ApplyVersionUpdatesResult::NoUpdates; - } - Outcome> MaterialSourceData::CreateMaterialAsset( - Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + Data::AssetId assetId, AZStd::string_view materialSourceFilePath, MaterialAssetProcessingMode processingMode, bool elevateWarnings) const { MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); - if (m_parentMaterial.empty()) + Outcome materialTypeAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); + if (!materialTypeAssetId) { - auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); - if (!materialTypeAsset.IsSuccess()) + return Failure(); + } + + Data::Asset materialTypeAsset; + + switch (processingMode) + { + case MaterialAssetProcessingMode::DeferredBake: { + // Don't load the material type data, just create a reference to it + materialTypeAsset = Data::Asset{ materialTypeAssetId.GetValue(), azrtti_typeid(), m_materialType }; + break; + } + case MaterialAssetProcessingMode::PreBake: + { + // In this case we need to load the material type data in preparation for the material->Finalize() step below. + auto materialTypeAssetOutcome = AssetUtils::LoadAsset(materialTypeAssetId.GetValue()); + if (!materialTypeAssetOutcome) + { + return Failure(); + } + materialTypeAsset = materialTypeAssetOutcome.GetValue(); + break; + } + default: + { + AZ_Assert(false, "Unhandled MaterialAssetProcessingMode"); return Failure(); } - - materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); } - else + + materialAssetCreator.Begin(assetId, materialTypeAsset); + + if (!m_parentMaterial.empty()) { auto parentMaterialAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_parentMaterial); if (!parentMaterialAsset.IsSuccess()) @@ -154,25 +126,53 @@ namespace AZ // Make sure the parent material has the same material type { - auto materialTypeIdOutcome = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); - if (!materialTypeIdOutcome.IsSuccess()) - { - return Failure(); - } - - Data::AssetId expectedMaterialTypeId = materialTypeIdOutcome.GetValue(); - Data::AssetId parentMaterialId = parentMaterialAsset.GetValue().GetId(); - // This will only be valid if the parent material is not a material type Data::AssetId parentsMaterialTypeId = parentMaterialAsset.GetValue()->GetMaterialTypeAsset().GetId(); - if (expectedMaterialTypeId != parentMaterialId && expectedMaterialTypeId != parentsMaterialTypeId) + if (materialTypeAssetId.GetValue() != parentsMaterialTypeId) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } } - materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); + // Inherit the parent's property values... + switch (processingMode) + { + case MaterialAssetProcessingMode::DeferredBake: + { + for (auto& property : parentMaterialAsset.GetValue()->GetRawPropertyValues()) + { + materialAssetCreator.SetPropertyValue(property.first, property.second); + } + + break; + } + case MaterialAssetProcessingMode::PreBake: + { + const MaterialPropertiesLayout* propertiesLayout = parentMaterialAsset.GetValue()->GetMaterialPropertiesLayout(); + + if (parentMaterialAsset.GetValue()->GetPropertyValues().size() != propertiesLayout->GetPropertyCount()) + { + AZ_Assert(false, "The parent material should have been finalized with %zu properties but it has %zu. Something is out of sync.", + propertiesLayout->GetPropertyCount(), parentMaterialAsset.GetValue()->GetPropertyValues().size()); + return Failure(); + } + + for (size_t propertyIndex = 0; propertyIndex < propertiesLayout->GetPropertyCount(); ++propertyIndex) + { + materialAssetCreator.SetPropertyValue( + propertiesLayout->GetPropertyDescriptor(MaterialPropertyIndex{propertyIndex})->GetName(), + parentMaterialAsset.GetValue()->GetPropertyValues()[propertyIndex]); + } + + break; + } + default: + { + AZ_Assert(false, "Unhandled MaterialAssetProcessingMode"); + return Failure(); + } + } } ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); @@ -180,6 +180,11 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { + if (processingMode == MaterialAssetProcessingMode::PreBake) + { + material->Finalize(); + } + return Success(material); } else @@ -192,7 +197,6 @@ namespace AZ Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, - bool includeMaterialPropertyNames, AZStd::unordered_set* sourceDependencies) const { const auto materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); @@ -270,7 +274,7 @@ namespace AZ // Create the material asset from all the previously loaded source data MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); - materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + materialAssetCreator.Begin(assetId, materialTypeAsset.GetValue()); while (!parentSourceDataStack.empty()) { @@ -283,6 +287,13 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { + // Unlike CreateMaterialAsset(), we can always finalize the material here because we loaded created the MaterialTypeAsset from + // the source .materialtype file, so the necessary data is always available. + // (In case you are wondering why we don't use CreateMaterialAssetFromSourceData in MaterialBuilder: that would require a + // source dependency between the .materialtype and .material file, which would cause all .material files to rebuild when you + // edit the .materialtype; it's faster to not read the material type data at all ... until it's needed at runtime) + material->Finalize(); + if (sourceDependencies) { sourceDependencies->insert(dependencies.begin(), dependencies.end()); @@ -306,59 +317,26 @@ namespace AZ { materialAssetCreator.ReportWarning("Source data for material property value is invalid."); } - else + else if (property.second.m_value.Is() && AzFramework::StringFunc::Contains(property.second.m_value.GetValue(), ".")) { - MaterialPropertyIndex propertyIndex = - materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); - if (propertyIndex.IsValid()) - { - const MaterialPropertyDescriptor* propertyDescriptor = - materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); - switch (propertyDescriptor->GetDataType()) - { - case MaterialPropertyDataType::Image: - { - Data::Asset imageAsset; + Data::Asset imageAsset; - MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( - imageAsset, materialSourceFilePath, property.second.m_value.GetValue()); + MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference( + imageAsset, materialSourceFilePath, property.second.m_value.GetValue()); - if (result == MaterialUtils::GetImageAssetResult::Missing) - { - materialAssetCreator.ReportWarning( - "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), - property.second.m_value.GetValue().data()); - } - - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); - } - break; - case MaterialPropertyDataType::Enum: - { - AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); - uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); - if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) - { - materialAssetCreator.ReportError( - "Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); - } - else - { - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); - } - } - break; - default: - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); - break; - } - } - else + if (result == MaterialUtils::GetImageAssetResult::Missing) { materialAssetCreator.ReportWarning( - "Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); + "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), + property.second.m_value.GetValue().data()); } + + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); + } + else + { + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 7fff8d81bc..475c6ca219 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -135,6 +136,20 @@ namespace AZ } } } + + bool BuildersShouldFinalizeMaterialAssets() + { + // We default to the faster workflow for developers. Enable this registry setting when releasing the + // game for faster load times and obfuscation of material assets. + bool shouldFinalize = false; + + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->Get(shouldFinalize, "/O3DE/Atom/RPI/MaterialBuilder/FinalizeMaterialAssets"); + } + + return shouldFinalize; + } } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 3c6947b83d..7962844736 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -33,11 +33,12 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(11) // Material version update + ->Version(13) // added m_rawPropertyValues ->Field("materialTypeAsset", &MaterialAsset::m_materialTypeAsset) ->Field("materialTypeVersion", &MaterialAsset::m_materialTypeVersion) ->Field("propertyValues", &MaterialAsset::m_propertyValues) - ->Field("propertyNames", &MaterialAsset::m_propertyNames) + ->Field("rawPropertyValues", &MaterialAsset::m_rawPropertyValues) + ->Field("isFinalized", &MaterialAsset::m_isFinalized) ; } } @@ -102,32 +103,95 @@ namespace AZ { return m_materialTypeAsset->GetMaterialPropertiesLayout(); } - - AZStd::array_view MaterialAsset::GetPropertyValues() const + + bool MaterialAsset::IsFinalized() const { - // If property names are included, they are used to re-arrange the property value list to align with the - // MaterialPropertiesLayout. This realignment would be necessary if the material type is updated with - // a new property layout, and a corresponding material is not reprocessed by the AP and continues using the - // old property layout. - if (!m_propertyNames.empty()) + if (m_isFinalized) { - const uint32_t materialTypeVersion = m_materialTypeAsset->GetVersion(); - if (m_materialTypeVersion < materialTypeVersion) - { - // It is possible that the material type has had some properties renamed. If that's the case, and this material - // is still referencing the old property layout, we need to apply any auto updates to rename those properties - // before using them to realign the property values. - const_cast(this)->ApplyVersionUpdates(); - } + AZ_Assert(GetMaterialPropertiesLayout() && m_propertyValues.size() == GetMaterialPropertiesLayout()->GetPropertyCount(), "MaterialAsset is marked as Finalized but does not have the right number of property values."); + } - if (m_isDirty) + return m_isFinalized; + } + + void MaterialAsset::Finalize() + { + if (IsFinalized()) + { + return; + } + + const uint32_t materialTypeVersion = m_materialTypeAsset->GetVersion(); + if (m_materialTypeVersion < materialTypeVersion) + { + // It is possible that the material type has had some properties renamed or otherwise updated. If that's the case, + // and this material is still referencing the old property layout, we need to apply any auto updates to rename those + // properties before using them to realign the property values. + ApplyVersionUpdates(); + } + + const MaterialPropertiesLayout* propertyLayout = GetMaterialPropertiesLayout(); + + AZStd::vector finalizedPropertyValues(m_materialTypeAsset->GetDefaultPropertyValues().begin(), m_materialTypeAsset->GetDefaultPropertyValues().end()); + + for (const auto& [name, value] : m_rawPropertyValues) + { + const MaterialPropertyIndex propertyIndex = propertyLayout->FindPropertyIndex(name); + if (propertyIndex.IsValid()) { - const_cast(this)->RealignPropertyValuesAndNames(); + const MaterialPropertyDescriptor* propertyDescriptor = propertyLayout->GetPropertyDescriptor(propertyIndex); + + if (value.Is() && propertyDescriptor->GetDataType() == MaterialPropertyDataType::Enum) + { + AZ::Name enumName = AZ::Name(value.GetValue()); + uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); + if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) + { + AZ_Error(s_debugTraceName, false, "Material property name \"%s\" has invalid enum value \"%s\".", name.GetCStr(), enumName.GetCStr()); + } + else + { + finalizedPropertyValues[propertyIndex.GetIndex()] = enumValue; + } + } + else if (value.Is() && propertyDescriptor->GetDataType() == MaterialPropertyDataType::Image) + { + // Here we assume that the material asset builder resolved any image source file paths to an ImageAsset reference. + // So the only way a string could be present is if it's an empty image path reference, meaning no image should be bound. + AZ_Assert(value.GetValue().empty(), "Material property '%s' references in image '%s'. Image file paths must be resolved by the material asset builder."); + + finalizedPropertyValues[propertyIndex.GetIndex()] = Data::Asset{}; + } + else + { + finalizedPropertyValues[propertyIndex.GetIndex()] = value; + } + } + else + { + AZ_Warning(s_debugTraceName, false, "Material property name \"%s\" is not found in the material properties layout and will not be used.", name.GetCStr()); } } + m_propertyValues.swap(finalizedPropertyValues); + + m_isFinalized = true; + } + + const AZStd::vector& MaterialAsset::GetPropertyValues() const + { + // This can't be done in MaterialAssetHandler::LoadAssetData because the MaterialTypeAsset isn't necessarily loaded at that point. + // And it can't be done in PostLoadInit() because that happens on the next frame which might be too late. So we finalize just-in-time + // when properties are accessed. + const_cast(this)->Finalize(); + return m_propertyValues; } + + const AZStd::vector>& MaterialAsset::GetRawPropertyValues() const + { + return m_rawPropertyValues; + } void MaterialAsset::SetReady() { @@ -173,34 +237,6 @@ namespace AZ } } - void MaterialAsset::RealignPropertyValuesAndNames() - { - const MaterialPropertiesLayout* propertyLayout = GetMaterialPropertiesLayout(); - AZStd::vector alignedPropertyValues(m_materialTypeAsset->GetDefaultPropertyValues().begin(), m_materialTypeAsset->GetDefaultPropertyValues().end()); - for (size_t i = 0; i < m_propertyNames.size(); ++i) - { - const MaterialPropertyIndex propertyIndex = propertyLayout->FindPropertyIndex(m_propertyNames[i]); - if (propertyIndex.IsValid()) - { - alignedPropertyValues[propertyIndex.GetIndex()] = m_propertyValues[i]; - } - else - { - AZ_Warning(s_debugTraceName, false, "Material property name \"%s\" is not found in the material properties layout and will not be used.", m_propertyNames[i].GetCStr()); - } - } - m_propertyValues.swap(alignedPropertyValues); - - const size_t propertyCount = propertyLayout->GetPropertyCount(); - m_propertyNames.resize(propertyCount); - for (size_t i = 0; i < propertyCount; ++i) - { - m_propertyNames[i] = propertyLayout->GetPropertyDescriptor(MaterialPropertyIndex{ i })->GetName(); - } - - m_isDirty = false; - } - void MaterialAsset::ApplyVersionUpdates() { if (m_materialTypeVersion == m_materialTypeAsset->GetVersion()) @@ -248,7 +284,13 @@ namespace AZ // This also covers the case where just the MaterialTypeAsset is reloaded and not the MaterialAsset. m_materialTypeAsset = newMaterialTypeAsset; - m_isDirty = true; + // If the material asset was not finalized on disk, then we clear the previously finalized property values to force re-finalize. + // This + if (!m_wasPreFinalized) + { + m_isFinalized = false; + m_propertyValues.clear(); + } // Notify interested parties that this MaterialAsset is changed and may require other data to reinitialize as well MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset{this, AZ::Data::AssetLoadBehavior::PreLoad}); @@ -276,6 +318,7 @@ namespace AZ if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete) { asset.GetAs()->AssetInitBus::Handler::BusConnect(); + asset.GetAs()->m_wasPreFinalized = asset.GetAs()->m_isFinalized; return Data::AssetHandler::LoadResult::LoadComplete; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp index b62a91a98d..4bee663791 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp @@ -16,89 +16,19 @@ namespace AZ { namespace RPI { - void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial, bool includeMaterialPropertyNames) - { - BeginCommon(assetId); - - if (ValidateIsReady()) - { - m_asset->m_materialTypeAsset = parentMaterial.m_materialTypeAsset; - m_asset->m_materialTypeVersion = m_asset->m_materialTypeAsset->GetVersion(); - - if (!m_asset->m_materialTypeAsset) - { - ReportError("MaterialTypeAsset is null"); - return; - } - - m_materialPropertiesLayout = m_asset->GetMaterialPropertiesLayout(); - if (!m_materialPropertiesLayout) - { - ReportError("MaterialPropertiesLayout is null"); - return; - } - if (includeMaterialPropertyNames) - { - PopulatePropertyNameList(); - } - - // Note we don't have to check the validity of these property values because the parent material's AssetCreator already did that. - m_asset->m_propertyValues.assign(parentMaterial.GetPropertyValues().begin(), parentMaterial.GetPropertyValues().end()); - - auto warningFunc = [this](const char* message) - { - ReportWarning("%s", message); - }; - auto errorFunc = [this](const char* message) - { - ReportError("%s", message); - }; - MaterialAssetCreatorCommon::OnBegin(m_materialPropertiesLayout, &(m_asset->m_propertyValues), warningFunc, errorFunc); - } - } - - void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType, bool includeMaterialPropertyNames) + void MaterialAssetCreator::Begin(const Data::AssetId& assetId, const Data::Asset& materialType) { BeginCommon(assetId); if (ValidateIsReady()) { - m_asset->m_materialTypeAsset = { &materialType, AZ::Data::AssetLoadBehavior::PreLoad }; + m_asset->m_materialTypeAsset = materialType; - if (!m_asset->m_materialTypeAsset) - { - ReportError("MaterialTypeAsset is null"); - return; - } - m_asset->m_materialTypeVersion = m_asset->m_materialTypeAsset->GetVersion(); + m_asset->m_materialTypeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); - m_materialPropertiesLayout = m_asset->GetMaterialPropertiesLayout(); - if (includeMaterialPropertyNames) - { - PopulatePropertyNameList(); - } - - if (!m_materialPropertiesLayout) - { - ReportError("MaterialPropertiesLayout is null"); - return; - } - - // Note we don't have to check the validity of these property values because the parent material's AssetCreator already did that. - m_asset->m_propertyValues.assign(materialType.GetDefaultPropertyValues().begin(), materialType.GetDefaultPropertyValues().end()); - - auto warningFunc = [this](const char* message) - { - ReportWarning("%s", message); - }; - auto errorFunc = [this](const char* message) - { - ReportError("%s", message); - }; - MaterialAssetCreatorCommon::OnBegin(m_materialPropertiesLayout, &(m_asset->m_propertyValues), warningFunc, errorFunc); } } - + bool MaterialAssetCreator::End(Data::Asset& result) { if (!ValidateIsReady()) @@ -106,20 +36,39 @@ namespace AZ return false; } - m_materialPropertiesLayout = nullptr; - MaterialAssetCreatorCommon::OnEnd(); - m_asset->SetReady(); return EndCommon(result); } - - void MaterialAssetCreator::PopulatePropertyNameList() + + void MaterialAssetCreator::SetMaterialTypeVersion(uint32_t version) { - for (int i = 0; i < m_materialPropertiesLayout->GetPropertyCount(); ++i) + if (ValidateIsReady()) { - MaterialPropertyIndex propertyIndex{ i }; - auto& propertyName = m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex)->GetName(); - m_asset->m_propertyNames.emplace_back(propertyName); + m_asset->m_materialTypeVersion = version; + } + } + + void MaterialAssetCreator::SetPropertyValue(const Name& name, const MaterialPropertyValue& value) + { + if (ValidateIsReady()) + { + // Here we are careful to keep the properties in the same order they were encountered. When the MaterialAsset + // is later finalized with a MaterialTypeAsset, there could be a version update procedure that includes renamed + // properties. So it's possible that the same property could be encountered twice but with two different names. + // Preserving the original order will ensure that the later properties still overwrite the earlier ones even after + // renames have been applied. + + auto iter = AZStd::find_if(m_asset->m_rawPropertyValues.begin(), m_asset->m_rawPropertyValues.end(), [&name](const AZStd::pair& pair) + { + return pair.first == name; + }); + + if (iter != m_asset->m_rawPropertyValues.end()) + { + m_asset->m_rawPropertyValues.erase(iter); + } + + m_asset->m_rawPropertyValues.emplace_back(name, value); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index 46086dfecc..dd023c56b8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -122,6 +122,21 @@ namespace AZ return false; } + // We don't allow previously renamed property names to be reused for new properties. This would just complicate too many things, + // as every use of every property name (like in Material Component, or in scripts, for example) would have to have a version number + // associated with it, in order to know whether or which rename to apply. + for (size_t propertyIndex = 0; propertyIndex < m_asset->m_materialPropertiesLayout->GetPropertyCount(); ++propertyIndex) + { + Name originalPropertyName = m_asset->m_materialPropertiesLayout->GetPropertyDescriptor(MaterialPropertyIndex{propertyIndex})->GetName(); + Name newPropertyName = originalPropertyName; + if (versionUpdate.ApplyPropertyRenames(newPropertyName)) + { + ReportError("There was a material property named '%s' at material type version %d. This name cannot be reused for another property.", + originalPropertyName.GetCStr(), versionUpdate.GetVersion()); + return false; + } + } + prevVersion = versionUpdate.GetVersion(); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialVersionUpdate.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialVersionUpdate.cpp index f5dfe9e80c..f12c865eee 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialVersionUpdate.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialVersionUpdate.cpp @@ -77,18 +77,14 @@ namespace AZ { bool changesWereApplied = false; - for (auto& propertyName : materialAsset.m_propertyNames) + for (auto& [name, value] : materialAsset.m_rawPropertyValues) { - for (const auto& action : m_actions) + if (ApplyPropertyRenames(name)) { - if (propertyName == action.m_fromPropertyId) - { - propertyName = action.m_toPropertyId; - changesWereApplied = true; - } + changesWereApplied = true; } } - + return changesWereApplied; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 97d8d5e354..93da118b5b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -680,12 +680,6 @@ namespace MaterialEditor return false; } m_materialTypeSourceData = materialTypeOutcome.GetValue(); - - if (MaterialSourceData::ApplyVersionUpdatesResult::Failed == m_materialSourceData.ApplyVersionUpdates(m_absolutePath)) - { - AZ_Error("MaterialDocument", false, "Material source data could not be auto updated to the latest version of the material type: '%s'.", m_materialSourceData.m_materialType.c_str()); - return false; - } } else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension)) { From a627cda5aeee1c7d2714045f5b58b51b57440393 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 17 Dec 2021 17:05:27 -0800 Subject: [PATCH 15/36] Got the unit tests working again. I made MaterialAsset::Finalize private so I could add some parameters specifically for MaterialAssetCreator to use. Now MaterialAssetCreator::Begin has an option to finalize the material or not. Moved MaterialAssetCreatorCommon::ValidateDataType to MaterialPropertyDescriptor as "ValidateMaterialPropertyDataType" so that MaterialAsset::Finalize could use it too Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Edit/Material/MaterialUtils.h | 1 + .../Include/Atom/RPI.Reflect/AssetCreator.h | 1 + .../Atom/RPI.Reflect/Material/MaterialAsset.h | 12 +- .../Material/MaterialAssetCreator.h | 24 +- .../Material/MaterialAssetCreatorCommon.h | 6 - .../Material/MaterialPropertyDescriptor.h | 5 + .../RPI.Builders/Material/MaterialBuilder.cpp | 2 +- .../Model/MaterialAssetBuilderComponent.cpp | 2 +- .../RPI.Edit/Material/MaterialSourceData.cpp | 23 +- .../RPI.Edit/Material/MaterialUtils.cpp | 1 + .../RPI.Reflect/Material/MaterialAsset.cpp | 27 +- .../Material/MaterialAssetCreator.cpp | 34 ++- .../Material/MaterialAssetCreatorCommon.cpp | 54 +--- .../Material/MaterialPropertyDescriptor.cpp | 51 ++++ .../Material/LuaMaterialFunctorTests.cpp | 8 +- .../Tests/Material/MaterialAssetTests.cpp | 166 +++++++---- .../Tests/Material/MaterialFunctorTests.cpp | 2 +- .../Material/MaterialSourceDataTests.cpp | 282 ++++-------------- .../RPI/Code/Tests/Material/MaterialTests.cpp | 22 +- 19 files changed, 333 insertions(+), 390 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index 2fb55e5f40..2a992159b3 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -69,6 +69,7 @@ namespace AZ //! Finalizing during asset processing reduces load times and obfuscates the material data. //! Waiting to finalize at load time reduces dependencies on the material type data, resulting in fewer asset rebuilds and less time spent processing assets. bool BuildersShouldFinalizeMaterialAssets(); + } } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h index 79d43d0b8d..257abcc785 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h @@ -28,6 +28,7 @@ namespace AZ // [GFX TODO] We need to iterate on this concept at some point. We may want to expose it through cvars or something // like that, or we may not need this at all. For now it's helpful for testing. void SetElevateWarnings(bool elevated); + bool GetElevateWarnings() const { return m_warningsElevated; } int GetErrorCount() const { return m_errorCount; } int GetWarningCount() const { return m_warningCount; } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 34e51b40af..736d7c5b53 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -110,11 +111,6 @@ namespace AZ //! If false, property values can be accessed through GetRawPropertyValues(). bool IsFinalized() const; - //! If the material asset is not finalized yet, this does the final processing of m_rawPropertyValues to - //! get the material asset ready to be used. - //! Note m_materialTypeAsset must be valid before this is called. - void Finalize(); - //! Returns the list of values for all properties in this material. //! The entries in this list align with the entries in the MaterialPropertiesLayout. Each AZStd::any is guaranteed //! to have a value of type that matches the corresponding MaterialPropertyDescriptor. @@ -129,6 +125,12 @@ namespace AZ private: bool PostLoadInit() override; + //! If the material asset is not finalized yet, this does the final processing of m_rawPropertyValues to + //! get the material asset ready to be used. + //! Note m_materialTypeAsset must be valid before this is called. + //! @param elevateWarnings Indicates whether to treat warnings as errors + void Finalize(AZStd::function reportWarning = nullptr, AZStd::function reportError = nullptr); + //! Checks the material type version and potentially applies a series of property changes (most common are simple property renames) //! based on the MaterialTypeAsset's version update procedure. void ApplyVersionUpdates(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h index b7b1f9705f..74bd909e08 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h @@ -9,30 +9,38 @@ #include #include +#include +#include namespace AZ { namespace RPI { //! Use a MaterialAssetCreator to create and configure a new MaterialAsset. - //! The MaterialAsset will be based on a MaterialTypeAsset or another MaterialAsset. - //! Either way, the base provides the necessary data to define the layout - //! and behavior of the material. The MaterialAsset only provides property value overrides. - //! Note however that the MaterialTypeAsset does not have to be loaded and available yet; - //! only the AssetId is required. The resulting MaterialAsset will be in a non-finalized state; - //! it must be finalized afterwards when the MaterialTypeAsset is available before it can be used. + //! + //! There are two options for how to create the MaterialAsset, whether it should be finalized now or deferred. + //! - Finalized now: This requires the MaterialTypeAsset to be fully populated so it can read the property layout. + //! - Deferred finalize: This only requires the MaterialTypeAsset to have a valid AssetId; the data inside will not be used. MaterialAsset::Finalize() + //! will need to be called later when the final MaterialTypeAsset is available, presumably after loading the MaterialAsset at runtime. class MaterialAssetCreator : public AssetCreator { public: friend class MaterialSourceData; - - void Begin(const Data::AssetId& assetId, const Data::Asset& materialType); + + void Begin(const Data::AssetId& assetId, const Data::Asset& materialType, bool shouldFinalize); bool End(Data::Asset& result); void SetMaterialTypeVersion(uint32_t version); void SetPropertyValue(const Name& name, const MaterialPropertyValue& value); + + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + + private: + bool m_shouldFinalize = false; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h index 312739a0f0..c7fa9c2a4c 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h @@ -52,12 +52,6 @@ namespace AZ private: bool PropertyCheck(TypeId typeId, const Name& name); - //! Returns the MaterialPropertyDataType value that corresponds to typeId - MaterialPropertyDataType GetMaterialPropertyDataType(TypeId typeId) const; - - //! Checks that the TypeId typeId matches the type expected by materialPropertyDescriptor - bool ValidateDataType(TypeId typeId, const Name& propertyName, const MaterialPropertyDescriptor* materialPropertyDescriptor); - const MaterialPropertiesLayout* m_propertyLayout = nullptr; //! Points to the m_propertyValues list in a MaterialAsset or MaterialTypeAsset AZStd::vector* m_propertyValues = nullptr; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h index 76bb2a6113..bd18c98780 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h @@ -17,6 +17,8 @@ namespace AZ { namespace RPI { + class MaterialPropertyDescriptor; + struct MaterialPropertyIndexType { AZ_TYPE_INFO(MaterialPropertyIndexType, "{cfc09268-f3f1-4474-bd8f-f2c8de27c5f1}"); }; @@ -76,6 +78,9 @@ namespace AZ const char* ToString(MaterialPropertyDataType materialPropertyDataType); AZStd::string GetMaterialPropertyDataTypeString(AZ::TypeId typeId); + + //! Checks that the TypeId matches the type expected by materialPropertyDescriptor + bool ValidateMaterialPropertyDataType(TypeId typeId, const Name& propertyName, const MaterialPropertyDescriptor* materialPropertyDescriptor, AZStd::function onError); //! A material property is any data input to a material, like a bool, float, Vector, Image, Buffer, etc. //! This descriptor defines a single input property, including it's name ID, and how it maps diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 1b5635a1c1..3aa8728e08 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -52,7 +52,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 111; // material dependency improvements + materialBuilderDescriptor.m_version = 112; // material dependency improvements materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index ef251b6848..6f71fb70d4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -127,7 +127,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(17); // Optional material conversion + ->Version(18); // material dependency improvements } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index cd01544bfa..23657f4871 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -114,7 +114,7 @@ namespace AZ } } - materialAssetCreator.Begin(assetId, materialTypeAsset); + materialAssetCreator.Begin(assetId, materialTypeAsset, processingMode == MaterialAssetProcessingMode::PreBake); if (!m_parentMaterial.empty()) { @@ -180,11 +180,6 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { - if (processingMode == MaterialAssetProcessingMode::PreBake) - { - material->Finalize(); - } - return Success(material); } else @@ -270,11 +265,18 @@ namespace AZ parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); parentSourceDataStack.emplace_back(AZStd::move(parentSourceData)); } + + // Unlike CreateMaterialAsset(), we can always finalize the material here because we loaded created the MaterialTypeAsset from + // the source .materialtype file, so the necessary data is always available. + // (In case you are wondering why we don't use CreateMaterialAssetFromSourceData in MaterialBuilder: that would require a + // source dependency between the .materialtype and .material file, which would cause all .material files to rebuild when you + // edit the .materialtype; it's faster to not read the material type data at all ... until it's needed at runtime) + const bool finalize = true; // Create the material asset from all the previously loaded source data MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); - materialAssetCreator.Begin(assetId, materialTypeAsset.GetValue()); + materialAssetCreator.Begin(assetId, materialTypeAsset.GetValue(), finalize); while (!parentSourceDataStack.empty()) { @@ -287,13 +289,6 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { - // Unlike CreateMaterialAsset(), we can always finalize the material here because we loaded created the MaterialTypeAsset from - // the source .materialtype file, so the necessary data is always available. - // (In case you are wondering why we don't use CreateMaterialAssetFromSourceData in MaterialBuilder: that would require a - // source dependency between the .materialtype and .material file, which would cause all .material files to rebuild when you - // edit the .materialtype; it's faster to not read the material type data at all ... until it's needed at runtime) - material->Finalize(); - if (sourceDependencies) { sourceDependencies->insert(dependencies.begin(), dependencies.end()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 475c6ca219..2fe30f632f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -150,6 +150,7 @@ namespace AZ return shouldFinalize; } + } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 7962844736..ce5847d12f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -114,13 +114,29 @@ namespace AZ return m_isFinalized; } - void MaterialAsset::Finalize() + void MaterialAsset::Finalize(AZStd::function reportWarning, AZStd::function reportError) { if (IsFinalized()) { return; } + if (!reportWarning) + { + reportWarning = [](const char* message) + { + AZ_Warning(s_debugTraceName, false, "%s", message); + }; + } + + if (!reportError) + { + reportError = [](const char* message) + { + AZ_Error(s_debugTraceName, false, "%s", message); + }; + } + const uint32_t materialTypeVersion = m_materialTypeAsset->GetVersion(); if (m_materialTypeVersion < materialTypeVersion) { @@ -147,7 +163,7 @@ namespace AZ uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) { - AZ_Error(s_debugTraceName, false, "Material property name \"%s\" has invalid enum value \"%s\".", name.GetCStr(), enumName.GetCStr()); + reportWarning(AZStd::string::format("Material property name \"%s\" has invalid enum value \"%s\".", name.GetCStr(), enumName.GetCStr()).c_str()); } else { @@ -164,12 +180,15 @@ namespace AZ } else { - finalizedPropertyValues[propertyIndex.GetIndex()] = value; + if (ValidateMaterialPropertyDataType(value.GetTypeId(), name, propertyDescriptor, reportError)) + { + finalizedPropertyValues[propertyIndex.GetIndex()] = value; + } } } else { - AZ_Warning(s_debugTraceName, false, "Material property name \"%s\" is not found in the material properties layout and will not be used.", name.GetCStr()); + reportWarning(AZStd::string::format("Material property name \"%s\" is not found in the material properties layout and will not be used.", name.GetCStr()).c_str()); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp index 4bee663791..f05fb8d848 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp @@ -16,16 +16,21 @@ namespace AZ { namespace RPI { - void MaterialAssetCreator::Begin(const Data::AssetId& assetId, const Data::Asset& materialType) + void MaterialAssetCreator::Begin(const Data::AssetId& assetId, const Data::Asset& materialType, bool shouldFinalize) { BeginCommon(assetId); if (ValidateIsReady()) { + m_shouldFinalize = shouldFinalize; + m_asset->m_materialTypeAsset = materialType; - m_asset->m_materialTypeAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); - + + if (shouldFinalize && !m_asset->m_materialTypeAsset) + { + ReportError("MaterialTypeAsset is null, the MaterialAsset cannot be finalized"); + } } } @@ -37,6 +42,14 @@ namespace AZ } m_asset->SetReady(); + + if (m_shouldFinalize) + { + m_asset->Finalize( + [this](const char* message) { ReportWarning("%s", message); }, + [this](const char* message) { ReportError("%s", message); }); + } + return EndCommon(result); } @@ -71,6 +84,21 @@ namespace AZ m_asset->m_rawPropertyValues.emplace_back(name, value); } } + + void MaterialAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + SetPropertyValue(name, MaterialPropertyValue{imageAsset}); + } + + void MaterialAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + SetPropertyValue(name, Data::Asset(imageAsset)); + } + + void MaterialAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + SetPropertyValue(name, Data::Asset(imageAsset)); + } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp index 1ba74ce0b9..4b2f163f7c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp @@ -7,6 +7,7 @@ */ #include +#include namespace AZ { @@ -32,57 +33,6 @@ namespace AZ m_reportError = nullptr; } - MaterialPropertyDataType MaterialAssetCreatorCommon::GetMaterialPropertyDataType(TypeId typeId) const - { - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Bool; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Int; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::UInt; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Float; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector2; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector3; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector4; } - if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Color; } - if (typeId == azrtti_typeid>()) { return MaterialPropertyDataType::Image; } - else - { - return MaterialPropertyDataType::Invalid; - } - } - - bool MaterialAssetCreatorCommon::ValidateDataType(TypeId typeId, const Name& propertyName, const MaterialPropertyDescriptor* materialPropertyDescriptor) - { - auto expectedDataType = materialPropertyDescriptor->GetDataType(); - auto actualDataType = GetMaterialPropertyDataType(typeId); - - if (expectedDataType == MaterialPropertyDataType::Enum) - { - if (actualDataType != MaterialPropertyDataType::UInt) - { - m_reportError( - AZStd::string::format("Material property '%s' is a Enum type, can only accept UInt value, input value is %s", - propertyName.GetCStr(), - ToString(actualDataType) - ).data()); - return false; - } - } - else - { - if (expectedDataType != actualDataType) - { - m_reportError( - AZStd::string::format("Material property '%s': Type mismatch. Expected %s but was %s", - propertyName.GetCStr(), - ToString(expectedDataType), - ToString(actualDataType) - ).data()); - return false; - } - } - - return true; - } - bool MaterialAssetCreatorCommon::PropertyCheck(TypeId typeId, const Name& name) { if (!m_reportWarning || !m_reportError) @@ -108,7 +58,7 @@ namespace AZ return false; } - if (!ValidateDataType(typeId, name, materialPropertyDescriptor)) + if (!ValidateMaterialPropertyDataType(typeId, name, materialPropertyDescriptor, m_reportError)) { return false; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp index 5d0a88a6d3..ddbb902761 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp @@ -97,6 +97,57 @@ namespace AZ return AZStd::string::format("", typeId.ToString().c_str()); } } + + bool ValidateMaterialPropertyDataType(TypeId typeId, const Name& propertyName, const MaterialPropertyDescriptor* materialPropertyDescriptor, AZStd::function onError) + { + auto toMaterialPropertyDataType = [](TypeId typeId) + { + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Bool; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Int; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::UInt; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Float; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector2; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector3; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Vector4; } + if (typeId == azrtti_typeid()) { return MaterialPropertyDataType::Color; } + if (typeId == azrtti_typeid>()) { return MaterialPropertyDataType::Image; } + else + { + return MaterialPropertyDataType::Invalid; + } + }; + + auto expectedDataType = materialPropertyDescriptor->GetDataType(); + auto actualDataType = toMaterialPropertyDataType(typeId); + + if (expectedDataType == MaterialPropertyDataType::Enum) + { + if (actualDataType != MaterialPropertyDataType::UInt) + { + onError( + AZStd::string::format("Material property '%s' is a Enum type, can only accept UInt value, input value is %s", + propertyName.GetCStr(), + ToString(actualDataType) + ).data()); + return false; + } + } + else + { + if (expectedDataType != actualDataType) + { + onError( + AZStd::string::format("Material property '%s': Type mismatch. Expected %s but was %s", + propertyName.GetCStr(), + ToString(expectedDataType), + ToString(actualDataType) + ).data()); + return false; + } + } + + return true; + } void MaterialPropertyOutputId::Reflect(ReflectContext* context) { diff --git a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp index 2608ac3a9b..5016f8303e 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp @@ -112,7 +112,7 @@ namespace UnitTest Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_materialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true); EXPECT_TRUE(materialCreator.End(materialAsset)); m_material = Material::Create(materialAsset); @@ -138,7 +138,7 @@ namespace UnitTest Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_materialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(),m_materialTypeAsset, true); EXPECT_TRUE(materialCreator.End(materialAsset)); m_material = Material::Create(materialAsset); @@ -165,7 +165,7 @@ namespace UnitTest Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_materialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true); EXPECT_TRUE(materialCreator.End(materialAsset)); m_material = Material::Create(materialAsset); @@ -194,7 +194,7 @@ namespace UnitTest Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_materialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true); EXPECT_TRUE(materialCreator.End(materialAsset)); m_material = Material::Create(materialAsset); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp index 58a852f176..633953cecc 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp @@ -94,7 +94,7 @@ namespace UnitTest Data::AssetId assetId(Uuid::CreateRandom()); MaterialAssetCreator creator; - creator.Begin(assetId, *m_testMaterialTypeAsset); + creator.Begin(assetId, m_testMaterialTypeAsset, true); creator.SetPropertyValue(Name{ "MyFloat2" }, Vector2{ 0.1f, 0.2f }); creator.SetPropertyValue(Name{ "MyFloat3" }, Vector3{ 1.1f, 1.2f, 1.3f }); creator.SetPropertyValue(Name{ "MyFloat4" }, Vector4{ 2.1f, 2.2f, 2.3f, 2.4f }); @@ -129,7 +129,7 @@ namespace UnitTest Data::AssetId assetId(Uuid::CreateRandom()); MaterialAssetCreator creator; - creator.Begin(assetId, *m_testMaterialTypeAsset); + creator.Begin(assetId, m_testMaterialTypeAsset, true); creator.SetPropertyValue(Name{ "MyFloat" }, 3.14f); Data::Asset materialAsset; @@ -171,7 +171,7 @@ namespace UnitTest Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *emptyMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), emptyMaterialTypeAsset, true); EXPECT_TRUE(materialCreator.End(materialAsset)); EXPECT_EQ(emptyMaterialTypeAsset, materialAsset->GetMaterialTypeAsset()); EXPECT_EQ(materialAsset->GetPropertyValues().size(), 0); @@ -189,7 +189,7 @@ namespace UnitTest Data::AssetId assetId(Uuid::CreateRandom()); MaterialAssetCreator creator; - creator.Begin(assetId, *m_testMaterialTypeAsset); + creator.Begin(assetId, m_testMaterialTypeAsset, true); creator.SetPropertyValue(Name{ "MyImage" }, streamingImageAsset); Data::Asset materialAsset; @@ -231,8 +231,8 @@ namespace UnitTest Data::AssetId assetId(Uuid::CreateRandom()); MaterialAssetCreator creator; - const bool includePropertyNames = true; - creator.Begin(assetId, *testMaterialTypeAssetV1, includePropertyNames); + const bool shouldFinalize = false; + creator.Begin(assetId, testMaterialTypeAssetV1, shouldFinalize); creator.SetPropertyValue(Name{ "MyInt" }, 7); creator.SetPropertyValue(Name{ "MyUInt" }, 8u); creator.SetPropertyValue(Name{ "MyFloat" }, 9.0f); @@ -307,26 +307,68 @@ namespace UnitTest // We use local functions to easily start a new MaterialAssetCreator for each test case because // the AssetCreator would just skip subsequent operations after the first failure is detected. - auto expectCreatorError = [this](AZStd::function passBadInput) + auto expectCreatorError = [this](const char* expectedErrorMessage, AZStd::function passBadInput) { - MaterialAssetCreator creator; - creator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + // Test with finalizing enabled + { + MaterialAssetCreator creator; + creator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); - AZ_TEST_START_ASSERTTEST; - passBadInput(creator); - AZ_TEST_STOP_ASSERTTEST(1); + ErrorMessageFinder errorMessageFinder; + errorMessageFinder.AddExpectedErrorMessage(expectedErrorMessage); + errorMessageFinder.AddIgnoredErrorMessage("Failed to build", true); - EXPECT_EQ(1, creator.GetErrorCount()); + passBadInput(creator); + + Data::Asset materialAsset; + EXPECT_FALSE(creator.End(materialAsset)); + + errorMessageFinder.CheckExpectedErrorsFound(); + + EXPECT_TRUE(creator.GetErrorCount() > 0); + } + + // Test with finalizing disabled, so no validation occurs because the MaterialTypeAsset data is not used. + { + MaterialAssetCreator creator; + creator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, false); + + passBadInput(creator); + + Data::Asset materialAsset; + EXPECT_TRUE(creator.End(materialAsset)); + + EXPECT_EQ(creator.GetErrorCount(), 0); + } }; auto expectCreatorWarning = [this](AZStd::function passBadInput) { - MaterialAssetCreator creator; - creator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + // Test with finalizing enabled + { + MaterialAssetCreator creator; + creator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); - passBadInput(creator); + passBadInput(creator); - EXPECT_EQ(1, creator.GetWarningCount()); + Data::Asset material; + creator.End(material); + + EXPECT_EQ(1, creator.GetWarningCount()); + } + + // Test with finalizing disabled, so no validation occurs because the MaterialTypeAsset data is not used. + { + MaterialAssetCreator creator; + creator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, false); + + passBadInput(creator); + + Data::Asset material; + creator.End(material); + + EXPECT_EQ(0, creator.GetWarningCount()); + } }; // Invalid input ID @@ -343,55 +385,65 @@ namespace UnitTest // Test data type mismatches... - expectCreatorError([this](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyBool" }, m_testImageAsset); - }); + expectCreatorError("Type mismatch", + [this](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyBool" }, m_testImageAsset); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyInt" }, 0.0f); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyInt" }, 0.0f); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyUInt" }, -1); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyUInt" }, -1); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyFloat" }, 10u); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyFloat" }, 10u); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyFloat2" }, 1.0f); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyFloat2" }, 1.0f); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyFloat3" }, AZ::Vector4{}); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyFloat3" }, AZ::Vector4{}); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyFloat4" }, AZ::Vector3{}); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyFloat4" }, AZ::Vector3{}); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyColor" }, MaterialPropertyValue(false)); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyColor" }, MaterialPropertyValue(false)); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyImage" }, true); - }); + expectCreatorError("Type mismatch", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyImage" }, true); + }); - expectCreatorError([](MaterialAssetCreator& creator) - { - creator.SetPropertyValue(Name{ "MyEnum" }, -1); - }); + expectCreatorError("can only accept UInt value", + [](MaterialAssetCreator& creator) + { + creator.SetPropertyValue(Name{ "MyEnum" }, -1); + }); } } diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index ff5d24ff9a..3373646c6e 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -275,7 +275,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialCreator.SetPropertyValue(registedPropertyName, 42); materialCreator.SetPropertyValue(unregistedPropertyName, 42); materialCreator.SetPropertyValue(unrelatedPropertyName, 42); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index d4bf3e5eaa..73aeacf818 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -175,7 +175,7 @@ namespace UnitTest AddProperty(sourceData, "general", "MyImage", AZStd::string("@exefolder@/Temp/test.streamingimage")); AddProperty(sourceData, "general", "MyEnum", AZStd::string("Enum1")); - auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetOutcome.IsSuccess()); Data::Asset materialAsset = materialAssetOutcome.GetValue(); @@ -544,17 +544,17 @@ namespace UnitTest AddPropertyGroup(sourceDataLevel3, "general"); AddProperty(sourceDataLevel3, "general", "MyFloat", 3.5f); - auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel1.IsSuccess()); m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetValue().GetId()); - auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel2.IsSuccess()); m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetValue().GetId()); - auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel3.IsSuccess()); auto layout = m_testMaterialTypeAsset->GetMaterialPropertiesLayout(); @@ -604,18 +604,18 @@ namespace UnitTest sourceDataLevel3.m_materialType = "@exefolder@/Temp/otherBase.materialtype"; sourceDataLevel3.m_parentMaterial = "level2.material"; - auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel1.IsSuccess()); m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetValue().GetId()); - auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel2.IsSuccess()); m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetValue().GetId()); AZ_TEST_START_ASSERTTEST; - auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", true); + auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); AZ_TEST_STOP_ASSERTTEST(1); EXPECT_FALSE(materialAssetLevel3.IsSuccess()); } @@ -625,7 +625,7 @@ namespace UnitTest // We use local functions to easily start a new MaterialAssetCreator for each test case because // the AssetCreator would just skip subsequent operations after the first failure is detected. - auto expectWarning = [](AZStd::function setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 1) + auto expectWarning = [](const char* expectedErrorMessage, AZStd::function setOneBadInput, bool warningOccursBeforeFinalize = false) { MaterialSourceData sourceData; @@ -635,233 +635,69 @@ namespace UnitTest setOneBadInput(sourceData); - AZ_TEST_START_ASSERTTEST; - auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", true); - AZ_TEST_STOP_ASSERTTEST(expectedAsserts); // Usually just one for when End() is called + // Check with MaterialAssetProcessingMode::PreBake + { + ErrorMessageFinder errorFinder; + errorFinder.AddExpectedErrorMessage(expectedErrorMessage); + errorFinder.AddIgnoredErrorMessage("Failed to build", true); + auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); + errorFinder.CheckExpectedErrorsFound(); - EXPECT_FALSE(materialAssetOutcome.IsSuccess()); + EXPECT_FALSE(materialAssetOutcome.IsSuccess()); + } + + // Check with MaterialAssetProcessingMode::DeferredBake, no validation occurs because the MaterialTypeAsset cannot be used and so the MaterialAsset is not finalized + if(!warningOccursBeforeFinalize) + { + auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); + EXPECT_TRUE(materialAssetOutcome.IsSuccess()); + } }; // Test property does not exist... - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", true); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", true); + }); - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", -10); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", -10); + }); - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", 25u); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", 25u); + }); - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", 1.5f); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", 1.5f); + }); - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", AZ::Color{ 0.1f, 0.2f, 0.3f, 0.4f }); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", AZ::Color{ 0.1f, 0.2f, 0.3f, 0.4f }); + }); - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "DoesNotExist", AZStd::string("@exefolder@/Temp/test.streamingimage")); - }); + expectWarning("\"general.DoesNotExist\" is not found in the material properties layout", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "DoesNotExist", AZStd::string("@exefolder@/Temp/test.streamingimage")); + }); // Missing image reference - expectWarning([](MaterialSourceData& materialSourceData) - { - AddProperty(materialSourceData, "general", "MyImage", AZStd::string("doesNotExist.streamingimage")); - }); - } - - - TEST_F(MaterialSourceDataTests, Load_MaterialTypeVersionUpdate) - { - const AZStd::string inputJson = R"( - { - "materialType": "@exefolder@/Temp/test.materialtype", - "materialTypeVersion": 1, - "properties": { - "general": { - "testColorNameA": [0.1, 0.2, 0.3] - } - } - } - )"; - - 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["general"].find("testColorNameA"), material.m_properties["general"].end()); - EXPECT_EQ(material.m_properties["general"].find("testColorNameB"), material.m_properties["general"].end()); - EXPECT_EQ(material.m_properties["general"].find("testColorNameC"), material.m_properties["general"].end()); - EXPECT_EQ(material.m_properties["general"].find("MyColor"), material.m_properties["general"].end()); - - AZ::Color testColor = material.m_properties["general"]["testColorNameA"].m_value.GetValue(); - EXPECT_TRUE(AZ::Color(0.1f, 0.2f, 0.3f, 1.0f).IsClose(testColor, 0.01)); - - EXPECT_EQ(1, 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 '1'"); - 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["general"].find("testColorNameA"), material.m_properties["general"].end()); - EXPECT_EQ(material.m_properties["general"].find("testColorNameB"), material.m_properties["general"].end()); - EXPECT_EQ(material.m_properties["general"].find("testColorNameC"), material.m_properties["general"].end()); - EXPECT_NE(material.m_properties["general"].find("MyColor"), material.m_properties["general"].end()); - - testColor = material.m_properties["general"]["MyColor"].m_value.GetValue(); - EXPECT_TRUE(AZ::Color(0.1f, 0.2f, 0.3f, 1.0f).IsClose(testColor, 0.01)); - - 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_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(); - EXPECT_EQ(myFloat, 1.2f); - - int32_t myInt = material.m_properties["oldGroup"]["MyIntOldName"].m_value.GetValue(); - 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(); - EXPECT_EQ(myFloat, 1.2f); - - myInt = material.m_properties["general"]["MyInt"].m_value.GetValue(); - 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 - // version so only some of the version updates are applied. - - const AZStd::string inputJson = R"( - { - "materialType": "@exefolder@/Temp/test.materialtype", - "materialTypeVersion": 3, - "properties": { - "general": { - "testColorNameB": [0.1, 0.2, 0.3] - } - } - } - )"; - - 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()); - - material.ApplyVersionUpdates(); - - AZ::Color testColor = material.m_properties["general"]["MyColor"].m_value.GetValue(); - EXPECT_TRUE(AZ::Color(0.1f, 0.2f, 0.3f, 1.0f).IsClose(testColor, 0.01)); - - EXPECT_EQ(10, material.m_materialTypeVersion); - } - - TEST_F(MaterialSourceDataTests, Load_Error_MaterialTypeVersionUpdateWithMismatchedVersion) - { - const AZStd::string inputJson = R"( - { - "materialType": "@exefolder@/Temp/test.materialtype", - "materialTypeVersion": 3, // At this version, the property should be testColorNameB not testColorNameA - "properties": { - "general": { - "testColorNameA": [0.1, 0.2, 0.3] - } - } - } - )"; - - MaterialSourceData material; - JsonTestResult loadResult = LoadTestDataFromJson(material, inputJson); - - loadResult.ContainsMessage("/properties/general/testColorNameA", "Property 'general.testColorNameA' not found in material type."); - - EXPECT_FALSE(material.m_properties["general"]["testColorNameA"].m_value.IsValid()); - - material.ApplyVersionUpdates(); - - EXPECT_FALSE(material.m_properties["general"]["MyColor"].m_value.IsValid()); + expectWarning("Could not find the image 'doesNotExist.streamingimage'", + [](MaterialSourceData& materialSourceData) + { + AddProperty(materialSourceData, "general", "MyImage", AZStd::string("doesNotExist.streamingimage")); + }, true); // In this case, the warning does happen even when the asset is not finalized, because the image path is checked earlier than that } } diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp index 477978875b..569f8f6df0 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp @@ -85,7 +85,7 @@ namespace UnitTest m_testImage = StreamingImage::FindOrCreate(m_testImageAsset); MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialCreator.SetPropertyValue(Name{ "MyFloat2" }, Vector2{ 0.1f, 0.2f }); materialCreator.SetPropertyValue(Name{ "MyFloat3" }, Vector3{ 1.1f, 1.2f, 1.3f }); materialCreator.SetPropertyValue(Name{ "MyFloat4" }, Vector4{ 2.1f, 2.2f, 2.3f, 2.4f }); @@ -289,7 +289,7 @@ namespace UnitTest materialTypeCreator.End(materialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *materialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), materialTypeAsset, true); materialAssetCreator.End(materialAsset); Data::Instance material = Material::FindOrCreate(materialAsset); @@ -341,7 +341,7 @@ namespace UnitTest Data::Asset materialAssetWithEmptyImage; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialCreator.SetPropertyValue(Name{"MyFloat2"}, Vector2{0.1f, 0.2f}); materialCreator.SetPropertyValue(Name{"MyFloat3"}, Vector3{1.1f, 1.2f, 1.3f}); materialCreator.SetPropertyValue(Name{"MyFloat4"}, Vector4{2.1f, 2.2f, 2.3f, 2.4f}); @@ -379,7 +379,7 @@ namespace UnitTest Data::Asset emptyMaterialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *emptyMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), emptyMaterialTypeAsset, true); EXPECT_TRUE(materialCreator.End(emptyMaterialAsset)); Data::Instance material = Material::FindOrCreate(emptyMaterialAsset); @@ -450,7 +450,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialAssetCreator.End(m_testMaterialAsset); Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); @@ -521,7 +521,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialAssetCreator.End(m_testMaterialAsset); Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); @@ -591,7 +591,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialAssetCreator.End(m_testMaterialAsset); Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); @@ -655,7 +655,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialAssetCreator.End(m_testMaterialAsset); Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); @@ -669,7 +669,7 @@ namespace UnitTest { Data::Asset materialAsset; MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialCreator.SetPropertyValue(Name{ "MyFloat2" }, Vector2{ 0.1f, 0.2f }); materialCreator.SetPropertyValue(Name{ "MyFloat3" }, Vector3{ 1.1f, 1.2f, 1.3f }); materialCreator.SetPropertyValue(Name{ "MyFloat4" }, Vector4{ 2.1f, 2.2f, 2.3f, 2.4f }); @@ -778,7 +778,7 @@ namespace UnitTest materialTypeCreator.End(materialTypeAsset); MaterialAssetCreator materialAssetCreator; - materialAssetCreator.Begin(Uuid::CreateRandom(), *materialTypeAsset); + materialAssetCreator.Begin(Uuid::CreateRandom(), materialTypeAsset, true); materialAssetCreator.End(materialAsset); Data::Instance material = Material::FindOrCreate(materialAsset); @@ -859,7 +859,7 @@ namespace UnitTest materialTypeCreator.End(m_testMaterialTypeAsset); MaterialAssetCreator materialCreator; - materialCreator.Begin(Uuid::CreateRandom(), *m_testMaterialTypeAsset); + materialCreator.Begin(Uuid::CreateRandom(), m_testMaterialTypeAsset, true); materialCreator.End(m_testMaterialAsset); Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); From 1fa1eaad158fae98e0339411e3fead04a6b120c9 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 28 Dec 2021 17:51:43 -0800 Subject: [PATCH 16/36] Added unit tests for the new functionality. I found a mistake where MaterialAssetCreator needs to clear the raw data when configured to finalize the material asset. Since MaterialSourceData no longer relies on the material type source file at all, I was able to change MaterialSourceDataTest to avoid saving the source data to disk. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Edit/Material/MaterialUtils.h | 1 - .../Atom/RPI.Reflect/Material/MaterialAsset.h | 1 - .../RPI.Edit/Material/MaterialUtils.cpp | 1 - .../Material/MaterialAssetCreator.cpp | 5 + .../Material/MaterialSourceDataTests.cpp | 248 ++++++++++++++++-- 5 files changed, 230 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h index 2a992159b3..2fb55e5f40 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialUtils.h @@ -69,7 +69,6 @@ namespace AZ //! Finalizing during asset processing reduces load times and obfuscates the material data. //! Waiting to finalize at load time reduces dependencies on the material type data, resulting in fewer asset rebuilds and less time spent processing assets. bool BuildersShouldFinalizeMaterialAssets(); - } } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 736d7c5b53..4cc6608225 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 2fe30f632f..475c6ca219 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -150,7 +150,6 @@ namespace AZ return shouldFinalize; } - } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp index f05fb8d848..7d4ecf0b18 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp @@ -48,6 +48,11 @@ namespace AZ m_asset->Finalize( [this](const char* message) { ReportWarning("%s", message); }, [this](const char* message) { ReportError("%s", message); }); + + // Finalize() doesn't clear the raw property data because that's the same function used at runtime, which does need to maintain the raw data + // to support hot reload. But here we are pre-baking with the assumption that AP build dependencies will keep the material type + // and material asset in sync, so we can discard the raw property data and just rely on the data in the material type asset. + m_asset->m_rawPropertyValues.clear(); } return EndCommon(result); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index 73aeacf818..e4d3cc9768 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -65,9 +66,29 @@ namespace UnitTest m_testShaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), m_testMaterialSrgLayout); m_assetSystemStub.RegisterSourceInfo("@exefolder@/Temp/test.shader", m_testShaderAsset.GetId()); - // The MaterialSourceData relies on both MaterialTypeSourceData and MaterialTypeAsset. We have to make sure the - // .materialtype file is present on disk, and that the MaterialTypeAsset is available through the asset database stub... + m_testMaterialTypeAsset = CreateTestMaterialTypeAsset(Uuid::CreateRandom()); + // Since this test doesn't actually instantiate a Material, it won't need to instantiate this ImageAsset, so all we + // need is an asset reference with a valid ID. + m_testImageAsset = Data::Asset{ Data::AssetId{Uuid::CreateRandom(), StreamingImageAsset::GetImageAssetSubId()}, azrtti_typeid() }; + + // Register the test assets with the AssetSystemStub so CreateMaterialAsset() can use AssetUtils. + m_assetSystemStub.RegisterSourceInfo("@exefolder@/Temp/test.materialtype", m_testMaterialTypeAsset.GetId()); + m_assetSystemStub.RegisterSourceInfo("@exefolder@/Temp/test.streamingimage", m_testImageAsset.GetId()); + } + + void TearDown() override + { + m_testMaterialTypeAsset.Reset(); + m_testMaterialSrgLayout = nullptr; + m_testShaderAsset.Reset(); + m_testImageAsset.Reset(); + + RPITestFixture::TearDown(); + } + + Data::Asset CreateTestMaterialTypeAsset(Data::AssetId assetId) + { const char* materialTypeJson = R"( { "version": 10, @@ -122,29 +143,10 @@ namespace UnitTest } )"; - AZ::Utils::WriteFile(materialTypeJson, "@exefolder@/Temp/test.materialtype"); MaterialTypeSourceData materialTypeSourceData; LoadTestDataFromJson(materialTypeSourceData, materialTypeJson); - m_testMaterialTypeAsset = materialTypeSourceData.CreateMaterialTypeAsset(Uuid::CreateRandom()).TakeValue(); - - // Since this test doesn't actually instantiate a Material, it won't need to instantiate this ImageAsset, so all we - // need is an asset reference with a valid ID. - m_testImageAsset = Data::Asset{ Data::AssetId{Uuid::CreateRandom(), StreamingImageAsset::GetImageAssetSubId()}, azrtti_typeid() }; - - // Register the test assets with the AssetSystemStub so CreateMaterialAsset() can use AssetUtils. - m_assetSystemStub.RegisterSourceInfo("@exefolder@/Temp/test.materialtype", m_testMaterialTypeAsset.GetId()); - m_assetSystemStub.RegisterSourceInfo("@exefolder@/Temp/test.streamingimage", m_testImageAsset.GetId()); - } - - void TearDown() override - { - m_testMaterialTypeAsset.Reset(); - m_testMaterialSrgLayout = nullptr; - m_testShaderAsset.Reset(); - m_testImageAsset.Reset(); - - RPITestFixture::TearDown(); + return materialTypeSourceData.CreateMaterialTypeAsset(assetId).TakeValue(); } }; @@ -180,7 +182,10 @@ namespace UnitTest Data::Asset materialAsset = materialAssetOutcome.GetValue(); - // The order here is based on the order in the MaterialTypeSourceData, as added to the the MaterialTypeAssetCreator. + EXPECT_TRUE(materialAsset->IsFinalized()); + EXPECT_EQ(0, materialAsset->GetRawPropertyValues().size()); // A pre-baked material has no need for the original raw property names and values + + // The order here is based on the order in the MaterialTypeSourceData, as added to the MaterialTypeAssetCreator. EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue(), true); EXPECT_EQ(materialAsset->GetPropertyValues()[1].GetValue(), -10); EXPECT_EQ(materialAsset->GetPropertyValues()[2].GetValue(), 25u); @@ -192,6 +197,105 @@ namespace UnitTest EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue>(), m_testImageAsset); EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue(), 1u); } + + TEST_F(MaterialSourceDataTests, CreateMaterialAsset_DeferredBake) + { + // This test is similar to CreateMaterialAsset_BasicProperties but uses MaterialAssetProcessingMode::DeferredBake instead of PreBake. + + Data::AssetId materialTypeAssetId = Uuid::CreateRandom(); + + // This material type asset will be known by the asset system (stub) but doesn't exist in the AssetManager. + // This demonstrates that the CreateMaterialAsset does not attempt to access the MaterialTypeAsset data in MaterialAssetProcessingMode::DeferredBake. + m_assetSystemStub.RegisterSourceInfo("testDeferredBake.materialtype", materialTypeAssetId); + + MaterialSourceData sourceData; + + sourceData.m_materialType = "testDeferredBake.materialtype"; + AddPropertyGroup(sourceData, "general"); + AddProperty(sourceData, "general", "MyBool" , true); + AddProperty(sourceData, "general", "MyInt" , -10); + AddProperty(sourceData, "general", "MyUInt" , 25u); + AddProperty(sourceData, "general", "MyFloat" , 1.5f); + AddProperty(sourceData, "general", "MyColor" , AZ::Color{0.1f, 0.2f, 0.3f, 0.4f}); + AddProperty(sourceData, "general", "MyFloat2", AZ::Vector2(2.1f, 2.2f)); + AddProperty(sourceData, "general", "MyFloat3", AZ::Vector3(3.1f, 3.2f, 3.3f)); + AddProperty(sourceData, "general", "MyFloat4", AZ::Vector4(4.1f, 4.2f, 4.3f, 4.4f)); + AddProperty(sourceData, "general", "MyImage" , AZStd::string("@exefolder@/Temp/test.streamingimage")); + AddProperty(sourceData, "general", "MyEnum" , AZStd::string("Enum1")); + + auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); + EXPECT_TRUE(materialAssetOutcome.IsSuccess()); + + Data::Asset materialAsset = materialAssetOutcome.GetValue(); + + EXPECT_FALSE(materialAsset->IsFinalized()); + // Note we avoid calling GetPropertyValues() because that will auto-finalize the material. We want to check its raw property values first. + + auto findRawPropertyValue = [materialAsset](const char* propertyId) + { + auto iter = AZStd::find_if(materialAsset->GetRawPropertyValues().begin(), materialAsset->GetRawPropertyValues().end(), [propertyId](const AZStd::pair& pair) + { + return pair.first == AZ::Name{propertyId}; + }); + + if (iter == materialAsset->GetRawPropertyValues().end()) + { + return MaterialPropertyValue{}; + } + else + { + return iter->second; + } + }; + + auto checkRawPropertyValues = [findRawPropertyValue, this]() + { + EXPECT_EQ(findRawPropertyValue("general.MyBool" ).GetValue(), true); + EXPECT_EQ(findRawPropertyValue("general.MyInt" ).GetValue(), -10); + EXPECT_EQ(findRawPropertyValue("general.MyUInt" ).GetValue(), 25u); + EXPECT_EQ(findRawPropertyValue("general.MyFloat" ).GetValue(), 1.5f); + EXPECT_EQ(findRawPropertyValue("general.MyFloat2").GetValue(), Vector2(2.1f, 2.2f)); + EXPECT_EQ(findRawPropertyValue("general.MyFloat3").GetValue(), Vector3(3.1f, 3.2f, 3.3f)); + EXPECT_EQ(findRawPropertyValue("general.MyFloat4").GetValue(), Vector4(4.1f, 4.2f, 4.3f, 4.4f)); + EXPECT_EQ(findRawPropertyValue("general.MyColor" ).GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); + EXPECT_EQ(findRawPropertyValue("general.MyImage" ).GetValue>(), m_testImageAsset); + // The raw value for an enum is the original string, not the numerical value, because the material type holds the necessary metadata to match the name to the value. + EXPECT_EQ(findRawPropertyValue("general.MyEnum" ).GetValue(), AZStd::string("Enum1")); + }; + + // We check the raw property values before the material type asset is even available + checkRawPropertyValues(); + + // Now we'll create the material type asset in memory so the material will have what it needs to finalize itself. + Data::Asset testMaterialTypeAsset = CreateTestMaterialTypeAsset(materialTypeAssetId); + + // The MaterialAsset is still holding an reference to an unloaded asset, so we run it through the serializer which causes the loaded MaterialAsset + // to have access to the testMaterialTypeAsset. This is similar to how the AP would save the MaterialAsset to the cache and the runtime would load it. + SerializeTester tester(GetSerializeContext()); + tester.SerializeOut(materialAsset.Get()); + materialAsset = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); + + // We check the raw property values again on the loaded data, showing that the same data is available in the original un-finalized state. + checkRawPropertyValues(); + + // The material will automatically finalize itself when the properties are accessed. + EXPECT_FALSE(materialAsset->IsFinalized()); + materialAsset->GetPropertyValues(); + EXPECT_TRUE(materialAsset->IsFinalized()); + + // Now all the property values should be available through the main GetPropertyValues() API. + EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue(), true); + EXPECT_EQ(materialAsset->GetPropertyValues()[1].GetValue(), -10); + EXPECT_EQ(materialAsset->GetPropertyValues()[2].GetValue(), 25u); + EXPECT_EQ(materialAsset->GetPropertyValues()[3].GetValue(), 1.5f); + EXPECT_EQ(materialAsset->GetPropertyValues()[4].GetValue(), Vector2(2.1f, 2.2f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[5].GetValue(), Vector3(3.1f, 3.2f, 3.3f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[6].GetValue(), Vector4(4.1f, 4.2f, 4.3f, 4.4f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[7].GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue>(), m_testImageAsset); + EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue(), 1u); + + } void CheckEqual(MaterialSourceData& a, MaterialSourceData& b) { @@ -546,16 +650,19 @@ namespace UnitTest auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel1.IsSuccess()); + EXPECT_TRUE(materialAssetLevel1.GetValue()->IsFinalized()); m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetValue().GetId()); auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel2.IsSuccess()); + EXPECT_TRUE(materialAssetLevel2.GetValue()->IsFinalized()); m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetValue().GetId()); auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel3.IsSuccess()); + EXPECT_TRUE(materialAssetLevel3.GetValue()->IsFinalized()); auto layout = m_testMaterialTypeAsset->GetMaterialPropertiesLayout(); MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat")); @@ -582,6 +689,101 @@ namespace UnitTest EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); } + + TEST_F(MaterialSourceDataTests, CreateMaterialAsset_MultiLevelDataInheritance_DeferredBake) + { + // This test is similar to CreateMaterialAsset_MultiLevelDataInheritance but uses MaterialAssetProcessingMode::DeferredBake instead of PreBake. + + Data::AssetId materialTypeAssetId = Uuid::CreateRandom(); + + // This material type asset will be known by the asset system (stub) but doesn't exist in the AssetManager. + // This demonstrates that the CreateMaterialAsset does not attempt to access the MaterialTypeAsset data in MaterialAssetProcessingMode::DeferredBake. + m_assetSystemStub.RegisterSourceInfo("testDeferredBake.materialtype", materialTypeAssetId); + + MaterialSourceData sourceDataLevel1; + sourceDataLevel1.m_materialType = "testDeferredBake.materialtype"; + AddPropertyGroup(sourceDataLevel1, "general"); + AddProperty(sourceDataLevel1, "general", "MyFloat", 1.5f); + AddProperty(sourceDataLevel1, "general", "MyColor", AZ::Color{0.1f, 0.2f, 0.3f, 0.4f}); + + MaterialSourceData sourceDataLevel2; + sourceDataLevel2.m_materialType = "testDeferredBake.materialtype"; + sourceDataLevel2.m_parentMaterial = "level1.material"; + AddPropertyGroup(sourceDataLevel2, "general"); + AddProperty(sourceDataLevel2, "general", "MyColor", AZ::Color{0.15f, 0.25f, 0.35f, 0.45f}); + AddProperty(sourceDataLevel2, "general", "MyFloat2", AZ::Vector2{4.1f, 4.2f}); + + MaterialSourceData sourceDataLevel3; + sourceDataLevel3.m_materialType = "testDeferredBake.materialtype"; + sourceDataLevel3.m_parentMaterial = "level2.material"; + AddPropertyGroup(sourceDataLevel3, "general"); + AddProperty(sourceDataLevel3, "general", "MyFloat", 3.5f); + + auto materialAssetLevel1Result = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); + EXPECT_TRUE(materialAssetLevel1Result.IsSuccess()); + Data::Asset materialAssetLevel1 = materialAssetLevel1Result.TakeValue(); + EXPECT_FALSE(materialAssetLevel1->IsFinalized()); + + m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetId()); + + auto materialAssetLevel2Result = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); + EXPECT_TRUE(materialAssetLevel2Result.IsSuccess()); + Data::Asset materialAssetLevel2 = materialAssetLevel2Result.TakeValue(); + EXPECT_FALSE(materialAssetLevel2->IsFinalized()); + + m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetId()); + + auto materialAssetLevel3Result = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); + EXPECT_TRUE(materialAssetLevel3Result.IsSuccess()); + Data::Asset materialAssetLevel3 = materialAssetLevel3Result.TakeValue(); + EXPECT_FALSE(materialAssetLevel3->IsFinalized()); + + // Now we'll create the material type asset in memory so the materials will have what they need to finalize. + Data::Asset testMaterialTypeAsset = CreateTestMaterialTypeAsset(materialTypeAssetId); + + auto layout = testMaterialTypeAsset->GetMaterialPropertiesLayout(); + MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat")); + MaterialPropertyIndex myFloat2 = layout->FindPropertyIndex(Name("general.MyFloat2")); + MaterialPropertyIndex myColor = layout->FindPropertyIndex(Name("general.MyColor")); + + + // The MaterialAsset is still holding an reference to an unloaded asset, so we run it through the serializer which causes the loaded MaterialAsset + // to have access to the testMaterialTypeAsset. This is similar to how the AP would save the MaterialAsset to the cache and the runtime would load it. + SerializeTester tester(GetSerializeContext()); + tester.SerializeOut(materialAssetLevel1.Get()); + materialAssetLevel1 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); + tester.SerializeOut(materialAssetLevel2.Get()); + materialAssetLevel2 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); + tester.SerializeOut(materialAssetLevel3.Get()); + materialAssetLevel3 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); + + + // The properties will finalize automatically when we call GetPropertyValues()... + + AZStd::array_view properties; + + // Check level 1 properties + properties = materialAssetLevel1->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(0.0f, 0.0f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); + + // Check level 2 properties + properties = materialAssetLevel2->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 1.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + + // Check level 3 properties + properties = materialAssetLevel3->GetPropertyValues(); + EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 3.5f); + EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); + EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); + + EXPECT_TRUE(materialAssetLevel1->IsFinalized()); + EXPECT_TRUE(materialAssetLevel2->IsFinalized()); + EXPECT_TRUE(materialAssetLevel3->IsFinalized()); + } TEST_F(MaterialSourceDataTests, CreateMaterialAsset_MultiLevelDataInheritance_Error_MaterialTypesDontMatch) { From 4ade6bc88a2432a0073c2edf521d6c8ab5cf0716 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 28 Dec 2021 17:52:13 -0800 Subject: [PATCH 17/36] Fixed compile errors in Material Editor. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../MaterialEditor/Code/Source/Document/MaterialDocument.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 93da118b5b..641d586ea7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -713,7 +713,7 @@ namespace MaterialEditor // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. auto materialAssetResult = - m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, elevateWarnings, true, &m_sourceDependencies); + m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, elevateWarnings, &m_sourceDependencies); if (!materialAssetResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); @@ -753,7 +753,7 @@ namespace MaterialEditor } auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( - parentMaterialAssetIdResult.GetValue(), m_materialSourceData.m_parentMaterial, true, true); + parentMaterialAssetIdResult.GetValue(), m_materialSourceData.m_parentMaterial, true); if (!parentMaterialAssetResult) { AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); From aafd34679af77484c949744964de6eb3fc6a4fb5 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Thu, 13 Jan 2022 12:48:32 -0800 Subject: [PATCH 18/36] Merged MaterialAssetCreatorCommon class into MaterialTypeAssetCreator because it is no longer needed for MaterialAssetCreator. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/MaterialAssetCreatorCommon.h | 64 ------------- .../RPI.Reflect/Material/MaterialTypeAsset.h | 1 - .../Material/MaterialTypeAssetCreator.h | 14 ++- .../RPI.Builders/Material/MaterialBuilder.cpp | 6 +- .../Model/MaterialAssetBuilderComponent.cpp | 2 +- .../Material/MaterialAssetCreatorCommon.cpp | 93 ------------------- .../Material/MaterialTypeAssetCreator.cpp | 61 +++++++++--- .../RPI/Code/atom_rpi_reflect_files.cmake | 2 - 8 files changed, 63 insertions(+), 180 deletions(-) delete mode 100644 Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h delete mode 100644 Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h deleted file mode 100644 index c7fa9c2a4c..0000000000 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 - * - */ -#pragma once - -#include -#include -#include -#include -#include - -// These classes are not directly referenced in this header only because the SetPropertyValue() -// function is templatized. But the API is still specific to these data types so we include them here. -#include -#include -#include -#include - -namespace AZ -{ - namespace RPI - { - class StreamingImageAsset; - class AttachmentImageAsset; - - //! Provides common functionality to both MaterialTypeAssetCreator and MaterialAssetCreator. - class MaterialAssetCreatorCommon - { - public: - void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); - void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); - void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); - - //! Sets a property value using data in AZStd::variant-based MaterialPropertyValue. The contained data must match - //! the data type of the property. For type Image, the value must be a Data::Asset. - void SetPropertyValue(const Name& name, const MaterialPropertyValue& value); - - protected: - MaterialAssetCreatorCommon() = default; - - void OnBegin( - const MaterialPropertiesLayout* propertyLayout, - AZStd::vector* propertyValues, - const AZStd::function& warningFunc, - const AZStd::function& errorFunc); - void OnEnd(); - - private: - bool PropertyCheck(TypeId typeId, const Name& name); - - const MaterialPropertiesLayout* m_propertyLayout = nullptr; - //! Points to the m_propertyValues list in a MaterialAsset or MaterialTypeAsset - AZStd::vector* m_propertyValues = nullptr; - - AZStd::function m_reportWarning = nullptr; - AZStd::function m_reportError = nullptr; - }; - - } // namespace RPI -} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h index f194d84263..9065b17254 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h @@ -54,7 +54,6 @@ namespace AZ { friend class MaterialTypeAssetCreator; friend class MaterialTypeAssetHandler; - friend class MaterialAssetCreatorCommon; public: AZ_RTTI(MaterialTypeAsset, "{CD7803AB-9C4C-4A33-9A14-7412F1665464}", AZ::Data::AssetData); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h index 5e5f94da6d..6bd84b5546 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include @@ -27,7 +26,6 @@ namespace AZ //! which provides the MaterialTypeAsset and default property values. class MaterialTypeAssetCreator : public AssetCreator - , public MaterialAssetCreatorCommon { public: //! Begin creating a MaterialTypeAsset @@ -71,6 +69,14 @@ namespace AZ //! Finishes creating a material property. void EndMaterialProperty(); + + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + void SetPropertyValue(const Name& name, const Data::Asset& imageAsset); + + //! Sets a property value using data in AZStd::variant-based MaterialPropertyValue. The contained data must match + //! the data type of the property. For type Image, the value must be a Data::Asset. + void SetPropertyValue(const Name& name, const MaterialPropertyValue& value); //! Adds a MaterialFunctor. //! Material functors provide custom logic and calculations to configure shaders, render states, and more.See MaterialFunctor.h for details. @@ -101,7 +107,9 @@ namespace AZ private: void AddMaterialProperty(MaterialPropertyDescriptor&& materialProperty); - + + bool PropertyCheck(TypeId typeId, const Name& name); + //! The material type holds references to shader assets that contain SRGs that are supposed to be the same across all passes in the material. //! This function searches for an SRG given a @bindingSlot. If a valid one is found it makes sure it is the same across all shaders //! and records in srgShaderIndexToUpdate the index of the ShaderAsset in the ShaderCollection where it was found. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 3aa8728e08..6e50e58dd3 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -52,7 +52,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 112; // material dependency improvements + materialBuilderDescriptor.m_version = 113; // material dependency improvements materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); @@ -95,7 +95,7 @@ namespace AZ const bool currentFileIsMaterial = AzFramework::StringFunc::Path::IsExtension(currentFilePath.c_str(), MaterialSourceData::Extension); const bool referencedFileIsMaterialType = AzFramework::StringFunc::Path::IsExtension(referencedParentPath.c_str(), MaterialTypeSourceData::Extension); - const bool ShouldFinalizeMaterialAssets = MaterialUtils::BuildersShouldFinalizeMaterialAssets(); + const bool shouldFinalizeMaterialAssets = MaterialUtils::BuildersShouldFinalizeMaterialAssets(); AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); for (auto& file : possibleDependencies) @@ -118,7 +118,7 @@ namespace AZ // If we aren't finalizing material assets, then a normal job dependency isn't needed because the MaterialTypeAsset data won't be used. // However, we do still need at least an OrderOnce dependency to ensure the Asset Processor knows about the material type asset so the builder can get it's AssetId. // This can significantly reduce AP processing time when a material type or its shaders are edited. - if (currentFileIsMaterial && referencedFileIsMaterialType && !ShouldFinalizeMaterialAssets) + if (currentFileIsMaterial && referencedFileIsMaterialType && !shouldFinalizeMaterialAssets) { jobDependency.m_type = AssetBuilderSDK::JobDependencyType::OrderOnce; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index 6f71fb70d4..1cc1925564 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -127,7 +127,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(18); // material dependency improvements + ->Version(19); // material dependency improvements } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp deleted file mode 100644 index 4b2f163f7c..0000000000 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 -#include - -namespace AZ -{ - namespace RPI - { - void MaterialAssetCreatorCommon::OnBegin( - const MaterialPropertiesLayout* propertyLayout, - AZStd::vector* propertyValues, - const AZStd::function& warningFunc, - const AZStd::function& errorFunc) - { - m_propertyLayout = propertyLayout; - m_propertyValues = propertyValues; - m_reportWarning = warningFunc; - m_reportError = errorFunc; - } - - void MaterialAssetCreatorCommon::OnEnd() - { - m_propertyLayout = nullptr; - m_propertyValues = nullptr; - m_reportWarning = nullptr; - m_reportError = nullptr; - } - - bool MaterialAssetCreatorCommon::PropertyCheck(TypeId typeId, const Name& name) - { - if (!m_reportWarning || !m_reportError) - { - AZ_Assert(false, "Call Begin() on the AssetCreator before using it."); - return false; - } - - MaterialPropertyIndex propertyIndex = m_propertyLayout->FindPropertyIndex(name); - if (!propertyIndex.IsValid()) - { - m_reportWarning( - AZStd::string::format("Material property '%s' not found", - name.GetCStr() - ).data()); - return false; - } - - const MaterialPropertyDescriptor* materialPropertyDescriptor = m_propertyLayout->GetPropertyDescriptor(propertyIndex); - if (!materialPropertyDescriptor) - { - m_reportError("A material property index was found but the property descriptor was null"); - return false; - } - - if (!ValidateMaterialPropertyDataType(typeId, name, materialPropertyDescriptor, m_reportError)) - { - return false; - } - - return true; - } - - void MaterialAssetCreatorCommon::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) - { - return SetPropertyValue(name, MaterialPropertyValue(imageAsset)); - } - - void MaterialAssetCreatorCommon::SetPropertyValue(const Name& name, const MaterialPropertyValue& value) - { - if (PropertyCheck(value.GetTypeId(), name)) - { - MaterialPropertyIndex propertyIndex = m_propertyLayout->FindPropertyIndex(name); - (*m_propertyValues)[propertyIndex.GetIndex()] = value; - } - } - - void MaterialAssetCreatorCommon::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) - { - SetPropertyValue(name, Data::Asset(imageAsset)); - } - - void MaterialAssetCreatorCommon::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) - { - SetPropertyValue(name, Data::Asset(imageAsset)); - } - } // namespace RPI -} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index dd023c56b8..6746b57740 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -22,17 +22,6 @@ namespace AZ { m_materialPropertiesLayout = aznew MaterialPropertiesLayout; m_asset->m_materialPropertiesLayout = m_materialPropertiesLayout; - - auto warningFunc = [this](const char* message) - { - ReportWarning("%s", message); - }; - auto errorFunc = [this](const char* message) - { - ReportError("%s", message); - }; - // Set empty for UV names as material type asset doesn't have overrides. - MaterialAssetCreatorCommon::OnBegin(m_materialPropertiesLayout, &(m_asset->m_propertyValues), warningFunc, errorFunc); } } @@ -48,8 +37,6 @@ namespace AZ m_materialShaderResourceGroupLayout = nullptr; m_materialPropertiesLayout = nullptr; - MaterialAssetCreatorCommon::OnEnd(); - return EndCommon(result); } @@ -499,6 +486,54 @@ namespace AZ m_wipMaterialProperty = MaterialPropertyDescriptor{}; } + + bool MaterialTypeAssetCreator::PropertyCheck(TypeId typeId, const Name& name) + { + MaterialPropertyIndex propertyIndex = m_materialPropertiesLayout->FindPropertyIndex(name); + if (!propertyIndex.IsValid()) + { + ReportWarning("Material property '%s' not found", name.GetCStr()); + return false; + } + + const MaterialPropertyDescriptor* materialPropertyDescriptor = m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); + if (!materialPropertyDescriptor) + { + ReportError("A material property index was found but the property descriptor was null"); + return false; + } + + if (!ValidateMaterialPropertyDataType(typeId, name, materialPropertyDescriptor, [this](const char* message){ReportError("%s", message);})) + { + return false; + } + + return true; + } + + void MaterialTypeAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + return SetPropertyValue(name, MaterialPropertyValue(imageAsset)); + } + + void MaterialTypeAssetCreator::SetPropertyValue(const Name& name, const MaterialPropertyValue& value) + { + if (PropertyCheck(value.GetTypeId(), name)) + { + MaterialPropertyIndex propertyIndex = m_materialPropertiesLayout->FindPropertyIndex(name); + m_asset->m_propertyValues[propertyIndex.GetIndex()] = value; + } + } + + void MaterialTypeAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + SetPropertyValue(name, Data::Asset(imageAsset)); + } + + void MaterialTypeAssetCreator::SetPropertyValue(const Name& name, const Data::Asset& imageAsset) + { + SetPropertyValue(name, Data::Asset(imageAsset)); + } void MaterialTypeAssetCreator::AddMaterialFunctor(const Ptr& functor) { diff --git a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake index df8f389c37..6e9cdfeb4e 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake @@ -51,7 +51,6 @@ set(FILES Include/Atom/RPI.Reflect/Image/StreamingImagePoolAssetCreator.h Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h Include/Atom/RPI.Reflect/Material/MaterialAsset.h - Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h @@ -133,7 +132,6 @@ set(FILES Source/RPI.Reflect/Image/StreamingImagePoolAssetCreator.cpp Source/RPI.Reflect/Material/MaterialPropertyValue.cpp Source/RPI.Reflect/Material/MaterialAsset.cpp - Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp Source/RPI.Reflect/Material/MaterialAssetCreator.cpp Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp From 8084775d7adf384f96672e69fa227c81156e9262 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Thu, 13 Jan 2022 12:49:35 -0800 Subject: [PATCH 19/36] Updating code comments. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Reflect/Material/MaterialAsset.h | 13 ++++++++++--- .../Source/RPI.Edit/Material/MaterialSourceData.cpp | 3 +++ .../Source/RPI.Reflect/Material/MaterialAsset.cpp | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 4cc6608225..2a6c89a8fa 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -34,8 +34,6 @@ namespace AZ class MaterialAssetHandler; //! MaterialAsset defines a single material, which can be used to create a Material instance for rendering at runtime. - //! It fetches MaterialTypeSourceData from the MaterialTypeAsset it owned. - //! //! Use a MaterialAssetCreator to create a MaterialAsset. class MaterialAsset : public AZ::Data::AssetData @@ -46,7 +44,6 @@ namespace AZ friend class MaterialVersionUpdate; friend class MaterialAssetCreator; friend class MaterialAssetHandler; - friend class MaterialAssetCreatorCommon; friend class UnitTest::MaterialTests; friend class UnitTest::MaterialAssetTests; @@ -117,8 +114,18 @@ namespace AZ //! //! Note that even though material source data files contain only override values and inherit the rest from //! their parent material, they all get flattened at build time so every MaterialAsset has the full set of values. + //! + //! Calling GetPropertyValues() will automatically finalize the material asset if it isn't finalized already. The + //! MaterialTypeAsset must be loaded and ready. const AZStd::vector& GetPropertyValues() const; + //! Returns the list of raw values for all properties in this material, as listed in the source .material file(s), before the material asset was Finalized. + //! + //! The MaterialAsset can be created in a "half-baked" state (see MaterialUtils::BuildersShouldFinalizeMaterialAssets) where + //! minimal processing has been done because it did not yet have access to the MaterialTypeAsset. In that case, the list will + //! be populated with values copied from the source .material file with little or no validation or other processing. It includes + //! all parent .material files, with properties listed in low-to-high priority order. + //! This list will be empty however if the asset was finalized at build-time. const AZStd::vector>& GetRawPropertyValues() const; private: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 23657f4871..bc764ec7fb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -312,6 +312,9 @@ namespace AZ { materialAssetCreator.ReportWarning("Source data for material property value is invalid."); } + // If the source value type is a string, there are two possible property types: Image and Enum. If there is a "." in + // the string (for the extension) we assume it's an Image and look up the referenced Asset. Otherwise, we can assume + // it's an Enum value and just preserve the original string. else if (property.second.m_value.Is() && AzFramework::StringFunc::Contains(property.second.m_value.GetValue(), ".")) { Data::Asset imageAsset; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index ce5847d12f..a40fa77019 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -304,7 +304,7 @@ namespace AZ m_materialTypeAsset = newMaterialTypeAsset; // If the material asset was not finalized on disk, then we clear the previously finalized property values to force re-finalize. - // This + // This is necessary in case the property layout changed in some way. if (!m_wasPreFinalized) { m_isFinalized = false; From 2d6d14abf72d3db6fba0ab225e83bc23fb7e34ba Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:49:17 -0800 Subject: [PATCH 20/36] Changed MaterialAsset::GetPropertyValues to not auto-finalize. Client code must call Finalize manually. It's better to avoid unexpected side-effects from a const getter function. In some cases it may be acceptable to do non-const things in a const function as long as it is only manipulating internal data, and the public facing API returns the same values as before. But in this case, the IsFinalized function is a public facing API that would have a different result after GetPropertyValues was called. I also updated a couple other minor things from code review feedback. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../RPI.Edit/Material/MaterialSourceData.h | 2 +- .../Atom/RPI.Reflect/Material/MaterialAsset.h | 11 ++++--- .../RPI.Builders/Material/MaterialBuilder.cpp | 2 +- .../Model/MaterialAssetBuilderComponent.cpp | 5 ++-- .../Source/RPI.Public/Material/Material.cpp | 2 ++ .../RPI.Reflect/Material/MaterialAsset.cpp | 5 +--- .../Tests/Material/MaterialAssetTests.cpp | 6 ++-- .../Material/MaterialSourceDataTests.cpp | 30 +++++++++++-------- 8 files changed, 35 insertions(+), 28 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index a5fb0214e6..0a9371f722 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -33,7 +33,7 @@ namespace AZ class MaterialAsset; class MaterialAssetCreator; - enum MaterialAssetProcessingMode + enum class MaterialAssetProcessingMode { PreBake, //!< all material asset processing is done in the Asset Processor, producing a finalized material asset DeferredBake //!< some material asset processing is deferred, and the material asset is finalized at runtime after loading diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 2a6c89a8fa..941fcd0fe9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -107,6 +107,11 @@ namespace AZ //! If false, property values can be accessed through GetRawPropertyValues(). bool IsFinalized() const; + //! If the material asset is not finalized yet, this does the final processing of the raw property values to + //! get the material asset ready to be used. + //! Note the MaterialTypeAsset must be valid before this is called. + void Finalize(AZStd::function reportWarning = nullptr, AZStd::function reportError = nullptr); + //! Returns the list of values for all properties in this material. //! The entries in this list align with the entries in the MaterialPropertiesLayout. Each AZStd::any is guaranteed //! to have a value of type that matches the corresponding MaterialPropertyDescriptor. @@ -131,12 +136,6 @@ namespace AZ private: bool PostLoadInit() override; - //! If the material asset is not finalized yet, this does the final processing of m_rawPropertyValues to - //! get the material asset ready to be used. - //! Note m_materialTypeAsset must be valid before this is called. - //! @param elevateWarnings Indicates whether to treat warnings as errors - void Finalize(AZStd::function reportWarning = nullptr, AZStd::function reportError = nullptr); - //! Checks the material type version and potentially applies a series of property changes (most common are simple property renames) //! based on the MaterialTypeAsset's version update procedure. void ApplyVersionUpdates(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 6e50e58dd3..cedbb1df6e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -52,7 +52,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 113; // material dependency improvements + materialBuilderDescriptor.m_version = 114; // material dependency improvements materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index 1cc1925564..a44b47ee6c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -45,7 +45,8 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(5) // <<<<< This probably is NOT the version number you want to bump. What you're looking for is MaterialAssetBuilderComponent::Reflect below + ->Version(5) // <<<<< If you have made changes to material code and need to force scene files to be reprocessed, this probably is + // NOT the version number you want to bump . What you're looking for is MaterialAssetBuilderComponent::Reflect below. ->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })); } } @@ -127,7 +128,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(19); // material dependency improvements + ->Version(20); // material dependency improvements } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index 1f739c24f1..fe9dbef278 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -62,6 +62,8 @@ namespace AZ m_materialAsset = { &materialAsset, AZ::Data::AssetLoadBehavior::PreLoad }; + m_materialAsset->Finalize(); + // Cache off pointers to some key data structures from the material type... auto srgLayout = m_materialAsset->GetMaterialSrgLayout(); if (srgLayout) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index a40fa77019..569e2de81a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -199,10 +199,7 @@ namespace AZ const AZStd::vector& MaterialAsset::GetPropertyValues() const { - // This can't be done in MaterialAssetHandler::LoadAssetData because the MaterialTypeAsset isn't necessarily loaded at that point. - // And it can't be done in PostLoadInit() because that happens on the next frame which might be too late. So we finalize just-in-time - // when properties are accessed. - const_cast(this)->Finalize(); + AZ_Error(s_debugTraceName, IsFinalized(), "MaterialAsset must be finalized before its property values can be accessed"); return m_propertyValues; } diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp index 633953cecc..fdb131d449 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp @@ -266,6 +266,10 @@ namespace UnitTest warningFinder.AddExpectedErrorMessage("Automatic updates are available. Consider updating the .material source file"); warningFinder.AddExpectedErrorMessage("This material is based on version '1'"); warningFinder.AddExpectedErrorMessage("material type is now at version '2'"); + + materialAsset->Finalize(); + + warningFinder.CheckExpectedErrorsFound(); // Even though this material was created using the old version of the material type, it's property values should get automatically // updated to align with the new property layout in the latest MaterialTypeAsset. @@ -273,8 +277,6 @@ namespace UnitTest EXPECT_EQ(2, myIntIndex.GetIndex()); EXPECT_EQ(7, materialAsset->GetPropertyValues()[myIntIndex.GetIndex()].GetValue()); - warningFinder.CheckExpectedErrorsFound(); - // Since the MaterialAsset has already been updated, and the warning reported once, we should not see the "consider updating" // warning reported again on subsequent property accesses. warningFinder.Reset(); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index e4d3cc9768..29f0e7d101 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -228,8 +228,13 @@ namespace UnitTest Data::Asset materialAsset = materialAssetOutcome.GetValue(); + ErrorMessageFinder expectNotFinalizedError("MaterialAsset must be finalized"); + EXPECT_FALSE(materialAsset->IsFinalized()); - // Note we avoid calling GetPropertyValues() because that will auto-finalize the material. We want to check its raw property values first. + + expectNotFinalizedError.ResetCounts(); + EXPECT_TRUE(materialAsset->GetPropertyValues().empty()); + expectNotFinalizedError.CheckExpectedErrorsFound(); auto findRawPropertyValue = [materialAsset](const char* propertyId) { @@ -275,12 +280,14 @@ namespace UnitTest tester.SerializeOut(materialAsset.Get()); materialAsset = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); - // We check the raw property values again on the loaded data, showing that the same data is available in the original un-finalized state. - checkRawPropertyValues(); - - // The material will automatically finalize itself when the properties are accessed. + // We check that everything is still in the original un-finalized state after going through the serialization process. EXPECT_FALSE(materialAsset->IsFinalized()); - materialAsset->GetPropertyValues(); + checkRawPropertyValues(); + expectNotFinalizedError.ResetCounts(); + EXPECT_TRUE(materialAsset->GetPropertyValues().empty()); + expectNotFinalizedError.CheckExpectedErrorsFound(); + + materialAsset->Finalize(); EXPECT_TRUE(materialAsset->IsFinalized()); // Now all the property values should be available through the main GetPropertyValues() API. @@ -295,6 +302,8 @@ namespace UnitTest EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue>(), m_testImageAsset); EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue(), 1u); + // The raw property values are still available (because they are needed if a hot-reload of the MaterialTypeAsset occurs) + checkRawPropertyValues(); } void CheckEqual(MaterialSourceData& a, MaterialSourceData& b) @@ -757,8 +766,9 @@ namespace UnitTest tester.SerializeOut(materialAssetLevel3.Get()); materialAssetLevel3 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); - - // The properties will finalize automatically when we call GetPropertyValues()... + materialAssetLevel1->Finalize(); + materialAssetLevel2->Finalize(); + materialAssetLevel3->Finalize(); AZStd::array_view properties; @@ -779,10 +789,6 @@ namespace UnitTest EXPECT_EQ(properties[myFloat.GetIndex()].GetValue(), 3.5f); EXPECT_EQ(properties[myFloat2.GetIndex()].GetValue(), Vector2(4.1f, 4.2f)); EXPECT_EQ(properties[myColor.GetIndex()].GetValue(), Color(0.15f, 0.25f, 0.35f, 0.45f)); - - EXPECT_TRUE(materialAssetLevel1->IsFinalized()); - EXPECT_TRUE(materialAssetLevel2->IsFinalized()); - EXPECT_TRUE(materialAssetLevel3->IsFinalized()); } TEST_F(MaterialSourceDataTests, CreateMaterialAsset_MultiLevelDataInheritance_Error_MaterialTypesDontMatch) From c24546a85d1ba0d190fac9e424e9e9b87a9fe6a5 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:57:03 -0800 Subject: [PATCH 21/36] Fixed unused variable warning. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 569e2de81a..310c10c39b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -123,7 +123,7 @@ namespace AZ if (!reportWarning) { - reportWarning = [](const char* message) + reportWarning = []([[maybe_unused]] const char* message) { AZ_Warning(s_debugTraceName, false, "%s", message); }; From 5c2e69d6d07b76f3fbc19d83a66ccab56f49854c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 18 Jan 2022 12:36:49 -0600 Subject: [PATCH 22/36] Atom Tools: move asset processor connection to fix thumbnails Thumbnails for the AtomLyIntegration common feature gem were no longer being rendered. The setup code was modified to initialize the thumbnail system after receiving a new event that critical assets finished compiling. This event was being sent and handled correctly in the main editor. This process was failing in other tools because the event was sent before systems were registered to listen for it. To resolve the problem, atom tools application now explicitly connects to the asset processor and processes critical assets after the base application StartCommon function is called. This ensures that the connection is established and the event gets sent after all of the system components have been activated. Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.h | 8 +------- .../Source/Application/AtomToolsApplication.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 9eaacbfa4f..9449c62de1 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -34,7 +33,6 @@ namespace AtomToolsFramework : public AzFramework::Application , public AzQtComponents::AzQtApplication , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler - , protected AzFramework::AssetSystemStatusBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler , protected AtomToolsMainWindowNotificationBus::Handler @@ -77,11 +75,6 @@ namespace AtomToolsFramework void Destroy() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::AssetSystemStatusBus::Handler overrides... - void AssetSystemAvailable() override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AZ::ComponentApplication overrides... void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override; @@ -107,6 +100,7 @@ namespace AtomToolsFramework virtual void LoadSettings(); virtual void UnloadSettings(); + virtual void ConnectToAssetProcessor(); virtual void CompileCriticalAssets(); virtual void ProcessCommandLine(const AZ::CommandLine& commandLine); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 02248fffd4..791738a06e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -171,7 +171,6 @@ namespace AtomToolsFramework void AtomToolsApplication::StartCommon(AZ::Entity* systemEntity) { - AzFramework::AssetSystemStatusBus::Handler::BusConnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect(); Base::StartCommon(systemEntity); @@ -179,6 +178,8 @@ namespace AtomToolsFramework const bool clearLogFile = GetSettingOrDefault("/O3DE/AtomToolsFramework/Application/ClearLogOnStart", false); m_traceLogger.OpenLogFile(GetBuildTargetName() + ".log", clearLogFile); + ConnectToAssetProcessor(); + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); @@ -236,7 +237,7 @@ namespace AtomToolsFramework return AZStd::vector({}); } - void AtomToolsApplication::AssetSystemAvailable() + void AtomToolsApplication::ConnectToAssetProcessor() { bool connectedToAssetProcessor = false; @@ -245,18 +246,19 @@ namespace AtomToolsFramework // and able to negotiate a connection when running a debug build // and to negotiate a connection - auto targetName = GetBuildTargetName(); + const auto targetName = GetBuildTargetName(); AzFramework::AssetSystem::ConnectionSettings connectionSettings; AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings); connectionSettings.m_connectionDirection = AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor; - connectionSettings.m_connectionIdentifier = GetBuildTargetName(); + connectionSettings.m_connectionIdentifier = targetName; connectionSettings.m_loggingCallback = [targetName]([[maybe_unused]] AZStd::string_view logData) { AZ_UNUSED(targetName); // Prevent unused warning in release builds AZ_TracePrintf(targetName.c_str(), "%.*s", aznumeric_cast(logData.size()), logData.data()); }; + AzFramework::AssetSystemRequestBus::BroadcastResult( connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection, connectionSettings); @@ -264,8 +266,6 @@ namespace AtomToolsFramework { CompileCriticalAssets(); } - - AzFramework::AssetSystemStatusBus::Handler::BusDisconnect(); } void AtomToolsApplication::CompileCriticalAssets() @@ -302,6 +302,7 @@ namespace AtomToolsFramework } AZ::ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "CriticalAssetsCompiled", R"({})"); + // Reload the assetcatalog.xml at this point again // Start Monitoring Asset changes over the network and load the AssetCatalog auto LoadCatalog = [settingsRegistry = m_settingsRegistry.get()](AZ::Data::AssetCatalogRequests* assetCatalogRequests) From 4af918a4a8895c553fe08264b96e05a1b65f3d28 Mon Sep 17 00:00:00 2001 From: jckand-amzn <82226555+jckand-amzn@users.noreply.github.com> Date: Tue, 18 Jan 2022 13:50:14 -0600 Subject: [PATCH 23/36] Skipping ShapeIntersectionFilter test (#6975) Signed-off-by: jckand-amzn <82226555+jckand-amzn@users.noreply.github.com> --- .../PythonTests/largeworlds/dyn_veg/TestSuite_Main_Optimized.py | 1 + 1 file changed, 1 insertion(+) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main_Optimized.py index 5b1e504442..af1c187817 100644 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main_Optimized.py @@ -131,6 +131,7 @@ class TestAutomation_PrefabNotEnabled(EditorTestSuite): class test_ShapeIntersectionFilter_InstancesPlantInAssignedShape(EditorParallelTest): from .EditorScripts import ShapeIntersectionFilter_InstancesPlantInAssignedShape as test_module + @pytest.mark.skip("https://github.com/o3de/o3de/issues/6973") class test_ShapeIntersectionFilter_FilterStageToggle(EditorParallelTest): from .EditorScripts import ShapeIntersectionFilter_FilterStageToggle as test_module From 2627b507d3081bf38248389b475e89e4192f0fd4 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 18 Jan 2022 12:01:19 -0800 Subject: [PATCH 24/36] Fixed unused variable warning Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 310c10c39b..0325c3ac38 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -131,7 +131,7 @@ namespace AZ if (!reportError) { - reportError = [](const char* message) + reportError = []([[maybe_unused]] const char* message) { AZ_Error(s_debugTraceName, false, "%s", message); }; From d9e636f77edf24f32985c48f7ecf638b53c90be0 Mon Sep 17 00:00:00 2001 From: AMZN-byrcolin <68035668+byrcolin@users.noreply.github.com> Date: Tue, 18 Jan 2022 12:12:55 -0800 Subject: [PATCH 25/36] fix edge case with deprecated pal functions (#6976) * fix edge case with deprecated pal functions Signed-off-by: byrcolin --- cmake/PAL.cmake | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index ef431ff92a..0359408200 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -298,21 +298,27 @@ function(ly_get_absolute_pal_filename out_name in_name) # parent relative path is optional if(${ARGC} GREATER 4) - set(parent_relative_path ${ARGV4}) + if(ARGV4) + set(parent_relative_path ${ARGV4}) + endif() endif() # The Default object path for path is the LY_ROOT_FOLDER cmake_path(SET object_path NORMALIZE "${LY_ROOT_FOLDER}") if(${ARGC} GREATER 3) - # The user has supplied an object restricted path, the object path for consideration - cmake_path(SET object_path NORMALIZE ${ARGV3}) + if(ARGV3) + # The user has supplied an object restricted path, the object path for consideration + cmake_path(SET object_path NORMALIZE ${ARGV3}) + endif() endif() # The default restricted object path is O3DE_ENGINE_RESTRICTED_PATH cmake_path(SET object_restricted_path NORMALIZE "${O3DE_ENGINE_RESTRICTED_PATH}") if(${ARGC} GREATER 2) - # The user has supplied an object restricted path - cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) + if(ARGV3) + # The user has supplied an object restricted path + cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) + endif() endif() if(${ARGC} GREATER 4) @@ -394,27 +400,33 @@ function(ly_get_list_relative_pal_filename out_name in_name) # parent relative path is optional if(${ARGC} GREATER 4) - set(parent_relative_path ${ARGV4}) + if(ARGV4) + set(parent_relative_path ${ARGV4}) + endif() endif() # The Default object path for path is the LY_ROOT_FOLDER cmake_path(SET object_path NORMALIZE "${LY_ROOT_FOLDER}") if(${ARGC} GREATER 3) - # The user has supplied an object restricted path, the object path for consideration - cmake_path(SET object_path NORMALIZE ${ARGV3}) + if(ARGV3) + # The user has supplied an object restricted path, the object path for consideration + cmake_path(SET object_path NORMALIZE ${ARGV3}) + endif() endif() # The default restricted object path is O3DE_ENGINE_RESTRICTED_PATH cmake_path(SET object_restricted_path NORMALIZE "${O3DE_ENGINE_RESTRICTED_PATH}") if(${ARGC} GREATER 2) - # The user has supplied an object restricted path - cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) + if(ARGV2) + # The user has supplied an object restricted path + cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) + endif() endif() if(${ARGC} GREATER 4) - o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path} ${parent_relative_path}) + o3de_pal_dir(abs_name ${in_name} "${object_restricted_path}" "${object_path}" "${parent_relative_path}") else() - o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path}) + o3de_pal_dir(abs_name ${in_name} "${object_restricted_path}" "${object_path}") endif() cmake_path(RELATIVE_PATH abs_name BASE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} OUTPUT_VARIABLE relative_name) From 3a3aa205451a41fc4e0ff3761cd98492d25688fa Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Tue, 18 Jan 2022 12:38:08 -0800 Subject: [PATCH 26/36] [development] added required runtime dependency Gem::PhysX.Editor to WhiteBox.Editor.Physics.Tests (#6871) Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- Gems/WhiteBox/Code/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/WhiteBox/Code/CMakeLists.txt b/Gems/WhiteBox/Code/CMakeLists.txt index 91536503ac..1a37a1ce34 100644 --- a/Gems/WhiteBox/Code/CMakeLists.txt +++ b/Gems/WhiteBox/Code/CMakeLists.txt @@ -198,6 +198,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzTestShared AZ::AzManipulatorTestFramework.Static Gem::WhiteBox.Editor.Static + RUNTIME_DEPENDENCIES + Gem::PhysX.Editor ) ly_add_googletest( From 4b9e53e623856b852720c7c22e14d5bcd237b183 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Tue, 18 Jan 2022 15:05:17 -0600 Subject: [PATCH 27/36] Another batch of GetValues() overrides. (#6915) * Another batch of GetValues() overrides. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added missing headers. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../Components/MixedGradientComponent.h | 29 ++++++ .../Components/PosterizeGradientComponent.h | 34 +++++++ .../Components/ReferenceGradientComponent.h | 1 + .../Components/SmoothStepGradientComponent.h | 1 + .../SurfaceAltitudeGradientComponent.h | 19 +++- .../Components/SurfaceMaskGradientComponent.h | 16 ++++ .../SurfaceSlopeGradientComponent.h | 33 +++++++ .../Components/ThresholdGradientComponent.h | 1 + .../Include/GradientSignal/GradientSampler.h | 2 +- .../Code/Include/GradientSignal/SmoothStep.h | 40 +++++--- .../Components/MixedGradientComponent.cpp | 94 +++++++++++-------- .../Components/PosterizeGradientComponent.cpp | 44 ++++----- .../Components/ReferenceGradientComponent.cpp | 15 ++- .../SmoothStepGradientComponent.cpp | 16 +++- .../SurfaceAltitudeGradientComponent.cpp | 42 +++++++-- .../SurfaceMaskGradientComponent.cpp | 48 ++++++++-- .../SurfaceSlopeGradientComponent.cpp | 60 +++++++----- .../Components/ThresholdGradientComponent.cpp | 17 +++- 18 files changed, 386 insertions(+), 126 deletions(-) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/MixedGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/MixedGradientComponent.h index 9c9867cf1e..658118fca4 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/MixedGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/MixedGradientComponent.h @@ -99,6 +99,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: @@ -110,6 +111,34 @@ namespace GradientSignal MixedGradientLayer* GetLayer(int layerIndex) override; private: + static float PerformMixingOperation(MixedGradientLayer::MixingOperation operation, float prevValue, float currentUnpremultiplied) + { + switch (operation) + { + case MixedGradientLayer::MixingOperation::Initialize: + return currentUnpremultiplied; + case MixedGradientLayer::MixingOperation::Multiply: + return prevValue * currentUnpremultiplied; + case MixedGradientLayer::MixingOperation::Add: + return prevValue + currentUnpremultiplied; + case MixedGradientLayer::MixingOperation::Subtract: + return prevValue - currentUnpremultiplied; + case MixedGradientLayer::MixingOperation::Min: + return AZStd::min(prevValue, currentUnpremultiplied); + case MixedGradientLayer::MixingOperation::Max: + return AZStd::max(prevValue, currentUnpremultiplied); + case MixedGradientLayer::MixingOperation::Average: + return (prevValue + currentUnpremultiplied) / 2.0f; + case MixedGradientLayer::MixingOperation::Normal: + return currentUnpremultiplied; + case MixedGradientLayer::MixingOperation::Overlay: + return (prevValue >= 0.5f) ? (1.0f - (2.0f * (1.0f - prevValue) * (1.0f - currentUnpremultiplied))) + : (2.0f * prevValue * currentUnpremultiplied); + default: + return currentUnpremultiplied; + } + } + MixedGradientConfig m_configuration; LmbrCentral::DependencyMonitor m_dependencyMonitor; }; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PosterizeGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PosterizeGradientComponent.h index 9b0714b449..bff49ac619 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PosterizeGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PosterizeGradientComponent.h @@ -73,6 +73,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: @@ -86,6 +87,39 @@ namespace GradientSignal GradientSampler& GetGradientSampler() override; private: + + static float PosterizeValue(float input, float bands, PosterizeGradientConfig::ModeType mode) + { + const float clampedInput = AZ::GetClamp(input, 0.0f, 1.0f); + float output = 0.0f; + + // "quantize" the input down to a number that goes from 0 to (bands-1) + const float band = AZ::GetMin(floorf(clampedInput * bands), bands - 1.0f); + + // Given our quantized band, produce the right output for that band range. + switch (mode) + { + default: + case PosterizeGradientConfig::ModeType::Floor: + // Floor: the output range should be the lowest value of each band, or (0 to bands-1) / bands + output = (band + 0.0f) / bands; + break; + case PosterizeGradientConfig::ModeType::Round: + // Round: the output range should be the midpoint of each band, or (0.5 to bands-0.5) / bands + output = (band + 0.5f) / bands; + break; + case PosterizeGradientConfig::ModeType::Ceiling: + // Ceiling: the output range should be the highest value of each band, or (1 to bands) / bands + output = (band + 1.0f) / bands; + break; + case PosterizeGradientConfig::ModeType::Ps: + // Ps: the output range should be equally distributed from 0-1, or (0 to bands-1) / (bands-1) + output = band / (bands - 1.0f); + break; + } + return AZ::GetMin(output, 1.0f); + } + PosterizeGradientConfig m_configuration; LmbrCentral::DependencyMonitor m_dependencyMonitor; }; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ReferenceGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ReferenceGradientComponent.h index bf16b484fc..17c40865b3 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ReferenceGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ReferenceGradientComponent.h @@ -64,6 +64,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SmoothStepGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SmoothStepGradientComponent.h index 85947175af..03f629ab1e 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SmoothStepGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SmoothStepGradientComponent.h @@ -71,6 +71,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceAltitudeGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceAltitudeGradientComponent.h index 6ed841dafb..eb76fac292 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceAltitudeGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceAltitudeGradientComponent.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace LmbrCentral { @@ -89,6 +90,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// @@ -105,7 +107,22 @@ namespace GradientSignal void AddTag(AZStd::string tag) override; private: - mutable AZStd::recursive_mutex m_cacheMutex; + static float CalculateAltitudeRatio(const SurfaceData::SurfacePointList& points, float altitudeMin, float altitudeMax) + { + if (points.empty()) + { + return 0.0f; + } + + // GetSurfacePoints (which was used to populate the points list) always returns points in decreasing height order, so the + // first point in the list contains the highest altitude. + const float highestAltitude = points.front().m_position.GetZ(); + + // Turn the absolute altitude value into a 0-1 value by returning the % of the given altitude range that it falls at. + return GetRatio(altitudeMin, altitudeMax, highestAltitude); + } + + mutable AZStd::shared_mutex m_cacheMutex; SurfaceAltitudeGradientConfig m_configuration; LmbrCentral::DependencyMonitor m_dependencyMonitor; AZStd::atomic_bool m_dirty{ false }; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceMaskGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceMaskGradientComponent.h index f5400719d0..3eafb8c115 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceMaskGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceMaskGradientComponent.h @@ -70,6 +70,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// @@ -80,6 +81,21 @@ namespace GradientSignal void AddTag(AZStd::string tag) override; private: + static float GetMaxSurfaceWeight(const SurfaceData::SurfacePointList& points) + { + float result = 0.0f; + + for (const auto& point : points) + { + for (const auto& [maskId, weight] : point.m_masks) + { + result = AZ::GetMax(AZ::GetClamp(weight, 0.0f, 1.0f), result); + } + } + + return result; + } + SurfaceMaskGradientConfig m_configuration; LmbrCentral::DependencyMonitor m_dependencyMonitor; }; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceSlopeGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceSlopeGradientComponent.h index b6805202f1..b464b6fb0f 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceSlopeGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/SurfaceSlopeGradientComponent.h @@ -14,6 +14,7 @@ #include #include #include +#include namespace LmbrCentral { @@ -91,6 +92,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// @@ -121,6 +123,37 @@ namespace GradientSignal void SetFallOffMidpoint(float midpoint) override; private: + float GetSlopeRatio(const SurfaceData::SurfacePointList& points, float angleMin, float angleMax) const + { + if (points.empty()) + { + return 0.0f; + } + + // Assuming our surface normal vector is actually normalized, we can get the slope + // by just grabbing the Z value. It's the same thing as normal.Dot(AZ::Vector3::CreateAxisZ()). + AZ_Assert( + points.front().m_normal.GetNormalized().IsClose(points.front().m_normal), + "Surface normals are expected to be normalized"); + const float slope = points.front().m_normal.GetZ(); + // Convert slope back to an angle so that we can lerp in "angular space", not "slope value space". + // (We want our 0-1 range to be linear across the range of angles) + const float slopeAngle = acosf(slope); + + switch (m_configuration.m_rampType) + { + case SurfaceSlopeGradientConfig::RampType::SMOOTH_STEP: + return m_configuration.m_smoothStep.GetSmoothedValue(GetRatio(angleMin, angleMax, slopeAngle)); + case SurfaceSlopeGradientConfig::RampType::LINEAR_RAMP_UP: + // For ramp up, linearly interpolate from min to max. + return GetRatio(angleMin, angleMax, slopeAngle); + case SurfaceSlopeGradientConfig::RampType::LINEAR_RAMP_DOWN: + default: + // For ramp down, linearly interpolate from max to min. + return GetRatio(angleMax, angleMin, slopeAngle); + } + } + SurfaceSlopeGradientConfig m_configuration; }; } diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ThresholdGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ThresholdGradientComponent.h index dbf211551c..96bc235ea8 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ThresholdGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ThresholdGradientComponent.h @@ -65,6 +65,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h index c9aa7f680c..bf5c8d1ea0 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h @@ -152,7 +152,7 @@ namespace GradientSignal auto ClearOutputValues = [](AZStd::span outValues) { // If we don't have a valid gradient (or it is fully transparent), clear out all the output values. - memset(outValues.data(), 0, outValues.size() * sizeof(float)); + AZStd::fill(outValues.begin(), outValues.end(), 0.0f); }; if (m_opacity <= 0.0f || !m_gradientId.IsValid()) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/SmoothStep.h b/Gems/GradientSignal/Code/Include/GradientSignal/SmoothStep.h index 0489fa4893..c8fc77ac60 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/SmoothStep.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/SmoothStep.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -26,29 +27,46 @@ namespace GradientSignal static void Reflect(AZ::ReflectContext* context); inline float GetSmoothedValue(float inputValue) const; + inline void GetSmoothedValues(AZStd::span inOutValues) const; float m_falloffMidpoint = 0.5f; float m_falloffRange = 0.5f; float m_falloffStrength = 0.25f; + + private: + inline float CalculateSmoothedValue(float min, float max, float valueFalloffStrength, float inputValue) const; }; - inline float SmoothStep::GetSmoothedValue(float inputValue) const + inline float SmoothStep::CalculateSmoothedValue(float min, float max, float valueFalloffStrength, float inputValue) const { - float output = 0.0f; - const float value = AZ::GetClamp(inputValue, 0.0f, 1.0f); - const float valueFalloffStrength = AZ::GetClamp(m_falloffStrength, 0.0f, 1.0f); - - float min = m_falloffMidpoint - m_falloffRange / 2.0f; - float max = m_falloffMidpoint + m_falloffRange / 2.0f; float result1 = GetRatio(min, min + valueFalloffStrength, value); result1 = GetSmoothStep(result1); float result2 = GetRatio(max - valueFalloffStrength, max, value); result2 = GetSmoothStep(result2); - output = result1 * (1.0f - result2); - - return output; + return result1 * (1.0f - result2); } -} + + inline float SmoothStep::GetSmoothedValue(float inputValue) const + { + const float min = m_falloffMidpoint - m_falloffRange / 2.0f; + const float max = m_falloffMidpoint + m_falloffRange / 2.0f; + const float valueFalloffStrength = AZ::GetClamp(m_falloffStrength, 0.0f, 1.0f); + + return CalculateSmoothedValue(min, max, valueFalloffStrength, inputValue); + } + + inline void SmoothStep::GetSmoothedValues(AZStd::span inOutValues) const + { + const float min = m_falloffMidpoint - m_falloffRange / 2.0f; + const float max = m_falloffMidpoint + m_falloffRange / 2.0f; + const float valueFalloffStrength = AZ::GetClamp(m_falloffStrength, 0.0f, 1.0f); + + for (auto& inOutValue : inOutValues) + { + inOutValue = CalculateSmoothedValue(min, max, valueFalloffStrength, inOutValue); + } + } +} // namespace GradientSignal diff --git a/Gems/GradientSignal/Code/Source/Components/MixedGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/MixedGradientComponent.cpp index e042188f8a..23bdd379fe 100644 --- a/Gems/GradientSignal/Code/Source/Components/MixedGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/MixedGradientComponent.cpp @@ -257,62 +257,80 @@ namespace GradientSignal float MixedGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - AZ_PROFILE_FUNCTION(Entity); - //accumulate the mixed/combined result of all layers and operations float result = 0.0f; - float operationResult = 0.0f; for (const auto& layer : m_configuration.m_layers) { // added check to prevent opacity of 0.0, which will bust when we unpremultiply the alpha out if (layer.m_enabled && layer.m_gradientSampler.m_opacity != 0.0f) { + // Precalculate the inverse opacity that we'll use for blending the current accumulated value with. + // In the one case of "Initialize" blending, force this value to 0 so that we erase any accumulated values. + const float inverseOpacity = (layer.m_operation == MixedGradientLayer::MixingOperation::Initialize) + ? 0.0f + : (1.0f - layer.m_gradientSampler.m_opacity); + // this includes leveling and opacity result, we need unpremultiplied opacity to combine properly float current = layer.m_gradientSampler.GetValue(sampleParams); // unpremultiplied alpha (we clamp the end result) - float currentUnpremultiplied = current / layer.m_gradientSampler.m_opacity; - switch (layer.m_operation) - { - default: - case MixedGradientLayer::MixingOperation::Initialize: - //reset the result of the mixed/combined layers to the current value - result = 0.0f; - operationResult = currentUnpremultiplied; - break; - case MixedGradientLayer::MixingOperation::Multiply: - operationResult = result * currentUnpremultiplied; - break; - case MixedGradientLayer::MixingOperation::Add: - operationResult = result + currentUnpremultiplied; - break; - case MixedGradientLayer::MixingOperation::Subtract: - operationResult = result - currentUnpremultiplied; - break; - case MixedGradientLayer::MixingOperation::Min: - operationResult = AZStd::min(currentUnpremultiplied, result); - break; - case MixedGradientLayer::MixingOperation::Max: - operationResult = AZStd::max(currentUnpremultiplied, result); - break; - case MixedGradientLayer::MixingOperation::Average: - operationResult = (result + currentUnpremultiplied) / 2.0f; - break; - case MixedGradientLayer::MixingOperation::Normal: - operationResult = currentUnpremultiplied; - break; - case MixedGradientLayer::MixingOperation::Overlay: - operationResult = (result >= 0.5f) ? (1.0f - (2.0f * (1.0f - result) * (1.0f - currentUnpremultiplied))) : (2.0f * result * currentUnpremultiplied); - break; - } + const float currentUnpremultiplied = current / layer.m_gradientSampler.m_opacity; + const float operationResult = PerformMixingOperation(layer.m_operation, result, currentUnpremultiplied); // blend layers (re-applying opacity, which is why we needed to use unpremultiplied) - result = (result * (1.0f - layer.m_gradientSampler.m_opacity)) + (operationResult * layer.m_gradientSampler.m_opacity); + result = (result * inverseOpacity) + (operationResult * layer.m_gradientSampler.m_opacity); } } return AZ::GetClamp(result, 0.0f, 1.0f); } + void MixedGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + // Initialize all of our output data to 0.0f. Layer blends will combine with this, so we need it to have an initial value. + AZStd::fill(outValues.begin(), outValues.end(), 0.0f); + + AZStd::vector layerValues(positions.size()); + + // accumulate the mixed/combined result of all layers and operations + for (const auto& layer : m_configuration.m_layers) + { + // added check to prevent opacity of 0.0, which will bust when we unpremultiply the alpha out + if (layer.m_enabled && layer.m_gradientSampler.m_opacity != 0.0f) + { + // Precalculate the inverse opacity that we'll use for blending the current accumulated value with. + // In the one case of "Initialize" blending, force this value to 0 so that we erase any accumulated values. + const float inverseOpacity = (layer.m_operation == MixedGradientLayer::MixingOperation::Initialize) + ? 0.0f + : (1.0f - layer.m_gradientSampler.m_opacity); + + // this includes leveling and opacity result, we need unpremultiplied opacity to combine properly + layer.m_gradientSampler.GetValues(positions, layerValues); + + for (size_t index = 0; index < outValues.size(); index++) + { + // unpremultiplied alpha (we clamp the end result) + const float currentUnpremultiplied = layerValues[index] / layer.m_gradientSampler.m_opacity; + const float operationResult = PerformMixingOperation(layer.m_operation, outValues[index], currentUnpremultiplied); + // blend layers (re-applying opacity, which is why we needed to use unpremultiplied) + outValues[index] = (outValues[index] * inverseOpacity) + (operationResult * layer.m_gradientSampler.m_opacity); + } + } + } + + for (auto& outValue : outValues) + { + outValue = AZ::GetClamp(outValue, 0.0f, 1.0f); + } + } + + + bool MixedGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const { for (const auto& layer : m_configuration.m_layers) diff --git a/Gems/GradientSignal/Code/Source/Components/PosterizeGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/PosterizeGradientComponent.cpp index 21d321df13..4616e080f1 100644 --- a/Gems/GradientSignal/Code/Source/Components/PosterizeGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/PosterizeGradientComponent.cpp @@ -151,34 +151,28 @@ namespace GradientSignal float PosterizeGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { const float bands = AZ::GetMax(static_cast(m_configuration.m_bands), 2.0f); - const float input = AZ::GetClamp(m_configuration.m_gradientSampler.GetValue(sampleParams), 0.0f, 1.0f); - float output = 0.0f; + const float input = m_configuration.m_gradientSampler.GetValue(sampleParams); + return PosterizeValue(input, bands, m_configuration.m_mode); + } - // "quantize" the input down to a number that goes from 0 to (bands-1) - const float band = AZ::GetClamp(floorf(input * bands), 0.0f, bands - 1.0f); - - // Given our quantized band, produce the right output for that band range. - switch (m_configuration.m_mode) + void PosterizeGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) { - default: - case PosterizeGradientConfig::ModeType::Floor: - // Floor: the output range should be the lowest value of each band, or (0 to bands-1) / bands - output = (band + 0.0f) / bands; - break; - case PosterizeGradientConfig::ModeType::Round: - // Round: the output range should be the midpoint of each band, or (0.5 to bands-0.5) / bands - output = (band + 0.5f) / bands; - break; - case PosterizeGradientConfig::ModeType::Ceiling: - // Ceiling: the output range should be the highest value of each band, or (1 to bands) / bands - output = (band + 1.0f) / bands; - break; - case PosterizeGradientConfig::ModeType::Ps: - // Ps: the output range should be equally distributed from 0-1, or (0 to bands-1) / (bands-1) - output = band / (bands - 1.0f); - break; + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + const float bands = AZ::GetMax(static_cast(m_configuration.m_bands), 2.0f); + + // Fill in the outValues with all of the generated inupt gradient values. + m_configuration.m_gradientSampler.GetValues(positions, outValues); + + // Run through all the input values and posterize them. + for (auto& outValue : outValues) + { + outValue = PosterizeValue(outValue, bands, m_configuration.m_mode); } - return AZ::GetClamp(output, 0.0f, 1.0f); } bool PosterizeGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const diff --git a/Gems/GradientSignal/Code/Source/Components/ReferenceGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ReferenceGradientComponent.cpp index ea304a7eed..e135401ff5 100644 --- a/Gems/GradientSignal/Code/Source/Components/ReferenceGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ReferenceGradientComponent.cpp @@ -131,13 +131,18 @@ namespace GradientSignal float ReferenceGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - AZ_PROFILE_FUNCTION(Entity); + return m_configuration.m_gradientSampler.GetValue(sampleParams); + } - float output = 0.0f; + void ReferenceGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } - output = m_configuration.m_gradientSampler.GetValue(sampleParams); - - return output; + m_configuration.m_gradientSampler.GetValues(positions, outValues); } bool ReferenceGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const diff --git a/Gems/GradientSignal/Code/Source/Components/SmoothStepGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/SmoothStepGradientComponent.cpp index 510ed41510..683f0a37fa 100644 --- a/Gems/GradientSignal/Code/Source/Components/SmoothStepGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/SmoothStepGradientComponent.cpp @@ -168,12 +168,20 @@ namespace GradientSignal float SmoothStepGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - float output = 0.0f; + const float value = m_configuration.m_gradientSampler.GetValue(sampleParams); + return m_configuration.m_smoothStep.GetSmoothedValue(value); + } - const float value = AZ::GetClamp(m_configuration.m_gradientSampler.GetValue(sampleParams), 0.0f, 1.0f); - output = m_configuration.m_smoothStep.GetSmoothedValue(value); + void SmoothStepGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } - return output; + m_configuration.m_gradientSampler.GetValues(positions, outValues); + m_configuration.m_smoothStep.GetSmoothedValues(outValues); } bool SmoothStepGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const diff --git a/Gems/GradientSignal/Code/Source/Components/SurfaceAltitudeGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/SurfaceAltitudeGradientComponent.cpp index 8b36182750..ee6c272e40 100644 --- a/Gems/GradientSignal/Code/Source/Components/SurfaceAltitudeGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/SurfaceAltitudeGradientComponent.cpp @@ -202,19 +202,49 @@ namespace GradientSignal float SurfaceAltitudeGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); SurfaceData::SurfacePointList points; SurfaceData::SurfaceDataSystemRequestBus::Broadcast(&SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePoints, sampleParams.m_position, m_configuration.m_surfaceTagsToSample, points); - if (points.empty()) + return CalculateAltitudeRatio(points, m_configuration.m_altitudeMin, m_configuration.m_altitudeMax); + } + + void SurfaceAltitudeGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) { - return 0.0f; + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; } - const AZ::Vector3& position = points.front().m_position; - return GetRatio(m_configuration.m_altitudeMin, m_configuration.m_altitudeMax, position.GetZ()); + AZStd::shared_lock lock(m_cacheMutex); + bool valuesFound = false; + + // Rather than calling GetSurfacePoints on the EBus repeatedly in a loop, we instead pass a lambda into the EBus that contains + // the loop within it so that we can avoid the repeated EBus-calling overhead. + SurfaceData::SurfaceDataSystemRequestBus::Broadcast( + [this, positions, &outValues, &valuesFound](SurfaceData::SurfaceDataSystemRequestBus::Events* surfaceDataRequests) + { + // It's possible that there's nothing connected to the EBus, so keep track of the fact that we have valid results. + valuesFound = true; + SurfaceData::SurfacePointList points; + + // For each position, call GetSurfacePoints() and turn the height into a 0-1 value based on our min/max altitudes. + for (size_t index = 0; index < positions.size(); index++) + { + points.clear(); + surfaceDataRequests->GetSurfacePoints(positions[index], m_configuration.m_surfaceTagsToSample, points); + outValues[index] = CalculateAltitudeRatio(points, m_configuration.m_altitudeMin, m_configuration.m_altitudeMax); + } + }); + + if (!valuesFound) + { + // No surface data, so no output values. + AZStd::fill(outValues.begin(), outValues.end(), 0.0f); + } } void SurfaceAltitudeGradientComponent::OnCompositionChanged() @@ -246,7 +276,7 @@ namespace GradientSignal { AZ_PROFILE_FUNCTION(Entity); - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); if (m_configuration.m_shapeEntityId.IsValid()) { diff --git a/Gems/GradientSignal/Code/Source/Components/SurfaceMaskGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/SurfaceMaskGradientComponent.cpp index df7a3f5787..f697050f56 100644 --- a/Gems/GradientSignal/Code/Source/Components/SurfaceMaskGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/SurfaceMaskGradientComponent.cpp @@ -161,8 +161,6 @@ namespace GradientSignal float SurfaceMaskGradientComponent::GetValue(const GradientSampleParams& params) const { - AZ_PROFILE_FUNCTION(Entity); - float result = 0.0f; if (!m_configuration.m_surfaceTagList.empty()) @@ -171,18 +169,50 @@ namespace GradientSignal SurfaceData::SurfaceDataSystemRequestBus::Broadcast(&SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePoints, params.m_position, m_configuration.m_surfaceTagList, points); - for (const auto& point : points) - { - for (const auto& maskPair : point.m_masks) - { - result = AZ::GetMax(AZ::GetClamp(maskPair.second, 0.0f, 1.0f), result); - } - } + result = GetMaxSurfaceWeight(points); } return result; } + void SurfaceMaskGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + bool valuesFound = false; + + if (!m_configuration.m_surfaceTagList.empty()) + { + // Rather than calling GetSurfacePoints on the EBus repeatedly in a loop, we instead pass a lambda into the EBus that contains + // the loop within it so that we can avoid the repeated EBus-calling overhead. + SurfaceData::SurfaceDataSystemRequestBus::Broadcast( + [this, positions, &outValues, &valuesFound](SurfaceData::SurfaceDataSystemRequestBus::Events* surfaceDataRequests) + { + // It's possible that there's nothing connected to the EBus, so keep track of the fact that we have valid results. + valuesFound = true; + SurfaceData::SurfacePointList points; + + for (size_t index = 0; index < positions.size(); index++) + { + points.clear(); + surfaceDataRequests->GetSurfacePoints(positions[index], m_configuration.m_surfaceTagList, points); + outValues[index] = GetMaxSurfaceWeight(points); + } + }); + } + + if (!valuesFound) + { + // No surface tags, so no output values. + AZStd::fill(outValues.begin(), outValues.end(), 0.0f); + } + + } + size_t SurfaceMaskGradientComponent::GetNumTags() const { return m_configuration.GetNumTags(); diff --git a/Gems/GradientSignal/Code/Source/Components/SurfaceSlopeGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/SurfaceSlopeGradientComponent.cpp index 84e0b61a62..50105a862f 100644 --- a/Gems/GradientSignal/Code/Source/Components/SurfaceSlopeGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/SurfaceSlopeGradientComponent.cpp @@ -209,36 +209,50 @@ namespace GradientSignal SurfaceData::SurfaceDataSystemRequestBus::Broadcast(&SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePoints, sampleParams.m_position, m_configuration.m_surfaceTagsToSample, points); - if (points.empty()) - { - return 0.0f; - } - - // Assuming our surface normal vector is actually normalized, we can get the slope - // by just grabbing the Z value. It's the same thing as normal.Dot(AZ::Vector3::CreateAxisZ()). - AZ_Assert(points.front().m_normal.GetNormalized().IsClose(points.front().m_normal), "Surface normals are expected to be normalized"); - const float slope = points.front().m_normal.GetZ(); - // Convert slope back to an angle so that we can lerp in "angular space", not "slope value space". - // (We want our 0-1 range to be linear across the range of angles) - const float slopeAngle = acosf(slope); - const float angleMin = AZ::DegToRad(AZ::GetClamp(m_configuration.m_slopeMin, 0.0f, 90.0f)); const float angleMax = AZ::DegToRad(AZ::GetClamp(m_configuration.m_slopeMax, 0.0f, 90.0f)); - switch (m_configuration.m_rampType) + return GetSlopeRatio(points, angleMin, angleMax); + } + + void SurfaceSlopeGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) { - case SurfaceSlopeGradientConfig::RampType::SMOOTH_STEP: - return m_configuration.m_smoothStep.GetSmoothedValue(GetRatio(angleMin, angleMax, slopeAngle)); - case SurfaceSlopeGradientConfig::RampType::LINEAR_RAMP_UP: - // For ramp up, linearly interpolate from min to max. - return GetRatio(angleMin, angleMax, slopeAngle); - case SurfaceSlopeGradientConfig::RampType::LINEAR_RAMP_DOWN: - default: - // For ramp down, linearly interpolate from max to min. - return GetRatio(angleMax, angleMin, slopeAngle); + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + bool valuesFound = false; + + // Rather than calling GetSurfacePoints on the EBus repeatedly in a loop, we instead pass a lambda into the EBus that contains + // the loop within it so that we can avoid the repeated EBus-calling overhead. + SurfaceData::SurfaceDataSystemRequestBus::Broadcast( + [this, positions, &outValues, &valuesFound](SurfaceData::SurfaceDataSystemRequestBus::Events* surfaceDataRequests) + { + // It's possible that there's nothing connected to the EBus, so keep track of the fact that we have valid results. + valuesFound = true; + SurfaceData::SurfacePointList points; + + const float angleMin = AZ::DegToRad(AZ::GetClamp(m_configuration.m_slopeMin, 0.0f, 90.0f)); + const float angleMax = AZ::DegToRad(AZ::GetClamp(m_configuration.m_slopeMax, 0.0f, 90.0f)); + + for (size_t index = 0; index < positions.size(); index++) + { + points.clear(); + surfaceDataRequests->GetSurfacePoints(positions[index], m_configuration.m_surfaceTagsToSample, points); + outValues[index] = GetSlopeRatio(points, angleMin, angleMax); + } + }); + + if (!valuesFound) + { + // No surface tags, so no output values. + AZStd::fill(outValues.begin(), outValues.end(), 0.0f); } } + float SurfaceSlopeGradientComponent::GetSlopeMin() const { return m_configuration.m_slopeMin; diff --git a/Gems/GradientSignal/Code/Source/Components/ThresholdGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ThresholdGradientComponent.cpp index a47ebdebe6..5df579576d 100644 --- a/Gems/GradientSignal/Code/Source/Components/ThresholdGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ThresholdGradientComponent.cpp @@ -138,11 +138,22 @@ namespace GradientSignal float ThresholdGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - float output = 0.0f; + return (m_configuration.m_gradientSampler.GetValue(sampleParams) <= m_configuration.m_threshold) ? 0.0f : 1.0f; + } - output = m_configuration.m_gradientSampler.GetValue(sampleParams) <= m_configuration.m_threshold ? 0.0f : 1.0f; + void ThresholdGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } - return output; + m_configuration.m_gradientSampler.GetValues(positions, outValues); + for (auto& outValue : outValues) + { + outValue = (outValue <= m_configuration.m_threshold) ? 0.0f : 1.0f; + } } bool ThresholdGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const From b09caa5e7576af98b060f339308f779c9af1b6d5 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 18 Jan 2022 17:14:49 -0600 Subject: [PATCH 28/36] Atom Tools: disabling auto load of unused gems in some atom tools Atom tools are set up to inherit and automatically load all of the gems used by the game project. This is a great simplification that saves us from having to manually update cmake settings for every game project to push dependencies to every tool. The tradeoff is that some dependencies will be added to certain tools that have no relevance whatsoever, potentially wasting initialization time, memory utilization, and some processing. This change follows an existing example to update a couple of tools to forego initializing unused gems. They can easily be reenabled as needed. Signed-off-by: Guthrie Adams --- .../Include/AtomToolsFramework/Util/Util.h | 2 +- .../Code/Source/Util/Util.cpp | 6 +- .../EditorMaterialSystemComponent.cpp | 2 +- Registry/gem_autoload.materialeditor.setreg | 69 +++++++++++++++++++ ...em_autoload.shadermanagementconsole.setreg | 69 +++++++++++++++++++ 5 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 Registry/gem_autoload.materialeditor.setreg create mode 100644 Registry/gem_autoload.shadermanagementconsole.setreg diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/Util.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/Util.h index ab2b8b46c0..57355e4f56 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/Util.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/Util.h @@ -38,5 +38,5 @@ namespace AtomToolsFramework QFileInfo GetOpenFileInfo(const AZStd::vector& assetTypes); QFileInfo GetUniqueFileInfo(const QString& initialPath); QFileInfo GetDuplicationFileInfo(const QString& initialPath); - bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments); + bool LaunchTool(const QString& baseName, const QStringList& arguments); } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/Util.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/Util.cpp index b45ff3c12f..89a5407260 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/Util.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/Util.cpp @@ -168,13 +168,13 @@ namespace AtomToolsFramework return duplicateFileInfo; } - bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments) + bool LaunchTool(const QString& baseName, const QStringList& arguments) { AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath(); AZ_Assert(!engineRoot.empty(), "Cannot query Engine Path"); - AZ::IO::FixedMaxPath launchPath = AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) - / (baseName + extension).toUtf8().constData(); + AZ::IO::FixedMaxPath launchPath = + AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / (baseName + AZ_TRAIT_OS_EXECUTABLE_EXTENSION).toUtf8().constData(); return QProcess::startDetached(launchPath.c_str(), arguments, engineRoot.c_str()); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index adaebfb889..e216606401 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -143,7 +143,7 @@ namespace AZ arguments.append(QString("--project-path=%1").arg(projectPath.c_str())); } - AtomToolsFramework::LaunchTool("MaterialEditor", AZ_TRAIT_OS_EXECUTABLE_EXTENSION, arguments); + AtomToolsFramework::LaunchTool("MaterialEditor", arguments); } void EditorMaterialSystemComponent::OpenMaterialInspector( diff --git a/Registry/gem_autoload.materialeditor.setreg b/Registry/gem_autoload.materialeditor.setreg new file mode 100644 index 0000000000..fd00ff05c7 --- /dev/null +++ b/Registry/gem_autoload.materialeditor.setreg @@ -0,0 +1,69 @@ +{ + "Amazon": { + "Gems": { + "ImGui.Editor": { + "AutoLoad": false + }, + "Gestures.Editor": { + "AutoLoad": false + }, + "GraphCanvas.Editor": { + "AutoLoad": false + }, + "GraphModel.Editor": { + "AutoLoad": false + }, + "PhysX.Editor": { + "AutoLoad": false + }, + "PhysXDebug.Editor": { + "AutoLoad": false + }, + "Blast.Editor": { + "AutoLoad": false + }, + "NVCloth.Editor": { + "AutoLoad": false + }, + "ScriptCanvas.Editor": { + "AutoLoad": false + }, + "ScriptCanvasPhysics": { + "AutoLoad": false + }, + "ScriptCanvasTesting.Editor": { + "AutoLoad": false + }, + "LandscapeCanvas.Editor": { + "AutoLoad": false + }, + "HttpRequestor.Editor": { + "AutoLoad": false + }, + "WhiteBox.Editor": { + "AutoLoad": false + }, + "PythonAssetBuilder.Editor": { + "AutoLoad": false + }, + "AWSCore": { + "AutoLoad": false + }, + "AWSCore.Editor": { + "AutoLoad": false + }, + "AWSClientAuth": { + "AutoLoad": false + }, + "AWSClientAuth.Editor": { + "AutoLoad": false + }, + "AWSMetrics": { + "AutoLoad": false + }, + "AWSMetrics.Editor": { + "AutoLoad": false + } + } + } +} diff --git a/Registry/gem_autoload.shadermanagementconsole.setreg b/Registry/gem_autoload.shadermanagementconsole.setreg new file mode 100644 index 0000000000..fd00ff05c7 --- /dev/null +++ b/Registry/gem_autoload.shadermanagementconsole.setreg @@ -0,0 +1,69 @@ +{ + "Amazon": { + "Gems": { + "ImGui.Editor": { + "AutoLoad": false + }, + "Gestures.Editor": { + "AutoLoad": false + }, + "GraphCanvas.Editor": { + "AutoLoad": false + }, + "GraphModel.Editor": { + "AutoLoad": false + }, + "PhysX.Editor": { + "AutoLoad": false + }, + "PhysXDebug.Editor": { + "AutoLoad": false + }, + "Blast.Editor": { + "AutoLoad": false + }, + "NVCloth.Editor": { + "AutoLoad": false + }, + "ScriptCanvas.Editor": { + "AutoLoad": false + }, + "ScriptCanvasPhysics": { + "AutoLoad": false + }, + "ScriptCanvasTesting.Editor": { + "AutoLoad": false + }, + "LandscapeCanvas.Editor": { + "AutoLoad": false + }, + "HttpRequestor.Editor": { + "AutoLoad": false + }, + "WhiteBox.Editor": { + "AutoLoad": false + }, + "PythonAssetBuilder.Editor": { + "AutoLoad": false + }, + "AWSCore": { + "AutoLoad": false + }, + "AWSCore.Editor": { + "AutoLoad": false + }, + "AWSClientAuth": { + "AutoLoad": false + }, + "AWSClientAuth.Editor": { + "AutoLoad": false + }, + "AWSMetrics": { + "AutoLoad": false + }, + "AWSMetrics.Editor": { + "AutoLoad": false + } + } + } +} From eb51cd4c06670380314c1a54a5b10a858749b354 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 18 Jan 2022 01:50:05 -0600 Subject: [PATCH 29/36] Atom Tools: moving custom asset browser code to common location Consolidated duplicate asset browser code from multiple tools into single class in atom tools framework Moved creation of asset browser and Python terminal windows into base main window class Fixed docked window orientations Added checks to asset browser to prevent crashes if tree state saver was null Signed-off-by: Guthrie Adams --- .../Views/AssetBrowserTreeView.cpp | 11 +- .../AssetBrowser/AtomToolsAssetBrowser.h} | 48 ++-- .../Window/AtomToolsMainWindow.h | 3 + .../AssetBrowser/AtomToolsAssetBrowser.cpp} | 215 +++++++++--------- .../AssetBrowser/AtomToolsAssetBrowser.qrc | 5 + .../AssetBrowser/AtomToolsAssetBrowser.ui} | 4 +- .../Code/Source/AssetBrowser/Icons/view.svg} | 0 .../Document/AtomToolsDocumentMainWindow.cpp | 2 + .../Source/Window/AtomToolsMainWindow.cpp | 6 + .../Code/atomtoolsframework_files.cmake | 4 + .../Code/Source/Window/MaterialEditor.qrc | 1 - .../Source/Window/MaterialEditorWindow.cpp | 36 ++- .../Code/Source/Window/MaterialEditorWindow.h | 5 +- .../Window/MaterialEditorWindowModule.cpp | 1 + .../Code/materialeditorwindow_files.cmake | 3 - .../Code/CMakeLists.txt | 1 - .../ShaderManagementConsoleBrowserWidget.h | 69 ------ .../ShaderManagementConsoleBrowserWidget.ui | 168 -------------- .../Window/ShaderManagementConsoleWindow.cpp | 19 +- .../Window/ShaderManagementConsoleWindow.h | 4 +- .../ShaderManagementConsoleWindowModule.cpp | 12 +- .../shadermanagementconsolewindow_files.cmake | 3 - 22 files changed, 212 insertions(+), 408 deletions(-) rename Gems/Atom/Tools/{MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h => AtomToolsFramework/Code/Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h} (54%) rename Gems/Atom/Tools/{MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp => AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp} (56%) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.qrc rename Gems/Atom/Tools/{MaterialEditor/Code/Source/Window/MaterialBrowserWidget.ui => AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.ui} (98%) rename Gems/Atom/Tools/{MaterialEditor/Code/Source/Window/Icons/View.svg => AtomToolsFramework/Code/Source/AssetBrowser/Icons/view.svg} (100%) delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.ui diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp index 146eab9073..93a153cc16 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.cpp @@ -230,7 +230,10 @@ namespace AzToolsFramework { QModelIndex curIndex = selectedIndexes[0]; m_expandToEntriesByDefault = true; - m_treeStateSaver->ApplySnapshot(); + if (m_treeStateSaver) + { + m_treeStateSaver->ApplySnapshot(); + } setCurrentIndex(curIndex); scrollTo(curIndex); @@ -240,8 +243,12 @@ namespace AzToolsFramework // Flag our default expansion state so that we expand down to source entries after filtering m_expandToEntriesByDefault = hasFilter; + // Then ask our state saver to apply its current snapshot again, falling back on asking us if entries should be expanded or not - m_treeStateSaver->ApplySnapshot(); + if (m_treeStateSaver) + { + m_treeStateSaver->ApplySnapshot(); + } // If we're filtering for a valid entry, select the first valid entry if (hasFilter && selectFirstValidEntry) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h similarity index 54% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h rename to Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h index 24a244bc3c..915387d7b1 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h @@ -9,17 +9,14 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include #include -#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include AZ_POP_DISABLE_WARNING - #endif namespace AzToolsFramework @@ -27,49 +24,50 @@ namespace AzToolsFramework namespace AssetBrowser { class AssetBrowserFilterModel; - class CompositeFilter; - class AssetBrowserEntry; - class ProductAssetBrowserEntry; - class SourceAssetBrowserEntry; } -} +} // namespace AzToolsFramework namespace Ui { - class MaterialBrowserWidget; + class AtomToolsAssetBrowser; } -namespace MaterialEditor +namespace AtomToolsFramework { - //! Provides a tree view of all available materials and other assets exposed by the MaterialEditor. - class MaterialBrowserWidget + //! Extends the standard asset browser with custom filters and multiselect behavior + class AtomToolsAssetBrowser : public QWidget , protected AZ::TickBus::Handler - , protected AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler { Q_OBJECT public: - MaterialBrowserWidget(QWidget* parent = nullptr); - ~MaterialBrowserWidget(); + AtomToolsAssetBrowser(QWidget* parent = nullptr); + ~AtomToolsAssetBrowser(); - private: - AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; + void SetFilterState(const AZStd::string& category, const AZStd::string& displayName, bool enabled); + void SetOpenHandler(AZStd::function openHandler); + + void SelectEntries(const AZStd::string& absolutePath); void OpenSelectedEntries(); + void OpenOptionsMenu(); - // AtomToolsDocumentNotificationBus::Handler implementation - void OnDocumentOpened(const AZ::Uuid& documentId) override; + protected: + AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; + void UpdateFilter(); + void UpdatePreview(); + void TogglePreview(); // AZ::TickBus::Handler void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - void OpenOptionsMenu(); - - QScopedPointer m_ui; + QScopedPointer m_ui; AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel = nullptr; - //! if new asset is being created with this path it will automatically be selected + //! If an asset is opened with this path it will automatically be selected AZStd::string m_pathToSelect; - QByteArray m_materialBrowserState; + QByteArray m_browserState; + + AZStd::function m_openHandler; }; -} // namespace MaterialEditor +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h index fab6e2fb01..92218d2542 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Window/AtomToolsMainWindow.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include #include @@ -53,6 +54,8 @@ namespace AtomToolsFramework QMenu* m_menuView = {}; QMenu* m_menuHelp = {}; + AtomToolsFramework::AtomToolsAssetBrowser* m_assetBrowser = {}; + AZStd::unordered_map m_dockWidgets; AZStd::unordered_map m_dockActions; }; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp similarity index 56% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp rename to Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp index 4df76b4dac..4270cb87fe 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.cpp @@ -6,13 +6,9 @@ * */ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -21,41 +17,32 @@ #include #include #include -#include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include #include -#include -#include #include #include #include -#include AZ_POP_DISABLE_WARNING -namespace MaterialEditor +namespace AtomToolsFramework { - MaterialBrowserWidget::MaterialBrowserWidget(QWidget* parent) + AtomToolsAssetBrowser::AtomToolsAssetBrowser(QWidget* parent) : QWidget(parent) - , m_ui(new Ui::MaterialBrowserWidget) + , m_ui(new Ui::AtomToolsAssetBrowser) { using namespace AzToolsFramework::AssetBrowser; m_ui->setupUi(this); m_ui->m_searchWidget->Setup(true, true); - m_ui->m_searchWidget->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true); - m_ui->m_searchWidget->SetFilterState("", AZ::RPI::MaterialAsset::Group, true); m_ui->m_searchWidget->setMinimumSize(QSize(150, 0)); - m_ui->m_viewOptionButton->setIcon(QIcon(":/Icons/View.svg")); + + m_ui->m_viewOptionButton->setIcon(QIcon(":/Icons/view.svg")); m_ui->m_splitter->setSizes(QList() << 400 << 200); m_ui->m_splitter->setStretchFactor(0, 1); - connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &MaterialBrowserWidget::OpenOptionsMenu); - // Get the asset browser model AssetBrowserModel* assetBrowserModel = nullptr; AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel); @@ -73,38 +60,82 @@ namespace MaterialEditor // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main"); - connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel, &AssetBrowserFilterModel::filterUpdatedSlot); - connect(m_filterModel, &AssetBrowserFilterModel::filterChanged, this, [this]() - { - const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); - constexpr bool selectFirstFilteredIndex = true; - m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); - }); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &MaterialBrowserWidget::OpenSelectedEntries); - connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, [this]() { - const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); - if (!selectedAssets.empty()) - { - m_ui->m_previewerFrame->Display(selectedAssets.front()); - } - else - { - m_ui->m_previewerFrame->Clear(); - } - }); - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(); + connect(m_filterModel, &AssetBrowserFilterModel::filterChanged, this, &AtomToolsAssetBrowser::UpdateFilter); + connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &AtomToolsAssetBrowser::OpenSelectedEntries); + connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AtomToolsAssetBrowser::UpdatePreview); + connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &AtomToolsAssetBrowser::OpenOptionsMenu); + connect( + m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel, + &AssetBrowserFilterModel::filterUpdatedSlot); } - MaterialBrowserWidget::~MaterialBrowserWidget() + AtomToolsAssetBrowser::~AtomToolsAssetBrowser() { // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } - AzToolsFramework::AssetBrowser::FilterConstType MaterialBrowserWidget::CreateFilter() const + void AtomToolsAssetBrowser::SetFilterState(const AZStd::string& category, const AZStd::string& displayName, bool enabled) + { + m_ui->m_searchWidget->SetFilterState(category.c_str(), displayName.c_str(), enabled); + } + + void AtomToolsAssetBrowser::SetOpenHandler(AZStd::function openHandler) + { + m_openHandler = openHandler; + } + + void AtomToolsAssetBrowser::SelectEntries(const AZStd::string& absolutePath) + { + if (!absolutePath.empty()) + { + // Selecting a new asset in the browser is not guaranteed to happen immediately. + // The asset browser model notifications are sent before the model is updated. + // Instead of relying on the notifications, queue the selection and process it on tick until this change occurs. + m_pathToSelect = absolutePath; + AzFramework::StringFunc::Path::Normalize(m_pathToSelect); + AZ::TickBus::Handler::BusConnect(); + } + } + + void AtomToolsAssetBrowser::OpenSelectedEntries() + { + const AZStd::vector entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); + + const int multiSelectPromptThreshold = 10; + if (entries.size() >= multiSelectPromptThreshold) + { + QMessageBox::StandardButton result = QMessageBox::question( + QApplication::activeWindow(), + tr("Attemptng to open %1 files").arg(entries.size()), + tr("Would you like to open anyway?"), + QMessageBox::Yes | QMessageBox::No); + if (result == QMessageBox::No) + { + return; + } + } + + for (const AssetBrowserEntry* entry : entries) + { + if (entry && entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Folder && m_openHandler) + { + m_openHandler(entry->GetFullPath().c_str()); + } + } + } + + void AtomToolsAssetBrowser::OpenOptionsMenu() + { + QMenu menu; + QAction* action = menu.addAction(tr("Show Asset Preview"), this, &AtomToolsAssetBrowser::TogglePreview); + action->setCheckable(true); + action->setChecked(m_ui->m_previewerFrame->isVisible()); + menu.exec(QCursor::pos()); + } + + AzToolsFramework::AssetBrowser::FilterConstType AtomToolsAssetBrowser::CreateFilter() const { using namespace AzToolsFramework::AssetBrowser; @@ -125,59 +156,42 @@ namespace MaterialEditor return finalFilter; } - void MaterialBrowserWidget::OpenSelectedEntries() + void AtomToolsAssetBrowser::UpdateFilter() { - const AZStd::vector entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); + const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty(); + constexpr bool selectFirstFilteredIndex = true; + m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex); + } - const int multiSelectPromptThreshold = 10; - if (entries.size() >= multiSelectPromptThreshold) + void AtomToolsAssetBrowser::UpdatePreview() + { + const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets(); + if (!selectedAssets.empty()) { - if (QMessageBox::question( - QApplication::activeWindow(), - QString("Attemptng to open %1 files").arg(entries.size()), - "Would you like to open anyway?", - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) - { - return; - } + m_ui->m_previewerFrame->Display(selectedAssets.front()); } - - for (const AssetBrowserEntry* entry : entries) + else { - if (entry) - { - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension)) - { - AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); - } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) - { - //ignore AZ::RPI::MaterialTypeSourceData::Extension - } - else - { - QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); - } - } + m_ui->m_previewerFrame->Clear(); } } - void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) + void AtomToolsAssetBrowser::TogglePreview() { - AZStd::string absolutePath; - AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath); - if (!absolutePath.empty()) + const bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible(); + m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible); + if (isPreviewFrameVisible) { - // Selecting a new asset in the browser is not guaranteed to happen immediately. - // The asset browser model notifications are sent before the model is updated. - // Instead of relying on the notifications, queue the selection and process it on tick until this change occurs. - m_pathToSelect = absolutePath; - AzFramework::StringFunc::Path::Normalize(m_pathToSelect); - AZ::TickBus::Handler::BusConnect(); + m_browserState = m_ui->m_splitter->saveState(); + m_ui->m_splitter->setSizes(QList({ 1, 0 })); + } + else + { + m_ui->m_splitter->restoreState(m_browserState); } } - void MaterialBrowserWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time) + void AtomToolsAssetBrowser::OnTick(float deltaTime, AZ::ScriptTimePoint time) { AZ_UNUSED(time); AZ_UNUSED(deltaTime); @@ -188,7 +202,7 @@ namespace MaterialEditor AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect); - // Iterate over the selected entries to verify if the selection was made + // Iterate over the selected entries to verify if the selection was made for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()) { if (entry) @@ -205,31 +219,6 @@ namespace MaterialEditor } } } +} // namespace AtomToolsFramework - void MaterialBrowserWidget::OpenOptionsMenu() - { - QMenu menu; - - QAction* action = new QAction("Show Asset Preview", this); - action->setCheckable(true); - action->setChecked(m_ui->m_previewerFrame->isVisible()); - connect(action, &QAction::triggered, [this]() { - bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible(); - m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible); - if (isPreviewFrameVisible) - { - m_materialBrowserState = m_ui->m_splitter->saveState(); - m_ui->m_splitter->setSizes(QList({ 1, 0 })); - } - else - { - m_ui->m_splitter->restoreState(m_materialBrowserState); - } - }); - menu.addAction(action); - menu.exec(QCursor::pos()); - } - -} // namespace MaterialEditor - -#include +#include diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.qrc b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.qrc new file mode 100644 index 0000000000..c24968e78a --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.qrc @@ -0,0 +1,5 @@ + + + Icons/view.svg + + diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.ui b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.ui similarity index 98% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.ui rename to Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.ui index 9e5344bea2..9b68b3edc9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.ui +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/AtomToolsAssetBrowser.ui @@ -1,7 +1,7 @@ - MaterialBrowserWidget - + AtomToolsAssetBrowser + 0 diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/View.svg b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/Icons/view.svg similarity index 100% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/View.svg rename to Gems/Atom/Tools/AtomToolsFramework/Code/Source/AssetBrowser/Icons/view.svg diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp index 0d62adc9ee..e8be20097f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentMainWindow.cpp @@ -414,6 +414,8 @@ namespace AtomToolsFramework m_actionPreviousTab->setEnabled(m_tabWidget->count() > 1); m_actionNextTab->setEnabled(m_tabWidget->count() > 1); + m_assetBrowser->SelectEntries(absolutePath); + activateWindow(); raise(); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp index f07fd9c536..6a30ffc421 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -40,6 +41,11 @@ namespace AtomToolsFramework centralWidget->setLayout(centralWidgetLayout); setCentralWidget(centralWidget); + m_assetBrowser = new AtomToolsFramework::AtomToolsAssetBrowser(this); + AddDockWidget("Asset Browser", m_assetBrowser, Qt::BottomDockWidgetArea, Qt::Horizontal); + AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + SetDockWidgetVisible("Python Terminal", false); + AtomToolsMainWindowRequestBus::Handler::BusConnect(); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 3ddcc05245..3de1bb65e2 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -8,6 +8,7 @@ set(FILES Include/AtomToolsFramework/Application/AtomToolsApplication.h + Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h Include/AtomToolsFramework/Communication/LocalServer.h Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -36,6 +37,9 @@ set(FILES Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h Source/Application/AtomToolsApplication.cpp + Source/AssetBrowser/AtomToolsAssetBrowser.cpp + Source/AssetBrowser/AtomToolsAssetBrowser.qrc + Source/AssetBrowser/AtomToolsAssetBrowser.ui Source/Communication/LocalServer.cpp Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditor.qrc b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditor.qrc index 902201e792..73b55f2f39 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditor.qrc +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditor.qrc @@ -21,6 +21,5 @@ Icons/shadow.svg Icons/skybox.svg Icons/toneMapping.svg - Icons/View.svg diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 0388af0134..44adda432d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -8,15 +8,16 @@ #include #include +#include +#include #include +#include #include #include #include -#include #include #include #include -#include #include #include #include @@ -27,14 +28,16 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include +#include #include +#include #include AZ_POP_DISABLE_WARNING namespace MaterialEditor { MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */) - : AtomToolsFramework::AtomToolsDocumentMainWindow(parent) + : Base(parent) { resize(1280, 1024); @@ -72,15 +75,30 @@ namespace MaterialEditor m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); centralWidget()->layout()->addWidget(m_materialViewport); - AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); - AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal); - AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Horizontal); - AddDockWidget("Performance Monitor", new PerformanceMonitorWidget, Qt::RightDockWidgetArea, Qt::Horizontal); - AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + m_assetBrowser->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true); + m_assetBrowser->SetFilterState("", AZ::RPI::MaterialAsset::Group, true); + m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) { + if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) + { + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath); + return; + } + + if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) + { + return; + } + + QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str())); + }); + + AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Vertical); + AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Vertical); + AddDockWidget("Performance Monitor", new PerformanceMonitorWidget, Qt::BottomDockWidgetArea, Qt::Horizontal); SetDockWidgetVisible("Viewport Settings", false); SetDockWidgetVisible("Performance Monitor", false); - SetDockWidgetVisible("Python Terminal", false); // Restore geometry and show the window mainWindowWrapper->showFromSettings(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index bed2aa34e4..8ad294c529 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -21,7 +21,6 @@ namespace MaterialEditor { //! MaterialEditorWindow is the main class. Its responsibility is limited to initializing and connecting //! its panels, managing selection of assets, and performing high-level actions like saving. It contains... - //! 1) MaterialBrowser - The user browses for Material (.material) assets. //! 2) MaterialViewport - The user can see the selected Material applied to a model. //! 3) MaterialPropertyInspector - The user edits the properties of the selected Material. class MaterialEditorWindow @@ -48,7 +47,7 @@ namespace MaterialEditor void closeEvent(QCloseEvent* closeEvent) override; - MaterialViewportWidget* m_materialViewport = nullptr; - MaterialEditorToolBar* m_toolBar = nullptr; + MaterialViewportWidget* m_materialViewport = {}; + MaterialEditorToolBar* m_toolBar = {}; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowModule.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowModule.cpp index c761c85556..1562d11647 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowModule.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowModule.cpp @@ -14,6 +14,7 @@ void InitMaterialEditorResources() //Must register qt resources from other modules Q_INIT_RESOURCE(MaterialEditor); Q_INIT_RESOURCE(InspectorWidget); + Q_INIT_RESOURCE(AtomToolsAssetBrowser); } namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index b814ad3f47..3d21e71294 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -15,9 +15,6 @@ set(FILES Source/Window/MaterialEditorWindow.cpp Source/Window/MaterialEditorWindowModule.cpp Source/Window/MaterialEditorWindowSettings.cpp - Source/Window/MaterialBrowserWidget.h - Source/Window/MaterialBrowserWidget.cpp - Source/Window/MaterialBrowserWidget.ui Source/Window/MaterialEditor.qrc Source/Window/MaterialEditor.qss Source/Window/MaterialEditorWindowComponent.h diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt index 3f7788418a..c5ceab5360 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt @@ -42,7 +42,6 @@ ly_add_target( NAME ShaderManagementConsole.Window STATIC NAMESPACE Gem AUTOMOC - AUTOUIC AUTORCC FILES_CMAKE shadermanagementconsolewindow_files.cmake diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h deleted file mode 100644 index 73a2a24aa9..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 - * - */ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#include - -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -AZ_POP_DISABLE_WARNING - -#endif - -namespace AzToolsFramework -{ - namespace AssetBrowser - { - class AssetBrowserFilterModel; - class CompositeFilter; - class AssetBrowserEntry; - class ProductAssetBrowserEntry; - class SourceAssetBrowserEntry; - } -} - -namespace Ui -{ - class ShaderManagementConsoleBrowserWidget; -} - -namespace ShaderManagementConsole -{ - //! Provides a tree view of all available assets - class ShaderManagementConsoleBrowserWidget - : public QWidget - , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler - { - Q_OBJECT - public: - ShaderManagementConsoleBrowserWidget(QWidget* parent = nullptr); - ~ShaderManagementConsoleBrowserWidget(); - - private: - AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; - void OpenSelectedEntries(); - - QScopedPointer m_ui; - AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel = nullptr; - - //! if new asset is being created with this path it will automatically be selected - AZStd::string m_pathToSelect; - - // AssetBrowserModelNotificationBus::Handler implementation - void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override; - - // AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler implementation - void OnDocumentOpened(const AZ::Uuid& documentId) override; - }; -} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.ui b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.ui deleted file mode 100644 index cf8a714273..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleBrowserWidget.ui +++ /dev/null @@ -1,168 +0,0 @@ - - - ShaderManagementConsoleBrowserWidget - - - - 0 - 0 - 691 - 554 - - - - Asset Browser - - - - 0 - - - - - - 1 - 1 - - - - true - - - - - 0 - 0 - 671 - 534 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - false - - - - - 0 - 0 - - - - vertical-align: top - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 1 - 0 - - - - QAbstractItemView::DragOnly - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - - - - - - AzToolsFramework::AssetBrowser::SearchWidget - QWidget -
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
- 1 -
- - AzToolsFramework::AssetBrowser::AssetBrowserTreeView - QTreeView -
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
-
- - AzToolsFramework::AssetBrowser::PreviewerFrame - QFrame -
AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h
- 1 -
-
- - -
diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index 29dafe99fe..8e8e047e83 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -7,23 +7,25 @@ */ #include +#include #include #include #include -#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include #include #include #include +#include #include AZ_POP_DISABLE_WARNING namespace ShaderManagementConsole { ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */) - : AtomToolsFramework::AtomToolsDocumentMainWindow(parent) + : Base(parent) { resize(1280, 1024); @@ -41,10 +43,17 @@ namespace ShaderManagementConsole m_toolBar->setObjectName("ToolBar"); addToolBar(m_toolBar); - AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical); - AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal); + m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true); + m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) { + if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) + { + AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath); + return; + } - SetDockWidgetVisible("Python Terminal", false); + QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str())); + }); // Restore geometry and show the window mainWindowWrapper->showFromSettings(); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h index 3ba122674a..1c7479e526 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.h @@ -14,9 +14,7 @@ #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include #include - #include AZ_POP_DISABLE_WARNING #endif @@ -40,6 +38,6 @@ namespace ShaderManagementConsole protected: QWidget* CreateDocumentTabView(const AZ::Uuid& documentId) override; - ShaderManagementConsoleToolBar* m_toolBar = nullptr; + ShaderManagementConsoleToolBar* m_toolBar = {}; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowModule.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowModule.cpp index 3db5b236d6..a13b873aee 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowModule.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindowModule.cpp @@ -9,10 +9,20 @@ #include #include +void InitShaderManagementConsoleResources() +{ + // Must register qt resources from other modules + Q_INIT_RESOURCE(ShaderManagementConsole); + Q_INIT_RESOURCE(InspectorWidget); + Q_INIT_RESOURCE(AtomToolsAssetBrowser); +} + namespace ShaderManagementConsole { ShaderManagementConsoleWindowModule::ShaderManagementConsoleWindowModule() { + InitShaderManagementConsoleResources(); + // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. m_descriptors.insert(m_descriptors.end(), { ShaderManagementConsoleWindowComponent::CreateDescriptor(), @@ -25,4 +35,4 @@ namespace ShaderManagementConsole azrtti_typeid(), }; } -} +} // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake index 0d33d990a4..fb5cc0dad6 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/shadermanagementconsolewindow_files.cmake @@ -14,9 +14,6 @@ set(FILES Source/Window/ShaderManagementConsoleWindow.h Source/Window/ShaderManagementConsoleWindow.cpp Source/Window/ShaderManagementConsoleWindowModule.cpp - Source/Window/ShaderManagementConsoleBrowserWidget.h - Source/Window/ShaderManagementConsoleBrowserWidget.cpp - Source/Window/ShaderManagementConsoleBrowserWidget.ui Source/Window/ShaderManagementConsole.qrc Source/Window/ShaderManagementConsoleWindowComponent.h Source/Window/ShaderManagementConsoleWindowComponent.cpp From 54de15b0ecd555a481c24f569e382d8a1e514ad0 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 18 Jan 2022 16:34:58 -0800 Subject: [PATCH 30/36] Adding '.network.spawnable' as a network constant Signed-off-by: Gene Walters --- .../Code/Include/Multiplayer/MultiplayerConstants.h | 1 + .../Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp | 3 ++- .../Code/Source/Pipeline/NetworkPrefabProcessor.cpp | 3 ++- Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h index 4471aa0c2b..3a4a9b1f58 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerConstants.h @@ -20,6 +20,7 @@ namespace Multiplayer constexpr AZStd::string_view MpNetworkInterfaceName("MultiplayerNetworkInterface"); constexpr AZStd::string_view MpEditorInterfaceName("MultiplayerEditorNetworkInterface"); constexpr AZStd::string_view LocalHost("127.0.0.1"); + constexpr AZStd::string_view NetworkSpawnableFileExtension(".network.spawnable"); constexpr uint16_t DefaultServerPort = 33450; constexpr uint16_t DefaultServerEditorPort = 33451; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp index 7fb7bfdc39..e668d43267 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace Multiplayer { @@ -42,7 +43,7 @@ namespace Multiplayer auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info) { if (info.m_assetType == AZ::AzTypeInfo::Uuid() && - info.m_relativePath.ends_with(".network.spawnable")) + info.m_relativePath.ends_with(NetworkSpawnableFileExtension)) { ProcessSpawnableAsset(info.m_relativePath, id); } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index a797523bc0..9d6c47bb00 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -95,7 +96,7 @@ namespace Multiplayer using namespace AzToolsFramework::Prefab; AZStd::string uniqueName = prefab.GetName(); - uniqueName += ".network.spawnable"; + uniqueName += NetworkSpawnableFileExtension; auto serializer = [serializationFormat](AZStd::vector& output, const ProcessedObjectStore& object) -> bool { AZ::IO::ByteContainerStream stream(&output); diff --git a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp index aef13fbfe2..32be828686 100644 --- a/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp +++ b/Gems/Multiplayer/Code/Tests/PrefabProcessingTests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace UnitTest @@ -92,7 +93,7 @@ namespace UnitTest // Verify the name and the type of the spawnable asset const AZ::Data::AssetData& spawnableAsset = processedObjects[0].GetAsset(); - EXPECT_EQ(prefabName + ".network.spawnable", processedObjects[0].GetId()); + EXPECT_EQ(prefabName + Multiplayer::NetworkSpawnableFileExtension.data(), processedObjects[0].GetId()); EXPECT_EQ(spawnableAsset.GetType(), azrtti_typeid()); // Verify we have only the networked entity in the network spawnable and not the static one From 45429872d60d79c1daa8b7957e967cc2526e642a Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 18 Jan 2022 17:39:44 -0800 Subject: [PATCH 31/36] Switched back to making MaterialAsset::GetPropertyValues automatically finalize the material asset. I realized that it's too burdensome to expect client code to call Finalize on the MaterialAsset; every code that calls GetPropertyValues would have to call Finalize(). Instead of using const_cast in GetPropertyValues like I was doing before, I just changed GetPropertyValues to be a non-const function. There were a few places in Decal code I had to update to pass non-const MaterialAsset pointers. This isn't ideal, but I think it's better than the alternatives. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Source/Decals/DecalTextureArray.cpp | 6 +- .../Code/Source/Decals/DecalTextureArray.h | 2 +- .../DecalTextureArrayFeatureProcessor.cpp | 6 +- .../DecalTextureArrayFeatureProcessor.h | 2 +- .../Atom/RPI.Reflect/Material/MaterialAsset.h | 29 ++++----- .../RPI.Builders/Material/MaterialBuilder.cpp | 2 +- .../Model/MaterialAssetBuilderComponent.cpp | 2 +- .../Source/RPI.Public/Material/Material.cpp | 2 - .../RPI.Reflect/Material/MaterialAsset.cpp | 33 ++++++---- .../Material/MaterialAssetCreator.cpp | 2 + .../Tests/Material/MaterialAssetTests.cpp | 61 +++++++++++++++++-- .../Material/MaterialSourceDataTests.cpp | 41 +++++-------- 12 files changed, 117 insertions(+), 71 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp index 36a59bd07f..56ff1648d4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.cpp @@ -49,7 +49,7 @@ namespace AZ } // Extract exactly which texture asset we need to load from the given material and map type (diffuse, normal, etc). - static AZ::Data::Asset GetStreamingImageAsset(const AZ::RPI::MaterialAsset& materialAsset, const AZ::Name& propertyName) + static AZ::Data::Asset GetStreamingImageAsset(AZ::RPI::MaterialAsset& materialAsset, const AZ::Name& propertyName) { if (!materialAsset.IsReady()) { @@ -84,7 +84,7 @@ namespace AZ static AZ::Data::Asset GetStreamingImageAsset(const AZ::Data::Asset materialAssetData, const AZ::Name& propertyName) { AZ_Assert(materialAssetData->IsReady(), "GetStreamingImageAsset() called with AssetData that is not ready."); - const AZ::RPI::MaterialAsset* materialAsset = materialAssetData.GetAs(); + AZ::RPI::MaterialAsset* materialAsset = materialAssetData.GetAs(); return GetStreamingImageAsset(*materialAsset, propertyName); } } @@ -141,7 +141,7 @@ namespace AZ return m_textureArrayPacked[mapType]; } - bool DecalTextureArray::IsValidDecalMaterial(const AZ::RPI::MaterialAsset& materialAsset) + bool DecalTextureArray::IsValidDecalMaterial(AZ::RPI::MaterialAsset& materialAsset) { return GetStreamingImageAsset(materialAsset, GetMapName(DecalMapType_Diffuse)).IsReady(); } diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.h b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.h index 97bd8b9cbe..39e66176fd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.h +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArray.h @@ -57,7 +57,7 @@ namespace AZ // often different (BC5 for normals, BC7 for diffuse, etc) const Data::Instance& GetPackedTexture(const DecalMapType mapType) const; - static bool IsValidDecalMaterial(const RPI::MaterialAsset& materialAsset); + static bool IsValidDecalMaterial(RPI::MaterialAsset& materialAsset); private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp index 393104907a..c6b4d4e754 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp @@ -25,7 +25,7 @@ namespace AZ { namespace { - static AZ::RHI::Size GetTextureSizeFromMaterialAsset(const AZ::RPI::MaterialAsset* materialAsset) + static AZ::RHI::Size GetTextureSizeFromMaterialAsset(AZ::RPI::MaterialAsset* materialAsset) { for (const auto& elem : materialAsset->GetPropertyValues()) { @@ -375,7 +375,7 @@ namespace AZ } } - AZStd::optional DecalTextureArrayFeatureProcessor::AddMaterialToTextureArrays(const AZ::RPI::MaterialAsset* materialAsset) + AZStd::optional DecalTextureArrayFeatureProcessor::AddMaterialToTextureArrays(AZ::RPI::MaterialAsset* materialAsset) { const RHI::Size textureSize = GetTextureSizeFromMaterialAsset(materialAsset); @@ -410,7 +410,7 @@ namespace AZ AZ_PROFILE_SCOPE(AzRender, "DecalTextureArrayFeatureProcessor: OnAssetReady"); const Data::AssetId& assetId = asset->GetId(); - const RPI::MaterialAsset* materialAsset = asset.GetAs(); + RPI::MaterialAsset* materialAsset = asset.GetAs(); const bool validDecalMaterial = materialAsset && DecalTextureArray::IsValidDecalMaterial(*materialAsset); if (validDecalMaterial) { diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h index fd535bbe64..bdd1739ebb 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.h @@ -111,7 +111,7 @@ namespace AZ void CacheShaderIndices(); // This call could fail (returning nullopt) if we run out of texture arrays - AZStd::optional AddMaterialToTextureArrays(const AZ::RPI::MaterialAsset* materialAsset); + AZStd::optional AddMaterialToTextureArrays(AZ::RPI::MaterialAsset* materialAsset); int FindTextureArrayWithSize(const RHI::Size& size) const; void RemoveMaterialFromDecal(const uint16_t decalIndex); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 941fcd0fe9..b7cc51dcc4 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -102,16 +102,6 @@ namespace AZ //! Returns a layout that includes a list of MaterialPropertyDescriptors for each material property. const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const; - //! Returns whether the material's properties are fully processed or not. - //! If true, property values can be accessed through GetPropertyValues(). - //! If false, property values can be accessed through GetRawPropertyValues(). - bool IsFinalized() const; - - //! If the material asset is not finalized yet, this does the final processing of the raw property values to - //! get the material asset ready to be used. - //! Note the MaterialTypeAsset must be valid before this is called. - void Finalize(AZStd::function reportWarning = nullptr, AZStd::function reportError = nullptr); - //! Returns the list of values for all properties in this material. //! The entries in this list align with the entries in the MaterialPropertiesLayout. Each AZStd::any is guaranteed //! to have a value of type that matches the corresponding MaterialPropertyDescriptor. @@ -122,19 +112,26 @@ namespace AZ //! //! Calling GetPropertyValues() will automatically finalize the material asset if it isn't finalized already. The //! MaterialTypeAsset must be loaded and ready. - const AZStd::vector& GetPropertyValues() const; - + const AZStd::vector& GetPropertyValues(); + + //! Returns true if material was created in a finalize state, as opposed to being finalized after loading from disk. + bool WasPreFinalized() const; + //! Returns the list of raw values for all properties in this material, as listed in the source .material file(s), before the material asset was Finalized. //! //! The MaterialAsset can be created in a "half-baked" state (see MaterialUtils::BuildersShouldFinalizeMaterialAssets) where //! minimal processing has been done because it did not yet have access to the MaterialTypeAsset. In that case, the list will //! be populated with values copied from the source .material file with little or no validation or other processing. It includes //! all parent .material files, with properties listed in low-to-high priority order. - //! This list will be empty however if the asset was finalized at build-time. + //! This list will be empty however if the asset was finalized at build-time (i.e. WasPreFinalized() returns true). const AZStd::vector>& GetRawPropertyValues() const; private: bool PostLoadInit() override; + + //! If the material asset is not finalized yet, this does the final processing of the raw property values to get the material asset ready to be used. + //! MaterialTypeAsset must be valid before this is called. + void Finalize(AZStd::function reportWarning = nullptr, AZStd::function reportError = nullptr); //! Checks the material type version and potentially applies a series of property changes (most common are simple property renames) //! based on the MaterialTypeAsset's version update procedure. @@ -159,7 +156,7 @@ namespace AZ //! Holds values for each material property, used to initialize Material instances. //! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout. - AZStd::vector m_propertyValues; + mutable AZStd::vector m_propertyValues; //! The MaterialAsset can be created in a "half-baked" state where minimal processing has been done because it does //! not yet have access to the MaterialTypeAsset. In that case, this list will be populated with values copied from @@ -175,10 +172,10 @@ namespace AZ AZStd::vector> m_rawPropertyValues; //! Tracks whether Finalize() has been called, meaning m_propertyValues is populated with data matching the material type's property layout. - bool m_isFinalized = false; + //! (This value is intentionally not serialized, it is set by the Finalize() function) + mutable bool m_isFinalized = false; //! Tracks whether the MaterialAsset was already in a finalized state when it was loaded. - //! (This value is intentionally not serialized) bool m_wasPreFinalized = false; //! The materialTypeVersion this materialAsset was based off. If the versions do not match at runtime when a diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index cedbb1df6e..768890a29b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -52,7 +52,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 114; // material dependency improvements + materialBuilderDescriptor.m_version = 115; // material dependency improvements updated materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index a44b47ee6c..9a92e7b762 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -128,7 +128,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(20); // material dependency improvements + ->Version(21); // material dependency improvements updated } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index fe9dbef278..1f739c24f1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -62,8 +62,6 @@ namespace AZ m_materialAsset = { &materialAsset, AZ::Data::AssetLoadBehavior::PreLoad }; - m_materialAsset->Finalize(); - // Cache off pointers to some key data structures from the material type... auto srgLayout = m_materialAsset->GetMaterialSrgLayout(); if (srgLayout) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 0325c3ac38..309daf8b62 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -33,12 +33,12 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(13) // added m_rawPropertyValues + ->Version(14) // added m_rawPropertyValues ->Field("materialTypeAsset", &MaterialAsset::m_materialTypeAsset) ->Field("materialTypeVersion", &MaterialAsset::m_materialTypeVersion) ->Field("propertyValues", &MaterialAsset::m_propertyValues) ->Field("rawPropertyValues", &MaterialAsset::m_rawPropertyValues) - ->Field("isFinalized", &MaterialAsset::m_isFinalized) + ->Field("finalized", &MaterialAsset::m_wasPreFinalized) ; } } @@ -104,19 +104,19 @@ namespace AZ return m_materialTypeAsset->GetMaterialPropertiesLayout(); } - bool MaterialAsset::IsFinalized() const + bool MaterialAsset::WasPreFinalized() const { - if (m_isFinalized) - { - AZ_Assert(GetMaterialPropertiesLayout() && m_propertyValues.size() == GetMaterialPropertiesLayout()->GetPropertyCount(), "MaterialAsset is marked as Finalized but does not have the right number of property values."); - } - - return m_isFinalized; + return m_wasPreFinalized; } void MaterialAsset::Finalize(AZStd::function reportWarning, AZStd::function reportError) { - if (IsFinalized()) + if (m_wasPreFinalized) + { + m_isFinalized = true; + } + + if (m_isFinalized) { return; } @@ -197,10 +197,18 @@ namespace AZ m_isFinalized = true; } - const AZStd::vector& MaterialAsset::GetPropertyValues() const + const AZStd::vector& MaterialAsset::GetPropertyValues() { - AZ_Error(s_debugTraceName, IsFinalized(), "MaterialAsset must be finalized before its property values can be accessed"); + // This can't be done in MaterialAssetHandler::LoadAssetData because the MaterialTypeAsset isn't necessarily loaded at that point. + // And it can't be done in PostLoadInit() because that happens on the next frame which might be too late. + // And overriding AssetHandler::InitAsset in MaterialAssetHandler didn't work, because there seems to be non-determinism on the order + // of InitAsset calls when a ModelAsset references a MaterialAsset, the model gets initialized first and then fails to use the material. + // So we finalize just-in-time when properties are accessed. + // If we could solve the problem with InitAsset, that would be the ideal place to call Finalize() and we could make GetPropertyValues() const again. + Finalize(); + AZ_Assert(GetMaterialPropertiesLayout() && m_propertyValues.size() == GetMaterialPropertiesLayout()->GetPropertyCount(), "MaterialAsset should be finalized but does not have the right number of property values."); + return m_propertyValues; } @@ -334,7 +342,6 @@ namespace AZ if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete) { asset.GetAs()->AssetInitBus::Handler::BusConnect(); - asset.GetAs()->m_wasPreFinalized = asset.GetAs()->m_isFinalized; return Data::AssetHandler::LoadResult::LoadComplete; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp index 7d4ecf0b18..872e4ad754 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAssetCreator.cpp @@ -49,6 +49,8 @@ namespace AZ [this](const char* message) { ReportWarning("%s", message); }, [this](const char* message) { ReportError("%s", message); }); + m_asset->m_wasPreFinalized = true; + // Finalize() doesn't clear the raw property data because that's the same function used at runtime, which does need to maintain the raw data // to support hot reload. But here we are pre-baking with the assumption that AP build dependencies will keep the material type // and material asset in sync, so we can discard the raw property data and just rely on the data in the material type asset. diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp index fdb131d449..61e1283f52 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialAssetTests.cpp @@ -111,6 +111,10 @@ namespace UnitTest EXPECT_EQ(assetId, materialAsset->GetId()); EXPECT_EQ(Data::AssetData::AssetStatus::Ready, materialAsset->GetStatus()); + + EXPECT_TRUE(materialAsset->WasPreFinalized()); + EXPECT_EQ(0, materialAsset->GetRawPropertyValues().size()); + validate(materialAsset); // Also test serialization... @@ -123,6 +127,57 @@ namespace UnitTest Data::Asset serializedAsset = tester.SerializeIn(Data::AssetId(Uuid::CreateRandom()), noAssets); validate(serializedAsset); } + + TEST_F(MaterialAssetTests, DeferredFinalize) + { + Data::AssetId assetId(Uuid::CreateRandom()); + + MaterialAssetCreator creator; + bool shouldFinalize = false; + creator.Begin(assetId, m_testMaterialTypeAsset, shouldFinalize); + + creator.SetPropertyValue(Name{ "MyFloat2" }, Vector2{ 0.1f, 0.2f }); + creator.SetPropertyValue(Name{ "MyFloat3" }, Vector3{ 1.1f, 1.2f, 1.3f }); + creator.SetPropertyValue(Name{ "MyFloat4" }, Vector4{ 2.1f, 2.2f, 2.3f, 2.4f }); + creator.SetPropertyValue(Name{ "MyColor" }, Color{ 1.0f, 1.0f, 1.0f, 1.0f }); + creator.SetPropertyValue(Name{ "MyInt" }, -2); + creator.SetPropertyValue(Name{ "MyUInt" }, 12u); + creator.SetPropertyValue(Name{ "MyFloat" }, 1.5f); + creator.SetPropertyValue(Name{ "MyBool" }, true); + creator.SetPropertyValue(Name{ "MyImage" }, m_testImageAsset); + creator.SetPropertyValue(Name{ "MyEnum" }, 1u); + + Data::Asset materialAsset; + EXPECT_TRUE(creator.End(materialAsset)); + + EXPECT_FALSE(materialAsset->WasPreFinalized()); + EXPECT_EQ(10, materialAsset->GetRawPropertyValues().size()); + + // Also test serialization... + + SerializeTester tester(GetSerializeContext()); + tester.SerializeOut(materialAsset.Get()); + + // Using a filter that skips loading assets because we are using a dummy image asset + ObjectStream::FilterDescriptor noAssets{ AZ::Data::AssetFilterNoAssetLoading }; + Data::Asset serializedAsset = tester.SerializeIn(Data::AssetId(Uuid::CreateRandom()), noAssets); + + EXPECT_FALSE(materialAsset->WasPreFinalized()); + EXPECT_EQ(10, materialAsset->GetRawPropertyValues().size()); + + // GetPropertyValues() will automatically finalize the material asset, so we can go ahead and check the property values. + EXPECT_EQ(materialAsset->GetPropertyValues().size(), 10); + EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue(), true); + EXPECT_EQ(materialAsset->GetPropertyValues()[1].GetValue(), -2); + EXPECT_EQ(materialAsset->GetPropertyValues()[2].GetValue(), 12); + EXPECT_EQ(materialAsset->GetPropertyValues()[3].GetValue(), 1.5f); + EXPECT_EQ(materialAsset->GetPropertyValues()[4].GetValue(), Vector2(0.1f, 0.2f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[5].GetValue(), Vector3(1.1f, 1.2f, 1.3f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[6].GetValue(), Vector4(2.1f, 2.2f, 2.3f, 2.4f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[7].GetValue(), Color(1.0f, 1.0f, 1.0f, 1.0f)); + EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue>(), m_testImageAsset); + EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue(), 1u); + } TEST_F(MaterialAssetTests, PropertyDefaultValuesComeFromParentMaterial) { @@ -267,15 +322,13 @@ namespace UnitTest warningFinder.AddExpectedErrorMessage("This material is based on version '1'"); warningFinder.AddExpectedErrorMessage("material type is now at version '2'"); - materialAsset->Finalize(); - - warningFinder.CheckExpectedErrorsFound(); - // Even though this material was created using the old version of the material type, it's property values should get automatically // updated to align with the new property layout in the latest MaterialTypeAsset. MaterialPropertyIndex myIntIndex = materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(Name{"MyIntRenamed"}); EXPECT_EQ(2, myIntIndex.GetIndex()); EXPECT_EQ(7, materialAsset->GetPropertyValues()[myIntIndex.GetIndex()].GetValue()); + + warningFinder.CheckExpectedErrorsFound(); // Since the MaterialAsset has already been updated, and the warning reported once, we should not see the "consider updating" // warning reported again on subsequent property accesses. diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp index 29f0e7d101..ef89e0138c 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialSourceDataTests.cpp @@ -182,7 +182,7 @@ namespace UnitTest Data::Asset materialAsset = materialAssetOutcome.GetValue(); - EXPECT_TRUE(materialAsset->IsFinalized()); + EXPECT_TRUE(materialAsset->WasPreFinalized()); EXPECT_EQ(0, materialAsset->GetRawPropertyValues().size()); // A pre-baked material has no need for the original raw property names and values // The order here is based on the order in the MaterialTypeSourceData, as added to the MaterialTypeAssetCreator. @@ -227,14 +227,10 @@ namespace UnitTest EXPECT_TRUE(materialAssetOutcome.IsSuccess()); Data::Asset materialAsset = materialAssetOutcome.GetValue(); - - ErrorMessageFinder expectNotFinalizedError("MaterialAsset must be finalized"); - EXPECT_FALSE(materialAsset->IsFinalized()); + EXPECT_FALSE(materialAsset->WasPreFinalized()); - expectNotFinalizedError.ResetCounts(); - EXPECT_TRUE(materialAsset->GetPropertyValues().empty()); - expectNotFinalizedError.CheckExpectedErrorsFound(); + // Note we avoid calling GetPropertyValues() because that will auto-finalize the material. We want to check its raw property values first. auto findRawPropertyValue = [materialAsset](const char* propertyId) { @@ -279,16 +275,10 @@ namespace UnitTest SerializeTester tester(GetSerializeContext()); tester.SerializeOut(materialAsset.Get()); materialAsset = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); - - // We check that everything is still in the original un-finalized state after going through the serialization process. - EXPECT_FALSE(materialAsset->IsFinalized()); - checkRawPropertyValues(); - expectNotFinalizedError.ResetCounts(); - EXPECT_TRUE(materialAsset->GetPropertyValues().empty()); - expectNotFinalizedError.CheckExpectedErrorsFound(); - materialAsset->Finalize(); - EXPECT_TRUE(materialAsset->IsFinalized()); + // We check that the asset is still in the original un-finalized state after going through the serialization process. + EXPECT_FALSE(materialAsset->WasPreFinalized()); + checkRawPropertyValues(); // Now all the property values should be available through the main GetPropertyValues() API. EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue(), true); @@ -301,8 +291,9 @@ namespace UnitTest EXPECT_EQ(materialAsset->GetPropertyValues()[7].GetValue(), Color(0.1f, 0.2f, 0.3f, 0.4f)); EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue>(), m_testImageAsset); EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue(), 1u); - + // The raw property values are still available (because they are needed if a hot-reload of the MaterialTypeAsset occurs) + EXPECT_FALSE(materialAsset->WasPreFinalized()); checkRawPropertyValues(); } @@ -659,19 +650,19 @@ namespace UnitTest auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel1.IsSuccess()); - EXPECT_TRUE(materialAssetLevel1.GetValue()->IsFinalized()); + EXPECT_TRUE(materialAssetLevel1.GetValue()->WasPreFinalized()); m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetValue().GetId()); auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel2.IsSuccess()); - EXPECT_TRUE(materialAssetLevel2.GetValue()->IsFinalized()); + EXPECT_TRUE(materialAssetLevel2.GetValue()->WasPreFinalized()); m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetValue().GetId()); auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true); EXPECT_TRUE(materialAssetLevel3.IsSuccess()); - EXPECT_TRUE(materialAssetLevel3.GetValue()->IsFinalized()); + EXPECT_TRUE(materialAssetLevel3.GetValue()->WasPreFinalized()); auto layout = m_testMaterialTypeAsset->GetMaterialPropertiesLayout(); MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat")); @@ -731,21 +722,21 @@ namespace UnitTest auto materialAssetLevel1Result = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); EXPECT_TRUE(materialAssetLevel1Result.IsSuccess()); Data::Asset materialAssetLevel1 = materialAssetLevel1Result.TakeValue(); - EXPECT_FALSE(materialAssetLevel1->IsFinalized()); + EXPECT_FALSE(materialAssetLevel1->WasPreFinalized()); m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetId()); auto materialAssetLevel2Result = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); EXPECT_TRUE(materialAssetLevel2Result.IsSuccess()); Data::Asset materialAssetLevel2 = materialAssetLevel2Result.TakeValue(); - EXPECT_FALSE(materialAssetLevel2->IsFinalized()); + EXPECT_FALSE(materialAssetLevel2->WasPreFinalized()); m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetId()); auto materialAssetLevel3Result = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true); EXPECT_TRUE(materialAssetLevel3Result.IsSuccess()); Data::Asset materialAssetLevel3 = materialAssetLevel3Result.TakeValue(); - EXPECT_FALSE(materialAssetLevel3->IsFinalized()); + EXPECT_FALSE(materialAssetLevel3->WasPreFinalized()); // Now we'll create the material type asset in memory so the materials will have what they need to finalize. Data::Asset testMaterialTypeAsset = CreateTestMaterialTypeAsset(materialTypeAssetId); @@ -766,9 +757,7 @@ namespace UnitTest tester.SerializeOut(materialAssetLevel3.Get()); materialAssetLevel3 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading}); - materialAssetLevel1->Finalize(); - materialAssetLevel2->Finalize(); - materialAssetLevel3->Finalize(); + // The properties will finalize automatically when we call GetPropertyValues()... AZStd::array_view properties; From fbfea49b68dbd0fb5c139087a6acbfe4a2f0c6be Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 18 Jan 2022 23:55:40 -0800 Subject: [PATCH 32/36] small comment tweak based on feedback Signed-off-by: Gene Walters --- .../Code/Source/NetworkEntity/NetworkSpawnableLibrary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h index 469086f4cb..ab6211f522 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h @@ -26,7 +26,7 @@ namespace Multiplayer //! INetworkSpawnableLibrary overrides. //! @{ // Iterates over all assets (on-disk and in-memory) and stores any spawnables that are "network.spawnables" - // This allows us to look up network spawnable assets by name or id for later use + // This allows users to look up network spawnable assets by name or id if needed later void BuildSpawnablesList() override; void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id) override; AZ::Name GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId) override; From 667a9df34231b2215cda2877b8f2ae0c70e2b243 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 19 Jan 2022 17:20:27 +0100 Subject: [PATCH 33/36] ImGui: Added new histogram group helper (#6998) * Added a helper class for a group containing several histograms. * The group is shown using collapsible header. Signed-off-by: Benjamin Jillich --- .../Include/LYImGuiUtils/HistogramGroup.h | 54 ++++++++++++ .../Source/LYImGuiUtils/HistogramGroup.cpp | 82 +++++++++++++++++++ .../Code/imgui_lyutils_static_files.cmake | 2 + 3 files changed, 138 insertions(+) create mode 100644 Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h create mode 100644 Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp diff --git a/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h new file mode 100644 index 0000000000..b3c7e0e7d8 --- /dev/null +++ b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h @@ -0,0 +1,54 @@ +/* + * 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 + * + */ + +#pragma once + +#ifdef IMGUI_ENABLED + +#include +#include +#include + +#include +#include + +namespace ImGui::LYImGuiUtils +{ + //! Helper for a group containing several histograms. + //! The group is shown using collapsible header. + class HistogramGroup + { + public: + HistogramGroup() = default; + HistogramGroup(const char* name, int histogramBinCount); + + void OnImGuiUpdate(); + void PushHistogramValue(const char* valueName, float value, const AZ::Color& color); + + const char* GetName() const { return m_name.c_str(); } + const AZStd::string& GetNameString() const { return m_name; } + void SetName(AZStd::string name) { m_name = name; } + + void SetHistogramBinCount(int count) { m_histogramBinCount = count; } + + //! Needs to be public for l-value access for ImGui::MenuItem() + bool m_show = true; + + private: + AZStd::string m_name; //< The name shown in the collapsible header. + int m_histogramBinCount = 100; //< The number of bins in the histogram. + + using HistogramIndexByNames = AZStd::unordered_map; + HistogramIndexByNames m_histogramIndexByName; //< Look-up table for the histogram index by name. + AZStd::vector m_histograms; //< Owns the histogram containers. + + static constexpr float s_histogramHeight = 85.0f; + }; +} // namespace ImGui::LYImGuiUtils + +#endif // IMGUI_ENABLED diff --git a/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp new file mode 100644 index 0000000000..62e8eb7b33 --- /dev/null +++ b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp @@ -0,0 +1,82 @@ +/* + * 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 + * + */ + +#ifdef IMGUI_ENABLED +#include "LYImGuiUtils/HistogramGroup.h" + +namespace ImGui::LYImGuiUtils +{ + HistogramGroup::HistogramGroup(const char* name, int histogramBinCount) + : m_name(name) + , m_histogramBinCount(histogramBinCount) + { + } + + void HistogramGroup::PushHistogramValue(const char* valueName, float value, const AZ::Color& color) + { + auto iterator = m_histogramIndexByName.find(valueName); + if (iterator != m_histogramIndexByName.end()) + { + ImGui::LYImGuiUtils::HistogramContainer& histogramContiner = m_histograms[iterator->second]; + histogramContiner.PushValue(value); + histogramContiner.SetBarLineColor(ImColor(color.GetR(), color.GetG(), color.GetB(), color.GetA())); + } + else + { + ImGui::LYImGuiUtils::HistogramContainer newHistogram; + newHistogram.Init(/*histogramName=*/valueName, + /*containerCount=*/m_histogramBinCount, + /*viewType=*/ImGui::LYImGuiUtils::HistogramContainer::ViewType::Histogram, + /*displayOverlays=*/true, + /*min=*/0.0f, + /*max=*/0.0f); + + newHistogram.SetMoveDirection(ImGui::LYImGuiUtils::HistogramContainer::PushRightMoveLeft); + newHistogram.PushValue(value); + + m_histogramIndexByName[valueName] = m_histograms.size(); + m_histograms.push_back(newHistogram); + } + } + + void HistogramGroup::OnImGuiUpdate() + { + if (!m_show) + { + return; + } + + if (ImGui::CollapsingHeader(m_name.c_str(), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed)) + { + for (auto& histogram : m_histograms) + { + ImGui::BeginGroup(); + { + histogram.Draw(ImGui::GetColumnWidth() - 70, s_histogramHeight); + + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0,0,0,255)); + { + const ImColor color = histogram.GetBarLineColor(); + ImGui::PushStyleColor(ImGuiCol_Button, color.Value); + { + const AZStd::string valueString = AZStd::string::format("%.2f", histogram.GetLastValue()); + ImGui::Button(valueString.c_str()); + } + ImGui::PopStyleColor(); + } + ImGui::PopStyleColor(); + } + ImGui::EndGroup(); + } + } + } +} // namespace ImGui::LYImGuiUtils + +#endif // IMGUI_ENABLED diff --git a/Gems/ImGui/Code/imgui_lyutils_static_files.cmake b/Gems/ImGui/Code/imgui_lyutils_static_files.cmake index d63730e6cb..9807cfe29d 100644 --- a/Gems/ImGui/Code/imgui_lyutils_static_files.cmake +++ b/Gems/ImGui/Code/imgui_lyutils_static_files.cmake @@ -8,7 +8,9 @@ set(FILES Include/LYImGuiUtils/HistogramContainer.h + Include/LYImGuiUtils/HistogramGroup.h Include/LYImGuiUtils/ImGuiDrawHelpers.h Source/LYImGuiUtils/HistogramContainer.cpp + Source/LYImGuiUtils/HistogramGroup.cpp Source/LYImGuiUtils/ImGuiDrawHelpers.cpp ) From 65a749494e01453f542ddbdfe143894608bc1be2 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez <82394219+AMZN-Igarri@users.noreply.github.com> Date: Wed, 19 Jan 2022 17:45:52 +0100 Subject: [PATCH 34/36] Fix: Entity Outliner: Outliner is unusable with the Editor in slice mode (#6983) * Fixed vertical offset Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed QPoint Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Fixed Entry delegate Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * SetRenderHint in Entry delegate Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Save and restore painter inside the highlighter Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Restoring Painter Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Removed comment Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- .../UI/Outliner/OutlinerListModel.cpp | 7 ++++--- .../AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp | 1 + .../AzToolsFramework/Editor/RichTextHighlighter.cpp | 8 +++----- .../AzToolsFramework/Editor/RichTextHighlighter.h | 3 ++- .../UI/Outliner/EntityOutlinerListModel.cpp | 2 ++ 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp index 1c361b050d..39be4839e6 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp @@ -2599,11 +2599,12 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optionV4.text.clear(); optionV4.widget->style()->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); - // Now we setup a Text Document so it can draw the rich text int verticalOffset = GetEntityNameVerticalOffset(entityId); - painter->translate(textRect.topLeft() + QPoint(0, verticalOffset)); - AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); + AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText( + entityNameRichText, painter, optionV4, textRect, QPoint(0, verticalOffset)); + + painter->restore(); OutlinerListModel::s_paintingName = false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index 8e69d5f788..5711ca2608 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -290,6 +290,7 @@ namespace AzToolsFramework { displayString = RichTextHighlighter::HighlightText(displayString, m_assetBrowserFilerModel->GetStringFilter()->GetFilterString()); } + RichTextHighlighter::PaintHighlightedRichText(displayString, painter, optionV4, remainingRect); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp index 8b28298c3d..f22fdd16b4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp @@ -29,12 +29,11 @@ namespace AzToolsFramework return highlightedString; } - void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect) + void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect, QPoint offset /* = QPoint()*/) { + // Now we setup a Text Document so it can draw the rich text painter->save(); painter->setRenderHint(QPainter::Antialiasing); - - // Now we setup a Text Document so it can draw the rich text QTextDocument textDoc; textDoc.setDefaultFont(option.font); if (option.state & QStyle::State_Enabled) @@ -46,10 +45,9 @@ namespace AzToolsFramework textDoc.setDefaultStyleSheet("body {color: #7C7C7C}"); } textDoc.setHtml("" + highlightedString + ""); - painter->translate(availableRect.topLeft()); + painter->translate(availableRect.topLeft() + offset); textDoc.setTextWidth(availableRect.width()); textDoc.drawContents(painter, QRectF(0, 0, availableRect.width(), availableRect.height())); - painter->restore(); } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h index b5c1859497..cdcb0b14b3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h @@ -30,7 +30,8 @@ namespace AzToolsFramework RichTextHighlighter() = delete; static QString HighlightText(const QString& displayString, const QString& matchingSubstring); - static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect); + static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, + QRect availableRect, QPoint offset = QPoint()); }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index e0060e2b42..93e4ffd3da 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -2368,6 +2368,8 @@ namespace AzToolsFramework AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); + painter->restore(); + EntityOutlinerListModel::s_paintingName = false; } From 9d3f8e0b7dfd81bfc091b072505e615f2f21e8ba Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 19 Jan 2022 09:09:32 -0800 Subject: [PATCH 35/36] [development] minor Android toolchain updates (#6931) Fixed issue with Android NDK r23 native only builds where the platform version was ignored Bumped the default ANDROID_NATIVE_API_LEVEL to 24 so it matches the Android project generator scripts Removed some unnecessary information from message strings Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- cmake/Platform/Android/Toolchain_android.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/Platform/Android/Toolchain_android.cmake b/cmake/Platform/Android/Toolchain_android.cmake index 75ff4554fd..974eb33681 100644 --- a/cmake/Platform/Android/Toolchain_android.cmake +++ b/cmake/Platform/Android/Toolchain_android.cmake @@ -37,9 +37,9 @@ if(NOT ANDROID_ABI MATCHES "^arm64-") message(FATAL_ERROR "Only the 64-bit ANDROID_ABI's are supported. arm64-v8a can be used if not set") endif() if(NOT ANDROID_NATIVE_API_LEVEL) - set(ANDROID_NATIVE_API_LEVEL 21) + set(ANDROID_NATIVE_API_LEVEL 24) endif() - +set(ANDROID_PLATFORM android-${ANDROID_NATIVE_API_LEVEL}) # Make a backup of the CMAKE_FIND_ROOT_PATH since it will be altered by the NDK toolchain file and needs to be restored after the input set(BACKUP_CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH}) @@ -64,9 +64,9 @@ set(LY_TOOLCHAIN_NDK_API_LEVEL ${ANDROID_PLATFORM_LEVEL}) set(MIN_NDK_VERSION 21) if(${LY_TOOLCHAIN_NDK_PKG_MAJOR} VERSION_LESS ${MIN_NDK_VERSION}) - message(FATAL_ERROR "Unsupported NDK Version ${LY_TOOLCHAIN_NDK_PKG_MAJOR}.${LY_TOOLCHAIN_NDK_PKG_MINOR}.${LY_TOOLCHAIN_NDK_API_LEVEL}. Must be version ${MIN_NDK_VERSION} or above") + message(FATAL_ERROR "Unsupported NDK Version ${LY_TOOLCHAIN_NDK_PKG_MAJOR}.${LY_TOOLCHAIN_NDK_PKG_MINOR}. Must be version ${MIN_NDK_VERSION} or above") else() - message(STATUS "Detected NDK Version ${LY_TOOLCHAIN_NDK_PKG_MAJOR}.${LY_TOOLCHAIN_NDK_PKG_MINOR}.${LY_TOOLCHAIN_NDK_PKG_MINOR}") + message(STATUS "Detected NDK Version ${LY_TOOLCHAIN_NDK_PKG_MAJOR}.${LY_TOOLCHAIN_NDK_PKG_MINOR}") endif() list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES LY_NDK_DIR) From a63ea12a1f6a47ba6ea27ce2ad847526023b1180 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 19 Jan 2022 09:52:27 -0800 Subject: [PATCH 36/36] System shortcuts crash the Editor when Global Preferences are open (#6994) * Changes to the keyPressEvent override of the Editor Preferences Dialog to prevent infinite loops on focus switches. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Renaming function to clarify its purpose. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Editor/EditorPreferencesDialog.cpp | 22 ++++++++++++---------- Code/Editor/EditorPreferencesDialog.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Code/Editor/EditorPreferencesDialog.cpp b/Code/Editor/EditorPreferencesDialog.cpp index 665daf52a8..42f7446716 100644 --- a/Code/Editor/EditorPreferencesDialog.cpp +++ b/Code/Editor/EditorPreferencesDialog.cpp @@ -112,29 +112,31 @@ void EditorPreferencesDialog::showEvent(QShowEvent* event) QDialog::showEvent(event); } -void WidgetHandleKeyPressEvent(QWidget* widget, QKeyEvent* event) +bool WidgetConsumesKeyPressEvent(QKeyEvent* event) { // If the enter key is pressed during any text input, the dialog box will close // making it inconvenient to do multiple edits. This routine captures the // Key_Enter or Key_Return and clears the focus to give a visible cue that - // editing of that field has finished and then doesn't propogate it. + // editing of that field has finished and then doesn't propagate it. if (event->key() != Qt::Key::Key_Enter && event->key() != Qt::Key::Key_Return) { - QApplication::sendEvent(widget, event); + return false; } - else + + if (QWidget* editWidget = QApplication::focusWidget()) { - if (QWidget* editWidget = QApplication::focusWidget()) - { - editWidget->clearFocus(); - } + editWidget->clearFocus(); } -} + return true; +} void EditorPreferencesDialog::keyPressEvent(QKeyEvent* event) { - WidgetHandleKeyPressEvent(this, event); + if (!WidgetConsumesKeyPressEvent(event)) + { + QDialog::keyPressEvent(event); + } } void EditorPreferencesDialog::OnTreeCurrentItemChanged() diff --git a/Code/Editor/EditorPreferencesDialog.h b/Code/Editor/EditorPreferencesDialog.h index a3f05ad00d..70a186375b 100644 --- a/Code/Editor/EditorPreferencesDialog.h +++ b/Code/Editor/EditorPreferencesDialog.h @@ -19,7 +19,7 @@ namespace Ui class EditorPreferencesTreeWidgetItem; -void WidgetHandleKeyPressEvent(QWidget* widget, QKeyEvent* event); +bool WidgetConsumesKeyPressEvent(QKeyEvent* event); class EditorPreferencesDialog : public QDialog