From c1d40fd78158a8eb82ae66beb885b6355cacb2d1 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 22 Mar 2017 16:25:45 +0000 Subject: [PATCH 01/39] add file placeholder --- scripts/system/avatarBookmarks.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/system/avatarBookmarks.js diff --git a/scripts/system/avatarBookmarks.js b/scripts/system/avatarBookmarks.js new file mode 100644 index 0000000000..e69de29bb2 From bda1d542095bf8b760a921faf1d793ba6fedeb84 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Fri, 24 Mar 2017 22:58:36 +0000 Subject: [PATCH 02/39] create AvatarBookmarks derive AvatarBookMarks and LocationBookmarks from Bookmarks, first pass at integration, QML issues noted --- .../dialogs/preferences/AvatarPreference.qml | 34 +++- interface/src/Application.cpp | 3 +- interface/src/Application.h | 9 +- interface/src/AvatarBookmarks.cpp | 116 +++++++++++++ interface/src/AvatarBookmarks.h | 38 ++++ interface/src/Bookmarks.cpp | 163 +++++------------- interface/src/Bookmarks.h | 22 +-- interface/src/LocationBookmarks.cpp | 108 ++++++++++++ interface/src/LocationBookmarks.h | 40 +++++ interface/src/Menu.cpp | 6 +- interface/src/Menu.h | 5 +- interface/src/ui/AddressBarDialog.cpp | 2 +- scripts/system/avatarBookmarks.js | 0 13 files changed, 392 insertions(+), 154 deletions(-) create mode 100644 interface/src/AvatarBookmarks.cpp create mode 100644 interface/src/AvatarBookmarks.h create mode 100644 interface/src/LocationBookmarks.cpp create mode 100644 interface/src/LocationBookmarks.h delete mode 100644 scripts/system/avatarBookmarks.js diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 0c5c5bf630..e3db8364f2 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -15,8 +15,9 @@ import "../../controls-uit" Preference { id: root + objectName: "avatarPreferencesRoot" + signal bookmarkAvatarSignal() property alias text: dataTextField.text - property alias buttonText: button.text property alias placeholderText: dataTextField.placeholderText property var browser; height: control.height + hifi.dimensions.controlInterlineHeight @@ -58,7 +59,7 @@ Preference { right: parent.right bottom: parent.bottom } - height: Math.max(dataTextField.controlHeight, button.height) + height: dataTextField.controlHeight + bookmarkAvatarButton.height + hifi.dimensions.contentSpacing.y TextField { id: dataTextField @@ -67,19 +68,33 @@ Preference { label: root.label anchors { left: parent.left - right: button.left - rightMargin: hifi.dimensions.contentSpacing.x - bottom: parent.bottom + right: parent.right + bottom: bookmarkAvatarButton.top + bottomMargin: hifi.dimensions.contentSpacing.y } colorScheme: hifi.colorSchemes.dark } Button { - id: button - text: "Browse" + id: bookmarkAvatarButton + text: "Bookmark Avatar" + width: 140 anchors { - right: parent.right - verticalCenter: dataTextField.verticalCenter + left: parent.left + bottom: parent.bottom + rightMargin: hifi.dimensions.contentSpacing.x + } + onClicked: root.bookmarkAvatarSignal() + } + + Button { + id: browseAvatarsButton + text: "Browse Avatars" + width: 140 + anchors { + left: bookmarkAvatarButton.right + bottom: parent.bottom + leftMargin: hifi.dimensions.contentSpacing.x } onClicked: { // Load dialog via OffscreenUi so that JavaScript EventBridge is available. @@ -89,5 +104,6 @@ Preference { }); } } + } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4b274906e7..33e2d03116 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -691,7 +691,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo usleep(USECS_PER_MSEC * 50); // 20hz } - _bookmarks = new Bookmarks(); // Before setting up the menu + _locationBookmarks = new LocationBookmarks(); // Before setting up the menu + _avatarBookmarks = new AvatarBookmarks(); // start the nodeThread so its event loop is running QThread* nodeThread = new QThread(this); diff --git a/interface/src/Application.h b/interface/src/Application.h index 7ae4160f8b..f07dc5ace6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -52,7 +52,8 @@ #include "avatar/MyAvatar.h" #include "BandwidthRecorder.h" -#include "Bookmarks.h" +#include "LocationBookmarks.h" +#include "AvatarBookmarks.h" #include "Camera.h" #include "ConnectionMonitor.h" #include "gpu/Context.h" @@ -263,7 +264,8 @@ public: glm::mat4 getEyeProjection(int eye) const; QRect getDesirableApplicationGeometry() const; - Bookmarks* getBookmarks() const { return _bookmarks; } + LocationBookmarks* getLocationBookmarks() const { return _locationBookmarks; } + AvatarBookmarks* getAvatarBookmarks() const { return _avatarBookmarks; } virtual bool canAcceptURL(const QString& url) const override; virtual bool acceptURL(const QString& url, bool defaultUpload = false) override; @@ -596,7 +598,8 @@ private: bool _aboutToQuit; - Bookmarks* _bookmarks; + QPointer _locationBookmarks; + QPointer _avatarBookmarks; bool _notifiedPacketVersionMismatchThisDomain; diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp new file mode 100644 index 0000000000..c799fb9ef2 --- /dev/null +++ b/interface/src/AvatarBookmarks.cpp @@ -0,0 +1,116 @@ +// +// AvatarBookmarks.cpp +// interface/src +// +// Created by Triplelexx on 23/03/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include + +#include +#include + +#include "MainWindow.h" +#include "Menu.h" + +#include + +#include "AvatarBookmarks.h" +#include + +AvatarBookmarks::AvatarBookmarks() { + _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/" + AvatarBookmarks_FILENAME; + readFromFile(); +} + +void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { + // Add menus/actions + auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkAvatar); + QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection); + _bookmarksMenu = menu->addMenu(MenuOption::AvatarBookmarks); + _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark); + QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); + + Bookmarks::setupMenus(menubar, menu); + + // connect bookmarkAvatarButton in AvatarPreferencesDialog.qml + + // TODO: attempt at connecting to bookmarkAvatarSignal in AvatarPreferencesDialog.qml + // the OffscreenUi doesn't seem available this early to recurse through to find the root object where the signal is declared + // I've added a delay for now + + // The OffscreenUi also doesn't create the object till it is shown first, so I'm forcing it to show so the object exists + QTimer::singleShot(2000, [&] { + auto offscreenUi = DependencyManager::get(); + offscreenUi->show(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), "AvatarPreferencesDialog"); + auto bookmarkAvatarButton = offscreenUi->getRootItem()->findChild("avatarPreferencesRoot"); + if (bookmarkAvatarButton) { + QObject::connect(bookmarkAvatarButton, SIGNAL(bookmarkAvatarSignal()), this, SLOT(addBookmark())); + } + }); +} + +void AvatarBookmarks::changeToBookmarkedAvatar() { + QAction* action = qobject_cast(sender()); + const QString& address = action->data().toString(); + + auto myAvatar = DependencyManager::get()->getMyAvatar(); + myAvatar->useFullAvatarURL(address); +} + +void AvatarBookmarks::addBookmark() { + // TODO: if you press the Bookmark Avatar button in the dialog it seems to maintain focus. + // Clicking afterwards results in multiple calls + // hide enforced till cause is determined + DependencyManager::get()->hide(QString("AvatarPreferencesDialog")); + + bool ok = false; + auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString(), &ok); + if (!ok) { + return; + } + + bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); + if (bookmarkName.length() == 0) { + return; + } + + auto myAvatar = DependencyManager::get()->getMyAvatar(); + const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString(); + + Menu* menubar = Menu::getInstance(); + if (contains(bookmarkName)) { + auto offscreenUi = DependencyManager::get(); + auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", + "The bookmark name you entered already exists in your list.", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); + + auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); + if (result != QMessageBox::Yes) { + return; + } + removeBookmarkFromMenu(menubar, bookmarkName); + } + + addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); + insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. + + enableMenuItems(true); +} + +void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { + QAction* changeAction = _bookmarksMenu->newAction(); + changeAction->setData(address); + connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar())); + + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, + name, 0, QAction::NoRole); +} diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h new file mode 100644 index 0000000000..9dfe274f65 --- /dev/null +++ b/interface/src/AvatarBookmarks.h @@ -0,0 +1,38 @@ +// +// AvatarBookmarks.h +// interface/src +// +// Created by Triplelexx on 23/03/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarBookmarks_h +#define hifi_AvatarBookmarks_h + +#include "Bookmarks.h" + +class AvatarBookmarks: public Bookmarks { + Q_OBJECT + +public: + AvatarBookmarks(); + + virtual void setupMenus(Menu* menubar, MenuWrapper* menu) override; + +public slots: + virtual void addBookmark() override; + +protected: + virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; + +private slots: +void changeToBookmarkedAvatar(); + +private: + const QString AvatarBookmarks_FILENAME = "avatarbookmarks.json"; +}; + +#endif // hifi_AvatarBookmarks_h diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 476925a0c5..d63d3d6bef 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -11,14 +11,10 @@ #include #include -#include -#include #include -#include #include #include -#include #include #include @@ -27,15 +23,47 @@ #include "InterfaceLogging.h" #include "Bookmarks.h" -#include - - -const QString Bookmarks::HOME_BOOKMARK = "Home"; Bookmarks::Bookmarks() { - _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME; - readFromFile(); +} + +void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { + // Enable/Disable menus as needed + enableMenuItems(_bookmarks.count() > 0); + + // Load Bookmarks + for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) { + QString bookmarkName = it.key(); + QString bookmarkAddress = it.value().toString(); + addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); + } +} + +void Bookmarks::deleteBookmark() { + QStringList bookmarkList; + QList menuItems = _bookmarksMenu->actions(); + for (int i = 0; i < menuItems.count(); i += 1) { + bookmarkList.append(menuItems[i]->text()); + } + + bool ok = false; + auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok); + if (!ok) { + return; + } + + bookmarkName = bookmarkName.trimmed(); + if (bookmarkName.length() == 0) { + return; + } + + removeBookmarkFromMenu(Menu::getInstance(), bookmarkName); + remove(bookmarkName); + + if (_bookmarksMenu->actions().count() == 0) { + enableMenuItems(false); + } } void Bookmarks::insert(const QString& name, const QString& address) { @@ -99,108 +127,6 @@ void Bookmarks::persistToFile() { saveFile.write(data); } -void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { - // Add menus/actions - auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation); - QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(bookmarkLocation()), Qt::QueuedConnection); - auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation); - QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection); - _bookmarksMenu = menu->addMenu(MenuOption::Bookmarks); - _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark); - QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); - - // Enable/Disable menus as needed - enableMenuItems(_bookmarks.count() > 0); - - // Load bookmarks - for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) { - QString bookmarkName = it.key(); - QString bookmarkAddress = it.value().toString(); - addLocationToMenu(menubar, bookmarkName, bookmarkAddress); - } -} - -void Bookmarks::bookmarkLocation() { - bool ok = false; - auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok); - if (!ok) { - return; - } - - bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); - if (bookmarkName.length() == 0) { - return; - } - - auto addressManager = DependencyManager::get(); - QString bookmarkAddress = addressManager->currentAddress().toString(); - - Menu* menubar = Menu::getInstance(); - if (contains(bookmarkName)) { - auto offscreenUi = DependencyManager::get(); - auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", - "The bookmark name you entered already exists in your list.", - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); - - auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); - if (result != QMessageBox::Yes) { - return; - } - removeLocationFromMenu(menubar, bookmarkName); - } - - addLocationToMenu(menubar, bookmarkName, bookmarkAddress); - insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - - enableMenuItems(true); -} - -void Bookmarks::setHomeLocation() { - Menu* menubar = Menu::getInstance(); - QString bookmarkName = HOME_BOOKMARK; - auto addressManager = DependencyManager::get(); - QString bookmarkAddress = addressManager->currentAddress().toString(); - - addLocationToMenu(menubar, bookmarkName, bookmarkAddress); - insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - - enableMenuItems(true); -} - -void Bookmarks::teleportToBookmark() { - QAction* action = qobject_cast(sender()); - QString address = action->data().toString(); - DependencyManager::get()->handleLookupString(address); -} - -void Bookmarks::deleteBookmark() { - - QStringList bookmarkList; - QList menuItems = _bookmarksMenu->actions(); - for (int i = 0; i < menuItems.count(); i += 1) { - bookmarkList.append(menuItems[i]->text()); - } - - bool ok = false; - auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok); - if (!ok) { - return; - } - - bookmarkName = bookmarkName.trimmed(); - if (bookmarkName.length() == 0) { - return; - } - - removeLocationFromMenu(Menu::getInstance(), bookmarkName); - remove(bookmarkName); - - if (_bookmarksMenu->actions().count() == 0) { - enableMenuItems(false); - } -} - void Bookmarks::enableMenuItems(bool enabled) { if (_bookmarksMenu) { _bookmarksMenu->setEnabled(enabled); @@ -210,17 +136,6 @@ void Bookmarks::enableMenuItems(bool enabled) { } } -void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) { - QAction* teleportAction = _bookmarksMenu->newAction(); - teleportAction->setData(address); - connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark())); - - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, - name, 0, QAction::NoRole); -} - -void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) { +void Bookmarks::removeBookmarkFromMenu(Menu* menubar, const QString& name) { menubar->removeAction(_bookmarksMenu, name); } - - diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index fd9598b7db..fbc0d41f33 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -27,25 +27,21 @@ class Bookmarks: public QObject { public: Bookmarks(); - void setupMenus(Menu* menubar, MenuWrapper* menu); - + virtual void setupMenus(Menu* menubar, MenuWrapper* menu); QString addressForBookmark(const QString& name) const; - static const QString HOME_BOOKMARK; +public slots: + virtual void addBookmark() = 0; -private slots: - void bookmarkLocation(); - void setHomeLocation(); - void teleportToBookmark(); +protected slots: void deleteBookmark(); -private: - QVariantMap _bookmarks; // { name: address, ... } +protected: + QVariantMap _bookmarks; // { name: url, ... } QPointer _bookmarksMenu; QPointer _deleteBookmarksAction; - const QString BOOKMARKS_FILENAME = "bookmarks.json"; QString _bookmarksFilename; void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name. @@ -56,8 +52,8 @@ private: void persistToFile(); void enableMenuItems(bool enabled); - void addLocationToMenu(Menu* menubar, QString& name, QString& address); - void removeLocationFromMenu(Menu* menubar, QString& name); + virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0; + void removeBookmarkFromMenu(Menu* menubar, const QString& name); }; -#endif // hifi_Bookmarks_h \ No newline at end of file +#endif // hifi_Bookmarks_h diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp new file mode 100644 index 0000000000..14bee4314c --- /dev/null +++ b/interface/src/LocationBookmarks.cpp @@ -0,0 +1,108 @@ +// +// LocationBookmarks.cpp +// interface/src +// +// Created by Triplelexx on 23/03/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include + +#include +#include +#include + +#include "MainWindow.h" +#include "Menu.h" + +#include "LocationBookmarks.h" +#include + +const QString LocationBookmarks::HOME_BOOKMARK = "Home"; + +LocationBookmarks::LocationBookmarks() { + _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + LocationBookmarks_FILENAME; + readFromFile(); +} + +void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { + // Add menus/actions + auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation); + QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection); + auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation); + QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection); + _bookmarksMenu = menu->addMenu(MenuOption::LocationBookmarks); + _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark); + QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); + + Bookmarks::setupMenus(menubar, menu); +} + +void LocationBookmarks::setHomeLocation() { + Menu* menubar = Menu::getInstance(); + QString bookmarkName = HOME_BOOKMARK; + auto addressManager = DependencyManager::get(); + QString bookmarkAddress = addressManager->currentAddress().toString(); + + addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); + insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. + + enableMenuItems(true); +} + +void LocationBookmarks::teleportToBookmark() { + QAction* action = qobject_cast(sender()); + QString address = action->data().toString(); + DependencyManager::get()->handleLookupString(address); +} + +void LocationBookmarks::addBookmark() { + bool ok = false; + auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok); + if (!ok) { + return; + } + + bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); + if (bookmarkName.length() == 0) { + return; + } + + auto addressManager = DependencyManager::get(); + QString bookmarkAddress = addressManager->currentAddress().toString(); + + Menu* menubar = Menu::getInstance(); + if (contains(bookmarkName)) { + auto offscreenUi = DependencyManager::get(); + auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", + "The bookmark name you entered already exists in your list.", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); + + auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); + if (result != QMessageBox::Yes) { + return; + } + removeBookmarkFromMenu(menubar, bookmarkName); + } + + addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); + insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. + + enableMenuItems(true); +} + +void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { + QAction* teleportAction = _bookmarksMenu->newAction(); + teleportAction->setData(address); + connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark())); + + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, + name, 0, QAction::NoRole); +} diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h new file mode 100644 index 0000000000..19059098e1 --- /dev/null +++ b/interface/src/LocationBookmarks.h @@ -0,0 +1,40 @@ +// +// LocationBookmarks.h +// interface/src +// +// Created by Triplelexx on 23/03/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_LocationBookmarks_h +#define hifi_LocationBookmarks_h + +#include "Bookmarks.h" + +class LocationBookmarks: public Bookmarks { + Q_OBJECT + +public: + LocationBookmarks(); + + virtual void setupMenus(Menu* menubar, MenuWrapper* menu) override; + static const QString HOME_BOOKMARK; + +public slots: + virtual void addBookmark() override; + +protected: + virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; + +private slots: + void setHomeLocation(); + void teleportToBookmark(); + +private: + const QString LocationBookmarks_FILENAME = "bookmarks.json"; +}; + +#endif // hifi_LocationBookmarks_h diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a48ee4e7db..05271e3b4d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -194,6 +194,8 @@ Menu::Menu() { 0, // QML Qt::Key_Apostrophe, qApp, SLOT(resetSensors())); + // Avatar > AvatarBookmarks related menus -- Note: the AvatarBookmarks class adds its own submenus here. + qApp->getAvatarBookmarks()->setupMenus(this, avatarMenu); // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have @@ -256,8 +258,8 @@ Menu::Menu() { addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L, dialogsManager.data(), SLOT(toggleAddressBar())); - // Navigate > Bookmark related menus -- Note: the Bookmark class adds its own submenus here. - qApp->getBookmarks()->setupMenus(this, navigateMenu); + // Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here. + qApp->getLocationBookmarks()->setupMenus(this, navigateMenu); // Navigate > Copy Address [advanced] auto addressManager = DependencyManager::get(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b4eaf56758..7c2ad58b06 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -47,10 +47,11 @@ namespace MenuOption { const QString AudioTools = "Show Level Meter"; const QString AutoMuteAudio = "Auto Mute Microphone"; const QString AvatarReceiveStats = "Show Receive Stats"; + const QString AvatarBookmarks = "Avatar Bookmarks"; const QString Back = "Back"; const QString BinaryEyelidControl = "Binary Eyelid Control"; + const QString BookmarkAvatar = "Bookmark Avatar"; const QString BookmarkLocation = "Bookmark Location"; - const QString Bookmarks = "Bookmarks"; const QString CalibrateCamera = "Calibrate Camera"; const QString CameraEntityMode = "Entity Mode"; const QString CenterPlayerInView = "Center Player In View"; @@ -78,6 +79,7 @@ namespace MenuOption { const QString DeadlockInterface = "Deadlock Interface"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DefaultSkybox = "Default Skybox"; + const QString DeleteAvatarBookmark = "Delete Avatar Bookmark..."; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableEyelidAdjustment = "Disable Eyelid Adjustment"; @@ -89,6 +91,7 @@ namespace MenuOption { const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayDebugTimingDetails = "Display Timing Details"; + const QString LocationBookmarks = "Bookmarks"; const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; const QString EchoLocalAudio = "Echo Local Audio"; diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index ac566d68c7..0534a9f456 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -52,7 +52,7 @@ void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) void AddressBarDialog::loadHome() { qDebug() << "Called LoadHome"; - QString homeLocation = qApp->getBookmarks()->addressForBookmark(Bookmarks::HOME_BOOKMARK); + QString homeLocation = qApp->getLocationBookmarks()->addressForBookmark(LocationBookmarks::HOME_BOOKMARK); const QString DEFAULT_HOME_LOCATION = "localhost"; if (homeLocation == "") { homeLocation = DEFAULT_HOME_LOCATION; diff --git a/scripts/system/avatarBookmarks.js b/scripts/system/avatarBookmarks.js deleted file mode 100644 index e69de29bb2..0000000000 From d1eee19d7dec23f21bfa873d70f848822cc76470 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 25 Mar 2017 01:01:25 +0000 Subject: [PATCH 03/39] move more Bookmark functionality into base class --- interface/src/AvatarBookmarks.cpp | 25 +++---------------------- interface/src/AvatarBookmarks.h | 8 ++++---- interface/src/Bookmarks.cpp | 22 ++++++++++++++++++++++ interface/src/Bookmarks.h | 2 +- interface/src/LocationBookmarks.cpp | 21 +-------------------- interface/src/LocationBookmarks.h | 6 +++--- 6 files changed, 34 insertions(+), 50 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index c799fb9ef2..8afddf1b83 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -46,7 +46,7 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { // the OffscreenUi doesn't seem available this early to recurse through to find the root object where the signal is declared // I've added a delay for now - // The OffscreenUi also doesn't create the object till it is shown first, so I'm forcing it to show so the object exists + // The OffscreenUi also doesn't create the object until it is shown first, so I'm forcing it to show so the object exists QTimer::singleShot(2000, [&] { auto offscreenUi = DependencyManager::get(); offscreenUi->show(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), "AvatarPreferencesDialog"); @@ -68,7 +68,7 @@ void AvatarBookmarks::changeToBookmarkedAvatar() { void AvatarBookmarks::addBookmark() { // TODO: if you press the Bookmark Avatar button in the dialog it seems to maintain focus. // Clicking afterwards results in multiple calls - // hide enforced till cause is determined + // hide enforced until cause is determined DependencyManager::get()->hide(QString("AvatarPreferencesDialog")); bool ok = false; @@ -84,26 +84,7 @@ void AvatarBookmarks::addBookmark() { auto myAvatar = DependencyManager::get()->getMyAvatar(); const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString(); - - Menu* menubar = Menu::getInstance(); - if (contains(bookmarkName)) { - auto offscreenUi = DependencyManager::get(); - auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", - "The bookmark name you entered already exists in your list.", - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); - - auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); - if (result != QMessageBox::Yes) { - return; - } - removeBookmarkFromMenu(menubar, bookmarkName); - } - - addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); - insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - - enableMenuItems(true); + Bookmarks::addBookmark(bookmarkName, bookmarkAddress); } void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 9dfe274f65..6c58ea7861 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -20,16 +20,16 @@ class AvatarBookmarks: public Bookmarks { public: AvatarBookmarks(); - virtual void setupMenus(Menu* menubar, MenuWrapper* menu) override; + void setupMenus(Menu* menubar, MenuWrapper* menu) override; public slots: - virtual void addBookmark() override; + void addBookmark(); protected: - virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; + void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; private slots: -void changeToBookmarkedAvatar(); + void changeToBookmarkedAvatar(); private: const QString AvatarBookmarks_FILENAME = "avatarbookmarks.json"; diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index d63d3d6bef..4462cb048c 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -66,6 +66,28 @@ void Bookmarks::deleteBookmark() { } } +void Bookmarks::addBookmark(const QString& bookmarkName, const QString& bookmarkAddress) { + Menu* menubar = Menu::getInstance(); + if (contains(bookmarkName)) { + auto offscreenUi = DependencyManager::get(); + auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", + "The bookmark name you entered already exists in your list.", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); + + auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); + if (result != QMessageBox::Yes) { + return; + } + removeBookmarkFromMenu(menubar, bookmarkName); + } + + addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); + insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. + + enableMenuItems(true); +} + void Bookmarks::insert(const QString& name, const QString& address) { _bookmarks.insert(name, address); diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index fbc0d41f33..8e6adb6d61 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -31,7 +31,7 @@ public: QString addressForBookmark(const QString& name) const; public slots: - virtual void addBookmark() = 0; + virtual void addBookmark(const QString& bookmarkName, const QString& bookmarkAddress); protected slots: void deleteBookmark(); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 14bee4314c..52bcc94c9f 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -76,26 +76,7 @@ void LocationBookmarks::addBookmark() { auto addressManager = DependencyManager::get(); QString bookmarkAddress = addressManager->currentAddress().toString(); - - Menu* menubar = Menu::getInstance(); - if (contains(bookmarkName)) { - auto offscreenUi = DependencyManager::get(); - auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark", - "The bookmark name you entered already exists in your list.", - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); - - auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); - if (result != QMessageBox::Yes) { - return; - } - removeBookmarkFromMenu(menubar, bookmarkName); - } - - addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); - insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - - enableMenuItems(true); + Bookmarks::addBookmark(bookmarkName, bookmarkAddress); } void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index 19059098e1..40d08e57e9 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -20,14 +20,14 @@ class LocationBookmarks: public Bookmarks { public: LocationBookmarks(); - virtual void setupMenus(Menu* menubar, MenuWrapper* menu) override; + void setupMenus(Menu* menubar, MenuWrapper* menu) override; static const QString HOME_BOOKMARK; public slots: - virtual void addBookmark() override; + void addBookmark(); protected: - virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; + void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; private slots: void setHomeLocation(); From 96f905362b0aefff289be4ac0650503397afae08 Mon Sep 17 00:00:00 2001 From: humbletim Date: Sat, 25 Mar 2017 01:17:27 -0400 Subject: [PATCH 04/39] alternative way to connect the button? --- .../qml/dialogs/preferences/AvatarPreference.qml | 2 +- interface/src/AvatarBookmarks.cpp | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index e3db8364f2..8c10ffd352 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -84,7 +84,7 @@ Preference { bottom: parent.bottom rightMargin: hifi.dimensions.contentSpacing.x } - onClicked: root.bookmarkAvatarSignal() + onClicked: { console.info('calling avatarBookmarks.addBookmark'); avatarBookmarks.addBookmark() } } Button { diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 8afddf1b83..25fbc5216d 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "MainWindow.h" #include "Menu.h" @@ -46,15 +47,9 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { // the OffscreenUi doesn't seem available this early to recurse through to find the root object where the signal is declared // I've added a delay for now - // The OffscreenUi also doesn't create the object until it is shown first, so I'm forcing it to show so the object exists - QTimer::singleShot(2000, [&] { - auto offscreenUi = DependencyManager::get(); - offscreenUi->show(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), "AvatarPreferencesDialog"); - auto bookmarkAvatarButton = offscreenUi->getRootItem()->findChild("avatarPreferencesRoot"); - if (bookmarkAvatarButton) { - QObject::connect(bookmarkAvatarButton, SIGNAL(bookmarkAvatarSignal()), this, SLOT(addBookmark())); - } - }); + auto offscreenUi = DependencyManager::get(); + auto context = offscreenUi->getRootContext(); + context->setContextProperty("avatarBookmarks", this); } void AvatarBookmarks::changeToBookmarkedAvatar() { From 630afb716f6d60532ebeb9e25d8884344679eaff Mon Sep 17 00:00:00 2001 From: humbletim Date: Sat, 25 Mar 2017 03:01:35 -0400 Subject: [PATCH 05/39] consolidate QML->C++ triggering workaround to help compartmentalize the problem for later fixin' --- .../resources/qml/controls-uit/Button.qml | 27 ++++++++++++++++++- .../dialogs/preferences/AvatarPreference.qml | 2 +- .../qml/hifi/dialogs/RunningScripts.qml | 27 ++----------------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index 59f8a63238..3755312128 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -23,8 +23,33 @@ Original.Button { HifiConstants { id: hifi } - style: ButtonStyle { + // FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML + // For some reason trigginer an API that enters + // an internal event loop directly from the button clicked + // trigger below causes the appliction to behave oddly. + // Most likely because the button onClicked handling is never + // completed until the function returns. + // FIXME find a better way of handling the input dialogs that + // doesn't trigger this. + + // NOTE: dialogs that need to use this workaround can connect via + // onQueuedClicked: ... + // instead of: + // onClicked: ... + + onClicked: fromTimer.running = true + signal queuedClicked() + Timer { + id: fromTimer + interval: 5 + repeat: false + running: false + onTriggered: { console.info('onQueuedClicked->onTriggered'); queuedClicked() } + } + onQueuedClicked: console.info('HifiControls.Button -- please define onClicked: or onQueuedClicked:') + + style: ButtonStyle { background: Rectangle { radius: hifi.buttons.radius diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 8c10ffd352..b98b706c37 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -84,7 +84,7 @@ Preference { bottom: parent.bottom rightMargin: hifi.dimensions.contentSpacing.x } - onClicked: { console.info('calling avatarBookmarks.addBookmark'); avatarBookmarks.addBookmark() } + onQueuedClicked: avatarBookmarks.addBookmark() } Button { diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 29807d9646..5321aacd25 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -223,37 +223,14 @@ ScrollingWindow { text: "from URL" color: hifi.buttons.black height: 26 - onClicked: fromUrlTimer.running = true - - // For some reason trigginer an API that enters - // an internal event loop directly from the button clicked - // trigger below causes the appliction to behave oddly. - // Most likely because the button onClicked handling is never - // completed until the function returns. - // FIXME find a better way of handling the input dialogs that - // doesn't trigger this. - Timer { - id: fromUrlTimer - interval: 5 - repeat: false - running: false - onTriggered: ApplicationInterface.loadScriptURLDialog(); - } + onQueuedClicked: ApplicationInterface.loadScriptURLDialog() } HifiControls.Button { text: "from Disk" color: hifi.buttons.black height: 26 - onClicked: fromDiskTimer.running = true - - Timer { - id: fromDiskTimer - interval: 5 - repeat: false - running: false - onTriggered: ApplicationInterface.loadDialog(); - } + onQueuedClicked: ApplicationInterface.loadDialog() } HifiControls.Button { From 5d5d947ddbf327cbb62cd67510ae97374d2c13f3 Mon Sep 17 00:00:00 2001 From: humbletim Date: Sat, 25 Mar 2017 04:01:02 -0400 Subject: [PATCH 06/39] updates per discussion with triplelexx --- .../resources/qml/controls-uit/Button.qml | 27 +----------- .../qml/controls-uit/QueuedButton.qml | 43 +++++++++++++++++++ .../dialogs/preferences/AvatarPreference.qml | 4 +- .../qml/hifi/dialogs/RunningScripts.qml | 8 ++-- 4 files changed, 50 insertions(+), 32 deletions(-) create mode 100644 interface/resources/qml/controls-uit/QueuedButton.qml diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index 3755312128..59f8a63238 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -23,33 +23,8 @@ Original.Button { HifiConstants { id: hifi } - // FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML - - // For some reason trigginer an API that enters - // an internal event loop directly from the button clicked - // trigger below causes the appliction to behave oddly. - // Most likely because the button onClicked handling is never - // completed until the function returns. - // FIXME find a better way of handling the input dialogs that - // doesn't trigger this. - - // NOTE: dialogs that need to use this workaround can connect via - // onQueuedClicked: ... - // instead of: - // onClicked: ... - - onClicked: fromTimer.running = true - signal queuedClicked() - Timer { - id: fromTimer - interval: 5 - repeat: false - running: false - onTriggered: { console.info('onQueuedClicked->onTriggered'); queuedClicked() } - } - onQueuedClicked: console.info('HifiControls.Button -- please define onClicked: or onQueuedClicked:') - style: ButtonStyle { + background: Rectangle { radius: hifi.buttons.radius diff --git a/interface/resources/qml/controls-uit/QueuedButton.qml b/interface/resources/qml/controls-uit/QueuedButton.qml new file mode 100644 index 0000000000..36ffbe582f --- /dev/null +++ b/interface/resources/qml/controls-uit/QueuedButton.qml @@ -0,0 +1,43 @@ +// +// QueuedButton.qml +// -- original Button.qml + signal timer workaround --ht +// Created by David Rowe on 16 Feb 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" +import "." as HifiControls + +HifiControls.Button { + // FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML + + // For some reason trigginer an API that enters + // an internal event loop directly from the button clicked + // trigger below causes the appliction to behave oddly. + // Most likely because the button onClicked handling is never + // completed until the function returns. + // FIXME find a better way of handling the input dialogs that + // doesn't trigger this. + + // NOTE: dialogs that need to use this workaround can connect via + // onQueuedClicked: ... + // instead of: + // onClicked: ... + + signal clickedQueued() + Timer { + id: fromTimer + interval: 5 + repeat: false + running: false + onTriggered: clickedQueued() + } + onClicked: fromTimer.running = true +} diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index b98b706c37..9e2ac34c64 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -75,7 +75,7 @@ Preference { colorScheme: hifi.colorSchemes.dark } - Button { + QueuedButton { id: bookmarkAvatarButton text: "Bookmark Avatar" width: 140 @@ -84,7 +84,7 @@ Preference { bottom: parent.bottom rightMargin: hifi.dimensions.contentSpacing.x } - onQueuedClicked: avatarBookmarks.addBookmark() + onClickedQueued: avatarBookmarks.addBookmark() } Button { diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 5321aacd25..d95dbc2e55 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -219,18 +219,18 @@ ScrollingWindow { Row { spacing: hifi.dimensions.contentSpacing.x - HifiControls.Button { + HifiControls.QueuedButton { text: "from URL" color: hifi.buttons.black height: 26 - onQueuedClicked: ApplicationInterface.loadScriptURLDialog() + onClickedQueued: ApplicationInterface.loadScriptURLDialog() } - HifiControls.Button { + HifiControls.QueuedButton { text: "from Disk" color: hifi.buttons.black height: 26 - onQueuedClicked: ApplicationInterface.loadDialog() + onClickedQueued: ApplicationInterface.loadDialog() } HifiControls.Button { From c4bcacf0e056b8850bb63a9e5746ef7cf4b05587 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 25 Mar 2017 19:04:40 +0000 Subject: [PATCH 07/39] use QueuedButton for upload dialog --- interface/resources/qml/AssetServer.qml | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index cf61a2ae4a..0e096cde22 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -542,7 +542,7 @@ ScrollingWindow { Item { height: parent.height width: parent.width - HifiControls.Button { + HifiControls.QueuedButton { id: uploadButton anchors.right: parent.right @@ -552,22 +552,7 @@ ScrollingWindow { height: 30 width: 155 - onClicked: uploadClickedTimer.running = true - - // For some reason trigginer an API that enters - // an internal event loop directly from the button clicked - // trigger below causes the appliction to behave oddly. - // Most likely because the button onClicked handling is never - // completed until the function returns. - // FIXME find a better way of handling the input dialogs that - // doesn't trigger this. - Timer { - id: uploadClickedTimer - interval: 5 - repeat: false - running: false - onTriggered: uploadClicked(); - } + onClickedQueued: uploadClicked() } Item { From 8f507942cffbc653d0957126b9163ef6fa1f3c1a Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 25 Mar 2017 19:10:12 +0000 Subject: [PATCH 08/39] change storage location still unsure what is best. this is consistent and doesn't require login --- .../resources/qml/dialogs/preferences/AvatarPreference.qml | 2 -- interface/src/AvatarBookmarks.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 9e2ac34c64..9a2d9f3edb 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -15,8 +15,6 @@ import "../../controls-uit" Preference { id: root - objectName: "avatarPreferencesRoot" - signal bookmarkAvatarSignal() property alias text: dataTextField.text property alias placeholderText: dataTextField.placeholderText property var browser; diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 25fbc5216d..4dba46b266 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -27,7 +27,7 @@ #include AvatarBookmarks::AvatarBookmarks() { - _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/" + AvatarBookmarks_FILENAME; + _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AvatarBookmarks_FILENAME; readFromFile(); } From a1db20c5fcd0d06440ead35896a0316265d9b88c Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sun, 26 Mar 2017 22:18:37 +0100 Subject: [PATCH 09/39] cleanup for QA added sorting --- interface/src/AvatarBookmarks.cpp | 20 ++++---------------- interface/src/AvatarBookmarks.h | 6 +++--- interface/src/Bookmarks.cpp | 17 +++++++++++++++-- interface/src/Bookmarks.h | 22 ++++++++++++---------- interface/src/LocationBookmarks.cpp | 17 ++++++----------- interface/src/LocationBookmarks.h | 6 +++--- 6 files changed, 43 insertions(+), 45 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 4dba46b266..69559cc5c9 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -13,16 +13,15 @@ #include #include #include +#include #include #include -#include +#include #include "MainWindow.h" #include "Menu.h" -#include - #include "AvatarBookmarks.h" #include @@ -41,12 +40,6 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { Bookmarks::setupMenus(menubar, menu); - // connect bookmarkAvatarButton in AvatarPreferencesDialog.qml - - // TODO: attempt at connecting to bookmarkAvatarSignal in AvatarPreferencesDialog.qml - // the OffscreenUi doesn't seem available this early to recurse through to find the root object where the signal is declared - // I've added a delay for now - auto offscreenUi = DependencyManager::get(); auto context = offscreenUi->getRootContext(); context->setContextProperty("avatarBookmarks", this); @@ -61,11 +54,6 @@ void AvatarBookmarks::changeToBookmarkedAvatar() { } void AvatarBookmarks::addBookmark() { - // TODO: if you press the Bookmark Avatar button in the dialog it seems to maintain focus. - // Clicking afterwards results in multiple calls - // hide enforced until cause is determined - DependencyManager::get()->hide(QString("AvatarPreferencesDialog")); - bool ok = false; auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString(), &ok); if (!ok) { @@ -87,6 +75,6 @@ void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, cons changeAction->setData(address); connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar())); - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, - name, 0, QAction::NoRole); + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); + Bookmarks::sortActions(_bookmarksMenu); } diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 6c58ea7861..78f2930106 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -28,11 +28,11 @@ public slots: protected: void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; -private slots: - void changeToBookmarkedAvatar(); - private: const QString AvatarBookmarks_FILENAME = "avatarbookmarks.json"; + +private slots: + void changeToBookmarkedAvatar(); }; #endif // hifi_AvatarBookmarks_h diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 4462cb048c..0e0dbb58c1 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -24,7 +24,6 @@ #include "Bookmarks.h" - Bookmarks::Bookmarks() { } @@ -84,7 +83,6 @@ void Bookmarks::addBookmark(const QString& bookmarkName, const QString& bookmark addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - enableMenuItems(true); } @@ -114,6 +112,21 @@ bool Bookmarks::contains(const QString& name) const { return _bookmarks.contains(name); } +bool Bookmarks::sortOrder(QAction* a, QAction* b) { + return a->text().toLower() < b->text().toLower(); +} + +void Bookmarks::sortActions(MenuWrapper* menuWrapper) { + QList tmpActions = menuWrapper->actions(); + qSort(tmpActions.begin(), tmpActions.end(), sortOrder); + for (QAction* action : menuWrapper->actions()) { + menuWrapper->removeAction(action); + } + for (QAction* action : tmpActions) { + menuWrapper->addAction(action); + } +} + QString Bookmarks::addressForBookmark(const QString& name) const { return _bookmarks.value(name).toString(); } diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index 8e6adb6d61..d998a201ae 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -33,26 +33,28 @@ public: public slots: virtual void addBookmark(const QString& bookmarkName, const QString& bookmarkAddress); -protected slots: - void deleteBookmark(); - protected: + virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0; + void enableMenuItems(bool enabled); + void readFromFile(); + void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name. + void sortActions(MenuWrapper* menuWrapper); + QVariantMap _bookmarks; // { name: url, ... } - QPointer _bookmarksMenu; QPointer _deleteBookmarksAction; - QString _bookmarksFilename; - - void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name. + +protected slots: + void deleteBookmark(); + +private: void remove(const QString& name); bool contains(const QString& name) const; + static bool sortOrder(QAction* a, QAction* b); - void readFromFile(); void persistToFile(); - void enableMenuItems(bool enabled); - virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0; void removeBookmarkFromMenu(Menu* menubar, const QString& name); }; diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 52bcc94c9f..7b39ed2926 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -40,20 +40,15 @@ void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { _bookmarksMenu = menu->addMenu(MenuOption::LocationBookmarks); _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark); QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); - + Bookmarks::setupMenus(menubar, menu); } void LocationBookmarks::setHomeLocation() { - Menu* menubar = Menu::getInstance(); - QString bookmarkName = HOME_BOOKMARK; auto addressManager = DependencyManager::get(); QString bookmarkAddress = addressManager->currentAddress().toString(); - - addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress); - insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. - - enableMenuItems(true); + Bookmarks::addBookmark(HOME_BOOKMARK, bookmarkAddress); + Bookmarks::sortActions(_bookmarksMenu); } void LocationBookmarks::teleportToBookmark() { @@ -83,7 +78,7 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co QAction* teleportAction = _bookmarksMenu->newAction(); teleportAction->setData(address); connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark())); - - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, - name, 0, QAction::NoRole); + + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); + Bookmarks::sortActions(_bookmarksMenu); } diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index 40d08e57e9..d1eeb87329 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -29,12 +29,12 @@ public slots: protected: void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; +private: + const QString LocationBookmarks_FILENAME = "bookmarks.json"; + private slots: void setHomeLocation(); void teleportToBookmark(); - -private: - const QString LocationBookmarks_FILENAME = "bookmarks.json"; }; #endif // hifi_LocationBookmarks_h From 07e6b766b564307f6d261d9bed8d0a27cc01c7b1 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sun, 26 Mar 2017 23:10:50 +0100 Subject: [PATCH 10/39] rename FILENAME constants --- .../qml/dialogs/preferences/AvatarPreference.qml | 12 ++++++++---- interface/src/AvatarBookmarks.cpp | 2 +- interface/src/AvatarBookmarks.h | 2 +- interface/src/LocationBookmarks.cpp | 2 +- interface/src/LocationBookmarks.h | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 9a2d9f3edb..c176370717 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -61,22 +61,26 @@ Preference { TextField { id: dataTextField + label: root.label placeholderText: root.placeholderText text: preference.value - label: root.label + colorScheme: dataTextField.acceptableInput ? hifi.colorSchemes.dark : hifi.colorSchemes.light + validator: RegExpValidator { + regExp: /.*\.(?:fst).*\?*/ig + } anchors { left: parent.left right: parent.right bottom: bookmarkAvatarButton.top bottomMargin: hifi.dimensions.contentSpacing.y } - colorScheme: hifi.colorSchemes.dark } QueuedButton { id: bookmarkAvatarButton text: "Bookmark Avatar" width: 140 + visible: dataTextField.acceptableInput anchors { left: parent.left bottom: parent.bottom @@ -90,9 +94,9 @@ Preference { text: "Browse Avatars" width: 140 anchors { - left: bookmarkAvatarButton.right + left: dataTextField.acceptableInput ? bookmarkAvatarButton.right : parent.left bottom: parent.bottom - leftMargin: hifi.dimensions.contentSpacing.x + leftMargin: dataTextField.acceptableInput ? hifi.dimensions.contentSpacing.x : 0 } onClicked: { // Load dialog via OffscreenUi so that JavaScript EventBridge is available. diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 69559cc5c9..b45a262093 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -26,7 +26,7 @@ #include AvatarBookmarks::AvatarBookmarks() { - _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AvatarBookmarks_FILENAME; + _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME; readFromFile(); } diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 78f2930106..958e0e891c 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -29,7 +29,7 @@ protected: void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; private: - const QString AvatarBookmarks_FILENAME = "avatarbookmarks.json"; + const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json"; private slots: void changeToBookmarkedAvatar(); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 7b39ed2926..f9719db18d 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -27,7 +27,7 @@ const QString LocationBookmarks::HOME_BOOKMARK = "Home"; LocationBookmarks::LocationBookmarks() { - _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + LocationBookmarks_FILENAME; + _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + LOCATIONBOOKMARKS_FILENAME; readFromFile(); } diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index d1eeb87329..b762a0be9d 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -30,7 +30,7 @@ protected: void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override; private: - const QString LocationBookmarks_FILENAME = "bookmarks.json"; + const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json"; private slots: void setHomeLocation(); From 255e781cc7ca796e620ea84da54b86a99df17103 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 29 Mar 2017 00:48:14 +0100 Subject: [PATCH 11/39] check-in after menu experiments https://highfidelity.fogbugz.com/f/cases/3714 --- interface/src/AvatarBookmarks.cpp | 16 +++++++++++--- interface/src/Bookmarks.cpp | 34 ++++++++++++++++++++++++----- interface/src/Bookmarks.h | 5 ++++- interface/src/LocationBookmarks.cpp | 16 +++++++++++--- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index b45a262093..a794c147c3 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -14,6 +14,7 @@ #include #include #include +//#include #include #include @@ -39,7 +40,7 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); Bookmarks::setupMenus(menubar, menu); - + Bookmarks::sortActions(menubar, _bookmarksMenu); auto offscreenUi = DependencyManager::get(); auto context = offscreenUi->getRootContext(); context->setContextProperty("avatarBookmarks", this); @@ -74,7 +75,16 @@ void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, cons QAction* changeAction = _bookmarksMenu->newAction(); changeAction->setData(address); connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar())); + if (!_isMenuSorted) { + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); + } else { + // TODO: this is aggressive but all other alternative have proved less fruitful so far. + // having experimented with various pointer types, It is possible the issues are deeper routed in the MenuWrapper/Menu Qt/QML architecture + // further research did not produce better results - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); - Bookmarks::sortActions(_bookmarksMenu); + //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole, + //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); + Bookmarks::sortActions(menubar, _bookmarksMenu); + } } diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 0e0dbb58c1..172bfd29ca 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -24,7 +24,9 @@ #include "Bookmarks.h" -Bookmarks::Bookmarks() { +Bookmarks::Bookmarks() : +_isMenuSorted(false) +{ } void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { @@ -113,18 +115,38 @@ bool Bookmarks::contains(const QString& name) const { } bool Bookmarks::sortOrder(QAction* a, QAction* b) { - return a->text().toLower() < b->text().toLower(); + return a->text().toLower().localeAwareCompare(b->text().toLower()) < 0; } -void Bookmarks::sortActions(MenuWrapper* menuWrapper) { - QList tmpActions = menuWrapper->actions(); - qSort(tmpActions.begin(), tmpActions.end(), sortOrder); +// TODO: inconsistent naming? +void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menuWrapper) { + QList actions = menuWrapper->actions(); + qSort(actions.begin(), actions.end(), sortOrder); for (QAction* action : menuWrapper->actions()) { menuWrapper->removeAction(action); + //removeBookmarkFromMenu(menubar, action->text()); } - for (QAction* action : tmpActions) { + for (QAction* action : actions) { menuWrapper->addAction(action); +// for (int i = 0; i < _bookmarks.size() ; i++) { +// if (_bookmarks.keys().at(i) == action->text()) { +// addBookmarkToMenu(menubar, action->text(), _bookmarks.values().at(i).toString()); +// } +// } } + _isMenuSorted = true; +} + +int Bookmarks::getMenuItemLocation(QList actions, const QString& name) const { + int menuItemLocation = 0; + for (QAction* action : actions) { + if (name.toLower().localeAwareCompare(action->text().toLower()) < 0) { + menuItemLocation = actions.indexOf(action); + break; + + } + } + return menuItemLocation; } QString Bookmarks::addressForBookmark(const QString& name) const { diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index d998a201ae..9ba2e4f45a 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -38,12 +38,15 @@ protected: void enableMenuItems(bool enabled); void readFromFile(); void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name. - void sortActions(MenuWrapper* menuWrapper); + void sortActions(Menu* menubar, MenuWrapper* menu); + int getMenuItemLocation(QList actions, const QString& name) const; QVariantMap _bookmarks; // { name: url, ... } + //QSharedPointer _bookmarksMenu; QPointer _bookmarksMenu; QPointer _deleteBookmarksAction; QString _bookmarksFilename; + bool _isMenuSorted; protected slots: void deleteBookmark(); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index f9719db18d..436b435bc4 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -13,6 +13,7 @@ #include #include #include +//#include #include #include @@ -42,13 +43,13 @@ void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); Bookmarks::setupMenus(menubar, menu); + Bookmarks::sortActions(menubar, _bookmarksMenu); } void LocationBookmarks::setHomeLocation() { auto addressManager = DependencyManager::get(); QString bookmarkAddress = addressManager->currentAddress().toString(); Bookmarks::addBookmark(HOME_BOOKMARK, bookmarkAddress); - Bookmarks::sortActions(_bookmarksMenu); } void LocationBookmarks::teleportToBookmark() { @@ -78,7 +79,16 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co QAction* teleportAction = _bookmarksMenu->newAction(); teleportAction->setData(address); connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark())); + if (!_isMenuSorted) { + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); + } else { + // TODO: this is aggressive but all other alternative have proved less fruitful so far. + // having experimented with various pointer types, It is possible the issues are deeper routed in the MenuWrapper/Menu Qt/QML architecture + // further research did not produce better results - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); - Bookmarks::sortActions(_bookmarksMenu); + //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole, + //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); + Bookmarks::sortActions(menubar, _bookmarksMenu); + } } From bec70976d8b562acbb00e8ac09595151d6320deb Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 30 Mar 2017 12:07:19 +0100 Subject: [PATCH 12/39] change hidden overloading --- interface/src/AvatarBookmarks.cpp | 3 ++- interface/src/Bookmarks.cpp | 2 +- interface/src/Bookmarks.h | 4 +--- interface/src/LocationBookmarks.cpp | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index a794c147c3..6b21065328 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -41,6 +41,7 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { Bookmarks::setupMenus(menubar, menu); Bookmarks::sortActions(menubar, _bookmarksMenu); + auto offscreenUi = DependencyManager::get(); auto context = offscreenUi->getRootContext(); context->setContextProperty("avatarBookmarks", this); @@ -68,7 +69,7 @@ void AvatarBookmarks::addBookmark() { auto myAvatar = DependencyManager::get()->getMyAvatar(); const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString(); - Bookmarks::addBookmark(bookmarkName, bookmarkAddress); + Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress); } void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 172bfd29ca..bb109ddc0b 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -67,7 +67,7 @@ void Bookmarks::deleteBookmark() { } } -void Bookmarks::addBookmark(const QString& bookmarkName, const QString& bookmarkAddress) { +void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress) { Menu* menubar = Menu::getInstance(); if (contains(bookmarkName)) { auto offscreenUi = DependencyManager::get(); diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index 9ba2e4f45a..09481d7db4 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -30,10 +30,8 @@ public: virtual void setupMenus(Menu* menubar, MenuWrapper* menu); QString addressForBookmark(const QString& name) const; -public slots: - virtual void addBookmark(const QString& bookmarkName, const QString& bookmarkAddress); - protected: + virtual void addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress); virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0; void enableMenuItems(bool enabled); void readFromFile(); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 436b435bc4..d0c5c4cd8a 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -49,7 +49,7 @@ void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { void LocationBookmarks::setHomeLocation() { auto addressManager = DependencyManager::get(); QString bookmarkAddress = addressManager->currentAddress().toString(); - Bookmarks::addBookmark(HOME_BOOKMARK, bookmarkAddress); + Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress); } void LocationBookmarks::teleportToBookmark() { @@ -72,7 +72,7 @@ void LocationBookmarks::addBookmark() { auto addressManager = DependencyManager::get(); QString bookmarkAddress = addressManager->currentAddress().toString(); - Bookmarks::addBookmark(bookmarkName, bookmarkAddress); + Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress); } void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) { From aa9a2532a99406a13ea5b55667996ffd61f7bcce Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 30 Mar 2017 13:54:33 +0100 Subject: [PATCH 13/39] fix for displaying "Bookmark Avatar" dialog in tablet ui --- .../qml/dialogs/preferences/AvatarPreference.qml | 2 +- interface/src/Application.cpp | 10 +++++++++- interface/src/Application.h | 1 + interface/src/AvatarBookmarks.cpp | 4 ---- interface/src/AvatarBookmarks.h | 4 +++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index 598b367995..bcc5a1d9e6 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -86,7 +86,7 @@ Preference { bottom: parent.bottom rightMargin: hifi.dimensions.contentSpacing.x } - onClickedQueued: avatarBookmarks.addBookmark() + onClickedQueued: ApplicationInterface.loadAddAvatarBookmarkDialog() } Button { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c8b01706fe..58d0042322 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -522,6 +523,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); + DependencyManager::set(); return previousSessionCrashed; } @@ -2000,6 +2002,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); + rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); // Caches rootContext->setContextProperty("AnimationCache", DependencyManager::get().data()); @@ -5481,6 +5484,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get()->getStats().data()); scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); @@ -6352,7 +6356,6 @@ void Application::loadLODToolsDialog() { } else { tablet->pushOntoStack("../../hifi/dialogs/TabletLODTools.qml"); } - } @@ -6402,6 +6405,11 @@ void Application::toggleEntityScriptServerLogDialog() { } } +void Application::loadAddAvatarBookmarkDialog() const { + auto avatarBookmarks = DependencyManager::get(); + avatarBookmarks->addBookmark(); +} + void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) { postLambdaEvent([notify, includeAnimated, aspectRatio, this] { QMediaPlayer* player = new QMediaPlayer(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0123bdaf59..aeb4966066 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -334,6 +334,7 @@ public slots: void toggleEntityScriptServerLogDialog(); void toggleRunningScriptsWidget() const; Q_INVOKABLE void showAssetServerWidget(QString filePath = ""); + Q_INVOKABLE void loadAddAvatarBookmarkDialog() const; void showDialog(const QString& desktopURL, const QString& tabletURL, const QString& name) const; diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 6b21065328..f9d9a18bc9 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -41,10 +41,6 @@ void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { Bookmarks::setupMenus(menubar, menu); Bookmarks::sortActions(menubar, _bookmarksMenu); - - auto offscreenUi = DependencyManager::get(); - auto context = offscreenUi->getRootContext(); - context->setContextProperty("avatarBookmarks", this); } void AvatarBookmarks::changeToBookmarkedAvatar() { diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 958e0e891c..725af88b0d 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -12,10 +12,12 @@ #ifndef hifi_AvatarBookmarks_h #define hifi_AvatarBookmarks_h +#include #include "Bookmarks.h" -class AvatarBookmarks: public Bookmarks { +class AvatarBookmarks: public Bookmarks, public Dependency { Q_OBJECT + SINGLETON_DEPENDENCY public: AvatarBookmarks(); From ae3f04288d446ebc8b1091ff9e36b7ffe2ccf0a0 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 30 Mar 2017 14:56:04 +0100 Subject: [PATCH 14/39] cleanup --- interface/src/AvatarBookmarks.cpp | 4 +--- interface/src/Bookmarks.cpp | 11 +++++------ interface/src/LocationBookmarks.cpp | 8 +++----- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index f9d9a18bc9..85534d6be9 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -75,9 +75,7 @@ void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, cons if (!_isMenuSorted) { menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); } else { - // TODO: this is aggressive but all other alternative have proved less fruitful so far. - // having experimented with various pointer types, It is possible the issues are deeper routed in the MenuWrapper/Menu Qt/QML architecture - // further research did not produce better results + // TODO: this is aggressive but other alternatives have proved less fruitful so far. //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole, //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index bb109ddc0b..b378b0b00f 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -118,16 +118,15 @@ bool Bookmarks::sortOrder(QAction* a, QAction* b) { return a->text().toLower().localeAwareCompare(b->text().toLower()) < 0; } -// TODO: inconsistent naming? -void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menuWrapper) { - QList actions = menuWrapper->actions(); +void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menu) { + QList actions = menu->actions(); qSort(actions.begin(), actions.end(), sortOrder); - for (QAction* action : menuWrapper->actions()) { - menuWrapper->removeAction(action); + for (QAction* action : menu->actions()) { + menu->removeAction(action); //removeBookmarkFromMenu(menubar, action->text()); } for (QAction* action : actions) { - menuWrapper->addAction(action); + menu->addAction(action); // for (int i = 0; i < _bookmarks.size() ; i++) { // if (_bookmarks.keys().at(i) == action->text()) { // addBookmarkToMenu(menubar, action->text(), _bookmarks.values().at(i).toString()); diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index d0c5c4cd8a..99d9219730 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -82,13 +82,11 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co if (!_isMenuSorted) { menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); } else { - // TODO: this is aggressive but all other alternative have proved less fruitful so far. - // having experimented with various pointer types, It is possible the issues are deeper routed in the MenuWrapper/Menu Qt/QML architecture - // further research did not produce better results + // TODO: this is aggressive but other alternatives have proved less fruitful so far. //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole, //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); - Bookmarks::sortActions(menubar, _bookmarksMenu); + menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); + Bookmarks::sortActions(menubar, _bookmarksMenu); } } From 57d6213175675b77e7cf8bf248b19e752372e297 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 30 Mar 2017 19:42:25 +0100 Subject: [PATCH 15/39] remove dead code --- interface/src/AvatarBookmarks.cpp | 3 --- interface/src/Bookmarks.cpp | 6 ------ interface/src/LocationBookmarks.cpp | 3 --- 3 files changed, 12 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 85534d6be9..4ca928bc25 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -76,9 +76,6 @@ void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, cons menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); } else { // TODO: this is aggressive but other alternatives have proved less fruitful so far. - - //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole, - //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); Bookmarks::sortActions(menubar, _bookmarksMenu); } diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index b378b0b00f..776ac3dbb0 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -123,15 +123,9 @@ void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menu) { qSort(actions.begin(), actions.end(), sortOrder); for (QAction* action : menu->actions()) { menu->removeAction(action); - //removeBookmarkFromMenu(menubar, action->text()); } for (QAction* action : actions) { menu->addAction(action); -// for (int i = 0; i < _bookmarks.size() ; i++) { -// if (_bookmarks.keys().at(i) == action->text()) { -// addBookmarkToMenu(menubar, action->text(), _bookmarks.values().at(i).toString()); -// } -// } } _isMenuSorted = true; } diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index 99d9219730..b571637610 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -83,9 +83,6 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); } else { // TODO: this is aggressive but other alternatives have proved less fruitful so far. - - //menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole, - //Bookmarks::getMenuItemLocation(_bookmarksMenu->actions(), name)); menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole); Bookmarks::sortActions(menubar, _bookmarksMenu); } From 8aa3e56ad459ccae10cc5f20230c68bbacdbf5c8 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 30 Mar 2017 19:47:50 +0100 Subject: [PATCH 16/39] remove dead code --- interface/src/AvatarBookmarks.cpp | 1 - interface/src/Bookmarks.h | 1 - interface/src/LocationBookmarks.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 4ca928bc25..5cdfc8213f 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -14,7 +14,6 @@ #include #include #include -//#include #include #include diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index 09481d7db4..6c322197cc 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -40,7 +40,6 @@ protected: int getMenuItemLocation(QList actions, const QString& name) const; QVariantMap _bookmarks; // { name: url, ... } - //QSharedPointer _bookmarksMenu; QPointer _bookmarksMenu; QPointer _deleteBookmarksAction; QString _bookmarksFilename; diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp index b571637610..b79adcf1b7 100644 --- a/interface/src/LocationBookmarks.cpp +++ b/interface/src/LocationBookmarks.cpp @@ -13,7 +13,6 @@ #include #include #include -//#include #include #include From 01b13d7032d51985c965bc14c362c43610d36724 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 4 Apr 2017 18:05:00 +0100 Subject: [PATCH 17/39] fix crash when pressing "Bookmark Avatar" button also modified LocationBookmarks for consistency --- interface/src/Application.cpp | 7 ++++--- interface/src/Application.h | 7 ------- interface/src/Bookmarks.cpp | 1 - interface/src/LocationBookmarks.h | 4 +++- interface/src/Menu.cpp | 8 ++++++-- interface/src/ui/AddressBarDialog.cpp | 4 +++- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58d0042322..36c1dfccdc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -82,6 +82,7 @@ #include #include #include +#include "LocationBookmarks.h" #include #include #include @@ -524,6 +525,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -698,9 +700,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo usleep(USECS_PER_MSEC * 50); // 20hz } - _locationBookmarks = new LocationBookmarks(); // Before setting up the menu - _avatarBookmarks = new AvatarBookmarks(); - // start the nodeThread so its event loop is running QThread* nodeThread = new QThread(this); nodeThread->setObjectName("NodeList Thread"); @@ -2003,6 +2002,7 @@ void Application::initializeUi() { rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance()); rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); + rootContext->setContextProperty("LocationBookmarks", DependencyManager::get().data()); // Caches rootContext->setContextProperty("AnimationCache", DependencyManager::get().data()); @@ -5485,6 +5485,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get()->getStats().data()); scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); diff --git a/interface/src/Application.h b/interface/src/Application.h index aeb4966066..0c06c086bc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -52,8 +52,6 @@ #include "avatar/MyAvatar.h" #include "BandwidthRecorder.h" -#include "LocationBookmarks.h" -#include "AvatarBookmarks.h" #include "Camera.h" #include "ConnectionMonitor.h" #include "gpu/Context.h" @@ -264,8 +262,6 @@ public: glm::mat4 getEyeProjection(int eye) const; QRect getDesirableApplicationGeometry() const; - LocationBookmarks* getLocationBookmarks() const { return _locationBookmarks; } - AvatarBookmarks* getAvatarBookmarks() const { return _avatarBookmarks; } virtual bool canAcceptURL(const QString& url) const override; virtual bool acceptURL(const QString& url, bool defaultUpload = false) override; @@ -605,9 +601,6 @@ private: bool _aboutToQuit; - QPointer _locationBookmarks; - QPointer _avatarBookmarks; - bool _notifiedPacketVersionMismatchThisDomain; QThread _settingsThread; diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 776ac3dbb0..e7af7ea2c9 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -136,7 +136,6 @@ int Bookmarks::getMenuItemLocation(QList actions, const QString& name) if (name.toLower().localeAwareCompare(action->text().toLower()) < 0) { menuItemLocation = actions.indexOf(action); break; - } } return menuItemLocation; diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index b762a0be9d..1324e96574 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -12,10 +12,12 @@ #ifndef hifi_LocationBookmarks_h #define hifi_LocationBookmarks_h +#include #include "Bookmarks.h" -class LocationBookmarks: public Bookmarks { +class LocationBookmarks : public Bookmarks, public Dependency { Q_OBJECT + SINGLETON_DEPENDENCY public: LocationBookmarks(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e63f87bc99..109900f4a6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -32,6 +32,7 @@ #include "assets/ATPAssetMigrator.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" +#include "AvatarBookmarks.h" #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "MainWindow.h" @@ -40,6 +41,7 @@ #include "ui/DialogsManager.h" #include "ui/StandAloneJSConsole.h" #include "InterfaceLogging.h" +#include "LocationBookmarks.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" @@ -195,7 +197,8 @@ Menu::Menu() { qApp, SLOT(resetSensors())); // Avatar > AvatarBookmarks related menus -- Note: the AvatarBookmarks class adds its own submenus here. - qApp->getAvatarBookmarks()->setupMenus(this, avatarMenu); + auto avatarBookmarks = DependencyManager::get(); + avatarBookmarks->setupMenus(this, avatarMenu); // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have @@ -259,7 +262,8 @@ Menu::Menu() { dialogsManager.data(), SLOT(toggleAddressBar())); // Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here. - qApp->getLocationBookmarks()->setupMenus(this, navigateMenu); + auto locationBookmarks = DependencyManager::get(); + locationBookmarks->setupMenus(this, navigateMenu); // Navigate > Copy Address [advanced] auto addressManager = DependencyManager::get(); diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 0534a9f456..8aaaac1a57 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -17,6 +17,7 @@ #include "DependencyManager.h" #include "AddressManager.h" #include "DialogsManager.h" +#include "LocationBookmarks.h" HIFI_QML_DEF(AddressBarDialog) @@ -52,7 +53,8 @@ void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) void AddressBarDialog::loadHome() { qDebug() << "Called LoadHome"; - QString homeLocation = qApp->getLocationBookmarks()->addressForBookmark(LocationBookmarks::HOME_BOOKMARK); + auto locationBookmarks = DependencyManager::get(); + QString homeLocation = locationBookmarks->addressForBookmark(LocationBookmarks::HOME_BOOKMARK); const QString DEFAULT_HOME_LOCATION = "localhost"; if (homeLocation == "") { homeLocation = DEFAULT_HOME_LOCATION; From b4b5d4fe9bb8ee5675bf089be1ce03cb6d26bf77 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 4 Apr 2017 18:15:12 +0100 Subject: [PATCH 18/39] resolve merge conflict --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 36c1dfccdc..fbd8c9e8c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -526,6 +526,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); DependencyManager::set(); + return previousSessionCrashed; } From c739db75621f9f28790ad7cbc3c5d3f743fd8b74 Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 5 Apr 2017 17:39:52 -0400 Subject: [PATCH 19/39] Added quadratic ease-in-and-out smoothing to remote avatars position/orientation updates (through... one path, at least?). --- interface/src/avatar/Avatar.cpp | 57 ++++++++++++++++++++++++++++++--- interface/src/avatar/Avatar.h | 13 ++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ade98c63d8..c1ba0bca65 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -97,7 +97,15 @@ Avatar::Avatar(RigPointer rig) : _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), _initialized(false), - _voiceSphereID(GeometryCache::UNKNOWN_ID) + _voiceSphereID(GeometryCache::UNKNOWN_ID), + _smoothPositionTime(0.15f), + _smoothPositionTimer(std::numeric_limits::max()), + _smoothOrientationTime(0.15f), + _smoothOrientationTimer(std::numeric_limits::max()), + _smoothPositionInitial(), + _smoothPositionTarget(), + _smoothOrientationInitial(), + _smoothOrientationTarget() { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -342,6 +350,25 @@ void Avatar::simulate(float deltaTime, bool inView) { _simulationInViewRate.increment(); } + if (!isMyAvatar()) { + if (_smoothPositionTimer < _smoothPositionTime) { + // Smooth the remote avatar movement. + _smoothPositionTimer += deltaTime; + if (_smoothPositionTimer < _smoothPositionTime) { + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + updateAttitude(); + } + } + + if (_smoothOrientationTimer < _smoothOrientationTime) { + // Smooth the remote avatar movement. + _smoothOrientationTimer += deltaTime; + if (_smoothOrientationTimer < _smoothOrientationTime) { + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + updateAttitude(); + } + } + } PerformanceTimer perfTimer("simulate"); { @@ -1343,13 +1370,33 @@ glm::quat Avatar::getUncachedRightPalmRotation() const { } void Avatar::setPosition(const glm::vec3& position) { - AvatarData::setPosition(position); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setPosition(position); + updateAttitude(); + + return; + } + + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothPositionInitial = getPosition(); + _smoothPositionTarget = position; + _smoothPositionTimer = 0.0f; } void Avatar::setOrientation(const glm::quat& orientation) { - AvatarData::setOrientation(orientation); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setOrientation(orientation); + updateAttitude(); + + return; + } + + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothOrientationInitial = getOrientation(); + _smoothOrientationTarget = orientation; + _smoothOrientationTimer = 0.0f; } void Avatar::updatePalms() { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ba7e1c617e..8d97553039 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -210,6 +210,10 @@ public: bool hasNewJointData() const { return _hasNewJointData; } + inline float easeInOutQuad(float t) { + return((t < 0.5) ? (2*t*t) : (t*(4 - 2*t) - 1)); + } + public slots: // FIXME - these should be migrated to use Pose data instead @@ -292,6 +296,15 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; + // Smoothing data for blending from one position/orientation to another on remote agents. + float _smoothPositionTime; + float _smoothPositionTimer; + float _smoothOrientationTime; + float _smoothOrientationTimer; + glm::vec3 _smoothPositionInitial; + glm::vec3 _smoothPositionTarget; + glm::quat _smoothOrientationInitial; + glm::quat _smoothOrientationTarget; private: class AvatarEntityDataHash { From 43b3a6c6246a954b81302f6dd0b1d9c67aa253c8 Mon Sep 17 00:00:00 2001 From: trent Date: Wed, 5 Apr 2017 21:31:13 -0400 Subject: [PATCH 20/39] Addressing some style inconsitency issues, as well as making the position/orientation times constants. --- interface/src/avatar/Avatar.cpp | 92 ++++++++++++++++----------------- interface/src/avatar/Avatar.h | 3 ++ 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c1ba0bca65..08f5c856b8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -98,14 +98,14 @@ Avatar::Avatar(RigPointer rig) : _moving(false), _initialized(false), _voiceSphereID(GeometryCache::UNKNOWN_ID), - _smoothPositionTime(0.15f), - _smoothPositionTimer(std::numeric_limits::max()), - _smoothOrientationTime(0.15f), - _smoothOrientationTimer(std::numeric_limits::max()), - _smoothPositionInitial(), - _smoothPositionTarget(), - _smoothOrientationInitial(), - _smoothOrientationTarget() + _smoothPositionTime(SMOOTH_TIME_POSITION), + _smoothPositionTimer(std::numeric_limits::max()), + _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), + _smoothOrientationTimer(std::numeric_limits::max()), + _smoothPositionInitial(), + _smoothPositionTarget(), + _smoothOrientationInitial(), + _smoothOrientationTarget() { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -350,25 +350,25 @@ void Avatar::simulate(float deltaTime, bool inView) { _simulationInViewRate.increment(); } - if (!isMyAvatar()) { - if (_smoothPositionTimer < _smoothPositionTime) { - // Smooth the remote avatar movement. - _smoothPositionTimer += deltaTime; - if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); - updateAttitude(); - } - } + if (!isMyAvatar()) { + if (_smoothPositionTimer < _smoothPositionTime) { + // Smooth the remote avatar movement. + _smoothPositionTimer += deltaTime; + if (_smoothPositionTimer < _smoothPositionTime) { + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + updateAttitude(); + } + } - if (_smoothOrientationTimer < _smoothOrientationTime) { - // Smooth the remote avatar movement. - _smoothOrientationTimer += deltaTime; - if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); - updateAttitude(); - } - } - } + if (_smoothOrientationTimer < _smoothOrientationTime) { + // Smooth the remote avatar movement. + _smoothOrientationTimer += deltaTime; + if (_smoothOrientationTimer < _smoothOrientationTime) { + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + updateAttitude(); + } + } + } PerformanceTimer perfTimer("simulate"); { @@ -1370,33 +1370,33 @@ glm::quat Avatar::getUncachedRightPalmRotation() const { } void Avatar::setPosition(const glm::vec3& position) { - if (isMyAvatar()) { - // This is the local avatar, no need to handle any position smoothing. - AvatarData::setPosition(position); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setPosition(position); + updateAttitude(); - return; - } + return; + } - // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. - _smoothPositionInitial = getPosition(); - _smoothPositionTarget = position; - _smoothPositionTimer = 0.0f; + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothPositionInitial = getPosition(); + _smoothPositionTarget = position; + _smoothPositionTimer = 0.0f; } void Avatar::setOrientation(const glm::quat& orientation) { - if (isMyAvatar()) { - // This is the local avatar, no need to handle any position smoothing. - AvatarData::setOrientation(orientation); - updateAttitude(); + if (isMyAvatar()) { + // This is the local avatar, no need to handle any position smoothing. + AvatarData::setOrientation(orientation); + updateAttitude(); - return; - } + return; + } - // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. - _smoothOrientationInitial = getOrientation(); - _smoothOrientationTarget = orientation; - _smoothOrientationTimer = 0.0f; + // Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position. + _smoothOrientationInitial = getOrientation(); + _smoothOrientationTarget = orientation; + _smoothOrientationTimer = 0.0f; } void Avatar::updatePalms() { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 8d97553039..e0bdeff411 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -228,6 +228,9 @@ public slots: protected: friend class AvatarManager; + const float SMOOTH_TIME_POSITION = 0.125f; + const float SMOOTH_TIME_ORIENTATION = 0.075f; + virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send. QString _empty{}; virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter! From 76d3e6d5983e4e8fc46428b47d3cd26459272b33 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 6 Apr 2017 13:21:59 -0400 Subject: [PATCH 21/39] Added an assert for out-of-bounds values in the smoothing function; also clamped the values that I was sending in on the avatar-side. --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Avatar.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 08f5c856b8..a4ab999a9c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -355,7 +355,7 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothPositionTimer += deltaTime; if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(_smoothPositionTimer / _smoothPositionTime))); + AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))); updateAttitude(); } } @@ -364,7 +364,7 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothOrientationTimer += deltaTime; if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(_smoothOrientationTimer / _smoothOrientationTime))); + AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))); updateAttitude(); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index e0bdeff411..ed6bd96a75 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -211,7 +211,9 @@ public: bool hasNewJointData() const { return _hasNewJointData; } inline float easeInOutQuad(float t) { - return((t < 0.5) ? (2*t*t) : (t*(4 - 2*t) - 1)); + assert(!((t < 0.0f) || (t > 1.0f))); + + return((t < 0.5f) ? (2.0f*t*t) : (t*(4.0f - 2.0f*t) - 1.0f)); } public slots: From 21f810e040ac8d0eace476c2223493a7d7791d32 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 6 Apr 2017 14:50:16 -0400 Subject: [PATCH 22/39] Fixed formatting concerns as well as a benign order-of-constructor warning. --- interface/src/avatar/Avatar.cpp | 24 ++++++++++++++--------- interface/src/avatar/Avatar.h | 34 ++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a4ab999a9c..4b427e8221 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -97,15 +97,15 @@ Avatar::Avatar(RigPointer rig) : _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), _initialized(false), - _voiceSphereID(GeometryCache::UNKNOWN_ID), - _smoothPositionTime(SMOOTH_TIME_POSITION), + _smoothPositionTime(SMOOTH_TIME_POSITION), _smoothPositionTimer(std::numeric_limits::max()), - _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), + _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), _smoothOrientationTimer(std::numeric_limits::max()), _smoothPositionInitial(), _smoothPositionTarget(), _smoothOrientationInitial(), - _smoothOrientationTarget() + _smoothOrientationTarget(), + _voiceSphereID(GeometryCache::UNKNOWN_ID) { // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); @@ -355,7 +355,11 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothPositionTimer += deltaTime; if (_smoothPositionTimer < _smoothPositionTime) { - AvatarData::setPosition(lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))); + AvatarData::setPosition( + lerp(_smoothPositionInitial, + _smoothPositionTarget, + easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f))) + ); updateAttitude(); } } @@ -364,8 +368,12 @@ void Avatar::simulate(float deltaTime, bool inView) { // Smooth the remote avatar movement. _smoothOrientationTimer += deltaTime; if (_smoothOrientationTimer < _smoothOrientationTime) { - AvatarData::setOrientation(slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))); - updateAttitude(); + AvatarData::setOrientation( + slerp(_smoothOrientationInitial, + _smoothOrientationTarget, + easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f))) + ); + updateAttitude(); } } } @@ -1374,7 +1382,6 @@ void Avatar::setPosition(const glm::vec3& position) { // This is the local avatar, no need to handle any position smoothing. AvatarData::setPosition(position); updateAttitude(); - return; } @@ -1389,7 +1396,6 @@ void Avatar::setOrientation(const glm::quat& orientation) { // This is the local avatar, no need to handle any position smoothing. AvatarData::setOrientation(orientation); updateAttitude(); - return; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ed6bd96a75..2091ab4208 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -210,11 +210,15 @@ public: bool hasNewJointData() const { return _hasNewJointData; } - inline float easeInOutQuad(float t) { - assert(!((t < 0.0f) || (t > 1.0f))); + inline float easeInOutQuad(float lerpValue) { + assert(!((lerpValue < 0.0f) || (lerpValue > 1.0f))); - return((t < 0.5f) ? (2.0f*t*t) : (t*(4.0f - 2.0f*t) - 1.0f)); - } + if (lerpValue < 0.5f) { + return (2.0f * lerpValue * lerpValue); + } + + return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f); + } public slots: @@ -230,8 +234,8 @@ public slots: protected: friend class AvatarManager; - const float SMOOTH_TIME_POSITION = 0.125f; - const float SMOOTH_TIME_ORIENTATION = 0.075f; + const float SMOOTH_TIME_POSITION = 0.125f; + const float SMOOTH_TIME_ORIENTATION = 0.075f; virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send. QString _empty{}; @@ -301,15 +305,15 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; - // Smoothing data for blending from one position/orientation to another on remote agents. - float _smoothPositionTime; - float _smoothPositionTimer; - float _smoothOrientationTime; - float _smoothOrientationTimer; - glm::vec3 _smoothPositionInitial; - glm::vec3 _smoothPositionTarget; - glm::quat _smoothOrientationInitial; - glm::quat _smoothOrientationTarget; + // Smoothing data for blending from one position/orientation to another on remote agents. + float _smoothPositionTime; + float _smoothPositionTimer; + float _smoothOrientationTime; + float _smoothOrientationTimer; + glm::vec3 _smoothPositionInitial; + glm::vec3 _smoothPositionTarget; + glm::quat _smoothOrientationInitial; + glm::quat _smoothOrientationTarget; private: class AvatarEntityDataHash { From 584905a618f0abaaab12b38072b0d2c586ceb27a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Apr 2017 15:41:35 -0700 Subject: [PATCH 23/39] fix warning --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b427e8221..92b0d40f93 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -96,7 +96,6 @@ Avatar::Avatar(RigPointer rig) : _lastOrientation(), _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), - _initialized(false), _smoothPositionTime(SMOOTH_TIME_POSITION), _smoothPositionTimer(std::numeric_limits::max()), _smoothOrientationTime(SMOOTH_TIME_ORIENTATION), @@ -105,6 +104,7 @@ Avatar::Avatar(RigPointer rig) : _smoothPositionTarget(), _smoothOrientationInitial(), _smoothOrientationTarget(), + _initialized(false), _voiceSphereID(GeometryCache::UNKNOWN_ID) { // we may have been created in the network thread, but we live in the main thread From 4c2823b42df7a724e8bd978be27c10f7680cba6c Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Fri, 7 Apr 2017 18:21:43 +0100 Subject: [PATCH 24/39] change increment operator --- interface/src/Bookmarks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index e7af7ea2c9..4cbc17f8ce 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -44,7 +44,7 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { void Bookmarks::deleteBookmark() { QStringList bookmarkList; QList menuItems = _bookmarksMenu->actions(); - for (int i = 0; i < menuItems.count(); i += 1) { + for (int i = 0; i < menuItems.count(); ++i) { bookmarkList.append(menuItems[i]->text()); } From 01ad010dc9fa597408ca1d4e7c70f1cc7cbfd68d Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Apr 2017 16:07:14 -0700 Subject: [PATCH 25/39] Cherry picking the fix for the new nv driver --- libraries/render-utils/src/LightAmbient.slh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 15e23015cb..a82dfd577e 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -82,13 +82,12 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie <@if supportScattering@> - float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; - float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; - ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); - - obscurance = min(obscurance, ambientOcclusion); - if (scattering * isScatteringEnabled() > 0.0) { + float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; + float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; + ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); + + obscurance = min(obscurance, ambientOcclusion); // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; From b2f463180df79b9a07a000983968e3f6199c19f7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 12 Apr 2017 03:44:24 +0200 Subject: [PATCH 26/39] fix teleport cool-in, added missing TARGETTING state and some ESLINT style fixes --- scripts/system/controllers/teleport.js | 63 ++++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 33c0b3116e..dcbcaeb621 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -29,13 +29,13 @@ var COLORS_TELEPORT_SEAT = { red: 255, green: 0, blue: 170 -} +}; var COLORS_TELEPORT_CAN_TELEPORT = { red: 97, green: 247, blue: 255 -} +}; var COLORS_TELEPORT_CANNOT_TELEPORT = { red: 0, @@ -52,7 +52,7 @@ var COLORS_TELEPORT_CANCEL = { var TELEPORT_CANCEL_RANGE = 1; var COOL_IN_DURATION = 500; -const handInfo = { +var handInfo = { right: { controllerInput: Controller.Standard.RightHand }, @@ -80,7 +80,7 @@ function Trigger(hand) { this.down = function() { var down = _this.buttonValue === 1 ? 1.0 : 0.0; - return down + return down; }; } @@ -90,8 +90,9 @@ var ignoredEntities = []; var TELEPORTER_STATES = { IDLE: 'idle', COOL_IN: 'cool_in', + TARGETTING: 'targetting', TARGETTING_INVALID: 'targetting_invalid', -} +}; var TARGET = { NONE: 'none', // Not currently targetting anything @@ -99,7 +100,7 @@ var TARGET = { INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.) SURFACE: 'surface', // The current target is a valid surface SEAT: 'seat', // The current target is a seat -} +}; function Teleporter() { var _this = this; @@ -114,8 +115,8 @@ function Teleporter() { this.updateConnected = null; this.activeHand = null; - this.telporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); - this.teleportMappingInternal = Controller.newMapping(this.telporterMappingInternalName); + this.teleporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); + this.teleportMappingInternal = Controller.newMapping(this.teleporterMappingInternalName); // Setup overlays this.cancelOverlay = Overlays.addOverlay("model", { @@ -135,11 +136,11 @@ function Teleporter() { }); this.enableMappings = function() { - Controller.enableMapping(this.telporterMappingInternalName); + Controller.enableMapping(this.teleporterMappingInternalName); }; this.disableMappings = function() { - Controller.disableMapping(teleporter.telporterMappingInternalName); + Controller.disableMapping(teleporter.teleporterMappingInternalName); }; this.cleanup = function() { @@ -179,7 +180,7 @@ function Teleporter() { if (_this.state === TELEPORTER_STATES.COOL_IN) { _this.state = TELEPORTER_STATES.TARGETTING; } - }, COOL_IN_DURATION) + }, COOL_IN_DURATION); this.activeHand = hand; this.enableMappings(); @@ -203,13 +204,13 @@ function Teleporter() { }; this.deleteOverlayBeams = function() { - for (key in this.overlayLines) { + for (var key in this.overlayLines) { if (this.overlayLines[key] !== null) { Overlays.deleteOverlay(this.overlayLines[key]); this.overlayLines[key] = null; } } - } + }; this.update = function() { if (_this.state === TELEPORTER_STATES.IDLE) { @@ -272,7 +273,8 @@ function Teleporter() { this.hideCancelOverlay(); this.hideSeatOverlay(); - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CAN_TELEPORT); + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, + COLORS_TELEPORT_CAN_TELEPORT); this.updateDestinationOverlay(this.targetOverlay, intersection); } } else if (teleportLocationType === TARGET.SEAT) { @@ -284,13 +286,15 @@ function Teleporter() { } - if (((_this.activeHand == 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { + if (((_this.activeHand === 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { + // remember the state before we exit teleport mode and set it back to IDLE + var previousState = this.state; this.exitTeleportMode(); this.hideCancelOverlay(); this.hideTargetOverlay(); this.hideSeatOverlay(); - if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || this.state === TELEPORTER_STATES.COOL_IN) { + if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || previousState === TELEPORTER_STATES.COOL_IN) { // Do nothing } else if (teleportLocationType === TARGET.SEAT) { Entities.callEntityMethod(intersection.entityID, 'sit'); @@ -321,7 +325,7 @@ function Teleporter() { this.overlayLines[hand] = Overlays.addOverlay("line3d", lineProperties); } else { - var success = Overlays.editOverlay(this.overlayLines[hand], { + Overlays.editOverlay(this.overlayLines[hand], { start: closePoint, end: farPoint, color: color @@ -361,7 +365,7 @@ function Teleporter() { }; } -//related to repositioning the avatar after you teleport +// related to repositioning the avatar after you teleport function getAvatarFootOffset() { var data = getJointData(); var upperLeg, lowerLeg, foot, toe, toeTop; @@ -384,14 +388,14 @@ function getAvatarFootOffset() { var offset = upperLeg + lowerLeg + foot + toe + toeTop; offset = offset / 100; return offset; -}; +} function getJointData() { var allJointData = []; var jointNames = MyAvatar.jointNames; jointNames.forEach(function(joint, index) { var translation = MyAvatar.getJointTranslation(index); - var rotation = MyAvatar.getJointRotation(index) + var rotation = MyAvatar.getJointRotation(index); allJointData.push({ joint: joint, index: index, @@ -401,7 +405,7 @@ function getJointData() { }); return allJointData; -}; +} var leftPad = new ThumbPad('left'); var rightPad = new ThumbPad('right'); @@ -420,7 +424,7 @@ function isMoving() { } else { return false; } -}; +} function parseJSON(json) { try { @@ -433,7 +437,7 @@ function parseJSON(json) { // point that is being intersected with is looked at. If this normal is more // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), then // you can't teleport there. -const MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; +var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; function getTeleportTargetType(intersection) { if (!intersection.intersects) { return TARGET.NONE; @@ -465,7 +469,7 @@ function getTeleportTargetType(intersection) { } else { return TARGET.SURFACE; } -}; +} function registerMappings() { mappingName = 'Hifi-Teleporter-Dev-' + Math.random(); @@ -487,7 +491,7 @@ function registerMappings() { if (isMoving() === true) { return; } - teleporter.enterTeleportMode('left') + teleporter.enterTeleportMode('left'); return; }); teleportMapping.from(Controller.Standard.RightPrimaryThumb) @@ -502,10 +506,10 @@ function registerMappings() { return; } - teleporter.enterTeleportMode('right') + teleporter.enterTeleportMode('right'); return; }); -}; +} registerMappings(); @@ -521,7 +525,6 @@ Script.scriptEnding.connect(cleanup); var isDisabled = false; var handleTeleportMessages = function(channel, message, sender) { - var data; if (sender === MyAvatar.sessionUUID) { if (channel === 'Hifi-Teleport-Disabler') { if (message === 'both') { @@ -531,7 +534,7 @@ var handleTeleportMessages = function(channel, message, sender) { isDisabled = 'left'; } if (message === 'right') { - isDisabled = 'right' + isDisabled = 'right'; } if (message === 'none') { isDisabled = false; @@ -545,7 +548,7 @@ var handleTeleportMessages = function(channel, message, sender) { } } } -} +}; Messages.subscribe('Hifi-Teleport-Disabler'); Messages.subscribe('Hifi-Teleport-Ignore-Add'); From 2d1d207c9be1bb3f2f06e3581e21d754bf5ba0a0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 12 Apr 2017 10:54:28 -0700 Subject: [PATCH 27/39] lol --- interface/src/avatar/Head.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 4c6aa10d12..282acf6bf5 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -77,7 +77,7 @@ void Head::simulate(float deltaTime, bool isMine) { float audioLoudness = 0.0f; if (_owningAvatar) { - _owningAvatar->getAudioLoudness(); + audioLoudness = _owningAvatar->getAudioLoudness(); } // Update audio trailing average for rendering facial animations From 6cb88c31f35c9557c6ee7a7be3648f21bd31cdcd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 11 Apr 2017 15:02:27 -0700 Subject: [PATCH 28/39] AvatarMixer sends min updates for out-of-view avatars --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 05de209e81..c4497a1066 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -325,7 +325,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { _stats.overBudgetAvatars++; detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; } else if (!isInView) { - detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; + detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::MinimumData; nodeData->incrementAvatarOutOfView(); } else { detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO From e751080f640ed06522283cc9fa7c5dee1edb18ca Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 11 Apr 2017 15:03:11 -0700 Subject: [PATCH 29/39] update model transform even when out of view --- interface/src/avatar/SkeletonModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d7dd93cedf..0c11fa456d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -240,8 +240,8 @@ void SkeletonModel::updateAttitude() { // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), // but just before head has been simulated. void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { + updateAttitude(); if (fullUpdate) { - updateAttitude(); setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); Model::simulate(deltaTime, fullUpdate); From 7189d4d7fafc77536661623c70ee657c1d1af7bd Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 14 Apr 2017 17:01:23 +0100 Subject: [PATCH 30/39] daving web work --- .../qml/controls/TabletWebButton.qml | 53 ++++ .../resources/qml/controls/TabletWebView.qml | 272 +++++++++++------- .../qml/hifi/tablet/TabletAddressDialog.qml | 10 +- .../HFTabletWebEngineRequestInterceptor.cpp | 12 +- 4 files changed, 236 insertions(+), 111 deletions(-) create mode 100644 interface/resources/qml/controls/TabletWebButton.qml diff --git a/interface/resources/qml/controls/TabletWebButton.qml b/interface/resources/qml/controls/TabletWebButton.qml new file mode 100644 index 0000000000..a5876d08dd --- /dev/null +++ b/interface/resources/qml/controls/TabletWebButton.qml @@ -0,0 +1,53 @@ +// +// TabletWebButton.qml +// +// Created by Dante Ruiz on 2017/4/13 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.4 +import "../styles-uit" + +Rectangle { + property alias text: label.text + property alias pixelSize: label.font.pixelSize; + property bool selected: false + property bool hovered: false + property bool enabled: false + property int spacing: 2 + property var action: function () {} + property string enabledColor: hifi.colors.blueHighlight + property string disabledColor: hifi.colors.blueHighlight + property string highlightColor: hifi.colors.blueHighlight; + width: label.width + 64 + height: 32 + color: hifi.colors.white + HifiConstants { id: hifi } + RalewaySemiBold { + id: label; + color: enabledColor + font.pixelSize: 15; + anchors { + horizontalCenter: parent.horizontalCenter; + verticalCenter: parent.verticalCenter; + } + } + + + Rectangle { + id: indicator + width: parent.width + height: selected ? 3 : 1 + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + color: hifi.colors.blueHighlight + visible: parent.selected || hovered + } +} diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 93e693ab2f..7e2e6d0a26 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -2,97 +2,81 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.2 import QtWebChannel 1.0 +import HFTabletWebEngineProfile 1.0 import "../controls-uit" as HiFiControls import "../styles" as HifiStyles import "../styles-uit" -import HFWebEngineProfile 1.0 -import HFTabletWebEngineProfile 1.0 import "../" +import "." Item { id: web + HifiConstants { id: hifi } width: parent.width height: parent.height property var parentStackItem: null - property int headerHeight: 38 + property int headerHeight: 70 property string url - property string address: url //for compatibility + property alias address: displayUrl.text //for compatibility property string scriptURL property alias eventBridge: eventBridgeWrapper.eventBridge property bool keyboardEnabled: HMD.active property bool keyboardRaised: false property bool punctuationMode: false property bool isDesktop: false - property WebEngineView view: loader.currentView property int currentPage: -1 // used as a model for repeater property alias pagesModel: pagesModel - Row { + Rectangle { id: buttons - HifiConstants { id: hifi } - HifiStyles.HifiConstants { id: hifistyles } - height: headerHeight - spacing: 4 - anchors.top: parent.top - anchors.topMargin: 8 - anchors.left: parent.left - anchors.leftMargin: 8 - HiFiGlyphs { - id: back; - enabled: currentPage >= 0 - text: hifi.glyphs.backward - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: goBack() } - } - - HiFiGlyphs { - id: forward; - enabled: currentPage < pagesModel.count - 1 - text: hifi.glyphs.forward - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: goForward() } - } - - HiFiGlyphs { - id: reload; - enabled: view != null; - text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload - color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: reloadPage(); } - } - - } + width: parent.width + height: parent.headerHeight + color: hifi.colors.white - TextField { - id: addressBar - height: 30 - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.left: buttons.right - anchors.leftMargin: 0 - anchors.verticalCenter: buttons.verticalCenter - focus: true - text: address - Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i") + Row { + id: nav + anchors { + top: parent.top + topMargin: 10 + horizontalCenter: parent.horizontalCenter + } + spacing: 120 + + TabletWebButton { + id: back + enabledColor: hifi.colors.baseGray + enabled: false + text: "BACK" - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Enter: - case Qt.Key_Return: - event.accepted = true; - if (text.indexOf("http") != 0) { - text = "http://" + text; - } - //root.hidePermissionsBar(); - web.keyboardRaised = false; - gotoPage(text); - break; + MouseArea { + anchors.fill: parent + onClicked: goBack() + hoverEnabled: true + + } + } - + TabletWebButton { + id: close + enabledColor: hifi.colors.darkGray + text: "CLOSE" + + MouseArea { + anchors.fill: parent + onClicked: closeWebEngine() + } + } + } + + + RalewaySemiBold { + id: displayUrl + color: hifi.colors.baseGray + font.pixelSize: 12 + anchors { + top: nav.bottom + horizontalCenter: parent.horizontalCenter; } } } @@ -100,15 +84,30 @@ Item { ListModel { id: pagesModel onCountChanged: { - currentPage = count - 1 + currentPage = count - 1; + if (currentPage > 0) { + back.enabledColor = hifi.colors.darkGray; + } else { + back.enabledColor = hifi.colors.baseGray; + } } } function goBack() { - if (currentPage > 0) { - currentPage--; - } else if (parentStackItem) { + if (webview.canGoBack) { + pagesModel.remove(currentPage); + webview.goBack(); + } else if (currentPage > 0) { + pagesModel.remove(currentPage); + } + } + + + function closeWebEngine() { + if (parentStackItem) { parentStackItem.pop(); + } else { + web.visible = false; } } @@ -130,18 +129,22 @@ Item { function urlAppend(url) { var lurl = decodeURIComponent(url) - if (lurl[lurl.length - 1] !== "/") + if (lurl[lurl.length - 1] !== "/") { lurl = lurl + "/" - if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== lurl) { - pagesModel.append({webUrl: lurl}) + } + console.log("-------------> is time running " + timer.running + " <--------------"); + if (currentPage === -1 || (pagesModel.get(currentPage).webUrl !== lurl && !timer.running)) { + console.log("---------> appending the url ----------> " + lurl); + timer.start(); + pagesModel.append({webUrl: lurl}); } } onCurrentPageChanged: { - if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) { - loader.item.url = pagesModel.get(currentPage).webUrl - web.url = loader.item.url - web.address = loader.item.url + if (currentPage >= 0 && currentPage < pagesModel.count) { + webview.url = pagesModel.get(currentPage).webUrl; + web.url = webview.url; + web.address = webview.url; } } @@ -155,45 +158,110 @@ Item { property var eventBridge; } - Loader { - id: loader + Timer { + id: timer + interval: 100 + running: false + repeat: false + onTriggered: timer.stop(); + } - property WebEngineView currentView: null + + + WebEngineView { + id: webview + objectName: "webEngineView" + x: 0 + y: 0 width: parent.width - height: parent.height - web.headerHeight - asynchronous: true + height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight anchors.top: buttons.bottom - active: false - source: "../TabletBrowser.qml" - onStatusChanged: { - if (loader.status === Loader.Ready) { - currentView = item.webView - item.webView.userScriptUrl = web.scriptURL - if (currentPage >= 0) { - //we got something to load already - item.url = pagesModel.get(currentPage).webUrl - web.address = loader.item.url + profile: HFTabletWebEngineProfile { + id: webviewTabletProfile + storageName: "qmlTabletWebEngine" + } + + property string userScriptUrl: "" + + // creates a global EventBridge object. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // detects when to raise and lower virtual keyboard + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + // User script. + WebEngineScript { + id: userScript + sourceUrl: webview.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + property string newUrl: "" + + webChannel.registeredObjects: [eventBridgeWrapper] + + Component.onCompleted: { + // Ensure the JS from the web-engine makes it to our logging + webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { + console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); + }); + + webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + web.address = url; + } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + + onLoadingChanged: { + keyboardRaised = false; + punctuationMode = false; + keyboard.resetShiftMode(false); + + // Required to support clicking on "hifi://" links + if (WebEngineView.LoadStartedStatus == loadRequest.status) { + urlAppend(loadRequest.url.toString()) + var url = loadRequest.url.toString(); + if (urlHandler.canHandleUrl(url)) { + if (urlHandler.handleUrl(url)) { + root.stop(); + } } } } - } + onNewViewRequested: { + request.openIn(webview); + } + } + Component.onCompleted: { web.isDesktop = (typeof desktop !== "undefined"); address = url; - loader.active = true } - Keys.onPressed: { + Keys.onPressed: { switch(event.key) { - case Qt.Key_L: - if (event.modifiers == Qt.ControlModifier) { - event.accepted = true - addressBar.selectAll() - addressBar.forceActiveFocus() - } - break; + case Qt.Key_L: + if (event.modifiers == Qt.ControlModifier) { + event.accepted = true + } + break; } } } diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 356ff92664..ab28b84a3d 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -35,8 +35,8 @@ StackView { property var tablet: null; property bool isDesktop: false; - - Component { id: tabletStoryCard; TabletStoryCard {} } + + Component { id: tabletWebView; TabletWebView {} } Component.onCompleted: { root.currentItem.focus = true; root.currentItem.forceActiveFocus(); @@ -68,9 +68,9 @@ StackView { } function goCard(targetString) { if (0 !== targetString.indexOf('hifi://')) { - var card = tabletStoryCard.createObject(); - card.setUrl(addressBarDialog.metaverseServerUrl + targetString); - card.eventBridge = root.eventBridge; + var card = tabletWebView.createObject(); + card.url = addressBarDialog.metaverseServerUrl + targetString; + card.parentStackItem = root; root.push(card); return; } diff --git a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp b/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp index 7282fb5e3d..fd79fc1cb6 100644 --- a/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFTabletWebEngineRequestInterceptor.cpp @@ -34,9 +34,13 @@ void HFTabletWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestI QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); } - } - static const QString USER_AGENT = "User-Agent"; - QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; - info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + static const QString USER_AGENT = "User-Agent"; + QString tokenString = "Chrome/48.0 (HighFidelityInterface)"; + info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + } else { + static const QString USER_AGENT = "User-Agent"; + QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit()); + } } From 863d64b2fd915d2a9ff51ca99bd7020ebb8714e2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 14 Apr 2017 18:06:44 +0100 Subject: [PATCH 31/39] removed comments and non-needed files --- .../resources/qml/controls/TabletWebView.qml | 2 - .../qml/hifi/tablet/TabletStoryCard.qml | 46 ------------------- 2 files changed, 48 deletions(-) delete mode 100644 interface/resources/qml/hifi/tablet/TabletStoryCard.qml diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 7e2e6d0a26..9a08e8b866 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -132,9 +132,7 @@ Item { if (lurl[lurl.length - 1] !== "/") { lurl = lurl + "/" } - console.log("-------------> is time running " + timer.running + " <--------------"); if (currentPage === -1 || (pagesModel.get(currentPage).webUrl !== lurl && !timer.running)) { - console.log("---------> appending the url ----------> " + lurl); timer.start(); pagesModel.append({webUrl: lurl}); } diff --git a/interface/resources/qml/hifi/tablet/TabletStoryCard.qml b/interface/resources/qml/hifi/tablet/TabletStoryCard.qml deleted file mode 100644 index 1d57c8a083..0000000000 --- a/interface/resources/qml/hifi/tablet/TabletStoryCard.qml +++ /dev/null @@ -1,46 +0,0 @@ -// -// TabletAddressDialog.qml -// -// Created by Dante Ruiz on 2017/04/24 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import Hifi 1.0 -import QtQuick 2.4 -import QtGraphicalEffects 1.0 -import "../../controls" -import "../../styles" -import "../../windows" -import "../" -import "../toolbars" -import "../../styles-uit" as HifiStyles -import "../../controls-uit" as HifiControlsUit -import "../../controls" as HifiControls - - -Rectangle { - id: cardRoot - HifiStyles.HifiConstants { id: hifi } - width: parent.width - height: parent.height - property string address: "" - property alias eventBridge: webview.eventBridge - function setUrl(url) { - cardRoot.address = url; - webview.url = url; - } - - HifiControls.TabletWebView { - id: webview - parentStackItem: root - anchors { - top: parent.top - right: parent.right - left: parent.left - bottom: parent.bottom - } - } -} From eaefa3d3f28ef260b7fe89ffd212cf1dee956d91 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 13:35:59 -0700 Subject: [PATCH 32/39] avatar-mixer resends to avoid stale avatar --- .../src/avatars/AvatarMixerSlave.cpp | 21 ++++++++++++++----- libraries/avatars/src/AvatarData.h | 7 +++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index c4497a1066..a4e9b608de 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -175,6 +175,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { } }); + const uint64_t MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR = (AVATAR_UPDATE_TIMEOUT - 1) * USECS_PER_SECOND; AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); std::priority_queue sortedAvatars; @@ -262,11 +263,17 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // have 15 (45hz-30hz) duplicate frames. In this case, the stat // avg_other_av_skips_per_second does report 15. // - // make sure we haven't already sent this data from this sender to this receiver + // make sure we haven't already sent this data from this sender to that receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - ++numAvatarsHeldBack; - shouldIgnore = true; + // don't ignore this avatar if we haven't sent any update for a long while + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); + const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); + if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && + lastBroadcastTime > startIgnoreCalculation - MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { + ++numAvatarsHeldBack; + shouldIgnore = true; + } } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -302,8 +309,12 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO - // the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A. - if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) { + // the time that Avatar B flagged an IDENTITY DATA change + // or if no packet of any type has been sent for some time + // send IDENTITY DATA about Avatar B to Avatar A + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); + if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || + startAvatarDataPacking > lastBroadcastTime + MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5ade0c448e..8319eb5249 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -110,6 +110,8 @@ const char LEFT_HAND_POINTING_FLAG = 1; const char RIGHT_HAND_POINTING_FLAG = 2; const char IS_FINGER_POINTING_FLAG = 4; +const qint64 AVATAR_UPDATE_TIMEOUT = 5 * USECS_PER_SECOND; + // AvatarData state flags - we store the details about the packet encoding in the first byte, // before the "header" structure const char AVATARDATA_FLAGS_MINIMUM = 0; @@ -599,10 +601,7 @@ public: } - bool shouldDie() const { - const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND; - return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; - } + bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_UPDATE_TIMEOUT; } static const float OUT_OF_VIEW_PENALTY; From d72f6cf45e9f8f2c8a0d11190453b7901e434763 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 13:37:18 -0700 Subject: [PATCH 33/39] avatar-mixer to send identity packets as 'reliable' --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index a4e9b608de..56c15f7793 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -69,7 +69,7 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { int bytesSent = 0; QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size()); + auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size(), true, true); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious bytesSent += individualData.size(); identityPacket->write(individualData); From 06b9fd6a7e14ca3dd4d87ca2bedc2fbc9fb10321 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 14:55:08 -0700 Subject: [PATCH 34/39] don't keep stale avatars alive --- .../src/avatars/AvatarMixerSlave.cpp | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 56c15f7793..ee3282f82b 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -67,15 +67,13 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { - int bytesSent = 0; QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size(), true, true); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious - bytesSent += individualData.size(); - identityPacket->write(individualData); - DependencyManager::get()->sendPacket(std::move(identityPacket), *destinationNode); + auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true); + identityPackets->write(individualData); + DependencyManager::get()->sendPacketList(std::move(identityPackets), *destinationNode); _stats.numIdentityPackets++; - return bytesSent; + return individualData.size(); } static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45; @@ -175,7 +173,6 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { } }); - const uint64_t MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR = (AVATAR_UPDATE_TIMEOUT - 1) * USECS_PER_SECOND; AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); std::priority_queue sortedAvatars; @@ -263,17 +260,11 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // have 15 (45hz-30hz) duplicate frames. In this case, the stat // avg_other_av_skips_per_second does report 15. // - // make sure we haven't already sent this data from this sender to that receiver + // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - // don't ignore this avatar if we haven't sent any update for a long while - uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); - const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); - if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && - lastBroadcastTime > startIgnoreCalculation - MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { - ++numAvatarsHeldBack; - shouldIgnore = true; - } + ++numAvatarsHeldBack; + shouldIgnore = true; } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -312,9 +303,10 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // the time that Avatar B flagged an IDENTITY DATA change // or if no packet of any type has been sent for some time // send IDENTITY DATA about Avatar B to Avatar A + const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || - startAvatarDataPacking > lastBroadcastTime + MIN_KEEP_ALIVE_PERIOD_FOR_OTHER_AVATAR) { + startAvatarDataPacking > lastBroadcastTime + AVATAR_UPDATE_STALE) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } From 6a8ddee8784a7b84280d41baaa33b464542cf76a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 13 Apr 2017 16:00:11 -0700 Subject: [PATCH 35/39] send keep-alive packets but don't resend identity --- .../src/avatars/AvatarMixerSlave.cpp | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index ee3282f82b..6e3dd150a4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -263,8 +263,16 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - ++numAvatarsHeldBack; - shouldIgnore = true; + // don't ignore this avatar if we haven't sent any update for a long while + // in an effort to prevent other interfaces from deleting a stale avatar instance + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); + const AvatarMixerClientData* otherNodeData = reinterpret_cast(avatarNode->getLinkedData()); + const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; + if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && + lastBroadcastTime + AVATAR_UPDATE_STALE > startIgnoreCalculation) { + ++numAvatarsHeldBack; + shouldIgnore = true; + } } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; @@ -300,13 +308,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO - // the time that Avatar B flagged an IDENTITY DATA change - // or if no packet of any type has been sent for some time - // send IDENTITY DATA about Avatar B to Avatar A - const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; - uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(otherNode->getUUID()); - if (lastBroadcastTime <= otherNodeData->getIdentityChangeTimestamp() || - startAvatarDataPacking > lastBroadcastTime + AVATAR_UPDATE_STALE) { + // the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A. + if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } From 66137e78a2d4de4094e5001e734fe6cd366aa4d2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 14:20:04 -0700 Subject: [PATCH 36/39] grab script checks for touch devices continually, rather than just when the script starts --- scripts/system/controllers/handControllerGrab.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d1c00a9d81..e5271b0e62 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1051,8 +1051,6 @@ function MyController(hand) { this.homeButtonTouched = false; this.editTriggered = false; - this.controllerJointIndex = getControllerJointIndex(this.hand); - // Until there is some reliable way to keep track of a "stack" of parentIDs, we'll have problems // when more than one avatar does parenting grabs on things. This script tries to work // around this with two associative arrays: previousParentID and previousParentJointIndex. If @@ -1736,6 +1734,7 @@ function MyController(hand) { this.off = function(deltaTime, timestamp) { + this.controllerJointIndex = getControllerJointIndex(this.hand); this.checkForUnexpectedChildren(); if (this.editTriggered) { From d1a11740f07f23ec4b8243ab49b4c543268c949d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 17 Apr 2017 11:02:27 -0700 Subject: [PATCH 37/39] Whoops --- libraries/avatars/src/AvatarHashMap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 87bedf8d51..e944c7c887 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -41,7 +41,7 @@ public: Q_INVOKABLE QVector getAvatarIdentifiers(); // Null/Default-constructed QUuids will return MyAvatar - virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } + Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); } int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); From 31b61c3225ed4609fc4abfdc385b68df046ce902 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 18 Apr 2017 00:24:34 +0100 Subject: [PATCH 38/39] removed white space --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index ece00bd0dd..bed1f82ac2 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -36,7 +36,7 @@ StackView { property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; property var tablet: null; - + Component { id: tabletWebView; TabletWebView {} } Component.onCompleted: { fillDestinations(); From 3113dced7b900741fe00c25d0d7b18b47461db8c Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 18 Apr 2017 12:06:44 -0700 Subject: [PATCH 39/39] Be sure to callback even on profile failure. --- scripts/system/pal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 5fbea90025..ae64065216 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -400,6 +400,7 @@ function getProfilePicture(username, callback) { // callback(url) if successfull var matched = !error && html.match(/img class="users-img" src="([^"]*)"/); if (!matched) { print('Error: Unable to get profile picture for', username, error); + callback(''); return; } callback(matched[1]);