From a5a42e3268dd3888327630615cf4c8f3cf82e3d8 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Tue, 30 Nov 2021 14:05:31 -0800 Subject: [PATCH 01/12] Add dialog window for messaging when SC assets fail to save Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Windows/MainWindow.cpp | 60 ++++++++++++++++++- .../Code/Editor/View/Windows/MainWindow.h | 10 +++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index e61b015aae..778ad9d5b7 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -914,6 +914,12 @@ namespace ScriptCanvasEditor void MainWindow::closeEvent(QCloseEvent* event) { + if (m_forceCloseInProgress) + { + event->accept(); + return; + } + // If we are in the middle of saving a graph. We don't want to close ourselves down and potentially retrigger the saving logic. if (m_queueCloseRequest) { @@ -1981,6 +1987,7 @@ namespace ScriptCanvasEditor EnableAssetView(memoryAsset); + ClearSaveAttempt(); UnblockCloseRequests(); } @@ -1992,6 +1999,7 @@ namespace ScriptCanvasEditor void MainWindow::SaveAsset(AZ::Data::AssetId assetId, const Callbacks::OnSave& onSave) { + MarkSaveAttempt(); PrepareAssetForSave(assetId); auto onSaveCallback = [this, onSave](bool saveSuccess, AZ::Data::AssetPtr asset, AZ::Data::AssetId previousAssetId) @@ -2020,6 +2028,7 @@ namespace ScriptCanvasEditor void MainWindow::SaveNewAsset(AZStd::string_view path, AZ::Data::AssetId inMemoryAssetId, const Callbacks::OnSave& onSave) { + MarkSaveAttempt(); PrepareAssetForSave(inMemoryAssetId); auto onSaveCallback = [this, onSave](bool saveSuccess, AZ::Data::AssetPtr asset, AZ::Data::AssetId previousAssetId) @@ -4213,6 +4222,11 @@ namespace ScriptCanvasEditor void MainWindow::OnSystemTick() { + if (m_saveAttemptInProgress) + { + EvaluateSaveAttempt(); + } + if (HasSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid)) { RemoveSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid); @@ -4246,13 +4260,56 @@ namespace ScriptCanvasEditor RemoveSystemTickAction(SystemTickActionFlag::CloseNextTabAction); CloseNextTab(); } + } - if (m_systemTickActions == 0) + void MainWindow::ClearSaveAttempt() + { + m_saveAttemptInProgress = false; + + if (!m_systemTickActions) { AZ::SystemTickBus::Handler::BusDisconnect(); } } + bool MainWindow::EvaluateSaveAttempt() + { + const AZ::s64 k_saveAttemptSeconds = 20; + + if (m_saveAttemptInProgress) + { + auto saveDuration = AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_saveAttemptTime).count(); + + if (saveDuration > k_saveAttemptSeconds) + { + WarnOnFailedSaveAttempt(); + } + } + + return m_forceCloseInProgress; + } + + void MainWindow::MarkSaveAttempt() + { + m_saveAttemptInProgress = true; + m_saveAttemptTime = AZStd::chrono::system_clock::now(); + + if (!AZ::SystemTickBus::Handler::BusIsConnected()) + { + AZ::SystemTickBus::Handler::BusConnect(); + } + } + + void MainWindow::WarnOnFailedSaveAttempt() + { + m_forceCloseInProgress = true; + QMessageBox::critical(this, QString(), QObject::tr + ("The ScriptCanvas Editor has encountered an external bug which prevents it from tracking the file state.

" + "Likely the Asset Processor has crashed. ScriptCanvas files may have saved successfully, but the O3DE Engine and Asset Processor should be restarted before continuing work.")); + AZ::SystemTickBus::Handler::BusDisconnect(); + qobject_cast(parent())->close(); + } + void MainWindow::OnCommandStarted(AZ::Crc32) { PushPreventUndoStateUpdate(); @@ -4486,7 +4543,6 @@ namespace ScriptCanvasEditor { AZ::SystemTickBus::Handler::BusConnect(); } - m_systemTickActions |= action; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index 7672f0a199..d73da41219 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -51,7 +51,7 @@ #include #include - +//#include #include #if SCRIPTCANVAS_EDITOR @@ -798,5 +798,13 @@ namespace ScriptCanvasEditor Workspace* m_workspace; void OnSaveCallback(bool saveSuccess, AZ::Data::AssetPtr, AZ::Data::AssetId previousFileAssetId); + + bool m_saveAttemptInProgress = false; + bool m_forceCloseInProgress = false; + AZStd::chrono::system_clock::time_point m_saveAttemptTime; + void ClearSaveAttempt(); + bool EvaluateSaveAttempt(); + void MarkSaveAttempt(); + void WarnOnFailedSaveAttempt(); }; } From 850d36130efb5571a63c14255554927333af971b Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:02:06 -0800 Subject: [PATCH 02/12] update error window message and add AP launch request Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Code/Editor/View/Windows/MainWindow.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 778ad9d5b7..ee36fc4212 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -154,6 +154,7 @@ #include #include +#include namespace ScriptCanvasEditor { @@ -4305,9 +4306,14 @@ namespace ScriptCanvasEditor m_forceCloseInProgress = true; QMessageBox::critical(this, QString(), QObject::tr ("The ScriptCanvas Editor has encountered an external bug which prevents it from tracking the file state.

" - "Likely the Asset Processor has crashed. ScriptCanvas files may have saved successfully, but the O3DE Engine and Asset Processor should be restarted before continuing work.")); + "The ScriptCanvas files in the process of being saved may have saved successfully.

Closing this window will close " + "the ScriptCanvas Editor, and request a launch of the Asset Processor.
" + "Verify that the Asset Processor or is running before launching the ScriptCanvas Editor again.
" + "The status of the Asset Processor can be monitored from the O3DE Editor in the bottom-right corner of the status bar.")); + + AzFramework::AssetSystem::LaunchAssetProcessor(); AZ::SystemTickBus::Handler::BusDisconnect(); - qobject_cast(parent())->close(); + AzToolsFramework::CloseViewPane(LyViewPane::ScriptCanvas); } void MainWindow::OnCommandStarted(AZ::Crc32) From 9e725da597c5a1681d1da73f7d10d2455bed8c7c Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:30:42 -0800 Subject: [PATCH 03/12] removed commented out include Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index d73da41219..8d84ece968 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -51,7 +51,6 @@ #include #include -//#include #include #if SCRIPTCANVAS_EDITOR From a359244c51f85d6d8894b3874cd15c08838388bd Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Tue, 30 Nov 2021 17:18:27 -0800 Subject: [PATCH 04/12] add pane close to system tick bus Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index ee36fc4212..4a20c6bc0d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -4275,13 +4275,13 @@ namespace ScriptCanvasEditor bool MainWindow::EvaluateSaveAttempt() { - const AZ::s64 k_saveAttemptSeconds = 20; + const AZ::s64 SaveAttemptSeconds = 20; if (m_saveAttemptInProgress) { auto saveDuration = AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_saveAttemptTime).count(); - if (saveDuration > k_saveAttemptSeconds) + if (saveDuration > SaveAttemptSeconds) { WarnOnFailedSaveAttempt(); } @@ -4313,7 +4313,10 @@ namespace ScriptCanvasEditor AzFramework::AssetSystem::LaunchAssetProcessor(); AZ::SystemTickBus::Handler::BusDisconnect(); - AzToolsFramework::CloseViewPane(LyViewPane::ScriptCanvas); + AZ::SystemTickBus::QueueFunction([]() + { + AzToolsFramework::CloseViewPane(LyViewPane::ScriptCanvas); + }); } void MainWindow::OnCommandStarted(AZ::Crc32) From b70545ad94e35203170985dc8e2d864ecfb993e6 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Thu, 2 Dec 2021 16:07:50 -0800 Subject: [PATCH 05/12] ScriptCanvas --> Script Canvas in comments Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 4a20c6bc0d..999afd7a9d 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -4305,10 +4305,10 @@ namespace ScriptCanvasEditor { m_forceCloseInProgress = true; QMessageBox::critical(this, QString(), QObject::tr - ("The ScriptCanvas Editor has encountered an external bug which prevents it from tracking the file state.

" - "The ScriptCanvas files in the process of being saved may have saved successfully.

Closing this window will close " - "the ScriptCanvas Editor, and request a launch of the Asset Processor.
" - "Verify that the Asset Processor or is running before launching the ScriptCanvas Editor again.
" + ("The Script Canvas Editor has encountered an external bug which prevents it from tracking the file state.

" + "The Script Canvas files in the process of being saved may have saved successfully.

Closing this window will close " + "the Script Canvas Editor, and request a launch of the Asset Processor.
" + "Verify that the Asset Processor is running before launching the Script Canvas Editor again.
" "The status of the Asset Processor can be monitored from the O3DE Editor in the bottom-right corner of the status bar.")); AzFramework::AssetSystem::LaunchAssetProcessor(); From 08cf53a3f663476307fb59f9d0d1c91353672017 Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Tue, 7 Dec 2021 16:37:53 -0800 Subject: [PATCH 06/12] Fix warnings, add branch notifier Signed-off-by: mrieggeramzn --- .../Assets/ShaderLib/Atom/Features/LightCulling/NVLC.azsli | 4 ++-- .../Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/NVLC.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/NVLC.azsli index f6dfc0aab4..7878d946b8 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/NVLC.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/LightCulling/NVLC.azsli @@ -74,7 +74,7 @@ struct TileLightData bool Light_IsInsideBin(uint package, uint bin) { - return (package & (1 << bin)) != 0; + return (package & (1u << bin)) != 0; } uint PackLightIndexWithBinMask(uint ind, uint bins) @@ -130,7 +130,7 @@ uint NVLC_GetBin(const float viewZ, const TileLightData data) const float zFarCoordSystemAdjusted = data.zFar * RH_COORD_SYSTEM_REVERSE; float f = saturate( (abs(viewZCoordSystemAdjusted) - zNearCoordSystemAdjusted) / (zFarCoordSystemAdjusted - zNearCoordSystemAdjusted) ); - float bin = min(f, 0.999999) * float(1 << data.logMaxBins); + float bin = min(f, 0.999999) * float(1u << data.logMaxBins); return uint(bin); } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli index aecb89eb92..1863c749b0 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Decals.azsli @@ -54,6 +54,8 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface) localPos = mul(decalRot, localPos); float3 decalUVW = localPos * rcp(decal.m_halfSize); + + [branch] if(decalUVW.x >= -1.0f && decalUVW.x <= 1.0f && decalUVW.y >= -1.0f && decalUVW.y <= 1.0f && decalUVW.z >= -1.0f && decalUVW.z <= 1.0f) @@ -72,6 +74,7 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface) float2 normalMap = 0; // Each texture array handles a size permutation. // e.g. it could be that tex array 0 handles 256x256 and tex array 1 handles 512x64, etc. + [branch] switch(textureArrayIndex) { case 0: From 766de68199203ad3095a711a6e1f6b180ac0aca4 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Wed, 8 Dec 2021 22:54:21 -0800 Subject: [PATCH 07/12] small fixes for SC play in editor and warnings Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Components/EditorScriptCanvasComponent.cpp | 10 ---------- .../Components/EditorScriptCanvasComponent.h | 4 +--- Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp | 13 ++++++++++++- Gems/ScriptCanvas/Code/Editor/SystemComponent.h | 10 +++++++++- .../Code/Include/ScriptCanvas/Core/Graph.cpp | 15 ++++++++++++++- 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 043e034062..a0e0868422 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -475,16 +475,6 @@ namespace ScriptCanvasEditor AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent); } - void EditorScriptCanvasComponent::OnStartPlayInEditor() - { - ScriptCanvas::Execution::PerformanceStatisticsEBus::Broadcast(&ScriptCanvas::Execution::PerformanceStatisticsBus::ClearSnaphotStatistics); - } - - void EditorScriptCanvasComponent::OnStopPlayInEditor() - { - AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect); - } - void EditorScriptCanvasComponent::SetAssetId(const AZ::Data::AssetId& assetId) { if (m_scriptCanvasAssetHolder.GetAssetId() != assetId) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h index 5dbe718eca..8fd4ce4f14 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponent.h @@ -96,9 +96,7 @@ namespace ScriptCanvasEditor //===================================================================== // EditorEntityContextNotificationBus - void OnStartPlayInEditor() override; - - void OnStopPlayInEditor() override; + protected: static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp index f901915fdb..d976e2c0b9 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -328,10 +329,20 @@ namespace ScriptCanvasEditor } }; - openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(), scriptCanvasEditorCallback }); + openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(ScriptCanvasAssetDescription().GetIconPathImpl()), scriptCanvasEditorCallback }); } } + void SystemComponent::OnStartPlayInEditor() + { + ScriptCanvas::Execution::PerformanceStatisticsEBus::Broadcast(&ScriptCanvas::Execution::PerformanceStatisticsBus::ClearSnaphotStatistics); + } + + void SystemComponent::OnStopPlayInEditor() + { + AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect); + } + void SystemComponent::OnUserSettingsActivated() { PopulateEditorCreatableTypes(); diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h index 6f85b3c5a6..c2c42c5b9d 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace ScriptCanvasEditor { @@ -36,6 +37,8 @@ namespace ScriptCanvasEditor , private AZ::Data::AssetBus::MultiHandler , private AzToolsFramework::AssetSeedManagerRequests::Bus::Handler , private AzToolsFramework::EditorContextMenuBus::Handler + , private AzToolsFramework::EditorEntityContextNotificationBus::Handler + { public: AZ_COMPONENT(SystemComponent, "{1DE7A120-4371-4009-82B5-8140CB1D7B31}"); @@ -97,7 +100,12 @@ namespace ScriptCanvasEditor //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - + + protected: + void OnStartPlayInEditor() override; + + void OnStopPlayInEditor() override; + private: SystemComponent(const SystemComponent&) = delete; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp index 9d848ff998..2b567aab0d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp @@ -52,6 +52,7 @@ namespace GraphCpp VariablePanelSymantics, AddVersionData, RemoveFunctionGraphMarker, + FixupVersionDataTypeId, // label your version above Current }; @@ -71,11 +72,23 @@ namespace ScriptCanvas componentElementNode.AddElementWithData(context, "m_assetType", azrtti_typeid()); } - if (componentElementNode.GetVersion() < GraphCpp::GraphVersion::RemoveFunctionGraphMarker) + if (componentElementNode.GetVersion() <= GraphCpp::GraphVersion::RemoveFunctionGraphMarker) { componentElementNode.RemoveElementByName(AZ_CRC_CE("isFunctionGraph")); } + if (componentElementNode.GetVersion() < GraphCpp::GraphVersion::FixupVersionDataTypeId) + { + if (auto subElement = componentElementNode.FindSubElement(AZ_CRC_CE("versionData"))) + { + if (subElement->GetId() == azrtti_typeid()) + { + componentElementNode.RemoveElementByName(AZ_CRC_CE("versionData")); + componentElementNode.AddElementWithData(context, "versionData", VersionData()); + } + } + } + return true; } From 70875651491842cf80d46371d1d1dcae5776dd23 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:23:03 -0800 Subject: [PATCH 08/12] fix interpreted statics Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Execution/Interpreted/ExecutionInterpretedAPI.cpp | 9 +++++---- .../Execution/Interpreted/ExecutionStateInterpreted.cpp | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp index 1855b348f2..561708dea1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp @@ -503,20 +503,21 @@ namespace ScriptCanvas void InitializeInterpretedStatics(RuntimeData& runtimeData) { - if (!runtimeData.m_areStaticsInitialized) + AZ_Error("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized"); { runtimeData.m_areStaticsInitialized = true; for (auto& dependency : runtimeData.m_requiredAssets) { - InitializeInterpretedStatics(dependency.Get()->GetData()); + if (!dependency.Get()->GetData().m_areStaticsInitialized) + { + InitializeInterpretedStatics(dependency.Get()->GetData()); + } } #if defined(AZ_PROFILE_BUILD) || defined(AZ_DEBUG_BUILD) Execution::InitializeFromLuaStackFunctions(const_cast(runtimeData.m_debugMap)); #endif - AZ_WarningOnce("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized"); - if (runtimeData.RequiresStaticInitialization()) { AZ::ScriptLoadResult result{}; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp index 3ae52846cd..3b963317ec 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp @@ -49,7 +49,10 @@ namespace ScriptCanvas , config.asset.GetId().ToString().data()); #endif - Execution::InitializeInterpretedStatics(runtimeAsset->GetData()); + if (!runtimeAsset->GetData().m_areStaticsInitialized) + { + Execution::InitializeInterpretedStatics(runtimeAsset->GetData()); + } } void ExecutionStateInterpreted::ClearLuaRegistryIndex() From 0bccecaa15ea756b840985ba562a1302e419b322 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 9 Dec 2021 11:36:39 -0600 Subject: [PATCH 09/12] Fixed logic for when to cull entities from having their viewport manipulators regenerated. Signed-off-by: Chris Galvan --- .../EditorTransformComponentSelection.cpp | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 336198c183..f430d3a61e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -2504,6 +2504,29 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); + // Do not create manipulators for the container entity of the focused prefab. + if (auto prefabFocusPublicInterface = AZ::Interface::Get()) + { + AzFramework::EntityContextId editorEntityContextId = GetEntityContextId(); + if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); + focusRoot.IsValid()) + { + m_selectedEntityIds.erase(focusRoot); + } + } + + // Do not create manipulators for any entities marked as read only + if (auto readOnlyEntityPublicInterface = AZ::Interface::Get()) + { + AZStd::erase_if( + m_selectedEntityIds, + [readOnlyEntityPublicInterface](auto entityId) + { + return readOnlyEntityPublicInterface->IsReadOnly(entityId); + } + ); + } + // note: create/destroy pattern to be addressed DestroyManipulators(m_entityIdManipulators); CreateEntityIdManipulators(); @@ -3635,29 +3658,6 @@ namespace AzToolsFramework m_selectedEntityIds.clear(); m_selectedEntityIds.reserve(selectedEntityIds.size()); AZStd::copy(selectedEntityIds.begin(), selectedEntityIds.end(), AZStd::inserter(m_selectedEntityIds, m_selectedEntityIds.end())); - - // Do not create manipulators for the container entity of the focused prefab. - if (auto prefabFocusPublicInterface = AZ::Interface::Get()) - { - AzFramework::EntityContextId editorEntityContextId = GetEntityContextId(); - if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); - focusRoot.IsValid()) - { - m_selectedEntityIds.erase(focusRoot); - } - } - - // Do not create manipulators for any entities marked as read only - if (auto readOnlyEntityPublicInterface = AZ::Interface::Get()) - { - AZStd::erase_if( - m_selectedEntityIds, - [readOnlyEntityPublicInterface](auto entityId) - { - return readOnlyEntityPublicInterface->IsReadOnly(entityId); - } - ); - } } void EditorTransformComponentSelection::OnTransformChanged( From e636ea39e3123fa576b45e21c6750aeb2cf1e17e Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 9 Dec 2021 13:15:20 -0600 Subject: [PATCH 10/12] Fixed comment casing to match rest of file. Signed-off-by: Chris Galvan --- .../ViewportSelection/EditorTransformComponentSelection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index f430d3a61e..bd9292db32 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -2504,7 +2504,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - // Do not create manipulators for the container entity of the focused prefab. + // do not create manipulators for the container entity of the focused prefab. if (auto prefabFocusPublicInterface = AZ::Interface::Get()) { AzFramework::EntityContextId editorEntityContextId = GetEntityContextId(); @@ -2515,7 +2515,7 @@ namespace AzToolsFramework } } - // Do not create manipulators for any entities marked as read only + // do not create manipulators for any entities marked as read only if (auto readOnlyEntityPublicInterface = AZ::Interface::Get()) { AZStd::erase_if( From c63b4eb905eb396c530cddbfcfcc194b19a5b0ba Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:53:25 -0600 Subject: [PATCH 11/12] Removing unused variable and fix typo (#6265) Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- .../AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp | 2 +- .../AzToolsFramework/Tests/Prefab/PrefabAssetFixupTests.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index 83e8d2e4be..50c61e6877 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -150,7 +150,7 @@ namespace AzToolsFramework return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success; } - // some assets may come in from the JSON serialzier with no AssetID, but have an asset hint + // some assets may come in from the JSON serializer with no AssetID, but have an asset hint // this attempts to fix up the assets using the assetHint field void FixUpInvalidAssets(AZ::Data::Asset& asset) { diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabAssetFixupTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabAssetFixupTests.cpp index 379392553e..4f2a19faec 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabAssetFixupTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabAssetFixupTests.cpp @@ -176,7 +176,6 @@ namespace UnitTest TEST_F(PrefabFixupTest, Test_LoadInstanceFromPrefabDom_Overload3) { Instance instance; - AZStd::vector> referencedAssets; Instance::EntityList entityList; (PrefabDomUtils::LoadInstanceFromPrefabDom(instance, entityList, m_prefabDom)); From 5e5bb272192043c18612942d660c1c98c18af583 Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:53:35 -0600 Subject: [PATCH 12/12] Procedural Prefabs: Python documentation cleanup (#6136) * Auto LOD script setup Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Working auto LODs Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Correctly selected LODs and added default prefab Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Cleanup code Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Cleanup code Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add missing legal header, move name cleanup to scene_helpers, add documentation Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add PhysX mesh group support. Updated example script to show usage Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add a physics collider component Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Update DefaultOrValue call Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Document remaining methods in scene_data.py Add enums where appropriate Add type hints and default values Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Remove unused import Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Convert docstring to numpy style Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix return types Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Remove empty returns Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add docs on enums Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- .../Editor/Scripts/scene_helpers.py | 38 +- .../Editor/Scripts/scene_mesh_to_prefab.py | 8 +- .../Editor/Scripts/scene_api/scene_data.py | 628 ++++++++++++------ 3 files changed, 474 insertions(+), 200 deletions(-) diff --git a/AutomatedTesting/Editor/Scripts/scene_helpers.py b/AutomatedTesting/Editor/Scripts/scene_helpers.py index 761068e796..cae4488abc 100644 --- a/AutomatedTesting/Editor/Scripts/scene_helpers.py +++ b/AutomatedTesting/Editor/Scripts/scene_helpers.py @@ -14,30 +14,44 @@ from scene_api.scene_data import SceneGraphName def log_exception_traceback(): - """ - Outputs an exception stacktrace. - """ + """Outputs an exception stacktrace.""" data = traceback.format_exc() logger = logging.getLogger('python') logger.error(data) -def sanitize_name_for_disk(name: str): - """ - Removes illegal filename characters from a string. +def sanitize_name_for_disk(name: str) -> str: + """Removes illegal filename characters from a string. + + Parameters + ---------- + name : + String to clean. + + + Returns + ------- + str + Name with illegal characters removed. - :param name: String to clean. - :return: Name with illegal characters removed. """ return "".join(char for char in name if char not in "|<>:\"/?*\\") def get_mesh_node_names(scene_graph: sceneData.SceneGraph) -> Tuple[List[SceneGraphName], List[str]]: - """ - Returns a tuple of all the mesh nodes as well as all the node paths + """Returns a tuple of all the mesh nodes as well as all the node paths + + Parameters + ---------- + scene_graph : + Scene graph to search + + + Returns + ------- + Tuple[List[SceneGraphName], List[str]] + Tuple of [Mesh Nodes, All Node Paths] - :param scene_graph: Scene graph to search - :return: Tuple of [Mesh Nodes, All Node Paths] """ import azlmbr.scene as sceneApi import azlmbr.scene.graph diff --git a/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py b/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py index db8df09091..f9c1e08558 100644 --- a/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py +++ b/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py @@ -8,7 +8,7 @@ import azlmbr.bus import azlmbr.math -from scene_api.scene_data import PrimitiveShape, DecompositionMode +from scene_api.scene_data import PrimitiveShape, DecompositionMode, ColorChannel, TangentSpaceSource, TangentSpaceMethod from scene_helpers import * @@ -71,6 +71,7 @@ def add_physx_meshes(scene_manifest: sceneData.SceneManifest, source_file_name: triangle = scene_manifest.add_physx_triangle_mesh_group(source_file_name + "_triangle", False, True, True, True, True, True) scene_manifest.physx_mesh_group_add_selected_unselected_nodes(triangle, [first_mesh], all_except_first_mesh) + def update_manifest(scene): import uuid, os import azlmbr.scene.graph @@ -114,10 +115,11 @@ def update_manifest(scene): if node != mesh_path: scene_manifest.mesh_group_unselect_node(mesh_group, node) - scene_manifest.mesh_group_add_cloth_rule(mesh_group, mesh_path, "Col0", 1, "Col0", 2, "Col0", 2, 3) + scene_manifest.mesh_group_add_cloth_rule(mesh_group, mesh_path, "Col0", ColorChannel.GREEN, "Col0", + ColorChannel.BLUE, "Col0", ColorChannel.BLUE, ColorChannel.ALPHA) scene_manifest.mesh_group_add_advanced_mesh_rule(mesh_group, True, False, True, "Col0") scene_manifest.mesh_group_add_skin_rule(mesh_group, 3, 0.002) - scene_manifest.mesh_group_add_tangent_rule(mesh_group, 1, 0) + scene_manifest.mesh_group_add_tangent_rule(mesh_group, TangentSpaceSource.MIKKT_GENERATION, TangentSpaceMethod.TSPACE_BASIC) # Create an editor entity entity_id = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "CreateEditorReadyEntity", mesh_group_name) diff --git a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py index 173558d784..66b836f171 100755 --- a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py +++ b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py @@ -7,13 +7,13 @@ SPDX-License-Identifier: Apache-2.0 OR MIT import typing import json import azlmbr.scene as sceneApi -from enum import Enum, IntEnum +from enum import IntEnum # Wraps the AZ.SceneAPI.Containers.SceneGraph.NodeIndex internal class class SceneGraphNodeIndex: - def __init__(self, sceneGraphNodeIndex) -> None: - self.nodeIndex = sceneGraphNodeIndex + def __init__(self, scene_graph_node_index) -> None: + self.nodeIndex = scene_graph_node_index def as_number(self): return self.nodeIndex.AsNumber() @@ -29,9 +29,9 @@ class SceneGraphNodeIndex: # Wraps AZ.SceneAPI.Containers.SceneGraph.Name internal class -class SceneGraphName(): - def __init__(self, sceneGraphName) -> None: - self.name = sceneGraphName +class SceneGraphName: + def __init__(self, scene_graph_name) -> None: + self.name = scene_graph_name def get_path(self) -> str: return self.name.GetPath() @@ -41,9 +41,9 @@ class SceneGraphName(): # Wraps AZ.SceneAPI.Containers.SceneGraph class -class SceneGraph(): - def __init__(self, sceneGraphInstance) -> None: - self.sceneGraph = sceneGraphInstance +class SceneGraph: + def __init__(self, scene_graph_instance) -> None: + self.sceneGraph = scene_graph_instance @classmethod def is_valid_name(cls, name): @@ -96,53 +96,161 @@ class SceneGraph(): return self.sceneGraph.GetNodeContent(node) +class ColorChannel(IntEnum): + RED = 0 + """ Red color channel """ + GREEN = 1 + """ Green color channel """ + BLUE = 2 + """ Blue color channel """ + ALPHA = 3 + """ Alpha color channel """ + + +class TangentSpaceSource(IntEnum): + SCENE = 0 + """ Extract the tangents and bitangents directly from the source scene file. """ + MIKKT_GENERATION = 1 + """ Use MikkT algorithm to generate tangents """ + + +class TangentSpaceMethod(IntEnum): + TSPACE = 0 + """ Generates the tangents and bitangents with their true magnitudes which can be used for relief mapping effects. + It calculates the 'real' bitangent which may not be perpendicular to the tangent. + However, both, the tangent and bitangent are perpendicular to the vertex normal. + """ + TSPACE_BASIC = 1 + """ Calculates unit vector tangents and bitangents at pixel/vertex level which are sufficient for basic normal mapping. """ + + class PrimitiveShape(IntEnum): BEST_FIT = 0 + """ The algorithm will determine which of the shapes fits best. """ SPHERE = 1 + """ Sphere shape """ BOX = 2 + """ Box shape """ CAPSULE = 3 + """ Capsule shape """ class DecompositionMode(IntEnum): VOXEL = 0 + """ Voxel-based approximate convex decomposition """ TETRAHEDRON = 1 + """ Tetrahedron-based approximate convex decomposition """ # Contains a dictionary to contain and export AZ.SceneAPI.Containers.SceneManifest -class SceneManifest(): +class SceneManifest: def __init__(self): self.manifest = {'values': []} def add_mesh_group(self, name: str) -> dict: - meshGroup = {} - meshGroup['$type'] = '{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup' - meshGroup['name'] = name - meshGroup['nodeSelectionList'] = {'selectedNodes': [], 'unselectedNodes': []} - meshGroup['rules'] = {'rules': [{'$type': 'MaterialRule'}]} - self.manifest['values'].append(meshGroup) - return meshGroup + """Adds a Mesh Group to the scene manifest. + + Parameters + ---------- + name : + Name of the mesh group. This will become a file on disk and be usable as a Mesh in the editor. + + + Returns + ------- + dict + Newly created mesh group. + + """ + mesh_group = { + '$type': '{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup', + 'name': name, + 'nodeSelectionList': {'selectedNodes': [], 'unselectedNodes': []}, + 'rules': {'rules': [{'$type': 'MaterialRule'}]} + } + self.manifest['values'].append(mesh_group) + return mesh_group def add_prefab_group(self, name: str, id: str, json: dict) -> dict: - prefabGroup = {} - prefabGroup['$type'] = '{99FE3C6F-5B55-4D8B-8013-2708010EC715} PrefabGroup' - prefabGroup['name'] = name - prefabGroup['id'] = id - prefabGroup['prefabDomData'] = json - self.manifest['values'].append(prefabGroup) - return prefabGroup + """Adds a Prefab Group to the scene manifest. This will become a file on disk and be usable as a ProceduralPrefab in the editor. + + Parameters + ---------- + name : + Name of the prefab. + id : + Unique ID for this prefab group. + json : + The prefab template data. + + + Returns + ------- + dict + The newly created Prefab group + + """ + prefab_group = { + '$type': '{99FE3C6F-5B55-4D8B-8013-2708010EC715} PrefabGroup', + 'name': name, + 'id': id, + 'prefabDomData': json + } + self.manifest['values'].append(prefab_group) + return prefab_group def mesh_group_select_node(self, mesh_group: dict, node_name: str) -> None: + """Adds a node as a selected node. + + Parameters + ---------- + mesh_group : + Mesh group to apply the selection to. + node_name : + Path of the node. + + """ mesh_group['nodeSelectionList']['selectedNodes'].append(node_name) def mesh_group_unselect_node(self, mesh_group: dict, node_name: str) -> None: + """Adds a node as an unselected node. + + Parameters + ---------- + mesh_group : + Mesh group to apply the selection to. + node_name : + Path of the node. + + """ mesh_group['nodeSelectionList']['unselectedNodes'].append(node_name) - def mesh_group_add_advanced_coordinate_system(self, mesh_group: dict, origin_node_name: str, translation: object, - rotation: object, scale: float) -> None: + def mesh_group_add_advanced_coordinate_system(self, mesh_group: dict, + origin_node_name: str = '', + translation: typing.Optional[object] = None, + rotation: typing.Optional[object] = None, + scale: float = 1.0) -> None: + """Adds an Advanced Coordinate System rule which modifies the target coordinate system, + applying a transformation to all data (transforms and vertex data if it exists). + + Parameters + ---------- + mesh_group : + Mesh group to add the Advanced Coordinate System rule to. + origin_node_name : + Path of the node to use as the origin. + translation : + Moves the group along the given vector. + rotation : + Sets the orientation offset of the processed mesh in degrees. Rotates the group after translation. + scale : + Sets the scale offset of the processed mesh. + + """ origin_rule = { '$type': 'CoordinateSystemRule', 'useAdvancedData': True, - 'originNodeName': '' if origin_node_name is None else origin_node_name + 'originNodeName': self.__default_or_value(origin_node_name, '') } if translation is not None: origin_rule['translation'] = translation @@ -153,31 +261,57 @@ class SceneManifest(): mesh_group['rules']['rules'].append(origin_rule) def mesh_group_add_comment(self, mesh_group: dict, comment: str) -> None: - commentRule = { + """Adds a Comment rule. + + Parameters + ---------- + mesh_group : + Mesh group to add the comment rule to. + comment : + Text for the comment rule. + + """ + comment_rule = { '$type': 'CommentRule', 'comment': comment } - mesh_group['rules']['rules'].append(commentRule) + mesh_group['rules']['rules'].append(comment_rule) def __default_or_value(self, val, default): return default if val is None else val - def mesh_group_add_cloth_rule(self, mesh_group: dict, cloth_node_name: str, - inverse_masses_stream_name: str, inverse_masses_channel: int, - motion_constraints_stream_name: str, motion_constraints_channel: int, - backstop_stream_name: str, backstop_offset_channel: int, - backstop_radius_channel: int) -> None: - """ - Adds a Cloth rule. 0 = Red, 1 = Green, 2 = Blue, 3 = Alpha - :param mesh_group: Mesh Group to add the cloth rule to - :param cloth_node_name: Name of the node that the rule applies to - :param inverse_masses_stream_name: Name of the color stream to use for inverse masses - :param inverse_masses_channel: Color channel (index) for inverse masses - :param motion_constraints_stream_name: Name of the color stream to use for motion constraints - :param motion_constraints_channel: Color channel (index) for motion constraints - :param backstop_stream_name: Name of the color stream to use for backstop - :param backstop_offset_channel: Color channel (index) for backstop offset value - :param backstop_radius_channel: Color chnanel (index) for backstop radius value + def mesh_group_add_cloth_rule(self, mesh_group: dict, + cloth_node_name: str, + inverse_masses_stream_name: typing.Optional[str], + inverse_masses_channel: typing.Optional[ColorChannel], + motion_constraints_stream_name: typing.Optional[str], + motion_constraints_channel: typing.Optional[ColorChannel], + backstop_stream_name: typing.Optional[str], + backstop_offset_channel: typing.Optional[ColorChannel], + backstop_radius_channel: typing.Optional[ColorChannel]) -> None: + """Adds a Cloth rule. + + Parameters + ---------- + mesh_group : + Mesh Group to add the cloth rule to + cloth_node_name : + Name of the node that the rule applies to + inverse_masses_stream_name : + Name of the color stream to use for inverse masses + inverse_masses_channel : + Color channel (index) for inverse masses + motion_constraints_stream_name : + Name of the color stream to use for motion constraints + motion_constraints_channel : + Color channel (index) for motion constraints + backstop_stream_name : + Name of the color stream to use for backstop + backstop_offset_channel : + Color channel (index) for backstop offset value + backstop_radius_channel : + Color channel (index) for backstop radius value + """ cloth_rule = { '$type': 'ClothRule', @@ -186,22 +320,31 @@ class SceneManifest(): } if inverse_masses_channel is not None: - cloth_rule['inverseMassesChannel'] = inverse_masses_channel + cloth_rule['inverseMassesChannel'] = int(inverse_masses_channel) cloth_rule['motionConstraintsStreamName'] = self.__default_or_value(motion_constraints_stream_name, 'Default: 1.0') if motion_constraints_channel is not None: - cloth_rule['motionConstraintsChannel'] = motion_constraints_channel + cloth_rule['motionConstraintsChannel'] = int(motion_constraints_channel) cloth_rule['backstopStreamName'] = self.__default_or_value(backstop_stream_name, 'None') if backstop_offset_channel is not None: - cloth_rule['backstopOffsetChannel'] = backstop_offset_channel + cloth_rule['backstopOffsetChannel'] = int(backstop_offset_channel) if backstop_radius_channel is not None: - cloth_rule['backstopRadiusChannel'] = backstop_radius_channel + cloth_rule['backstopRadiusChannel'] = int(backstop_radius_channel) mesh_group['rules']['rules'].append(cloth_rule) def mesh_group_add_lod_rule(self, mesh_group: dict) -> dict: - """ - Adds an LOD rule - :param mesh_group: Mesh Group to add the rule to - :return: LOD rule + """Adds an LOD rule. + + Parameters + ---------- + mesh_group : + Mesh Group to add the rule to. + + + Returns + ------- + dict + LOD rule. + """ lod_rule = { '$type': '{6E796AC8-1484-4909-860A-6D3F22A7346F} LodRule', @@ -212,47 +355,76 @@ class SceneManifest(): return lod_rule def lod_rule_add_lod(self, lod_rule: dict) -> dict: - """ - Adds an LOD level to the LOD rule. Nodes are added in order. The first node added represents LOD1, 2nd LOD2, etc - :param lod_rule: LOD rule to add the LOD level to - :return: LOD level + """Adds an LOD level to the LOD rule. Nodes are added in order. The first node added represents LOD1, 2nd LOD2, etc. + + Parameters + ---------- + lod_rule : + LOD rule to add the LOD level to. + + + Returns + ------- + dict + LOD level. + """ lod = {'selectedNodes': [], 'unselectedNodes': []} lod_rule['nodeSelectionList'].append(lod) return lod def lod_select_node(self, lod: dict, selected_node: str) -> None: - """ - Adds a node as a selected node - :param lod: LOD level to add the node to - :param selected_node: Path of the node + """Adds a node as a selected node. + + Parameters + ---------- + lod : + LOD level to add the node to. + selected_node : + Path of the node. + """ lod['selectedNodes'].append(selected_node) def lod_unselect_node(self, lod: dict, unselected_node: str) -> None: - """ - Adds a node as an unselected node - :param lod: LOD rule to add the node to - :param unselected_node: Path of the node + """Adds a node as an unselected node. + + Parameters + ---------- + lod : + LOD rule to add the node to. + unselected_node : + Path of the node. + """ lod['unselectedNodes'].append(unselected_node) - def mesh_group_add_advanced_mesh_rule(self, mesh_group: dict, use_32bit_vertices: bool, merge_meshes: bool, - use_custom_normals: bool, - vertex_color_stream: str) -> None: - """ - Adds an Advanced Mesh rule - :param mesh_group: Mesh Group to add the rule to - :param use_32bit_vertices: False = 16bit vertex position precision. True = 32bit vertex position precision - :param merge_meshes: Merge all meshes into a single mesh - :param use_custom_normals: True = use normals from DCC tool. False = average normals - :param vertex_color_stream: Color stream name to use for Vertex Coloring + def mesh_group_add_advanced_mesh_rule(self, mesh_group: dict, + use_32bit_vertices: bool = False, + merge_meshes: bool = True, + use_custom_normals: bool = True, + vertex_color_stream: typing.Optional[str] = None) -> None: + """Adds an Advanced Mesh rule. + + Parameters + ---------- + mesh_group : + Mesh Group to add the rule to. + use_32bit_vertices : + False = 16bit vertex position precision. True = 32bit vertex position precision. + merge_meshes : + Merge all meshes into a single mesh. + use_custom_normals : + True = use normals from DCC tool. False = average normals. + vertex_color_stream : + Color stream name to use for Vertex Coloring. + """ rule = { '$type': 'StaticMeshAdvancedRule', - 'use32bitVertices': self.__default_or_value(use_32bit_vertices, False), - 'mergeMeshes': self.__default_or_value(merge_meshes, True), - 'useCustomNormals': self.__default_or_value(use_custom_normals, True) + 'use32bitVertices': use_32bit_vertices, + 'mergeMeshes': merge_meshes, + 'useCustomNormals': use_custom_normals } if vertex_color_stream is not None: @@ -260,37 +432,51 @@ class SceneManifest(): mesh_group['rules']['rules'].append(rule) - def mesh_group_add_skin_rule(self, mesh_group: dict, max_weights_per_vertex: int, weight_threshold: float) -> None: - """ - Adds a Skin rule - :param mesh_group: Mesh Group to add the rule to - :param max_weights_per_vertex: Max number of joints that can influence a vertex - :param weight_threshold: Weight values below this value will be treated as 0 + def mesh_group_add_skin_rule(self, mesh_group: dict, max_weights_per_vertex: int = 4, weight_threshold: float = 0.001) -> None: + """Adds a Skin rule. + + Parameters + ---------- + mesh_group : + Mesh Group to add the rule to. + max_weights_per_vertex : + Max number of joints that can influence a vertex. + weight_threshold : + Weight values below this value will be treated as 0. + """ rule = { '$type': 'SkinRule', - 'maxWeightsPerVertex': self.__default_or_value(max_weights_per_vertex, 4), - 'weightThreshold': self.__default_or_value(weight_threshold, 0.001) + 'maxWeightsPerVertex': max_weights_per_vertex, + 'weightThreshold': weight_threshold } mesh_group['rules']['rules'].append(rule) - def mesh_group_add_tangent_rule(self, mesh_group: dict, tangent_space: int, tspace_method: int) -> None: - """ - Adds a Tangent rule to control tangent space generation - :param mesh_group: Mesh Group to add the rule to - :param tangent_space: Tangent space source. 0 = Scene, 1 = MikkT Tangent Generation - :param tspace_method: MikkT Generation method. 0 = TSpace, 1 = TSpaceBasic + def mesh_group_add_tangent_rule(self, mesh_group: dict, + tangent_space: TangentSpaceSource = TangentSpaceSource.SCENE, + tspace_method: TangentSpaceMethod = TangentSpaceMethod.TSPACE) -> None: + """Adds a Tangent rule to control tangent space generation. + + Parameters + ---------- + mesh_group : + Mesh Group to add the rule to. + tangent_space : + Tangent space source. 0 = Scene, 1 = MikkT Tangent Generation. + tspace_method : + MikkT Generation method. 0 = TSpace, 1 = TSpaceBasic. + """ rule = { '$type': 'TangentsRule', - 'tangentSpace': self.__default_or_value(tangent_space, 1), - 'tSpaceMethod': self.__default_or_value(tspace_method, 0) + 'tangentSpace': int(tangent_space), + 'tSpaceMethod': int(tspace_method) } mesh_group['rules']['rules'].append(rule) - def __add_physx_base_mesh_group(self, name: str, physics_material: typing.Optional[str]) -> dict: + def __add_physx_base_mesh_group(self, name: str, physics_material: typing.Optional[str] = None) -> dict: import azlmbr.math group = { '$type': '{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup', @@ -314,7 +500,9 @@ class SceneManifest(): return group - def add_physx_triangle_mesh_group(self, name: str, merge_meshes: bool = True, weld_vertices: bool = False, + def add_physx_triangle_mesh_group(self, name: str, + merge_meshes: bool = True, + weld_vertices: bool = False, disable_clean_mesh: bool = False, force_32bit_indices: bool = False, suppress_triangle_mesh_remap_table: bool = False, @@ -322,26 +510,42 @@ class SceneManifest(): mesh_weld_tolerance: float = 0.0, num_tris_per_leaf: int = 4, physics_material: typing.Optional[str] = None) -> dict: - """ - Adds a Triangle type PhysX Mesh Group to the scene. + """Adds a Triangle type PhysX Mesh Group to the scene. + + Parameters + ---------- + name : + Name of the mesh group. + merge_meshes : + When true, all selected nodes will be merged into a single collision mesh. + weld_vertices : + When true, mesh welding is performed. Clean mesh must be enabled. + disable_clean_mesh : + When true, mesh cleaning is disabled. This makes cooking faster. + force_32bit_indices : + When true, 32-bit indices will always be created regardless of triangle count. + suppress_triangle_mesh_remap_table : + When true, the face remap table is not created. + This saves a significant amount of memory, but the SDK will not be able to provide the remap + information for internal mesh triangles returned by collisions, sweeps or raycasts hits. + build_triangle_adjacencies : + When true, the triangle adjacency information is created. + mesh_weld_tolerance : + If mesh welding is enabled, this controls the distance at + which vertices are welded. If mesh welding is not enabled, this value defines the + acceptance distance for mesh validation. Provided no two vertices are within this + distance, the mesh is considered to be clean. If not, a warning will be emitted. + num_tris_per_leaf : + Mesh cooking hint for max triangles per leaf limit. Fewer triangles per leaf + produces larger meshes with better runtime performance and worse cooking performance. + physics_material : + Configure which physics material to use. + + Returns + ------- + dict + The newly created mesh group. - :param name: Name of the mesh group. - :param merge_meshes: When true, all selected nodes will be merged into a single collision mesh. - :param weld_vertices: When true, mesh welding is performed. Clean mesh must be enabled. - :param disable_clean_mesh: When true, mesh cleaning is disabled. This makes cooking faster. - :param force_32bit_indices: When true, 32-bit indices will always be created regardless of triangle count. - :param suppress_triangle_mesh_remap_table: When true, the face remap table is not created. - This saves a significant amount of memory, but the SDK will not be able to provide the remap - information for internal mesh triangles returned by collisions, sweeps or raycasts hits. - :param build_triangle_adjacencies: When true, the triangle adjacency information is created. - :param mesh_weld_tolerance: If mesh welding is enabled, this controls the distance at - which vertices are welded. If mesh welding is not enabled, this value defines the - acceptance distance for mesh validation. Provided no two vertices are within this - distance, the mesh is considered to be clean. If not, a warning will be emitted. - :param num_tris_per_leaf: Mesh cooking hint for max triangles per leaf limit. Fewer triangles per leaf - produces larger meshes with better runtime performance and worse cooking performance. - :param physics_material: Configure which physics material to use. - :return: The newly created mesh group. """ group = self.__add_physx_base_mesh_group(name, physics_material) group["export method"] = 0 @@ -367,32 +571,49 @@ class SceneManifest(): gauss_map_limit: int = 32, build_gpu_data: bool = False, physics_material: typing.Optional[str] = None) -> dict: - """ - Adds a Convex type PhysX Mesh Group to the scene. + """Adds a Convex type PhysX Mesh Group to the scene. + + Parameters + ---------- + name : + Name of the mesh group. + area_test_epsilon : + If the area of a triangle of the hull is below this value, the triangle will be + rejected. This test is done only if Check Zero Area Triangles is used. + plane_tolerance : + The value is used during hull construction. When a new point is about to be added + to the hull it gets dropped when the point is closer to the hull than the planeTolerance. + use_16bit_indices : + Denotes the use of 16-bit vertex indices in Convex triangles or polygons. + check_zero_area_triangles : + Checks and removes almost zero-area triangles during convex hull computation. + The rejected area size is specified in Area Test Epsilon. + quantize_input : + Quantizes the input vertices using the k-means clustering. + use_plane_shifting : + Enables plane shifting vertex limit algorithm. Plane shifting is an alternative + algorithm for the case when the computed hull has more vertices than the specified vertex + limit. + shift_vertices : + Convex hull input vertices are shifted to be around origin to provide better + computation stability + gauss_map_limit : + Vertex limit beyond which additional acceleration structures are computed for each + convex mesh. Increase that limit to reduce memory usage. Computing the extra structures + all the time does not guarantee optimal performance. + build_gpu_data : + When true, additional information required for GPU-accelerated rigid body + simulation is created. This can increase memory usage and cooking times for convex meshes + and triangle meshes. Convex hulls are created with respect to GPU simulation limitations. + Vertex limit is set to 64 and vertex limit per face is internally set to 32. + physics_material : + Configure which physics material to use. + + Returns + ------- + dict + The newly created mesh group. - :param name: Name of the mesh group. - :param area_test_epsilon: If the area of a triangle of the hull is below this value, the triangle will be - rejected. This test is done only if Check Zero Area Triangles is used. - :param plane_tolerance: The value is used during hull construction. When a new point is about to be added - to the hull it gets dropped when the point is closer to the hull than the planeTolerance. - :param use_16bit_indices: Denotes the use of 16-bit vertex indices in Convex triangles or polygons. - :param check_zero_area_triangles: Checks and removes almost zero-area triangles during convex hull computation. - The rejected area size is specified in Area Test Epsilon. - :param quantize_input: Quantizes the input vertices using the k-means clustering. - :param use_plane_shifting: Enables plane shifting vertex limit algorithm. Plane shifting is an alternative - algorithm for the case when the computed hull has more vertices than the specified vertex - limit. - :param shift_vertices: Convex hull input vertices are shifted to be around origin to provide better - computation stability - :param gauss_map_limit: Vertex limit beyond which additional acceleration structures are computed for each - convex mesh. Increase that limit to reduce memory usage. Computing the extra structures - all the time does not guarantee optimal performance. - :param build_gpu_data: When true, additional information required for GPU-accelerated rigid body - simulation is created. This can increase memory usage and cooking times for convex meshes - and triangle meshes. Convex hulls are created with respect to GPU simulation limitations. - Vertex limit is set to 64 and vertex limit per face is internally set to 32. - :param physics_material: Configure which physics material to use. - :return: The newly created mesh group. """ group = self.__add_physx_base_mesh_group(name, physics_material) group["export method"] = 1 @@ -414,17 +635,27 @@ class SceneManifest(): primitive_shape_target: PrimitiveShape = PrimitiveShape.BEST_FIT, volume_term_coefficient: float = 0.0, physics_material: typing.Optional[str] = None) -> dict: - """ - Adds a Primitive Shape type PhysX Mesh Group to the scene + """Adds a Primitive Shape type PhysX Mesh Group to the scene + + Parameters + ---------- + name : + Name of the mesh group. + primitive_shape_target : + The shape that should be fitted to this mesh. If BEST_FIT is selected, the + algorithm will determine which of the shapes fits best. + volume_term_coefficient : + This parameter controls how aggressively the primitive fitting algorithm will try + to minimize the volume of the fitted primitive. A value of 0 (no volume minimization) is + recommended for most meshes, especially those with moderate to high vertex counts. + physics_material : + Configure which physics material to use. + + Returns + ------- + dict + The newly created mesh group. - :param name: Name of the mesh group. - :param primitive_shape_target: The shape that should be fitted to this mesh. If BEST_FIT is selected, the - algorithm will determine which of the shapes fits best. - :param volume_term_coefficient: This parameter controls how aggressively the primitive fitting algorithm will try - to minimize the volume of the fitted primitive. A value of 0 (no volume minimization) is - recommended for most meshes, especially those with moderate to high vertex counts. - :param physics_material: Configure which physics material to use. - :return: The newly created mesh group. """ group = self.__add_physx_base_mesh_group(name, physics_material) group["export method"] = 2 @@ -447,26 +678,40 @@ class SceneManifest(): convex_hull_downsampling: int = 4, pca: bool = False, project_hull_vertices: bool = True) -> None: - """ - Enables and configures mesh decomposition for a PhysX Mesh Group. + """Enables and configures mesh decomposition for a PhysX Mesh Group. Only valid for convex or primitive mesh types. - :param mesh_group: Mesh group to configure decomposition for. - :param max_convex_hulls: Controls the maximum number of hulls to generate. - :param max_num_vertices_per_convex_hull: Controls the maximum number of triangles per convex hull. - :param concavity: Maximum concavity of each approximate convex hull. - :param resolution: Maximum number of voxels generated during the voxelization stage. - :param mode: Select voxel-based approximate convex decomposition or tetrahedron-based - approximate convex decomposition. - :param alpha: Controls the bias toward clipping along symmetry planes. - :param beta: Controls the bias toward clipping along revolution axes. - :param min_volume_per_convex_hull: Controls the adaptive sampling of the generated convex hulls. - :param plane_downsampling: Controls the granularity of the search for the best clipping plane. - :param convex_hull_downsampling: Controls the precision of the convex hull generation process - during the clipping plane selection stage. - :param pca: Enable or disable normalizing the mesh before applying the convex decomposition. - :param project_hull_vertices: Project the output convex hull vertices onto the original source mesh to increase - the floating point accuracy of the results. + Parameters + ---------- + mesh_group : + Mesh group to configure decomposition for. + max_convex_hulls : + Controls the maximum number of hulls to generate. + max_num_vertices_per_convex_hull : + Controls the maximum number of triangles per convex hull. + concavity : + Maximum concavity of each approximate convex hull. + resolution : + Maximum number of voxels generated during the voxelization stage. + mode : + Select voxel-based approximate convex decomposition or tetrahedron-based + approximate convex decomposition. + alpha : + Controls the bias toward clipping along symmetry planes. + beta : + Controls the bias toward clipping along revolution axes. + min_volume_per_convex_hull : + Controls the adaptive sampling of the generated convex hulls. + plane_downsampling : + Controls the granularity of the search for the best clipping plane. + convex_hull_downsampling : + Controls the precision of the convex hull generation process + during the clipping plane selection stage. + pca : + Enable or disable normalizing the mesh before applying the convex decomposition. + project_hull_vertices : + Project the output convex hull vertices onto the original source mesh to increase + the floating point accuracy of the results. """ mesh_group['DecomposeMeshes'] = True mesh_group['ConvexDecompositionParams'] = { @@ -485,41 +730,54 @@ class SceneManifest(): } def physx_mesh_group_add_selected_node(self, mesh_group: dict, node: str) -> None: - """ - Adds a node to the selected nodes list + """Adds a node to the selected nodes list - :param mesh_group: Mesh group to add to. - :param node: Node path to add. + Parameters + ---------- + mesh_group : + Mesh group to add to. + node : + Node path to add. """ mesh_group['NodeSelectionList']['selectedNodes'].append(node) def physx_mesh_group_add_unselected_node(self, mesh_group: dict, node: str) -> None: - """ - Adds a node to the unselected nodes list + """Adds a node to the unselected nodes list - :param mesh_group: Mesh group to add to. - :param node: Node path to add. + Parameters + ---------- + mesh_group : + Mesh group to add to. + node : + Node path to add. """ mesh_group['NodeSelectionList']['unselectedNodes'].append(node) def physx_mesh_group_add_selected_unselected_nodes(self, mesh_group: dict, selected: typing.List[str], unselected: typing.List[str]) -> None: - """ - Adds a set of nodes to the selected/unselected node lists + """Adds a set of nodes to the selected/unselected node lists - :param mesh_group: Mesh group to add to. - :param selected: List of node paths to add to the selected list. - :param unselected: List of node paths to add to the unselected list. + Parameters + ---------- + mesh_group : + Mesh group to add to. + selected : + List of node paths to add to the selected list. + unselected : + List of node paths to add to the unselected list. """ mesh_group['NodeSelectionList']['selectedNodes'].extend(selected) mesh_group['NodeSelectionList']['unselectedNodes'].extend(unselected) def physx_mesh_group_add_comment(self, mesh_group: dict, comment: str) -> None: - """ - Adds a comment rule + """Adds a comment rule - :param mesh_group: Mesh group to add the rule to. - :param comment: Comment string. + Parameters + ---------- + mesh_group : + Mesh group to add the rule to. + comment : + Comment string. """ rule = { "$type": "CommentRule",