diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 66b59f0aea..cc64d0f2b4 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -12,7 +12,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "../dialogs" -import "../menus" import "../js/Utils.js" as Utils // This is our primary 'desktop' object to which all VR dialogs and windows are childed. @@ -465,32 +464,7 @@ FocusScope { Component { id: fileDialogBuilder; FileDialog { } } function fileDialog(properties) { return fileDialogBuilder.createObject(desktop, properties); - } - - MenuMouseHandler { id: menuPopperUpper } - function popupMenu(point) { - menuPopperUpper.popup(desktop, rootMenu.items, point); - } - - function toggleMenu(point) { - menuPopperUpper.toggle(desktop, rootMenu.items, point); - } - - Keys.onEscapePressed: { - if (menuPopperUpper.closeLastMenu()) { - event.accepted = true; - return; - } - event.accepted = false; - } - - Keys.onLeftPressed: { - if (menuPopperUpper.closeLastMenu()) { - event.accepted = true; - return; - } - event.accepted = false; - } + } function unfocusWindows() { // First find the active focus item, and unfocus it, all the way diff --git a/interface/resources/qml/hifi/tablet/TabletMenu.qml b/interface/resources/qml/hifi/tablet/TabletMenu.qml new file mode 100644 index 0000000000..36de421a78 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/TabletMenu.qml @@ -0,0 +1,27 @@ +import QtQuick 2.5 +import QtGraphicalEffects 1.0 +import QtQuick.Controls 1.4 +import QtQml 2.2 +import "." + + +Item { + id: tabletMenu + objectName: "tabletMenu" + + width: parent.width + height: parent.height + + property var rootMenu: Menu { objectName:"rootMenu" } + property var point: Qt.point(50, 50) + + TabletMouseHandler { id: menuPopperUpper } + + function setRootMenu(menu) { + tabletMenu.rootMenu = menu + buildMenu() + } + function buildMenu() { + menuPopperUpper.popup(tabletMenu, rootMenu.items) + } +} diff --git a/interface/resources/qml/menus/VrMenuItem.qml b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml similarity index 98% rename from interface/resources/qml/menus/VrMenuItem.qml rename to interface/resources/qml/hifi/tablet/TabletMenuItem.qml index 38d2b57c03..ce45ca7065 100644 --- a/interface/resources/qml/menus/VrMenuItem.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml @@ -12,8 +12,8 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 -import "../controls-uit" -import "../styles-uit" +import "../../controls-uit" +import "../../styles-uit" Item { id: root diff --git a/interface/resources/qml/menus/VrMenuView.qml b/interface/resources/qml/hifi/tablet/TabletMenuView.qml similarity index 96% rename from interface/resources/qml/menus/VrMenuView.qml rename to interface/resources/qml/hifi/tablet/TabletMenuView.qml index 5db13fc160..b3a6bcf811 100644 --- a/interface/resources/qml/menus/VrMenuView.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuView.qml @@ -12,7 +12,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 -import "../styles-uit" +import "../../styles-uit" FocusScope { id: root @@ -38,8 +38,8 @@ FocusScope { ListView { id: listView x: 8; y: 8 - width: 128 - height: count * 32 + width: parent.width + height: parent.height topMargin: hifi.dimensions.menuPadding.y onEnabledChanged: recalcSize(); onVisibleChanged: recalcSize(); @@ -57,7 +57,7 @@ FocusScope { color: hifi.colors.white } - delegate: VrMenuItem { + delegate: TabletMenuItem { text: name source: item onImplicitHeightChanged: listView.recalcSize() diff --git a/interface/resources/qml/menus/MenuMouseHandler.qml b/interface/resources/qml/hifi/tablet/TabletMouseHandler.qml similarity index 83% rename from interface/resources/qml/menus/MenuMouseHandler.qml rename to interface/resources/qml/hifi/tablet/TabletMouseHandler.qml index 48574d41e5..db74de82fb 100644 --- a/interface/resources/qml/menus/MenuMouseHandler.qml +++ b/interface/resources/qml/hifi/tablet/TabletMouseHandler.qml @@ -16,11 +16,11 @@ import "." Item { id: root anchors.fill: parent - objectName: "MouseMenuHandlerItem" + objectName: "tabletMenuHandlerItem" MouseArea { id: menuRoot; - objectName: "MouseMenuHandlerMouseArea" + objectName: "tabletMenuHandlerMouseArea" anchors.fill: parent enabled: d.topMenu !== null onClicked: { @@ -34,7 +34,7 @@ Item { property var topMenu: null; property var modelMaker: Component { ListModel { } } property var menuViewMaker: Component { - VrMenuView { + TabletMenuView { id: subMenu onSelected: d.handleSelection(subMenu, currentItem, item) } @@ -54,10 +54,11 @@ Item { } function toModel(items) { - var result = modelMaker.createObject(desktop); + var result = modelMaker.createObject(tabletMenu); for (var i = 0; i < items.length; ++i) { var item = items[i]; if (!item.visible) continue; + console.log(item.title) switch (item.type) { case MenuItemType.Menu: result.append({"name": item.title, "item": item}) @@ -82,7 +83,7 @@ Item { topMenu.focus = true; } else { topMenu = null; - offscreenFlags.navigationFocused = false; + //offscreenFlags.navigationFocused = false; menuRoot.enabled = false; } } @@ -91,7 +92,7 @@ Item { menuStack.push(newMenu); topMenu = newMenu; topMenu.focus = true; - offscreenFlags.navigationFocused = true; + //offscreenFlags.navigationFocused = true; } function clearMenus() { @@ -118,12 +119,7 @@ Item { function buildMenu(items, targetPosition) { var model = toModel(items); // Menus must be childed to desktop for Z-ordering - var newMenu = menuViewMaker.createObject(desktop, { model: model, z: topMenu ? topMenu.z + 1 : desktop.zLevels.menu, isSubMenu: topMenu !== null }); - if (targetPosition) { - newMenu.x = targetPosition.x - newMenu.y = targetPosition.y - newMenu.height / 3 * 1 - } - clampMenuPosition(newMenu); + var newMenu = menuViewMaker.createObject(tabletMenu, { model: model, isSubMenu: topMenu !== null }); pushMenu(newMenu); return newMenu; } @@ -150,20 +146,12 @@ Item { } - function popup(parent, items, point) { + function popup(parent, items) { d.clearMenus(); menuRoot.enabled = true; d.buildMenu(items, point); } - function toggle(parent, items, point) { - if (d.topMenu) { - d.clearMenus(); - return; - } - popup(parent, items, point); - } - function closeLastMenu() { if (d.menuStack.length) { d.popMenu(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1458ec0018..f28ed10bdc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1059,10 +1059,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->toggleMute(); } else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) { cycleCamera(); - } else if (action == controller::toInt(controller::Action::UI_NAV_SELECT)) { - if (!offscreenUi->navigationFocused()) { - toggleMenuUnderReticle(); - } } else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) { toggleTabletUI(); } else if (action == controller::toInt(controller::Action::RETICLE_X)) { @@ -1580,17 +1576,6 @@ QString Application::getUserAgent() { return userAgent; } -void Application::toggleMenuUnderReticle() const { - // In HMD, if the menu is near the mouse but not under it, the reticle can be at a significantly - // different depth. When you focus on the menu, the cursor can appear to your crossed eyes as both - // on the menu and off. - // Even in 2D, it is arguable whether the user would want the menu to be to the side. - const float X_LEFT_SHIFT = 50.0; - auto offscreenUi = DependencyManager::get(); - auto reticlePosition = getApplicationCompositor().getReticlePosition(); - offscreenUi->toggleMenu(QPoint(reticlePosition.x - X_LEFT_SHIFT, reticlePosition.y)); -} - uint64_t lastTabletUIToggle { 0 }; const uint64_t toggleTabletUILockout { 500000 }; void Application::toggleTabletUI() const { @@ -2931,10 +2916,6 @@ void Application::keyPressEvent(QKeyEvent* event) { void Application::keyReleaseEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { - toggleMenuUnderReticle(); - } - _keysPressed.remove(event->key()); _controllerScriptingInterface->emitKeyReleaseEvent(event); // send events to any registered scripts diff --git a/interface/src/Application.h b/interface/src/Application.h index c789c705a3..3b89aa52f3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -484,7 +484,6 @@ private: static void dragEnterEvent(QDragEnterEvent* event); void maybeToggleMenuVisible(QMouseEvent* event) const; - void toggleMenuUnderReticle() const; void toggleTabletUI() const; MainWindow* _window; diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 056d946482..45635d0cbb 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -14,6 +14,8 @@ #include #include #include "ScriptEngineLogging.h" +#include "DependencyManager.h" +#include "OffscreenUi.h" TabletScriptingInterface::TabletScriptingInterface() { qmlRegisterType("Hifi", 1, 0, "SoundEffect"); @@ -56,6 +58,7 @@ void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qm static const char* TABLET_SOURCE_URL = "Tablet.qml"; static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; static const char* LOADER_SOURCE_PROPERTY_NAME = "LoaderSource"; +static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; TabletProxy::TabletProxy(QString name) : _name(name) { ; @@ -95,6 +98,15 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr } } +void TabletProxy::gotoMenuScreen() { + if (_qmlTabletRoot) { + _qmlTabletRoot->setProperty(LOADER_SOURCE_PROPERTY_NAME, VRMENU_SOURCE_URL); + auto loader = _qmlTabletRoot->findChild("loader"); + QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen())); + QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL))); + } +} + void TabletProxy::gotoHomeScreen() { if (_qmlTabletRoot) { QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString(); @@ -160,7 +172,7 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { void TabletProxy::updateAudioBar(const double micLevel) { auto tablet = getQmlTablet(); if (!tablet) { - qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; + //qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; } else { QMetaObject::invokeMethod(tablet, "setMicLevel", Qt::AutoConnection, Q_ARG(QVariant, QVariant(micLevel))); } @@ -186,6 +198,27 @@ void TabletProxy::addButtonsToHomeScreen() { QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); } +void TabletProxy::addButtonsToMenuScreen() { + if (!_qmlTabletRoot) { + return; + } + + auto loader = _qmlTabletRoot->findChild("loader"); + if (!loader) { + return; + } + + QQuickItem* VrMenu = loader->findChild("tabletMenu"); + if (!VrMenu) { + qDebug() << "----------> could not find vr menu"; + return; + } + + auto offscreenUi = DependencyManager::get(); + QObject* menu = offscreenUi->getRootMenu(); + QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu))); +} + void TabletProxy::removeButtonsFromHomeScreen() { auto tabletScriptingInterface = DependencyManager::get(); for (auto& buttonProxy : _tabletButtonProxies) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index 43750e2519..f49c9ea498 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -65,6 +65,8 @@ public: void setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface); + Q_INVOKABLE void gotoMenuScreen(); + /**jsdoc * transition to the home screen * @function TabletProxy#gotoHomeScreen @@ -120,6 +122,7 @@ signals: private slots: void addButtonsToHomeScreen(); + void addButtonsToMenuScreen(); protected: void removeButtonsFromHomeScreen(); QQuickItem* getQmlTablet() const; diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 60d80c6b35..918fb7b54a 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -524,6 +524,10 @@ QQuickItem* OffscreenUi::getDesktop() { return _desktop; } +QObject* OffscreenUi::getRootMenu() { + return getRootItem()->findChild("rootMenu"); +} + QQuickItem* OffscreenUi::getToolWindow() { return _toolWindow; } @@ -533,11 +537,6 @@ void OffscreenUi::unfocusWindows() { Q_ASSERT(invokeResult); } -void OffscreenUi::toggleMenu(const QPoint& screenPosition) { // caller should already have mapped using getReticlePosition - emit showDesktop(); // we really only want to do this if you're showing the menu, but for now this works - QMetaObject::invokeMethod(_desktop, "toggleMenu", Q_ARG(QVariant, screenPosition)); -} - class FileDialogListener : public ModalDialogListener { Q_OBJECT diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 3ab4fa0758..c648e2ec86 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -45,12 +45,11 @@ public: bool navigationFocused(); void setNavigationFocused(bool focused); void unfocusWindows(); - void toggleMenu(const QPoint& screenCoordinates); // Setting pinned to true will hide all overlay elements on the desktop that don't have a pinned flag void setPinned(bool pinned = true); - + void togglePinned(); void setConstrainToolbarToCenterX(bool constrained); @@ -59,7 +58,7 @@ public: QObject* getFlags(); QQuickItem* getDesktop(); QQuickItem* getToolWindow(); - + QObject* getRootMenu(); enum Icon { ICON_NONE = 0, ICON_QUESTION, diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 61461c7f06..bd3131f4ff 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -35,7 +35,8 @@ var DEFAULT_SCRIPTS = [ "system/snapshot.js", "system/help.js", "system/bubble.js", - "system/tablet-ui/tabletUI.js" + "system/tablet-ui/tabletUI.js", + "system/menu.js" ]; // add a menu item for debugging diff --git a/scripts/system/menu.js b/scripts/system/menu.js new file mode 100644 index 0000000000..94097271bf --- /dev/null +++ b/scripts/system/menu.js @@ -0,0 +1,30 @@ +// +// menu.js +// scripts/system/ +// +// Created by Dante Ruiz on 5 Jun 2017 +// 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 +// + +(function() { + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + icon: "icons/tablet-icons/menu-i.svg", + text: "Menu" + }); + + + function onClicked() { + tablet.gotoMenuScreen(); + } + + button.clicked.connect(onClicked); + + Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + }) +}()); \ No newline at end of file