Merge pull request #7613 from aws-lumberyard-dev/Atom/guthadam/centralize_shader_management_console_operations_in_document_class

Atom Tools: Moving shader management console file operations into document class
monroegm-disable-blank-issue-2
Guthrie Adams 4 years ago committed by GitHub
commit ba43efd3d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -43,7 +43,7 @@ namespace AtomToolsFramework
using Base = AzFramework::Application; using Base = AzFramework::Application;
AtomToolsApplication(const AZStd::string& targetName, int* argc, char*** argv); AtomToolsApplication(const char* targetName, int* argc, char*** argv);
~AtomToolsApplication(); ~AtomToolsApplication();
virtual bool LaunchLocalServer(); virtual bool LaunchLocalServer();

@ -22,7 +22,7 @@ namespace AtomToolsFramework
using Base = AtomToolsApplication; using Base = AtomToolsApplication;
AtomToolsDocumentApplication(const AZStd::string& targetName, int* argc, char*** argv); AtomToolsDocumentApplication(const char* targetName, int* argc, char*** argv);
protected: protected:
// AtomToolsApplication overrides... // AtomToolsApplication overrides...

@ -45,7 +45,7 @@ AZ_POP_DISABLE_WARNING
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsApplication::AtomToolsApplication(const AZStd::string& targetName, int* argc, char*** argv) AtomToolsApplication::AtomToolsApplication(const char* targetName, int* argc, char*** argv)
: Application(argc, argv) : Application(argc, argv)
, AzQtApplication(*argc, *argv) , AzQtApplication(*argc, *argv)
, m_targetName(targetName) , m_targetName(targetName)

@ -11,7 +11,7 @@
namespace AtomToolsFramework namespace AtomToolsFramework
{ {
AtomToolsDocumentApplication::AtomToolsDocumentApplication(const AZStd::string& targetName, int* argc, char*** argv) AtomToolsDocumentApplication::AtomToolsDocumentApplication(const char* targetName, int* argc, char*** argv)
: Base(targetName, argc, argv) : Base(targetName, argc, argv)
{ {
} }

@ -6,10 +6,18 @@
* *
*/ */
#include <AssetDatabase/AssetDatabaseConnection.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h> #include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h> #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Document/ShaderManagementConsoleDocument.h> #include <Document/ShaderManagementConsoleDocument.h>
namespace ShaderManagementConsole namespace ShaderManagementConsole
@ -25,17 +33,15 @@ namespace ShaderManagementConsole
ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect();
} }
void ShaderManagementConsoleDocument::SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) void ShaderManagementConsoleDocument::SetShaderVariantListSourceData(
const AZ::RPI::ShaderVariantListSourceData& shaderVariantListSourceData)
{ {
m_shaderVariantListSourceData = sourceData; m_shaderVariantListSourceData = shaderVariantListSourceData;
AZStd::string shaderPath = m_shaderVariantListSourceData.m_shaderFilePath; AZStd::string shaderPath = m_shaderVariantListSourceData.m_shaderFilePath;
AzFramework::StringFunc::Path::ReplaceExtension(shaderPath, AZ::RPI::ShaderAsset::Extension); AzFramework::StringFunc::Path::ReplaceExtension(shaderPath, AZ::RPI::ShaderAsset::Extension);
m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::ShaderAsset>(shaderPath.c_str()); m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::ShaderAsset>(shaderPath.c_str());
if (!m_shaderAsset) AZ_Error("ShaderManagementConsoleDocument", m_shaderAsset.IsReady(), "Could not load shader asset: %s.", shaderPath.c_str());
{
AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str());
}
AtomToolsFramework::AtomToolsDocumentNotificationBus::Event( AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id);
@ -107,22 +113,18 @@ namespace ShaderManagementConsole
return false; return false;
} }
if (!AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderSourceData::Extension))
{ {
AZ_Error("ShaderManagementConsoleDocument", false, "Document extension is not supported: '%s.'", m_absolutePath.c_str()); return LoadShaderSourceData();
return OpenFailed();
} }
// Load the shader config data and create a shader config asset from it if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
AZ::RPI::ShaderVariantListSourceData sourceData;
if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, sourceData))
{ {
AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()); return LoadShaderVariantListSourceData();
return OpenFailed();
} }
SetShaderVariantListSourceData(sourceData); AZ_Error("ShaderManagementConsoleDocument", false, "Document extension is not supported: '%s.'", m_absolutePath.c_str());
return IsOpen() ? OpenSucceeded() : OpenFailed(); return OpenFailed();
} }
bool ShaderManagementConsoleDocument::Save() bool ShaderManagementConsoleDocument::Save()
@ -173,7 +175,8 @@ namespace ShaderManagementConsole
bool ShaderManagementConsoleDocument::IsSavable() const bool ShaderManagementConsoleDocument::IsSavable() const
{ {
return true; return IsOpen() &&
AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension);
} }
void ShaderManagementConsoleDocument::Clear() void ShaderManagementConsoleDocument::Clear()
@ -195,4 +198,178 @@ namespace ShaderManagementConsole
m_absolutePath = m_savePathNormalized; m_absolutePath = m_savePathNormalized;
return SaveSucceeded(); return SaveSucceeded();
} }
bool ShaderManagementConsoleDocument::LoadShaderSourceData()
{
// Get info such as relative path of the file and asset id
bool result = false;
AZ::Data::AssetInfo shaderAssetInfo;
AZStd::string watchFolder;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, m_absolutePath.c_str(), shaderAssetInfo,
watchFolder);
if (!result)
{
AZ_Error("ShaderManagementConsoleDocument", false, "Failed to get the asset info for the file: %s.", m_absolutePath.c_str());
return OpenFailed();
}
// retrieves a list of all material source files that use the shader. Note that materials inherit from materialtype files, which
// are actual files that refer to shader files.
const auto& materialAssetIds = FindMaterialAssetsUsingShader(shaderAssetInfo.m_relativePath);
// This loop collects all uniquely-identified shader items used by the materials based on its shader variant id.
AZStd::set<AZ::RPI::ShaderVariantId> shaderVariantIds;
AZStd::vector<AZ::RPI::ShaderOptionGroup> shaderVariantListShaderOptionGroups;
for (const auto& materialAssetId : materialAssetIds)
{
const auto& materialInstanceShaderItems = GetMaterialInstanceShaderItems(materialAssetId);
for (const auto& shaderItem : materialInstanceShaderItems)
{
const auto& shaderAssetId = shaderItem.GetShaderAsset().GetId();
if (shaderAssetInfo.m_assetId == shaderAssetId)
{
const auto& shaderVariantId = shaderItem.GetShaderVariantId();
if (!shaderVariantId.IsEmpty() && shaderVariantIds.insert(shaderVariantId).second)
{
shaderVariantListShaderOptionGroups.push_back(shaderItem.GetShaderOptionGroup());
}
}
}
}
// Generate the shader variant list data by collecting shader option name-value pairs.s
AZ::RPI::ShaderVariantListSourceData shaderVariantListSourceData;
shaderVariantListSourceData.m_shaderFilePath = shaderAssetInfo.m_relativePath;
int stableId = 1;
for (const auto& shaderOptionGroup : shaderVariantListShaderOptionGroups)
{
AZ::RPI::ShaderVariantListSourceData::VariantInfo variantInfo;
variantInfo.m_stableId = stableId;
const auto& shaderOptionDescriptors = shaderOptionGroup.GetShaderOptionDescriptors();
for (const auto& shaderOptionDescriptor : shaderOptionDescriptors)
{
const auto& optionName = shaderOptionDescriptor.GetName();
const auto& optionValue = shaderOptionGroup.GetValue(optionName);
if (!optionValue.IsValid())
{
continue;
}
const auto& valueName = shaderOptionDescriptor.GetValueName(optionValue);
variantInfo.m_options[optionName.GetStringView()] = valueName.GetStringView();
}
if (!variantInfo.m_options.empty())
{
shaderVariantListSourceData.m_shaderVariants.push_back(variantInfo);
stableId++;
}
}
SetShaderVariantListSourceData(shaderVariantListSourceData);
return IsOpen() ? OpenSucceeded() : OpenFailed();
}
bool ShaderManagementConsoleDocument::LoadShaderVariantListSourceData()
{
// Load previously generated shader variant list source data
AZ::RPI::ShaderVariantListSourceData shaderVariantListSourceData;
if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, shaderVariantListSourceData))
{
AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str());
return OpenFailed();
}
SetShaderVariantListSourceData(shaderVariantListSourceData);
return IsOpen() ? OpenSucceeded() : OpenFailed();
}
AZStd::vector<AZ::Data::AssetId> ShaderManagementConsoleDocument::FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath)
{
AzToolsFramework::AssetDatabase::AssetDatabaseConnection assetDatabaseConnection;
assetDatabaseConnection.OpenDatabase();
// Find all material types that reference shaderFilePath
AZStd::vector<AZStd::string> materialTypeSources;
assetDatabaseConnection.QuerySourceDependencyByDependsOnSource(
shaderFilePath.c_str(), nullptr, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_Any,
[&](AzToolsFramework::AssetDatabase::SourceFileDependencyEntry& sourceFileDependencyEntry)
{
if (AzFramework::StringFunc::Path::IsExtension(
sourceFileDependencyEntry.m_source.c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
{
materialTypeSources.push_back(sourceFileDependencyEntry.m_source);
}
return true;
});
// Find all materials that reference any of the material types using this shader
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer productDependencies;
for (const auto& materialTypeSource : materialTypeSources)
{
bool result = false;
AZ::Data::AssetInfo materialTypeSourceAssetInfo;
AZStd::string watchFolder;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, materialTypeSource.c_str(),
materialTypeSourceAssetInfo, watchFolder);
assetDatabaseConnection.QueryDirectReverseProductDependenciesBySourceGuidSubId(
materialTypeSourceAssetInfo.m_assetId.m_guid, materialTypeSourceAssetInfo.m_assetId.m_subId,
[&](AzToolsFramework::AssetDatabase::ProductDatabaseEntry& entry)
{
if (AzFramework::StringFunc::Path::IsExtension(entry.m_productName.c_str(), AZ::RPI::MaterialAsset::Extension))
{
productDependencies.push_back(entry);
}
return true;
});
}
AZStd::vector<AZ::Data::AssetId> results;
results.reserve(productDependencies.size());
for (auto product : productDependencies)
{
assetDatabaseConnection.QueryCombinedByProductID(
product.m_productID,
[&](AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& combined)
{
results.push_back({ combined.m_sourceGuid, combined.m_subID });
return false;
},
nullptr);
}
return results;
}
AZStd::vector<AZ::RPI::ShaderCollection::Item> ShaderManagementConsoleDocument::GetMaterialInstanceShaderItems(
const AZ::Data::AssetId& materialAssetId)
{
auto materialAsset =
AZ::RPI::AssetUtils::LoadAssetById<AZ::RPI::MaterialAsset>(materialAssetId, AZ::RPI::AssetUtils::TraceLevel::Error);
if (!materialAsset.IsReady())
{
AZ_Error(
"ShaderManagementConsoleDocument", false, "Failed to load material asset from asset id: %s",
materialAssetId.ToString<AZStd::string>().c_str());
return AZStd::vector<AZ::RPI::ShaderCollection::Item>();
}
auto materialInstance = AZ::RPI::Material::Create(materialAsset);
if (!materialInstance)
{
AZ_Error(
"ShaderManagementConsoleDocument", false, "Failed to create material instance from asset: %s",
materialAsset.ToString<AZStd::string>().c_str());
return AZStd::vector<AZ::RPI::ShaderCollection::Item>();
}
return AZStd::vector<AZ::RPI::ShaderCollection::Item>(
materialInstance->GetShaderCollection().begin(), materialInstance->GetShaderCollection().end());
}
} // namespace ShaderManagementConsole } // namespace ShaderManagementConsole

@ -5,20 +5,21 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h> #include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Reflect/Material/ShaderCollection.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h> #include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocument.h> #include <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AzCore/Asset/AssetCommon.h> #include <AzCore/Asset/AssetCommon.h>
#include <AzCore/RTTI/RTTI.h> #include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/vector.h>
#include <Document/ShaderManagementConsoleDocumentRequestBus.h> #include <Document/ShaderManagementConsoleDocumentRequestBus.h>
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
/** //! ShaderManagementConsoleDocument provides an API for modifying and saving document properties.
* ShaderManagementConsoleDocument provides an API for modifying and saving document properties.
*/
class ShaderManagementConsoleDocument class ShaderManagementConsoleDocument
: public AtomToolsFramework::AtomToolsDocument : public AtomToolsFramework::AtomToolsDocument
, public ShaderManagementConsoleDocumentRequestBus::Handler , public ShaderManagementConsoleDocumentRequestBus::Handler
@ -42,7 +43,7 @@ namespace ShaderManagementConsole
bool IsSavable() const override; bool IsSavable() const override;
// ShaderManagementConsoleDocumentRequestBus::Handler overridfes... // ShaderManagementConsoleDocumentRequestBus::Handler overridfes...
void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) override; void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& shaderVariantListSourceData) override;
const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const override; const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const override;
size_t GetShaderVariantCount() const override; size_t GetShaderVariantCount() const override;
const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override;
@ -53,8 +54,21 @@ namespace ShaderManagementConsole
// AtomToolsFramework::AtomToolsDocument overrides... // AtomToolsFramework::AtomToolsDocument overrides...
void Clear() override; void Clear() override;
// Write shader variant list source data to JSON
bool SaveSourceData(); bool SaveSourceData();
// Read shader variant list source data from JSON and initialize the document
bool LoadShaderSourceData();
// Read shader source data from JSON then find all references to to populate the shader variant list and initialize the document
bool LoadShaderVariantListSourceData();
// Find all material assets that reference material types using shaderFilePath
AZStd::vector<AZ::Data::AssetId> FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath);
// Retrieve all of the shader collection items from a material instance created from materialAssetId
AZStd::vector<AZ::RPI::ShaderCollection::Item> GetMaterialInstanceShaderItems(const AZ::Data::AssetId& materialAssetId);
// Source data for shader variant list // Source data for shader variant list
AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData; AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData;

@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <Atom/RPI.Edit/Shader/ShaderSourceData.h> #include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
@ -14,9 +15,7 @@
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
class ShaderManagementConsoleDocumentRequests : public AZ::EBusTraits
class ShaderManagementConsoleDocumentRequests
: public AZ::EBusTraits
{ {
public: public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
@ -24,7 +23,7 @@ namespace ShaderManagementConsole
typedef AZ::Uuid BusIdType; typedef AZ::Uuid BusIdType;
//! Set the shader variant list //! Set the shader variant list
virtual void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) = 0; virtual void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& shaderVariantListSourceData) = 0;
//! Get the shader variant list //! Get the shader variant list
virtual const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const = 0; virtual const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const = 0;

@ -6,27 +6,17 @@
* *
*/ */
#include <AssetDatabase/AssetDatabaseConnection.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/RTTI/BehaviorContext.h> #include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h> #include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h> #include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/UI/UICore/QWidgetSavedState.h>
#include <Document/ShaderManagementConsoleDocument.h> #include <Document/ShaderManagementConsoleDocument.h>
#include <Document/ShaderManagementConsoleDocumentRequestBus.h> #include <Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <ShaderManagementConsoleApplication.h> #include <ShaderManagementConsoleApplication.h>
#include <ShaderManagementConsoleRequestBus.h>
#include <ShaderManagementConsole_Traits_Platform.h> #include <ShaderManagementConsole_Traits_Platform.h>
#include <QDesktopServices> #include <QDesktopServices>
@ -62,13 +52,11 @@ namespace ShaderManagementConsole
QApplication::setApplicationName("O3DE Shader Management Console"); QApplication::setApplicationName("O3DE Shader Management Console");
ShaderManagementConsoleRequestBus::Handler::BusConnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
} }
ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication() ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication()
{ {
ShaderManagementConsoleRequestBus::Handler::BusDisconnect();
AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
m_window.reset(); m_window.reset();
} }
@ -79,15 +67,6 @@ namespace ShaderManagementConsole
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{ {
behaviorContext->EBus<ShaderManagementConsoleRequestBus>("ShaderManagementConsoleRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole")
->Event("GetSourceAssetInfo", &ShaderManagementConsoleRequestBus::Events::GetSourceAssetInfo)
->Event("FindMaterialAssetsUsingShader", &ShaderManagementConsoleRequestBus::Events::FindMaterialAssetsUsingShader )
->Event("GetMaterialInstanceShaderItems", &ShaderManagementConsoleRequestBus::Events::GetMaterialInstanceShaderItems)
;
behaviorContext->EBus<ShaderManagementConsoleDocumentRequestBus>("ShaderManagementConsoleDocumentRequestBus") behaviorContext->EBus<ShaderManagementConsoleDocumentRequestBus>("ShaderManagementConsoleDocumentRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Category, "Editor")
@ -145,8 +124,11 @@ namespace ShaderManagementConsole
pythonArgs); pythonArgs);
}); });
} }
else if (AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) if (AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderSourceData::Extension) ||
AzFramework::StringFunc::Path::IsExtension(
entries.front()->GetFullPath().c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{ {
menu->addAction(QObject::tr("Open"), [entries, this]() menu->addAction(QObject::tr("Open"), [entries, this]()
{ {
@ -180,100 +162,4 @@ namespace ShaderManagementConsole
{ {
return m_window.get(); return m_window.get();
} }
AZ::Data::AssetInfo ShaderManagementConsoleApplication::GetSourceAssetInfo(const AZStd::string& sourceAssetFileName)
{
bool result = false;
AZ::Data::AssetInfo assetInfo;
AZStd::string watchFolder;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, sourceAssetFileName.c_str(), assetInfo,
watchFolder);
AZ_Error(nullptr, result, "Failed to get the asset info for the file: %s.", sourceAssetFileName.c_str());
return assetInfo;
}
AZStd::vector<AZ::Data::AssetId> ShaderManagementConsoleApplication::FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath)
{
// Collect the material types referencing the shader
AZStd::vector<AZStd::string> materialTypeSources;
AzToolsFramework::AssetDatabase::AssetDatabaseConnection assetDatabaseConnection;
assetDatabaseConnection.OpenDatabase();
assetDatabaseConnection.QuerySourceDependencyByDependsOnSource(
shaderFilePath.c_str(), nullptr, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_Any,
[&](AzToolsFramework::AssetDatabase::SourceFileDependencyEntry& sourceFileDependencyEntry)
{
AZStd::string assetExtension;
if (AzFramework::StringFunc::Path::GetExtension(sourceFileDependencyEntry.m_source.c_str(), assetExtension, false))
{
if (assetExtension == "materialtype")
{
materialTypeSources.push_back(sourceFileDependencyEntry.m_source);
}
}
return true;
});
AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer productDependencies;
for (const auto& materialTypeSource : materialTypeSources)
{
bool result = false;
AZ::Data::AssetInfo materialTypeSourceAssetInfo;
AZStd::string watchFolder;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, materialTypeSource.c_str(),
materialTypeSourceAssetInfo, watchFolder);
assetDatabaseConnection.QueryDirectReverseProductDependenciesBySourceGuidSubId(
materialTypeSourceAssetInfo.m_assetId.m_guid, materialTypeSourceAssetInfo.m_assetId.m_subId,
[&](AzToolsFramework::AssetDatabase::ProductDatabaseEntry& entry)
{
AZStd::string assetExtension;
if (AzFramework::StringFunc::Path::GetExtension(entry.m_productName.c_str(), assetExtension, false))
{
if (assetExtension == "azmaterial")
{
productDependencies.push_back(entry);
}
}
return true;
});
}
AZStd::vector<AZ::Data::AssetId> results;
results.reserve(productDependencies.size());
for (auto product : productDependencies)
{
assetDatabaseConnection.QueryCombinedByProductID(
product.m_productID,
[&](AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& combined)
{
results.push_back({ combined.m_sourceGuid, combined.m_subID });
return false;
},
nullptr);
}
return results;
}
AZStd::vector<AZ::RPI::ShaderCollection::Item> ShaderManagementConsoleApplication::GetMaterialInstanceShaderItems(
const AZ::Data::AssetId& assetId)
{
auto materialAsset = AZ::RPI::AssetUtils::LoadAssetById<AZ::RPI::MaterialAsset>(assetId, AZ::RPI::AssetUtils::TraceLevel::Error);
auto materialInstance = AZ::RPI::Material::Create(materialAsset);
AZ_Error(
nullptr, materialAsset, "Failed to get a material instance from product asset id: %s",
assetId.ToString<AZStd::string>().c_str());
if (materialInstance != nullptr)
{
return AZStd::vector<AZ::RPI::ShaderCollection::Item>(
materialInstance->GetShaderCollection().begin(), materialInstance->GetShaderCollection().end());
}
return AZStd::vector<AZ::RPI::ShaderCollection::Item>();
}
} // namespace ShaderManagementConsole } // namespace ShaderManagementConsole

@ -12,14 +12,12 @@
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h> #include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h> #include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
#include <AzToolsFramework/API/EditorWindowRequestBus.h> #include <AzToolsFramework/API/EditorWindowRequestBus.h>
#include <ShaderManagementConsoleRequestBus.h>
#include <Window/ShaderManagementConsoleWindow.h> #include <Window/ShaderManagementConsoleWindow.h>
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
class ShaderManagementConsoleApplication class ShaderManagementConsoleApplication
: public AtomToolsFramework::AtomToolsDocumentApplication : public AtomToolsFramework::AtomToolsDocumentApplication
, private ShaderManagementConsoleRequestBus::Handler
, private AzToolsFramework::EditorWindowRequestBus::Handler , private AzToolsFramework::EditorWindowRequestBus::Handler
{ {
public: public:
@ -42,11 +40,6 @@ namespace ShaderManagementConsole
// AzToolsFramework::EditorWindowRequests::Bus::Handler // AzToolsFramework::EditorWindowRequests::Bus::Handler
QWidget* GetAppMainWindow() override; QWidget* GetAppMainWindow() override;
// ShaderManagementConsoleRequestBus::Handler overrides...
AZ::Data::AssetInfo GetSourceAssetInfo(const AZStd::string& sourceAssetFileName) override;
AZStd::vector<AZ::Data::AssetId> FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath) override;
AZStd::vector<AZ::RPI::ShaderCollection::Item> GetMaterialInstanceShaderItems(const AZ::Data::AssetId& assetId) override;
private: private:
AZStd::unique_ptr<ShaderManagementConsoleWindow> m_window; AZStd::unique_ptr<ShaderManagementConsoleWindow> m_window;
AZStd::unique_ptr<AtomToolsFramework::AtomToolsAssetBrowserInteractions> m_assetBrowserInteractions; AZStd::unique_ptr<AtomToolsFramework::AtomToolsAssetBrowserInteractions> m_assetBrowserInteractions;

@ -1,38 +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 <AzCore/std/containers/vector.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Reflect/Material/ShaderCollection.h>
namespace ShaderManagementConsole
{
//! ShaderManagementConsoleRequestBus provides
class ShaderManagementConsoleRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Returns a shader file's asset id and relative filepath
virtual AZ::Data::AssetInfo GetSourceAssetInfo(const AZStd::string& sourceAssetFileName) = 0;
// [GFX TODO][ATOM-14857] Generalize this API
//! Returns a list of material AssetIds that use the shader file.
virtual AZStd::vector<AZ::Data::AssetId> FindMaterialAssetsUsingShader (const AZStd::string& shaderFilePath) = 0;
//! Returns a list of shader items contained within an instantiated material source's shader collection.
virtual AZStd::vector<AZ::RPI::ShaderCollection::Item> GetMaterialInstanceShaderItems(const AZ::Data::AssetId& assetId) = 0;
};
using ShaderManagementConsoleRequestBus = AZ::EBus<ShaderManagementConsoleRequests>;
} // namespace ShaderManagementConsole

@ -0,0 +1,106 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Name/Name.h>
#include <Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <Window/ShaderManagementConsoleTableView.h>
#include <QHeaderView>
namespace ShaderManagementConsole
{
ShaderManagementConsoleTableView::ShaderManagementConsoleTableView(
const AZ::Crc32& toolId, const AZ::Uuid& documentId, QWidget* parent)
: QTableView(parent)
, m_toolId(toolId)
, m_documentId(documentId)
, m_model(new QStandardItemModel(this))
{
setSelectionBehavior(QAbstractItemView::SelectRows);
setModel(m_model);
RebuildTable();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
}
ShaderManagementConsoleTableView::~ShaderManagementConsoleTableView()
{
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
}
void ShaderManagementConsoleTableView::OnDocumentOpened(const AZ::Uuid& documentId)
{
if (m_documentId == documentId)
{
RebuildTable();
}
}
void ShaderManagementConsoleTableView::OnDocumentModified(const AZ::Uuid& documentId)
{
if (m_documentId == documentId)
{
RebuildTable();
}
}
void ShaderManagementConsole::ShaderManagementConsoleTableView::RebuildTable()
{
AZStd::unordered_set<AZStd::string> optionNames;
size_t shaderOptionCount = 0;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderOptionCount, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount);
for (size_t optionIndex = 0; optionIndex < shaderOptionCount; ++optionIndex)
{
AZ::RPI::ShaderOptionDescriptor shaderOptionDesc;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderOptionDesc, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor, optionIndex);
optionNames.insert(shaderOptionDesc.GetName().GetCStr());
}
size_t shaderVariantCount = 0;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderVariantCount, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount);
m_model->clear();
m_model->setRowCount(static_cast<int>(shaderVariantCount));
m_model->setColumnCount(static_cast<int>(optionNames.size()));
int nameIndex = 0;
for (const auto& optionName : optionNames)
{
m_model->setHeaderData(nameIndex++, Qt::Horizontal, optionName.c_str());
}
for (int variantIndex = 0; variantIndex < shaderVariantCount; ++variantIndex)
{
AZ::RPI::ShaderVariantListSourceData::VariantInfo shaderVariantInfo;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderVariantInfo, m_documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo, variantIndex);
m_model->setHeaderData(variantIndex, Qt::Vertical, QString::number(variantIndex));
for (const auto& shaderOption : shaderVariantInfo.m_options)
{
AZ::Name optionName{ shaderOption.first };
AZ::Name optionValue{ shaderOption.second };
auto optionIt = optionNames.find(optionName.GetCStr());
int optionIndex = static_cast<int>(AZStd::distance(optionNames.begin(), optionIt));
QStandardItem* item = new QStandardItem(optionValue.GetCStr());
m_model->setItem(variantIndex, optionIndex, item);
}
}
}
} // namespace ShaderManagementConsole
#include <Window/moc_ShaderManagementConsoleTableView.cpp>
#include "ShaderManagementConsoleTableView.h"

@ -0,0 +1,40 @@
/*
* 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 <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <QStandardItemModel>
#include <QTableView>
#endif
namespace ShaderManagementConsole
{
class ShaderManagementConsoleTableView
: public QTableView
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(ShaderManagementConsoleTableView, AZ::SystemAllocator, 0);
ShaderManagementConsoleTableView(const AZ::Crc32& toolId, const AZ::Uuid& documentId, QWidget* parent);
~ShaderManagementConsoleTableView();
protected:
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler overrides...
void OnDocumentOpened(const AZ::Uuid& documentId) override;
void OnDocumentModified(const AZ::Uuid& documentId) override;
void RebuildTable();
const AZ::Crc32 m_toolId = {};
const AZ::Uuid m_documentId = AZ::Uuid::CreateNull();
QStandardItemModel* m_model = {};
};
} // namespace ShaderManagementConsole

@ -6,23 +6,19 @@
* *
*/ */
#include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h> #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h> #include <AzCore/Utils/Utils.h>
#include <AzCore/Name/Name.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h> #include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <Document/ShaderManagementConsoleDocumentRequestBus.h> #include <Window/ShaderManagementConsoleTableView.h>
#include <Window/ShaderManagementConsoleWindow.h> #include <Window/ShaderManagementConsoleWindow.h>
#include <AzCore/Utils/Utils.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QDesktopServices> #include <QDesktopServices>
#include <QFileDialog> #include <QFileDialog>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableView>
#include <QUrl> #include <QUrl>
#include <QWindow> #include <QWindow>
AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
@ -40,16 +36,18 @@ namespace ShaderManagementConsole
setObjectName("ShaderManagementConsoleWindow"); setObjectName("ShaderManagementConsoleWindow");
m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true); m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true);
m_assetBrowser->SetOpenHandler([this](const AZStd::string& absolutePath) { m_assetBrowser->SetOpenHandler([this](const AZStd::string& absolutePath)
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{ {
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event( if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderSourceData::Extension) ||
m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath); AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
return; {
} AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
return;
}
QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str())); QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str()));
}); });
// Restore geometry and show the window // Restore geometry and show the window
mainWindowWrapper->showFromSettings(); mainWindowWrapper->showFromSettings();
@ -66,68 +64,18 @@ namespace ShaderManagementConsole
bool ShaderManagementConsoleWindow::GetOpenDocumentParams(AZStd::string& openPath) bool ShaderManagementConsoleWindow::GetOpenDocumentParams(AZStd::string& openPath)
{ {
openPath = QFileDialog::getOpenFileName( openPath = QFileDialog::getOpenFileName(
this, tr("Open Document"), AZ::Utils::GetProjectPath().c_str(), tr("Files (*.%1)").arg(AZ::RPI::ShaderVariantListSourceData::Extension)).toUtf8().constData(); this, tr("Open Document"), AZ::Utils::GetProjectPath().c_str(),
tr("Shader Files (*.%1);;Shader Variant List Files (*.%2)")
.arg(AZ::RPI::ShaderSourceData::Extension)
.arg(AZ::RPI::ShaderVariantListSourceData::Extension))
.toUtf8()
.constData();
return !openPath.empty(); return !openPath.empty();
} }
QWidget* ShaderManagementConsoleWindow::CreateDocumentTabView(const AZ::Uuid& documentId) QWidget* ShaderManagementConsoleWindow::CreateDocumentTabView(const AZ::Uuid& documentId)
{ {
AZStd::unordered_set<AZStd::string> optionNames; return new ShaderManagementConsoleTableView(m_toolId, documentId, centralWidget());
size_t shaderOptionCount = 0;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderOptionCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount);
for (size_t optionIndex = 0; optionIndex < shaderOptionCount; ++optionIndex)
{
AZ::RPI::ShaderOptionDescriptor shaderOptionDesc;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderOptionDesc, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor, optionIndex);
const char* optionName = shaderOptionDesc.GetName().GetCStr();
optionNames.insert(optionName);
}
size_t shaderVariantCount = 0;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderVariantCount, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount);
auto model = new QStandardItemModel();
model->setRowCount(static_cast<int>(shaderVariantCount));
model->setColumnCount(static_cast<int>(optionNames.size()));
int nameIndex = 0;
for (const auto& optionName : optionNames)
{
model->setHeaderData(nameIndex++, Qt::Horizontal, optionName.c_str());
}
for (int variantIndex = 0; variantIndex < shaderVariantCount; ++variantIndex)
{
AZ::RPI::ShaderVariantListSourceData::VariantInfo shaderVariantInfo;
ShaderManagementConsoleDocumentRequestBus::EventResult(
shaderVariantInfo, documentId, &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantInfo, variantIndex);
model->setHeaderData(variantIndex, Qt::Vertical, QString::number(variantIndex));
for (const auto& shaderOption : shaderVariantInfo.m_options)
{
AZ::Name optionName{ shaderOption.first };
AZ::Name optionValue{ shaderOption.second };
auto optionIt = optionNames.find(optionName.GetCStr());
int optionIndex = static_cast<int>(AZStd::distance(optionNames.begin(), optionIt));
QStandardItem* item = new QStandardItem(optionValue.GetCStr());
model->setItem(variantIndex, optionIndex, item);
}
}
// The document tab contains a table view.
auto contentWidget = new QTableView(centralWidget());
contentWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
contentWidget->setModel(model);
return contentWidget;
} }
} // namespace ShaderManagementConsole } // namespace ShaderManagementConsole

@ -8,16 +8,8 @@
#pragma once #pragma once
#if !defined(Q_MOC_RUN)
#include <Atom/RPI.Edit/Shader/ShaderVariantListSourceData.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h> #include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QStandardItemModel>
AZ_POP_DISABLE_WARNING
#endif
namespace ShaderManagementConsole namespace ShaderManagementConsole
{ {
//! ShaderManagementConsoleWindow is the main class. Its responsibility is limited to initializing and connecting //! ShaderManagementConsoleWindow is the main class. Its responsibility is limited to initializing and connecting

@ -11,6 +11,8 @@ set(FILES
Source/Document/ShaderManagementConsoleDocument.cpp Source/Document/ShaderManagementConsoleDocument.cpp
Source/Document/ShaderManagementConsoleDocument.h Source/Document/ShaderManagementConsoleDocument.h
Source/Window/ShaderManagementConsoleTableView.h
Source/Window/ShaderManagementConsoleTableView.cpp
Source/Window/ShaderManagementConsoleWindow.h Source/Window/ShaderManagementConsoleWindow.h
Source/Window/ShaderManagementConsoleWindow.cpp Source/Window/ShaderManagementConsoleWindow.cpp
Source/Window/ShaderManagementConsole.qrc Source/Window/ShaderManagementConsole.qrc
@ -18,6 +20,5 @@ set(FILES
Source/main.cpp Source/main.cpp
Source/ShaderManagementConsoleApplication.cpp Source/ShaderManagementConsoleApplication.cpp
Source/ShaderManagementConsoleApplication.h Source/ShaderManagementConsoleApplication.h
Source/ShaderManagementConsoleRequestBus.h
../Scripts/GenerateShaderVariantListForMaterials.py ../Scripts/GenerateShaderVariantListForMaterials.py
) )

@ -39,27 +39,15 @@ def main():
print("The input argument for the script is not a valid .shader file") print("The input argument for the script is not a valid .shader file")
return return
# Get info such as relative path of the file and asset id # prompt the user to save the file in the project folder or same folder as the shader
shaderAssetInfo = azlmbr.shadermanagementconsole.ShaderManagementConsoleRequestBus(
azlmbr.bus.Broadcast,
'GetSourceAssetInfo',
filename
)
# retrieves a list of all material source files that use the shader. Note that materials inherit from materialtype files, which are actual files that refer to shader files.
materialAssetIds = azlmbr.shadermanagementconsole.ShaderManagementConsoleRequestBus(
azlmbr.bus.Broadcast,
'FindMaterialAssetsUsingShader',
shaderAssetInfo.relativePath
)
msgBox = QtWidgets.QMessageBox( msgBox = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Question, QtWidgets.QMessageBox.Question,
"Choose Save Location for .shadervariantlist File", "Choose Save Location for .shadervariantlist File",
"Save .shadervariantlist file in Project folder or in the same folder as shader file?" "Save .shadervariantlist file in Project folder or in the same folder as shader file?"
) )
projectButton = msgBox.addButton("Project Folder", QtWidgets.QMessageBox.AcceptRole) projectButton = msgBox.addButton("Project Folder", QtWidgets.QMessageBox.AcceptRole)
msgBox.addButton("Same Folder as Shader", QtWidgets.QMessageBox.AcceptRole) shaderButton = msgBox.addButton("Same Folder as Shader", QtWidgets.QMessageBox.AcceptRole)
cancelButton = msgBox.addButton("Cancel", QtWidgets.QMessageBox.RejectRole) cancelButton = msgBox.addButton("Cancel", QtWidgets.QMessageBox.RejectRole)
msgBox.exec() msgBox.exec()
@ -69,80 +57,36 @@ def main():
elif msgBox.clickedButton() == cancelButton: elif msgBox.clickedButton() == cancelButton:
return return
# This loop collects all uniquely-identified shader items used by the materials based on its shader variant id. # open the shader file as a document which will generate all of the shader variant list data
shader_file = os.path.basename(filename) documentId = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
shaderVariantIds = [] azlmbr.bus.Broadcast,
shaderVariantListShaderOptionGroups = [] 'OpenDocument',
progressDialog = QtWidgets.QProgressDialog(f"Generating .shadervariantlist file for:\n{shader_file}", "Cancel", 0, len(materialAssetIds)) filename
progressDialog.setMaximumWidth(400) )
progressDialog.setMaximumHeight(100)
progressDialog.setModal(True) if documentId.IsNull():
progressDialog.setWindowTitle("Generating Shader Variant List") print("The shader source data file could not be opened")
for i, materialAssetId in enumerate(materialAssetIds): return
materialInstanceShaderItems = azlmbr.shadermanagementconsole.ShaderManagementConsoleRequestBus(azlmbr.bus.Broadcast, 'GetMaterialInstanceShaderItems', materialAssetId)
for shaderItem in materialInstanceShaderItems:
shaderAssetId = shaderItem.GetShaderAsset().get_id()
if shaderAssetInfo.assetId == shaderAssetId:
shaderVariantId = shaderItem.GetShaderVariantId()
if not shaderVariantId.IsEmpty():
# Check for repeat shader variant ids. We are using a list here
# instead of a set to check for duplicates on shaderVariantIds because
# shaderVariantId is not hashed by the ID like it is in the C++ side.
has_repeat = False
for variantId in shaderVariantIds:
if shaderVariantId == variantId:
has_repeat = True
break
if has_repeat:
continue
shaderVariantIds.append(shaderVariantId)
shaderVariantListShaderOptionGroups.append(shaderItem.GetShaderOptionGroup())
progressDialog.setValue(i)
if progressDialog.wasCanceled():
return
progressDialog.close()
# Generate the shader variant list data by collecting shader option name-value pairs.s
shaderVariantList = azlmbr.shader.ShaderVariantListSourceData()
shaderVariantList.shaderFilePath = shaderAssetInfo.relativePath
shaderVariants = []
stableId = 1
for shaderOptionGroup in shaderVariantListShaderOptionGroups:
variantInfo = azlmbr.shader.ShaderVariantInfo()
variantInfo.stableId = stableId
options = {}
shaderOptionDescriptors = shaderOptionGroup.GetShaderOptionDescriptors()
for shaderOptionDescriptor in shaderOptionDescriptors:
optionName = shaderOptionDescriptor.GetName()
optionValue = shaderOptionGroup.GetValueByOptionName(optionName)
if not optionValue.IsValid():
continue
valueName = shaderOptionDescriptor.GetValueName(optionValue)
options[optionName.ToString()] = valueName.ToString()
if len(options) != 0:
variantInfo.options = options
shaderVariants.append(variantInfo)
stableId += 1
shaderVariantList.shaderVariants = shaderVariants
# clean previously generated shader variant list file so they don't clash. # get the shader variant list data object which is only needed for the shader file path
pre, ext = os.path.splitext(shaderAssetInfo.relativePath) shaderVariantList = azlmbr.shadermanagementconsole.ShaderManagementConsoleDocumentRequestBus(
projectShaderVariantListFilePath = os.path.join(azlmbr.paths.projectroot, PROJECT_SHADER_VARIANTS_FOLDER, f'{pre}.shadervariantlist') azlmbr.bus.Event,
'GetShaderVariantListSourceData',
documentId
)
# generate the default save file path by replacing the extension of the open shader file
pre, ext = os.path.splitext(filename) pre, ext = os.path.splitext(filename)
defaultShaderVariantListFilePath = f'{pre}.shadervariantlist' defaultShaderVariantListFilePath = f'{pre}.shadervariantlist'
# clean previously generated shader variant list file so they don't clash.
pre, ext = os.path.splitext(shaderVariantList.shaderFilePath)
projectShaderVariantListFilePath = os.path.join(azlmbr.paths.projectroot, PROJECT_SHADER_VARIANTS_FOLDER, f'{pre}.shadervariantlist')
clean_existing_shadervariantlist_files([ clean_existing_shadervariantlist_files([
projectShaderVariantListFilePath projectShaderVariantListFilePath
]) ])
# Save the shader variant list file # Save the shader variant list file
if is_save_in_project_folder: if is_save_in_project_folder:
shaderVariantListFilePath = projectShaderVariantListFilePath shaderVariantListFilePath = projectShaderVariantListFilePath
@ -150,16 +94,16 @@ def main():
shaderVariantListFilePath = defaultShaderVariantListFilePath shaderVariantListFilePath = defaultShaderVariantListFilePath
shaderVariantListFilePath = shaderVariantListFilePath.replace("\\", "/") shaderVariantListFilePath = shaderVariantListFilePath.replace("\\", "/")
azlmbr.shader.SaveShaderVariantListSourceData(shaderVariantListFilePath, shaderVariantList)
# Open the document in shader management console # Save the document in shader management console
result = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus( saveResult = azlmbr.atomtools.AtomToolsDocumentSystemRequestBus(
azlmbr.bus.Broadcast, azlmbr.bus.Broadcast,
'OpenDocument', 'SaveDocumentAsChild',
documentId,
shaderVariantListFilePath shaderVariantListFilePath
) )
if not result.IsNull(): if saveResult:
msgBox = QtWidgets.QMessageBox( msgBox = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information, QtWidgets.QMessageBox.Information,
"Shader Variant List File Successfully Generated", "Shader Variant List File Successfully Generated",

Loading…
Cancel
Save