diff --git a/Gems/Prefab/PrefabBuilder/PrefabGroup/ProceduralAssetHandler.cpp b/Gems/Prefab/PrefabBuilder/PrefabGroup/ProceduralAssetHandler.cpp index 17ed4d9c0c..bcfedad8a8 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabGroup/ProceduralAssetHandler.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabGroup/ProceduralAssetHandler.cpp @@ -8,12 +8,16 @@ #include #include +#include #include #include -#include +#include +#include +#include #include +#include #include -#include +#include namespace AZ::Prefab { @@ -21,6 +25,7 @@ namespace AZ::Prefab class PrefabGroupAssetHandler::AssetTypeInfoHandler final : public AZ::AssetTypeInfoBus::Handler + , protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler { public: AZ_CLASS_ALLOCATOR(AssetTypeInfoHandler, AZ::SystemAllocator, 0); @@ -31,15 +36,21 @@ namespace AZ::Prefab const char* GetGroup() const override; const char* GetBrowserIcon() const override; void GetAssetTypeExtensions(AZStd::vector& extensions) override; + + // AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) override; + bool SaveAsAuthoredPrefab(const AZ::Data::AssetId& assetId, const char* destinationFilename); }; PrefabGroupAssetHandler::AssetTypeInfoHandler::AssetTypeInfoHandler() { AZ::AssetTypeInfoBus::Handler::BusConnect(azrtti_typeid()); + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); } PrefabGroupAssetHandler::AssetTypeInfoHandler::~AssetTypeInfoHandler() { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); AZ::AssetTypeInfoBus::Handler::BusDisconnect(azrtti_typeid()); } @@ -68,6 +79,84 @@ namespace AZ::Prefab extensions.push_back(PrefabGroupAssetHandler::s_Extension); } + void PrefabGroupAssetHandler::AssetTypeInfoHandler::AddContextMenuActions( + [[maybe_unused]] QWidget* caller, + QMenu* menu, + const AZStd::vector& entries) + { + using namespace AzToolsFramework::AssetBrowser; + auto entryIt = AZStd::find_if + ( + entries.begin(), + entries.end(), + [](const AssetBrowserEntry* entry) -> bool + { + return entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product; + } + ); + + if (entryIt == entries.end()) + { + return; + } + else if ((*entryIt)->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product) + { + ProductAssetBrowserEntry* product = azrtti_cast(*entryIt); + if (product->GetAssetType() == azrtti_typeid()) + { + AZ::Data::AssetId assetId = product->GetAssetId(); + menu->addAction("Save as Prefab...", [assetId, this]() + { + QString filePath = AzQtComponents::FileDialog::GetSaveFileName(nullptr, QString("Save to file"), "", QString("Prefab file (*.prefab)")); + if (filePath.isEmpty()) + { + return; + } + if (SaveAsAuthoredPrefab(assetId, filePath.toUtf8().data())) + { + AZ_Printf("Prefab", "Prefab was saved to a .prefab file %s", filePath.toUtf8().data()); + } + }); + } + } + } + + bool PrefabGroupAssetHandler::AssetTypeInfoHandler::SaveAsAuthoredPrefab(const AZ::Data::AssetId& assetId, const char* destinationFilename) + { + using namespace AzToolsFramework::Prefab; + using namespace AZ::Data; + + auto procPrefabAsset = AssetManager::Instance().GetAsset(assetId, AssetLoadBehavior::Default); + const auto status = AssetManager::Instance().BlockUntilLoadComplete(procPrefabAsset); + if (status != AssetData::AssetStatus::Ready) + { + return false; + } + + auto* prefabLoaderInterface = AZ::Interface::Get(); + if (!prefabLoaderInterface) + { + return false; + } + + const auto templateId = procPrefabAsset.GetAs()->GetTemplateId(); + AZStd::string outputJson; + if (prefabLoaderInterface->SaveTemplateToString(templateId, outputJson) == false) + { + return false; + } + + const auto fileMode = AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath | AZ::IO::OpenMode::ModeText; + AZ::IO::FileIOStream outputFileStream; + if (outputFileStream.Open(destinationFilename, fileMode) == false) + { + return false; + } + + outputFileStream.Write(outputJson.size(), outputJson.data()); + return true; + } + // PrefabGroupAssetHandler AZStd::string_view PrefabGroupAssetHandler::s_Extension{ "procprefab" };