diff --git a/interface/resources/icons/tablet-icons/mic-mute.svg b/interface/resources/icons/tablet-icons/mic-mute.svg
new file mode 100644
index 0000000000..bd42fded05
--- /dev/null
+++ b/interface/resources/icons/tablet-icons/mic-mute.svg
@@ -0,0 +1,60 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/tablet-icons/mic.svg b/interface/resources/icons/tablet-icons/mic.svg
new file mode 100644
index 0000000000..30b46d18dd
--- /dev/null
+++ b/interface/resources/icons/tablet-icons/mic.svg
@@ -0,0 +1,62 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml
index 0d563ed5bb..3fb70f9cca 100644
--- a/interface/resources/qml/hifi/tablet/Tablet.qml
+++ b/interface/resources/qml/hifi/tablet/Tablet.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../../styles-uit"
@@ -6,10 +6,16 @@ Item {
id: tablet
objectName: "tablet"
property double micLevel: 0.8
+ property bool micEnabled: true
property int rowIndex: 0
property int columnIndex: 0
property int count: (flowMain.children.length - 1)
+ // called by C++ code to keep mic state updated
+ function setMicEnabled(newMicEnabled) {
+ tablet.micEnabled = newMicEnabled;
+ }
+
// called by C++ code to keep audio bar updated
function setMicLevel(newMicLevel) {
tablet.micLevel = newMicLevel;
@@ -97,17 +103,38 @@ Item {
anchors.topMargin: 0
anchors.top: parent.top
-
- Image {
- id: muteIcon
+ Item {
+ id: audioIcon
+ anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
- source: "../../../icons/tablet-mute-icon.svg"
- anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+
+ Image {
+ id: micIcon
+ source: "../../../icons/tablet-icons/mic.svg"
+ }
+
+ Item {
+ visible: (!tablet.micEnabled && !toggleMuteMouseArea.containsMouse)
+ || (tablet.micEnabled && toggleMuteMouseArea.containsMouse)
+
+ Image {
+ id: muteIcon
+ source: "../../../icons/tablet-icons/mic-mute.svg"
+ }
+
+ ColorOverlay {
+ anchors.fill: muteIcon
+ source: muteIcon
+ color: toggleMuteMouseArea.containsMouse ? "#a0a0a0" : "#ff0000"
+ }
+ }
}
Item {
- id: item1
+ id: audioBar
width: 170
height: 10
anchors.left: parent.left
@@ -157,6 +184,22 @@ Item {
}
}
+ MouseArea {
+ id: toggleMuteMouseArea
+ anchors {
+ left: audioIcon.left
+ right: audioBar.right
+ top: audioIcon.top
+ bottom: audioIcon.bottom
+ }
+
+ hoverEnabled: true
+ preventStealing: true
+ propagateComposedEvents: false
+ scrollGestureEnabled: false
+ onClicked: tabletRoot.toggleMicEnabled()
+ }
+
RalewaySemiBold {
id: usernameText
text: tablet.parent.parent.username
@@ -175,7 +218,6 @@ Item {
GradientStop {
position: 0
color: "#2b2b2b"
-
}
GradientStop {
@@ -225,7 +267,7 @@ Item {
PropertyChanges {
target: muteIcon
- source: "../../../icons/tablet-unmute-icon.svg"
+ visible: micEnabled
}
PropertyChanges {
diff --git a/interface/resources/qml/hifi/tablet/TabletMenu.qml b/interface/resources/qml/hifi/tablet/TabletMenu.qml
index cd3a9cacae..c154ac0f49 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenu.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenu.qml
@@ -14,6 +14,7 @@ FocusScope {
property var rootMenu: Menu { objectName:"rootMenu" }
property var point: Qt.point(50, 50)
+ property string subMenu: ""
TabletMouseHandler { id: menuPopperUpper }
@@ -101,6 +102,24 @@ FocusScope {
buildMenu()
}
function buildMenu() {
- menuPopperUpper.popup(tabletMenu, rootMenu.items)
+ // Build submenu if specified.
+ if (subMenu !== "") {
+ var index = 0;
+ var found = false;
+ while (!found && index < rootMenu.items.length) {
+ found = rootMenu.items[index].title === subMenu;
+ if (!found) {
+ index += 1;
+ }
+ }
+ subMenu = ""; // Continue with full menu after initially displaying submenu.
+ if (found) {
+ menuPopperUpper.popup(tabletMenu, rootMenu.items[index].items);
+ return;
+ }
+ }
+
+ // Otherwise build whole menu.
+ menuPopperUpper.popup(tabletMenu, rootMenu.items);
}
}
diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml
index 0260bd6a01..481c7846a9 100644
--- a/interface/resources/qml/hifi/tablet/TabletRoot.qml
+++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml
@@ -6,9 +6,14 @@ Item {
objectName: "tabletRoot"
property string username: "Unknown user"
property var eventBridge;
+ property string option: ""
signal showDesktop();
+ function setOption(value) {
+ option = value;
+ }
+
function loadSource(url) {
loader.source = url;
}
@@ -42,6 +47,10 @@ Item {
}
}
+ function toggleMicEnabled() {
+ ApplicationInterface.toggleMuteAudio();
+ }
+
function setUsername(newUsername) {
username = newUsername;
}
@@ -68,6 +77,9 @@ Item {
if (loader.item.hasOwnProperty("sendToScript")) {
loader.item.sendToScript.connect(tabletRoot.sendToScript);
}
+ if (loader.item.hasOwnProperty("subMenu")) {
+ loader.item.subMenu = option;
+ }
loader.item.forceActiveFocus();
}
}
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index b7aecfa597..488e97b5e6 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -6853,3 +6853,8 @@ void Application::updateThreadPoolCount() const {
qCDebug(interfaceapp) << "Setting thread pool size to " << threadPoolSize;
QThreadPool::globalInstance()->setMaxThreadCount(threadPoolSize);
}
+
+void Application::toggleMuteAudio() {
+ auto menu = Menu::getInstance();
+ menu->setIsOptionChecked(MenuOption::MuteAudio, !menu->isOptionChecked(MenuOption::MuteAudio));
+}
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 6072acac93..cab830ec88 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -386,6 +386,8 @@ public slots:
void addAssetToWorldMessageClose();
+ Q_INVOKABLE void toggleMuteAudio();
+
private slots:
void showDesktop();
void clearDomainOctreeDetails();
diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp
index 71f0073ead..7e8fdd6bc3 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.cpp
+++ b/libraries/script-engine/src/TabletScriptingInterface.cpp
@@ -213,10 +213,11 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
}
}
-void TabletProxy::gotoMenuScreen() {
+void TabletProxy::gotoMenuScreen(const QString& submenu) {
if (_qmlTabletRoot) {
if (_state != State::Menu) {
removeButtonsFromHomeScreen();
+ QMetaObject::invokeMethod(_qmlTabletRoot, "setOption", Q_ARG(const QVariant&, QVariant(submenu)));
auto loader = _qmlTabletRoot->findChild("loader");
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen()), Qt::DirectConnection);
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
@@ -309,6 +310,15 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) {
}
}
+void TabletProxy::updateMicEnabled(const bool micOn) {
+ auto tablet = getQmlTablet();
+ if (!tablet) {
+ //qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
+ } else {
+ QMetaObject::invokeMethod(tablet, "setMicEnabled", Qt::AutoConnection, Q_ARG(QVariant, QVariant(micOn)));
+ }
+}
+
void TabletProxy::updateAudioBar(const double micLevel) {
auto tablet = getQmlTablet();
if (!tablet) {
@@ -359,13 +369,13 @@ void TabletProxy::addButtonsToMenuScreen() {
}
QQuickItem* VrMenu = loader->findChild("tabletMenu");
- if (!VrMenu) {
- return;
+ if (VrMenu) {
+ auto offscreenUi = DependencyManager::get();
+ QObject* menu = offscreenUi->getRootMenu();
+ QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu)));
}
- auto offscreenUi = DependencyManager::get();
- QObject* menu = offscreenUi->getRootMenu();
- QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu)));
+ QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen()));
}
void TabletProxy::removeButtonsFromHomeScreen() {
diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h
index 9986fc78b0..8ba69ccdde 100644
--- a/libraries/script-engine/src/TabletScriptingInterface.h
+++ b/libraries/script-engine/src/TabletScriptingInterface.h
@@ -72,7 +72,7 @@ public:
void setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface);
- Q_INVOKABLE void gotoMenuScreen();
+ Q_INVOKABLE void gotoMenuScreen(const QString& submenu = "");
/**jsdoc
* transition to the home screen
@@ -106,6 +106,13 @@ public:
*/
Q_INVOKABLE void removeButton(QObject* tabletButtonProxy);
+ /**jsdoc
+ * Updates the tablet's mic enabled state
+ * @function TabletProxy#updateMicEnabled
+ * @param micEnabled {bool} mic enabled state
+ */
+ Q_INVOKABLE void updateMicEnabled(const bool micEnabled);
+
/**jsdoc
* Updates the audio bar in tablet to reflect latest mic level
* @function TabletProxy#updateAudioBar
diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js
index 36b0ddde85..40a77eda55 100644
--- a/scripts/defaultScripts.js
+++ b/scripts/defaultScripts.js
@@ -14,7 +14,7 @@
var DEFAULT_SCRIPTS = [
"system/progress.js",
"system/away.js",
- "system/mute.js",
+ "system/audio.js",
"system/hmd.js",
"system/menu.js",
"system/bubble.js",
diff --git a/scripts/system/mute.js b/scripts/system/audio.js
similarity index 56%
rename from scripts/system/mute.js
rename to scripts/system/audio.js
index 822a8f127a..dd49f944ea 100644
--- a/scripts/system/mute.js
+++ b/scripts/system/audio.js
@@ -1,8 +1,7 @@
"use strict";
//
-// goto.js
-// scripts/system/
+// audio.js
//
// Created by Howard Stearns on 2 Jun 2016
// Copyright 2016 High Fidelity, Inc.
@@ -14,22 +13,33 @@
(function() { // BEGIN LOCAL_SCOPE
var button;
-var buttonName = "MUTE";
+var TOOLBAR_BUTTON_NAME = "MUTE";
+var TABLET_BUTTON_NAME = "AUDIO";
var toolBar = null;
var tablet = null;
+var isHUDUIEnabled = Settings.getValue("HUDUIEnabled");
+var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
function onMuteToggled() {
- button.editProperties({isActive: AudioDevice.getMuted()});
+ if (isHUDUIEnabled) {
+ button.editProperties({ isActive: AudioDevice.getMuted() });
+ }
}
function onClicked(){
- var menuItem = "Mute Microphone";
- Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem));
+ if (isHUDUIEnabled) {
+ var menuItem = "Mute Microphone";
+ Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem));
+ } else {
+ var entity = HMD.tabletID;
+ Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+ tablet.gotoMenuScreen("Audio");
+ }
}
if (Settings.getValue("HUDUIEnabled")) {
toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
button = toolBar.addButton({
- objectName: buttonName,
+ objectName: TOOLBAR_BUTTON_NAME,
imageURL: Script.resolvePath("assets/images/tools/mic.svg"),
visible: true,
alpha: 0.9
@@ -37,12 +47,8 @@ if (Settings.getValue("HUDUIEnabled")) {
} else {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
button = tablet.addButton({
- icon: "icons/tablet-icons/mic-unmute-i.svg",
- hoverIcon: "icons/tablet-icons/mic-mute-i.svg",
- activeIcon: "icons/tablet-icons/mic-mute-a.svg",
- activeHoverIcon: "icons/tablet-icons/mic-unmute-a.svg",
- text: "MUTE",
- activeText: "UNMUTE",
+ icon: "icons/tablet-icons/mic-i.svg",
+ text: TABLET_BUTTON_NAME,
sortOrder: 1
});
}
@@ -58,7 +64,7 @@ Script.scriptEnding.connect(function () {
tablet.removeButton(button);
}
if (toolBar) {
- toolBar.removeButton(buttonName);
+ toolBar.removeButton(TOOLBAR_BUTTON_NAME);
}
});
diff --git a/scripts/system/selectAudioDevice.js b/scripts/system/selectAudioDevice.js
index c618909e8c..9b97b24455 100644
--- a/scripts/system/selectAudioDevice.js
+++ b/scripts/system/selectAudioDevice.js
@@ -52,33 +52,7 @@ var selectedInputMenu = "";
var selectedOutputMenu = "";
function setupAudioMenus() {
- Menu.addMenu("Audio > Devices");
- Menu.addSeparator("Audio > Devices","Output Audio Device");
-
- var outputDeviceSetting = Settings.getValue(OUTPUT_DEVICE_SETTING);
- var outputDevices = AudioDevice.getOutputDevices();
- var selectedOutputDevice = AudioDevice.getOutputDevice();
- if (outputDevices.indexOf(outputDeviceSetting) != -1 && selectedOutputDevice != outputDeviceSetting) {
- if (AudioDevice.setOutputDevice(outputDeviceSetting)) {
- selectedOutputDevice = outputDeviceSetting;
- }
- }
- print("audio output devices: " + outputDevices);
- for(var i = 0; i < outputDevices.length; i++) {
- var thisDeviceSelected = (outputDevices[i] == selectedOutputDevice);
- var menuItem = "Use " + outputDevices[i] + " for Output";
- Menu.addMenuItem({
- menuName: "Audio > Devices",
- menuItemName: menuItem,
- isCheckable: true,
- isChecked: thisDeviceSelected
- });
- if (thisDeviceSelected) {
- selectedOutputMenu = menuItem;
- }
- }
-
- Menu.addSeparator("Audio > Devices","Input Audio Device");
+ Menu.addSeparator("Audio", "Input Audio Device");
var inputDeviceSetting = Settings.getValue(INPUT_DEVICE_SETTING);
var inputDevices = AudioDevice.getInputDevices();
@@ -93,7 +67,7 @@ function setupAudioMenus() {
var thisDeviceSelected = (inputDevices[i] == selectedInputDevice);
var menuItem = "Use " + inputDevices[i] + " for Input";
Menu.addMenuItem({
- menuName: "Audio > Devices",
+ menuName: "Audio",
menuItemName: menuItem,
isCheckable: true,
isChecked: thisDeviceSelected
@@ -102,6 +76,31 @@ function setupAudioMenus() {
selectedInputMenu = menuItem;
}
}
+
+ Menu.addSeparator("Audio", "Output Audio Device");
+
+ var outputDeviceSetting = Settings.getValue(OUTPUT_DEVICE_SETTING);
+ var outputDevices = AudioDevice.getOutputDevices();
+ var selectedOutputDevice = AudioDevice.getOutputDevice();
+ if (outputDevices.indexOf(outputDeviceSetting) != -1 && selectedOutputDevice != outputDeviceSetting) {
+ if (AudioDevice.setOutputDevice(outputDeviceSetting)) {
+ selectedOutputDevice = outputDeviceSetting;
+ }
+ }
+ print("audio output devices: " + outputDevices);
+ for (var i = 0; i < outputDevices.length; i++) {
+ var thisDeviceSelected = (outputDevices[i] == selectedOutputDevice);
+ var menuItem = "Use " + outputDevices[i] + " for Output";
+ Menu.addMenuItem({
+ menuName: "Audio",
+ menuItemName: menuItem,
+ isCheckable: true,
+ isChecked: thisDeviceSelected
+ });
+ if (thisDeviceSelected) {
+ selectedOutputMenu = menuItem;
+ }
+ }
}
function onDevicechanged() {
diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js
index dc1d71f402..1dc6b7fef8 100644
--- a/scripts/system/tablet-ui/tabletUI.js
+++ b/scripts/system/tablet-ui/tabletUI.js
@@ -53,8 +53,11 @@
function updateShowTablet() {
if (tabletShown) {
+ var MUTE_MICROPHONE_MENU_ITEM = "Mute Microphone";
+ var currentMicEnabled = !Menu.isOptionChecked(MUTE_MICROPHONE_MENU_ITEM);
var currentMicLevel = getMicLevel();
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+ tablet.updateMicEnabled(currentMicEnabled);
tablet.updateAudioBar(currentMicLevel);
}