//// Menu.cpp// interface/src//// Created by Stephen Birarda on 8/12/13.// Copyright 2013 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "Menu.h"#include <QDesktopServices>#include <QFileDialog>#include <QMenuBar>#include <QShortcut> #include <thread> #include <AddressManager.h>#include <AudioClient.h>#include <CrashHelpers.h>#include <DependencyManager.h>#include <ui/TabletScriptingInterface.h>#include <display-plugins/DisplayPlugin.h>#include <PathUtils.h>#include <SettingHandle.h>#include <UserActivityLogger.h>#include <VrMenu.h>#include <ScriptEngines.h>#include <MenuItemProperties.h> #include "Application.h"#include "AccountManager.h"#include "assets/ATPAssetMigrator.h"#include "audio/AudioScope.h"#include "avatar/AvatarManager.h"#include "AvatarBookmarks.h"#include "devices/DdeFaceTracker.h"#include "MainWindow.h"#include "render/DrawStatus.h"#include "scripting/MenuScriptingInterface.h"#include "scripting/HMDScriptingInterface.h"#include "ui/DialogsManager.h"#include "ui/StandAloneJSConsole.h"#include "InterfaceLogging.h"#include "LocationBookmarks.h"#include "DeferredLightingEffect.h"#include "PickManager.h" #include "AmbientOcclusionEffect.h"#include "RenderShadowTask.h"#include "AntialiasingEffect.h" #include "scripting/SettingsScriptingInterface.h"#if defined(Q_OS_MAC) || defined(Q_OS_WIN)#include "SpeechRecognizer.h"#endif extern bool DEV_DECIMATE_TEXTURES; Menu* Menu::getInstance() { return dynamic_cast<Menu*>(qApp->getWindow()->menuBar());} const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; Menu::Menu() { auto dialogsManager = DependencyManager::get<DialogsManager>(); auto accountManager = DependencyManager::get<AccountManager>(); // File/Application menu ---------------------------------- MenuWrapper* fileMenu = addMenu("File"); // File > Login menu items { addActionToQMenuAndActionHash(fileMenu, MenuOption::Login); // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item connect(accountManager.data(), &AccountManager::profileChanged, dialogsManager.data(), &DialogsManager::toggleLoginDialog); connect(accountManager.data(), &AccountManager::logoutComplete, dialogsManager.data(), &DialogsManager::toggleLoginDialog); } // File > Quit addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole); // Edit menu ---------------------------------- MenuWrapper* editMenu = addMenu("Edit"); // Edit > Cut auto cutAction = addActionToQMenuAndActionHash(editMenu, "Cut", QKeySequence::Cut); connect(cutAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Copy auto copyAction = addActionToQMenuAndActionHash(editMenu, "Copy", QKeySequence::Copy); connect(copyAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Paste auto pasteAction = addActionToQMenuAndActionHash(editMenu, "Paste", QKeySequence::Paste); connect(pasteAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_V, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Delete auto deleteAction = addActionToQMenuAndActionHash(editMenu, "Delete", QKeySequence::Delete); connect(deleteAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); editMenu->addSeparator(); // Edit > Running Scripts auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml"); static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml"); static const QString name("RunningScripts"); qApp->showDialog(widgetUrl, tabletUrl, name); }); editMenu->addSeparator(); // Edit > Asset Browser auto assetServerAction = addActionToQMenuAndActionHash(editMenu, MenuOption::AssetServer, Qt::CTRL | Qt::SHIFT | Qt::Key_A, qApp, SLOT(showAssetServerWidget())); { auto nodeList = DependencyManager::get<NodeList>(); QObject::connect(nodeList.data(), &NodeList::canWriteAssetsChanged, assetServerAction, &QAction::setEnabled); assetServerAction->setEnabled(nodeList->getThisNodeCanWriteAssets()); } // Edit > Package Model as .fst... addActionToQMenuAndActionHash(editMenu, MenuOption::PackageModel, 0, qApp, SLOT(packageModel())); // Edit > Reload All Content addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate // default 3D display mode addMenu(DisplayPlugin::MENU_PATH()); MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu); QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu); displayModeGroup->setExclusive(true); // View menu ---------------------------------- MenuWrapper* viewMenu = addMenu("View"); QActionGroup* cameraModeGroup = new QActionGroup(viewMenu); // View > [camera group] cameraModeGroup->setExclusive(true); // View > First Person auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FirstPerson, 0, true, qApp, SLOT(cameraMenuChanged()))); firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Third Person auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::ThirdPerson, 0, false, qApp, SLOT(cameraMenuChanged()))); thirdPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Mirror auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FullscreenMirror, 0, false, qApp, SLOT(cameraMenuChanged()))); viewMirrorAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Independent auto viewIndependentAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::IndependentMode, 0, false, qApp, SLOT(cameraMenuChanged()))); viewIndependentAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Entity Camera auto viewEntityCameraAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CameraEntityMode, 0, false, qApp, SLOT(cameraMenuChanged()))); viewEntityCameraAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); viewMenu->addSeparator(); // View > Center Player In View addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, 0, true, qApp, SLOT(rotationModeChanged())); // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); //TODO: Remove Navigation menu when these functions are included in GoTo menu // Navigate menu ---------------------------------- MenuWrapper* navigateMenu = addMenu("Navigate"); // Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here. auto locationBookmarks = DependencyManager::get<LocationBookmarks>(); locationBookmarks->setupMenus(this, navigateMenu); // Navigate > Copy Address auto addressManager = DependencyManager::get<AddressManager>(); addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyAddress, 0, addressManager.data(), SLOT(copyAddress())); // Navigate > Copy Path addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyPath, 0, addressManager.data(), SLOT(copyPath())); // Settings menu ---------------------------------- MenuWrapper* settingsMenu = addMenu("Settings"); // Settings > General... action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog"); }); // Settings > Controls... action = addActionToQMenuAndActionHash(settingsMenu, "Controls..."); connect(action, &QAction::triggered, [] { auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get<HMDScriptingInterface>(); tablet->pushOntoStack("hifi/tablet/ControllerSettings.qml"); if (!hmd->getShouldShowTablet()) { hmd->toggleShouldShowTablet(); } }); // Settings > Audio... action = addActionToQMenuAndActionHash(settingsMenu, "Audio..."); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/Audio.qml"); static const QUrl tabletUrl("hifi/audio/Audio.qml"); static const QString name("AudioDialog"); qApp->showDialog(widgetUrl, tabletUrl, name); }); // Settings > Graphics... action = addActionToQMenuAndActionHash(settingsMenu, "Graphics..."); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); }); // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); // Settings > Ask to Reset Settings addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::AskToResetSettings, 0, false); // Developer menu ---------------------------------- MenuWrapper* developerMenu = addMenu("Developer", "Developer"); // Developer > UI >>> MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI"); action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0, qApp->getDesktopTabletBecomesToolbarSetting()); connect(action, &QAction::triggered, [action] { qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked()); }); action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0, qApp->getHmdTabletBecomesToolbarSetting()); connect(action, &QAction::triggered, [action] { qApp->setHmdTabletBecomesToolbarSetting(action->isChecked()); }); // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, true); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewJitterCamConfig = renderConfig->getConfig<JitterSample>("RenderMainView.JitterCam"); auto mainViewAntialiasingConfig = renderConfig->getConfig<Antialiasing>("RenderMainView.Antialiasing"); if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { if (action->isChecked()) { mainViewJitterCamConfig->play(); mainViewAntialiasingConfig->setDebugFXAA(false); } else { mainViewJitterCamConfig->none(); mainViewAntialiasingConfig->setDebugFXAA(true); } } } }); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, true); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewShadowTaskConfig = renderConfig->getConfig<RenderShadowTask>("RenderMainView.RenderShadowTask"); if (mainViewShadowTaskConfig) { if (action->isChecked()) { mainViewShadowTaskConfig->setPreset("Enabled"); } else { mainViewShadowTaskConfig->setPreset("None"); } } } }); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, false); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewAmbientOcclusionConfig = renderConfig->getConfig<AmbientOcclusionEffect>("RenderMainView.AmbientOcclusion"); if (mainViewAmbientOcclusionConfig) { if (action->isChecked()) { mainViewAmbientOcclusionConfig->setPreset("Enabled"); } else { mainViewAmbientOcclusionConfig->setPreset("None"); } } } }); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true); // Developer > Render > Throttle FPS If Not Focus addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true); // Developer > Render > OpenVR threaded submit addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true); // Developer > Render > Resolution MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution); QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu); resolutionGroup->setExclusive(true); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, true)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false)); //const QString = "Automatic Texture Memory"; //const QString = "64 MB"; //const QString = "256 MB"; //const QString = "512 MB"; //const QString = "1024 MB"; //const QString = "2048 MB"; // Developer > Render > Maximum Texture Memory MenuWrapper* textureMenu = renderOptionsMenu->addMenu(MenuOption::RenderMaxTextureMemory); QActionGroup* textureGroup = new QActionGroup(textureMenu); textureGroup->setExclusive(true); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTextureAutomatic, 0, true)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture4MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture64MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture256MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture512MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture1024MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture2048MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture4096MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture6144MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture8192MB, 0, false)); connect(textureGroup, &QActionGroup::triggered, [textureGroup] { auto checked = textureGroup->checkedAction(); auto text = checked->text(); gpu::Context::Size newMaxTextureMemory { 0 }; if (MenuOption::RenderMaxTexture4MB == text) { newMaxTextureMemory = MB_TO_BYTES(4); } else if (MenuOption::RenderMaxTexture64MB == text) { newMaxTextureMemory = MB_TO_BYTES(64); } else if (MenuOption::RenderMaxTexture256MB == text) { newMaxTextureMemory = MB_TO_BYTES(256); } else if (MenuOption::RenderMaxTexture512MB == text) { newMaxTextureMemory = MB_TO_BYTES(512); } else if (MenuOption::RenderMaxTexture1024MB == text) { newMaxTextureMemory = MB_TO_BYTES(1024); } else if (MenuOption::RenderMaxTexture2048MB == text) { newMaxTextureMemory = MB_TO_BYTES(2048); } else if (MenuOption::RenderMaxTexture4096MB == text) { newMaxTextureMemory = MB_TO_BYTES(4096); } else if (MenuOption::RenderMaxTexture6144MB == text) { newMaxTextureMemory = MB_TO_BYTES(6144); } else if (MenuOption::RenderMaxTexture8192MB == text) { newMaxTextureMemory = MB_TO_BYTES(8192); } gpu::Texture::setAllowedGPUMemoryUsage(newMaxTextureMemory); }); #ifdef Q_OS_WIN // Developer > Render > Enable Sparse Textures { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::SparseTextureManagement, 0, gpu::Texture::getEnableSparseTextures()); connect(action, &QAction::triggered, [&](bool checked) { qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked; gpu::Texture::setEnableSparseTextures(checked); }); } #else qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer and Dynamic Texture Management not supported on this platform.";#endif { auto action = addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderClearKtxCache); connect(action, &QAction::triggered, []{ Setting::Handle<int>(KTXCache::SETTING_VERSION_NAME, KTXCache::INVALID_VERSION).set(KTXCache::INVALID_VERSION); }); } // Developer > Render > LOD Tools addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, qApp, SLOT(loadLODToolsDialog())); // HACK enable texture decimation { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, "Decimate Textures"); connect(action, &QAction::triggered, [&](bool checked) { DEV_DECIMATE_TEXTURES = checked; }); } addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true, DependencyManager::get<ModelBlender>().data(), SLOT(setComputeBlendshapes(bool))); // Developer > Assets >>> // Menu item is not currently needed but code should be kept in case it proves useful again at some stage.//#define WANT_ASSET_MIGRATION#ifdef WANT_ASSET_MIGRATION MenuWrapper* assetDeveloperMenu = developerMenu->addMenu("Assets"); auto& atpMigrator = ATPAssetMigrator::getInstance(); atpMigrator.setDialogParent(this); addActionToQMenuAndActionHash(assetDeveloperMenu, MenuOption::AssetMigration, 0, &atpMigrator, SLOT(loadEntityServerFile()));#endif // Developer > Avatar >>> MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar"); // Developer > Avatar > Face Tracking MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking"); { QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu); bool defaultNoFaceTracking = true;#ifdef HAVE_DDE defaultNoFaceTracking = false;#endif QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, 0, defaultNoFaceTracking, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(noFaceTracker); #ifdef HAVE_DDE QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseCamera, 0, true, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker);#endif }#ifdef HAVE_DDE faceTrackingMenu->addSeparator(); QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true); binaryEyelidControl->setVisible(true); // DDE face tracking is on by default QAction* coupleEyelids = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CoupleEyelids, 0, true); coupleEyelids->setVisible(true); // DDE face tracking is on by default QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); useAudioForMouth->setVisible(true); // DDE face tracking is on by default QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); ddeFiltering->setVisible(true); // DDE face tracking is on by default QAction* ddeCalibrate = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CalibrateCamera, 0, DependencyManager::get<DdeFaceTracker>().data(), SLOT(calibrate())); ddeCalibrate->setVisible(true); // DDE face tracking is on by default faceTrackingMenu->addSeparator(); addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking, [](bool mute) { FaceTracker::setIsMuted(mute); }, Qt::CTRL | Qt::SHIFT | Qt::Key_F, FaceTracker::isMuted()); addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, false);#endifLines 1–500 of 892. Load more
// // Menu.cpp // interface/src // // Created by Stephen Birarda on 8/12/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "Menu.h" #include <QDesktopServices> #include <QFileDialog> #include <QMenuBar> #include <QShortcut> #include <thread> #include <AddressManager.h> #include <AudioClient.h> #include <CrashHelpers.h> #include <DependencyManager.h> #include <ui/TabletScriptingInterface.h> #include <display-plugins/DisplayPlugin.h> #include <PathUtils.h> #include <SettingHandle.h> #include <UserActivityLogger.h> #include <VrMenu.h> #include <ScriptEngines.h> #include <MenuItemProperties.h> #include "Application.h" #include "AccountManager.h" #include "assets/ATPAssetMigrator.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" #include "AvatarBookmarks.h" #include "devices/DdeFaceTracker.h" #include "MainWindow.h" #include "render/DrawStatus.h" #include "scripting/MenuScriptingInterface.h" #include "scripting/HMDScriptingInterface.h" #include "ui/DialogsManager.h" #include "ui/StandAloneJSConsole.h" #include "InterfaceLogging.h" #include "LocationBookmarks.h" #include "DeferredLightingEffect.h" #include "PickManager.h" #include "AmbientOcclusionEffect.h" #include "RenderShadowTask.h" #include "AntialiasingEffect.h" #include "scripting/SettingsScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" #endif extern bool DEV_DECIMATE_TEXTURES; Menu* Menu::getInstance() { return dynamic_cast<Menu*>(qApp->getWindow()->menuBar()); } const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; Menu::Menu() { auto dialogsManager = DependencyManager::get<DialogsManager>(); auto accountManager = DependencyManager::get<AccountManager>(); // File/Application menu ---------------------------------- MenuWrapper* fileMenu = addMenu("File"); // File > Login menu items { addActionToQMenuAndActionHash(fileMenu, MenuOption::Login); // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item connect(accountManager.data(), &AccountManager::profileChanged, dialogsManager.data(), &DialogsManager::toggleLoginDialog); connect(accountManager.data(), &AccountManager::logoutComplete, dialogsManager.data(), &DialogsManager::toggleLoginDialog); } // File > Quit addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole); // Edit menu ---------------------------------- MenuWrapper* editMenu = addMenu("Edit"); // Edit > Cut auto cutAction = addActionToQMenuAndActionHash(editMenu, "Cut", QKeySequence::Cut); connect(cutAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Copy auto copyAction = addActionToQMenuAndActionHash(editMenu, "Copy", QKeySequence::Copy); connect(copyAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Paste auto pasteAction = addActionToQMenuAndActionHash(editMenu, "Paste", QKeySequence::Paste); connect(pasteAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_V, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); // Edit > Delete auto deleteAction = addActionToQMenuAndActionHash(editMenu, "Delete", QKeySequence::Delete); connect(deleteAction, &QAction::triggered, [] { QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::ControlModifier); QCoreApplication::postEvent(QCoreApplication::instance(), keyEvent); }); editMenu->addSeparator(); // Edit > Running Scripts auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml"); static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml"); static const QString name("RunningScripts"); qApp->showDialog(widgetUrl, tabletUrl, name); }); editMenu->addSeparator(); // Edit > Asset Browser auto assetServerAction = addActionToQMenuAndActionHash(editMenu, MenuOption::AssetServer, Qt::CTRL | Qt::SHIFT | Qt::Key_A, qApp, SLOT(showAssetServerWidget())); { auto nodeList = DependencyManager::get<NodeList>(); QObject::connect(nodeList.data(), &NodeList::canWriteAssetsChanged, assetServerAction, &QAction::setEnabled); assetServerAction->setEnabled(nodeList->getThisNodeCanWriteAssets()); } // Edit > Package Model as .fst... addActionToQMenuAndActionHash(editMenu, MenuOption::PackageModel, 0, qApp, SLOT(packageModel())); // Edit > Reload All Content addActionToQMenuAndActionHash(editMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate // default 3D display mode addMenu(DisplayPlugin::MENU_PATH()); MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu); QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu); displayModeGroup->setExclusive(true); // View menu ---------------------------------- MenuWrapper* viewMenu = addMenu("View"); QActionGroup* cameraModeGroup = new QActionGroup(viewMenu); // View > [camera group] cameraModeGroup->setExclusive(true); // View > First Person auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FirstPerson, 0, true, qApp, SLOT(cameraMenuChanged()))); firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Third Person auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::ThirdPerson, 0, false, qApp, SLOT(cameraMenuChanged()))); thirdPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Mirror auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FullscreenMirror, 0, false, qApp, SLOT(cameraMenuChanged()))); viewMirrorAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Independent auto viewIndependentAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::IndependentMode, 0, false, qApp, SLOT(cameraMenuChanged()))); viewIndependentAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Entity Camera auto viewEntityCameraAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CameraEntityMode, 0, false, qApp, SLOT(cameraMenuChanged()))); viewEntityCameraAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); viewMenu->addSeparator(); // View > Center Player In View addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, 0, true, qApp, SLOT(rotationModeChanged())); // View > Enter First Person Mode in HMD addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); //TODO: Remove Navigation menu when these functions are included in GoTo menu // Navigate menu ---------------------------------- MenuWrapper* navigateMenu = addMenu("Navigate"); // Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here. auto locationBookmarks = DependencyManager::get<LocationBookmarks>(); locationBookmarks->setupMenus(this, navigateMenu); // Navigate > Copy Address auto addressManager = DependencyManager::get<AddressManager>(); addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyAddress, 0, addressManager.data(), SLOT(copyAddress())); // Navigate > Copy Path addActionToQMenuAndActionHash(navigateMenu, MenuOption::CopyPath, 0, addressManager.data(), SLOT(copyPath())); // Settings menu ---------------------------------- MenuWrapper* settingsMenu = addMenu("Settings"); // Settings > General... action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog"); }); // Settings > Controls... action = addActionToQMenuAndActionHash(settingsMenu, "Controls..."); connect(action, &QAction::triggered, [] { auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get<HMDScriptingInterface>(); tablet->pushOntoStack("hifi/tablet/ControllerSettings.qml"); if (!hmd->getShouldShowTablet()) { hmd->toggleShouldShowTablet(); } }); // Settings > Audio... action = addActionToQMenuAndActionHash(settingsMenu, "Audio..."); connect(action, &QAction::triggered, [] { static const QUrl widgetUrl("hifi/dialogs/Audio.qml"); static const QUrl tabletUrl("hifi/audio/Audio.qml"); static const QString name("AudioDialog"); qApp->showDialog(widgetUrl, tabletUrl, name); }); // Settings > Graphics... action = addActionToQMenuAndActionHash(settingsMenu, "Graphics..."); connect(action, &QAction::triggered, [] { qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); }); // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); // Settings > Ask to Reset Settings addCheckableActionToQMenuAndActionHash(settingsMenu, MenuOption::AskToResetSettings, 0, false); // Developer menu ---------------------------------- MenuWrapper* developerMenu = addMenu("Developer", "Developer"); // Developer > UI >>> MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI"); action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0, qApp->getDesktopTabletBecomesToolbarSetting()); connect(action, &QAction::triggered, [action] { qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked()); }); action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0, qApp->getHmdTabletBecomesToolbarSetting()); connect(action, &QAction::triggered, [action] { qApp->setHmdTabletBecomesToolbarSetting(action->isChecked()); }); // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, true); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewJitterCamConfig = renderConfig->getConfig<JitterSample>("RenderMainView.JitterCam"); auto mainViewAntialiasingConfig = renderConfig->getConfig<Antialiasing>("RenderMainView.Antialiasing"); if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { if (action->isChecked()) { mainViewJitterCamConfig->play(); mainViewAntialiasingConfig->setDebugFXAA(false); } else { mainViewJitterCamConfig->none(); mainViewAntialiasingConfig->setDebugFXAA(true); } } } }); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, true); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewShadowTaskConfig = renderConfig->getConfig<RenderShadowTask>("RenderMainView.RenderShadowTask"); if (mainViewShadowTaskConfig) { if (action->isChecked()) { mainViewShadowTaskConfig->setPreset("Enabled"); } else { mainViewShadowTaskConfig->setPreset("None"); } } } }); action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, false); connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { auto mainViewAmbientOcclusionConfig = renderConfig->getConfig<AmbientOcclusionEffect>("RenderMainView.AmbientOcclusion"); if (mainViewAmbientOcclusionConfig) { if (action->isChecked()) { mainViewAmbientOcclusionConfig->setPreset("Enabled"); } else { mainViewAmbientOcclusionConfig->setPreset("None"); } } } }); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true); // Developer > Render > Throttle FPS If Not Focus addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true); // Developer > Render > OpenVR threaded submit addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true); // Developer > Render > Resolution MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution); QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu); resolutionGroup->setExclusive(true); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, true)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false)); resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false)); //const QString = "Automatic Texture Memory"; //const QString = "64 MB"; //const QString = "256 MB"; //const QString = "512 MB"; //const QString = "1024 MB"; //const QString = "2048 MB"; // Developer > Render > Maximum Texture Memory MenuWrapper* textureMenu = renderOptionsMenu->addMenu(MenuOption::RenderMaxTextureMemory); QActionGroup* textureGroup = new QActionGroup(textureMenu); textureGroup->setExclusive(true); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTextureAutomatic, 0, true)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture4MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture64MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture256MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture512MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture1024MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture2048MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture4096MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture6144MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture8192MB, 0, false)); connect(textureGroup, &QActionGroup::triggered, [textureGroup] { auto checked = textureGroup->checkedAction(); auto text = checked->text(); gpu::Context::Size newMaxTextureMemory { 0 }; if (MenuOption::RenderMaxTexture4MB == text) { newMaxTextureMemory = MB_TO_BYTES(4); } else if (MenuOption::RenderMaxTexture64MB == text) { newMaxTextureMemory = MB_TO_BYTES(64); } else if (MenuOption::RenderMaxTexture256MB == text) { newMaxTextureMemory = MB_TO_BYTES(256); } else if (MenuOption::RenderMaxTexture512MB == text) { newMaxTextureMemory = MB_TO_BYTES(512); } else if (MenuOption::RenderMaxTexture1024MB == text) { newMaxTextureMemory = MB_TO_BYTES(1024); } else if (MenuOption::RenderMaxTexture2048MB == text) { newMaxTextureMemory = MB_TO_BYTES(2048); } else if (MenuOption::RenderMaxTexture4096MB == text) { newMaxTextureMemory = MB_TO_BYTES(4096); } else if (MenuOption::RenderMaxTexture6144MB == text) { newMaxTextureMemory = MB_TO_BYTES(6144); } else if (MenuOption::RenderMaxTexture8192MB == text) { newMaxTextureMemory = MB_TO_BYTES(8192); } gpu::Texture::setAllowedGPUMemoryUsage(newMaxTextureMemory); }); #ifdef Q_OS_WIN // Developer > Render > Enable Sparse Textures { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::SparseTextureManagement, 0, gpu::Texture::getEnableSparseTextures()); connect(action, &QAction::triggered, [&](bool checked) { qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked; gpu::Texture::setEnableSparseTextures(checked); }); } #else qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer and Dynamic Texture Management not supported on this platform."; #endif { auto action = addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderClearKtxCache); connect(action, &QAction::triggered, []{ Setting::Handle<int>(KTXCache::SETTING_VERSION_NAME, KTXCache::INVALID_VERSION).set(KTXCache::INVALID_VERSION); }); } // Developer > Render > LOD Tools addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, qApp, SLOT(loadLODToolsDialog())); // HACK enable texture decimation { auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, "Decimate Textures"); connect(action, &QAction::triggered, [&](bool checked) { DEV_DECIMATE_TEXTURES = checked; }); } addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true, DependencyManager::get<ModelBlender>().data(), SLOT(setComputeBlendshapes(bool))); // Developer > Assets >>> // Menu item is not currently needed but code should be kept in case it proves useful again at some stage. //#define WANT_ASSET_MIGRATION #ifdef WANT_ASSET_MIGRATION MenuWrapper* assetDeveloperMenu = developerMenu->addMenu("Assets"); auto& atpMigrator = ATPAssetMigrator::getInstance(); atpMigrator.setDialogParent(this); addActionToQMenuAndActionHash(assetDeveloperMenu, MenuOption::AssetMigration, 0, &atpMigrator, SLOT(loadEntityServerFile())); #endif // Developer > Avatar >>> MenuWrapper* avatarDebugMenu = developerMenu->addMenu("Avatar"); // Developer > Avatar > Face Tracking MenuWrapper* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking"); { QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu); bool defaultNoFaceTracking = true; #ifdef HAVE_DDE defaultNoFaceTracking = false; #endif QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking, 0, defaultNoFaceTracking, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(noFaceTracker); #ifdef HAVE_DDE QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseCamera, 0, true, qApp, SLOT(setActiveFaceTracker())); faceTrackerGroup->addAction(ddeFaceTracker); #endif } #ifdef HAVE_DDE faceTrackingMenu->addSeparator(); QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true); binaryEyelidControl->setVisible(true); // DDE face tracking is on by default QAction* coupleEyelids = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CoupleEyelids, 0, true); coupleEyelids->setVisible(true); // DDE face tracking is on by default QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); useAudioForMouth->setVisible(true); // DDE face tracking is on by default QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); ddeFiltering->setVisible(true); // DDE face tracking is on by default QAction* ddeCalibrate = addActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CalibrateCamera, 0, DependencyManager::get<DdeFaceTracker>().data(), SLOT(calibrate())); ddeCalibrate->setVisible(true); // DDE face tracking is on by default faceTrackingMenu->addSeparator(); addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking, [](bool mute) { FaceTracker::setIsMuted(mute); }, Qt::CTRL | Qt::SHIFT | Qt::Key_F, FaceTracker::isMuted()); addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, false); #endif