History

resolve conflicts on merge with upstream master

Stephen Birarda committed 12 years ago

Commit efcf5062 parents 45d796e 72d09a576 files · +5243 −2058Browse files

Showing the changes to interface/src/Menu.cpp (1 of 76 files). Show all

Unified · Split

interface/src/Menu.cpp+135−82
@@ -29,7 +29,6 @@ · 28 unmodified lines
2929 #include <AccountManager.h>
3030 #include <XmppClient.h>
3131 #include <UUID.h>
32−#include <FileDownloader.h>
3332
3433 #include "Application.h"
3534 #include "Menu.h"
@@ -37,7 +36,7 @@ · 1 unmodified line
3736 #include "Util.h"
3837 #include "ui/InfoView.h"
3938 #include "ui/MetavoxelEditor.h"
40−#include "ui/ModelBrowser.h"
39+#include "ui/ModelsBrowser.h"
4140
4241
4342 Menu* Menu::_instance = NULL;
@@ -87,7 +86,7 @@ Menu::Menu() : · 43 unmodified lines
8786 _loginAction(NULL)
8887 {
8988 Application *appInstance = Application::getInstance();
90−
89+
9190 QMenu* fileMenu = addMenu("File");
9291
9392 #ifdef Q_OS_MAC
@@ -100,23 +99,24 @@ Menu::Menu() : · 6 unmodified lines
10099 #endif
101100
102101 AccountManager& accountManager = AccountManager::getInstance();
103−
102+
104103 _loginAction = addActionToQMenuAndActionHash(fileMenu, MenuOption::Logout);
105−
104+
106105 // call our toggle login function now so the menu option is setup properly
107106 toggleLoginMenuItem();
108−
107+
109108 // connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item
110109 connect(&accountManager, &AccountManager::accessTokenChanged, this, &Menu::toggleLoginMenuItem);
111110 connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem);
112111
113112 addDisabledActionAndSeparator(fileMenu, "Scripts");
114113 addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog()));
115− addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
114+ addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
116115 Qt::CTRL | Qt::SHIFT | Qt::Key_O, appInstance, SLOT(loadScriptURLDialog()));
117116 addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, appInstance, SLOT(stopAllScripts()));
118117 addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, 0, appInstance, SLOT(reloadAllScripts()));
119− _activeScriptsMenu = fileMenu->addMenu("Running Scripts");
118+ addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
119+ appInstance, SLOT(toggleRunningScriptsWidget()));
120120
121121 addDisabledActionAndSeparator(fileMenu, "Go");
122122 addActionToQMenuAndActionHash(fileMenu,
@@ -146,8 +146,8 @@ Menu::Menu() : · 23 unmodified lines
146146 SLOT(goTo()));
147147
148148 addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
149− addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadFST, 0, Application::getInstance(), SLOT(uploadFST()));
150−
149+ addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead()));
150+ addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0, Application::getInstance(), SLOT(uploadSkeleton()));
151151 addDisabledActionAndSeparator(fileMenu, "Settings");
152152 addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings()));
153153 addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings()));
@@ -172,26 +172,25 @@ Menu::Menu() : · 18 unmodified lines
172172 addDisabledActionAndSeparator(editMenu, "Physics");
173173 addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false);
174174
175−
176−
175+
176+
177177
178178 addAvatarCollisionSubMenu(editMenu);
179179
180180 QMenu* toolsMenu = addMenu("Tools");
181181 addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor()));
182182
183+#ifdef HAVE_QXMPP
183184 _chatAction = addActionToQMenuAndActionHash(toolsMenu,
184185 MenuOption::Chat,
185186 Qt::Key_Return,
186187 this,
187188 SLOT(showChat()));
188−#ifdef HAVE_QXMPP
189+
189190 const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
190191 toggleChat();
191192 connect(&xmppClient, SIGNAL(connected()), this, SLOT(toggleChat()));
192193 connect(&xmppClient, SIGNAL(disconnected()), this, SLOT(toggleChat()));
193−#else
194− _chatAction->setEnabled(false);
195194 #endif
196195
197196 QMenu* viewMenu = addMenu("View");
@@ -207,7 +206,7 @@ Menu::Menu() : · 9 unmodified lines
207206 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true);
208207 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
209208 appInstance, SLOT(cameraMenuChanged()));
210−
209+
211210 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,
212211 false,
213212 appInstance,
@@ -241,7 +240,7 @@ Menu::Menu() : · 27 unmodified lines
241240 addDisabledActionAndSeparator(viewMenu, "Stats");
242241 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash);
243242 addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
244− addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, true);
243+ addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, false);
245244 addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
246245 addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
247246 addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
@@ -282,8 +281,9 @@ Menu::Menu() : · 34 unmodified lines
282281 QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
283282
284283 addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
285− addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionProxies);
286− addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionProxies);
284+ addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionShapes);
285+ addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes);
286+ addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderBoundingCollisionShapes);
287287
288288 addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false);
289289 addCheckableActionToQMenuAndActionHash(avatarOptionsMenu,
@@ -333,16 +333,16 @@ Menu::Menu() : · 43 unmodified lines
333333 addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings, Qt::CTRL | Qt::SHIFT | Qt::Key_P);
334334 addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::SuppressShortTimings, Qt::CTRL | Qt::SHIFT | Qt::Key_S);
335335
336− addCheckableActionToQMenuAndActionHash(renderDebugMenu,
337− MenuOption::CullSharedFaces,
338− Qt::CTRL | Qt::SHIFT | Qt::Key_C,
336+ addCheckableActionToQMenuAndActionHash(renderDebugMenu,
337+ MenuOption::CullSharedFaces,
338+ Qt::CTRL | Qt::SHIFT | Qt::Key_C,
339339 false,
340340 appInstance->getVoxels(),
341341 SLOT(cullSharedFaces()));
342342
343− addCheckableActionToQMenuAndActionHash(renderDebugMenu,
344− MenuOption::ShowCulledSharedFaces,
345− Qt::CTRL | Qt::SHIFT | Qt::Key_X,
343+ addCheckableActionToQMenuAndActionHash(renderDebugMenu,
344+ MenuOption::ShowCulledSharedFaces,
345+ Qt::CTRL | Qt::SHIFT | Qt::Key_X,
346346 false,
347347 appInstance->getVoxels(),
348348 SLOT(showCulledSharedFaces()));
@@ -360,14 +360,19 @@ Menu::Menu() : · 11 unmodified lines
360360 false,
361361 appInstance->getAudio(),
362362 SLOT(toggleMute()));
363−
363+ addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioToneInjection,
364+ 0,
365+ false,
366+ appInstance->getAudio(),
367+ SLOT(toggleToneInjection()));
368+
364369 addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel,
365370 Qt::CTRL | Qt::SHIFT | Qt::Key_V,
366371 this,
367372 SLOT(pasteToVoxel()));
368373
369374 connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
370−
375+
371376 #ifndef Q_OS_MAC
372377 QMenu* helpMenu = addMenu("Help");
373378 QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp);
@@ -571,7 +576,7 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& · 197 unmodified lines
571576 QAction* separatorText = new QAction(actionName,destinationMenu);
572577 separatorText->setEnabled(false);
573578 destinationMenu->insertAction(actionBefore, separatorText);
574−
579+
575580 } else {
576581 destinationMenu->addSeparator();
577582 (destinationMenu->addAction(actionName))->setEnabled(false);
@@ -623,7 +628,7 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, · 45 unmodified lines
623628 const char* member,
624629 int menuItemLocation) {
625630
626− QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member,
631+ QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member,
627632 QAction::NoRole, menuItemLocation);
628633 action->setCheckable(true);
629634 action->setChecked(checked);
@@ -677,55 +682,55 @@ const float DIALOG_RATIO_OF_WINDOW = 0.30f; · 47 unmodified lines
677682 void Menu::loginForCurrentDomain() {
678683 QDialog loginDialog(Application::getInstance()->getWindow());
679684 loginDialog.setWindowTitle("Login");
680−
685+
681686 QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
682687 loginDialog.setLayout(layout);
683688 loginDialog.setWindowFlags(Qt::Sheet);
684−
689+
685690 QFormLayout* form = new QFormLayout();
686691 layout->addLayout(form, 1);
687−
692+
688693 QLineEdit* loginLineEdit = new QLineEdit();
689694 loginLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
690695 form->addRow("Login:", loginLineEdit);
691−
696+
692697 QLineEdit* passwordLineEdit = new QLineEdit();
693698 passwordLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
694699 passwordLineEdit->setEchoMode(QLineEdit::Password);
695700 form->addRow("Password:", passwordLineEdit);
696−
701+
697702 QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
698703 loginDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
699704 loginDialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
700705 layout->addWidget(buttons);
701−
706+
702707 int dialogReturn = loginDialog.exec();
703−
708+
704709 if (dialogReturn == QDialog::Accepted && !loginLineEdit->text().isEmpty() && !passwordLineEdit->text().isEmpty()) {
705710 // attempt to get an access token given this username and password
706711 AccountManager::getInstance().requestAccessToken(loginLineEdit->text(), passwordLineEdit->text());
707712 }
708−
713+
709714 sendFakeEnterEvent();
710715 }
711716
712717 void Menu::editPreferences() {
713− Application* applicationInstance = Application::getInstance();
714− ModelBrowser headBrowser(Head);
715− ModelBrowser skeletonBrowser(Skeleton);
718+ Application* applicationInstance = Application::getInstance();
719+ ModelsBrowser headBrowser(Head);
720+ ModelsBrowser skeletonBrowser(Skeleton);
716721
717722 const QString BROWSE_BUTTON_TEXT = "Browse";
718723
719724 QDialog dialog(applicationInstance->getWindow());
720725 dialog.setWindowTitle("Interface Preferences");
721−
726+
722727 QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
723728 dialog.setLayout(layout);
724−
729+
725730 QFormLayout* form = new QFormLayout();
726731 layout->addLayout(form, 1);
727732
728−
733+
729734 QHBoxLayout headModelLayout;
730735 QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString();
731736 QLineEdit headURLEdit(faceURLString);
@@ -737,7 +742,7 @@ void Menu::editPreferences() { · 5 unmodified lines
737742 headModelLayout.addWidget(&headURLEdit);
738743 headModelLayout.addWidget(&headBrowseButton);
739744 form->addRow("Head URL:", &headModelLayout);
740−
745+
741746 QHBoxLayout skeletonModelLayout;
742747 QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString();
743748 QLineEdit skeletonURLEdit(skeletonURLString);
@@ -749,7 +754,7 @@ void Menu::editPreferences() { · 5 unmodified lines
749754 skeletonModelLayout.addWidget(&skeletonURLEdit);
750755 skeletonModelLayout.addWidget(&SkeletonBrowseButton);
751756 form->addRow("Skeleton URL:", &skeletonModelLayout);
752−
757+
753758
754759 QString displayNameString = applicationInstance->getAvatar()->getDisplayName();
755760 QLineEdit* displayNameEdit = new QLineEdit(displayNameString);
@@ -813,25 +818,33 @@ void Menu::editPreferences() { · 57 unmodified lines
813818 if (ret == QDialog::Accepted) {
814819 bool shouldDispatchIdentityPacket = false;
815820
816− if (headURLEdit.text() != faceURLString && !headURLEdit.text().isEmpty()) {
821+ if (headURLEdit.text() != faceURLString) {
817822 // change the faceModelURL in the profile, it will also update this user's BlendFace
818− applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.text()));
823+ if (headURLEdit.text().isEmpty()) {
824+ applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.placeholderText()));
825+ } else {
826+ applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.text()));
827+ }
819828 shouldDispatchIdentityPacket = true;
820829 }
821830
822− if (skeletonURLEdit.text() != skeletonURLString && !skeletonURLEdit.text().isEmpty()) {
831+ if (skeletonURLEdit.text() != skeletonURLString) {
823832 // change the skeletonModelURL in the profile, it will also update this user's Body
824− applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.text()));
833+ if (skeletonURLEdit.text().isEmpty()) {
834+ applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.placeholderText()));
835+ } else {
836+ applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.text()));
837+ }
825838 shouldDispatchIdentityPacket = true;
826839 }
827840
828841 QString displayNameStr(displayNameEdit->text());
829−
842+
830843 if (displayNameStr != displayNameString) {
831844 applicationInstance->getAvatar()->setDisplayName(displayNameStr);
832845 shouldDispatchIdentityPacket = true;
833846 }
834−
847+
835848 if (shouldDispatchIdentityPacket) {
836849 applicationInstance->getAvatar()->sendIdentityPacket();
837850 }
@@ -864,10 +877,9 @@ void Menu::editPreferences() { · 26 unmodified lines
864877
865878 void Menu::goToDomain(const QString newDomain) {
866879 if (NodeList::getInstance()->getDomainHandler().getHostname() != newDomain) {
867−
868880 // send a node kill request, indicating to other clients that they should play the "disappeared" effect
869881 Application::getInstance()->getAvatar()->sendKillAvatar();
870−
882+
871883 // give our nodeList the new domain-server hostname
872884 NodeList::getInstance()->getDomainHandler().setHostname(newDomain);
873885 }
@@ -897,7 +909,7 @@ void Menu::goToDomainDialog() { · 23 unmodified lines
897909 // the user input a new hostname, use that
898910 newHostname = domainDialog.textValue();
899911 }
900−
912+
901913 goToDomain(newHostname);
902914 }
903915
@@ -912,19 +924,58 @@ bool Menu::goToDestination(QString destination) { · 8 unmodified lines
912924 return LocationManager::getInstance().goToDestination(destination);
913925 }
914926
927+void Menu::goTo(QString destination) {
928+ LocationManager::getInstance().goTo(destination);
929+}
930+
915931 void Menu::goTo() {
916−
932+
917933 QInputDialog gotoDialog(Application::getInstance()->getWindow());
918934 gotoDialog.setWindowTitle("Go to");
919− gotoDialog.setLabelText("Destination:");
935+ gotoDialog.setLabelText("Destination or URL:\n @user, #place, hifi://domain/location/orientation");
920936 QString destination = QString();
937+
921938 gotoDialog.setTextValue(destination);
922939 gotoDialog.setWindowFlags(Qt::Sheet);
923940 gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height());
924−
941+
925942 int dialogReturn = gotoDialog.exec();
926943 if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
927− goToUser(gotoDialog.textValue());
944+ QString desiredDestination = gotoDialog.textValue();
945+
946+ if (desiredDestination.startsWith(CUSTOM_URL_SCHEME + "//")) {
947+ QStringList urlParts = desiredDestination.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts);
948+
949+ if (urlParts.count() > 1) {
950+ // if url has 2 or more parts, the first one is domain name
951+ QString domain = urlParts[0];
952+
953+ // second part is either a destination coordinate or
954+ // a place name
955+ QString destination = urlParts[1];
956+
957+ // any third part is an avatar orientation.
958+ QString orientation = urlParts.count() > 2 ? urlParts[2] : QString();
959+
960+ goToDomain(domain);
961+
962+ // goto either @user, #place, or x-xx,y-yy,z-zz
963+ // style co-ordinate.
964+ goTo(destination);
965+
966+ if (!orientation.isEmpty()) {
967+ // location orientation
968+ goToOrientation(orientation);
969+ }
970+ } else if (urlParts.count() == 1) {
971+ // location coordinates or place name
972+ QString destination = urlParts[0];
973+ goTo(destination);
974+ }
975+
976+ } else {
977+ goToUser(gotoDialog.textValue());
978+ }
928979 }
929980 sendFakeEnterEvent();
930981 }
@@ -1070,7 +1121,7 @@ void Menu::toggleLoginMenuItem() { · 139 unmodified lines
10701121 AccountManager& accountManager = AccountManager::getInstance();
10711122
10721123 disconnect(_loginAction, 0, 0, 0);
1073−
1124+
10741125 if (accountManager.isLoggedIn()) {
10751126 // change the menu item to logout
10761127 _loginAction->setText("Logout " + accountManager.getUsername());
@@ -1078,7 +1129,7 @@ void Menu::toggleLoginMenuItem() { · 1 unmodified line
10781129 } else {
10791130 // change the menu item to login
10801131 _loginAction->setText("Login");
1081−
1132+
10821133 connect(_loginAction, &QAction::triggered, this, &Menu::loginForCurrentDomain);
10831134 }
10841135 }
@@ -1180,7 +1231,7 @@ QString Menu::getLODFeedbackText() { · 95 unmodified lines
11801231 } break;
11811232 }
11821233
1183− // distance feedback
1234+ // distance feedback
11841235 float voxelSizeScale = getVoxelSizeScale();
11851236 float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
11861237 QString result;
@@ -1195,7 +1246,7 @@ QString Menu::getLODFeedbackText() { · 8 unmodified lines
11951246 }
11961247
11971248 void Menu::autoAdjustLOD(float currentFPS) {
1198− // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
1249+ // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
11991250 // really want to count them in our average, so we will ignore the real frame rates and stuff
12001251 // our moving average with simulated good data
12011252 const int IGNORE_THESE_SAMPLES = 100;
@@ -1207,30 +1258,32 @@ void Menu::autoAdjustLOD(float currentFPS) { · 5 unmodified lines
12071258 _fastFPSAverage.updateAverage(currentFPS);
12081259
12091260 quint64 now = usecTimestampNow();
1210−
1261+
1262+ const float ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
12111263 const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000;
1212− if (_fastFPSAverage.getAverage() < ADJUST_LOD_DOWN_FPS) {
1264+ if (_fastFPSAverage.getAverage() < ADJUST_AVATAR_LOD_DOWN_FPS) {
12131265 if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) {
12141266 // attempt to lower the detail in proportion to the fps difference
1215− float targetFps = (ADJUST_LOD_DOWN_FPS + ADJUST_LOD_UP_FPS) * 0.5f;
1267+ float targetFps = (ADJUST_AVATAR_LOD_DOWN_FPS + ADJUST_LOD_UP_FPS) * 0.5f;
12161268 float averageFps = _fastFPSAverage.getAverage();
12171269 const float MAXIMUM_MULTIPLIER_SCALE = 2.0f;
1218− _avatarLODDistanceMultiplier *= (averageFps < EPSILON) ? MAXIMUM_MULTIPLIER_SCALE :
1219− qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps);
1270+ const float MAXIMUM_DISTANCE_MULTIPLIER = 15.0f;
1271+ _avatarLODDistanceMultiplier = qMin(MAXIMUM_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier *
1272+ (averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE : qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps)));
12201273 _lastAvatarDetailDrop = now;
12211274 }
12221275 } else if (_fastFPSAverage.getAverage() > ADJUST_LOD_UP_FPS) {
12231276 // let the detail level creep slowly upwards
1224− const float DISTANCE_DECREASE_RATE = 0.02f;
1277+ const float DISTANCE_DECREASE_RATE = 0.05f;
12251278 const float MINIMUM_DISTANCE_MULTIPLIER = 0.1f;
12261279 _avatarLODDistanceMultiplier = qMax(MINIMUM_DISTANCE_MULTIPLIER,
12271280 _avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE);
12281281 }
1229−
1282+
12301283 bool changed = false;
12311284 quint64 elapsed = now - _lastAdjust;
12321285
1233− if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
1286+ if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
12341287 && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
12351288
12361289 _voxelSizeScale *= ADJUST_LOD_DOWN_BY;
@@ -1243,7 +1296,7 @@ void Menu::autoAdjustLOD(float currentFPS) { · 6 unmodified lines
12431296 << "_voxelSizeScale=" << _voxelSizeScale;
12441297 }
12451298
1246− if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
1299+ if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
12471300 && _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
12481301 _voxelSizeScale *= ADJUST_LOD_UP_BY;
12491302 if (_voxelSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
@@ -1254,7 +1307,7 @@ void Menu::autoAdjustLOD(float currentFPS) { · 4 unmodified lines
12541307 qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
12551308 << "_voxelSizeScale=" << _voxelSizeScale;
12561309 }
1257−
1310+
12581311 if (changed) {
12591312 if (_lodToolsDialog) {
12601313 _lodToolsDialog->reloadSliders();
@@ -1332,13 +1385,13 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { · 71 unmodified lines
13321385
13331386 Application* appInstance = Application::getInstance();
13341387 QObject* avatar = appInstance->getAvatar();
1335− addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment,
1388+ addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment,
13361389 0, false, avatar, SLOT(updateCollisionFlags()));
1337− addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars,
1390+ addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars,
13381391 0, true, avatar, SLOT(updateCollisionFlags()));
1339− addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels,
1392+ addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels,
13401393 0, false, avatar, SLOT(updateCollisionFlags()));
1341− addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles,
1394+ addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles,
13421395 0, true, avatar, SLOT(updateCollisionFlags()));
13431396 }
13441397
@@ -1347,9 +1400,9 @@ QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { · 2 unmodified lines
13471400 if (menu) {
13481401 menuActions = menu->actions();
13491402 } else {
1350− menuActions = actions();
1403+ menuActions = actions();
13511404 }
1352−
1405+
13531406 foreach (QAction* menuAction, menuActions) {
13541407 if (menuName == menuAction->text()) {
13551408 return menuAction;
@@ -1456,7 +1509,7 @@ QMenu* Menu::addMenu(const QString& menuName) { · 100 unmodified lines
14561509
14571510 void Menu::removeMenu(const QString& menuName) {
14581511 QAction* action = getMenuAction(menuName);
1459−
1512+
14601513 // only proceed if the menu actually exists
14611514 if (action) {
14621515 QString finalMenuPart;
@@ -1508,7 +1561,7 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 45 unmodified lines
15081561 if (!properties.shortcutKeySequence.isEmpty()) {
15091562 shortcut = new QShortcut(properties.shortcutKeySequence, this);
15101563 }
1511−
1564+
15121565 // check for positioning requests
15131566 int requestedPosition = properties.position;
15141567 if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) {
@@ -1522,13 +1575,13 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 7 unmodified lines
15221575 requestedPosition = afterPosition + 1;
15231576 }
15241577 }
1525−
1578+
15261579 QAction* menuItemAction = NULL;
15271580 if (properties.isSeparator) {
15281581 addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);
15291582 } else if (properties.isCheckable) {
15301583 menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
1531− properties.shortcutKeySequence, properties.isChecked,
1584+ properties.shortcutKeySequence, properties.isChecked,
15321585 MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);
15331586 } else {
15341587 menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,