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;