false, &UserActivityLogger::getInstance(), SLOT(disable(bool))); addActionToQMenuAndActionHash(developerMenu, MenuOption::WalletPrivateKey, 0, this, SLOT(changePrivateKey())); QMenu* timingMenu = developerMenu->addMenu("Timing and Stats"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings); QMenu* frustumMenu = developerMenu->addMenu("View Frustum"); addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F); addActionToQMenuAndActionHash(frustumMenu, MenuOption::FrustumRenderMode, Qt::SHIFT | Qt::Key_R, this, SLOT(cycleFrustumRenderMode())); updateFrustumRenderModeAction(); QMenu* audioDebugMenu = developerMenu->addMenu("Audio"); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, 0, true, appInstance->getAudio(), SLOT(toggleAudioNoiseReduction())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false, appInstance->getAudio(), SLOT(toggleStereoInput())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, Qt::CTRL | Qt::Key_M, false, appInstance->getAudio(), SLOT(toggleMute())); addActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteEnvironment, 0, this, SLOT(muteEnvironment())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioSourceInject, 0, false, appInstance->getAudio(), SLOT(toggleAudioSourceInject())); QMenu* audioSourceMenu = audioDebugMenu->addMenu("Generated Audio Source"); { QAction *pinkNoise = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourcePinkNoise, 0, false, appInstance->getAudio(), SLOT(selectAudioSourcePinkNoise())); QAction *sine440 = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourceSine440, 0, true, appInstance->getAudio(), SLOT(selectAudioSourceSine440())); QActionGroup* audioSourceGroup = new QActionGroup(audioSourceMenu); audioSourceGroup->addAction(pinkNoise); audioSourceGroup->addAction(sine440); } QMenu* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_P, false, appInstance->getAudio(), SLOT(toggleScope())); addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::SHIFT | Qt::Key_P , false, appInstance->getAudio(), SLOT(toggleScopePause())); addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); { QAction *fiveFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiveFrames, 0, true, appInstance->getAudio(), SLOT(selectAudioScopeFiveFrames())); QAction *twentyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeTwentyFrames, 0, false, appInstance->getAudio(), SLOT(selectAudioScopeTwentyFrames())); QAction *fiftyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiftyFrames, 0, false, appInstance->getAudio(), SLOT(selectAudioScopeFiftyFrames())); QActionGroup* audioScopeFramesGroup = new QActionGroup(audioScopeMenu); audioScopeFramesGroup->addAction(fiveFrames); audioScopeFramesGroup->addAction(twentyFrames); audioScopeFramesGroup->addAction(fiftyFrames); } addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats, Qt::CTRL | Qt::Key_A, false, appInstance->getAudio(), SLOT(toggleStats())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStatsShowInjectedStreams, 0, false, appInstance->getAudio(), SLOT(toggleStatsShowInjectedStreams())); connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); QMenu* experimentalOptionsMenu = developerMenu->addMenu("Experimental"); addCheckableActionToQMenuAndActionHash(experimentalOptionsMenu, MenuOption::StringHair, 0, false); addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, Qt::CTRL | Qt::SHIFT | Qt::Key_V, this, SLOT(pasteToVoxel())); #ifndef Q_OS_MAC QMenu* helpMenu = addMenu("Help"); QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); connect(helpAction, SIGNAL(triggered()), this, SLOT(aboutApp()));#endif} Menu::~Menu() { bandwidthDetailsClosed(); octreeStatsDetailsClosed(); if (_hmdToolsDialog) { delete _hmdToolsDialog; _hmdToolsDialog = NULL; }} void Menu::loadSettings(QSettings* settings) { bool lockedSettings = false; if (!settings) { settings = Application::getInstance()->lockSettings(); lockedSettings = true; } _receivedAudioStreamSettings._dynamicJitterBuffers = settings->value("dynamicJitterBuffers", DEFAULT_DYNAMIC_JITTER_BUFFERS).toBool(); _receivedAudioStreamSettings._maxFramesOverDesired = settings->value("maxFramesOverDesired", DEFAULT_MAX_FRAMES_OVER_DESIRED).toInt(); _receivedAudioStreamSettings._staticDesiredJitterBufferFrames = settings->value("staticDesiredJitterBufferFrames", DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES).toInt(); _receivedAudioStreamSettings._useStDevForJitterCalc = settings->value("useStDevForJitterCalc", DEFAULT_USE_STDEV_FOR_JITTER_CALC).toBool(); _receivedAudioStreamSettings._windowStarveThreshold = settings->value("windowStarveThreshold", DEFAULT_WINDOW_STARVE_THRESHOLD).toInt(); _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves = settings->value("windowSecondsForDesiredCalcOnTooManyStarves", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES).toInt(); _receivedAudioStreamSettings._windowSecondsForDesiredReduction = settings->value("windowSecondsForDesiredReduction", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION).toInt(); _receivedAudioStreamSettings._repetitionWithFade = settings->value("repetitionWithFade", DEFAULT_REPETITION_WITH_FADE).toBool(); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); _realWorldFieldOfView = loadSetting(settings, "realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES); _faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION); _faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString(); _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); _maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS); _voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE); _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool(); _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS); _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS); _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier", DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER); _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); _snapshotsLocation = settings->value("snapshotsLocation", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString(); setScriptsLocation(settings->value("scriptsLocation", QString()).toString()); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) _speechRecognizer.setEnabled(settings->value("speechRecognitionEnabled", false).toBool());#endif settings->beginGroup("View Frustum Offset Camera"); // in case settings is corrupt or missing loadSetting() will check for NaN _viewFrustumOffset.yaw = loadSetting(settings, "viewFrustumOffsetYaw", 0.0f); _viewFrustumOffset.pitch = loadSetting(settings, "viewFrustumOffsetPitch", 0.0f); _viewFrustumOffset.roll = loadSetting(settings, "viewFrustumOffsetRoll", 0.0f); _viewFrustumOffset.distance = loadSetting(settings, "viewFrustumOffsetDistance", 0.0f); _viewFrustumOffset.up = loadSetting(settings, "viewFrustumOffsetUp", 0.0f); settings->endGroup(); _walletPrivateKey = settings->value("privateKey").toByteArray(); scanMenuBar(&loadAction, settings); Application::getInstance()->getAvatar()->loadData(settings); Application::getInstance()->updateWindowTitle(); // notify that a settings has changed connect(&NodeList::getInstance()->getDomainHandler(), &DomainHandler::hostnameChanged, this, &Menu::bumpSettings); // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. setIsOptionChecked(MenuOption::KeyboardMotorControl , true); MyAvatar* myAvatar = Application::getInstance()->getAvatar(); myAvatar->updateCollisionGroups(); myAvatar->onToggleRagdoll(); myAvatar->updateMotionBehavior(); if (lockedSettings) { Application::getInstance()->unlockSettings(); }} void Menu::saveSettings(QSettings* settings) { bool lockedSettings = false; if (!settings) { settings = Application::getInstance()->lockSettings(); lockedSettings = true; } settings->setValue("dynamicJitterBuffers", _receivedAudioStreamSettings._dynamicJitterBuffers); settings->setValue("maxFramesOverDesired", _receivedAudioStreamSettings._maxFramesOverDesired); settings->setValue("staticDesiredJitterBufferFrames", _receivedAudioStreamSettings._staticDesiredJitterBufferFrames); settings->setValue("useStDevForJitterCalc", _receivedAudioStreamSettings._useStDevForJitterCalc); settings->setValue("windowStarveThreshold", _receivedAudioStreamSettings._windowStarveThreshold); settings->setValue("windowSecondsForDesiredCalcOnTooManyStarves", _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves); settings->setValue("windowSecondsForDesiredReduction", _receivedAudioStreamSettings._windowSecondsForDesiredReduction); settings->setValue("repetitionWithFade", _receivedAudioStreamSettings._repetitionWithFade); settings->setValue("fieldOfView", _fieldOfView); settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection); settings->setValue("faceshiftHostname", _faceshiftHostname); settings->setValue("maxVoxels", _maxVoxels); settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond); settings->setValue("voxelSizeScale", _voxelSizeScale); settings->setValue("automaticAvatarLOD", _automaticAvatarLOD); settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS); settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS); settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->setValue("snapshotsLocation", _snapshotsLocation); settings->setValue("scriptsLocation", _scriptsLocation);#if defined(Q_OS_MAC) || defined(Q_OS_WIN) settings->setValue("speechRecognitionEnabled", _speechRecognizer.getEnabled());#endif settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); settings->setValue("viewFrustumOffsetRoll", _viewFrustumOffset.roll); settings->setValue("viewFrustumOffsetDistance", _viewFrustumOffset.distance); settings->setValue("viewFrustumOffsetUp", _viewFrustumOffset.up); settings->endGroup(); settings->setValue("privateKey", _walletPrivateKey); scanMenuBar(&saveAction, settings); Application::getInstance()->getAvatar()->saveData(settings); settings->setValue(SETTINGS_ADDRESS_KEY, AddressManager::getInstance().currentAddress()); if (lockedSettings) { Application::getInstance()->unlockSettings(); }} void Menu::importSettings() { QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(), tr("Open .ini config file"), locationDir, tr("Text files (*.ini)")); if (fileName != "") { QSettings tmp(fileName, QSettings::IniFormat); loadSettings(&tmp); }} void Menu::exportSettings() { QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getSaveFileName(Application::getInstance()->getWindow(), tr("Save .ini config file"), locationDir, tr("Text files (*.ini)")); if (fileName != "") { QSettings tmp(fileName, QSettings::IniFormat); saveSettings(&tmp); tmp.sync(); }} void Menu::loadAction(QSettings* set, QAction* action) { if (action->isChecked() != set->value(action->text(), action->isChecked()).toBool()) { action->trigger(); }} void Menu::saveAction(QSettings* set, QAction* action) { set->setValue(action->text(), action->isChecked());} void Menu::scanMenuBar(settingsAction modifySetting, QSettings* set) { QList<QMenu*> menus = this->findChildren<QMenu *>(); for (QList<QMenu *>::const_iterator it = menus.begin(); menus.end() != it; ++it) { scanMenu(*it, modifySetting, set); }} void Menu::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) { QList<QAction*> actions = menu->actions(); set->beginGroup(menu->title()); for (QList<QAction *>::const_iterator it = actions.begin(); actions.end() != it; ++it) { if ((*it)->menu()) { scanMenu((*it)->menu(), modifySetting, set); } if ((*it)->isCheckable()) { modifySetting(set, *it); } } set->endGroup();} bool Menu::getShadowsEnabled() const { return isOptionChecked(MenuOption::SimpleShadows) || isOptionChecked(MenuOption::CascadedShadows);} void Menu::handleViewFrustumOffsetKeyModifier(int key) { const float VIEW_FRUSTUM_OFFSET_DELTA = 0.5f; const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; switch (key) { case Qt::Key_QuoteDbl: _viewFrustumOffset.yaw = 0.0f; _viewFrustumOffset.pitch = 0.0f; _viewFrustumOffset.roll = 0.0f; _viewFrustumOffset.up = 0.0f; _viewFrustumOffset.distance = 0.0f; break; case Qt::Key_BracketLeft: _viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BracketRight: _viewFrustumOffset.yaw += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BraceLeft: _viewFrustumOffset.pitch -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BraceRight: _viewFrustumOffset.pitch += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_ParenLeft: _viewFrustumOffset.roll -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_ParenRight: _viewFrustumOffset.roll += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Less: _viewFrustumOffset.distance -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Greater: _viewFrustumOffset.distance += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Comma: _viewFrustumOffset.up -= VIEW_FRUSTUM_OFFSET_UP_DELTA; break; case Qt::Key_Period: _viewFrustumOffset.up += VIEW_FRUSTUM_OFFSET_UP_DELTA; break; default: break; } bumpSettings();} void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) { QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (actionBefore) { QAction* separator = new QAction("",destinationMenu); destinationMenu->insertAction(actionBefore, separator); separator->setSeparator(true); QAction* separatorText = new QAction(actionName,destinationMenu); separatorText->setEnabled(false); destinationMenu->insertAction(actionBefore, separatorText); } else { destinationMenu->addSeparator(); (destinationMenu->addAction(actionName))->setEnabled(false); }} QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu, const QString& actionName, const QKeySequence& shortcut, const QObject* receiver, const char* member, QAction::MenuRole role, int menuItemLocation) { QAction* action = NULL; QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (!actionBefore) { if (receiver && member) { action = destinationMenu->addAction(actionName, receiver, member, shortcut); } else { action = destinationMenu->addAction(actionName); action->setShortcut(shortcut); } } else { action = new QAction(actionName, destinationMenu); action->setShortcut(shortcut); destinationMenu->insertAction(actionBefore, action); if (receiver && member) { connect(action, SIGNAL(triggered()), receiver, member); } } action->setMenuRole(role); _actionHash.insert(actionName, action); return action;} QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu, QAction* action, const QString& actionName, const QKeySequence& shortcut, QAction::MenuRole role, int menuItemLocation) { QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (!actionName.isEmpty()) { action->setText(actionName); } if (shortcut != 0) { action->setShortcut(shortcut); } if (role != QAction::NoRole) { action->setMenuRole(role); } if (!actionBefore) { destinationMenu->addAction(action); } else { destinationMenu->insertAction(actionBefore, action); } _actionHash.insert(action->text(), action); return action;} QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, const QString& actionName, const QKeySequence& shortcut, const bool checked, const QObject* receiver, const char* member, int menuItemLocation) { QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, QAction::NoRole, menuItemLocation); action->setCheckable(true); action->setChecked(checked); connect(action, SIGNAL(changed()), this, SLOT(bumpSettings())); return action;}Lines 501–1000 of 1892. Previous lines Load more
false, &UserActivityLogger::getInstance(), SLOT(disable(bool))); addActionToQMenuAndActionHash(developerMenu, MenuOption::WalletPrivateKey, 0, this, SLOT(changePrivateKey())); QMenu* timingMenu = developerMenu->addMenu("Timing and Stats"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings); QMenu* frustumMenu = developerMenu->addMenu("View Frustum"); addCheckableActionToQMenuAndActionHash(frustumMenu, MenuOption::DisplayFrustum, Qt::SHIFT | Qt::Key_F); addActionToQMenuAndActionHash(frustumMenu, MenuOption::FrustumRenderMode, Qt::SHIFT | Qt::Key_R, this, SLOT(cycleFrustumRenderMode())); updateFrustumRenderModeAction(); QMenu* audioDebugMenu = developerMenu->addMenu("Audio"); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, 0, true, appInstance->getAudio(), SLOT(toggleAudioNoiseReduction())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false, appInstance->getAudio(), SLOT(toggleStereoInput())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, Qt::CTRL | Qt::Key_M, false, appInstance->getAudio(), SLOT(toggleMute())); addActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteEnvironment, 0, this, SLOT(muteEnvironment())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioSourceInject, 0, false, appInstance->getAudio(), SLOT(toggleAudioSourceInject())); QMenu* audioSourceMenu = audioDebugMenu->addMenu("Generated Audio Source"); { QAction *pinkNoise = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourcePinkNoise, 0, false, appInstance->getAudio(), SLOT(selectAudioSourcePinkNoise())); QAction *sine440 = addCheckableActionToQMenuAndActionHash(audioSourceMenu, MenuOption::AudioSourceSine440, 0, true, appInstance->getAudio(), SLOT(selectAudioSourceSine440())); QActionGroup* audioSourceGroup = new QActionGroup(audioSourceMenu); audioSourceGroup->addAction(pinkNoise); audioSourceGroup->addAction(sine440); } QMenu* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope"); addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_P, false, appInstance->getAudio(), SLOT(toggleScope())); addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopePause, Qt::CTRL | Qt::SHIFT | Qt::Key_P , false, appInstance->getAudio(), SLOT(toggleScopePause())); addDisabledActionAndSeparator(audioScopeMenu, "Display Frames"); { QAction *fiveFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiveFrames, 0, true, appInstance->getAudio(), SLOT(selectAudioScopeFiveFrames())); QAction *twentyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeTwentyFrames, 0, false, appInstance->getAudio(), SLOT(selectAudioScopeTwentyFrames())); QAction *fiftyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiftyFrames, 0, false, appInstance->getAudio(), SLOT(selectAudioScopeFiftyFrames())); QActionGroup* audioScopeFramesGroup = new QActionGroup(audioScopeMenu); audioScopeFramesGroup->addAction(fiveFrames); audioScopeFramesGroup->addAction(twentyFrames); audioScopeFramesGroup->addAction(fiftyFrames); } addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats, Qt::CTRL | Qt::Key_A, false, appInstance->getAudio(), SLOT(toggleStats())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStatsShowInjectedStreams, 0, false, appInstance->getAudio(), SLOT(toggleStatsShowInjectedStreams())); connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); QMenu* experimentalOptionsMenu = developerMenu->addMenu("Experimental"); addCheckableActionToQMenuAndActionHash(experimentalOptionsMenu, MenuOption::StringHair, 0, false); addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, Qt::CTRL | Qt::SHIFT | Qt::Key_V, this, SLOT(pasteToVoxel())); #ifndef Q_OS_MAC QMenu* helpMenu = addMenu("Help"); QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); connect(helpAction, SIGNAL(triggered()), this, SLOT(aboutApp())); #endif } Menu::~Menu() { bandwidthDetailsClosed(); octreeStatsDetailsClosed(); if (_hmdToolsDialog) { delete _hmdToolsDialog; _hmdToolsDialog = NULL; } } void Menu::loadSettings(QSettings* settings) { bool lockedSettings = false; if (!settings) { settings = Application::getInstance()->lockSettings(); lockedSettings = true; } _receivedAudioStreamSettings._dynamicJitterBuffers = settings->value("dynamicJitterBuffers", DEFAULT_DYNAMIC_JITTER_BUFFERS).toBool(); _receivedAudioStreamSettings._maxFramesOverDesired = settings->value("maxFramesOverDesired", DEFAULT_MAX_FRAMES_OVER_DESIRED).toInt(); _receivedAudioStreamSettings._staticDesiredJitterBufferFrames = settings->value("staticDesiredJitterBufferFrames", DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES).toInt(); _receivedAudioStreamSettings._useStDevForJitterCalc = settings->value("useStDevForJitterCalc", DEFAULT_USE_STDEV_FOR_JITTER_CALC).toBool(); _receivedAudioStreamSettings._windowStarveThreshold = settings->value("windowStarveThreshold", DEFAULT_WINDOW_STARVE_THRESHOLD).toInt(); _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves = settings->value("windowSecondsForDesiredCalcOnTooManyStarves", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES).toInt(); _receivedAudioStreamSettings._windowSecondsForDesiredReduction = settings->value("windowSecondsForDesiredReduction", DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION).toInt(); _receivedAudioStreamSettings._repetitionWithFade = settings->value("repetitionWithFade", DEFAULT_REPETITION_WITH_FADE).toBool(); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); _realWorldFieldOfView = loadSetting(settings, "realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES); _faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION); _faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString(); _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); _maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS); _voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE); _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool(); _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS); _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS); _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier", DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER); _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); _snapshotsLocation = settings->value("snapshotsLocation", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString(); setScriptsLocation(settings->value("scriptsLocation", QString()).toString()); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) _speechRecognizer.setEnabled(settings->value("speechRecognitionEnabled", false).toBool()); #endif settings->beginGroup("View Frustum Offset Camera"); // in case settings is corrupt or missing loadSetting() will check for NaN _viewFrustumOffset.yaw = loadSetting(settings, "viewFrustumOffsetYaw", 0.0f); _viewFrustumOffset.pitch = loadSetting(settings, "viewFrustumOffsetPitch", 0.0f); _viewFrustumOffset.roll = loadSetting(settings, "viewFrustumOffsetRoll", 0.0f); _viewFrustumOffset.distance = loadSetting(settings, "viewFrustumOffsetDistance", 0.0f); _viewFrustumOffset.up = loadSetting(settings, "viewFrustumOffsetUp", 0.0f); settings->endGroup(); _walletPrivateKey = settings->value("privateKey").toByteArray(); scanMenuBar(&loadAction, settings); Application::getInstance()->getAvatar()->loadData(settings); Application::getInstance()->updateWindowTitle(); // notify that a settings has changed connect(&NodeList::getInstance()->getDomainHandler(), &DomainHandler::hostnameChanged, this, &Menu::bumpSettings); // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. setIsOptionChecked(MenuOption::KeyboardMotorControl , true); MyAvatar* myAvatar = Application::getInstance()->getAvatar(); myAvatar->updateCollisionGroups(); myAvatar->onToggleRagdoll(); myAvatar->updateMotionBehavior(); if (lockedSettings) { Application::getInstance()->unlockSettings(); } } void Menu::saveSettings(QSettings* settings) { bool lockedSettings = false; if (!settings) { settings = Application::getInstance()->lockSettings(); lockedSettings = true; } settings->setValue("dynamicJitterBuffers", _receivedAudioStreamSettings._dynamicJitterBuffers); settings->setValue("maxFramesOverDesired", _receivedAudioStreamSettings._maxFramesOverDesired); settings->setValue("staticDesiredJitterBufferFrames", _receivedAudioStreamSettings._staticDesiredJitterBufferFrames); settings->setValue("useStDevForJitterCalc", _receivedAudioStreamSettings._useStDevForJitterCalc); settings->setValue("windowStarveThreshold", _receivedAudioStreamSettings._windowStarveThreshold); settings->setValue("windowSecondsForDesiredCalcOnTooManyStarves", _receivedAudioStreamSettings._windowSecondsForDesiredCalcOnTooManyStarves); settings->setValue("windowSecondsForDesiredReduction", _receivedAudioStreamSettings._windowSecondsForDesiredReduction); settings->setValue("repetitionWithFade", _receivedAudioStreamSettings._repetitionWithFade); settings->setValue("fieldOfView", _fieldOfView); settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection); settings->setValue("faceshiftHostname", _faceshiftHostname); settings->setValue("maxVoxels", _maxVoxels); settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond); settings->setValue("voxelSizeScale", _voxelSizeScale); settings->setValue("automaticAvatarLOD", _automaticAvatarLOD); settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS); settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS); settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->setValue("snapshotsLocation", _snapshotsLocation); settings->setValue("scriptsLocation", _scriptsLocation); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) settings->setValue("speechRecognitionEnabled", _speechRecognizer.getEnabled()); #endif settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); settings->setValue("viewFrustumOffsetRoll", _viewFrustumOffset.roll); settings->setValue("viewFrustumOffsetDistance", _viewFrustumOffset.distance); settings->setValue("viewFrustumOffsetUp", _viewFrustumOffset.up); settings->endGroup(); settings->setValue("privateKey", _walletPrivateKey); scanMenuBar(&saveAction, settings); Application::getInstance()->getAvatar()->saveData(settings); settings->setValue(SETTINGS_ADDRESS_KEY, AddressManager::getInstance().currentAddress()); if (lockedSettings) { Application::getInstance()->unlockSettings(); } } void Menu::importSettings() { QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(), tr("Open .ini config file"), locationDir, tr("Text files (*.ini)")); if (fileName != "") { QSettings tmp(fileName, QSettings::IniFormat); loadSettings(&tmp); } } void Menu::exportSettings() { QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileName = QFileDialog::getSaveFileName(Application::getInstance()->getWindow(), tr("Save .ini config file"), locationDir, tr("Text files (*.ini)")); if (fileName != "") { QSettings tmp(fileName, QSettings::IniFormat); saveSettings(&tmp); tmp.sync(); } } void Menu::loadAction(QSettings* set, QAction* action) { if (action->isChecked() != set->value(action->text(), action->isChecked()).toBool()) { action->trigger(); } } void Menu::saveAction(QSettings* set, QAction* action) { set->setValue(action->text(), action->isChecked()); } void Menu::scanMenuBar(settingsAction modifySetting, QSettings* set) { QList<QMenu*> menus = this->findChildren<QMenu *>(); for (QList<QMenu *>::const_iterator it = menus.begin(); menus.end() != it; ++it) { scanMenu(*it, modifySetting, set); } } void Menu::scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set) { QList<QAction*> actions = menu->actions(); set->beginGroup(menu->title()); for (QList<QAction *>::const_iterator it = actions.begin(); actions.end() != it; ++it) { if ((*it)->menu()) { scanMenu((*it)->menu(), modifySetting, set); } if ((*it)->isCheckable()) { modifySetting(set, *it); } } set->endGroup(); } bool Menu::getShadowsEnabled() const { return isOptionChecked(MenuOption::SimpleShadows) || isOptionChecked(MenuOption::CascadedShadows); } void Menu::handleViewFrustumOffsetKeyModifier(int key) { const float VIEW_FRUSTUM_OFFSET_DELTA = 0.5f; const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; switch (key) { case Qt::Key_QuoteDbl: _viewFrustumOffset.yaw = 0.0f; _viewFrustumOffset.pitch = 0.0f; _viewFrustumOffset.roll = 0.0f; _viewFrustumOffset.up = 0.0f; _viewFrustumOffset.distance = 0.0f; break; case Qt::Key_BracketLeft: _viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BracketRight: _viewFrustumOffset.yaw += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BraceLeft: _viewFrustumOffset.pitch -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_BraceRight: _viewFrustumOffset.pitch += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_ParenLeft: _viewFrustumOffset.roll -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_ParenRight: _viewFrustumOffset.roll += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Less: _viewFrustumOffset.distance -= VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Greater: _viewFrustumOffset.distance += VIEW_FRUSTUM_OFFSET_DELTA; break; case Qt::Key_Comma: _viewFrustumOffset.up -= VIEW_FRUSTUM_OFFSET_UP_DELTA; break; case Qt::Key_Period: _viewFrustumOffset.up += VIEW_FRUSTUM_OFFSET_UP_DELTA; break; default: break; } bumpSettings(); } void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName, int menuItemLocation) { QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (actionBefore) { QAction* separator = new QAction("",destinationMenu); destinationMenu->insertAction(actionBefore, separator); separator->setSeparator(true); QAction* separatorText = new QAction(actionName,destinationMenu); separatorText->setEnabled(false); destinationMenu->insertAction(actionBefore, separatorText); } else { destinationMenu->addSeparator(); (destinationMenu->addAction(actionName))->setEnabled(false); } } QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu, const QString& actionName, const QKeySequence& shortcut, const QObject* receiver, const char* member, QAction::MenuRole role, int menuItemLocation) { QAction* action = NULL; QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (!actionBefore) { if (receiver && member) { action = destinationMenu->addAction(actionName, receiver, member, shortcut); } else { action = destinationMenu->addAction(actionName); action->setShortcut(shortcut); } } else { action = new QAction(actionName, destinationMenu); action->setShortcut(shortcut); destinationMenu->insertAction(actionBefore, action); if (receiver && member) { connect(action, SIGNAL(triggered()), receiver, member); } } action->setMenuRole(role); _actionHash.insert(actionName, action); return action; } QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu, QAction* action, const QString& actionName, const QKeySequence& shortcut, QAction::MenuRole role, int menuItemLocation) { QAction* actionBefore = NULL; if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { actionBefore = destinationMenu->actions()[menuItemLocation]; } if (!actionName.isEmpty()) { action->setText(actionName); } if (shortcut != 0) { action->setShortcut(shortcut); } if (role != QAction::NoRole) { action->setMenuRole(role); } if (!actionBefore) { destinationMenu->addAction(action); } else { destinationMenu->insertAction(actionBefore, action); } _actionHash.insert(action->text(), action); return action; } QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, const QString& actionName, const QKeySequence& shortcut, const bool checked, const QObject* receiver, const char* member, int menuItemLocation) { QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, QAction::NoRole, menuItemLocation); action->setCheckable(true); action->setChecked(checked); connect(action, SIGNAL(changed()), this, SLOT(bumpSettings())); return action; }