From 7a83950f5929c0ff6ee9c9df5a5658b9db37831a Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Fri, 20 Aug 2021 11:14:56 -0700 Subject: [PATCH 01/17] Initial draft for save all prefabs workflow Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 95 +++++++++++ Code/Editor/CryEditDoc.cpp | 160 ++++++++++++++++-- Code/Editor/EditorPreferencesPageGeneral.cpp | 19 +++ Code/Editor/EditorPreferencesPageGeneral.h | 8 + Code/Editor/Settings.cpp | 24 ++- Code/Editor/Settings.h | 10 ++ Code/Editor/Style/Editor.qss | 24 +++ .../PrefabEditorEntityOwnershipInterface.h | 8 + .../PrefabEditorEntityOwnershipService.cpp | 21 +++ .../PrefabEditorEntityOwnershipService.h | 3 + .../Prefab/PrefabSystemComponent.cpp | 11 ++ .../Prefab/PrefabSystemComponent.h | 2 + .../Prefab/PrefabSystemComponentInterface.h | 1 + 13 files changed, 373 insertions(+), 13 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 280613815e..af7151a633 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -33,6 +33,9 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include +#include +#include // Aws Native SDK #include @@ -68,10 +71,12 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include // AzQtComponents #include +#include #include #include #include @@ -724,6 +729,96 @@ void CCryEditApp::OnFileSave() const QScopedValueRollback rollback(m_savingLevel, true); GetIEditor()->GetDocument()->DoFileSave(); + + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + + if (usePrefabSystemForLevels) + { + auto prefabSystemComponentInterface = AZ::Interface::Get(); + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + } + else if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::Unspecified) + { + QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox.setObjectName("SaveAllPrefabsDialog"); + QBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); + + QFrame* levelSavedMessageFrame = new QFrame(&saveModifiedMessageBox); + QHBoxLayout* levelSavedMessageLayout = new QHBoxLayout(&saveModifiedMessageBox); + levelSavedMessageFrame->setObjectName("LevelSavedMessageFrame"); + QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); + QLabel* levelSavedSuccessfullyIcon = new QLabel(); + levelSavedSuccessfullyIcon->setPixmap(checkMarkIcon); + levelSavedSuccessfullyIcon->setFixedWidth(checkMarkIcon.width()); + QLabel* levelSavedSuccessfullyLabel = new QLabel("All entities inside level have been saved successfully."); + levelSavedSuccessfullyLabel->setObjectName("LevelSavedSuccessfullyLabel"); + levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIcon); + levelSavedMessageLayout->addWidget(levelSavedSuccessfullyLabel); + levelSavedMessageFrame->setLayout(levelSavedMessageLayout); + + QFrame* prefabSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); + QHBoxLayout* prefabSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); + QLabel* warningIconContainer = new QLabel(); + QPixmap warningIcon(QString(":/Cards/img/UI20/Cards/warning.svg")); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + prefabSaveQuestionLayout->addWidget(warningIconContainer); + QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save all unsaved prefabs?"); + prefabSaveQuestionFrame->setObjectName("PrefabSaveQuestionFrame"); + prefabSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); + prefabSaveQuestionFrame->setLayout(prefabSaveQuestionLayout); + + contentLayout->addWidget(levelSavedMessageFrame); + contentLayout->addWidget(prefabSaveQuestionFrame); + + QFrame* footerSeparatorLine = new QFrame(); + footerSeparatorLine->setObjectName("FooterSeparatorLine"); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); + QCheckBox* saveAllPrefabsPreference = new QCheckBox("Remember my preference."); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreference); + QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); + footerPreferenceLayout->addWidget(saveAllPrefabsPreference); + QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit->GlobalPreferences."); + prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + footerPreferenceLayout->addWidget(prefabSavePreferenceHint); + footerLayout->addLayout(footerPreferenceLayout); + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); + footerLayout->addWidget(prefabSaveConfirmationButtons); + + contentLayout->addLayout(footerLayout); + + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); + + int prefabSaveSelection = saveModifiedMessageBox.exec(); + switch (prefabSaveSelection) + { + case QDialog::Accepted: + if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveAll); + } + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + break; + case QDialog::Rejected: + if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveNone); + } + break; + } + } + } } diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index e5988918f5..1eb0a5c0b8 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -13,6 +13,10 @@ // Qt #include +#include +#include +#include +#include // AzCore #include @@ -31,6 +35,7 @@ #include #include #include +#include // Editor #include "Settings.h" @@ -664,19 +669,116 @@ bool CCryEditDoc::SaveModified() return true; } - auto button = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - switch (button) + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (usePrefabSystemForLevels) { - case QMessageBox::Cancel: - return false; - case QMessageBox::Yes: - return DoFileSave(); - case QMessageBox::No: - SetModifiedFlag(false); - return true; + auto prefabSystemComponentInterface = AZ::Interface::Get(); + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + + QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox.setObjectName("SaveDirtyLevelDialog"); + + QVBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); + QFrame* levelEntitiesSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); + QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); + levelEntitiesSaveQuestionFrame->setObjectName("LevelEntitiesSaveQuestionFrame"); + QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); + + levelEntitiesSaveQuestionFrame->setLayout(levelEntitiesSaveQuestionLayout); + QPixmap warningIcon(QString(":/Cards/img/UI20/Cards/warning.svg")); + QLabel* warningIconContainer = new QLabel(); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); + levelEntitiesSaveQuestionLayout->addWidget(levelEntitiesSaveQuestionLabel); + contentLayout->addWidget(levelEntitiesSaveQuestionFrame); + + QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); + saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); + QObject::connect( + saveAllPrefabsCheckbox, &QCheckBox::stateChanged, + [&savePrefabsPreference](int state) + { + savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked + ? AzToolsFramework::SavePrefabsPreference::SaveAll + : AzToolsFramework::SavePrefabsPreference::SaveNone; + }); + contentLayout->addWidget(saveAllPrefabsCheckbox); + QFrame* footerSeparatorLine = new QFrame(); + footerSeparatorLine->setObjectName("FooterSeparatorLine"); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); + QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + saveAllPrefabsPreferenceCheckBox->setCheckState(Qt::CheckState::Checked); + saveAllPrefabsCheckbox->setCheckState(Qt::CheckState::Checked); + } + QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); + footerPreferenceLayout->addWidget(saveAllPrefabsPreferenceCheckBox); + QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); + prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + footerPreferenceLayout->addWidget(prefabSavePreferenceHint); + footerLayout->addLayout(footerPreferenceLayout); + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel); + footerLayout->addWidget(prefabSaveConfirmationButtons); + + contentLayout->addLayout(footerLayout); + + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); + + int prefabSaveSelection = saveModifiedMessageBox.exec(); + + if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(savePrefabsPreference); + prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference(savePrefabsPreference); + } + + switch (prefabSaveSelection) + { + case QDialog::Accepted: + DoFileSave(); + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + } + return true; + case QDialog::Rejected: + return false; + } + Q_UNREACHABLE(); + } + else + { + QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox.setText(QString("Save changes to %1?").arg(GetTitle())); + saveModifiedMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + saveModifiedMessageBox.setIcon(QMessageBox::Icon::Question); + + auto button = QMessageBox::question( + AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + switch (button) + { + case QMessageBox::Cancel: + return false; + case QMessageBox::Yes: + return DoFileSave(); + case QMessageBox::No: + SetModifiedFlag(false); + return true; + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); } void CCryEditDoc::OnFileSaveAs() @@ -1258,6 +1360,42 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (openResult) { AZ::IO::FileIOStream stream(tempSaveFileHandle, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, false); + //SaveAllPrefabsDialog dlg(MainWindow::instance()); + //dlg.exec(); + /* + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = + prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::Unspecified && !m_modified) + { + QMessageBox prefabSavePreferenceBox(AzToolsFramework::GetActiveWindow()); + prefabSavePreferenceBox.setText(QString("Save all prefabs in %1?").arg(GetTitle())); + prefabSavePreferenceBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + QCheckBox* checkbox = new QCheckBox("Remember my preference."); + prefabSavePreferenceBox.setCheckBox(checkbox); + prefabSavePreferenceBox.checkBox(); + int button = prefabSavePreferenceBox.exec(); + switch (button) + { + case QMessageBox::Yes: + if (checkbox->checkState() == Qt::CheckState::Checked) + { + prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference( + AzToolsFramework::SavePrefabsPreference::SaveAll); + gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveAll); + } + prefabEditorEntityOwnershipInterface->SetSaveAllPrefabs(true); + break; + case QMessageBox::No: + if (checkbox->checkState() == Qt::CheckState::Checked) + { + prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference( + AzToolsFramework::SavePrefabsPreference::SaveNone); + gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveNone); + } + prefabEditorEntityOwnershipInterface->SetSaveAllPrefabs(false); + break; + } + }*/ contentsAllSaved = prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); stream.Close(); } diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 79ecfbdfc7..f11659576b 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -42,6 +42,10 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector) ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera); + serialize.Class() + ->Version(1) + ->Field("SavePrefabsPreference", &PrefabSettings::m_savePrefabsPreference); + serialize.Class() ->Version(2) ->Field("ShowDashboard", &Messaging::m_showDashboard) @@ -64,6 +68,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) serialize.Class() ->Version(1) ->Field("General Settings", &CEditorPreferencesPage_General::m_generalSettings) + ->Field("Prefab Settings", &CEditorPreferencesPage_General::m_prefabSettings) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) @@ -92,6 +97,13 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); + editContext->Class("Prefabs", "") + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &PrefabSettings::m_savePrefabsPreference, "Save Prefabs Preference","Save Prefabs Preference") + ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::Unspecified, "Unspecified") + ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveAll, "Save All") + ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveNone, "Save None"); + editContext->Class("Messaging", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showCircularDependencyError, "Show Error: Circular dependency", "Show an error message when adding a slice instance to the target slice would create a cyclic asset dependency. All other valid overrides will be saved even if this is turned off."); @@ -115,6 +127,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_prefabSettings, "Prefabs", "Prefab Settings") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") @@ -161,6 +174,9 @@ void CEditorPreferencesPage_General::OnApply() MainWindow::instance()->AdjustToolBarIconSize(m_generalSettings.m_toolbarIconSize); } + //prefabs + gSettings.prefabSettings.savePrefabsPreference = m_prefabSettings.m_savePrefabsPreference; + //undo gSettings.undoLevels = m_undo.m_undoLevels; @@ -190,6 +206,9 @@ void CEditorPreferencesPage_General::InitializeSettings() m_generalSettings.m_toolbarIconSize = static_cast(gSettings.gui.nToolbarIconSize); + //prefabs + m_prefabSettings.m_savePrefabsPreference = gSettings.prefabSettings.savePrefabsPreference; + //Messaging m_messaging.m_showDashboard = gSettings.bShowDashboardAtStartup; m_messaging.m_showCircularDependencyError = gSettings.m_showCircularDependencyError; diff --git a/Code/Editor/EditorPreferencesPageGeneral.h b/Code/Editor/EditorPreferencesPageGeneral.h index 9a3a0f21e8..29dcefcb80 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Editor/EditorPreferencesPageGeneral.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "Settings.h" @@ -57,6 +58,12 @@ private: bool m_enableSceneInspector; }; + struct PrefabSettings + { + AZ_TYPE_INFO(PrefabSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); + AzToolsFramework::SavePrefabsPreference m_savePrefabsPreference; + }; + struct Messaging { AZ_TYPE_INFO(Messaging, "{A6AD87CB-E905-409B-A2BF-C43CDCE63B0C}") @@ -89,6 +96,7 @@ private: }; GeneralSettings m_generalSettings; + PrefabSettings m_prefabSettings; Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 8672bad5c4..0197a45cfa 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -255,6 +255,7 @@ SEditorSettings::SEditorSettings() g_TemporaryLevelName = nullptr; sliceSettings.dynamicByDefault = false; + prefabSettings.savePrefabsPreference = AzToolsFramework::SavePrefabsPreference::Unspecified; } void SEditorSettings::Connect() @@ -669,12 +670,20 @@ void SEditorSettings::Save() AzFramework::ApplicationRequests::Bus::Broadcast( &AzFramework::ApplicationRequests::SetPrefabSystemEnabled, prefabSystem); + AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipService = + AZ::Interface::Get(); + prefabEditorEntityOwnershipService->SetSavePrefabsPreference(prefabSettings.savePrefabsPreference); + SaveSettingsRegistryFile(); } ////////////////////////////////////////////////////////////////////////// void SEditorSettings::Load() { + AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipService = + AZ::Interface::Get(); + prefabSettings.savePrefabsPreference = prefabEditorEntityOwnershipService->GetSavePrefabsPreference(); + // Load from Settings Registry AzFramework::ApplicationRequests::Bus::BroadcastResult( prefabSystem, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); @@ -1073,6 +1082,11 @@ void SEditorSettings::ConvertPath(const AZStd::string_view sourcePath, AZStd::st AZStd::replace(category.begin(), category.end(), '|', '\\'); } +void SEditorSettings::SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference savePrefabsPreference) +{ + prefabSettings.savePrefabsPreference = savePrefabsPreference; +} + AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome SEditorSettings::GetValue(const AZStd::string_view path) { if (path.find("|") == AZStd::string_view::npos) @@ -1148,11 +1162,17 @@ void SEditorSettings::SaveSettingsRegistryFile() AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; dumperSettings.m_prettifyOutput = true; - dumperSettings.m_jsonPointerPrefix = "/Amazon/Preferences"; + dumperSettings.m_includeFilter = [](AZStd::string_view path) + { + AZStd::string_view amazonPrefixPath("/Amazon/Preferences"); + AZStd::string_view o3dePrefixPath("/O3DE/Preferences"); + return amazonPrefixPath.starts_with(path.substr(0, amazonPrefixPath.size())) || + o3dePrefixPath.starts_with(path.substr(0, o3dePrefixPath.size())); + }; AZStd::string stringBuffer; AZ::IO::ByteContainerStream stringStream(&stringBuffer); - if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "/Amazon/Preferences", stringStream, dumperSettings)) + if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "", stringStream, dumperSettings)) { AZ_Warning("SEditorSettings", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)", editorPreferencesFilePath.c_str()); diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index 51931ab955..72e6a54032 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -230,6 +231,11 @@ struct SSliceSettings bool dynamicByDefault; }; +struct SPrefabSettings +{ + AzToolsFramework::SavePrefabsPreference savePrefabsPreference; +}; + ////////////////////////////////////////////////////////////////////////// struct SAssetBrowserSettings { @@ -466,8 +472,12 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING SSliceSettings sliceSettings; + SPrefabSettings prefabSettings; + bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities. + void SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference savePrefabsPreference); + private: void SaveValue(const char* sSection, const char* sKey, int value); void SaveValue(const char* sSection, const char* sKey, const QColor& value); diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index b900dbeff3..e1b790ed0c 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -244,3 +244,27 @@ QTableWidget#recentLevelTable::item { max-height: 16px; qproperty-iconSize: 16px 16px; } + +#LevelSavedMessageFrame{ + border: 1px solid green; + border-radius: 2px; + margin: 5px 20px 5px 20px; + padding: 5px 2px 5px 2px; +} + +#SaveAllPrefabsDialog #PrefabSaveQuestionFrame, #SaveDirtyLevelDialog #LevelEntitiesSaveQuestionFrame, #SaveAllPrefabsCheckbox{ + border: 1px solid orange; + border-radius: 2px; + margin: 5px 20px 5px 20px; + padding: 5px 2px 5px 2px; + color : white; +} + +#SaveAllPrefabsDialog #FooterSeparatorLine, #SaveDirtyLevelDialog #FooterSeparatorLine{ + color: gray; +} + +#SaveAllPrefabsDialog #PrefabSavePreferenceHint, #SaveDirtyLevelDialog #PrefabSavePreferenceHint{ + font: italic; + color: #999999; +} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index 1cd36e8055..f26f80ca10 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -18,6 +18,12 @@ namespace AzToolsFramework { + enum class SavePrefabsPreference : AZ::s64 + { + Unspecified = 0, + SaveAll = 1, + SaveNone = -1 + }; class PrefabEditorEntityOwnershipInterface { @@ -54,5 +60,7 @@ namespace AzToolsFramework virtual void StopPlayInEditor() = 0; virtual void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) = 0; + virtual SavePrefabsPreference GetSavePrefabsPreference() = 0; + virtual void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) = 0; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 7df1e1b5c1..bd8bf28de2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,8 @@ namespace AzToolsFramework { + static constexpr const char s_savePrefabsKey[] = "/O3DE/Preferences/SavePrefabs"; + PrefabEditorEntityOwnershipService::PrefabEditorEntityOwnershipService(const AzFramework::EntityContextId& entityContextId, AZ::SerializeContext* serializeContext) : m_entityContextId(entityContextId) @@ -607,6 +610,24 @@ namespace AzToolsFramework m_playInEditorData.m_isEnabled = false; } + SavePrefabsPreference PrefabEditorEntityOwnershipService::GetSavePrefabsPreference() + { + AZ::s64 savePrefabsPreference = static_cast(SavePrefabsPreference::Unspecified); + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->Get(savePrefabsPreference, s_savePrefabsKey); + } + return static_cast(savePrefabsPreference); + } + + void PrefabEditorEntityOwnershipService::SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) + { + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->Set(s_savePrefabsKey, static_cast(savePrefabsPreference)); + } + } + ////////////////////////////////////////////////////////////////////////// // Slice Buses implementation with Assert(false), this will exist only during Slice->Prefab // development to pinpoint and replace specific calls to Slice system diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index bf1199d6dd..e94c955061 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -168,6 +168,9 @@ namespace AzToolsFramework void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) override; + SavePrefabsPreference GetSavePrefabsPreference() override; + void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) override; + protected: AZ::SliceComponent::SliceInstanceAddress GetOwningSlice() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 1051e530c8..31f5816bfc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -753,6 +753,17 @@ namespace AzToolsFramework } } + void PrefabSystemComponent::SaveAllDirtyTemplates() + { + for (auto& [id, templateObject] : m_templateIdMap) + { + if (IsTemplateDirty(id)) + { + m_prefabLoader.SaveTemplate(id); + } + } + } + bool PrefabSystemComponent::ConnectTemplates( Link& link, TemplateId sourceTemplateId, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index b07ccbada6..3539a79d54 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -183,6 +183,8 @@ namespace AzToolsFramework */ void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override; + void SaveAllDirtyTemplates() override; + ////////////////////////////////////////////////////////////////////////// /** diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 0c758a21af..bcea8a8b2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -49,6 +49,7 @@ namespace AzToolsFramework virtual bool IsTemplateDirty(const TemplateId& templateId) = 0; virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; + virtual void SaveAllDirtyTemplates() = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; From c20ec14af793bbbbc950b8a1b704dc9b742ee705 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Fri, 20 Aug 2021 13:37:38 -0700 Subject: [PATCH 02/17] Added comments and did some code clean up Changes in this commit: - Added comments to dialog code in CryEdit.cpp and CryEditDoc.cpp - Moved Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/Cards/warning.svg to Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/warning.svg - Improved the hover message over prefab settings in EditorPreferencesPageGeneral.cpp - Fixed a syntax error in Editor.qss Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 32 +++--- Code/Editor/CryEditDoc.cpp | 99 +++++++------------ Code/Editor/EditorPreferencesPageGeneral.cpp | 3 +- Code/Editor/Settings.h | 2 +- Code/Editor/Style/Editor.qss | 9 +- .../Components/Widgets/Card.cpp | 2 +- .../AzQtComponents/Components/resources.qrc | 1 - .../Notifications}/warning.svg | 0 .../AzQtComponents/Images/resources.qrc | 1 + 9 files changed, 67 insertions(+), 82 deletions(-) rename Code/Framework/AzQtComponents/AzQtComponents/{Components/img/UI20/Cards => Images/Notifications}/warning.svg (100%) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index af7151a633..9b46f99e16 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -747,55 +747,65 @@ void CCryEditApp::OnFileSave() else if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::Unspecified) { QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + + // Main Content section begins. saveModifiedMessageBox.setObjectName("SaveAllPrefabsDialog"); QBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); - QFrame* levelSavedMessageFrame = new QFrame(&saveModifiedMessageBox); QHBoxLayout* levelSavedMessageLayout = new QHBoxLayout(&saveModifiedMessageBox); levelSavedMessageFrame->setObjectName("LevelSavedMessageFrame"); + + // Add a checkMark icon next to the level entities saved message. QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); - QLabel* levelSavedSuccessfullyIcon = new QLabel(); - levelSavedSuccessfullyIcon->setPixmap(checkMarkIcon); - levelSavedSuccessfullyIcon->setFixedWidth(checkMarkIcon.width()); + QLabel* levelSavedSuccessfullyIconContainer = new QLabel(); + levelSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); + levelSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); + + // Add a message that level entities are saved successfully. QLabel* levelSavedSuccessfullyLabel = new QLabel("All entities inside level have been saved successfully."); levelSavedSuccessfullyLabel->setObjectName("LevelSavedSuccessfullyLabel"); - levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIcon); + levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIconContainer); levelSavedMessageLayout->addWidget(levelSavedSuccessfullyLabel); levelSavedMessageFrame->setLayout(levelSavedMessageLayout); + QFrame* prefabSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); QHBoxLayout* prefabSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); + + // Add a warning icon next to prefabs save question. QLabel* warningIconContainer = new QLabel(); - QPixmap warningIcon(QString(":/Cards/img/UI20/Cards/warning.svg")); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); warningIconContainer->setPixmap(warningIcon); warningIconContainer->setFixedWidth(warningIcon.width()); prefabSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask if user wants all prefabs saved. QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save all unsaved prefabs?"); prefabSaveQuestionFrame->setObjectName("PrefabSaveQuestionFrame"); prefabSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); prefabSaveQuestionFrame->setLayout(prefabSaveQuestionLayout); - contentLayout->addWidget(levelSavedMessageFrame); contentLayout->addWidget(prefabSaveQuestionFrame); - + + // Footer section begins. QFrame* footerSeparatorLine = new QFrame(); footerSeparatorLine->setObjectName("FooterSeparatorLine"); footerSeparatorLine->setFrameShape(QFrame::HLine); contentLayout->addWidget(footerSeparatorLine); QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); + + // Provide option for user to remember their prefab save preference. QCheckBox* saveAllPrefabsPreference = new QCheckBox("Remember my preference."); AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreference); QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); footerPreferenceLayout->addWidget(saveAllPrefabsPreference); - QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit->GlobalPreferences."); + QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); footerPreferenceLayout->addWidget(prefabSavePreferenceHint); footerLayout->addLayout(footerPreferenceLayout); QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 1eb0a5c0b8..37a5750e1f 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -672,7 +672,29 @@ bool CCryEditDoc::SaveModified() bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); - if (usePrefabSystemForLevels) + if (!usePrefabSystemForLevels) + { + QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox.setText(QString("Save changes to %1?").arg(GetTitle())); + saveModifiedMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + saveModifiedMessageBox.setIcon(QMessageBox::Icon::Question); + + auto button = QMessageBox::question( + AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + switch (button) + { + case QMessageBox::Cancel: + return false; + case QMessageBox::Yes: + return DoFileSave(); + case QMessageBox::No: + SetModifiedFlag(false); + return true; + } + Q_UNREACHABLE(); + } + else { auto prefabSystemComponentInterface = AZ::Interface::Get(); auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); @@ -681,21 +703,26 @@ bool CCryEditDoc::SaveModified() QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); saveModifiedMessageBox.setObjectName("SaveDirtyLevelDialog"); + // Main Content section begins. QVBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); QFrame* levelEntitiesSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); levelEntitiesSaveQuestionFrame->setObjectName("LevelEntitiesSaveQuestionFrame"); - QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); - + + // Add a warning icon next to save entities question. levelEntitiesSaveQuestionFrame->setLayout(levelEntitiesSaveQuestionLayout); - QPixmap warningIcon(QString(":/Cards/img/UI20/Cards/warning.svg")); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); QLabel* warningIconContainer = new QLabel(); warningIconContainer->setPixmap(warningIcon); warningIconContainer->setFixedWidth(warningIcon.width()); levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask user if they want to save entities in level. + QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); levelEntitiesSaveQuestionLayout->addWidget(levelEntitiesSaveQuestionLabel); contentLayout->addWidget(levelEntitiesSaveQuestionFrame); + // Ask user if they want to save unsaved prefabs in the level too. QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); @@ -708,11 +735,15 @@ bool CCryEditDoc::SaveModified() : AzToolsFramework::SavePrefabsPreference::SaveNone; }); contentLayout->addWidget(saveAllPrefabsCheckbox); + + // Footer section begins. QFrame* footerSeparatorLine = new QFrame(); footerSeparatorLine->setObjectName("FooterSeparatorLine"); footerSeparatorLine->setFrameShape(QFrame::HLine); contentLayout->addWidget(footerSeparatorLine); QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); + + // Provide option for user to remember their prefab save preference. QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) @@ -728,9 +759,7 @@ bool CCryEditDoc::SaveModified() footerLayout->addLayout(footerPreferenceLayout); QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel); footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); @@ -757,28 +786,6 @@ bool CCryEditDoc::SaveModified() } Q_UNREACHABLE(); } - else - { - QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); - saveModifiedMessageBox.setText(QString("Save changes to %1?").arg(GetTitle())); - saveModifiedMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - saveModifiedMessageBox.setIcon(QMessageBox::Icon::Question); - - auto button = QMessageBox::question( - AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - switch (button) - { - case QMessageBox::Cancel: - return false; - case QMessageBox::Yes: - return DoFileSave(); - case QMessageBox::No: - SetModifiedFlag(false); - return true; - } - Q_UNREACHABLE(); - } } void CCryEditDoc::OnFileSaveAs() @@ -1360,42 +1367,6 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (openResult) { AZ::IO::FileIOStream stream(tempSaveFileHandle, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, false); - //SaveAllPrefabsDialog dlg(MainWindow::instance()); - //dlg.exec(); - /* - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = - prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::Unspecified && !m_modified) - { - QMessageBox prefabSavePreferenceBox(AzToolsFramework::GetActiveWindow()); - prefabSavePreferenceBox.setText(QString("Save all prefabs in %1?").arg(GetTitle())); - prefabSavePreferenceBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - QCheckBox* checkbox = new QCheckBox("Remember my preference."); - prefabSavePreferenceBox.setCheckBox(checkbox); - prefabSavePreferenceBox.checkBox(); - int button = prefabSavePreferenceBox.exec(); - switch (button) - { - case QMessageBox::Yes: - if (checkbox->checkState() == Qt::CheckState::Checked) - { - prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference( - AzToolsFramework::SavePrefabsPreference::SaveAll); - gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveAll); - } - prefabEditorEntityOwnershipInterface->SetSaveAllPrefabs(true); - break; - case QMessageBox::No: - if (checkbox->checkState() == Qt::CheckState::Checked) - { - prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference( - AzToolsFramework::SavePrefabsPreference::SaveNone); - gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveNone); - } - prefabEditorEntityOwnershipInterface->SetSaveAllPrefabs(false); - break; - } - }*/ contentsAllSaved = prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); stream.Close(); } diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index f11659576b..08703ba6cc 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -99,7 +99,8 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) editContext->Class("Prefabs", "") ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &PrefabSettings::m_savePrefabsPreference, "Save Prefabs Preference","Save Prefabs Preference") + AZ::Edit::UIHandlers::ComboBox, &PrefabSettings::m_savePrefabsPreference, "Save Prefabs Preference", + "When saving levels, this option controls whether and how prefabs should be saved along with the level.") ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::Unspecified, "Unspecified") ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveAll, "Save All") ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveNone, "Save None"); diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index 72e6a54032..61f89a8a05 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index e1b790ed0c..2999eb388f 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -252,7 +252,8 @@ QTableWidget#recentLevelTable::item { padding: 5px 2px 5px 2px; } -#SaveAllPrefabsDialog #PrefabSaveQuestionFrame, #SaveDirtyLevelDialog #LevelEntitiesSaveQuestionFrame, #SaveAllPrefabsCheckbox{ +#SaveAllPrefabsDialog #PrefabSaveQuestionFrame, #SaveDirtyLevelDialog #LevelEntitiesSaveQuestionFrame, #SaveAllPrefabsCheckbox +{ border: 1px solid orange; border-radius: 2px; margin: 5px 20px 5px 20px; @@ -260,11 +261,13 @@ QTableWidget#recentLevelTable::item { color : white; } -#SaveAllPrefabsDialog #FooterSeparatorLine, #SaveDirtyLevelDialog #FooterSeparatorLine{ +#SaveAllPrefabsDialog #FooterSeparatorLine, #SaveDirtyLevelDialog #FooterSeparatorLine +{ color: gray; } -#SaveAllPrefabsDialog #PrefabSavePreferenceHint, #SaveDirtyLevelDialog #PrefabSavePreferenceHint{ +#SaveAllPrefabsDialog #PrefabSavePreferenceHint, #SaveDirtyLevelDialog #PrefabSavePreferenceHint +{ font: italic; color: #999999; } diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp index a4ab3c5e5d..b4fd74dd25 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp @@ -347,7 +347,7 @@ namespace AzQtComponents config.toolTipPaddingInPixels = 5; config.headerIconSizeInPixels = CardHeader::defaultIconSize(); config.rootLayoutSpacing = 0; - config.warningIcon = QStringLiteral(":/Cards/img/UI20/Cards/warning.svg"); + config.warningIcon = QStringLiteral(":/Notifications/warning.svg"); config.warningIconSize = {24, 24}; config.disabledIconAlpha = 0.25; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc index 909510d63b..7321128b57 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc @@ -424,7 +424,6 @@ img/UI20/Cards/menu_ico.png img/UI20/Cards/error_icon.png img/UI20/Cards/warning.png - img/UI20/Cards/warning.svg img/UI20/Cards/search.png img/UI20/Cards/close.png img/UI20/Cards/error-conclict-state.svg diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/Cards/warning.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/warning.svg similarity index 100% rename from Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/Cards/warning.svg rename to Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/warning.svg diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc index c72687359b..0c8fedc79d 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc @@ -30,6 +30,7 @@ Notifications/checkmark.svg Notifications/download.svg Notifications/link.svg + Notifications/warning.svg Outliner/sort_a_to_z.svg From 79dd041d024b08eddc0319889bc8a2eda99dbd31 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 24 Aug 2021 17:22:50 -0700 Subject: [PATCH 03/17] Add helper methods to create and execute save level dialogs Changes in this commit : - Added AreDirtyTemplatesPresent() method to PrefabSystemComponentInterface - Added ConstructSaveLevelDialog() helper method to create the save level dialog - Added ExecuteSavePrefabsDialog() helper method to create and execute the save prefabs dialog Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 176 ++++------- Code/Editor/CryEditDoc.cpp | 297 +++++++++++++----- Code/Editor/CryEditDoc.h | 6 + .../Prefab/PrefabSystemComponent.cpp | 12 + .../Prefab/PrefabSystemComponent.h | 2 + .../Prefab/PrefabSystemComponentInterface.h | 1 + 6 files changed, 308 insertions(+), 186 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 9b46f99e16..6e921833cb 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -736,98 +736,7 @@ void CCryEditApp::OnFileSave() if (usePrefabSystemForLevels) { - auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); - - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) - { - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - } - else if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::Unspecified) - { - QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); - - // Main Content section begins. - saveModifiedMessageBox.setObjectName("SaveAllPrefabsDialog"); - QBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); - QFrame* levelSavedMessageFrame = new QFrame(&saveModifiedMessageBox); - QHBoxLayout* levelSavedMessageLayout = new QHBoxLayout(&saveModifiedMessageBox); - levelSavedMessageFrame->setObjectName("LevelSavedMessageFrame"); - - // Add a checkMark icon next to the level entities saved message. - QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); - QLabel* levelSavedSuccessfullyIconContainer = new QLabel(); - levelSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); - levelSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); - - // Add a message that level entities are saved successfully. - QLabel* levelSavedSuccessfullyLabel = new QLabel("All entities inside level have been saved successfully."); - levelSavedSuccessfullyLabel->setObjectName("LevelSavedSuccessfullyLabel"); - levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIconContainer); - levelSavedMessageLayout->addWidget(levelSavedSuccessfullyLabel); - levelSavedMessageFrame->setLayout(levelSavedMessageLayout); - - - QFrame* prefabSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); - QHBoxLayout* prefabSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); - - // Add a warning icon next to prefabs save question. - QLabel* warningIconContainer = new QLabel(); - QPixmap warningIcon(QString(":/Notifications/warning.svg")); - warningIconContainer->setPixmap(warningIcon); - warningIconContainer->setFixedWidth(warningIcon.width()); - prefabSaveQuestionLayout->addWidget(warningIconContainer); - - // Ask if user wants all prefabs saved. - QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save all unsaved prefabs?"); - prefabSaveQuestionFrame->setObjectName("PrefabSaveQuestionFrame"); - prefabSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); - prefabSaveQuestionFrame->setLayout(prefabSaveQuestionLayout); - contentLayout->addWidget(levelSavedMessageFrame); - contentLayout->addWidget(prefabSaveQuestionFrame); - - // Footer section begins. - QFrame* footerSeparatorLine = new QFrame(); - footerSeparatorLine->setObjectName("FooterSeparatorLine"); - footerSeparatorLine->setFrameShape(QFrame::HLine); - contentLayout->addWidget(footerSeparatorLine); - QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); - - // Provide option for user to remember their prefab save preference. - QCheckBox* saveAllPrefabsPreference = new QCheckBox("Remember my preference."); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreference); - QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); - footerPreferenceLayout->addWidget(saveAllPrefabsPreference); - QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); - prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); - footerPreferenceLayout->addWidget(prefabSavePreferenceHint); - footerLayout->addLayout(footerPreferenceLayout); - QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); - footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); - - int prefabSaveSelection = saveModifiedMessageBox.exec(); - switch (prefabSaveSelection) - { - case QDialog::Accepted: - if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) - { - gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveAll); - } - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - break; - case QDialog::Rejected: - if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) - { - gSettings.SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference::SaveNone); - } - break; - } - } + GetIEditor()->GetDocument()->ExecuteSavePrefabsDialog(); } } @@ -3239,29 +3148,80 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) bool bIsDocModified = GetIEditor()->GetDocument()->IsModified(); if (GetIEditor()->GetDocument()->IsDocumentReady() && bIsDocModified) { - QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); - int result = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (QMessageBox::Yes == result) + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (!usePrefabSystemForLevels) { - if (!GetIEditor()->GetDocument()->DoFileSave()) + QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); + int result = QMessageBox::question( + AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str, + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (QMessageBox::Yes == result) + { + if (!GetIEditor()->GetDocument()->DoFileSave()) + { + // if the file save operation failed, assume that the user was informed of why + // already and treat it as a cancel + wasCreateLevelOperationCancelled = true; + return false; + } + + bIsDocModified = false; + } + else if (QMessageBox::No == result) + { + // Set Modified flag to false to prevent show Save unchanged dialog again + GetIEditor()->GetDocument()->SetModifiedFlag(false); + } + else if (QMessageBox::Cancel == result) { - // if the file save operation failed, assume that the user was informed of why - // already and treat it as a cancel wasCreateLevelOperationCancelled = true; return false; } - - bIsDocModified = false; - } - else if (QMessageBox::No == result) - { - // Set Modified flag to false to prevent show Save unchanged dialog again - GetIEditor()->GetDocument()->SetModifiedFlag(false); } - else if (QMessageBox::Cancel == result) + else { - wasCreateLevelOperationCancelled = true; - return false; + auto prefabSystemComponentInterface = AZ::Interface::Get(); + auto prefabSaveSelectionDialog = GetIEditor()->GetDocument()->ConstructSaveLevelDialog(); + + int prefabSaveSelection = prefabSaveSelectionDialog->exec(); + QCheckBox* saveAllPrefabsPreferenceCheckBox = + prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); + QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() + ? AzToolsFramework::SavePrefabsPreference::SaveAll + : AzToolsFramework::SavePrefabsPreference::SaveNone; + + switch (1 - prefabSaveSelection) + { + case QDialogButtonBox::AcceptRole: + if (!GetIEditor()->GetDocument()->DoFileSave()) + { + // if the file save operation failed, assume that the user was informed of why + // already and treat it as a cancel + wasCreateLevelOperationCancelled = true; + return false; + } + if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(savePrefabsPreference); + gSettings.Save(); + } + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + } + bIsDocModified = prefabSystemComponentInterface->AreDirtyTemplatesPresent(); + break; + case QDialogButtonBox::RejectRole: + wasCreateLevelOperationCancelled = true; + return false; + case QDialogButtonBox::InvalidRole: + // Set Modified flag to false to prevent show Save unchanged dialog again + GetIEditor()->GetDocument()->SetModifiedFlag(false); + break; + } } } diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 37a5750e1f..3301d2521a 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -697,92 +697,34 @@ bool CCryEditDoc::SaveModified() else { auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); - - QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); - saveModifiedMessageBox.setObjectName("SaveDirtyLevelDialog"); - - // Main Content section begins. - QVBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); - QFrame* levelEntitiesSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); - QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); - levelEntitiesSaveQuestionFrame->setObjectName("LevelEntitiesSaveQuestionFrame"); - - // Add a warning icon next to save entities question. - levelEntitiesSaveQuestionFrame->setLayout(levelEntitiesSaveQuestionLayout); - QPixmap warningIcon(QString(":/Notifications/warning.svg")); - QLabel* warningIconContainer = new QLabel(); - warningIconContainer->setPixmap(warningIcon); - warningIconContainer->setFixedWidth(warningIcon.width()); - levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); - - // Ask user if they want to save entities in level. - QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); - levelEntitiesSaveQuestionLayout->addWidget(levelEntitiesSaveQuestionLabel); - contentLayout->addWidget(levelEntitiesSaveQuestionFrame); - - // Ask user if they want to save unsaved prefabs in the level too. - QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); - saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); - QObject::connect( - saveAllPrefabsCheckbox, &QCheckBox::stateChanged, - [&savePrefabsPreference](int state) - { - savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked - ? AzToolsFramework::SavePrefabsPreference::SaveAll - : AzToolsFramework::SavePrefabsPreference::SaveNone; - }); - contentLayout->addWidget(saveAllPrefabsCheckbox); - - // Footer section begins. - QFrame* footerSeparatorLine = new QFrame(); - footerSeparatorLine->setObjectName("FooterSeparatorLine"); - footerSeparatorLine->setFrameShape(QFrame::HLine); - contentLayout->addWidget(footerSeparatorLine); - QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); - - // Provide option for user to remember their prefab save preference. - QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) - { - saveAllPrefabsPreferenceCheckBox->setCheckState(Qt::CheckState::Checked); - saveAllPrefabsCheckbox->setCheckState(Qt::CheckState::Checked); - } - QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); - footerPreferenceLayout->addWidget(saveAllPrefabsPreferenceCheckBox); - QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); - prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); - footerPreferenceLayout->addWidget(prefabSavePreferenceHint); - footerLayout->addLayout(footerPreferenceLayout); - QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel); - footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); - - int prefabSaveSelection = saveModifiedMessageBox.exec(); - - if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) + auto prefabSaveSelectionDialog = ConstructSaveLevelDialog(); + + int prefabSaveSelection = prefabSaveSelectionDialog->exec(); + QCheckBox* saveAllPrefabsPreferenceCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); + QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() + ? AzToolsFramework::SavePrefabsPreference::SaveAll + : AzToolsFramework::SavePrefabsPreference::SaveNone; + + switch (1 - prefabSaveSelection) { - gSettings.SetSavePrefabsPreference(savePrefabsPreference); - prefabEditorEntityOwnershipInterface->SetSavePrefabsPreference(savePrefabsPreference); - } - - switch (prefabSaveSelection) - { - case QDialog::Accepted: + case QDialogButtonBox::AcceptRole: DoFileSave(); + if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(savePrefabsPreference); + gSettings.Save(); + } if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) { prefabSystemComponentInterface->SaveAllDirtyTemplates(); } return true; - case QDialog::Rejected: + case QDialogButtonBox::RejectRole: return false; + case QDialogButtonBox::InvalidRole: + SetModifiedFlag(false); + return true; } Q_UNREACHABLE(); } @@ -799,6 +741,17 @@ void CCryEditDoc::OnFileSaveAs() if (OnSaveDocument(levelFileDialog.GetFileName())) { CCryEditApp::instance()->AddToRecentFileList(levelFileDialog.GetFileName()); + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (usePrefabSystemForLevels) + { + auto prefabSystemComponentInterface = AZ::Interface::Get(); + if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) + { + ExecuteSavePrefabsDialog(); + } + } } } } @@ -2308,6 +2261,194 @@ void CCryEditDoc::OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAsset } ////////////////////////////////////////////////////////////////////////// +AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() +{ + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + + AZStd::shared_ptr saveModifiedMessageBox = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); + AZStd::weak_ptr saveModifiedMessageBoxWeakPtr(saveModifiedMessageBox); + // saveModifiedMessageBox.overrideWindowFlags((saveModifiedMessageBox.windowFlags()) & ~Qt::WindowCloseButtonHint); + saveModifiedMessageBox->setObjectName("SaveDirtyLevelDialog"); + + // Main Content section begins. + QVBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); + QFrame* levelEntitiesSaveQuestionFrame = new QFrame(saveModifiedMessageBox.get()); + QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + levelEntitiesSaveQuestionFrame->setObjectName("LevelEntitiesSaveQuestionFrame"); + + // Add a warning icon next to save entities question. + levelEntitiesSaveQuestionFrame->setLayout(levelEntitiesSaveQuestionLayout); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); + QLabel* warningIconContainer = new QLabel(); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask user if they want to save entities in level. + QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); + levelEntitiesSaveQuestionLayout->addWidget(levelEntitiesSaveQuestionLabel); + contentLayout->addWidget(levelEntitiesSaveQuestionFrame); + + // Ask user if they want to save unsaved prefabs in the level too. + QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); + saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + saveAllPrefabsCheckbox->setCheckState(Qt::CheckState::Checked); + } + QObject::connect( + saveAllPrefabsCheckbox, &QCheckBox::stateChanged, + [&savePrefabsPreference](int state) + { + savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked + ? AzToolsFramework::SavePrefabsPreference::SaveAll + : AzToolsFramework::SavePrefabsPreference::SaveNone; + }); + contentLayout->addWidget(saveAllPrefabsCheckbox); + + // Footer section begins. + QFrame* footerSeparatorLine = new QFrame(); + footerSeparatorLine->setObjectName("FooterSeparatorLine"); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + + // Provide option for user to remember their prefab save preference. + QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); + saveAllPrefabsPreferenceCheckBox->setObjectName("SaveAllPrefabsPreferenceCheckBox"); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); + if (savePrefabsPreference != AzToolsFramework::SavePrefabsPreference::Unspecified) + { + saveAllPrefabsPreferenceCheckBox->setCheckState(Qt::CheckState::Checked); + } + QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(saveModifiedMessageBox.get()); + footerPreferenceLayout->addWidget(saveAllPrefabsPreferenceCheckBox); + QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); + prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + footerPreferenceLayout->addWidget(prefabSavePreferenceHint); + footerLayout->addLayout(footerPreferenceLayout); + QDialogButtonBox* prefabSaveConfirmationButtons = + new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); + connect( + prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, saveModifiedMessageBox.get(), + [saveModifiedMessageBoxWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) + { + int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button); + saveModifiedMessageBoxWeakPtr.lock()->done(prefabSaveSelection); + }); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.get(), QStringLiteral("style:Editor.qss")); + return saveModifiedMessageBox; +} + +void CCryEditDoc::ExecuteSavePrefabsDialog() +{ + auto prefabSystemComponentInterface = AZ::Interface::Get(); + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + + if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + { + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + SetModifiedFlag(false); + } + else if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveNone) + { + if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) + { + SetModifiedFlag(true); + } + } + else // AzToolsFramework::SavePrefabsPreference::Unspecified + { + QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + + // Main Content section begins. + saveModifiedMessageBox.setObjectName("SaveAllPrefabsDialog"); + QBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); + QFrame* levelSavedMessageFrame = new QFrame(&saveModifiedMessageBox); + QHBoxLayout* levelSavedMessageLayout = new QHBoxLayout(&saveModifiedMessageBox); + levelSavedMessageFrame->setObjectName("LevelSavedMessageFrame"); + + // Add a checkMark icon next to the level entities saved message. + QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); + QLabel* levelSavedSuccessfullyIconContainer = new QLabel(); + levelSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); + levelSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); + + // Add a message that level entities are saved successfully. + QLabel* levelSavedSuccessfullyLabel = new QLabel("All entities inside level have been saved successfully."); + levelSavedSuccessfullyLabel->setObjectName("LevelSavedSuccessfullyLabel"); + levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIconContainer); + levelSavedMessageLayout->addWidget(levelSavedSuccessfullyLabel); + levelSavedMessageFrame->setLayout(levelSavedMessageLayout); + + QFrame* prefabSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); + QHBoxLayout* prefabSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); + + // Add a warning icon next to prefabs save question. + QLabel* warningIconContainer = new QLabel(); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + prefabSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask if user wants all prefabs saved. + QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save all unsaved prefabs?"); + prefabSaveQuestionFrame->setObjectName("PrefabSaveQuestionFrame"); + prefabSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); + prefabSaveQuestionFrame->setLayout(prefabSaveQuestionLayout); + contentLayout->addWidget(levelSavedMessageFrame); + contentLayout->addWidget(prefabSaveQuestionFrame); + + // Footer section begins. + QFrame* footerSeparatorLine = new QFrame(); + footerSeparatorLine->setObjectName("FooterSeparatorLine"); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); + + // Provide option for user to remember their prefab save preference. + QCheckBox* saveAllPrefabsPreference = new QCheckBox("Remember my preference."); + AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreference); + QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); + footerPreferenceLayout->addWidget(saveAllPrefabsPreference); + QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); + prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + footerPreferenceLayout->addWidget(prefabSavePreferenceHint); + footerLayout->addLayout(footerPreferenceLayout); + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); + + int prefabSaveSelection = saveModifiedMessageBox.exec(); + + if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) + { + gSettings.SetSavePrefabsPreference(savePrefabsPreference); + gSettings.Save(); + } + switch (prefabSaveSelection) + { + case QDialog::Accepted: + prefabSystemComponentInterface->SaveAllDirtyTemplates(); + SetModifiedFlag(false); + break; + case QDialog::Rejected: + SetModifiedFlag(true); + break; + } + } +} + namespace AzToolsFramework { void CryEditDocFuncsHandler::Reflect(AZ::ReflectContext* context) diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h index a96e9428b6..3a12b461fb 100644 --- a/Code/Editor/CryEditDoc.h +++ b/Code/Editor/CryEditDoc.h @@ -104,6 +104,12 @@ public: // Create from serialization only bool CanCloseFrame(); + //! Returns a Modal containing options to save the current level. + AZStd::shared_ptr ConstructSaveLevelDialog(); + + //! Executes a Modal asking users about their prefabs save preference. + void ExecuteSavePrefabsDialog(); + enum class FetchPolicy { DELETE_FOLDER, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 31f5816bfc..c6f91a422a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -753,6 +753,18 @@ namespace AzToolsFramework } } + bool PrefabSystemComponent::AreDirtyTemplatesPresent() + { + for (const auto& [id, templateObject] : m_templateIdMap) + { + if (IsTemplateDirty(id)) + { + return true; + } + } + return false; + } + void PrefabSystemComponent::SaveAllDirtyTemplates() { for (auto& [id, templateObject] : m_templateIdMap) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 3539a79d54..cb95f9b367 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -183,6 +183,8 @@ namespace AzToolsFramework */ void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override; + bool AreDirtyTemplatesPresent() override; + void SaveAllDirtyTemplates() override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index bcea8a8b2d..252c8bdb6a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -49,6 +49,7 @@ namespace AzToolsFramework virtual bool IsTemplateDirty(const TemplateId& templateId) = 0; virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; + virtual bool AreDirtyTemplatesPresent() = 0; virtual void SaveAllDirtyTemplates() = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; From 1ca67cad804c72920e842fcace94f3964f974bac Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 24 Aug 2021 18:34:51 -0700 Subject: [PATCH 04/17] Moved PrefabSavePreference settings registry code from PrefabEditorEntityOwnershipInterface to PrefabLoaderInterface Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 10 +++--- Code/Editor/CryEditDoc.cpp | 36 ++++++++++--------- Code/Editor/EditorPreferencesPageGeneral.cpp | 6 ++-- Code/Editor/EditorPreferencesPageGeneral.h | 4 +-- Code/Editor/Settings.cpp | 16 ++++----- Code/Editor/Settings.h | 6 ++-- .../PrefabEditorEntityOwnershipInterface.h | 9 ----- .../PrefabEditorEntityOwnershipService.cpp | 20 ----------- .../PrefabEditorEntityOwnershipService.h | 3 -- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 31 ++++++++++++++++ .../AzToolsFramework/Prefab/PrefabLoader.h | 5 +++ .../Prefab/PrefabLoaderInterface.h | 15 ++++++++ .../Prefab/PrefabSystemComponent.cpp | 1 + 13 files changed, 94 insertions(+), 68 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 6e921833cb..b60351b6b9 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3182,6 +3182,8 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) } else { + using namespace AzToolsFramework::Prefab; + auto prefabSystemComponentInterface = AZ::Interface::Get(); auto prefabSaveSelectionDialog = GetIEditor()->GetDocument()->ConstructSaveLevelDialog(); @@ -3189,9 +3191,9 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) QCheckBox* saveAllPrefabsPreferenceCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() - ? AzToolsFramework::SavePrefabsPreference::SaveAll - : AzToolsFramework::SavePrefabsPreference::SaveNone; + SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() + ? SavePrefabsPreference::SaveAll + : SavePrefabsPreference::SaveNone; switch (1 - prefabSaveSelection) { @@ -3208,7 +3210,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) gSettings.SetSavePrefabsPreference(savePrefabsPreference); gSettings.Save(); } - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + if (savePrefabsPreference == SavePrefabsPreference::SaveAll) { prefabSystemComponentInterface->SaveAllDirtyTemplates(); } diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 3301d2521a..208604e2dd 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include // Editor @@ -696,15 +697,16 @@ bool CCryEditDoc::SaveModified() } else { + using namespace AzToolsFramework::Prefab; + auto prefabSystemComponentInterface = AZ::Interface::Get(); auto prefabSaveSelectionDialog = ConstructSaveLevelDialog(); int prefabSaveSelection = prefabSaveSelectionDialog->exec(); QCheckBox* saveAllPrefabsPreferenceCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() - ? AzToolsFramework::SavePrefabsPreference::SaveAll - : AzToolsFramework::SavePrefabsPreference::SaveNone; + SavePrefabsPreference savePrefabsPreference = + saveAllPrefabsCheckBox->isChecked() ? SavePrefabsPreference::SaveAll : SavePrefabsPreference::SaveNone; switch (1 - prefabSaveSelection) { @@ -715,7 +717,7 @@ bool CCryEditDoc::SaveModified() gSettings.SetSavePrefabsPreference(savePrefabsPreference); gSettings.Save(); } - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + if (savePrefabsPreference == SavePrefabsPreference::SaveAll) { prefabSystemComponentInterface->SaveAllDirtyTemplates(); } @@ -2263,8 +2265,9 @@ void CCryEditDoc::OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAsset AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() { - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + using namespace AzToolsFramework::Prefab; + auto prefabLoaderInterface = AZ::Interface::Get(); + SavePrefabsPreference savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); AZStd::shared_ptr saveModifiedMessageBox = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); AZStd::weak_ptr saveModifiedMessageBoxWeakPtr(saveModifiedMessageBox); @@ -2294,7 +2297,7 @@ AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + if (savePrefabsPreference == SavePrefabsPreference::SaveAll) { saveAllPrefabsCheckbox->setCheckState(Qt::CheckState::Checked); } @@ -2302,9 +2305,8 @@ AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() saveAllPrefabsCheckbox, &QCheckBox::stateChanged, [&savePrefabsPreference](int state) { - savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked - ? AzToolsFramework::SavePrefabsPreference::SaveAll - : AzToolsFramework::SavePrefabsPreference::SaveNone; + savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked ? SavePrefabsPreference::SaveAll + : SavePrefabsPreference::SaveNone; }); contentLayout->addWidget(saveAllPrefabsCheckbox); @@ -2319,7 +2321,7 @@ AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); saveAllPrefabsPreferenceCheckBox->setObjectName("SaveAllPrefabsPreferenceCheckBox"); AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); - if (savePrefabsPreference != AzToolsFramework::SavePrefabsPreference::Unspecified) + if (savePrefabsPreference != SavePrefabsPreference::Unspecified) { saveAllPrefabsPreferenceCheckBox->setCheckState(Qt::CheckState::Checked); } @@ -2348,23 +2350,25 @@ AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() void CCryEditDoc::ExecuteSavePrefabsDialog() { + using namespace AzToolsFramework::Prefab; + auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AzToolsFramework::SavePrefabsPreference savePrefabsPreference = prefabEditorEntityOwnershipInterface->GetSavePrefabsPreference(); + auto prefabLoaderInterface = AZ::Interface::Get(); + SavePrefabsPreference savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); - if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveAll) + if (savePrefabsPreference == SavePrefabsPreference::SaveAll) { prefabSystemComponentInterface->SaveAllDirtyTemplates(); SetModifiedFlag(false); } - else if (savePrefabsPreference == AzToolsFramework::SavePrefabsPreference::SaveNone) + else if (savePrefabsPreference == SavePrefabsPreference::SaveNone) { if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) { SetModifiedFlag(true); } } - else // AzToolsFramework::SavePrefabsPreference::Unspecified + else // SavePrefabsPreference::Unspecified { QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 08703ba6cc..9e0d2962a9 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -101,9 +101,9 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement( AZ::Edit::UIHandlers::ComboBox, &PrefabSettings::m_savePrefabsPreference, "Save Prefabs Preference", "When saving levels, this option controls whether and how prefabs should be saved along with the level.") - ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::Unspecified, "Unspecified") - ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveAll, "Save All") - ->EnumAttribute(AzToolsFramework::SavePrefabsPreference::SaveNone, "Save None"); + ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::Unspecified, "Unspecified") + ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::SaveAll, "Save All") + ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::SaveNone, "Save None"); editContext->Class("Messaging", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") diff --git a/Code/Editor/EditorPreferencesPageGeneral.h b/Code/Editor/EditorPreferencesPageGeneral.h index 29dcefcb80..b2d652ccba 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Editor/EditorPreferencesPageGeneral.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "Settings.h" @@ -61,7 +61,7 @@ private: struct PrefabSettings { AZ_TYPE_INFO(PrefabSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); - AzToolsFramework::SavePrefabsPreference m_savePrefabsPreference; + AzToolsFramework::Prefab::SavePrefabsPreference m_savePrefabsPreference; }; struct Messaging diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 0197a45cfa..d20f132848 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -255,7 +255,7 @@ SEditorSettings::SEditorSettings() g_TemporaryLevelName = nullptr; sliceSettings.dynamicByDefault = false; - prefabSettings.savePrefabsPreference = AzToolsFramework::SavePrefabsPreference::Unspecified; + prefabSettings.savePrefabsPreference = AzToolsFramework::Prefab::SavePrefabsPreference::Unspecified; } void SEditorSettings::Connect() @@ -670,9 +670,9 @@ void SEditorSettings::Save() AzFramework::ApplicationRequests::Bus::Broadcast( &AzFramework::ApplicationRequests::SetPrefabSystemEnabled, prefabSystem); - AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipService = - AZ::Interface::Get(); - prefabEditorEntityOwnershipService->SetSavePrefabsPreference(prefabSettings.savePrefabsPreference); + AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = + AZ::Interface::Get(); + prefabLoaderInterface->SetSavePrefabsPreference(prefabSettings.savePrefabsPreference); SaveSettingsRegistryFile(); } @@ -680,9 +680,9 @@ void SEditorSettings::Save() ////////////////////////////////////////////////////////////////////////// void SEditorSettings::Load() { - AzToolsFramework::PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipService = - AZ::Interface::Get(); - prefabSettings.savePrefabsPreference = prefabEditorEntityOwnershipService->GetSavePrefabsPreference(); + AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = + AZ::Interface::Get(); + prefabSettings.savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); // Load from Settings Registry AzFramework::ApplicationRequests::Bus::BroadcastResult( @@ -1082,7 +1082,7 @@ void SEditorSettings::ConvertPath(const AZStd::string_view sourcePath, AZStd::st AZStd::replace(category.begin(), category.end(), '|', '\\'); } -void SEditorSettings::SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference savePrefabsPreference) +void SEditorSettings::SetSavePrefabsPreference(AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference) { prefabSettings.savePrefabsPreference = savePrefabsPreference; } diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index 61f89a8a05..dcc96dd2da 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -233,7 +233,7 @@ struct SSliceSettings struct SPrefabSettings { - AzToolsFramework::SavePrefabsPreference savePrefabsPreference; + AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference; }; ////////////////////////////////////////////////////////////////////////// @@ -476,7 +476,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities. - void SetSavePrefabsPreference(AzToolsFramework::SavePrefabsPreference savePrefabsPreference); + void SetSavePrefabsPreference(AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference); private: void SaveValue(const char* sSection, const char* sKey, int value); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index f26f80ca10..f9b8e679b5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -18,13 +18,6 @@ namespace AzToolsFramework { - enum class SavePrefabsPreference : AZ::s64 - { - Unspecified = 0, - SaveAll = 1, - SaveNone = -1 - }; - class PrefabEditorEntityOwnershipInterface { public: @@ -60,7 +53,5 @@ namespace AzToolsFramework virtual void StopPlayInEditor() = 0; virtual void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) = 0; - virtual SavePrefabsPreference GetSavePrefabsPreference() = 0; - virtual void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) = 0; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index bd8bf28de2..f336a9765c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -28,8 +28,6 @@ namespace AzToolsFramework { - static constexpr const char s_savePrefabsKey[] = "/O3DE/Preferences/SavePrefabs"; - PrefabEditorEntityOwnershipService::PrefabEditorEntityOwnershipService(const AzFramework::EntityContextId& entityContextId, AZ::SerializeContext* serializeContext) : m_entityContextId(entityContextId) @@ -610,24 +608,6 @@ namespace AzToolsFramework m_playInEditorData.m_isEnabled = false; } - SavePrefabsPreference PrefabEditorEntityOwnershipService::GetSavePrefabsPreference() - { - AZ::s64 savePrefabsPreference = static_cast(SavePrefabsPreference::Unspecified); - if (auto* registry = AZ::SettingsRegistry::Get()) - { - registry->Get(savePrefabsPreference, s_savePrefabsKey); - } - return static_cast(savePrefabsPreference); - } - - void PrefabEditorEntityOwnershipService::SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) - { - if (auto* registry = AZ::SettingsRegistry::Get()) - { - registry->Set(s_savePrefabsKey, static_cast(savePrefabsPreference)); - } - } - ////////////////////////////////////////////////////////////////////////// // Slice Buses implementation with Assert(false), this will exist only during Slice->Prefab // development to pinpoint and replace specific calls to Slice system diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index e94c955061..bf1199d6dd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -168,9 +168,6 @@ namespace AzToolsFramework void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) override; - SavePrefabsPreference GetSavePrefabsPreference() override; - void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) override; - protected: AZ::SliceComponent::SliceInstanceAddress GetOwningSlice() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 0a9c937832..d8c308528d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -25,6 +25,19 @@ namespace AzToolsFramework { namespace Prefab { + static constexpr const char s_savePrefabsKey[] = "/O3DE/Preferences/SavePrefabs"; + + void PrefabLoader::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Enum() + ->Value("Unspecified", SavePrefabsPreference::Unspecified) + ->Value("SaveAll", SavePrefabsPreference::SaveAll) + ->Value("SaveNone", SavePrefabsPreference::SaveNone); + } + } + void PrefabLoader::RegisterPrefabLoaderInterface() { m_prefabSystemComponentInterface = AZ::Interface::Get(); @@ -656,6 +669,24 @@ namespace AzToolsFramework return finalPath; } + SavePrefabsPreference PrefabLoader::GetSavePrefabsPreference() + { + SavePrefabsPreference savePrefabsPreference = SavePrefabsPreference::Unspecified; + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->GetObject(savePrefabsPreference, s_savePrefabsKey); + } + return static_cast(savePrefabsPreference); + } + + void PrefabLoader::SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) + { + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->SetObject(s_savePrefabsKey, savePrefabsPreference); + } + } + AZ::IO::Path PrefabLoaderInterface::GeneratePath() { return AZStd::string::format("Prefab_%s", AZ::Entity::MakeId().ToString().c_str()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h index 007933c021..e97eb694c2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h @@ -39,6 +39,8 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR(PrefabLoader, AZ::SystemAllocator, 0); AZ_RTTI(PrefabLoader, "{A302B072-4DC4-4B7E-9188-226F56A3429C8}", PrefabLoaderInterface); + static void Reflect(AZ::ReflectContext* context); + ////////////////////////////////////////////////////////////////////////// // PrefabLoaderInterface interface implementation @@ -108,6 +110,9 @@ namespace AzToolsFramework //! Returns if the path is a valid path for a prefab static bool IsValidPrefabPath(AZ::IO::PathView path); + SavePrefabsPreference GetSavePrefabsPreference() override; + void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) override; + private: /** * Copies the template dom provided and manipulates it into the proper format to be saved to disk. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index 3c60bea18c..938ad00809 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -17,6 +17,13 @@ namespace AzToolsFramework { namespace Prefab { + enum class SavePrefabsPreference : AZ::u8 + { + Unspecified = 0, + SaveAll = 1, + SaveNone = 2 + }; + /*! * PrefabLoaderInterface * Interface for saving/loading Prefab files. @@ -84,6 +91,9 @@ namespace AzToolsFramework //! The path will always use the '/' separator. virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0; + virtual SavePrefabsPreference GetSavePrefabsPreference() = 0; + virtual void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) = 0; + protected: // Generates a new path @@ -93,3 +103,8 @@ namespace AzToolsFramework } // namespace Prefab } // namespace AzToolsFramework +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AzToolsFramework::Prefab::SavePrefabsPreference, "{7E61EA82-4DE4-4A3F-945F-C8FEDC1114B5}"); +} + diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index c6f91a422a..928158dae0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -57,6 +57,7 @@ namespace AzToolsFramework AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor::Reflect(context); AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover::Reflect(context); PrefabPublicRequestHandler::Reflect(context); + PrefabLoader::Reflect(context); AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) From a13fb3c13aaee60fca81a9ec86f556e5df3bba57 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 24 Aug 2021 19:21:06 -0700 Subject: [PATCH 05/17] Added some comments and some minor fixes Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 7 +- Code/Editor/CryEditDoc.cpp | 3 +- Code/Editor/SaveAllPrefabsDialog.cpp | 29 +++++ Code/Editor/SaveAllPrefabsDialog.h | 29 +++++ Code/Editor/SaveAllPrefabsDialog.ui | 107 ++++++++++++++++++ .../PrefabEditorEntityOwnershipInterface.h | 1 + .../PrefabEditorEntityOwnershipService.cpp | 1 - .../AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- 8 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 Code/Editor/SaveAllPrefabsDialog.cpp create mode 100644 Code/Editor/SaveAllPrefabsDialog.h create mode 100644 Code/Editor/SaveAllPrefabsDialog.ui diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index b60351b6b9..83a98ca67b 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -736,7 +736,11 @@ void CCryEditApp::OnFileSave() if (usePrefabSystemForLevels) { - GetIEditor()->GetDocument()->ExecuteSavePrefabsDialog(); + auto prefabSystemComponentInterface = AZ::Interface::Get(); + if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) + { + GetIEditor()->GetDocument()->ExecuteSavePrefabsDialog(); + } } } @@ -3195,6 +3199,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) ? SavePrefabsPreference::SaveAll : SavePrefabsPreference::SaveNone; + // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 208604e2dd..3e619aba24 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -707,7 +707,8 @@ bool CCryEditDoc::SaveModified() QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() ? SavePrefabsPreference::SaveAll : SavePrefabsPreference::SaveNone; - + + // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: diff --git a/Code/Editor/SaveAllPrefabsDialog.cpp b/Code/Editor/SaveAllPrefabsDialog.cpp new file mode 100644 index 0000000000..4a344b32ae --- /dev/null +++ b/Code/Editor/SaveAllPrefabsDialog.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + #include + #include "SaveAllPrefabsDialog.h" + #include + +AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING +#include +AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING + +SaveAllPrefabsDialog::SaveAllPrefabsDialog(QWidget* parent) + : QDialog(parent) + , ui(new Ui::SaveAllPrefabsDialog) +{ + ui->setupUi(this); + AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->saveAllPrefabsCheckBox); + AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->rememberPrefabSavePreferenceCheckBox); +} + +SaveAllPrefabsDialog::~SaveAllPrefabsDialog() +{ + delete ui; +} diff --git a/Code/Editor/SaveAllPrefabsDialog.h b/Code/Editor/SaveAllPrefabsDialog.h new file mode 100644 index 0000000000..807f902309 --- /dev/null +++ b/Code/Editor/SaveAllPrefabsDialog.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +namespace Ui +{ + class SaveAllPrefabsDialog; +} + + + class SaveAllPrefabsDialog : public QDialog + { + public: + SaveAllPrefabsDialog(QWidget* pParent = nullptr); + ~SaveAllPrefabsDialog(); + + private: + Ui::SaveAllPrefabsDialog* ui; + }; + diff --git a/Code/Editor/SaveAllPrefabsDialog.ui b/Code/Editor/SaveAllPrefabsDialog.ui new file mode 100644 index 0000000000..8d1e70b935 --- /dev/null +++ b/Code/Editor/SaveAllPrefabsDialog.ui @@ -0,0 +1,107 @@ + + + SaveAllPrefabsDialog + + + + 0 + 0 + 800 + 600 + + + + Dialog + + + + + + Changes in level saved successfully + + + + + + + Second text + + + + + + + + + CheckBox + + + + + + + TextLabel + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + + CheckBox + + + + + + + TextLabel + + + + + + + + + TextLabel + + + + + + + + + PushButton + + + + + + + PushButton + + + + + + + + + + diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index f9b8e679b5..1cd36e8055 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -18,6 +18,7 @@ namespace AzToolsFramework { + class PrefabEditorEntityOwnershipInterface { public: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index f336a9765c..7df1e1b5c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index d8c308528d..2f0a0601b9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -676,7 +676,7 @@ namespace AzToolsFramework { registry->GetObject(savePrefabsPreference, s_savePrefabsKey); } - return static_cast(savePrefabsPreference); + return savePrefabsPreference; } void PrefabLoader::SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) From 06b1d9afbb697248e958e66a05ed6bc650c78655 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 24 Aug 2021 19:25:06 -0700 Subject: [PATCH 06/17] Delete some accidentally committed local ui work Signed-off-by: srikappa-amzn --- Code/Editor/SaveAllPrefabsDialog.cpp | 29 -------- Code/Editor/SaveAllPrefabsDialog.h | 29 -------- Code/Editor/SaveAllPrefabsDialog.ui | 107 --------------------------- 3 files changed, 165 deletions(-) delete mode 100644 Code/Editor/SaveAllPrefabsDialog.cpp delete mode 100644 Code/Editor/SaveAllPrefabsDialog.h delete mode 100644 Code/Editor/SaveAllPrefabsDialog.ui diff --git a/Code/Editor/SaveAllPrefabsDialog.cpp b/Code/Editor/SaveAllPrefabsDialog.cpp deleted file mode 100644 index 4a344b32ae..0000000000 --- a/Code/Editor/SaveAllPrefabsDialog.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - - #include - #include "SaveAllPrefabsDialog.h" - #include - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -SaveAllPrefabsDialog::SaveAllPrefabsDialog(QWidget* parent) - : QDialog(parent) - , ui(new Ui::SaveAllPrefabsDialog) -{ - ui->setupUi(this); - AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->saveAllPrefabsCheckBox); - AzQtComponents::CheckBox::applyToggleSwitchStyle(ui->rememberPrefabSavePreferenceCheckBox); -} - -SaveAllPrefabsDialog::~SaveAllPrefabsDialog() -{ - delete ui; -} diff --git a/Code/Editor/SaveAllPrefabsDialog.h b/Code/Editor/SaveAllPrefabsDialog.h deleted file mode 100644 index 807f902309..0000000000 --- a/Code/Editor/SaveAllPrefabsDialog.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include - -namespace Ui -{ - class SaveAllPrefabsDialog; -} - - - class SaveAllPrefabsDialog : public QDialog - { - public: - SaveAllPrefabsDialog(QWidget* pParent = nullptr); - ~SaveAllPrefabsDialog(); - - private: - Ui::SaveAllPrefabsDialog* ui; - }; - diff --git a/Code/Editor/SaveAllPrefabsDialog.ui b/Code/Editor/SaveAllPrefabsDialog.ui deleted file mode 100644 index 8d1e70b935..0000000000 --- a/Code/Editor/SaveAllPrefabsDialog.ui +++ /dev/null @@ -1,107 +0,0 @@ - - - SaveAllPrefabsDialog - - - - 0 - 0 - 800 - 600 - - - - Dialog - - - - - - Changes in level saved successfully - - - - - - - Second text - - - - - - - - - CheckBox - - - - - - - TextLabel - - - - - - - - - Qt::Horizontal - - - - - - - - - - - - - CheckBox - - - - - - - TextLabel - - - - - - - - - TextLabel - - - - - - - - - PushButton - - - - - - - PushButton - - - - - - - - - - From 89a415d50cbbfe08bcb4e8f1733c5cb6b0d0658e Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 24 Aug 2021 19:56:29 -0700 Subject: [PATCH 07/17] Removed az::u8 from Prefab save preference Enum Signed-off-by: srikappa-amzn --- .../AzToolsFramework/Prefab/PrefabLoaderInterface.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index 938ad00809..57ef6d6a3a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -17,11 +17,11 @@ namespace AzToolsFramework { namespace Prefab { - enum class SavePrefabsPreference : AZ::u8 + enum class SavePrefabsPreference { - Unspecified = 0, - SaveAll = 1, - SaveNone = 2 + Unspecified, + SaveAll, + SaveNone }; /*! From f6acf4321d7c680f8cedb6c556bd99a579c425f3 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Thu, 2 Sep 2021 15:37:29 -0700 Subject: [PATCH 08/17] Did a major refactor of ui to be less dependent on levels Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 48 ++-- Code/Editor/CryEditDoc.cpp | 245 ++--------------- Code/Editor/CryEditDoc.h | 15 +- Code/Editor/EditorPreferencesPageGeneral.cpp | 24 +- Code/Editor/EditorPreferencesPageGeneral.h | 8 +- Code/Editor/Settings.cpp | 11 +- Code/Editor/Settings.h | 8 +- Code/Editor/Style/Editor.qss | 29 +- .../PrefabEditorEntityOwnershipInterface.h | 3 + .../PrefabEditorEntityOwnershipService.cpp | 15 ++ .../PrefabEditorEntityOwnershipService.h | 2 + .../AzToolsFramework/Prefab/PrefabLoader.cpp | 20 +- .../AzToolsFramework/Prefab/PrefabLoader.h | 4 +- .../Prefab/PrefabLoaderInterface.h | 10 +- .../Prefab/PrefabSystemComponent.cpp | 52 +++- .../Prefab/PrefabSystemComponent.h | 6 +- .../Prefab/PrefabSystemComponentInterface.h | 8 +- .../UI/Prefab/PrefabIntegrationInterface.h | 4 + .../UI/Prefab/PrefabIntegrationManager.cpp | 252 ++++++++++++++++++ .../UI/Prefab/PrefabIntegrationManager.h | 13 + 20 files changed, 458 insertions(+), 319 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 83a98ca67b..ecbdde7f13 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -728,19 +728,26 @@ void CCryEditApp::OnFileSave() const QScopedValueRollback rollback(m_savingLevel, true); - GetIEditor()->GetDocument()->DoFileSave(); + bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); - if (usePrefabSystemForLevels) + + + if (!usePrefabSystemForLevels) { - auto prefabSystemComponentInterface = AZ::Interface::Get(); - if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) - { - GetIEditor()->GetDocument()->ExecuteSavePrefabsDialog(); - } + GetIEditor()->GetDocument()->DoFileSave(); + } + else + { + //auto prefabSystemComponentInterface = AZ::Interface::Get(); + auto prefabEditorEntityOwnershipService = AZ::Interface::Get(); + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipService->GetRootPrefabTemplateId(); + auto prefabIntegrationInterface = AZ::Interface::Get(); + prefabIntegrationInterface->ExecuteSavePrefabsDialog(rootPrefabTemplateId, true); + // prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId) } } @@ -3186,18 +3193,12 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) } else { - using namespace AzToolsFramework::Prefab; + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + auto prefabIntegrationInterface = AZ::Interface::Get(); + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); - auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabSaveSelectionDialog = GetIEditor()->GetDocument()->ConstructSaveLevelDialog(); - - int prefabSaveSelection = prefabSaveSelectionDialog->exec(); - QCheckBox* saveAllPrefabsPreferenceCheckBox = - prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); - QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); - SavePrefabsPreference savePrefabsPreference = saveAllPrefabsCheckBox->isChecked() - ? SavePrefabsPreference::SaveAll - : SavePrefabsPreference::SaveNone; + int prefabSaveSelection = + prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. switch (1 - prefabSaveSelection) @@ -3210,16 +3211,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) wasCreateLevelOperationCancelled = true; return false; } - if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) - { - gSettings.SetSavePrefabsPreference(savePrefabsPreference); - gSettings.Save(); - } - if (savePrefabsPreference == SavePrefabsPreference::SaveAll) - { - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - } - bIsDocModified = prefabSystemComponentInterface->AreDirtyTemplatesPresent(); + bIsDocModified = false; break; case QDialogButtonBox::RejectRole: wasCreateLevelOperationCancelled = true; diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 3e619aba24..3fb39d4268 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -15,8 +15,14 @@ #include #include #include +#include +#include +#include +#include +#include #include #include +#include // AzCore #include @@ -34,9 +40,6 @@ #include #include #include -#include -#include -#include // Editor #include "Settings.h" @@ -138,6 +141,14 @@ CCryEditDoc::CCryEditDoc() RegisterConsoleVariables(); MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_AS, this, &CCryEditDoc::OnFileSaveAs); + m_prefabSystemComponentInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabSystemComponentInterface, "PrefabSystemComponentInterface is not found."); + m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabEditorEntityOwnershipInterface, "PrefabEditorEntityOwnershipInterface is not found."); + m_prefabLoaderInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabLoaderInterface, "PrefabLoaderInterface is not found."); + m_prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabIntegrationInterface, "PrefabIntegrationInterface is not found."); } CCryEditDoc::~CCryEditDoc() @@ -699,29 +710,18 @@ bool CCryEditDoc::SaveModified() { using namespace AzToolsFramework::Prefab; - auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabSaveSelectionDialog = ConstructSaveLevelDialog(); - - int prefabSaveSelection = prefabSaveSelectionDialog->exec(); - QCheckBox* saveAllPrefabsPreferenceCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsPreferenceCheckBox"); - QCheckBox* saveAllPrefabsCheckBox = prefabSaveSelectionDialog->findChild("SaveAllPrefabsCheckbox"); - SavePrefabsPreference savePrefabsPreference = - saveAllPrefabsCheckBox->isChecked() ? SavePrefabsPreference::SaveAll : SavePrefabsPreference::SaveNone; + TemplateId rootPrefabTemplateId = m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + if (!m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId)) + { + return true; + } + + int prefabSaveSelection = m_prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: - DoFileSave(); - if (saveAllPrefabsPreferenceCheckBox->checkState() == Qt::CheckState::Checked) - { - gSettings.SetSavePrefabsPreference(savePrefabsPreference); - gSettings.Save(); - } - if (savePrefabsPreference == SavePrefabsPreference::SaveAll) - { - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - } return true; case QDialogButtonBox::RejectRole: return false; @@ -749,11 +749,9 @@ void CCryEditDoc::OnFileSaveAs() usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); if (usePrefabSystemForLevels) { - auto prefabSystemComponentInterface = AZ::Interface::Get(); - if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) - { - ExecuteSavePrefabsDialog(); - } + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = + m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + SetModifiedFlag(m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId)); } } } @@ -1311,8 +1309,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) } else { - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - if (prefabEditorEntityOwnershipInterface) + if (m_prefabEditorEntityOwnershipInterface) { AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); AZ_Assert(fileIO, "No File IO implementation available"); @@ -1323,7 +1320,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (openResult) { AZ::IO::FileIOStream stream(tempSaveFileHandle, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, false); - contentsAllSaved = prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); + contentsAllSaved = m_prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); stream.Close(); } } @@ -2264,196 +2261,6 @@ void CCryEditDoc::OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAsset } ////////////////////////////////////////////////////////////////////////// -AZStd::shared_ptr CCryEditDoc::ConstructSaveLevelDialog() -{ - using namespace AzToolsFramework::Prefab; - auto prefabLoaderInterface = AZ::Interface::Get(); - SavePrefabsPreference savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); - - AZStd::shared_ptr saveModifiedMessageBox = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); - AZStd::weak_ptr saveModifiedMessageBoxWeakPtr(saveModifiedMessageBox); - // saveModifiedMessageBox.overrideWindowFlags((saveModifiedMessageBox.windowFlags()) & ~Qt::WindowCloseButtonHint); - saveModifiedMessageBox->setObjectName("SaveDirtyLevelDialog"); - - // Main Content section begins. - QVBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); - QFrame* levelEntitiesSaveQuestionFrame = new QFrame(saveModifiedMessageBox.get()); - QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(saveModifiedMessageBox.get()); - levelEntitiesSaveQuestionFrame->setObjectName("LevelEntitiesSaveQuestionFrame"); - - // Add a warning icon next to save entities question. - levelEntitiesSaveQuestionFrame->setLayout(levelEntitiesSaveQuestionLayout); - QPixmap warningIcon(QString(":/Notifications/warning.svg")); - QLabel* warningIconContainer = new QLabel(); - warningIconContainer->setPixmap(warningIcon); - warningIconContainer->setFixedWidth(warningIcon.width()); - levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); - - // Ask user if they want to save entities in level. - QLabel* levelEntitiesSaveQuestionLabel = new QLabel("Do you want to save unsaved entities in the level?"); - levelEntitiesSaveQuestionLayout->addWidget(levelEntitiesSaveQuestionLabel); - contentLayout->addWidget(levelEntitiesSaveQuestionFrame); - - // Ask user if they want to save unsaved prefabs in the level too. - QCheckBox* saveAllPrefabsCheckbox = new QCheckBox("Save all unsaved prefabs in the level too."); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsCheckbox); - saveAllPrefabsCheckbox->setObjectName("SaveAllPrefabsCheckbox"); - if (savePrefabsPreference == SavePrefabsPreference::SaveAll) - { - saveAllPrefabsCheckbox->setCheckState(Qt::CheckState::Checked); - } - QObject::connect( - saveAllPrefabsCheckbox, &QCheckBox::stateChanged, - [&savePrefabsPreference](int state) - { - savePrefabsPreference = static_cast(state) == Qt::CheckState::Checked ? SavePrefabsPreference::SaveAll - : SavePrefabsPreference::SaveNone; - }); - contentLayout->addWidget(saveAllPrefabsCheckbox); - - // Footer section begins. - QFrame* footerSeparatorLine = new QFrame(); - footerSeparatorLine->setObjectName("FooterSeparatorLine"); - footerSeparatorLine->setFrameShape(QFrame::HLine); - contentLayout->addWidget(footerSeparatorLine); - QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); - - // Provide option for user to remember their prefab save preference. - QCheckBox* saveAllPrefabsPreferenceCheckBox = new QCheckBox("Remember my preference."); - saveAllPrefabsPreferenceCheckBox->setObjectName("SaveAllPrefabsPreferenceCheckBox"); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreferenceCheckBox); - if (savePrefabsPreference != SavePrefabsPreference::Unspecified) - { - saveAllPrefabsPreferenceCheckBox->setCheckState(Qt::CheckState::Checked); - } - QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(saveModifiedMessageBox.get()); - footerPreferenceLayout->addWidget(saveAllPrefabsPreferenceCheckBox); - QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); - prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); - footerPreferenceLayout->addWidget(prefabSavePreferenceHint); - footerLayout->addLayout(footerPreferenceLayout); - QDialogButtonBox* prefabSaveConfirmationButtons = - new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel); - footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); - connect( - prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, saveModifiedMessageBox.get(), - [saveModifiedMessageBoxWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) - { - int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button); - saveModifiedMessageBoxWeakPtr.lock()->done(prefabSaveSelection); - }); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.get(), QStringLiteral("style:Editor.qss")); - return saveModifiedMessageBox; -} - -void CCryEditDoc::ExecuteSavePrefabsDialog() -{ - using namespace AzToolsFramework::Prefab; - - auto prefabSystemComponentInterface = AZ::Interface::Get(); - auto prefabLoaderInterface = AZ::Interface::Get(); - SavePrefabsPreference savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); - - if (savePrefabsPreference == SavePrefabsPreference::SaveAll) - { - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - SetModifiedFlag(false); - } - else if (savePrefabsPreference == SavePrefabsPreference::SaveNone) - { - if (prefabSystemComponentInterface->AreDirtyTemplatesPresent()) - { - SetModifiedFlag(true); - } - } - else // SavePrefabsPreference::Unspecified - { - QDialog saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); - - // Main Content section begins. - saveModifiedMessageBox.setObjectName("SaveAllPrefabsDialog"); - QBoxLayout* contentLayout = new QVBoxLayout(&saveModifiedMessageBox); - QFrame* levelSavedMessageFrame = new QFrame(&saveModifiedMessageBox); - QHBoxLayout* levelSavedMessageLayout = new QHBoxLayout(&saveModifiedMessageBox); - levelSavedMessageFrame->setObjectName("LevelSavedMessageFrame"); - - // Add a checkMark icon next to the level entities saved message. - QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); - QLabel* levelSavedSuccessfullyIconContainer = new QLabel(); - levelSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); - levelSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); - - // Add a message that level entities are saved successfully. - QLabel* levelSavedSuccessfullyLabel = new QLabel("All entities inside level have been saved successfully."); - levelSavedSuccessfullyLabel->setObjectName("LevelSavedSuccessfullyLabel"); - levelSavedMessageLayout->addWidget(levelSavedSuccessfullyIconContainer); - levelSavedMessageLayout->addWidget(levelSavedSuccessfullyLabel); - levelSavedMessageFrame->setLayout(levelSavedMessageLayout); - - QFrame* prefabSaveQuestionFrame = new QFrame(&saveModifiedMessageBox); - QHBoxLayout* prefabSaveQuestionLayout = new QHBoxLayout(&saveModifiedMessageBox); - - // Add a warning icon next to prefabs save question. - QLabel* warningIconContainer = new QLabel(); - QPixmap warningIcon(QString(":/Notifications/warning.svg")); - warningIconContainer->setPixmap(warningIcon); - warningIconContainer->setFixedWidth(warningIcon.width()); - prefabSaveQuestionLayout->addWidget(warningIconContainer); - - // Ask if user wants all prefabs saved. - QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save all unsaved prefabs?"); - prefabSaveQuestionFrame->setObjectName("PrefabSaveQuestionFrame"); - prefabSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); - prefabSaveQuestionFrame->setLayout(prefabSaveQuestionLayout); - contentLayout->addWidget(levelSavedMessageFrame); - contentLayout->addWidget(prefabSaveQuestionFrame); - - // Footer section begins. - QFrame* footerSeparatorLine = new QFrame(); - footerSeparatorLine->setObjectName("FooterSeparatorLine"); - footerSeparatorLine->setFrameShape(QFrame::HLine); - contentLayout->addWidget(footerSeparatorLine); - QHBoxLayout* footerLayout = new QHBoxLayout(&saveModifiedMessageBox); - - // Provide option for user to remember their prefab save preference. - QCheckBox* saveAllPrefabsPreference = new QCheckBox("Remember my preference."); - AzQtComponents::CheckBox::applyToggleSwitchStyle(saveAllPrefabsPreference); - QVBoxLayout* footerPreferenceLayout = new QVBoxLayout(&saveModifiedMessageBox); - footerPreferenceLayout->addWidget(saveAllPrefabsPreference); - QLabel* prefabSavePreferenceHint = new QLabel("You can change this anytime in Edit -> Editor Settings -> GlobalPreferences."); - prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); - footerPreferenceLayout->addWidget(prefabSavePreferenceHint); - footerLayout->addLayout(footerPreferenceLayout); - QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); - footerLayout->addWidget(prefabSaveConfirmationButtons); - contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, &saveModifiedMessageBox, &QDialog::accept); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, &saveModifiedMessageBox, &QDialog::reject); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.parentWidget(), QStringLiteral("style:Editor.qss")); - - int prefabSaveSelection = saveModifiedMessageBox.exec(); - - if (saveAllPrefabsPreference->checkState() == Qt::CheckState::Checked) - { - gSettings.SetSavePrefabsPreference(savePrefabsPreference); - gSettings.Save(); - } - switch (prefabSaveSelection) - { - case QDialog::Accepted: - prefabSystemComponentInterface->SaveAllDirtyTemplates(); - SetModifiedFlag(false); - break; - case QDialog::Rejected: - SetModifiedFlag(true); - break; - } - } -} - namespace AzToolsFramework { void CryEditDocFuncsHandler::Reflect(AZ::ReflectContext* context) diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h index 3a12b461fb..b47f4f0645 100644 --- a/Code/Editor/CryEditDoc.h +++ b/Code/Editor/CryEditDoc.h @@ -13,8 +13,13 @@ #if !defined(Q_MOC_RUN) #include "DocMultiArchive.h" +#include #include +#include +#include +#include #include +#include #include #include #endif @@ -104,12 +109,6 @@ public: // Create from serialization only bool CanCloseFrame(); - //! Returns a Modal containing options to save the current level. - AZStd::shared_ptr ConstructSaveLevelDialog(); - - //! Executes a Modal asking users about their prefabs save preference. - void ExecuteSavePrefabsDialog(); - enum class FetchPolicy { DELETE_FOLDER, @@ -215,6 +214,10 @@ protected: const char* m_envProbeSliceRelativePath = "EngineAssets/Slices/DefaultLevelSetup.slice"; const float m_envProbeHeight = 200.0f; bool m_hasErrors = false; ///< This is used to warn the user that they may lose work when they go to save. + AzToolsFramework::Prefab::PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; + AzToolsFramework::PrefabEditorEntityOwnershipInterface* m_prefabEditorEntityOwnershipInterface = nullptr; + AzToolsFramework::Prefab::PrefabLoaderInterface* m_prefabLoaderInterface = nullptr; + AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr; }; class CAutoDocNotReady diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 9e0d2962a9..4721944b18 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -42,9 +42,9 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector) ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera); - serialize.Class() + serialize.Class() ->Version(1) - ->Field("SavePrefabsPreference", &PrefabSettings::m_savePrefabsPreference); + ->Field("SaveAllPrefabsPreference", &GlobalSaveSettings::m_saveAllPrefabsPreference); serialize.Class() ->Version(2) @@ -68,7 +68,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) serialize.Class() ->Version(1) ->Field("General Settings", &CEditorPreferencesPage_General::m_generalSettings) - ->Field("Prefab Settings", &CEditorPreferencesPage_General::m_prefabSettings) + ->Field("Global Save Settings", &CEditorPreferencesPage_General::m_globalSaveSettings) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) @@ -97,13 +97,13 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); - editContext->Class("Prefabs", "") + editContext->Class("Global Save Settings (File > Save & Ctrl+S)", "") ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &PrefabSettings::m_savePrefabsPreference, "Save Prefabs Preference", - "When saving levels, this option controls whether and how prefabs should be saved along with the level.") - ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::Unspecified, "Unspecified") - ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::SaveAll, "Save All") - ->EnumAttribute(AzToolsFramework::Prefab::SavePrefabsPreference::SaveNone, "Save None"); + AZ::Edit::UIHandlers::ComboBox, &GlobalSaveSettings::m_saveAllPrefabsPreference, "Save Prefabs Preference", + "This option controls whether prefabs should be saved along with the level") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime, "Ask every time") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveAll, "Save all") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveNone, "Save none"); editContext->Class("Messaging", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") @@ -128,7 +128,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_prefabSettings, "Prefabs", "Prefab Settings") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_globalSaveSettings, "Global Save Settings", "Global Save Settings") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") @@ -176,7 +176,7 @@ void CEditorPreferencesPage_General::OnApply() } //prefabs - gSettings.prefabSettings.savePrefabsPreference = m_prefabSettings.m_savePrefabsPreference; + gSettings.globalSaveSettings.saveAllPrefabsPreference = m_globalSaveSettings.m_saveAllPrefabsPreference; //undo gSettings.undoLevels = m_undo.m_undoLevels; @@ -208,7 +208,7 @@ void CEditorPreferencesPage_General::InitializeSettings() m_generalSettings.m_toolbarIconSize = static_cast(gSettings.gui.nToolbarIconSize); //prefabs - m_prefabSettings.m_savePrefabsPreference = gSettings.prefabSettings.savePrefabsPreference; + m_globalSaveSettings.m_saveAllPrefabsPreference = gSettings.globalSaveSettings.saveAllPrefabsPreference; //Messaging m_messaging.m_showDashboard = gSettings.bShowDashboardAtStartup; diff --git a/Code/Editor/EditorPreferencesPageGeneral.h b/Code/Editor/EditorPreferencesPageGeneral.h index b2d652ccba..e5888b2705 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Editor/EditorPreferencesPageGeneral.h @@ -58,10 +58,10 @@ private: bool m_enableSceneInspector; }; - struct PrefabSettings + struct GlobalSaveSettings { - AZ_TYPE_INFO(PrefabSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); - AzToolsFramework::Prefab::SavePrefabsPreference m_savePrefabsPreference; + AZ_TYPE_INFO(GlobalSaveSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); + AzToolsFramework::Prefab::SaveAllPrefabsPreference m_saveAllPrefabsPreference; }; struct Messaging @@ -96,7 +96,7 @@ private: }; GeneralSettings m_generalSettings; - PrefabSettings m_prefabSettings; + GlobalSaveSettings m_globalSaveSettings; Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index d20f132848..4af0989b13 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -255,7 +255,7 @@ SEditorSettings::SEditorSettings() g_TemporaryLevelName = nullptr; sliceSettings.dynamicByDefault = false; - prefabSettings.savePrefabsPreference = AzToolsFramework::Prefab::SavePrefabsPreference::Unspecified; + globalSaveSettings.saveAllPrefabsPreference = AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime; } void SEditorSettings::Connect() @@ -672,7 +672,7 @@ void SEditorSettings::Save() AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = AZ::Interface::Get(); - prefabLoaderInterface->SetSavePrefabsPreference(prefabSettings.savePrefabsPreference); + prefabLoaderInterface->SetSaveAllPrefabsPreference(globalSaveSettings.saveAllPrefabsPreference); SaveSettingsRegistryFile(); } @@ -682,7 +682,7 @@ void SEditorSettings::Load() { AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = AZ::Interface::Get(); - prefabSettings.savePrefabsPreference = prefabLoaderInterface->GetSavePrefabsPreference(); + globalSaveSettings.saveAllPrefabsPreference = prefabLoaderInterface->GetSaveAllPrefabsPreference(); // Load from Settings Registry AzFramework::ApplicationRequests::Bus::BroadcastResult( @@ -1082,11 +1082,6 @@ void SEditorSettings::ConvertPath(const AZStd::string_view sourcePath, AZStd::st AZStd::replace(category.begin(), category.end(), '|', '\\'); } -void SEditorSettings::SetSavePrefabsPreference(AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference) -{ - prefabSettings.savePrefabsPreference = savePrefabsPreference; -} - AzToolsFramework::EditorSettingsAPIRequests::SettingOutcome SEditorSettings::GetValue(const AZStd::string_view path) { if (path.find("|") == AZStd::string_view::npos) diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index dcc96dd2da..fca3480241 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -231,9 +231,9 @@ struct SSliceSettings bool dynamicByDefault; }; -struct SPrefabSettings +struct SGlobalSaveSettings { - AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference; + AzToolsFramework::Prefab::SaveAllPrefabsPreference saveAllPrefabsPreference; }; ////////////////////////////////////////////////////////////////////////// @@ -472,12 +472,10 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING SSliceSettings sliceSettings; - SPrefabSettings prefabSettings; + SGlobalSaveSettings globalSaveSettings; bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities. - void SetSavePrefabsPreference(AzToolsFramework::Prefab::SavePrefabsPreference savePrefabsPreference); - private: void SaveValue(const char* sSection, const char* sKey, int value); void SaveValue(const char* sSection, const char* sKey, const QColor& value); diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index 2999eb388f..72ddeaee5a 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -245,29 +245,44 @@ QTableWidget#recentLevelTable::item { qproperty-iconSize: 16px 16px; } -#LevelSavedMessageFrame{ +QListWidget::item +{ + border : none; +} + +#SavePrefabDialog, #SaveAllFilesDialog +{ + min-width : 640px; +} + +#SaveDependentPrefabsCard +{ + margin: 0px 15px 10px 15px; +} + +#PrefabSavedMessageFrame{ border: 1px solid green; + margin: 10px 15px 10px 15px; border-radius: 2px; - margin: 5px 20px 5px 20px; padding: 5px 2px 5px 2px; } -#SaveAllPrefabsDialog #PrefabSaveQuestionFrame, #SaveDirtyLevelDialog #LevelEntitiesSaveQuestionFrame, #SaveAllPrefabsCheckbox +#SavePrefabDialog #PrefabSaveWarningFrame { border: 1px solid orange; + margin: 10px 15px 10px 15px; border-radius: 2px; - margin: 5px 20px 5px 20px; padding: 5px 2px 5px 2px; color : white; } -#SaveAllPrefabsDialog #FooterSeparatorLine, #SaveDirtyLevelDialog #FooterSeparatorLine +#SaveAllFilesDialog #FooterSeparatorLine, #SavePrefabDialog #FooterSeparatorLine { color: gray; } -#SaveAllPrefabsDialog #PrefabSavePreferenceHint, #SaveDirtyLevelDialog #PrefabSavePreferenceHint +#SaveAllFilesDialog #PrefabSavePreferenceHint, #SavePrefabDialog #PrefabSavePreferenceHint { font: italic; color: #999999; -} +} \ No newline at end of file diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index 1cd36e8055..68b9c1dabb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -43,6 +43,8 @@ namespace AzToolsFramework virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0; + virtual Prefab::TemplateId GetRootPrefabTemplateId() = 0; + //! Get all Assets generated by Prefab processing when entering Play-In Editor mode (Ctrl+G) //! /return The vector of Assets generated by Prefab processing virtual const AZStd::vector>& GetPlayInEditorAssetData() = 0; @@ -54,5 +56,6 @@ namespace AzToolsFramework virtual void StopPlayInEditor() = 0; virtual void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) = 0; + virtual bool IsRootTemplateDirty() = 0; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 7df1e1b5c1..8994adc9af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -359,6 +359,16 @@ namespace AzToolsFramework return AZStd::nullopt; } + Prefab::TemplateId PrefabEditorEntityOwnershipService::GetRootPrefabTemplateId() + { + AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService."); + if (m_rootInstance) + { + return m_rootInstance->GetTemplateId(); + } + return Prefab::InvalidTemplateId; + } + const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData() { return m_playInEditorData.m_assets; @@ -607,6 +617,11 @@ namespace AzToolsFramework m_playInEditorData.m_isEnabled = false; } + bool PrefabEditorEntityOwnershipService::IsRootTemplateDirty() + { + return (m_prefabSystemComponent->IsTemplateDirty(m_rootInstance->GetTemplateId())); + } + ////////////////////////////////////////////////////////////////////////// // Slice Buses implementation with Assert(false), this will exist only during Slice->Prefab // development to pinpoint and replace specific calls to Slice system diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index bf1199d6dd..962b197b5d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -193,8 +193,10 @@ namespace AzToolsFramework AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override; Prefab::InstanceOptionalReference GetRootPrefabInstance() override; + Prefab::TemplateId GetRootPrefabTemplateId() override; const AZStd::vector>& GetPlayInEditorAssetData() override; + bool IsRootTemplateDirty() override; ////////////////////////////////////////////////////////////////////////// void OnEntityRemoved(AZ::EntityId entityId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 2f0a0601b9..7b462e3a2f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -31,10 +31,10 @@ namespace AzToolsFramework { if (auto* serializeContext = azrtti_cast(context)) { - serializeContext->Enum() - ->Value("Unspecified", SavePrefabsPreference::Unspecified) - ->Value("SaveAll", SavePrefabsPreference::SaveAll) - ->Value("SaveNone", SavePrefabsPreference::SaveNone); + serializeContext->Enum() + ->Value("Ask every time", SaveAllPrefabsPreference::AskEveryTime) + ->Value("Save all", SaveAllPrefabsPreference::SaveAll) + ->Value("Save none", SaveAllPrefabsPreference::SaveNone); } } @@ -669,21 +669,21 @@ namespace AzToolsFramework return finalPath; } - SavePrefabsPreference PrefabLoader::GetSavePrefabsPreference() + SaveAllPrefabsPreference PrefabLoader::GetSaveAllPrefabsPreference() { - SavePrefabsPreference savePrefabsPreference = SavePrefabsPreference::Unspecified; + SaveAllPrefabsPreference saveAllPrefabsPreference = SaveAllPrefabsPreference::AskEveryTime; if (auto* registry = AZ::SettingsRegistry::Get()) { - registry->GetObject(savePrefabsPreference, s_savePrefabsKey); + registry->GetObject(saveAllPrefabsPreference, s_savePrefabsKey); } - return savePrefabsPreference; + return saveAllPrefabsPreference; } - void PrefabLoader::SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) + void PrefabLoader::SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) { if (auto* registry = AZ::SettingsRegistry::Get()) { - registry->SetObject(s_savePrefabsKey, savePrefabsPreference); + registry->SetObject(s_savePrefabsKey, saveAllPrefabsPreference); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h index e97eb694c2..5940d887da 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h @@ -110,8 +110,8 @@ namespace AzToolsFramework //! Returns if the path is a valid path for a prefab static bool IsValidPrefabPath(AZ::IO::PathView path); - SavePrefabsPreference GetSavePrefabsPreference() override; - void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) override; + SaveAllPrefabsPreference GetSaveAllPrefabsPreference() override; + void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) override; private: /** diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index 57ef6d6a3a..b34f868304 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -17,9 +17,9 @@ namespace AzToolsFramework { namespace Prefab { - enum class SavePrefabsPreference + enum class SaveAllPrefabsPreference { - Unspecified, + AskEveryTime, SaveAll, SaveNone }; @@ -91,8 +91,8 @@ namespace AzToolsFramework //! The path will always use the '/' separator. virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0; - virtual SavePrefabsPreference GetSavePrefabsPreference() = 0; - virtual void SetSavePrefabsPreference(SavePrefabsPreference savePrefabsPreference) = 0; + virtual SaveAllPrefabsPreference GetSaveAllPrefabsPreference() = 0; + virtual void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) = 0; protected: @@ -105,6 +105,6 @@ namespace AzToolsFramework namespace AZ { - AZ_TYPE_INFO_SPECIALIZE(AzToolsFramework::Prefab::SavePrefabsPreference, "{7E61EA82-4DE4-4A3F-945F-C8FEDC1114B5}"); + AZ_TYPE_INFO_SPECIALIZE(AzToolsFramework::Prefab::SaveAllPrefabsPreference, "{7E61EA82-4DE4-4A3F-945F-C8FEDC1114B5}"); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 928158dae0..e465e111aa 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -754,25 +754,61 @@ namespace AzToolsFramework } } - bool PrefabSystemComponent::AreDirtyTemplatesPresent() + bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId templateId) { - for (const auto& [id, templateObject] : m_templateIdMap) + auto parentTemplate = FindTemplate(templateId); + if (IsTemplateDirty(templateId)) + { + return true; + } + + auto linkIds = parentTemplate->get().GetLinks(); + + for (auto linkId : linkIds) { - if (IsTemplateDirty(id)) + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) { - return true; + return AreDirtyTemplatesPresent(linkIterator->second.GetSourceTemplateId()); } } return false; } - void PrefabSystemComponent::SaveAllDirtyTemplates() + void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId templateId) { - for (auto& [id, templateObject] : m_templateIdMap) + auto parentTemplate = FindTemplate(templateId); + if (IsTemplateDirty(templateId)) + { + m_prefabLoader.SaveTemplate(templateId); + } + auto linkIds = parentTemplate->get().GetLinks(); + + for (auto linkId : linkIds) + { + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) + { + SaveAllDirtyTemplates(linkIterator->second.GetSourceTemplateId()); + } + } + } + + void PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) + { + auto parentTemplate = FindTemplate(parentTemplateId); + if (IsTemplateDirty(parentTemplateId)) + { + dirtyTemplatePaths.emplace(parentTemplate->get().GetFilePath()); + } + auto linkIds = parentTemplate->get().GetLinks(); + + for (auto linkId : linkIds) { - if (IsTemplateDirty(id)) + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) { - m_prefabLoader.SaveTemplate(id); + GetDirtyTemplatePaths(linkIterator->second.GetSourceTemplateId(), dirtyTemplatePaths); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index cb95f9b367..153a0e2b47 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -183,9 +183,11 @@ namespace AzToolsFramework */ void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override; - bool AreDirtyTemplatesPresent() override; + bool AreDirtyTemplatesPresent(TemplateId templateId) override; - void SaveAllDirtyTemplates() override; + void SaveAllDirtyTemplates(TemplateId templateId) override; + + void GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 252c8bdb6a..a5abf138f7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -9,11 +9,12 @@ #pragma once #include +#include +#include #include #include #include #include -#include namespace AzToolsFramework { @@ -49,8 +50,9 @@ namespace AzToolsFramework virtual bool IsTemplateDirty(const TemplateId& templateId) = 0; virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; - virtual bool AreDirtyTemplatesPresent() = 0; - virtual void SaveAllDirtyTemplates() = 0; + virtual bool AreDirtyTemplatesPresent(TemplateId templateId) = 0; + virtual void SaveAllDirtyTemplates(TemplateId templateId) = 0; + virtual void GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h index 0befe55822..afd764232d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AzToolsFramework { @@ -28,6 +29,9 @@ namespace AzToolsFramework * @return The id of the newly created entity. */ virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0; + + virtual int ExecuteClosePrefabDialog(TemplateId templateId) = 0; + virtual void ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0; }; } // namespace Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index c17b96411e..825dea6072 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -27,12 +28,28 @@ #include #include +#include +#include +#include +#include + + #include +#include +#include +#include #include #include +#include +#include +#include #include #include #include +#include +#include +#include + namespace AzToolsFramework { @@ -43,6 +60,7 @@ namespace AzToolsFramework PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr; PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; + PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr; const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; @@ -88,6 +106,13 @@ namespace AzToolsFramework return; } + s_prefabSystemComponentInterface = AZ::Interface::Get(); + if (s_prefabSystemComponentInterface == nullptr) + { + AZ_Assert(false, "Prefab - could not get PrefabSystemComponentInterface on PrefabIntegrationManager construction."); + return; + } + EditorContextMenuBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); @@ -1050,5 +1075,232 @@ namespace AzToolsFramework return AZ::EntityId(); } } + + int PrefabIntegrationManager::ExecuteClosePrefabDialog(TemplateId templateId) + { + auto prefabSaveSelectionDialog = ConstructClosePrefabDialog(templateId); + + int prefabSaveSelection = prefabSaveSelectionDialog->exec(); + + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(prefabSaveSelectionDialog.get()); + } + return prefabSaveSelection; + } + + void PrefabIntegrationManager::ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + { + using namespace AzToolsFramework::Prefab; + + auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); + + if (s_prefabSystemComponentInterface->IsTemplateDirty(templateId)) + { + if (s_prefabLoaderInterface->SaveTemplate(templateId) == false) + { + AZ_Error("Prefabs", false, "Template '%s' could not be saved successfully.", prefabTemplatePath.c_str()); + return; + } + } + + if (useSaveAllPrefabsPreference) + { + SaveAllPrefabsPreference saveAllPrefabsPreference = s_prefabLoaderInterface->GetSaveAllPrefabsPreference(); + + if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveAll) + { + s_prefabSystemComponentInterface->SaveAllDirtyTemplates(templateId); + return; + } + else if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveNone) + { + return; + } + } + + AZStd::unique_ptr savePrefabsDialog = ConstructSavePrefabsDialog(templateId, useSaveAllPrefabsPreference); + if (savePrefabsDialog) + { + int prefabSaveSelection = savePrefabsDialog->exec(); + + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(savePrefabsDialog.get()); + } + } + } + + void PrefabIntegrationManager::SavePrefabsInDialog(QDialog* unsavedPrefabsDialog) + { + QList unsavedPrefabFileLabels = unsavedPrefabsDialog->findChildren("UnsavedPrefabFileName"); + if (unsavedPrefabFileLabels.size() > 0) + { + for (const QLabel* unsavedPrefabFileLabel : unsavedPrefabFileLabels) + { + AZStd::string unsavedPrefabFileName = unsavedPrefabFileLabel->property("FilePath").toString().toUtf8().data(); + AzToolsFramework::Prefab::TemplateId unsavedPrefabTemplateId = + s_prefabSystemComponentInterface->GetTemplateIdFromFilePath(unsavedPrefabFileName.data()); + bool isTemplateSavedSuccessfully = s_prefabLoaderInterface->SaveTemplate(unsavedPrefabTemplateId); + AZ_Assert(isTemplateSavedSuccessfully, "Prefab '%s' could not be saved successfully.", unsavedPrefabFileName.c_str()); + } + } + } + + AZStd::unique_ptr PrefabIntegrationManager::ConstructSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + { + AZStd::unique_ptr saveModifiedMessageBox = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); + + saveModifiedMessageBox->setWindowTitle("Unsaved files detected"); + + // Main Content section begins. + saveModifiedMessageBox->setObjectName("SaveAllFilesDialog"); + QBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); + + QFrame* prefabSavedMessageFrame = new QFrame(saveModifiedMessageBox.get()); + QHBoxLayout* prefabSavedMessageLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + prefabSavedMessageFrame->setObjectName("PrefabSavedMessageFrame"); + prefabSavedMessageFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + + // Add a checkMark icon next to the level entities saved message. + QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); + QLabel* prefabSavedSuccessfullyIconContainer = new QLabel(); + prefabSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); + prefabSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); + + // Add a message that level entities are saved successfully. + + auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); + QLabel* prefabSavedSuccessfullyLabel = new QLabel( + QString("Prefab %1 has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str())); + prefabSavedSuccessfullyLabel->setObjectName("PrefabSavedSuccessfullyLabel"); + prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyIconContainer); + prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyLabel); + prefabSavedMessageFrame->setLayout(prefabSavedMessageLayout); + contentLayout->addWidget(prefabSavedMessageFrame); + + AzQtComponents::Card* unsavedPrefabsContainer = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsContainer); + + contentLayout->addStretch(); + + // Footer section begins. + QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + + if (useSaveAllPrefabsPreference) + { + QFrame* footerSeparatorLine = new QFrame(); + footerSeparatorLine->setObjectName("FooterSeparatorLine"); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + + QLabel* prefabSavePreferenceHint = + new QLabel("You can prevent this window from showing in the future by updating your global save preferences."); + prefabSavePreferenceHint->setToolTip( + "Go to 'Edit > Editor Settings > Global Preferences... > Global save preferences' to update your preference"); + prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + footerLayout->addWidget(prefabSavePreferenceHint); + } + + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox->parentWidget(), QStringLiteral("style:Editor.qss")); + + return AZStd::move(saveModifiedMessageBox); + } + + AZStd::shared_ptr PrefabIntegrationManager::ConstructClosePrefabDialog(TemplateId templateId) + { + AZStd::shared_ptr saveModifiedMessageBox = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox->setWindowTitle("Unsaved files detected"); + AZStd::weak_ptr saveModifiedMessageBoxWeakPtr(saveModifiedMessageBox); + saveModifiedMessageBox->setObjectName("SavePrefabDialog"); + + // Main Content section begins. + QVBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); + QFrame* prefabSaveWarningFrame = new QFrame(saveModifiedMessageBox.get()); + QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + prefabSaveWarningFrame->setObjectName("PrefabSaveWarningFrame"); + + // Add a warning icon next to save prefab warning. + prefabSaveWarningFrame->setLayout(levelEntitiesSaveQuestionLayout); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); + QLabel* warningIconContainer = new QLabel(); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask user if they want to save entities in level. + QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save the below unsaved prefabs?", saveModifiedMessageBox.get()); + levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); + contentLayout->addWidget(prefabSaveWarningFrame); + + AZStd::set dirtyTemplatePaths; + s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); + auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath(); + AzQtComponents::Card* unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsCard); + + contentLayout->addStretch(); + + QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + + QDialogButtonBox* prefabSaveConfirmationButtons = + new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); + QObject::connect( + prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, saveModifiedMessageBox.get(), + [saveModifiedMessageBoxWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) + { + int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button); + saveModifiedMessageBoxWeakPtr.lock()->done(prefabSaveSelection); + }); + AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.get(), QStringLiteral("style:Editor.qss")); + return saveModifiedMessageBox; + } + + AzQtComponents::Card* PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId) + { + FlowLayout* unsavedPrefabsLayout = new FlowLayout; + + AZStd::set dirtyTemplatePaths; + s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); + + for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) + { + QLabel* prefabNameLabel = new QLabel(QString("%1").arg(dirtyTemplatePath.Filename().Native().data())); + prefabNameLabel->setObjectName("UnsavedPrefabFileName"); + prefabNameLabel->setWordWrap(true); + prefabNameLabel->setToolTip(dirtyTemplatePath.Native().data()); + prefabNameLabel->setProperty("FilePath", dirtyTemplatePath.Native().data()); + unsavedPrefabsLayout->addWidget(prefabNameLabel); + } + + AzQtComponents::Card* unsavedPrefabsContainer = new AzQtComponents::Card; + unsavedPrefabsContainer->setObjectName("SaveDependentPrefabsCard"); + unsavedPrefabsContainer->setTitle("Unsaved Prefabs"); + unsavedPrefabsContainer->header()->setHasContextMenu(false); + unsavedPrefabsContainer->header()->setIcon(QIcon(QStringLiteral(":/Entity/prefab_edit.svg"))); + + QFrame* unsavedPrefabsFrame = new QFrame(unsavedPrefabsContainer); + unsavedPrefabsFrame->setLayout(unsavedPrefabsLayout); + QScrollArea* unsavedPrefabsScrollArea = new QScrollArea(); + unsavedPrefabsScrollArea->setWidget(unsavedPrefabsFrame); + //unsavedPrefabsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + unsavedPrefabsScrollArea->setWidgetResizable(true); + unsavedPrefabsScrollArea->setObjectName("SavePrefabsCardContent"); + unsavedPrefabsContainer->setContentWidget(unsavedPrefabsScrollArea); + + return AZStd::move(unsavedPrefabsContainer); + } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index b40f0169c9..8a210c2de0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include #include #include +#include + namespace AzToolsFramework { namespace Prefab @@ -49,6 +52,7 @@ namespace AzToolsFramework , public AssetBrowser::AssetBrowserSourceDropBus::Handler , public PrefabInstanceContainerNotificationBus::Handler , public PrefabIntegrationInterface + , public QObject { public: AZ_CLASS_ALLOCATOR(PrefabIntegrationManager, AZ::SystemAllocator, 0); @@ -72,6 +76,8 @@ namespace AzToolsFramework // PrefabIntegrationInterface... AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override; + int ExecuteClosePrefabDialog(TemplateId templateId) override; + void ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; private: // Manages the Edit Mode UI for prefabs @@ -124,12 +130,19 @@ namespace AzToolsFramework static AZ::u32 GetSliceFlags(const AZ::Edit::ElementData* editData, const AZ::Edit::ClassData* classData); + AZStd::shared_ptr ConstructClosePrefabDialog(TemplateId templateId); + AzQtComponents::Card* ConstructUnsavedPrefabsCard(TemplateId templateId); + AZStd::unique_ptr ConstructSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); + void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog); + + static const AZStd::string s_prefabFileExtension; static EditorEntityUiInterface* s_editorEntityUiInterface; static PrefabPublicInterface* s_prefabPublicInterface; static PrefabEditInterface* s_prefabEditInterface; static PrefabLoaderInterface* s_prefabLoaderInterface; + static PrefabSystemComponentInterface* s_prefabSystemComponentInterface; }; } } From 7e75559200ed3d9c9fd8783d34a76a346dbde87a Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Thu, 2 Sep 2021 17:26:32 -0700 Subject: [PATCH 09/17] Removed unused Qt classes and do some more code clean up Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 15 +-------------- Code/Editor/CryEditDoc.cpp | 9 --------- Code/Editor/EditorPreferencesPageGeneral.cpp | 2 +- Code/Editor/Style/Editor.qss | 5 ----- .../Entity/PrefabEditorEntityOwnershipInterface.h | 1 - .../Entity/PrefabEditorEntityOwnershipService.cpp | 5 ----- .../Entity/PrefabEditorEntityOwnershipService.h | 1 - .../AzToolsFramework/Prefab/PrefabLoader.cpp | 6 +++--- .../UI/Prefab/PrefabIntegrationInterface.h | 2 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 12 ++++++------ .../UI/Prefab/PrefabIntegrationManager.h | 4 ++-- 11 files changed, 14 insertions(+), 48 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index ecbdde7f13..4725101599 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -33,9 +33,7 @@ AZ_POP_DISABLE_WARNING #include #include #include -#include #include -#include // Aws Native SDK #include @@ -71,12 +69,10 @@ AZ_POP_DISABLE_WARNING #include #include #include -#include #include // AzQtComponents #include -#include #include #include #include @@ -742,12 +738,10 @@ void CCryEditApp::OnFileSave() } else { - //auto prefabSystemComponentInterface = AZ::Interface::Get(); auto prefabEditorEntityOwnershipService = AZ::Interface::Get(); AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipService->GetRootPrefabTemplateId(); auto prefabIntegrationInterface = AZ::Interface::Get(); - prefabIntegrationInterface->ExecuteSavePrefabsDialog(rootPrefabTemplateId, true); - // prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId) + prefabIntegrationInterface->ExecuteSavePrefabDialog(rootPrefabTemplateId, true); } } @@ -3204,13 +3198,6 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: - if (!GetIEditor()->GetDocument()->DoFileSave()) - { - // if the file save operation failed, assume that the user was informed of why - // already and treat it as a cancel - wasCreateLevelOperationCancelled = true; - return false; - } bIsDocModified = false; break; case QDialogButtonBox::RejectRole: diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 3fb39d4268..2985f9fec2 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -13,16 +13,7 @@ // Qt #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include // AzCore #include diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 4721944b18..2cba7e7801 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -97,7 +97,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); - editContext->Class("Global Save Settings (File > Save & Ctrl+S)", "") + editContext->Class("Global Save Settings (File>Save & Ctrl+S)", "") ->DataElement( AZ::Edit::UIHandlers::ComboBox, &GlobalSaveSettings::m_saveAllPrefabsPreference, "Save Prefabs Preference", "This option controls whether prefabs should be saved along with the level") diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index 72ddeaee5a..3bf92b4495 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -245,11 +245,6 @@ QTableWidget#recentLevelTable::item { qproperty-iconSize: 16px 16px; } -QListWidget::item -{ - border : none; -} - #SavePrefabDialog, #SaveAllFilesDialog { min-width : 640px; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index 68b9c1dabb..feb2fc12bf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -56,6 +56,5 @@ namespace AzToolsFramework virtual void StopPlayInEditor() = 0; virtual void CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) = 0; - virtual bool IsRootTemplateDirty() = 0; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 8994adc9af..c9365683b5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -617,11 +617,6 @@ namespace AzToolsFramework m_playInEditorData.m_isEnabled = false; } - bool PrefabEditorEntityOwnershipService::IsRootTemplateDirty() - { - return (m_prefabSystemComponent->IsTemplateDirty(m_rootInstance->GetTemplateId())); - } - ////////////////////////////////////////////////////////////////////////// // Slice Buses implementation with Assert(false), this will exist only during Slice->Prefab // development to pinpoint and replace specific calls to Slice system diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index 962b197b5d..a98fce8059 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -196,7 +196,6 @@ namespace AzToolsFramework Prefab::TemplateId GetRootPrefabTemplateId() override; const AZStd::vector>& GetPlayInEditorAssetData() override; - bool IsRootTemplateDirty() override; ////////////////////////////////////////////////////////////////////////// void OnEntityRemoved(AZ::EntityId entityId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 7b462e3a2f..8be3b402fa 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -25,7 +25,7 @@ namespace AzToolsFramework { namespace Prefab { - static constexpr const char s_savePrefabsKey[] = "/O3DE/Preferences/SavePrefabs"; + static constexpr const char s_saveAllPrefabsKey[] = "/O3DE/Preferences/SaveAllPrefabs"; void PrefabLoader::Reflect(AZ::ReflectContext* context) { @@ -674,7 +674,7 @@ namespace AzToolsFramework SaveAllPrefabsPreference saveAllPrefabsPreference = SaveAllPrefabsPreference::AskEveryTime; if (auto* registry = AZ::SettingsRegistry::Get()) { - registry->GetObject(saveAllPrefabsPreference, s_savePrefabsKey); + registry->GetObject(saveAllPrefabsPreference, s_saveAllPrefabsKey); } return saveAllPrefabsPreference; } @@ -683,7 +683,7 @@ namespace AzToolsFramework { if (auto* registry = AZ::SettingsRegistry::Get()) { - registry->SetObject(s_savePrefabsKey, saveAllPrefabsPreference); + registry->SetObject(s_saveAllPrefabsKey, saveAllPrefabsPreference); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h index afd764232d..f5f393f3b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h @@ -31,7 +31,7 @@ namespace AzToolsFramework virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0; virtual int ExecuteClosePrefabDialog(TemplateId templateId) = 0; - virtual void ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0; + virtual void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0; }; } // namespace Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 825dea6072..42d8ec80bf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1089,7 +1089,7 @@ namespace AzToolsFramework return prefabSaveSelection; } - void PrefabIntegrationManager::ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + void PrefabIntegrationManager::ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) { using namespace AzToolsFramework::Prefab; @@ -1120,14 +1120,14 @@ namespace AzToolsFramework } } - AZStd::unique_ptr savePrefabsDialog = ConstructSavePrefabsDialog(templateId, useSaveAllPrefabsPreference); - if (savePrefabsDialog) + AZStd::unique_ptr savePrefabDialog = ConstructSavePrefabDialog(templateId, useSaveAllPrefabsPreference); + if (savePrefabDialog) { - int prefabSaveSelection = savePrefabsDialog->exec(); + int prefabSaveSelection = savePrefabDialog->exec(); if (prefabSaveSelection == QDialog::Accepted) { - SavePrefabsInDialog(savePrefabsDialog.get()); + SavePrefabsInDialog(savePrefabDialog.get()); } } } @@ -1148,7 +1148,7 @@ namespace AzToolsFramework } } - AZStd::unique_ptr PrefabIntegrationManager::ConstructSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + AZStd::unique_ptr PrefabIntegrationManager::ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) { AZStd::unique_ptr saveModifiedMessageBox = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 8a210c2de0..64d3b652fc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -77,7 +77,7 @@ namespace AzToolsFramework // PrefabIntegrationInterface... AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override; int ExecuteClosePrefabDialog(TemplateId templateId) override; - void ExecuteSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; + void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; private: // Manages the Edit Mode UI for prefabs @@ -132,7 +132,7 @@ namespace AzToolsFramework AZStd::shared_ptr ConstructClosePrefabDialog(TemplateId templateId); AzQtComponents::Card* ConstructUnsavedPrefabsCard(TemplateId templateId); - AZStd::unique_ptr ConstructSavePrefabsDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); + AZStd::unique_ptr ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog); From 5a8998add11b6657d6b365802943240086fae584 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Thu, 2 Sep 2021 23:35:28 -0700 Subject: [PATCH 10/17] Added function comments and nullptr checks Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 28 ++-- Code/Editor/Style/Editor.qss | 9 +- .../Prefab/PrefabSystemComponent.cpp | 49 ++++--- .../Prefab/PrefabSystemComponentInterface.h | 10 ++ .../UI/Prefab/PrefabIntegrationInterface.h | 6 + .../UI/Prefab/PrefabIntegrationManager.cpp | 123 ++++++++++-------- .../UI/Prefab/PrefabIntegrationManager.h | 2 +- 7 files changed, 137 insertions(+), 90 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 4725101599..2e738a18c5 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -723,24 +723,22 @@ void CCryEditApp::OnFileSave() } const QScopedValueRollback rollback(m_savingLevel, true); - - bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); - - if (!usePrefabSystemForLevels) { GetIEditor()->GetDocument()->DoFileSave(); } else { - auto prefabEditorEntityOwnershipService = AZ::Interface::Get(); - AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipService->GetRootPrefabTemplateId(); - auto prefabIntegrationInterface = AZ::Interface::Get(); + auto* prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + auto* prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found."); + AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found."); + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); prefabIntegrationInterface->ExecuteSavePrefabDialog(rootPrefabTemplateId, true); } } @@ -3187,12 +3185,18 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) } else { - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - auto prefabIntegrationInterface = AZ::Interface::Get(); - AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + auto* prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + auto* prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found."); + AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found."); - int prefabSaveSelection = - prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); + if (prefabEditorEntityOwnershipInterface == nullptr || prefabIntegrationInterface == nullptr) + { + return false; + } + + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + int prefabSaveSelection = prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. switch (1 - prefabSaveSelection) diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index 3bf92b4495..302b7703a5 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -245,7 +245,8 @@ QTableWidget#recentLevelTable::item { qproperty-iconSize: 16px 16px; } -#SavePrefabDialog, #SaveAllFilesDialog + +#ClosePrefabDialog, #SavePrefabDialog { min-width : 640px; } @@ -262,7 +263,7 @@ QTableWidget#recentLevelTable::item { padding: 5px 2px 5px 2px; } -#SavePrefabDialog #PrefabSaveWarningFrame +#ClosePrefabDialog #PrefabSaveWarningFrame { border: 1px solid orange; margin: 10px 15px 10px 15px; @@ -271,12 +272,12 @@ QTableWidget#recentLevelTable::item { color : white; } -#SaveAllFilesDialog #FooterSeparatorLine, #SavePrefabDialog #FooterSeparatorLine +#SavePrefabDialog #FooterSeparatorLine { color: gray; } -#SaveAllFilesDialog #PrefabSavePreferenceHint, #SavePrefabDialog #PrefabSavePreferenceHint +#SavePrefabDialog #PrefabSavePreferenceHint { font: italic; color: #999999; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index e465e111aa..a2ef30d1f7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -756,13 +756,20 @@ namespace AzToolsFramework bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId templateId) { - auto parentTemplate = FindTemplate(templateId); + auto prefabTemplate = FindTemplate(templateId); + + if (!prefabTemplate.has_value()) + { + AZ_Assert(false, "Template with id %llu is not found", templateId); + return false; + } + if (IsTemplateDirty(templateId)) { return true; } - auto linkIds = parentTemplate->get().GetLinks(); + auto linkIds = prefabTemplate->get().GetLinks(); for (auto linkId : linkIds) { @@ -777,31 +784,39 @@ namespace AzToolsFramework void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId templateId) { - auto parentTemplate = FindTemplate(templateId); - if (IsTemplateDirty(templateId)) - { - m_prefabLoader.SaveTemplate(templateId); - } - auto linkIds = parentTemplate->get().GetLinks(); + AZStd::set dirtyTemplatePaths; + GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); - for (auto linkId : linkIds) + for (auto dirtyTemplatePath : dirtyTemplatePaths) { - auto linkIterator = m_linkIdMap.find(linkId); - if (linkIterator != m_linkIdMap.end()) + auto dirtyTemplateIterator = m_templateFilePathToIdMap.find(dirtyTemplatePath); + if (dirtyTemplateIterator == m_templateFilePathToIdMap.end()) { - SaveAllDirtyTemplates(linkIterator->second.GetSourceTemplateId()); + AZ_Assert(false, "Template id for template with path '%s' is not found.", dirtyTemplatePath); + } + else + { + m_prefabLoader.SaveTemplate(dirtyTemplateIterator->second); } } } - void PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) + void PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId templateId, AZStd::set& dirtyTemplatePaths) { - auto parentTemplate = FindTemplate(parentTemplateId); - if (IsTemplateDirty(parentTemplateId)) + auto prefabTemplate = FindTemplate(templateId); + + if (!prefabTemplate.has_value()) + { + AZ_Assert(false, "Template with id %llu is not found", templateId); + return; + } + + if (IsTemplateDirty(templateId)) { - dirtyTemplatePaths.emplace(parentTemplate->get().GetFilePath()); + dirtyTemplatePaths.emplace(prefabTemplate->get().GetFilePath()); } - auto linkIds = parentTemplate->get().GetLinks(); + + auto linkIds = prefabTemplate->get().GetLinks(); for (auto linkId : linkIds) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index a5abf138f7..98e7719907 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -50,8 +50,18 @@ namespace AzToolsFramework virtual bool IsTemplateDirty(const TemplateId& templateId) = 0; virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; + + //! Recursive function to check if the template is dirty or if any dirty templates are presents in the links of the template. + //! @param templateId The id of the template provided as the beginning template to check the outgoing links. virtual bool AreDirtyTemplatesPresent(TemplateId templateId) = 0; + + //! Recursive function to save if the template is dirty and save all the dirty templates in the links of the template. + //! @param templateId The id of the template provided as the beginning template to check the outgoing links. virtual void SaveAllDirtyTemplates(TemplateId templateId) = 0; + + //! Recursive function that fetches the set of dirty templates given a starting template to check for outgoing links. + //! @param templateId The id of the template provided as the beginning template to check the outgoing links. + //! @param[out] dirtyTemplatePaths The set of dirty template paths populated. virtual void GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h index f5f393f3b8..e92f08f9ff 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h @@ -30,7 +30,13 @@ namespace AzToolsFramework */ virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0; + //! Constructs and executes the close dialog on a prefab template corresponding to templateId. + //! @param templateId The id of the template the user chose to close. virtual int ExecuteClosePrefabDialog(TemplateId templateId) = 0; + + //! Constructs and executes the save dialog on a prefab template corresponding to templateId. + //! @param templateId The id of the template the user chose to save. + //! @param useSaveAllPrefabsPreference A flag indicating whether SaveAllPrefabsPreference should be used for saving templates. virtual void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 42d8ec80bf..ad3ac9e69f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -63,6 +63,16 @@ namespace AzToolsFramework PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr; const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; + + static constexpr char* const ClosePrefabDialog = "ClosePrefabDialog"; + static constexpr char* const FooterSeparatorLine = "FooterSeparatorLine"; + static constexpr char* const PrefabSavedMessageFrame = "PrefabSavedMessageFrame"; + static constexpr char* const PrefabSavePreferenceHint = "PrefabSavePreferenceHint"; + static constexpr char* const PrefabSaveWarningFrame = "PrefabSaveWarningFrame"; + static constexpr char* const SaveDependentPrefabsCard = "SaveDependentPrefabsCard"; + static constexpr char* const SavePrefabDialog = "SavePrefabDialog"; + static constexpr char* const UnsavedPrefabFileName = "UnsavedPrefabFileName"; + void PrefabUserSettings::Reflect(AZ::ReflectContext* context) { @@ -1100,7 +1110,7 @@ namespace AzToolsFramework { if (s_prefabLoaderInterface->SaveTemplate(templateId) == false) { - AZ_Error("Prefabs", false, "Template '%s' could not be saved successfully.", prefabTemplatePath.c_str()); + AZ_Error("Prefab", false, "Template '%s' could not be saved successfully.", prefabTemplatePath.c_str()); return; } } @@ -1134,7 +1144,7 @@ namespace AzToolsFramework void PrefabIntegrationManager::SavePrefabsInDialog(QDialog* unsavedPrefabsDialog) { - QList unsavedPrefabFileLabels = unsavedPrefabsDialog->findChildren("UnsavedPrefabFileName"); + QList unsavedPrefabFileLabels = unsavedPrefabsDialog->findChildren(UnsavedPrefabFileName); if (unsavedPrefabFileLabels.size() > 0) { for (const QLabel* unsavedPrefabFileLabel : unsavedPrefabFileLabels) @@ -1150,22 +1160,22 @@ namespace AzToolsFramework AZStd::unique_ptr PrefabIntegrationManager::ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) { - AZStd::unique_ptr saveModifiedMessageBox = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); + AZStd::unique_ptr savePrefabDialog = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); - saveModifiedMessageBox->setWindowTitle("Unsaved files detected"); + savePrefabDialog->setWindowTitle("Unsaved files detected"); // Main Content section begins. - saveModifiedMessageBox->setObjectName("SaveAllFilesDialog"); - QBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); + savePrefabDialog->setObjectName(SavePrefabDialog); + QBoxLayout* contentLayout = new QVBoxLayout(savePrefabDialog.get()); - QFrame* prefabSavedMessageFrame = new QFrame(saveModifiedMessageBox.get()); - QHBoxLayout* prefabSavedMessageLayout = new QHBoxLayout(saveModifiedMessageBox.get()); - prefabSavedMessageFrame->setObjectName("PrefabSavedMessageFrame"); + QFrame* prefabSavedMessageFrame = new QFrame(savePrefabDialog.get()); + QHBoxLayout* prefabSavedMessageLayout = new QHBoxLayout(savePrefabDialog.get()); + prefabSavedMessageFrame->setObjectName(PrefabSavedMessageFrame); prefabSavedMessageFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); // Add a checkMark icon next to the level entities saved message. QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); - QLabel* prefabSavedSuccessfullyIconContainer = new QLabel(); + QLabel* prefabSavedSuccessfullyIconContainer = new QLabel(savePrefabDialog.get()); prefabSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); prefabSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); @@ -1174,69 +1184,71 @@ namespace AzToolsFramework auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); QLabel* prefabSavedSuccessfullyLabel = new QLabel( - QString("Prefab %1 has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str())); - prefabSavedSuccessfullyLabel->setObjectName("PrefabSavedSuccessfullyLabel"); + QString("Prefab %1 has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str()), + savePrefabDialog.get()); prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyIconContainer); prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyLabel); prefabSavedMessageFrame->setLayout(prefabSavedMessageLayout); contentLayout->addWidget(prefabSavedMessageFrame); - AzQtComponents::Card* unsavedPrefabsContainer = ConstructUnsavedPrefabsCard(templateId); - contentLayout->addWidget(unsavedPrefabsContainer); + AZStd::unique_ptr unsavedPrefabsContainer = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsContainer.release()); contentLayout->addStretch(); // Footer section begins. - QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + QHBoxLayout* footerLayout = new QHBoxLayout(savePrefabDialog.get()); if (useSaveAllPrefabsPreference) { - QFrame* footerSeparatorLine = new QFrame(); - footerSeparatorLine->setObjectName("FooterSeparatorLine"); + QFrame* footerSeparatorLine = new QFrame(savePrefabDialog.get()); + footerSeparatorLine->setObjectName(FooterSeparatorLine); footerSeparatorLine->setFrameShape(QFrame::HLine); contentLayout->addWidget(footerSeparatorLine); - QLabel* prefabSavePreferenceHint = - new QLabel("You can prevent this window from showing in the future by updating your global save preferences."); + QLabel* prefabSavePreferenceHint = new QLabel( + "You can prevent this window from showing in the future by updating your global save preferences.", + savePrefabDialog.get()); prefabSavePreferenceHint->setToolTip( "Go to 'Edit > Editor Settings > Global Preferences... > Global save preferences' to update your preference"); - prefabSavePreferenceHint->setObjectName("PrefabSavePreferenceHint"); + prefabSavePreferenceHint->setObjectName(PrefabSavePreferenceHint); footerLayout->addWidget(prefabSavePreferenceHint); } - QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No); + QDialogButtonBox* prefabSaveConfirmationButtons = + new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No, savePrefabDialog.get()); footerLayout->addWidget(prefabSaveConfirmationButtons); contentLayout->addLayout(footerLayout); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); - connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox->parentWidget(), QStringLiteral("style:Editor.qss")); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, savePrefabDialog.get(), &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, savePrefabDialog.get(), &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(savePrefabDialog->parentWidget(), QStringLiteral("style:Editor.qss")); - return AZStd::move(saveModifiedMessageBox); + return AZStd::move(savePrefabDialog); } AZStd::shared_ptr PrefabIntegrationManager::ConstructClosePrefabDialog(TemplateId templateId) { - AZStd::shared_ptr saveModifiedMessageBox = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); - saveModifiedMessageBox->setWindowTitle("Unsaved files detected"); - AZStd::weak_ptr saveModifiedMessageBoxWeakPtr(saveModifiedMessageBox); - saveModifiedMessageBox->setObjectName("SavePrefabDialog"); + AZStd::shared_ptr closePrefabDialog = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); + closePrefabDialog->setWindowTitle("Unsaved files detected"); + AZStd::weak_ptr closePrefabDialogWeakPtr(closePrefabDialog); + closePrefabDialog->setObjectName(ClosePrefabDialog); // Main Content section begins. - QVBoxLayout* contentLayout = new QVBoxLayout(saveModifiedMessageBox.get()); - QFrame* prefabSaveWarningFrame = new QFrame(saveModifiedMessageBox.get()); - QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(saveModifiedMessageBox.get()); - prefabSaveWarningFrame->setObjectName("PrefabSaveWarningFrame"); + QVBoxLayout* contentLayout = new QVBoxLayout(closePrefabDialog.get()); + QFrame* prefabSaveWarningFrame = new QFrame(closePrefabDialog.get()); + QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(closePrefabDialog.get()); + prefabSaveWarningFrame->setObjectName(PrefabSaveWarningFrame); // Add a warning icon next to save prefab warning. prefabSaveWarningFrame->setLayout(levelEntitiesSaveQuestionLayout); QPixmap warningIcon(QString(":/Notifications/warning.svg")); - QLabel* warningIconContainer = new QLabel(); + QLabel* warningIconContainer = new QLabel(closePrefabDialog.get()); warningIconContainer->setPixmap(warningIcon); warningIconContainer->setFixedWidth(warningIcon.width()); levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); // Ask user if they want to save entities in level. - QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save the below unsaved prefabs?", saveModifiedMessageBox.get()); + QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save the below unsaved prefabs?", closePrefabDialog.get()); levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); contentLayout->addWidget(prefabSaveWarningFrame); @@ -1244,60 +1256,59 @@ namespace AzToolsFramework s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath(); - AzQtComponents::Card* unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); - contentLayout->addWidget(unsavedPrefabsCard); + AZStd::unique_ptr unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsCard.release()); contentLayout->addStretch(); - QHBoxLayout* footerLayout = new QHBoxLayout(saveModifiedMessageBox.get()); + QHBoxLayout* footerLayout = new QHBoxLayout(closePrefabDialog.get()); - QDialogButtonBox* prefabSaveConfirmationButtons = - new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel); + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox( + QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel, closePrefabDialog.get()); footerLayout->addWidget(prefabSaveConfirmationButtons); contentLayout->addLayout(footerLayout); - QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, saveModifiedMessageBox.get(), &QDialog::accept); - QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, saveModifiedMessageBox.get(), &QDialog::reject); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, closePrefabDialog.get(), &QDialog::accept); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, closePrefabDialog.get(), &QDialog::reject); QObject::connect( - prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, saveModifiedMessageBox.get(), - [saveModifiedMessageBoxWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) + prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, closePrefabDialog.get(), + [closePrefabDialogWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) { int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button); - saveModifiedMessageBoxWeakPtr.lock()->done(prefabSaveSelection); + closePrefabDialogWeakPtr.lock()->done(prefabSaveSelection); }); - AzQtComponents::StyleManager::setStyleSheet(saveModifiedMessageBox.get(), QStringLiteral("style:Editor.qss")); - return saveModifiedMessageBox; + AzQtComponents::StyleManager::setStyleSheet(closePrefabDialog.get(), QStringLiteral("style:Editor.qss")); + return closePrefabDialog; } - AzQtComponents::Card* PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId) + AZStd::unique_ptr PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId) { - FlowLayout* unsavedPrefabsLayout = new FlowLayout; + FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow()); AZStd::set dirtyTemplatePaths; s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) { - QLabel* prefabNameLabel = new QLabel(QString("%1").arg(dirtyTemplatePath.Filename().Native().data())); - prefabNameLabel->setObjectName("UnsavedPrefabFileName"); + QLabel* prefabNameLabel = + new QLabel(QString("%1").arg(dirtyTemplatePath.Filename().Native().data()), AzToolsFramework::GetActiveWindow()); + prefabNameLabel->setObjectName(UnsavedPrefabFileName); prefabNameLabel->setWordWrap(true); prefabNameLabel->setToolTip(dirtyTemplatePath.Native().data()); prefabNameLabel->setProperty("FilePath", dirtyTemplatePath.Native().data()); unsavedPrefabsLayout->addWidget(prefabNameLabel); } - AzQtComponents::Card* unsavedPrefabsContainer = new AzQtComponents::Card; + AZStd::unique_ptr unsavedPrefabsContainer = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); unsavedPrefabsContainer->setObjectName("SaveDependentPrefabsCard"); unsavedPrefabsContainer->setTitle("Unsaved Prefabs"); unsavedPrefabsContainer->header()->setHasContextMenu(false); unsavedPrefabsContainer->header()->setIcon(QIcon(QStringLiteral(":/Entity/prefab_edit.svg"))); - QFrame* unsavedPrefabsFrame = new QFrame(unsavedPrefabsContainer); + QFrame* unsavedPrefabsFrame = new QFrame(unsavedPrefabsContainer.get()); unsavedPrefabsFrame->setLayout(unsavedPrefabsLayout); - QScrollArea* unsavedPrefabsScrollArea = new QScrollArea(); + QScrollArea* unsavedPrefabsScrollArea = new QScrollArea(unsavedPrefabsContainer.get()); unsavedPrefabsScrollArea->setWidget(unsavedPrefabsFrame); - //unsavedPrefabsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); unsavedPrefabsScrollArea->setWidgetResizable(true); - unsavedPrefabsScrollArea->setObjectName("SavePrefabsCardContent"); unsavedPrefabsContainer->setContentWidget(unsavedPrefabsScrollArea); return AZStd::move(unsavedPrefabsContainer); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 64d3b652fc..3e66350932 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -131,7 +131,7 @@ namespace AzToolsFramework static AZ::u32 GetSliceFlags(const AZ::Edit::ElementData* editData, const AZ::Edit::ClassData* classData); AZStd::shared_ptr ConstructClosePrefabDialog(TemplateId templateId); - AzQtComponents::Card* ConstructUnsavedPrefabsCard(TemplateId templateId); + AZStd::unique_ptr ConstructUnsavedPrefabsCard(TemplateId templateId); AZStd::unique_ptr ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog); From 8331b8dd8ad26b84928817b3cc3490508b04c458 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Fri, 3 Sep 2021 01:34:32 -0700 Subject: [PATCH 11/17] Fix a compile error by changing to const instead of constexpr Signed-off-by: srikappa-amzn --- .../UI/Prefab/PrefabIntegrationManager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index ca09bbe88d..3df7e68008 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -64,14 +64,14 @@ namespace AzToolsFramework const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; - static constexpr char* const ClosePrefabDialog = "ClosePrefabDialog"; - static constexpr char* const FooterSeparatorLine = "FooterSeparatorLine"; - static constexpr char* const PrefabSavedMessageFrame = "PrefabSavedMessageFrame"; - static constexpr char* const PrefabSavePreferenceHint = "PrefabSavePreferenceHint"; - static constexpr char* const PrefabSaveWarningFrame = "PrefabSaveWarningFrame"; - static constexpr char* const SaveDependentPrefabsCard = "SaveDependentPrefabsCard"; - static constexpr char* const SavePrefabDialog = "SavePrefabDialog"; - static constexpr char* const UnsavedPrefabFileName = "UnsavedPrefabFileName"; + static const char* const ClosePrefabDialog = "ClosePrefabDialog"; + static const char* const FooterSeparatorLine = "FooterSeparatorLine"; + static const char* const PrefabSavedMessageFrame = "PrefabSavedMessageFrame"; + static const char* const PrefabSavePreferenceHint = "PrefabSavePreferenceHint"; + static const char* const PrefabSaveWarningFrame = "PrefabSaveWarningFrame"; + static const char* const SaveDependentPrefabsCard = "SaveDependentPrefabsCard"; + static const char* const SavePrefabDialog = "SavePrefabDialog"; + static const char* const UnsavedPrefabFileName = "UnsavedPrefabFileName"; void PrefabUserSettings::Reflect(AZ::ReflectContext* context) From f6ce3678fa4d71f0ea620773afc1f09ca5f7c7c4 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Fri, 3 Sep 2021 12:34:32 -0700 Subject: [PATCH 12/17] Used actual types instead of auto and some more minor changes Signed-off-by: srikappa-amzn --- Code/Editor/CryEdit.cpp | 2 ++ Code/Editor/CryEditDoc.cpp | 6 ++-- Code/Editor/EditorPreferencesPageGeneral.cpp | 4 +-- .../PrefabEditorEntityOwnershipService.cpp | 6 +--- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- .../AzToolsFramework/Prefab/PrefabLoader.h | 2 +- .../Prefab/PrefabLoaderInterface.h | 2 +- .../Prefab/PrefabSystemComponent.cpp | 32 ++++++++++++------- .../Prefab/PrefabSystemComponent.h | 5 ++- .../Prefab/PrefabSystemComponentInterface.h | 4 +-- .../UI/Prefab/PrefabIntegrationManager.cpp | 10 +++--- 11 files changed, 41 insertions(+), 34 deletions(-) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 5c0938216a..b5eb4229df 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -3193,6 +3193,8 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) int prefabSaveSelection = prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. + // For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to + // QDialogButtonBox::AcceptRole(0). switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 5df046bf54..b1186202f9 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -699,9 +699,7 @@ bool CCryEditDoc::SaveModified() } else { - using namespace AzToolsFramework::Prefab; - - TemplateId rootPrefabTemplateId = m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); if (!m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId)) { return true; @@ -710,6 +708,8 @@ bool CCryEditDoc::SaveModified() int prefabSaveSelection = m_prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. + // For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to + // QDialogButtonBox::AcceptRole(0). switch (1 - prefabSaveSelection) { case QDialogButtonBox::AcceptRole: diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 2cba7e7801..2b044e800a 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -97,7 +97,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); - editContext->Class("Global Save Settings (File>Save & Ctrl+S)", "") + editContext->Class("Global Save Settings", "") ->DataElement( AZ::Edit::UIHandlers::ComboBox, &GlobalSaveSettings::m_saveAllPrefabsPreference, "Save Prefabs Preference", "This option controls whether prefabs should be saved along with the level") @@ -128,7 +128,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_globalSaveSettings, "Global Save Settings", "Global Save Settings") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_globalSaveSettings, "Global Save Settings", "Global Save Settings (File>Save & Ctrl+S)") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index c9365683b5..114f45d501 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -362,11 +362,7 @@ namespace AzToolsFramework Prefab::TemplateId PrefabEditorEntityOwnershipService::GetRootPrefabTemplateId() { AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService."); - if (m_rootInstance) - { - return m_rootInstance->GetTemplateId(); - } - return Prefab::InvalidTemplateId; + return m_rootInstance ? m_rootInstance->GetTemplateId() : Prefab::InvalidTemplateId; } const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 666386d4aa..3db78b1d39 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -670,7 +670,7 @@ namespace AzToolsFramework return finalPath; } - SaveAllPrefabsPreference PrefabLoader::GetSaveAllPrefabsPreference() + SaveAllPrefabsPreference PrefabLoader::GetSaveAllPrefabsPreference() const { SaveAllPrefabsPreference saveAllPrefabsPreference = SaveAllPrefabsPreference::AskEveryTime; if (auto* registry = AZ::SettingsRegistry::Get()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h index 5940d887da..15f201e027 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h @@ -110,7 +110,7 @@ namespace AzToolsFramework //! Returns if the path is a valid path for a prefab static bool IsValidPrefabPath(AZ::IO::PathView path); - SaveAllPrefabsPreference GetSaveAllPrefabsPreference() override; + SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const override; void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) override; private: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index b34f868304..a428f8a7b9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -91,7 +91,7 @@ namespace AzToolsFramework //! The path will always use the '/' separator. virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0; - virtual SaveAllPrefabsPreference GetSaveAllPrefabsPreference() = 0; + virtual SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const = 0; virtual void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) = 0; protected: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index a4fbd1e251..9059bf5368 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -756,7 +756,7 @@ namespace AzToolsFramework bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId templateId) { - auto prefabTemplate = FindTemplate(templateId); + TemplateReference prefabTemplate = FindTemplate(templateId); if (!prefabTemplate.has_value()) { @@ -769,9 +769,9 @@ namespace AzToolsFramework return true; } - auto linkIds = prefabTemplate->get().GetLinks(); + const Template::Links& linkIds = prefabTemplate->get().GetLinks(); - for (auto linkId : linkIds) + for (LinkId linkId : linkIds) { auto linkIterator = m_linkIdMap.find(linkId); if (linkIterator != m_linkIdMap.end()) @@ -784,10 +784,9 @@ namespace AzToolsFramework void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId templateId) { - AZStd::set dirtyTemplatePaths; - GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); + AZStd::set dirtyTemplatePaths = GetDirtyTemplatePaths(templateId); - for (auto dirtyTemplatePath : dirtyTemplatePaths) + for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) { auto dirtyTemplateIterator = m_templateFilePathToIdMap.find(dirtyTemplatePath); if (dirtyTemplateIterator == m_templateFilePathToIdMap.end()) @@ -801,9 +800,18 @@ namespace AzToolsFramework } } - void PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId templateId, AZStd::set& dirtyTemplatePaths) + AZStd::set PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId templateId) + { + AZStd::vector dirtyTemplatePathVector; + GetDirtyTemplatePathsHelper(templateId, dirtyTemplatePathVector); + AZStd::set dirtyTemplatePaths; + dirtyTemplatePaths.insert(dirtyTemplatePathVector.begin(), dirtyTemplatePathVector.end()); + return AZStd::move(dirtyTemplatePaths); + } + + void PrefabSystemComponent::GetDirtyTemplatePathsHelper(TemplateId templateId, AZStd::vector& dirtyTemplatePaths) { - auto prefabTemplate = FindTemplate(templateId); + TemplateReference prefabTemplate = FindTemplate(templateId); if (!prefabTemplate.has_value()) { @@ -813,17 +821,17 @@ namespace AzToolsFramework if (IsTemplateDirty(templateId)) { - dirtyTemplatePaths.emplace(prefabTemplate->get().GetFilePath()); + dirtyTemplatePaths.emplace_back(prefabTemplate->get().GetFilePath()); } - auto linkIds = prefabTemplate->get().GetLinks(); + const Template::Links& linkIds = prefabTemplate->get().GetLinks(); - for (auto linkId : linkIds) + for (LinkId linkId : linkIds) { auto linkIterator = m_linkIdMap.find(linkId); if (linkIterator != m_linkIdMap.end()) { - GetDirtyTemplatePaths(linkIterator->second.GetSourceTemplateId(), dirtyTemplatePaths); + GetDirtyTemplatePathsHelper(linkIterator->second.GetSourceTemplateId(), dirtyTemplatePaths); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 153a0e2b47..a09edfe03a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -187,7 +187,7 @@ namespace AzToolsFramework void SaveAllDirtyTemplates(TemplateId templateId) override; - void GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) override; + AZStd::set GetDirtyTemplatePaths(TemplateId parentTemplateId) override; ////////////////////////////////////////////////////////////////////////// @@ -341,6 +341,9 @@ namespace AzToolsFramework */ bool RemoveLinkFromTargetTemplate(const LinkId& linkId, const Link& link); + // Helper function for GetDirtyTemplatePaths(). It uses vector to speed up iteration times. + void GetDirtyTemplatePathsHelper(TemplateId parentTemplateId, AZStd::vector& dirtyTemplatePaths); + // A container for mapping Templates to the Links they may propagate changes to. AZStd::unordered_map> m_templateToLinkIdsMap; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 98e7719907..72b8fad162 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -61,8 +61,8 @@ namespace AzToolsFramework //! Recursive function that fetches the set of dirty templates given a starting template to check for outgoing links. //! @param templateId The id of the template provided as the beginning template to check the outgoing links. - //! @param[out] dirtyTemplatePaths The set of dirty template paths populated. - virtual void GetDirtyTemplatePaths(TemplateId parentTemplateId, AZStd::set& dirtyTemplatePaths) = 0; + //! @return The set of dirty template paths populated. + virtual AZStd::set GetDirtyTemplatePaths(TemplateId parentTemplateId) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 3df7e68008..e82e8fa0ca 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1096,13 +1096,12 @@ namespace AzToolsFramework { SavePrefabsInDialog(prefabSaveSelectionDialog.get()); } + return prefabSaveSelection; } void PrefabIntegrationManager::ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) { - using namespace AzToolsFramework::Prefab; - auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); @@ -1252,8 +1251,8 @@ namespace AzToolsFramework levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); contentLayout->addWidget(prefabSaveWarningFrame); - AZStd::set dirtyTemplatePaths; - s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); + AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId); + auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath(); AZStd::unique_ptr unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); @@ -1284,8 +1283,7 @@ namespace AzToolsFramework { FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow()); - AZStd::set dirtyTemplatePaths; - s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId, dirtyTemplatePaths); + AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId); for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) { From d0b7ffab67f4f9e7ad44016eb878cf96a5fabab9 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 7 Sep 2021 14:27:00 -0700 Subject: [PATCH 13/17] Changed parameter names to reflect the recursive nature of functions and some more changes Signed-off-by: srikappa-amzn --- Code/Editor/EditorPreferencesPageGeneral.cpp | 16 ++--- Code/Editor/EditorPreferencesPageGeneral.h | 6 +- Code/Editor/Settings.cpp | 6 +- Code/Editor/Settings.h | 4 +- .../Prefab/PrefabSystemComponent.cpp | 27 ++++---- .../Prefab/PrefabSystemComponent.h | 8 +-- .../Prefab/PrefabSystemComponentInterface.h | 12 ++-- .../UI/Prefab/PrefabIntegrationManager.cpp | 62 +++++++++++-------- 8 files changed, 75 insertions(+), 66 deletions(-) diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 2b044e800a..95b3bc4c50 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -42,9 +42,9 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector) ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera); - serialize.Class() + serialize.Class() ->Version(1) - ->Field("SaveAllPrefabsPreference", &GlobalSaveSettings::m_saveAllPrefabsPreference); + ->Field("SaveAllPrefabsPreference", &LevelSaveSettings::m_saveAllPrefabsPreference); serialize.Class() ->Version(2) @@ -68,7 +68,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) serialize.Class() ->Version(1) ->Field("General Settings", &CEditorPreferencesPage_General::m_generalSettings) - ->Field("Global Save Settings", &CEditorPreferencesPage_General::m_globalSaveSettings) + ->Field("Level Save Settings", &CEditorPreferencesPage_General::m_levelSaveSettings) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) @@ -97,9 +97,9 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); - editContext->Class("Global Save Settings", "") + editContext->Class("Level Save Settings", "") ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &GlobalSaveSettings::m_saveAllPrefabsPreference, "Save Prefabs Preference", + AZ::Edit::UIHandlers::ComboBox, &LevelSaveSettings::m_saveAllPrefabsPreference, "Save All Prefabs Preference", "This option controls whether prefabs should be saved along with the level") ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime, "Ask every time") ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveAll, "Save all") @@ -128,7 +128,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_globalSaveSettings, "Global Save Settings", "Global Save Settings (File>Save & Ctrl+S)") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_levelSaveSettings, "Level Save Settings", "File>Save") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") @@ -176,7 +176,7 @@ void CEditorPreferencesPage_General::OnApply() } //prefabs - gSettings.globalSaveSettings.saveAllPrefabsPreference = m_globalSaveSettings.m_saveAllPrefabsPreference; + gSettings.levelSaveSettings.saveAllPrefabsPreference = m_levelSaveSettings.m_saveAllPrefabsPreference; //undo gSettings.undoLevels = m_undo.m_undoLevels; @@ -208,7 +208,7 @@ void CEditorPreferencesPage_General::InitializeSettings() m_generalSettings.m_toolbarIconSize = static_cast(gSettings.gui.nToolbarIconSize); //prefabs - m_globalSaveSettings.m_saveAllPrefabsPreference = gSettings.globalSaveSettings.saveAllPrefabsPreference; + m_levelSaveSettings.m_saveAllPrefabsPreference = gSettings.levelSaveSettings.saveAllPrefabsPreference; //Messaging m_messaging.m_showDashboard = gSettings.bShowDashboardAtStartup; diff --git a/Code/Editor/EditorPreferencesPageGeneral.h b/Code/Editor/EditorPreferencesPageGeneral.h index e5888b2705..01700dea88 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Editor/EditorPreferencesPageGeneral.h @@ -58,9 +58,9 @@ private: bool m_enableSceneInspector; }; - struct GlobalSaveSettings + struct LevelSaveSettings { - AZ_TYPE_INFO(GlobalSaveSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); + AZ_TYPE_INFO(LevelSaveSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); AzToolsFramework::Prefab::SaveAllPrefabsPreference m_saveAllPrefabsPreference; }; @@ -96,7 +96,7 @@ private: }; GeneralSettings m_generalSettings; - GlobalSaveSettings m_globalSaveSettings; + LevelSaveSettings m_levelSaveSettings; Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 92617248d3..81182c0a20 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -254,7 +254,7 @@ SEditorSettings::SEditorSettings() g_TemporaryLevelName = nullptr; sliceSettings.dynamicByDefault = false; - globalSaveSettings.saveAllPrefabsPreference = AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime; + levelSaveSettings.saveAllPrefabsPreference = AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime; } void SEditorSettings::Connect() @@ -671,7 +671,7 @@ void SEditorSettings::Save() AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = AZ::Interface::Get(); - prefabLoaderInterface->SetSaveAllPrefabsPreference(globalSaveSettings.saveAllPrefabsPreference); + prefabLoaderInterface->SetSaveAllPrefabsPreference(levelSaveSettings.saveAllPrefabsPreference); SaveSettingsRegistryFile(); } @@ -681,7 +681,7 @@ void SEditorSettings::Load() { AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = AZ::Interface::Get(); - globalSaveSettings.saveAllPrefabsPreference = prefabLoaderInterface->GetSaveAllPrefabsPreference(); + levelSaveSettings.saveAllPrefabsPreference = prefabLoaderInterface->GetSaveAllPrefabsPreference(); // Load from Settings Registry AzFramework::ApplicationRequests::Bus::BroadcastResult( diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index fca3480241..8f94e482d3 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -231,7 +231,7 @@ struct SSliceSettings bool dynamicByDefault; }; -struct SGlobalSaveSettings +struct SLevelSaveSettings { AzToolsFramework::Prefab::SaveAllPrefabsPreference saveAllPrefabsPreference; }; @@ -472,7 +472,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING SSliceSettings sliceSettings; - SGlobalSaveSettings globalSaveSettings; + SLevelSaveSettings levelSaveSettings; bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 9059bf5368..5863ccfbf9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -370,7 +370,7 @@ namespace AzToolsFramework PrefabDom& PrefabSystemComponent::FindTemplateDom(TemplateId templateId) { AZStd::optional> findTemplateResult = FindTemplate(templateId); - AZ_Assert(findTemplateResult.has_value(), + AZ_Assert(false, "PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. " "Template could not be found", templateId); @@ -754,17 +754,17 @@ namespace AzToolsFramework } } - bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId templateId) + bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId rootTemplateId) { - TemplateReference prefabTemplate = FindTemplate(templateId); + TemplateReference prefabTemplate = FindTemplate(rootTemplateId); if (!prefabTemplate.has_value()) { - AZ_Assert(false, "Template with id %llu is not found", templateId); + AZ_Assert(false, "Template with id %llu is not found", rootTemplateId); return false; } - if (IsTemplateDirty(templateId)) + if (IsTemplateDirty(rootTemplateId)) { return true; } @@ -782,9 +782,9 @@ namespace AzToolsFramework return false; } - void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId templateId) + void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId rootTemplateId) { - AZStd::set dirtyTemplatePaths = GetDirtyTemplatePaths(templateId); + AZStd::set dirtyTemplatePaths = GetDirtyTemplatePaths(rootTemplateId); for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) { @@ -800,26 +800,27 @@ namespace AzToolsFramework } } - AZStd::set PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId templateId) + AZStd::set PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId rootTemplateId) { AZStd::vector dirtyTemplatePathVector; - GetDirtyTemplatePathsHelper(templateId, dirtyTemplatePathVector); + GetDirtyTemplatePathsHelper(rootTemplateId, dirtyTemplatePathVector); AZStd::set dirtyTemplatePaths; dirtyTemplatePaths.insert(dirtyTemplatePathVector.begin(), dirtyTemplatePathVector.end()); return AZStd::move(dirtyTemplatePaths); } - void PrefabSystemComponent::GetDirtyTemplatePathsHelper(TemplateId templateId, AZStd::vector& dirtyTemplatePaths) + void PrefabSystemComponent::GetDirtyTemplatePathsHelper( + TemplateId rootTemplateId, AZStd::vector& dirtyTemplatePaths) { - TemplateReference prefabTemplate = FindTemplate(templateId); + TemplateReference prefabTemplate = FindTemplate(rootTemplateId); if (!prefabTemplate.has_value()) { - AZ_Assert(false, "Template with id %llu is not found", templateId); + AZ_Assert(false, "Template with id %llu is not found", rootTemplateId); return; } - if (IsTemplateDirty(templateId)) + if (IsTemplateDirty(rootTemplateId)) { dirtyTemplatePaths.emplace_back(prefabTemplate->get().GetFilePath()); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index a09edfe03a..04bcee2961 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -183,11 +183,11 @@ namespace AzToolsFramework */ void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override; - bool AreDirtyTemplatesPresent(TemplateId templateId) override; + bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) override; - void SaveAllDirtyTemplates(TemplateId templateId) override; + void SaveAllDirtyTemplates(TemplateId rootTemplateId) override; - AZStd::set GetDirtyTemplatePaths(TemplateId parentTemplateId) override; + AZStd::set GetDirtyTemplatePaths(TemplateId rootTemplateId) override; ////////////////////////////////////////////////////////////////////////// @@ -342,7 +342,7 @@ namespace AzToolsFramework bool RemoveLinkFromTargetTemplate(const LinkId& linkId, const Link& link); // Helper function for GetDirtyTemplatePaths(). It uses vector to speed up iteration times. - void GetDirtyTemplatePathsHelper(TemplateId parentTemplateId, AZStd::vector& dirtyTemplatePaths); + void GetDirtyTemplatePathsHelper(TemplateId rootTemplateId, AZStd::vector& dirtyTemplatePaths); // A container for mapping Templates to the Links they may propagate changes to. AZStd::unordered_map> m_templateToLinkIdsMap; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 72b8fad162..ae66700728 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -52,17 +52,17 @@ namespace AzToolsFramework virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; //! Recursive function to check if the template is dirty or if any dirty templates are presents in the links of the template. - //! @param templateId The id of the template provided as the beginning template to check the outgoing links. - virtual bool AreDirtyTemplatesPresent(TemplateId templateId) = 0; + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. + virtual bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) = 0; //! Recursive function to save if the template is dirty and save all the dirty templates in the links of the template. - //! @param templateId The id of the template provided as the beginning template to check the outgoing links. - virtual void SaveAllDirtyTemplates(TemplateId templateId) = 0; + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. + virtual void SaveAllDirtyTemplates(TemplateId rootTemplateId) = 0; //! Recursive function that fetches the set of dirty templates given a starting template to check for outgoing links. - //! @param templateId The id of the template provided as the beginning template to check the outgoing links. + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. //! @return The set of dirty template paths populated. - virtual AZStd::set GetDirtyTemplatePaths(TemplateId parentTemplateId) = 0; + virtual AZStd::set GetDirtyTemplatePaths(TemplateId rootTemplateId) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index e82e8fa0ca..6b67f94582 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1088,16 +1088,21 @@ namespace AzToolsFramework int PrefabIntegrationManager::ExecuteClosePrefabDialog(TemplateId templateId) { - auto prefabSaveSelectionDialog = ConstructClosePrefabDialog(templateId); + if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId)) + { + auto prefabSaveSelectionDialog = ConstructClosePrefabDialog(templateId); - int prefabSaveSelection = prefabSaveSelectionDialog->exec(); + int prefabSaveSelection = prefabSaveSelectionDialog->exec(); - if (prefabSaveSelection == QDialog::Accepted) - { - SavePrefabsInDialog(prefabSaveSelectionDialog.get()); + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(prefabSaveSelectionDialog.get()); + } + + return prefabSaveSelection; } - return prefabSaveSelection; + return QDialogButtonBox::DestructiveRole; } void PrefabIntegrationManager::ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) @@ -1114,29 +1119,32 @@ namespace AzToolsFramework } } - if (useSaveAllPrefabsPreference) + if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId)) { - SaveAllPrefabsPreference saveAllPrefabsPreference = s_prefabLoaderInterface->GetSaveAllPrefabsPreference(); - - if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveAll) - { - s_prefabSystemComponentInterface->SaveAllDirtyTemplates(templateId); - return; - } - else if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveNone) + if (useSaveAllPrefabsPreference) { - return; - } - } + SaveAllPrefabsPreference saveAllPrefabsPreference = s_prefabLoaderInterface->GetSaveAllPrefabsPreference(); - AZStd::unique_ptr savePrefabDialog = ConstructSavePrefabDialog(templateId, useSaveAllPrefabsPreference); - if (savePrefabDialog) - { - int prefabSaveSelection = savePrefabDialog->exec(); + if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveAll) + { + s_prefabSystemComponentInterface->SaveAllDirtyTemplates(templateId); + return; + } + else if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveNone) + { + return; + } + } - if (prefabSaveSelection == QDialog::Accepted) + AZStd::unique_ptr savePrefabDialog = ConstructSavePrefabDialog(templateId, useSaveAllPrefabsPreference); + if (savePrefabDialog) { - SavePrefabsInDialog(savePrefabDialog.get()); + int prefabSaveSelection = savePrefabDialog->exec(); + + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(savePrefabDialog.get()); + } } } } @@ -1152,7 +1160,7 @@ namespace AzToolsFramework AzToolsFramework::Prefab::TemplateId unsavedPrefabTemplateId = s_prefabSystemComponentInterface->GetTemplateIdFromFilePath(unsavedPrefabFileName.data()); bool isTemplateSavedSuccessfully = s_prefabLoaderInterface->SaveTemplate(unsavedPrefabTemplateId); - AZ_Assert(isTemplateSavedSuccessfully, "Prefab '%s' could not be saved successfully.", unsavedPrefabFileName.c_str()); + AZ_Error("Prefab", isTemplateSavedSuccessfully, "Prefab '%s' could not be saved successfully.", unsavedPrefabFileName.c_str()); } } } @@ -1222,6 +1230,7 @@ namespace AzToolsFramework connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, savePrefabDialog.get(), &QDialog::reject); AzQtComponents::StyleManager::setStyleSheet(savePrefabDialog->parentWidget(), QStringLiteral("style:Editor.qss")); + savePrefabDialog->setLayout(contentLayout); return AZStd::move(savePrefabDialog); } @@ -1251,8 +1260,6 @@ namespace AzToolsFramework levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); contentLayout->addWidget(prefabSaveWarningFrame); - AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId); - auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath(); AZStd::unique_ptr unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); @@ -1276,6 +1283,7 @@ namespace AzToolsFramework closePrefabDialogWeakPtr.lock()->done(prefabSaveSelection); }); AzQtComponents::StyleManager::setStyleSheet(closePrefabDialog.get(), QStringLiteral("style:Editor.qss")); + closePrefabDialog->setLayout(contentLayout); return closePrefabDialog; } From 0f1e117904730637f9ae09a5d88cd0234ec5a223 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Tue, 7 Sep 2021 14:32:13 -0700 Subject: [PATCH 14/17] Reverted a small local change that got pushed by mistake Signed-off-by: srikappa-amzn --- .../AzToolsFramework/Prefab/PrefabSystemComponent.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 5863ccfbf9..76254b6717 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -370,9 +370,11 @@ namespace AzToolsFramework PrefabDom& PrefabSystemComponent::FindTemplateDom(TemplateId templateId) { AZStd::optional> findTemplateResult = FindTemplate(templateId); - AZ_Assert(false, + AZ_Assert( + findTemplateResult.has_value(), "PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. " - "Template could not be found", templateId); + "Template could not be found", + templateId); AZ_Assert(findTemplateResult->get().IsValid(), "PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. " From c7fbdb0ace923bbf274204480c55c2c9342e10e3 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Wed, 8 Sep 2021 11:49:33 -0700 Subject: [PATCH 15/17] Make level name appear in bold and update save all prefabs settings registry key Signed-off-by: srikappa-amzn --- .../AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp | 2 +- .../AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 3db78b1d39..09439724cd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -26,7 +26,7 @@ namespace AzToolsFramework { namespace Prefab { - static constexpr const char s_saveAllPrefabsKey[] = "/O3DE/Preferences/SaveAllPrefabs"; + static constexpr const char s_saveAllPrefabsKey[] = "/O3DE/Preferences/Prefabs/SaveAllPrefabs"; void PrefabLoader::Reflect(AZ::ReflectContext* context) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 6b67f94582..a1c3b936b2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1191,7 +1191,7 @@ namespace AzToolsFramework auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); QLabel* prefabSavedSuccessfullyLabel = new QLabel( - QString("Prefab %1 has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str()), + QString("Prefab '%1' has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str()), savePrefabDialog.get()); prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyIconContainer); prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyLabel); From b87b807de90e7dded698c5b2f32b5b255f0007fc Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Wed, 8 Sep 2021 16:07:22 -0700 Subject: [PATCH 16/17] Fixed an unused variable error in linux build Signed-off-by: srikappa-amzn --- .../AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index a1c3b936b2..0c61ccb501 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1305,7 +1305,7 @@ namespace AzToolsFramework } AZStd::unique_ptr unsavedPrefabsContainer = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); - unsavedPrefabsContainer->setObjectName("SaveDependentPrefabsCard"); + unsavedPrefabsContainer->setObjectName(SaveDependentPrefabsCard); unsavedPrefabsContainer->setTitle("Unsaved Prefabs"); unsavedPrefabsContainer->header()->setHasContextMenu(false); unsavedPrefabsContainer->header()->setIcon(QIcon(QStringLiteral(":/Entity/prefab_edit.svg"))); From 5dcfb8e6542f858a31b04b090650ee3b55197900 Mon Sep 17 00:00:00 2001 From: srikappa-amzn Date: Wed, 8 Sep 2021 23:19:05 -0700 Subject: [PATCH 17/17] Initialize prefab interface pointers only when prefabs are enabled Signed-off-by: srikappa-amzn --- Code/Editor/CryEditDoc.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 76704a3f07..a61429fc87 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -132,14 +132,19 @@ CCryEditDoc::CCryEditDoc() RegisterConsoleVariables(); MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_AS, this, &CCryEditDoc::OnFileSaveAs); - m_prefabSystemComponentInterface = AZ::Interface::Get(); - AZ_Assert(m_prefabSystemComponentInterface, "PrefabSystemComponentInterface is not found."); - m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AZ_Assert(m_prefabEditorEntityOwnershipInterface, "PrefabEditorEntityOwnershipInterface is not found."); - m_prefabLoaderInterface = AZ::Interface::Get(); - AZ_Assert(m_prefabLoaderInterface, "PrefabLoaderInterface is not found."); - m_prefabIntegrationInterface = AZ::Interface::Get(); - AZ_Assert(m_prefabIntegrationInterface, "PrefabIntegrationInterface is not found."); + bool isPrefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + if (isPrefabSystemEnabled) + { + m_prefabSystemComponentInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabSystemComponentInterface, "PrefabSystemComponentInterface is not found."); + m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabEditorEntityOwnershipInterface, "PrefabEditorEntityOwnershipInterface is not found."); + m_prefabLoaderInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabLoaderInterface, "PrefabLoaderInterface is not found."); + m_prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabIntegrationInterface, "PrefabIntegrationInterface is not found."); + } } CCryEditDoc::~CCryEditDoc()