Showing the changes to interface/src/Menu.cpp (1 of 76 files). Show all
Unified · Split
| @@ -29,7 +29,6 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <AccountManager.h> |
| 30 | 30 | #include <XmppClient.h> |
| 31 | 31 | #include <UUID.h> |
| 32 | −#include <FileDownloader.h> | |
| 33 | 32 | |
| 34 | 33 | #include "Application.h" |
| 35 | 34 | #include "Menu.h" |
| @@ -37,7 +36,7 @@ · 1 unmodified line | ||
| 37 | 36 | #include "Util.h" |
| 38 | 37 | #include "ui/InfoView.h" |
| 39 | 38 | #include "ui/MetavoxelEditor.h" |
| 40 | −#include "ui/ModelBrowser.h" | |
| 39 | +#include "ui/ModelsBrowser.h" | |
| 41 | 40 | |
| 42 | 41 | |
| 43 | 42 | Menu* Menu::_instance = NULL; |
| @@ -87,7 +86,7 @@ Menu::Menu() : · 43 unmodified lines | ||
| 87 | 86 | _loginAction(NULL) |
| 88 | 87 | { |
| 89 | 88 | Application *appInstance = Application::getInstance(); |
| 90 | − | |
| 89 | + | |
| 91 | 90 | QMenu* fileMenu = addMenu("File"); |
| 92 | 91 | |
| 93 | 92 | #ifdef Q_OS_MAC |
| @@ -100,23 +99,24 @@ Menu::Menu() : · 6 unmodified lines | ||
| 100 | 99 | #endif |
| 101 | 100 | |
| 102 | 101 | AccountManager& accountManager = AccountManager::getInstance(); |
| 103 | − | |
| 102 | + | |
| 104 | 103 | _loginAction = addActionToQMenuAndActionHash(fileMenu, MenuOption::Logout); |
| 105 | − | |
| 104 | + | |
| 106 | 105 | // call our toggle login function now so the menu option is setup properly |
| 107 | 106 | toggleLoginMenuItem(); |
| 108 | − | |
| 107 | + | |
| 109 | 108 | // connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item |
| 110 | 109 | connect(&accountManager, &AccountManager::accessTokenChanged, this, &Menu::toggleLoginMenuItem); |
| 111 | 110 | connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem); |
| 112 | 111 | |
| 113 | 112 | addDisabledActionAndSeparator(fileMenu, "Scripts"); |
| 114 | 113 | addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog())); |
| 115 | − addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL, | |
| 114 | + addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL, | |
| 116 | 115 | Qt::CTRL | Qt::SHIFT | Qt::Key_O, appInstance, SLOT(loadScriptURLDialog())); |
| 117 | 116 | addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, appInstance, SLOT(stopAllScripts())); |
| 118 | 117 | 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())); | |
| 120 | 120 | |
| 121 | 121 | addDisabledActionAndSeparator(fileMenu, "Go"); |
| 122 | 122 | addActionToQMenuAndActionHash(fileMenu, |
| @@ -146,8 +146,8 @@ Menu::Menu() : · 23 unmodified lines | ||
| 146 | 146 | SLOT(goTo())); |
| 147 | 147 | |
| 148 | 148 | 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())); | |
| 151 | 151 | addDisabledActionAndSeparator(fileMenu, "Settings"); |
| 152 | 152 | addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings())); |
| 153 | 153 | addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings())); |
| @@ -172,26 +172,25 @@ Menu::Menu() : · 18 unmodified lines | ||
| 172 | 172 | addDisabledActionAndSeparator(editMenu, "Physics"); |
| 173 | 173 | addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false); |
| 174 | 174 | |
| 175 | − | |
| 176 | − | |
| 175 | + | |
| 176 | + | |
| 177 | 177 | |
| 178 | 178 | addAvatarCollisionSubMenu(editMenu); |
| 179 | 179 | |
| 180 | 180 | QMenu* toolsMenu = addMenu("Tools"); |
| 181 | 181 | addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor())); |
| 182 | 182 | |
| 183 | +#ifdef HAVE_QXMPP | |
| 183 | 184 | _chatAction = addActionToQMenuAndActionHash(toolsMenu, |
| 184 | 185 | MenuOption::Chat, |
| 185 | 186 | Qt::Key_Return, |
| 186 | 187 | this, |
| 187 | 188 | SLOT(showChat())); |
| 188 | −#ifdef HAVE_QXMPP | |
| 189 | + | |
| 189 | 190 | const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); |
| 190 | 191 | toggleChat(); |
| 191 | 192 | connect(&xmppClient, SIGNAL(connected()), this, SLOT(toggleChat())); |
| 192 | 193 | connect(&xmppClient, SIGNAL(disconnected()), this, SLOT(toggleChat())); |
| 193 | −#else | |
| 194 | − _chatAction->setEnabled(false); | |
| 195 | 194 | #endif |
| 196 | 195 | |
| 197 | 196 | QMenu* viewMenu = addMenu("View"); |
| @@ -207,7 +206,7 @@ Menu::Menu() : · 9 unmodified lines | ||
| 207 | 206 | addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true); |
| 208 | 207 | addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false, |
| 209 | 208 | appInstance, SLOT(cameraMenuChanged())); |
| 210 | − | |
| 209 | + | |
| 211 | 210 | addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0, |
| 212 | 211 | false, |
| 213 | 212 | appInstance, |
| @@ -241,7 +240,7 @@ Menu::Menu() : · 27 unmodified lines | ||
| 241 | 240 | addDisabledActionAndSeparator(viewMenu, "Stats"); |
| 242 | 241 | addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); |
| 243 | 242 | 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); | |
| 245 | 244 | addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true); |
| 246 | 245 | addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails())); |
| 247 | 246 | addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails())); |
| @@ -282,8 +281,9 @@ Menu::Menu() : · 34 unmodified lines | ||
| 282 | 281 | QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); |
| 283 | 282 | |
| 284 | 283 | 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); | |
| 287 | 287 | |
| 288 | 288 | addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false); |
| 289 | 289 | addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, |
| @@ -333,16 +333,16 @@ Menu::Menu() : · 43 unmodified lines | ||
| 333 | 333 | addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings, Qt::CTRL | Qt::SHIFT | Qt::Key_P); |
| 334 | 334 | addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::SuppressShortTimings, Qt::CTRL | Qt::SHIFT | Qt::Key_S); |
| 335 | 335 | |
| 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, | |
| 339 | 339 | false, |
| 340 | 340 | appInstance->getVoxels(), |
| 341 | 341 | SLOT(cullSharedFaces())); |
| 342 | 342 | |
| 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, | |
| 346 | 346 | false, |
| 347 | 347 | appInstance->getVoxels(), |
| 348 | 348 | SLOT(showCulledSharedFaces())); |
| @@ -360,14 +360,19 @@ Menu::Menu() : · 11 unmodified lines | ||
| 360 | 360 | false, |
| 361 | 361 | appInstance->getAudio(), |
| 362 | 362 | SLOT(toggleMute())); |
| 363 | − | |
| 363 | + addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioToneInjection, | |
| 364 | + 0, | |
| 365 | + false, | |
| 366 | + appInstance->getAudio(), | |
| 367 | + SLOT(toggleToneInjection())); | |
| 368 | + | |
| 364 | 369 | addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, |
| 365 | 370 | Qt::CTRL | Qt::SHIFT | Qt::Key_V, |
| 366 | 371 | this, |
| 367 | 372 | SLOT(pasteToVoxel())); |
| 368 | 373 | |
| 369 | 374 | connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); |
| 370 | − | |
| 375 | + | |
| 371 | 376 | #ifndef Q_OS_MAC |
| 372 | 377 | QMenu* helpMenu = addMenu("Help"); |
| 373 | 378 | QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp); |
| @@ -571,7 +576,7 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& · 197 unmodified lines | ||
| 571 | 576 | QAction* separatorText = new QAction(actionName,destinationMenu); |
| 572 | 577 | separatorText->setEnabled(false); |
| 573 | 578 | destinationMenu->insertAction(actionBefore, separatorText); |
| 574 | − | |
| 579 | + | |
| 575 | 580 | } else { |
| 576 | 581 | destinationMenu->addSeparator(); |
| 577 | 582 | (destinationMenu->addAction(actionName))->setEnabled(false); |
| @@ -623,7 +628,7 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu, · 45 unmodified lines | ||
| 623 | 628 | const char* member, |
| 624 | 629 | int menuItemLocation) { |
| 625 | 630 | |
| 626 | − QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, | |
| 631 | + QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, | |
| 627 | 632 | QAction::NoRole, menuItemLocation); |
| 628 | 633 | action->setCheckable(true); |
| 629 | 634 | action->setChecked(checked); |
| @@ -677,55 +682,55 @@ const float DIALOG_RATIO_OF_WINDOW = 0.30f; · 47 unmodified lines | ||
| 677 | 682 | void Menu::loginForCurrentDomain() { |
| 678 | 683 | QDialog loginDialog(Application::getInstance()->getWindow()); |
| 679 | 684 | loginDialog.setWindowTitle("Login"); |
| 680 | − | |
| 685 | + | |
| 681 | 686 | QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); |
| 682 | 687 | loginDialog.setLayout(layout); |
| 683 | 688 | loginDialog.setWindowFlags(Qt::Sheet); |
| 684 | − | |
| 689 | + | |
| 685 | 690 | QFormLayout* form = new QFormLayout(); |
| 686 | 691 | layout->addLayout(form, 1); |
| 687 | − | |
| 692 | + | |
| 688 | 693 | QLineEdit* loginLineEdit = new QLineEdit(); |
| 689 | 694 | loginLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); |
| 690 | 695 | form->addRow("Login:", loginLineEdit); |
| 691 | − | |
| 696 | + | |
| 692 | 697 | QLineEdit* passwordLineEdit = new QLineEdit(); |
| 693 | 698 | passwordLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); |
| 694 | 699 | passwordLineEdit->setEchoMode(QLineEdit::Password); |
| 695 | 700 | form->addRow("Password:", passwordLineEdit); |
| 696 | − | |
| 701 | + | |
| 697 | 702 | QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); |
| 698 | 703 | loginDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); |
| 699 | 704 | loginDialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); |
| 700 | 705 | layout->addWidget(buttons); |
| 701 | − | |
| 706 | + | |
| 702 | 707 | int dialogReturn = loginDialog.exec(); |
| 703 | − | |
| 708 | + | |
| 704 | 709 | if (dialogReturn == QDialog::Accepted && !loginLineEdit->text().isEmpty() && !passwordLineEdit->text().isEmpty()) { |
| 705 | 710 | // attempt to get an access token given this username and password |
| 706 | 711 | AccountManager::getInstance().requestAccessToken(loginLineEdit->text(), passwordLineEdit->text()); |
| 707 | 712 | } |
| 708 | − | |
| 713 | + | |
| 709 | 714 | sendFakeEnterEvent(); |
| 710 | 715 | } |
| 711 | 716 | |
| 712 | 717 | 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); | |
| 716 | 721 | |
| 717 | 722 | const QString BROWSE_BUTTON_TEXT = "Browse"; |
| 718 | 723 | |
| 719 | 724 | QDialog dialog(applicationInstance->getWindow()); |
| 720 | 725 | dialog.setWindowTitle("Interface Preferences"); |
| 721 | − | |
| 726 | + | |
| 722 | 727 | QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); |
| 723 | 728 | dialog.setLayout(layout); |
| 724 | − | |
| 729 | + | |
| 725 | 730 | QFormLayout* form = new QFormLayout(); |
| 726 | 731 | layout->addLayout(form, 1); |
| 727 | 732 | |
| 728 | − | |
| 733 | + | |
| 729 | 734 | QHBoxLayout headModelLayout; |
| 730 | 735 | QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString(); |
| 731 | 736 | QLineEdit headURLEdit(faceURLString); |
| @@ -737,7 +742,7 @@ void Menu::editPreferences() { · 5 unmodified lines | ||
| 737 | 742 | headModelLayout.addWidget(&headURLEdit); |
| 738 | 743 | headModelLayout.addWidget(&headBrowseButton); |
| 739 | 744 | form->addRow("Head URL:", &headModelLayout); |
| 740 | − | |
| 745 | + | |
| 741 | 746 | QHBoxLayout skeletonModelLayout; |
| 742 | 747 | QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString(); |
| 743 | 748 | QLineEdit skeletonURLEdit(skeletonURLString); |
| @@ -749,7 +754,7 @@ void Menu::editPreferences() { · 5 unmodified lines | ||
| 749 | 754 | skeletonModelLayout.addWidget(&skeletonURLEdit); |
| 750 | 755 | skeletonModelLayout.addWidget(&SkeletonBrowseButton); |
| 751 | 756 | form->addRow("Skeleton URL:", &skeletonModelLayout); |
| 752 | − | |
| 757 | + | |
| 753 | 758 | |
| 754 | 759 | QString displayNameString = applicationInstance->getAvatar()->getDisplayName(); |
| 755 | 760 | QLineEdit* displayNameEdit = new QLineEdit(displayNameString); |
| @@ -813,25 +818,33 @@ void Menu::editPreferences() { · 57 unmodified lines | ||
| 813 | 818 | if (ret == QDialog::Accepted) { |
| 814 | 819 | bool shouldDispatchIdentityPacket = false; |
| 815 | 820 | |
| 816 | − if (headURLEdit.text() != faceURLString && !headURLEdit.text().isEmpty()) { | |
| 821 | + if (headURLEdit.text() != faceURLString) { | |
| 817 | 822 | // 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 | + } | |
| 819 | 828 | shouldDispatchIdentityPacket = true; |
| 820 | 829 | } |
| 821 | 830 | |
| 822 | − if (skeletonURLEdit.text() != skeletonURLString && !skeletonURLEdit.text().isEmpty()) { | |
| 831 | + if (skeletonURLEdit.text() != skeletonURLString) { | |
| 823 | 832 | // 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 | + } | |
| 825 | 838 | shouldDispatchIdentityPacket = true; |
| 826 | 839 | } |
| 827 | 840 | |
| 828 | 841 | QString displayNameStr(displayNameEdit->text()); |
| 829 | − | |
| 842 | + | |
| 830 | 843 | if (displayNameStr != displayNameString) { |
| 831 | 844 | applicationInstance->getAvatar()->setDisplayName(displayNameStr); |
| 832 | 845 | shouldDispatchIdentityPacket = true; |
| 833 | 846 | } |
| 834 | − | |
| 847 | + | |
| 835 | 848 | if (shouldDispatchIdentityPacket) { |
| 836 | 849 | applicationInstance->getAvatar()->sendIdentityPacket(); |
| 837 | 850 | } |
| @@ -864,10 +877,9 @@ void Menu::editPreferences() { · 26 unmodified lines | ||
| 864 | 877 | |
| 865 | 878 | void Menu::goToDomain(const QString newDomain) { |
| 866 | 879 | if (NodeList::getInstance()->getDomainHandler().getHostname() != newDomain) { |
| 867 | − | |
| 868 | 880 | // send a node kill request, indicating to other clients that they should play the "disappeared" effect |
| 869 | 881 | Application::getInstance()->getAvatar()->sendKillAvatar(); |
| 870 | − | |
| 882 | + | |
| 871 | 883 | // give our nodeList the new domain-server hostname |
| 872 | 884 | NodeList::getInstance()->getDomainHandler().setHostname(newDomain); |
| 873 | 885 | } |
| @@ -897,7 +909,7 @@ void Menu::goToDomainDialog() { · 23 unmodified lines | ||
| 897 | 909 | // the user input a new hostname, use that |
| 898 | 910 | newHostname = domainDialog.textValue(); |
| 899 | 911 | } |
| 900 | − | |
| 912 | + | |
| 901 | 913 | goToDomain(newHostname); |
| 902 | 914 | } |
| 903 | 915 | |
| @@ -912,19 +924,58 @@ bool Menu::goToDestination(QString destination) { · 8 unmodified lines | ||
| 912 | 924 | return LocationManager::getInstance().goToDestination(destination); |
| 913 | 925 | } |
| 914 | 926 | |
| 927 | +void Menu::goTo(QString destination) { | |
| 928 | + LocationManager::getInstance().goTo(destination); | |
| 929 | +} | |
| 930 | + | |
| 915 | 931 | void Menu::goTo() { |
| 916 | − | |
| 932 | + | |
| 917 | 933 | QInputDialog gotoDialog(Application::getInstance()->getWindow()); |
| 918 | 934 | gotoDialog.setWindowTitle("Go to"); |
| 919 | − gotoDialog.setLabelText("Destination:"); | |
| 935 | + gotoDialog.setLabelText("Destination or URL:\n @user, #place, hifi://domain/location/orientation"); | |
| 920 | 936 | QString destination = QString(); |
| 937 | + | |
| 921 | 938 | gotoDialog.setTextValue(destination); |
| 922 | 939 | gotoDialog.setWindowFlags(Qt::Sheet); |
| 923 | 940 | gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height()); |
| 924 | − | |
| 941 | + | |
| 925 | 942 | int dialogReturn = gotoDialog.exec(); |
| 926 | 943 | 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 | + } | |
| 928 | 979 | } |
| 929 | 980 | sendFakeEnterEvent(); |
| 930 | 981 | } |
| @@ -1070,7 +1121,7 @@ void Menu::toggleLoginMenuItem() { · 139 unmodified lines | ||
| 1070 | 1121 | AccountManager& accountManager = AccountManager::getInstance(); |
| 1071 | 1122 | |
| 1072 | 1123 | disconnect(_loginAction, 0, 0, 0); |
| 1073 | − | |
| 1124 | + | |
| 1074 | 1125 | if (accountManager.isLoggedIn()) { |
| 1075 | 1126 | // change the menu item to logout |
| 1076 | 1127 | _loginAction->setText("Logout " + accountManager.getUsername()); |
| @@ -1078,7 +1129,7 @@ void Menu::toggleLoginMenuItem() { · 1 unmodified line | ||
| 1078 | 1129 | } else { |
| 1079 | 1130 | // change the menu item to login |
| 1080 | 1131 | _loginAction->setText("Login"); |
| 1081 | − | |
| 1132 | + | |
| 1082 | 1133 | connect(_loginAction, &QAction::triggered, this, &Menu::loginForCurrentDomain); |
| 1083 | 1134 | } |
| 1084 | 1135 | } |
| @@ -1180,7 +1231,7 @@ QString Menu::getLODFeedbackText() { · 95 unmodified lines | ||
| 1180 | 1231 | } break; |
| 1181 | 1232 | } |
| 1182 | 1233 | |
| 1183 | − // distance feedback | |
| 1234 | + // distance feedback | |
| 1184 | 1235 | float voxelSizeScale = getVoxelSizeScale(); |
| 1185 | 1236 | float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE; |
| 1186 | 1237 | QString result; |
| @@ -1195,7 +1246,7 @@ QString Menu::getLODFeedbackText() { · 8 unmodified lines | ||
| 1195 | 1246 | } |
| 1196 | 1247 | |
| 1197 | 1248 | 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 | |
| 1199 | 1250 | // really want to count them in our average, so we will ignore the real frame rates and stuff |
| 1200 | 1251 | // our moving average with simulated good data |
| 1201 | 1252 | const int IGNORE_THESE_SAMPLES = 100; |
| @@ -1207,30 +1258,32 @@ void Menu::autoAdjustLOD(float currentFPS) { · 5 unmodified lines | ||
| 1207 | 1258 | _fastFPSAverage.updateAverage(currentFPS); |
| 1208 | 1259 | |
| 1209 | 1260 | quint64 now = usecTimestampNow(); |
| 1210 | − | |
| 1261 | + | |
| 1262 | + const float ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f; | |
| 1211 | 1263 | 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) { | |
| 1213 | 1265 | if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) { |
| 1214 | 1266 | // 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; | |
| 1216 | 1268 | float averageFps = _fastFPSAverage.getAverage(); |
| 1217 | 1269 | 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))); | |
| 1220 | 1273 | _lastAvatarDetailDrop = now; |
| 1221 | 1274 | } |
| 1222 | 1275 | } else if (_fastFPSAverage.getAverage() > ADJUST_LOD_UP_FPS) { |
| 1223 | 1276 | // let the detail level creep slowly upwards |
| 1224 | − const float DISTANCE_DECREASE_RATE = 0.02f; | |
| 1277 | + const float DISTANCE_DECREASE_RATE = 0.05f; | |
| 1225 | 1278 | const float MINIMUM_DISTANCE_MULTIPLIER = 0.1f; |
| 1226 | 1279 | _avatarLODDistanceMultiplier = qMax(MINIMUM_DISTANCE_MULTIPLIER, |
| 1227 | 1280 | _avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE); |
| 1228 | 1281 | } |
| 1229 | − | |
| 1282 | + | |
| 1230 | 1283 | bool changed = false; |
| 1231 | 1284 | quint64 elapsed = now - _lastAdjust; |
| 1232 | 1285 | |
| 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 | |
| 1234 | 1287 | && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { |
| 1235 | 1288 | |
| 1236 | 1289 | _voxelSizeScale *= ADJUST_LOD_DOWN_BY; |
| @@ -1243,7 +1296,7 @@ void Menu::autoAdjustLOD(float currentFPS) { · 6 unmodified lines | ||
| 1243 | 1296 | << "_voxelSizeScale=" << _voxelSizeScale; |
| 1244 | 1297 | } |
| 1245 | 1298 | |
| 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 | |
| 1247 | 1300 | && _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { |
| 1248 | 1301 | _voxelSizeScale *= ADJUST_LOD_UP_BY; |
| 1249 | 1302 | if (_voxelSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { |
| @@ -1254,7 +1307,7 @@ void Menu::autoAdjustLOD(float currentFPS) { · 4 unmodified lines | ||
| 1254 | 1307 | qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() |
| 1255 | 1308 | << "_voxelSizeScale=" << _voxelSizeScale; |
| 1256 | 1309 | } |
| 1257 | − | |
| 1310 | + | |
| 1258 | 1311 | if (changed) { |
| 1259 | 1312 | if (_lodToolsDialog) { |
| 1260 | 1313 | _lodToolsDialog->reloadSliders(); |
| @@ -1332,13 +1385,13 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { · 71 unmodified lines | ||
| 1332 | 1385 | |
| 1333 | 1386 | Application* appInstance = Application::getInstance(); |
| 1334 | 1387 | QObject* avatar = appInstance->getAvatar(); |
| 1335 | − addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment, | |
| 1388 | + addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment, | |
| 1336 | 1389 | 0, false, avatar, SLOT(updateCollisionFlags())); |
| 1337 | − addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars, | |
| 1390 | + addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars, | |
| 1338 | 1391 | 0, true, avatar, SLOT(updateCollisionFlags())); |
| 1339 | − addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels, | |
| 1392 | + addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels, | |
| 1340 | 1393 | 0, false, avatar, SLOT(updateCollisionFlags())); |
| 1341 | − addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles, | |
| 1394 | + addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles, | |
| 1342 | 1395 | 0, true, avatar, SLOT(updateCollisionFlags())); |
| 1343 | 1396 | } |
| 1344 | 1397 | |
| @@ -1347,9 +1400,9 @@ QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { · 2 unmodified lines | ||
| 1347 | 1400 | if (menu) { |
| 1348 | 1401 | menuActions = menu->actions(); |
| 1349 | 1402 | } else { |
| 1350 | − menuActions = actions(); | |
| 1403 | + menuActions = actions(); | |
| 1351 | 1404 | } |
| 1352 | − | |
| 1405 | + | |
| 1353 | 1406 | foreach (QAction* menuAction, menuActions) { |
| 1354 | 1407 | if (menuName == menuAction->text()) { |
| 1355 | 1408 | return menuAction; |
| @@ -1456,7 +1509,7 @@ QMenu* Menu::addMenu(const QString& menuName) { · 100 unmodified lines | ||
| 1456 | 1509 | |
| 1457 | 1510 | void Menu::removeMenu(const QString& menuName) { |
| 1458 | 1511 | QAction* action = getMenuAction(menuName); |
| 1459 | − | |
| 1512 | + | |
| 1460 | 1513 | // only proceed if the menu actually exists |
| 1461 | 1514 | if (action) { |
| 1462 | 1515 | QString finalMenuPart; |
| @@ -1508,7 +1561,7 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 45 unmodified lines | ||
| 1508 | 1561 | if (!properties.shortcutKeySequence.isEmpty()) { |
| 1509 | 1562 | shortcut = new QShortcut(properties.shortcutKeySequence, this); |
| 1510 | 1563 | } |
| 1511 | − | |
| 1564 | + | |
| 1512 | 1565 | // check for positioning requests |
| 1513 | 1566 | int requestedPosition = properties.position; |
| 1514 | 1567 | if (requestedPosition == UNSPECIFIED_POSITION && !properties.beforeItem.isEmpty()) { |
| @@ -1522,13 +1575,13 @@ void Menu::addMenuItem(const MenuItemProperties& properties) { · 7 unmodified lines | ||
| 1522 | 1575 | requestedPosition = afterPosition + 1; |
| 1523 | 1576 | } |
| 1524 | 1577 | } |
| 1525 | − | |
| 1578 | + | |
| 1526 | 1579 | QAction* menuItemAction = NULL; |
| 1527 | 1580 | if (properties.isSeparator) { |
| 1528 | 1581 | addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition); |
| 1529 | 1582 | } else if (properties.isCheckable) { |
| 1530 | 1583 | menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName, |
| 1531 | − properties.shortcutKeySequence, properties.isChecked, | |
| 1584 | + properties.shortcutKeySequence, properties.isChecked, | |
| 1532 | 1585 | MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition); |
| 1533 | 1586 | } else { |
| 1534 | 1587 | menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence, |