You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1257 lines
39 KiB
C++
1257 lines
39 KiB
C++
/*
|
|
* 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 "EditorDefs.h"
|
|
|
|
// Editor
|
|
#include "Resource.h"
|
|
#include "LevelEditorMenuHandler.h"
|
|
#include "CryEdit.h"
|
|
#include "MainWindow.h"
|
|
#include "QtViewPaneManager.h"
|
|
#include "ToolBox.h"
|
|
#include "Include/IObjectManager.h"
|
|
#include "Objects/SelectionGroup.h"
|
|
#include "ViewManager.h"
|
|
|
|
#include <AzCore/Interface/Interface.h>
|
|
|
|
// Qt
|
|
#include <QMenuBar>
|
|
#include <QUrlQuery>
|
|
#include <QDesktopServices>
|
|
#include <QHBoxLayout>
|
|
#include <QUrl>
|
|
|
|
// AzFramework
|
|
#include <AzFramework/API/ApplicationAPI.h>
|
|
|
|
// AzToolsFramework
|
|
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
|
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
|
|
|
|
// AzQtComponents
|
|
#include <AzQtComponents/Components/SearchLineEdit.h>
|
|
|
|
using namespace AZ;
|
|
using namespace AzToolsFramework;
|
|
|
|
static const char* const s_LUAEditorName = "Lua Editor";
|
|
|
|
// top level menu ids
|
|
static const char* const s_fileMenuId = "FileMenu";
|
|
static const char* const s_editMenuId = "EditMenu";
|
|
static const char* const s_gameMenuId = "GameMenu";
|
|
static const char* const s_toolMenuId = "ToolMenu";
|
|
static const char* const s_viewMenuId = "ViewMenu";
|
|
static const char* const s_helpMenuId = "HelpMenu";
|
|
|
|
static bool CompareLayoutNames(const QString& name1, const QString& name2)
|
|
{
|
|
return name1.compare(name2, Qt::CaseInsensitive) < 0;
|
|
}
|
|
|
|
static void AddOpenViewPaneAction(ActionManager::MenuWrapper& menu, const char* viewPaneName, const char* menuActionText = nullptr)
|
|
{
|
|
QAction* action = menu->addAction(QObject::tr(menuActionText ? menuActionText : viewPaneName));
|
|
QObject::connect(action, &QAction::triggered, action, [viewPaneName]()
|
|
{
|
|
QtViewPaneManager::instance()->OpenPane(viewPaneName);
|
|
});
|
|
}
|
|
|
|
namespace
|
|
{
|
|
// This helper allows us to watch editor notifications to control action enable states
|
|
class EditorListener
|
|
: public QObject
|
|
, public IEditorNotifyListener
|
|
{
|
|
public:
|
|
explicit EditorListener(QObject* parent, AZStd::function<void(EEditorNotifyEvent)> trigger)
|
|
: QObject(parent)
|
|
, m_trigger(trigger)
|
|
{}
|
|
|
|
~EditorListener() override
|
|
{
|
|
GetIEditor()->UnregisterNotifyListener(this);
|
|
}
|
|
|
|
void OnEditorNotifyEvent(EEditorNotifyEvent event) override
|
|
{
|
|
m_trigger(event);
|
|
}
|
|
|
|
private:
|
|
AZStd::function<void(EEditorNotifyEvent)> m_trigger;
|
|
};
|
|
|
|
void DisableActionWhileLevelChanges(QAction* action, EEditorNotifyEvent e)
|
|
{
|
|
if (e == eNotify_OnBeginNewScene || e == eNotify_OnBeginLoad)
|
|
{
|
|
action->setDisabled(true);
|
|
}
|
|
else if (e == eNotify_OnEndNewScene || e == eNotify_OnEndLoad)
|
|
{
|
|
action->setDisabled(false);
|
|
}
|
|
}
|
|
|
|
void HideActionWhileEntitiesDeselected(QAction* action, EEditorNotifyEvent editorNotifyEvent)
|
|
{
|
|
if (action == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (editorNotifyEvent)
|
|
{
|
|
case eNotify_OnEntitiesDeselected:
|
|
{
|
|
action->setVisible(false);
|
|
break;
|
|
}
|
|
case eNotify_OnEntitiesSelected:
|
|
{
|
|
action->setVisible(true);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DisableActionWhileInSimMode(QAction* action, EEditorNotifyEvent editorNotifyEvent)
|
|
{
|
|
if (action == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (editorNotifyEvent)
|
|
{
|
|
case eNotify_OnBeginSimulationMode:
|
|
{
|
|
action->setVisible(false);
|
|
action->setDisabled(true);
|
|
break;
|
|
}
|
|
case eNotify_OnEndSimulationMode:
|
|
{
|
|
action->setVisible(true);
|
|
action->setDisabled(false);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
LevelEditorMenuHandler::LevelEditorMenuHandler(MainWindow* mainWindow, QtViewPaneManager* const viewPaneManager)
|
|
: QObject(mainWindow)
|
|
, m_mainWindow(mainWindow)
|
|
, m_viewPaneManager(viewPaneManager)
|
|
, m_actionManager(mainWindow->GetActionManager())
|
|
{
|
|
#if defined(AZ_PLATFORM_MAC)
|
|
// Hide the non-native toolbar, then setNativeMenuBar to ensure it is always visible on macOS.
|
|
m_mainWindow->menuBar()->hide();
|
|
m_mainWindow->menuBar()->setNativeMenuBar(true);
|
|
#endif
|
|
|
|
ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
|
|
EditorMenuRequestBus::Handler::BusConnect();
|
|
}
|
|
|
|
LevelEditorMenuHandler::~LevelEditorMenuHandler()
|
|
{
|
|
EditorMenuRequestBus::Handler::BusDisconnect();
|
|
ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void LevelEditorMenuHandler::Initialize()
|
|
{
|
|
// make sure we can fix the view menus
|
|
connect(
|
|
m_viewPaneManager, &QtViewPaneManager::registeredPanesChanged,
|
|
this, &LevelEditorMenuHandler::ResetToolsMenus);
|
|
|
|
m_levelExtension = EditorUtils::LevelFile::GetDefaultFileExtension();
|
|
|
|
m_topLevelMenus << CreateFileMenu();
|
|
|
|
auto editMenu = CreateEditMenu();
|
|
auto editMenuWrapper = ActionManager::MenuWrapper(editMenu, m_actionManager);
|
|
PopulateEditMenu(editMenuWrapper);
|
|
|
|
m_editmenu = editMenu;
|
|
|
|
m_topLevelMenus << editMenu;
|
|
m_topLevelMenus << CreateGameMenu();
|
|
m_topLevelMenus << CreateToolsMenu();
|
|
m_topLevelMenus << CreateViewMenu();
|
|
m_topLevelMenus << CreateHelpMenu();
|
|
|
|
// have to do this after creating the AWS Menu for the first time
|
|
ResetToolsMenus();
|
|
|
|
// Add our menus to the main window menu bar
|
|
QMenuBar* menuBar = m_mainWindow->menuBar();
|
|
menuBar->clear();
|
|
for (QMenu* menu : m_topLevelMenus)
|
|
{
|
|
menuBar->addMenu(menu);
|
|
}
|
|
}
|
|
|
|
bool LevelEditorMenuHandler::MRUEntryIsValid(const QString& entry, const QString& gameFolderPath)
|
|
{
|
|
if (entry.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
QFileInfo info(entry);
|
|
if (!info.exists())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!entry.endsWith(m_levelExtension))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const QDir gameDir(gameFolderPath);
|
|
QDir dir(entry); // actually pointing at file, first cdUp() gets us the parent dir
|
|
while (dir.cdUp())
|
|
{
|
|
if (dir == gameDir)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void LevelEditorMenuHandler::IncrementViewPaneVersion()
|
|
{
|
|
m_viewPaneVersion++;
|
|
}
|
|
|
|
int LevelEditorMenuHandler::GetViewPaneVersion() const
|
|
{
|
|
return m_viewPaneVersion;
|
|
}
|
|
|
|
void LevelEditorMenuHandler::UpdateViewLayoutsMenu(ActionManager::MenuWrapper& layoutsMenu)
|
|
{
|
|
if (layoutsMenu.isNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
QStringList layoutNames = m_viewPaneManager->LayoutNames();
|
|
std::sort(layoutNames.begin(), layoutNames.end(), CompareLayoutNames);
|
|
layoutsMenu->clear();
|
|
const int MAX_LAYOUTS = ID_VIEW_LAYOUT_LAST - ID_VIEW_LAYOUT_FIRST + 1;
|
|
|
|
// Component entity layout is the default
|
|
QString componentLayoutLabel = tr("Component Entity Layout");
|
|
QAction* componentLayoutAction = layoutsMenu->addAction(componentLayoutLabel);
|
|
connect(componentLayoutAction, &QAction::triggered, this, &LevelEditorMenuHandler::LoadComponentLayout);
|
|
|
|
layoutsMenu.AddSeparator();
|
|
|
|
for (int i = 0; i < layoutNames.size() && i <= MAX_LAYOUTS; i++)
|
|
{
|
|
const QString layoutName = layoutNames[i];
|
|
QAction* action = layoutsMenu->addAction(layoutName);
|
|
QMenu* subSubMenu = new QMenu();
|
|
|
|
QAction* subSubAction = subSubMenu->addAction(tr("Load"));
|
|
connect(subSubAction, &QAction::triggered, this, [layoutName, this]() { m_mainWindow->ViewLoadPaneLayout(layoutName); });
|
|
|
|
subSubAction = subSubMenu->addAction(tr("Save"));
|
|
connect(subSubAction, &QAction::triggered, this, [layoutName, this]() { m_mainWindow->ViewSavePaneLayout(layoutName); });
|
|
|
|
subSubAction = subSubMenu->addAction(tr("Rename..."));
|
|
connect(subSubAction, &QAction::triggered, this, [layoutName, this]() { m_mainWindow->ViewRenamePaneLayout(layoutName); });
|
|
|
|
subSubAction = subSubMenu->addAction(tr("Delete"));
|
|
connect(subSubAction, &QAction::triggered, this, [layoutName, this]() { m_mainWindow->ViewDeletePaneLayout(layoutName); });
|
|
|
|
action->setMenu(subSubMenu);
|
|
}
|
|
|
|
layoutsMenu.AddAction(ID_VIEW_SAVELAYOUT);
|
|
|
|
layoutsMenu.AddAction(ID_VIEW_LAYOUT_LOAD_DEFAULT);
|
|
}
|
|
|
|
void LevelEditorMenuHandler::ResetToolsMenus()
|
|
{
|
|
if (!m_toolsMenu->isEmpty())
|
|
{
|
|
// Clear everything from the Tools menu
|
|
m_toolsMenu->clear();
|
|
AzToolsFramework::EditorMenuNotificationBus::Broadcast(&AzToolsFramework::EditorMenuNotificationBus::Handler::OnResetToolMenuItems);
|
|
}
|
|
|
|
QtViewPanes allRegisteredViewPanes = QtViewPaneManager::instance()->GetRegisteredPanes();
|
|
|
|
QMap<QString, QList<QtViewPane*> > menuMap;
|
|
|
|
CreateMenuMap(menuMap, allRegisteredViewPanes);
|
|
|
|
CreateMenuOptions(&menuMap, m_toolsMenu, LyViewPane::CategoryTools);
|
|
|
|
AzToolsFramework::EditorMenuNotificationBus::Broadcast(&AzToolsFramework::EditorMenuNotificationBus::Handler::OnPopulateToolMenuItems);
|
|
|
|
m_toolsMenu.AddSeparator();
|
|
|
|
// Other
|
|
auto otherSubMenu = m_toolsMenu.AddMenu(QObject::tr("Other"));
|
|
|
|
CreateMenuOptions(&menuMap, otherSubMenu, LyViewPane::CategoryOther);
|
|
|
|
m_toolsMenu.AddSeparator();
|
|
|
|
// Optional Sub Menus
|
|
if (!menuMap.isEmpty())
|
|
{
|
|
QMap<QString, QList<QtViewPane*> >::iterator it = menuMap.begin();
|
|
|
|
while (it != menuMap.end())
|
|
{
|
|
auto currentSubMenu = m_toolsMenu.AddMenu(it.key());
|
|
CreateMenuOptions(&menuMap, currentSubMenu, it.key().toStdString().c_str());
|
|
|
|
it = menuMap.begin();
|
|
}
|
|
}
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateFileMenu()
|
|
{
|
|
auto fileMenu = m_actionManager->AddMenu(tr("&File"), s_fileMenuId);
|
|
connect(fileMenu, &QMenu::aboutToShow, this, &LevelEditorMenuHandler::OnUpdateOpenRecent);
|
|
|
|
// New level
|
|
auto fileNew = fileMenu.AddAction(ID_FILE_NEW);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(fileNew, [fileNew](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(fileNew, e);
|
|
}));
|
|
|
|
// Open level...
|
|
auto fileOpenLevel = fileMenu.AddAction(ID_FILE_OPEN_LEVEL);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(fileOpenLevel, [fileOpenLevel](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(fileOpenLevel, e);
|
|
}));
|
|
|
|
#ifdef ENABLE_SLICE_EDITOR
|
|
// New slice
|
|
auto fileNewSlice = fileMenu.AddAction(ID_FILE_NEW_SLICE);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(fileNewSlice, [fileNewSlice](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(fileNewSlice, e);
|
|
}));
|
|
|
|
// Open slice...
|
|
auto fileOpenSlice = fileMenu.AddAction(ID_FILE_OPEN_SLICE);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(fileOpenSlice, [fileOpenSlice](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(fileOpenSlice, e);
|
|
}));
|
|
#endif
|
|
|
|
// Save Selected Slice
|
|
auto saveSelectedSlice = fileMenu.AddAction(ID_FILE_SAVE_SELECTED_SLICE);
|
|
saveSelectedSlice->setVisible(false);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(saveSelectedSlice, [saveSelectedSlice](EEditorNotifyEvent e)
|
|
{
|
|
HideActionWhileEntitiesDeselected(saveSelectedSlice, e);
|
|
}));
|
|
|
|
// Save Slice to Root
|
|
auto saveSliceToRoot = fileMenu.AddAction(ID_FILE_SAVE_SLICE_TO_ROOT);
|
|
saveSliceToRoot->setVisible(false);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(saveSliceToRoot, [saveSliceToRoot](EEditorNotifyEvent e)
|
|
{
|
|
HideActionWhileEntitiesDeselected(saveSliceToRoot, e);
|
|
}));
|
|
|
|
// Open Recent
|
|
m_mostRecentLevelsMenu = fileMenu.AddMenu(tr("Open Recent"));
|
|
connect(m_mostRecentLevelsMenu, &QMenu::aboutToShow, this, &LevelEditorMenuHandler::UpdateMRUFiles);
|
|
|
|
OnUpdateOpenRecent();
|
|
|
|
// Import...
|
|
auto assetImporterMenu = fileMenu.Get()->addAction(tr("Import..."));
|
|
connect(assetImporterMenu, &QAction::triggered, this, &LevelEditorMenuHandler::ActivateAssetImporter);
|
|
|
|
fileMenu.AddSeparator();
|
|
|
|
// Save
|
|
fileMenu.AddAction(ID_FILE_SAVE_LEVEL);
|
|
|
|
// Save As...
|
|
fileMenu.AddAction(ID_FILE_SAVE_AS);
|
|
|
|
// Save Level Statistics
|
|
fileMenu.AddAction(ID_TOOLS_LOGMEMORYUSAGE);
|
|
fileMenu.AddSeparator();
|
|
|
|
// Project Settings
|
|
fileMenu.AddAction(ID_FILE_PROJECT_MANAGER_SETTINGS);
|
|
|
|
// Platform Settings - Project Settings Tool
|
|
// Shortcut must be set while adding the action otherwise it doesn't work
|
|
fileMenu.Get()->addAction(
|
|
tr(LyViewPane::ProjectSettingsTool),
|
|
[]() { QtViewPaneManager::instance()->OpenPane(LyViewPane::ProjectSettingsTool); },
|
|
tr("Ctrl+Shift+P"));
|
|
|
|
fileMenu.AddSeparator();
|
|
fileMenu.AddAction(ID_FILE_PROJECT_MANAGER_NEW);
|
|
fileMenu.AddAction(ID_FILE_PROJECT_MANAGER_OPEN);
|
|
fileMenu.AddSeparator();
|
|
|
|
// NEWMENUS: NEEDS IMPLEMENTATION
|
|
// should have the equivalent of a Close here; it should be close the current slice, but the editor isn't slice based right now
|
|
// so that won't work.
|
|
// instead, it should be Close of the level, but we don't have that either. I'm leaving it here so that it's obvious where UX intended it
|
|
// to go
|
|
//fileMenu.AddAction(ID_FILE_CLOSE);
|
|
|
|
// Show Log File
|
|
fileMenu.AddAction(ID_FILE_EDITLOGFILE);
|
|
|
|
fileMenu.AddSeparator();
|
|
|
|
fileMenu.AddAction(ID_FILE_RESAVESLICES);
|
|
|
|
fileMenu.AddSeparator();
|
|
|
|
fileMenu.AddAction(ID_APP_EXIT);
|
|
|
|
return fileMenu;
|
|
}
|
|
|
|
void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMenu)
|
|
{
|
|
// Undo
|
|
editMenu.AddAction(ID_UNDO);
|
|
|
|
// Redo
|
|
editMenu.AddAction(ID_REDO);
|
|
|
|
editMenu.AddSeparator();
|
|
|
|
// NEWMENUS: NEEDS IMPLEMENTATION
|
|
// Not quite ready for these yet. Have to register them with the ActionManager in MainWindow.cpp when we're ready
|
|
// editMenu->addAction(ID_EDIT_CUT);
|
|
// editMenu->addAction(ID_EDIT_COPY);
|
|
// editMenu->addAction(ID_EDIT_PASTE);
|
|
// editMenu.AddSeparator();
|
|
|
|
// Duplicate
|
|
editMenu.AddAction(AzToolsFramework::DuplicateSelect);
|
|
|
|
// Delete
|
|
editMenu.AddAction(AzToolsFramework::DeleteSelect);
|
|
|
|
editMenu.AddSeparator();
|
|
|
|
// Select All
|
|
editMenu.AddAction(AzToolsFramework::SelectAll);
|
|
|
|
// Invert Selection
|
|
editMenu.AddAction(AzToolsFramework::InvertSelect);
|
|
|
|
editMenu.AddSeparator();
|
|
|
|
// New Viewport Interaction Model actions/shortcuts
|
|
editMenu.AddAction(AzToolsFramework::EditPivot);
|
|
editMenu.AddAction(AzToolsFramework::EditReset);
|
|
editMenu.AddAction(AzToolsFramework::EditResetManipulator);
|
|
|
|
// Hide Selection
|
|
editMenu.AddAction(AzToolsFramework::HideSelection);
|
|
|
|
// Show All
|
|
editMenu.AddAction(AzToolsFramework::ShowAll);
|
|
|
|
// Lock Selection
|
|
editMenu.AddAction(AzToolsFramework::LockSelection);
|
|
|
|
// UnLock All
|
|
editMenu.AddAction(AzToolsFramework::UnlockAll);
|
|
|
|
/*
|
|
* The following block of code is part of the feature "Isolation Mode" and is temporarily
|
|
* disabled for 1.10 release.
|
|
* Jira: LY-49532
|
|
// Isolate Selected
|
|
QAction* isolateSelectedAction = editMenu->addAction(tr("Isolate Selected"));
|
|
connect(isolateSelectedAction, &QAction::triggered, this, []() {
|
|
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::EnterEditorIsolationMode);
|
|
});
|
|
// Exit Isolation
|
|
QAction* exitIsolationAction = editMenu->addAction(tr("Exit Isolation"));
|
|
connect(exitIsolationAction, &QAction::triggered, this, []() {
|
|
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::ExitEditorIsolationMode);
|
|
});
|
|
connect(editMenu, &QMenu::aboutToShow, this, [isolateSelectedAction, exitIsolationAction]() {
|
|
bool isInIsolationMode = false;
|
|
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(isInIsolationMode, &AzToolsFramework::ToolsApplicationRequestBus::Events::IsEditorInIsolationMode);
|
|
if (isInIsolationMode)
|
|
{
|
|
isolateSelectedAction->setDisabled(true);
|
|
exitIsolationAction->setDisabled(false);
|
|
}
|
|
else
|
|
{
|
|
isolateSelectedAction->setDisabled(false);
|
|
exitIsolationAction->setDisabled(true);
|
|
}
|
|
});
|
|
*/
|
|
|
|
editMenu.AddSeparator();
|
|
|
|
// Modify Menu
|
|
auto modifyMenu = editMenu.AddMenu(tr("&Modify"));
|
|
|
|
auto snapMenu = modifyMenu.AddMenu(tr("Snap"));
|
|
|
|
snapMenu.AddAction(AzToolsFramework::SnapAngle);
|
|
|
|
auto transformModeMenu = modifyMenu.AddMenu(tr("Transform Mode"));
|
|
transformModeMenu.AddAction(AzToolsFramework::EditModeMove);
|
|
transformModeMenu.AddAction(AzToolsFramework::EditModeRotate);
|
|
transformModeMenu.AddAction(AzToolsFramework::EditModeScale);
|
|
|
|
editMenu.AddSeparator();
|
|
|
|
// Editor Settings
|
|
auto editorSettingsMenu = editMenu.AddMenu(tr("Editor Settings"));
|
|
|
|
// Global Preferences...
|
|
editorSettingsMenu.AddAction(ID_TOOLS_PREFERENCES);
|
|
|
|
// Editor Settings Manager
|
|
AddOpenViewPaneAction(editorSettingsMenu, LyViewPane::EditorSettingsManager);
|
|
|
|
// Keyboard Customization
|
|
auto keyboardCustomizationMenu = editorSettingsMenu.AddMenu(tr("Keyboard Customization"));
|
|
keyboardCustomizationMenu.AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD);
|
|
keyboardCustomizationMenu.AddAction(ID_TOOLS_EXPORT_SHORTCUTS);
|
|
keyboardCustomizationMenu.AddAction(ID_TOOLS_IMPORT_SHORTCUTS);
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateEditMenu()
|
|
{
|
|
return m_actionManager->AddMenu(tr("&Edit"), s_editMenuId);
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateGameMenu()
|
|
{
|
|
auto gameMenu = m_actionManager->AddMenu(tr("&Game"), s_gameMenuId);
|
|
|
|
// Play Game
|
|
gameMenu.AddAction(ID_VIEW_SWITCHTOGAME);
|
|
|
|
// Enable Physics/AI
|
|
gameMenu.AddAction(ID_SWITCH_PHYSICS);
|
|
gameMenu.AddSeparator();
|
|
|
|
|
|
bool usePrefabSystemForLevels = false;
|
|
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
|
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
|
if (!usePrefabSystemForLevels)
|
|
{
|
|
// Export to Engine
|
|
gameMenu.AddAction(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE);
|
|
}
|
|
|
|
// Export Selected Objects
|
|
gameMenu.AddAction(ID_FILE_EXPORT_SELECTEDOBJECTS);
|
|
|
|
// Export Occlusion Mesh
|
|
gameMenu.AddAction(ID_FILE_EXPORTOCCLUSIONMESH);
|
|
|
|
gameMenu.AddSeparator();
|
|
|
|
// Synchronize Player with Camera
|
|
gameMenu.AddAction(ID_GAME_SYNCPLAYER);
|
|
|
|
gameMenu.AddSeparator();
|
|
|
|
// Audio
|
|
auto audioMenu = gameMenu.AddMenu(tr("Audio"));
|
|
|
|
// Stop All Sounds
|
|
audioMenu.AddAction(ID_SOUND_STOPALLSOUNDS);
|
|
|
|
// Refresh Audio
|
|
audioMenu.AddAction(ID_AUDIO_REFRESH_AUDIO_SYSTEM);
|
|
|
|
gameMenu.AddSeparator();
|
|
|
|
CreateDebuggingSubMenu(gameMenu);
|
|
|
|
return gameMenu;
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateToolsMenu()
|
|
{
|
|
// Tools
|
|
m_toolsMenu = m_actionManager->AddMenu(tr("&Tools"), s_toolMenuId);
|
|
return m_toolsMenu;
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateViewMenu()
|
|
{
|
|
auto viewMenu = m_actionManager->AddMenu(tr("&View"), s_viewMenuId);
|
|
|
|
// NEWMENUS: NEEDS IMPLEMENTATION
|
|
// minimize window - Ctrl+M
|
|
// Zoom - Ctrl+Plus(+) -> Need the inverse too?
|
|
|
|
#ifdef FEATURE_ORTHOGRAPHIC_VIEW
|
|
// Cycle Viewports
|
|
viewMenu.AddAction(ID_VIEW_CYCLE2DVIEWPORT);
|
|
#endif
|
|
|
|
// Center on Selection
|
|
viewMenu.AddAction(ID_MODIFY_GOTO_SELECTION);
|
|
|
|
// Show Quick Access Bar
|
|
viewMenu.AddAction(ID_OPEN_QUICK_ACCESS_BAR);
|
|
|
|
// Layouts
|
|
if (CViewManager::IsMultiViewportEnabled()) // Only supports 1 viewport for now.
|
|
{
|
|
// Disable Layouts menu
|
|
m_layoutsMenu = viewMenu.AddMenu(tr("Layouts"));
|
|
connect(m_viewPaneManager, &QtViewPaneManager::savedLayoutsChanged, this, [this]()
|
|
{
|
|
UpdateViewLayoutsMenu(m_layoutsMenu);
|
|
});
|
|
|
|
UpdateViewLayoutsMenu(m_layoutsMenu);
|
|
}
|
|
|
|
// Viewport
|
|
auto viewportViewsMenuWrapper = viewMenu.AddMenu(tr("Viewport"));
|
|
|
|
#ifdef FEATURE_ORTHOGRAPHIC_VIEW
|
|
auto viewportTypesMenuWrapper = viewportViewsMenuWrapper.AddMenu(tr("Viewport Type"));
|
|
|
|
m_viewportViewsMenu = viewportViewsMenuWrapper;
|
|
connect(viewportTypesMenuWrapper, &QMenu::aboutToShow, this, &LevelEditorMenuHandler::UpdateOpenViewPaneMenu);
|
|
|
|
InitializeViewPaneMenu(m_actionManager, viewportTypesMenuWrapper, [](const QtViewPane& view)
|
|
{
|
|
return view.IsViewportPane();
|
|
});
|
|
|
|
viewportViewsMenuWrapper.AddSeparator();
|
|
|
|
#endif
|
|
|
|
if (CViewManager::IsMultiViewportEnabled())
|
|
{
|
|
viewportViewsMenuWrapper.AddAction(ID_VIEW_CONFIGURELAYOUT);
|
|
}
|
|
viewportViewsMenuWrapper.AddSeparator();
|
|
|
|
viewportViewsMenuWrapper.AddAction(ID_DISPLAY_GOTOPOSITION);
|
|
viewportViewsMenuWrapper.AddAction(ID_MODIFY_GOTO_SELECTION);
|
|
|
|
auto gotoLocationMenu = viewportViewsMenuWrapper.AddMenu(tr("Go to Location"));
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC1);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC2);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC3);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC4);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC5);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC6);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC7);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC8);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC9);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC10);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC11);
|
|
gotoLocationMenu.AddAction(ID_GOTO_LOC12);
|
|
|
|
auto rememberLocationMenu = viewportViewsMenuWrapper.AddMenu(tr("Remember Location"));
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC1);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC2);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC3);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC4);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC5);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC6);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC7);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC8);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC9);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC10);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC11);
|
|
rememberLocationMenu.AddAction(ID_TAG_LOC12);
|
|
|
|
viewportViewsMenuWrapper.AddSeparator();
|
|
|
|
auto switchCameraMenu = viewportViewsMenuWrapper.AddMenu(tr("Switch Camera"));
|
|
switchCameraMenu.AddAction(ID_SWITCHCAMERA_DEFAULTCAMERA);
|
|
switchCameraMenu.AddAction(ID_SWITCHCAMERA_SEQUENCECAMERA);
|
|
switchCameraMenu.AddAction(ID_SWITCHCAMERA_SELECTEDCAMERA);
|
|
switchCameraMenu.AddAction(ID_SWITCHCAMERA_NEXT);
|
|
|
|
// NEWMENUS:
|
|
// MISSING AVIRECORDER
|
|
|
|
viewportViewsMenuWrapper.AddSeparator();
|
|
viewportViewsMenuWrapper.AddAction(ID_DISPLAY_SHOWHELPERS);
|
|
|
|
// Refresh Style
|
|
viewMenu.AddAction(ID_SKINS_REFRESH);
|
|
|
|
return viewMenu;
|
|
}
|
|
|
|
QMenu* LevelEditorMenuHandler::CreateHelpMenu()
|
|
{
|
|
// Help
|
|
auto helpMenu = m_actionManager->AddMenu(tr("&Help"), s_helpMenuId);
|
|
|
|
auto lineEditSearchAction = new QWidgetAction(m_mainWindow);
|
|
auto containerWidget = new QWidget(m_mainWindow);
|
|
auto lineEdit = new AzQtComponents::SearchLineEdit(m_mainWindow);
|
|
QHBoxLayout *layout = new QHBoxLayout;
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->addWidget(lineEdit);
|
|
containerWidget->setLayout(layout);
|
|
containerWidget->setContentsMargins(2, 0, 2, 0);
|
|
lineEdit->setPlaceholderText(tr("Search documentation"));
|
|
lineEditSearchAction->setDefaultWidget(containerWidget);
|
|
|
|
auto searchAction = [lineEdit]()
|
|
{
|
|
auto text = lineEdit->text();
|
|
if (text.isEmpty())
|
|
{
|
|
QDesktopServices::openUrl(QUrl("https://o3de.org/docs/"));
|
|
}
|
|
else
|
|
{
|
|
static const int versionStringSize = 128;
|
|
char productVersionString[versionStringSize];
|
|
const SFileVersion& productVersion = gEnv->pSystem->GetProductVersion();
|
|
productVersion.ToString(productVersionString, versionStringSize);
|
|
|
|
QUrl docSearchUrl("https://o3de.org/docs/");
|
|
QUrlQuery docSearchQuery;
|
|
docSearchQuery.addQueryItem("query", text);
|
|
docSearchUrl.setQuery(docSearchQuery);
|
|
QDesktopServices::openUrl(docSearchUrl);
|
|
}
|
|
lineEdit->clear();
|
|
};
|
|
connect(lineEdit, &QLineEdit::returnPressed, this, searchAction);
|
|
connect(helpMenu.Get(), &QMenu::aboutToHide, lineEdit, &QLineEdit::clear);
|
|
connect(helpMenu.Get(), &QMenu::aboutToShow, lineEdit, &QLineEdit::clearFocus);
|
|
helpMenu->addAction(lineEditSearchAction);
|
|
|
|
// Tutorials
|
|
helpMenu.AddAction(ID_DOCUMENTATION_TUTORIALS);
|
|
|
|
// Documentation
|
|
auto documentationMenu = helpMenu.AddMenu(tr("Documentation"));
|
|
|
|
// Open 3D Engine Documentation
|
|
documentationMenu.AddAction(ID_DOCUMENTATION_O3DE);
|
|
|
|
// GameLift Documentation
|
|
documentationMenu.AddAction(ID_DOCUMENTATION_GAMELIFT);
|
|
|
|
// Release Notes
|
|
documentationMenu.AddAction(ID_DOCUMENTATION_RELEASENOTES);
|
|
|
|
// GameDev Resources
|
|
auto gameDevResourceMenu = helpMenu.AddMenu(tr("GameDev Resources"));
|
|
|
|
// Game Dev Blog
|
|
gameDevResourceMenu.AddAction(ID_DOCUMENTATION_GAMEDEVBLOG);
|
|
|
|
// Forums
|
|
gameDevResourceMenu.AddAction(ID_DOCUMENTATION_FORUMS);
|
|
|
|
// AWS Support
|
|
gameDevResourceMenu.AddAction(ID_DOCUMENTATION_AWSSUPPORT);
|
|
|
|
helpMenu.AddSeparator();
|
|
|
|
// About Open 3D Engine
|
|
helpMenu.AddAction(ID_APP_ABOUT);
|
|
|
|
// Welcome dialog
|
|
auto helpWelcome = helpMenu.AddAction(ID_APP_SHOW_WELCOME);
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(helpWelcome, [helpWelcome](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(helpWelcome, e);
|
|
}));
|
|
|
|
return helpMenu;
|
|
}
|
|
|
|
QAction* LevelEditorMenuHandler::CreateViewPaneAction(const QtViewPane* view)
|
|
{
|
|
QAction* action = m_actionManager->HasAction(view->m_id) ? m_actionManager->GetAction(view->m_id) : nullptr;
|
|
|
|
if (!action)
|
|
{
|
|
const QString menuText = view->m_options.optionalMenuText.length() > 0
|
|
? view->m_options.optionalMenuText
|
|
: view->m_name;
|
|
|
|
action = new QAction(menuText, this);
|
|
action->setObjectName(view->m_name);
|
|
action->setCheckable(true);
|
|
|
|
if (view->m_options.showOnToolsToolbar)
|
|
{
|
|
action->setIcon(QIcon(view->m_options.toolbarIcon.c_str()));
|
|
}
|
|
|
|
m_actionManager->AddAction(view->m_id, action);
|
|
|
|
if (!view->m_options.shortcut.isEmpty())
|
|
{
|
|
action->setShortcut(view->m_options.shortcut);
|
|
}
|
|
|
|
QObject::connect(
|
|
action, &QAction::triggered, this, &LevelEditorMenuHandler::checkOrOpenView, Qt::UniqueConnection);
|
|
}
|
|
|
|
return action;
|
|
}
|
|
|
|
// Function used to show menu options without its icon and be able to toggle shortcut visibility in the new menu layout
|
|
// This is a work around for the fact that setting the shortcut on the original action isn't working for some reasons
|
|
// and we need to investigate it further in the future.
|
|
QAction* LevelEditorMenuHandler::CreateViewPaneMenuItem(
|
|
[[maybe_unused]] ActionManager* actionManager, ActionManager::MenuWrapper& menu, const QtViewPane* view)
|
|
{
|
|
QAction* action = CreateViewPaneAction(view);
|
|
|
|
if (action && view->m_options.isDisabledInSimMode)
|
|
{
|
|
AddDisableActionInSimModeListener(action);
|
|
}
|
|
|
|
menu->addAction(action);
|
|
|
|
if (view->m_options.showOnToolsToolbar)
|
|
{
|
|
m_mainWindow->GetToolbarManager()->AddButtonToEditToolbar(action);
|
|
}
|
|
|
|
return action;
|
|
}
|
|
|
|
void LevelEditorMenuHandler::InitializeViewPaneMenu(
|
|
ActionManager* actionManager, ActionManager::MenuWrapper& menu,
|
|
AZStd::function <bool(const QtViewPane& view)> functor)
|
|
{
|
|
QtViewPanes views = QtViewPaneManager::instance()->GetRegisteredPanes();
|
|
|
|
for (auto it = views.cbegin(), end = views.cend(); it != end; ++it)
|
|
{
|
|
const QtViewPane& view = *it;
|
|
if (!functor(view))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CreateViewPaneMenuItem(actionManager, menu, it);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::LoadComponentLayout()
|
|
{
|
|
m_viewPaneManager->RestoreDefaultLayout();
|
|
}
|
|
|
|
QMap<QString, QList<QtViewPane*>> LevelEditorMenuHandler::CreateMenuMap(
|
|
QMap<QString, QList<QtViewPane*> >& menuMap, QtViewPanes& allRegisteredViewPanes)
|
|
{
|
|
// set up view panes to each category
|
|
for (QtViewPane& viewpane : allRegisteredViewPanes)
|
|
{
|
|
// only store the view panes that should be shown in the menu
|
|
if (!viewpane.IsViewportPane())
|
|
{
|
|
menuMap[viewpane.m_category].push_back(&viewpane);
|
|
}
|
|
}
|
|
|
|
return menuMap;
|
|
}
|
|
|
|
// sort the menu option name in alphabetically order
|
|
struct CaseInsensitiveStringCompare
|
|
{
|
|
bool operator() (const QString& left, const QString& right) const
|
|
{
|
|
return left.toLower() < right.toLower();
|
|
}
|
|
};
|
|
|
|
static void LaunchLuaEditor()
|
|
{
|
|
AzToolsFramework::EditorRequestBus::Broadcast(
|
|
&AzToolsFramework::EditorRequests::LaunchLuaEditor, nullptr);
|
|
}
|
|
|
|
void LevelEditorMenuHandler::CreateMenuOptions(
|
|
QMap<QString, QList<QtViewPane*> >* menuMap, ActionManager::MenuWrapper& menu, const char* category)
|
|
{
|
|
// list in the menu and remove this menu category from the menuMap
|
|
QList<QtViewPane*> menuList = menuMap->take(category);
|
|
|
|
std::map<QString, std::function<void()>, CaseInsensitiveStringCompare> sortMenuMap;
|
|
|
|
// store menu options into the map
|
|
// name as a key, functionality as a value
|
|
for (QtViewPane* viewpane : menuList)
|
|
{
|
|
if (viewpane->m_options.builtInActionId != LyViewPane::NO_BUILTIN_ACTION)
|
|
{
|
|
sortMenuMap[viewpane->m_name] = [this, &menu, viewpane]()
|
|
{
|
|
// Handle shortcuts for actions with a built-in ID since they
|
|
// bypass our CreateViewPaneMenuItem method
|
|
QAction* action = menu.AddAction(viewpane->m_options.builtInActionId);
|
|
if (action)
|
|
{
|
|
if (viewpane->m_options.isDisabledInSimMode)
|
|
{
|
|
AddDisableActionInSimModeListener(action);
|
|
}
|
|
if (!viewpane->m_options.shortcut.isEmpty())
|
|
{
|
|
action->setShortcut(viewpane->m_options.shortcut);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
else
|
|
{
|
|
const QString menuText = viewpane->m_options.optionalMenuText.length() > 0
|
|
? viewpane->m_options.optionalMenuText
|
|
: viewpane->m_name;
|
|
|
|
sortMenuMap[menuText] = [this, viewpane, &menu]()
|
|
{
|
|
CreateViewPaneMenuItem(m_actionManager, menu, viewpane);
|
|
};
|
|
}
|
|
}
|
|
|
|
if (category == LyViewPane::CategoryTools)
|
|
{
|
|
// Add LUA Editor into the Tools map
|
|
sortMenuMap[s_LUAEditorName] = [this, &menu]()
|
|
{
|
|
auto luaEditormenu = menu.AddAction(ID_TOOLS_LUA_EDITOR);
|
|
connect(luaEditormenu, &QAction::triggered, this, &LaunchLuaEditor, Qt::UniqueConnection);
|
|
};
|
|
}
|
|
|
|
// add each menu option into the menu
|
|
std::map<QString, std::function<void()>, CaseInsensitiveStringCompare>::iterator iter;
|
|
for (iter = sortMenuMap.begin(); iter != sortMenuMap.end(); ++iter)
|
|
{
|
|
iter->second();
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::CreateDebuggingSubMenu(ActionManager::MenuWrapper gameMenu)
|
|
{
|
|
// DebuggingSubMenu
|
|
auto debuggingSubMenu = gameMenu.AddMenu(QObject::tr("Debugging"));
|
|
|
|
// Error Report
|
|
AddOpenViewPaneAction(debuggingSubMenu, LyViewPane::ErrorReport);
|
|
|
|
debuggingSubMenu.AddSeparator();
|
|
|
|
// Configure Toolbox Macros
|
|
debuggingSubMenu.AddAction(ID_TOOLS_CONFIGURETOOLS);
|
|
|
|
// Toolbox Macros
|
|
m_macrosMenu = debuggingSubMenu.AddMenu(tr("ToolBox Macros"));
|
|
connect(m_macrosMenu, &QMenu::aboutToShow, this, &LevelEditorMenuHandler::UpdateMacrosMenu, Qt::UniqueConnection);
|
|
|
|
UpdateMacrosMenu();
|
|
}
|
|
|
|
void LevelEditorMenuHandler::UpdateMRUFiles()
|
|
{
|
|
auto cryEdit = CCryEditApp::instance();
|
|
RecentFileList* mruList = cryEdit->GetRecentFileList();
|
|
const int numMru = mruList->GetSize();
|
|
|
|
if (!m_mostRecentLevelsMenu)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Remove most recent items
|
|
m_mostRecentLevelsMenu->clear();
|
|
|
|
// Insert mrus
|
|
QString sCurDir = QString(Path::GetEditingGameDataFolder().c_str()) + QDir::separator();
|
|
|
|
QFileInfo gameDir(sCurDir); // Pass it through QFileInfo so it comes out normalized
|
|
const QString gameDirPath = gameDir.absolutePath();
|
|
|
|
for (int i = 0; i < numMru; ++i)
|
|
{
|
|
if (!MRUEntryIsValid((*mruList)[i], gameDirPath))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
QString displayName;
|
|
mruList->GetDisplayName(displayName, i, sCurDir);
|
|
|
|
QString entry = QString("%1 %2").arg(i + 1).arg(displayName);
|
|
QAction* action = m_actionManager->GetAction(ID_FILE_MRU_FILE1 + i);
|
|
action->setText(entry);
|
|
|
|
m_actionManager->RegisterActionHandler(ID_FILE_MRU_FILE1 + i, [i]()
|
|
{
|
|
auto cryEdit = CCryEditApp::instance();
|
|
RecentFileList* mruList = cryEdit->GetRecentFileList();
|
|
// Check file is still available
|
|
if (mruList->GetSize() > i)
|
|
{
|
|
cryEdit->OpenDocumentFile((*mruList)[i].toUtf8().data());
|
|
}
|
|
});
|
|
m_actionManager->RegisterUpdateCallback(ID_FILE_MRU_FILE1 + i, cryEdit, &CCryEditApp::OnUpdateFileOpen);
|
|
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(action, [action](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileLevelChanges(action, e);
|
|
}));
|
|
|
|
m_mostRecentLevelsMenu->addAction(action);
|
|
}
|
|
|
|
// Used when disabling the "Open Recent" menu options
|
|
OnUpdateOpenRecent();
|
|
|
|
m_mostRecentLevelsMenu->addSeparator();
|
|
|
|
// Clear All
|
|
auto clearAllMenu = m_mostRecentLevelsMenu->addAction(tr("Clear All"));
|
|
connect(clearAllMenu, &QAction::triggered, this, &LevelEditorMenuHandler::ClearAll);
|
|
}
|
|
|
|
void LevelEditorMenuHandler::ClearAll()
|
|
{
|
|
RecentFileList* mruList = CCryEditApp::instance()->GetRecentFileList();
|
|
|
|
// remove everything from the mru list
|
|
for (int i = mruList->GetSize(); i > 0; i--)
|
|
{
|
|
mruList->Remove(i - 1);
|
|
}
|
|
|
|
// save the settings immediately to the registry
|
|
mruList->WriteList();
|
|
|
|
// re-update the menus
|
|
UpdateMRUFiles();
|
|
}
|
|
|
|
// Used for disabling "Open Recent" menu option
|
|
void LevelEditorMenuHandler::OnUpdateOpenRecent()
|
|
{
|
|
RecentFileList* mruList = CCryEditApp::instance()->GetRecentFileList();
|
|
const int numMru = mruList->GetSize();
|
|
QString currentMru = numMru > 0 ? (*mruList)[0] : QString();
|
|
|
|
if (!currentMru.isEmpty())
|
|
{
|
|
m_mostRecentLevelsMenu->setEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
m_mostRecentLevelsMenu->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::OnUpdateMacrosMenu()
|
|
{
|
|
auto tools = GetIEditor()->GetToolBoxManager();
|
|
const int macroCount = tools->GetMacroCount(true);
|
|
|
|
if (macroCount <= 0)
|
|
{
|
|
m_macrosMenu->setEnabled(false);
|
|
}
|
|
else
|
|
{
|
|
m_macrosMenu->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::UpdateMacrosMenu()
|
|
{
|
|
m_macrosMenu->clear();
|
|
|
|
auto tools = GetIEditor()->GetToolBoxManager();
|
|
const int macroCount = tools->GetMacroCount(true);
|
|
|
|
for (int i = 0; i < macroCount; ++i)
|
|
{
|
|
auto macro = tools->GetMacro(i, true);
|
|
const int toolbarId = macro->GetToolbarId();
|
|
if (toolbarId == -1 || toolbarId == ID_TOOLS_TOOL1)
|
|
{
|
|
m_macrosMenu->addAction(macro->action());
|
|
}
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::UpdateOpenViewPaneMenu()
|
|
{
|
|
// This function goes through all the viewport menu actions (top, left, perspective...)
|
|
// and adds a check mark on the viewport that has focus
|
|
|
|
QtViewport* viewport = m_mainWindow->GetActiveViewport();
|
|
QString activeViewportName = viewport ? viewport->GetName() : QString();
|
|
|
|
for (QAction* action : m_viewportViewsMenu->actions())
|
|
{
|
|
action->setChecked(action->objectName() == activeViewportName);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::checkOrOpenView()
|
|
{
|
|
QAction* action = qobject_cast<QAction*>(sender());
|
|
const QString viewPaneName = action->objectName();
|
|
// If this action is checkable and was just unchecked, then we
|
|
// should close the view pane
|
|
if (action->isCheckable() && !action->isChecked())
|
|
{
|
|
QtViewPaneManager::instance()->ClosePane(viewPaneName);
|
|
}
|
|
// Otherwise, this action should open the view pane
|
|
else
|
|
{
|
|
const QtViewPane* pane = QtViewPaneManager::instance()->OpenPane(viewPaneName);
|
|
|
|
QObject::connect(pane->Widget(), &QWidget::destroyed, action, [action]
|
|
{
|
|
action->setChecked(false);
|
|
});
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::AddDisableActionInSimModeListener(QAction* action)
|
|
{
|
|
GetIEditor()->RegisterNotifyListener(new EditorListener(action, [action](EEditorNotifyEvent e)
|
|
{
|
|
DisableActionWhileInSimMode(action, e);
|
|
}));
|
|
}
|
|
|
|
void LevelEditorMenuHandler::OnEditorModeActivated(
|
|
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
|
{
|
|
if (mode == ViewportEditorMode::Component)
|
|
{
|
|
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
|
!menuWrapper.isNull())
|
|
{
|
|
// copy of menu actions
|
|
auto actions = menuWrapper.Get()->actions();
|
|
// remove all non-reserved edit menu options
|
|
actions.erase(
|
|
std::remove_if(actions.begin(), actions.end(), [](QAction* action)
|
|
{
|
|
return !action->property("Reserved").toBool();
|
|
}),
|
|
actions.end());
|
|
|
|
// clear and update the menu with new actions
|
|
menuWrapper.Get()->clear();
|
|
menuWrapper.Get()->addActions(actions);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::OnEditorModeDeactivated(
|
|
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
|
{
|
|
if (mode == ViewportEditorMode::Component)
|
|
{
|
|
RestoreEditMenuToDefault();
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::AddEditMenuAction(QAction* action)
|
|
{
|
|
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
|
!menuWrapper.isNull())
|
|
{
|
|
menuWrapper.Get()->addAction(action);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::AddMenuAction(AZStd::string_view categoryId, QAction* action, bool addToToolsToolbar)
|
|
{
|
|
auto menuWrapper = m_actionManager->FindMenu(categoryId.data());
|
|
if (menuWrapper.isNull())
|
|
{
|
|
AZ_Assert(false, "No %s category exists in Editor menu.");
|
|
return;
|
|
}
|
|
menuWrapper.Get()->addAction(action);
|
|
|
|
if (addToToolsToolbar)
|
|
{
|
|
m_mainWindow->GetToolbarManager()->AddButtonToEditToolbar(action);
|
|
}
|
|
}
|
|
|
|
void LevelEditorMenuHandler::RestoreEditMenuToDefault()
|
|
{
|
|
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
|
!menuWrapper.isNull())
|
|
{
|
|
menuWrapper.Get()->clear();
|
|
PopulateEditMenu(menuWrapper);
|
|
}
|
|
}
|
|
|
|
#include <Core/moc_LevelEditorMenuHandler.cpp>
|