From f18094f5654c57dde49e1c54147964188be35f33 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 25 Jan 2017 12:00:34 -0800 Subject: [PATCH] make use of tablet or HUD depend on a single variable. avoid some duplicated code --- .../src/scripting/HMDScriptingInterface.h | 10 +- .../scripting/ToolbarScriptingInterface.cpp | 4 + scripts/defaultScripts.js | 2 + scripts/defaultScriptsHUD.js | 131 -- scripts/system/bubble.js | 32 +- scripts/system/bubbleHUD.js | 195 --- scripts/system/edit.js | 35 +- scripts/system/goto.js | 41 +- scripts/system/gotoHUD.js | 46 - scripts/system/help.js | 41 +- scripts/system/helpHUD.js | 41 - scripts/system/hmd.js | 63 +- scripts/system/hmdHUD.js | 79 -- scripts/system/marketplaces/marketplaceHUD.js | 131 -- scripts/system/marketplaces/marketplaces.js | 115 +- .../system/marketplaces/marketplacesHUD.js | 233 ---- scripts/system/mute.js | 43 +- scripts/system/muteHUD.js | 51 - scripts/system/pal.js | 33 +- scripts/system/palHUD.js | 658 --------- scripts/system/snapshot.js | 41 +- scripts/system/snapshotHUD.js | 226 --- scripts/system/tablet-ui/tabletUI.js | 2 +- scripts/system/users.js | 104 +- scripts/system/usersHUD.js | 1237 ----------------- 25 files changed, 406 insertions(+), 3188 deletions(-) delete mode 100644 scripts/defaultScriptsHUD.js delete mode 100644 scripts/system/bubbleHUD.js delete mode 100644 scripts/system/gotoHUD.js delete mode 100644 scripts/system/helpHUD.js delete mode 100644 scripts/system/hmdHUD.js delete mode 100644 scripts/system/marketplaces/marketplaceHUD.js delete mode 100644 scripts/system/marketplaces/marketplacesHUD.js delete mode 100644 scripts/system/muteHUD.js delete mode 100644 scripts/system/palHUD.js delete mode 100644 scripts/system/snapshotHUD.js delete mode 100644 scripts/system/usersHUD.js diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index bbf446456d..a8c1600a16 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -31,7 +31,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(bool showTablet READ getShouldShowTablet) Q_PROPERTY(QUuid tabletID READ getCurrentTableUIID WRITE setCurrentTabletUIID) Q_PROPERTY(unsigned int homeButtonID READ getCurrentHomeButtonUUID WRITE setCurrentHomeButtonUUID) - + Q_PROPERTY(bool hudUIEnabled READ getHUDUIEnabled WRITE setHUDUIEnabled); public: Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; @@ -91,11 +91,13 @@ public: bool getShouldShowTablet() const { return _showTablet; } void setCurrentTabletUIID(QUuid tabletID) { _tabletUIID = tabletID; } - QUuid getCurrentTableUIID() { return _tabletUIID; } + QUuid getCurrentTableUIID() const { return _tabletUIID; } void setCurrentHomeButtonUUID(unsigned int homeButtonID) { _homeButtonID = homeButtonID; } - unsigned int getCurrentHomeButtonUUID() { return _homeButtonID; } + unsigned int getCurrentHomeButtonUUID() const { return _homeButtonID; } + bool getHUDUIEnabled() const { return _hudUIEnabled; } + void setHUDUIEnabled(bool value) { _hudUIEnabled = value; } private: bool _showTablet { false }; @@ -112,6 +114,8 @@ private: bool getHUDLookAtPosition3D(glm::vec3& result) const; glm::mat4 getWorldHMDMatrix() const; std::atomic _showHandControllersCount { 0 }; + + bool _hudUIEnabled; }; #endif // hifi_HMDScriptingInterface_h diff --git a/interface/src/scripting/ToolbarScriptingInterface.cpp b/interface/src/scripting/ToolbarScriptingInterface.cpp index 1f2228c6d9..eb60ff0f67 100644 --- a/interface/src/scripting/ToolbarScriptingInterface.cpp +++ b/interface/src/scripting/ToolbarScriptingInterface.cpp @@ -22,6 +22,10 @@ public: connect(qmlObject, SIGNAL(clicked()), this, SIGNAL(clicked())); } + Q_INVOKABLE void editProperties(QVariantMap properties) { + qDebug() << "XXX WRITE TabletButtonProxy::editProperties"; + } + signals: void clicked(); }; diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index bd3131f4ff..f046351147 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -43,6 +43,8 @@ var DEFAULT_SCRIPTS = [ var MENU_CATEGORY = "Developer"; var MENU_ITEM = "Debug defaultScripts.js"; +HMD.hudUIEnabled = true; + var SETTINGS_KEY = '_debugDefaultScriptsIsChecked'; var previousSetting = Settings.getValue(SETTINGS_KEY); diff --git a/scripts/defaultScriptsHUD.js b/scripts/defaultScriptsHUD.js deleted file mode 100644 index 098a74ffd0..0000000000 --- a/scripts/defaultScriptsHUD.js +++ /dev/null @@ -1,131 +0,0 @@ -"use strict"; -/* jslint vars: true, plusplus: true */ - -// -// defaultScripts.js -// examples -// -// Copyright 2014 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 -// - -var DEFAULT_SCRIPTS = [ - "system/progress.js", - "system/away.js", - "system/usersHUD.js", - "system/muteHUD.js", - "system/gotoHUD.js", - "system/hmdHUD.js", - "system/marketplaces/marketplacesHUD.js", - "system/edit.js", - "system/palHUD.js", //"system/mod.js", // older UX, if you prefer - "system/selectAudioDevice.js", - "system/notifications.js", - "system/controllers/controllerDisplayManager.js", - "system/controllers/handControllerGrab.js", - "system/controllers/handControllerPointer.js", - "system/controllers/squeezeHands.js", - "system/controllers/grab.js", - "system/controllers/teleport.js", - "system/controllers/toggleAdvancedMovementForHandControllers.js", - "system/dialTone.js", - "system/firstPersonHMD.js", - "system/snapshotHUD.js", - "system/helpHUD.js", - "system/bubbleHUD.js" -]; - -// add a menu item for debugging -var MENU_CATEGORY = "Developer"; -var MENU_ITEM = "Debug defaultScripts.js"; - -var SETTINGS_KEY = '_debugDefaultScriptsIsChecked'; -var previousSetting = Settings.getValue(SETTINGS_KEY); - -if (previousSetting === '' || previousSetting === false || previousSetting === 'false') { - previousSetting = false; -} - -if (previousSetting === true || previousSetting === 'true') { - previousSetting = true; -} - - - - -if (Menu.menuExists(MENU_CATEGORY) && !Menu.menuItemExists(MENU_CATEGORY, MENU_ITEM)) { - Menu.addMenuItem({ - menuName: MENU_CATEGORY, - menuItemName: MENU_ITEM, - isCheckable: true, - isChecked: previousSetting, - grouping: "Advanced" - }); -} - -function runDefaultsTogether() { - for (var j in DEFAULT_SCRIPTS) { - Script.include(DEFAULT_SCRIPTS[j]); - } -} - -function runDefaultsSeparately() { - for (var i in DEFAULT_SCRIPTS) { - Script.load(DEFAULT_SCRIPTS[i]); - } -} -// start all scripts -if (Menu.isOptionChecked(MENU_ITEM)) { - // we're debugging individual default scripts - // so we load each into its own ScriptEngine instance - debuggingDefaultScripts = true; - runDefaultsSeparately(); -} else { - // include all default scripts into this ScriptEngine - runDefaultsTogether(); -} - -function menuItemEvent(menuItem) { - if (menuItem == MENU_ITEM) { - - isChecked = Menu.isOptionChecked(MENU_ITEM); - if (isChecked === true) { - Settings.setValue(SETTINGS_KEY, true); - } else if (isChecked === false) { - Settings.setValue(SETTINGS_KEY, false); - } - Window.alert('You must reload all scripts for this to take effect.') - } - - -} - - - -function stopLoadedScripts() { - // remove debug script loads - var runningScripts = ScriptDiscoveryService.getRunning(); - for (var i in runningScripts) { - var scriptName = runningScripts[i].name; - for (var j in DEFAULT_SCRIPTS) { - if (DEFAULT_SCRIPTS[j].slice(-scriptName.length) === scriptName) { - ScriptDiscoveryService.stopScript(runningScripts[i].url); - } - } - } -} - -function removeMenuItem() { - if (!Menu.isOptionChecked(MENU_ITEM)) { - Menu.removeMenuItem(MENU_CATEGORY, MENU_ITEM); - } -} - -Script.scriptEnding.connect(function() { - stopLoadedScripts(); - removeMenuItem(); -}); - -Menu.menuItemEvent.connect(menuItemEvent); diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index e787793eb2..4d93926abb 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -15,8 +15,7 @@ (function () { // BEGIN LOCAL_SCOPE - // grab the toolbar - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button; // Used for animating and disappearing the bubble var bubbleOverlayTimestamp; // Used for flashing the HUD button upon activation @@ -164,11 +163,23 @@ } } - // Setup the bubble button and add it to the toolbar - var button = tablet.addButton({ - icon: "icons/tablet-icons/bubble-i.svg", - text: "BUBBLE" - }); + // Setup the bubble button + var buttonName = "BUBBLE"; + if (HMD.hudUIEnabled) { + var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolbar.addButton({ + objectName: 'bubble', + imageURL: buttonImageURL(), + visible: true, + alpha: 0.9 + }); + } else { + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/bubble-i.svg", + text: buttonName + }); + } onBubbleToggled(); button.clicked.connect(Users.toggleIgnoreRadius); @@ -178,7 +189,12 @@ // Cleanup the toolbar button and overlays when script is stopped Script.scriptEnding.connect(function () { button.clicked.disconnect(Users.toggleIgnoreRadius); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolbar) { + toolbar.removeButton('bubble'); + } Users.ignoreRadiusEnabledChanged.disconnect(onBubbleToggled); Users.enteredIgnoreRadius.disconnect(enteredIgnoreRadius); Overlays.deleteOverlay(bubbleOverlay); diff --git a/scripts/system/bubbleHUD.js b/scripts/system/bubbleHUD.js deleted file mode 100644 index 2f7286872e..0000000000 --- a/scripts/system/bubbleHUD.js +++ /dev/null @@ -1,195 +0,0 @@ -"use strict"; - -// -// bubble.js -// scripts/system/ -// -// Created by Brad Hefta-Gaub on 11/18/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 -// -/* global Toolbars, Script, Users, Overlays, AvatarList, Controller, Camera, getControllerWorldLocation */ - - -(function () { // BEGIN LOCAL_SCOPE - - // grab the toolbar - var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - // Used for animating and disappearing the bubble - var bubbleOverlayTimestamp; - // Used for flashing the HUD button upon activation - var bubbleButtonFlashState = false; - // Used for flashing the HUD button upon activation - var bubbleButtonTimestamp; - // Affects bubble height - const BUBBLE_HEIGHT_SCALE = 0.15; - // The bubble model itself - var bubbleOverlay = Overlays.addOverlay("model", { - url: Script.resolvePath("assets/models/Bubble-v14.fbx"), // If you'd like to change the model, modify this line (and the dimensions below) - dimensions: { x: 1.0, y: 0.75, z: 1.0 }, - position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { x: 2, y: MyAvatar.scale * 0.5 + 0.5, z: 2 }, - visible: false, - ignoreRayIntersection: true - }); - // The bubble activation sound - var bubbleActivateSound = SoundCache.getSound(Script.resolvePath("assets/sounds/bubble.wav")); - // Is the update() function connected? - var updateConnected = false; - - const BUBBLE_VISIBLE_DURATION_MS = 3000; - const BUBBLE_RAISE_ANIMATION_DURATION_MS = 750; - const BUBBLE_HUD_ICON_FLASH_INTERVAL_MS = 500; - - var ASSETS_PATH = Script.resolvePath("assets"); - var TOOLS_PATH = Script.resolvePath("assets/images/tools/"); - - function buttonImageURL() { - return TOOLS_PATH + 'bubble.svg'; - } - - // Hides the bubble model overlay and resets the button flash state - function hideOverlays() { - Overlays.editOverlay(bubbleOverlay, { - visible: false - }); - bubbleButtonFlashState = false; - } - - // Make the bubble overlay visible, set its position, and play the sound - function createOverlays() { - Audio.playSound(bubbleActivateSound, { - position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, - localOnly: true, - volume: 0.2 - }); - hideOverlays(); - if (updateConnected === true) { - updateConnected = false; - Script.update.disconnect(update); - } - - Overlays.editOverlay(bubbleOverlay, { - position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { x: 2, y: MyAvatar.scale * 0.5 + 0.5, z: 2 }, - visible: true - }); - bubbleOverlayTimestamp = Date.now(); - bubbleButtonTimestamp = bubbleOverlayTimestamp; - Script.update.connect(update); - updateConnected = true; - } - - // Called from the C++ scripting interface to show the bubble overlay - function enteredIgnoreRadius() { - createOverlays(); - } - - // Used to set the state of the bubble HUD button - function writeButtonProperties(parameter) { - button.writeProperty('buttonState', parameter ? 0 : 1); - button.writeProperty('defaultState', parameter ? 0 : 1); - button.writeProperty('hoverState', parameter ? 2 : 3); - } - - // The bubble script's update function - update = function () { - var timestamp = Date.now(); - var delay = (timestamp - bubbleOverlayTimestamp); - var overlayAlpha = 1.0 - (delay / BUBBLE_VISIBLE_DURATION_MS); - if (overlayAlpha > 0) { - // Flash button - if ((timestamp - bubbleButtonTimestamp) >= BUBBLE_VISIBLE_DURATION_MS) { - writeButtonProperties(bubbleButtonFlashState); - bubbleButtonTimestamp = timestamp; - bubbleButtonFlashState = !bubbleButtonFlashState; - } - - if (delay < BUBBLE_RAISE_ANIMATION_DURATION_MS) { - Overlays.editOverlay(bubbleOverlay, { - // Quickly raise the bubble from the ground up - position: { - x: MyAvatar.position.x, - y: (-((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { - x: 2, - y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.5), - z: 2 - } - }); - } else { - // Keep the bubble in place for a couple seconds - Overlays.editOverlay(bubbleOverlay, { - position: { - x: MyAvatar.position.x, - y: MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { - x: 2, - y: MyAvatar.scale * 0.5 + 0.5, - z: 2 - } - }); - } - } else { - hideOverlays(); - if (updateConnected === true) { - Script.update.disconnect(update); - updateConnected = false; - } - var bubbleActive = Users.getIgnoreRadiusEnabled(); - writeButtonProperties(bubbleActive); - } - }; - - // When the space bubble is toggled... - function onBubbleToggled() { - var bubbleActive = Users.getIgnoreRadiusEnabled(); - writeButtonProperties(bubbleActive); - if (bubbleActive) { - createOverlays(); - } else { - hideOverlays(); - if (updateConnected === true) { - Script.update.disconnect(update); - updateConnected = false; - } - } - } - - // Setup the bubble button and add it to the toolbar - var button = toolbar.addButton({ - objectName: 'bubble', - imageURL: buttonImageURL(), - visible: true, - alpha: 0.9 - }); - onBubbleToggled(); - - button.clicked.connect(Users.toggleIgnoreRadius); - Users.ignoreRadiusEnabledChanged.connect(onBubbleToggled); - Users.enteredIgnoreRadius.connect(enteredIgnoreRadius); - - // Cleanup the toolbar button and overlays when script is stopped - Script.scriptEnding.connect(function () { - toolbar.removeButton('bubble'); - button.clicked.disconnect(Users.toggleIgnoreRadius); - Users.ignoreRadiusEnabledChanged.disconnect(onBubbleToggled); - Users.enteredIgnoreRadius.disconnect(enteredIgnoreRadius); - Overlays.deleteOverlay(bubbleOverlay); - bubbleButtonFlashState = false; - if (updateConnected === true) { - Script.update.disconnect(update); - } - }); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/edit.js b/scripts/system/edit.js index ee16b683b3..075bc4360d 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -170,8 +170,9 @@ var toolBar = (function () { var EDIT_SETTING = "io.highfidelity.isEditting"; // for communication with other scripts var that = {}, toolBar, - activeButton, - tablet; + activeButton = null, + systemToolbar = null, + tablet = null; function createNewEntity(properties) { Settings.setValue(EDIT_SETTING, false); @@ -196,7 +197,12 @@ var toolBar = (function () { function cleanup() { that.setActive(false); - tablet.removeButton(activeButton); + if (tablet) { + tablet.removeButton(activeButton); + } + if (systemToolbar) { + systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); + } } function addButton(name, image, handler) { @@ -231,11 +237,24 @@ var toolBar = (function () { }); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - activeButton = tablet.addButton({ - icon: "icons/tablet-icons/edit-i.svg", - text: "EDIT" - }); + if (HMD.hudUIEnabled) { + systemToolbar = Toolbars.getToolbar(SYSTEM_TOOLBAR); + activeButton = systemToolbar.addButton({ + objectName: EDIT_TOGGLE_BUTTON, + imageURL: TOOLS_PATH + "edit.svg", + visible: true, + alpha: 0.9, + buttonState: 1, + hoverState: 3, + defaultState: 1 + }); + } else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + activeButton = tablet.addButton({ + icon: "icons/tablet-icons/edit-i.svg", + text: "EDIT" + }); + } activeButton.clicked.connect(function() { that.toggle(); diff --git a/scripts/system/goto.js b/scripts/system/goto.js index 2051c2a9b0..b9ae33339b 100644 --- a/scripts/system/goto.js +++ b/scripts/system/goto.js @@ -10,32 +10,53 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* globals Tablet, Toolbars, Script, HMD, DialogsManager */ (function() { // BEGIN LOCAL_SCOPE -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); -var button = tablet.addButton({ - icon: "icons/tablet-icons/goto-i.svg", - text:"GOTO" -}); - +var button; +var buttonName = "GOTO"; +var toolBar = null; +var tablet = null; function onAddressBarShown(visible) { button.editProperties({isActive: visible}); } -function setActive(active) { - isActive = active; -} function onClicked(){ DialogsManager.toggleAddressBar(); } + +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/directory.svg"), + visible: true, + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/goto-i.svg", + text: buttonName + }); +} + button.clicked.connect(onClicked); DialogsManager.addressBarShown.connect(onAddressBarShown); Script.scriptEnding.connect(function () { button.clicked.disconnect(onClicked); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } DialogsManager.addressBarShown.disconnect(onAddressBarShown); }); diff --git a/scripts/system/gotoHUD.js b/scripts/system/gotoHUD.js deleted file mode 100644 index 9116142293..0000000000 --- a/scripts/system/gotoHUD.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; - -// -// goto.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Jun 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - - -var button = toolBar.addButton({ - objectName: "goto", - imageURL: Script.resolvePath("assets/images/tools/directory.svg"), - visible: true, - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9, -}); - -function onAddressBarShown(visible) { - button.writeProperty('buttonState', visible ? 0 : 1); - button.writeProperty('defaultState', visible ? 0 : 1); - button.writeProperty('hoverState', visible ? 2 : 3); -} -function onClicked(){ - DialogsManager.toggleAddressBar(); -} -button.clicked.connect(onClicked); -DialogsManager.addressBarShown.connect(onAddressBarShown); - -Script.scriptEnding.connect(function () { - toolBar.removeButton("goto"); - button.clicked.disconnect(onClicked); - DialogsManager.addressBarShown.disconnect(onAddressBarShown); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/help.js b/scripts/system/help.js index a83ac24595..483a1c3dc4 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -10,19 +10,34 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* globals Tablet */ +/* globals Tablet, Toolbars, Script, HMD, Controller, Menu */ (function() { // BEGIN LOCAL_SCOPE - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - icon: "icons/tablet-icons/help-i.svg", - text: "HELP" - }); + var button; + var buttonName = "HELP"; + var toolBar = null; + var tablet = null; + if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/help.svg"), + visible: true, + hoverState: 2, + defaultState: 1, + buttonState: 1, + alpha: 0.9 + }); + } else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/help-i.svg", + text: buttonName + }); + } var enabled = false; function onClicked() { - var HELP_URL = Script.resourcesPath() + "html/help.html"; - // Similar logic to Application::showHelp() var defaultTab = "kbm"; var handControllerName = "vive"; @@ -37,8 +52,6 @@ } else if ("SDL2" in Controller.Hardware) { defaultTab = "gamepad"; } - var queryParameters = "handControllerName=" + handControllerName + "&defaultTab=" + defaultTab; - print("Help enabled " + Menu.isMenuEnabled("Help...")) if (enabled) { Menu.closeInfoView('InfoView_html/help.html'); @@ -63,8 +76,14 @@ }, POLL_RATE); Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); Script.clearInterval(interval); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } }); }()); // END LOCAL_SCOPE diff --git a/scripts/system/helpHUD.js b/scripts/system/helpHUD.js deleted file mode 100644 index e79ed0444c..0000000000 --- a/scripts/system/helpHUD.js +++ /dev/null @@ -1,41 +0,0 @@ -"use strict"; - -// -// help.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Nov 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 -// - -(function() { // BEGIN LOCAL_SCOPE - - var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - var buttonName = "help"; // matching location reserved in Desktop.qml - var button = toolBar.addButton({ - objectName: buttonName, - imageURL: Script.resolvePath("assets/images/tools/help.svg"), - visible: true, - hoverState: 2, - defaultState: 1, - buttonState: 1, - alpha: 0.9 - }); - - // TODO: make button state reflect whether the window is opened or closed (independently from us). - - function onClicked(){ - Menu.triggerOption('Help...') - } - - button.clicked.connect(onClicked); - - Script.scriptEnding.connect(function () { - toolBar.removeButton(buttonName); - button.clicked.disconnect(onClicked); - }); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index 26d37d15c7..0261b2f684 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -10,6 +10,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/*globals HMD, Toolbars, Script, Menu, Tablet, Camera */ (function() { // BEGIN LOCAL_SCOPE @@ -35,23 +36,37 @@ function updateControllerDisplay() { } } -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button; +var toolBar = null; +var tablet = null; + +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +} + // Independent and Entity mode make people sick. Third Person and Mirror have traps that we need to work through. // Disable them in hmd. var desktopOnlyViews = ['Mirror', 'Independent Mode', 'Entity Mode']; function onHmdChanged(isHmd) { - //TODO change button icon when the hmd changes - if (isHmd) { - button.editProperties({ - icon: "icons/tablet-icons/switch-a.svg", - text: "DESKTOP" - }); + if (HMD.hudUIEnabled) { + button.writeProperty('buttonState', isHmd ? 0 : 1); + button.writeProperty('defaultState', isHmd ? 0 : 1); + button.writeProperty('hoverState', isHmd ? 2 : 3); } else { - button.editProperties({ - icon: "icons/tablet-icons/switch-i.svg", - text: "VR" - }); + //TODO change button icon when the hmd changes + if (isHmd) { + button.editProperties({ + icon: "icons/tablet-icons/switch-a.svg", + text: "DESKTOP" + }); + } else { + button.editProperties({ + icon: "icons/tablet-icons/switch-i.svg", + text: "VR" + }); + } } desktopOnlyViews.forEach(function (view) { Menu.setMenuEnabled("View>" + view, !isHmd); @@ -63,10 +78,21 @@ function onClicked(){ Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true); } if (headset) { - button = tablet.addButton({ - icon: "icons/tablet-icons/switch-a.svg", - text: "SWITCH" - }); + if (HMD.hudUIEnabled) { + button = toolBar.addButton({ + objectName: "hmdToggle", + imageURL: Script.resolvePath("assets/images/tools/switch.svg"), + visible: true, + hoverState: 2, + defaultState: 0, + alpha: 0.9 + }); + } else { + button = tablet.addButton({ + icon: "icons/tablet-icons/switch-a.svg", + text: "SWITCH" + }); + } onHmdChanged(HMD.active); button.clicked.connect(onClicked); @@ -75,7 +101,12 @@ if (headset) { Script.scriptEnding.connect(function () { button.clicked.disconnect(onClicked); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton("hmdToggle"); + } HMD.displayModeChanged.disconnect(onHmdChanged); Camera.modeUpdated.disconnect(updateControllerDisplay); }); diff --git a/scripts/system/hmdHUD.js b/scripts/system/hmdHUD.js deleted file mode 100644 index 5dd06de8eb..0000000000 --- a/scripts/system/hmdHUD.js +++ /dev/null @@ -1,79 +0,0 @@ -"use strict"; - -// -// hmd.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Jun 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -var headset; // The preferred headset. Default to the first one found in the following list. -var displayMenuName = "Display"; -var desktopMenuItemName = "Desktop"; -['OpenVR (Vive)', 'Oculus Rift'].forEach(function (name) { - if (!headset && Menu.menuItemExists(displayMenuName, name)) { - headset = name; - } -}); - -var controllerDisplay = false; -function updateControllerDisplay() { - if (HMD.active && Menu.isOptionChecked("Third Person")) { - if (!controllerDisplay) { - HMD.requestShowHandControllers(); - controllerDisplay = true; - } - } else if (controllerDisplay) { - HMD.requestHideHandControllers(); - controllerDisplay = false; - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); -var button; -// Independent and Entity mode make people sick. Third Person and Mirror have traps that we need to work through. -// Disable them in hmd. -var desktopOnlyViews = ['Mirror', 'Independent Mode', 'Entity Mode']; -function onHmdChanged(isHmd) { - button.writeProperty('buttonState', isHmd ? 0 : 1); - button.writeProperty('defaultState', isHmd ? 0 : 1); - button.writeProperty('hoverState', isHmd ? 2 : 3); - desktopOnlyViews.forEach(function (view) { - Menu.setMenuEnabled("View>" + view, !isHmd); - }); - updateControllerDisplay(); -} -function onClicked(){ - var isDesktop = Menu.isOptionChecked(desktopMenuItemName); - Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true); -} -if (headset) { - button = toolBar.addButton({ - objectName: "hmdToggle", - imageURL: Script.resolvePath("assets/images/tools/switch.svg"), - visible: true, - hoverState: 2, - defaultState: 0, - alpha: 0.9 - }); - onHmdChanged(HMD.active); - - button.clicked.connect(onClicked); - HMD.displayModeChanged.connect(onHmdChanged); - Camera.modeUpdated.connect(updateControllerDisplay); - - Script.scriptEnding.connect(function () { - toolBar.removeButton("hmdToggle"); - button.clicked.disconnect(onClicked); - HMD.displayModeChanged.disconnect(onHmdChanged); - Camera.modeUpdated.disconnect(updateControllerDisplay); - }); -} - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/marketplaces/marketplaceHUD.js b/scripts/system/marketplaces/marketplaceHUD.js deleted file mode 100644 index 894dae7eac..0000000000 --- a/scripts/system/marketplaces/marketplaceHUD.js +++ /dev/null @@ -1,131 +0,0 @@ -// -// marketplace.js -// -// Created by Eric Levin on 8 Jan 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -/* global WebTablet */ -Script.include("../libraries/WebTablet.js"); - -var toolIconUrl = Script.resolvePath("../assets/images/tools/"); - -var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ - title: "Marketplace", - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; -var marketplaceVisible = false; -var marketplaceWebTablet; - -// We persist clientOnly data in the .ini file, and reconsistitute it on restart. -// To keep things consistent, we pickle the tablet data in Settings, and kill any existing such on restart and domain change. -var persistenceKey = "io.highfidelity.lastDomainTablet"; - -function shouldShowWebTablet() { - var rightPose = Controller.getPoseValue(Controller.Standard.RightHand); - var leftPose = Controller.getPoseValue(Controller.Standard.LeftHand); - var hasHydra = !!Controller.Hardware.Hydra; - return HMD.active && (leftPose.valid || rightPose.valid || hasHydra); -} - -function showMarketplace(marketplaceID) { - if (shouldShowWebTablet()) { - updateButtonState(true); - marketplaceWebTablet = new WebTablet("https://metaverse.highfidelity.com/marketplace", null, null, true); - Settings.setValue(persistenceKey, marketplaceWebTablet.pickle()); - } else { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setURL(url); - marketplaceWindow.setVisible(true); - } - - marketplaceVisible = true; - UserActivityLogger.openedMarketplace(); -} - -function hideTablet(tablet) { - if (!tablet) { - return; - } - updateButtonState(false); - tablet.destroy(); - marketplaceWebTablet = null; - Settings.setValue(persistenceKey, ""); -} -function clearOldTablet() { // If there was a tablet from previous domain or session, kill it and let it be recreated - var tablet = WebTablet.unpickle(Settings.getValue(persistenceKey, "")); - hideTablet(tablet); -} -function hideMarketplace() { - if (marketplaceWindow.visible) { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); - } else if (marketplaceWebTablet) { - hideTablet(marketplaceWebTablet); - } - marketplaceVisible = false; -} - -function toggleMarketplace() { - if (marketplaceVisible) { - hideMarketplace(); - } else { - showMarketplace(); - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "market.svg", - objectName: "marketplace", - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9 -}); - -function updateButtonState(visible) { - browseExamplesButton.writeProperty('buttonState', visible ? 0 : 1); - browseExamplesButton.writeProperty('defaultState', visible ? 0 : 1); - browseExamplesButton.writeProperty('hoverState', visible ? 2 : 3); -} -function onMarketplaceWindowVisibilityChanged() { - updateButtonState(marketplaceWindow.visible); - marketplaceVisible = marketplaceWindow.visible; -} - -function onClick() { - toggleMarketplace(); -} - -browseExamplesButton.clicked.connect(onClick); -marketplaceWindow.visibleChanged.connect(onMarketplaceWindowVisibilityChanged); - -clearOldTablet(); // Run once at startup, in case there's anything laying around from a crash. -// We could also optionally do something like Window.domainChanged.connect(function () {Script.setTimeout(clearOldTablet, 2000)}), -// but the HUD version stays around, so lets do the same. - -Script.scriptEnding.connect(function () { - toolBar.removeButton("marketplace"); - browseExamplesButton.clicked.disconnect(onClick); - marketplaceWindow.visibleChanged.disconnect(onMarketplaceWindowVisibilityChanged); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 3e06b05edc..2b17cf3b7e 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global WebTablet Tablet */ +/* global Tablet, Script, HMD, Toolbars, UserActivityLogger, Entities */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function() { // BEGIN LOCAL_SCOPE @@ -31,6 +31,8 @@ var QUERY_CAN_WRITE_ASSETS = "QUERY_CAN_WRITE_ASSETS"; var CAN_WRITE_ASSETS = "CAN_WRITE_ASSETS"; var WARN_USER_NO_PERMISSIONS = "WARN_USER_NO_PERMISSIONS"; +var marketplaceWindow = null; + var CLARA_DOWNLOAD_TITLE = "Preparing Download"; var messageBox = null; var isDownloadBeingCancelled = false; @@ -51,49 +53,54 @@ function onMessageBoxClosed(id, button) { Window.messageBoxClosed.connect(onMessageBoxClosed); function showMarketplace() { - tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL); - UserActivityLogger.openedMarketplace(); - tablet.webEventReceived.connect(function (message) { - if (message === GOTO_DIRECTORY) { - tablet.gotoWebScreen(MARKETPLACES_URL); - } + if (tablet) { + tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL); + tablet.webEventReceived.connect(function (message) { + if (message === GOTO_DIRECTORY) { + tablet.gotoWebScreen(MARKETPLACES_URL); + } - if (message === QUERY_CAN_WRITE_ASSETS) { - tablet.emitScriptEvent(CAN_WRITE_ASSETS + " " + Entities.canWriteAssets()); - } + if (message === QUERY_CAN_WRITE_ASSETS) { + tablet.emitScriptEvent(CAN_WRITE_ASSETS + " " + Entities.canWriteAssets()); + } - if (message === WARN_USER_NO_PERMISSIONS) { - Window.alert(NO_PERMISSIONS_ERROR_MESSAGE); - } + if (message === WARN_USER_NO_PERMISSIONS) { + Window.alert(NO_PERMISSIONS_ERROR_MESSAGE); + } - if (message.slice(0, CLARA_IO_STATUS.length) === CLARA_IO_STATUS) { - if (isDownloadBeingCancelled) { + if (message.slice(0, CLARA_IO_STATUS.length) === CLARA_IO_STATUS) { + if (isDownloadBeingCancelled) { + return; + } + + var text = message.slice(CLARA_IO_STATUS.length); + if (messageBox === null) { + messageBox = Window.openMessageBox(CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); + } else { + Window.updateMessageBox(messageBox, CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); + } return; } - var text = message.slice(CLARA_IO_STATUS.length); - if (messageBox === null) { - messageBox = Window.openMessageBox(CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); - } else { - Window.updateMessageBox(messageBox, CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); + if (message.slice(0, CLARA_IO_DOWNLOAD.length) === CLARA_IO_DOWNLOAD) { + if (messageBox !== null) { + Window.closeMessageBox(messageBox); + messageBox = null; + } + return; } - return; - } - if (message.slice(0, CLARA_IO_DOWNLOAD.length) === CLARA_IO_DOWNLOAD) { - if (messageBox !== null) { - Window.closeMessageBox(messageBox); - messageBox = null; + if (message === CLARA_IO_CANCELLED_DOWNLOAD) { + isDownloadBeingCancelled = false; } - return; - } - - if (message === CLARA_IO_CANCELLED_DOWNLOAD) { - isDownloadBeingCancelled = false; - } - }); + }); + } else { + marketplaceWindow.setURL(MARKETPLACE_URL_INITIAL); + marketplaceWindow.setVisible(true); + marketplaceVisible = true; + } } function toggleMarketplace() { @@ -102,12 +109,35 @@ function toggleMarketplace() { showMarketplace(); } -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - -var marketplaceButton = tablet.addButton({ - icon: "icons/tablet-icons/market-i.svg", - text: "MARKET" -}); +var tablet = null; +var toolBar = null; +var marketplaceButton = null; +if (HMD.hudUIEnabled) { + marketplaceWindow = new OverlayWebWindow({ + title: "Marketplace", + source: "about:blank", + width: 900, + height: 700, + visible: false + }); + marketplaceWindow.setScriptURL(MARKETPLACES_INJECT_SCRIPT_URL); + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + var toolIconUrl = Script.resolvePath("../assets/images/tools/"); + marketplaceButton = toolBar.addButton({ + imageURL: toolIconUrl + "market.svg", + objectName: "marketplace", + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + marketplaceButton = tablet.addButton({ + icon: "icons/tablet-icons/market-i.svg", + text: "MARKET" + }); +} function onCanWriteAssetsChanged() { var message = CAN_WRITE_ASSETS + " " + Entities.canWriteAssets(); @@ -122,7 +152,12 @@ marketplaceButton.clicked.connect(onClick); Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged); Script.scriptEnding.connect(function () { - tablet.removeButton(marketplaceButton); + if (toolBar) { + toolBar.removeButton("marketplace"); + } + if (tablet) { + tablet.removeButton(marketplaceButton); + } Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged); }); diff --git a/scripts/system/marketplaces/marketplacesHUD.js b/scripts/system/marketplaces/marketplacesHUD.js deleted file mode 100644 index d5530e7db2..0000000000 --- a/scripts/system/marketplaces/marketplacesHUD.js +++ /dev/null @@ -1,233 +0,0 @@ -// -// marketplaces.js -// -// Created by Eric Levin on 8 Jan 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -/* global WebTablet */ -Script.include("../libraries/WebTablet.js"); - -var toolIconUrl = Script.resolvePath("../assets/images/tools/"); - -var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page. -var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html"); -var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js"); - -// Event bridge messages. -var CLARA_IO_DOWNLOAD = "CLARA.IO DOWNLOAD"; -var CLARA_IO_STATUS = "CLARA.IO STATUS"; -var CLARA_IO_CANCEL_DOWNLOAD = "CLARA.IO CANCEL DOWNLOAD"; -var CLARA_IO_CANCELLED_DOWNLOAD = "CLARA.IO CANCELLED DOWNLOAD"; -var GOTO_DIRECTORY = "GOTO_DIRECTORY"; -var QUERY_CAN_WRITE_ASSETS = "QUERY_CAN_WRITE_ASSETS"; -var CAN_WRITE_ASSETS = "CAN_WRITE_ASSETS"; -var WARN_USER_NO_PERMISSIONS = "WARN_USER_NO_PERMISSIONS"; - -var CLARA_DOWNLOAD_TITLE = "Preparing Download"; -var messageBox = null; -var isDownloadBeingCancelled = false; - -var CANCEL_BUTTON = 4194304; // QMessageBox::Cancel -var NO_BUTTON = 0; // QMessageBox::NoButton - -var NO_PERMISSIONS_ERROR_MESSAGE = "Cannot download model because you can't write to \nthe domain's Asset Server."; - -var marketplaceWindow = new OverlayWebWindow({ - title: "Marketplace", - source: "about:blank", - width: 900, - height: 700, - visible: false -}); -marketplaceWindow.setScriptURL(MARKETPLACES_INJECT_SCRIPT_URL); - -function onWebEventReceived(message) { - if (message === GOTO_DIRECTORY) { - var url = MARKETPLACES_URL; - if (marketplaceWindow.visible) { - marketplaceWindow.setURL(url); - } - if (marketplaceWebTablet) { - marketplaceWebTablet.setURL(url); - } - return; - } - if (message === QUERY_CAN_WRITE_ASSETS) { - var canWriteAssets = CAN_WRITE_ASSETS + " " + Entities.canWriteAssets(); - if (marketplaceWindow.visible) { - marketplaceWindow.emitScriptEvent(canWriteAssets); - } - if (marketplaceWebTablet) { - marketplaceWebTablet.getOverlayObject().emitScriptEvent(canWriteAssets); - } - return; - } - if (message === WARN_USER_NO_PERMISSIONS) { - Window.alert(NO_PERMISSIONS_ERROR_MESSAGE); - return; - } - - if (message.slice(0, CLARA_IO_STATUS.length) === CLARA_IO_STATUS) { - if (isDownloadBeingCancelled) { - return; - } - - var text = message.slice(CLARA_IO_STATUS.length); - if (messageBox === null) { - messageBox = Window.openMessageBox(CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); - } else { - Window.updateMessageBox(messageBox, CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON); - } - return; - } - - if (message.slice(0, CLARA_IO_DOWNLOAD.length) === CLARA_IO_DOWNLOAD) { - if (messageBox !== null) { - Window.closeMessageBox(messageBox); - messageBox = null; - } - return; - } - - if (message === CLARA_IO_CANCELLED_DOWNLOAD) { - isDownloadBeingCancelled = false; - } -} - -marketplaceWindow.webEventReceived.connect(onWebEventReceived); - -function onMessageBoxClosed(id, button) { - if (id === messageBox && button === CANCEL_BUTTON) { - isDownloadBeingCancelled = true; - messageBox = null; - marketplaceWindow.emitScriptEvent(CLARA_IO_CANCEL_DOWNLOAD); - } -} - -Window.messageBoxClosed.connect(onMessageBoxClosed); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; -var marketplaceVisible = false; -var marketplaceWebTablet; - -// We persist clientOnly data in the .ini file, and reconstitute it on restart. -// To keep things consistent, we pickle the tablet data in Settings, and kill any existing such on restart and domain change. -var persistenceKey = "io.highfidelity.lastDomainTablet"; - -function shouldShowWebTablet() { - var rightPose = Controller.getPoseValue(Controller.Standard.RightHand); - var leftPose = Controller.getPoseValue(Controller.Standard.LeftHand); - var hasHydra = !!Controller.Hardware.Hydra; - return HMD.active && (leftPose.valid || rightPose.valid || hasHydra); -} - -function showMarketplace() { - if (shouldShowWebTablet()) { - updateButtonState(true); - marketplaceWebTablet = new WebTablet(MARKETPLACE_URL_INITIAL, null, null, true); - Settings.setValue(persistenceKey, marketplaceWebTablet.pickle()); - marketplaceWebTablet.setScriptURL(MARKETPLACES_INJECT_SCRIPT_URL); - marketplaceWebTablet.getOverlayObject().webEventReceived.connect(onWebEventReceived); - } else { - marketplaceWindow.setURL(MARKETPLACE_URL_INITIAL); - marketplaceWindow.setVisible(true); - } - - marketplaceVisible = true; - UserActivityLogger.openedMarketplace(); -} - -function hideTablet(tablet) { - if (!tablet) { - return; - } - updateButtonState(false); - tablet.destroy(); - marketplaceWebTablet = null; - Settings.setValue(persistenceKey, ""); -} -function clearOldTablet() { // If there was a tablet from previous domain or session, kill it and let it be recreated - var tablet = WebTablet.unpickle(Settings.getValue(persistenceKey, "")); - hideTablet(tablet); -} -function hideMarketplace() { - if (marketplaceWindow.visible) { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); - } else if (marketplaceWebTablet) { - hideTablet(marketplaceWebTablet); - } - marketplaceVisible = false; -} -marketplaceWindow.closed.connect(function () { - marketplaceWindow.setURL("about:blank"); -}); - -function toggleMarketplace() { - if (marketplaceVisible) { - hideMarketplace(); - } else { - showMarketplace(); - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "market.svg", - objectName: "marketplace", - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9 -}); - -function updateButtonState(visible) { - browseExamplesButton.writeProperty('buttonState', visible ? 0 : 1); - browseExamplesButton.writeProperty('defaultState', visible ? 0 : 1); - browseExamplesButton.writeProperty('hoverState', visible ? 2 : 3); -} -function onMarketplaceWindowVisibilityChanged() { - updateButtonState(marketplaceWindow.visible); - marketplaceVisible = marketplaceWindow.visible; -} - -function onCanWriteAssetsChanged() { - var message = CAN_WRITE_ASSETS + " " + Entities.canWriteAssets(); - if (marketplaceWindow.visible) { - marketplaceWindow.emitScriptEvent(message); - } - if (marketplaceWebTablet) { - marketplaceWebTablet.getOverlayObject().emitScriptEvent(message); - } -} - -function onClick() { - toggleMarketplace(); -} - -browseExamplesButton.clicked.connect(onClick); -marketplaceWindow.visibleChanged.connect(onMarketplaceWindowVisibilityChanged); -Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged); - -clearOldTablet(); // Run once at startup, in case there's anything laying around from a crash. -// We could also optionally do something like Window.domainChanged.connect(function () {Script.setTimeout(clearOldTablet, 2000)}), -// but the HUD version stays around, so lets do the same. - -Script.scriptEnding.connect(function () { - toolBar.removeButton("marketplace"); - browseExamplesButton.clicked.disconnect(onClick); - marketplaceWindow.visibleChanged.disconnect(onMarketplaceWindowVisibilityChanged); - Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/mute.js b/scripts/system/mute.js index 03e0d784f1..147e87d3e4 100644 --- a/scripts/system/mute.js +++ b/scripts/system/mute.js @@ -13,30 +13,53 @@ (function() { // BEGIN LOCAL_SCOPE -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - -var button = tablet.addButton({ - icon: "icons/tablet-icons/mic-a.svg", - text: "MUTE", - activeIcon: "icons/tablet-icons/mic-i.svg", - activeText: "UNMUTE" -}); +var button; +var buttonName = "MUTE"; +var toolBar = null; +var tablet = null; function onMuteToggled() { button.editProperties({isActive: AudioDevice.getMuted()}); } -onMuteToggled(); function onClicked(){ var menuItem = "Mute Microphone"; Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem)); } + +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/mic.svg"), + visible: true, + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/mic-a.svg", + text: buttonName, + activeIcon: "icons/// TODO: ablet-icons/mic-i.svg", + activeText: "UNMUTE" + }); +} +onMuteToggled(); + button.clicked.connect(onClicked); AudioDevice.muteToggled.connect(onMuteToggled); Script.scriptEnding.connect(function () { button.clicked.disconnect(onClicked); - tablet.removeButton(button); AudioDevice.muteToggled.disconnect(onMuteToggled); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } }); }()); // END LOCAL_SCOPE diff --git a/scripts/system/muteHUD.js b/scripts/system/muteHUD.js deleted file mode 100644 index 722ed65b3d..0000000000 --- a/scripts/system/muteHUD.js +++ /dev/null @@ -1,51 +0,0 @@ -"use strict"; - -// -// goto.js -// scripts/system/ -// -// Created by Howard Stearns on 2 Jun 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var button = toolBar.addButton({ - objectName: "mute", - imageURL: Script.resolvePath("assets/images/tools/mic.svg"), - visible: true, - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9 -}); - -function onMuteToggled() { - // We could just toggle state, but we're less likely to get out of wack if we read the AudioDevice. - // muted => button "on" state => 1. go figure. - var state = AudioDevice.getMuted() ? 0 : 1; - var hoverState = AudioDevice.getMuted() ? 2 : 3; - button.writeProperty('buttonState', state); - button.writeProperty('defaultState', state); - button.writeProperty('hoverState', hoverState); -} -onMuteToggled(); -function onClicked(){ - var menuItem = "Mute Microphone"; - Menu.setIsOptionChecked(menuItem, !Menu.isOptionChecked(menuItem)); -} -button.clicked.connect(onClicked); -AudioDevice.muteToggled.connect(onMuteToggled); - -Script.scriptEnding.connect(function () { - toolBar.removeButton("mute"); - button.clicked.disconnect(onClicked); - AudioDevice.muteToggled.disconnect(onMuteToggled); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 71d0182d08..7a5546c949 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -477,12 +477,28 @@ triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Cont // // Manage the connection between the button and the window. // -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); +var button; var buttonName = "PAL"; -var button = tablet.addButton({ - text: buttonName, - icon: "icons/tablet-icons/people-i.svg" -}); +var tablet = null; +var toolBar = null; +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/people.svg"), + visible: true, + hoverState: 2, + defaultState: 1, + buttonState: 1, + alpha: 0.9 + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + text: buttonName, + icon: "icons/tablet-icons/people-i.svg" + }); +} var isWired = false; function off() { if (isWired) { // It is not ok to disconnect these twice, hence guard. @@ -623,7 +639,12 @@ Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); // Script.scriptEnding.connect(function () { button.clicked.disconnect(onClicked); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } pal.visibleChanged.disconnect(onVisibleChanged); pal.closed.disconnect(off); Users.usernameFromIDReply.disconnect(usernameFromIDReply); diff --git a/scripts/system/palHUD.js b/scripts/system/palHUD.js deleted file mode 100644 index f148ad5fdb..0000000000 --- a/scripts/system/palHUD.js +++ /dev/null @@ -1,658 +0,0 @@ -"use strict"; -/*jslint vars: true, plusplus: true, forin: true*/ -/*globals Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print, getControllerWorldLocation */ -// -// pal.js -// -// Created by Howard Stearns on December 9, 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 -// - -// hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed -// something, will revisit as this is sorta horrible. -const UNSELECTED_TEXTURES = {"idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png") -}; -const SELECTED_TEXTURES = { "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-selected.png") -}; -const HOVER_TEXTURES = { "idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png"), - "idle-E": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-hover.png") -}; - -const UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6}; -const SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29}; -const HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now - -(function() { // BEGIN LOCAL_SCOPE - -Script.include("/~/system/libraries/controllers.js"); - -// -// Overlays. -// -var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. - -function ExtendedOverlay(key, type, properties, selected, hasModel) { // A wrapper around overlays to store the key it is associated with. - overlays[key] = this; - if (hasModel) { - var modelKey = key + "-m"; - this.model = new ExtendedOverlay(modelKey, "model", { - url: Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx"), - textures: textures(selected), - ignoreRayIntersection: true - }, false, false); - } else { - this.model = undefined; - } - this.key = key; - this.selected = selected || false; // not undefined - this.hovering = false; - this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... -} -// Instance methods: -ExtendedOverlay.prototype.deleteOverlay = function () { // remove display and data of this overlay - Overlays.deleteOverlay(this.activeOverlay); - delete overlays[this.key]; -}; - -ExtendedOverlay.prototype.editOverlay = function (properties) { // change display of this overlay - Overlays.editOverlay(this.activeOverlay, properties); -}; - -function color(selected, hovering, level) { - var base = hovering ? HOVER_COLOR : selected ? SELECTED_COLOR : UNSELECTED_COLOR; - function scale(component) { - var delta = 0xFF - component; - return component + (delta * level); - } - return {red: scale(base.red), green: scale(base.green), blue: scale(base.blue)}; -} - -function textures(selected, hovering) { - return hovering ? HOVER_TEXTURES : selected ? SELECTED_TEXTURES : UNSELECTED_TEXTURES; -} -// so we don't have to traverse the overlays to get the last one -var lastHoveringId = 0; -ExtendedOverlay.prototype.hover = function (hovering) { - this.hovering = hovering; - if (this.key === lastHoveringId) { - if (hovering) { - return; - } else { - lastHoveringId = 0; - } - } - this.editOverlay({color: color(this.selected, hovering, this.audioLevel)}); - if (this.model) { - this.model.editOverlay({textures: textures(this.selected, hovering)}); - } - if (hovering) { - // un-hover the last hovering overlay - if (lastHoveringId && lastHoveringId != this.key) { - ExtendedOverlay.get(lastHoveringId).hover(false); - } - lastHoveringId = this.key; - } -} -ExtendedOverlay.prototype.select = function (selected) { - if (this.selected === selected) { - return; - } - - UserActivityLogger.palAction(selected ? "avatar_selected" : "avatar_deselected", this.key); - - this.editOverlay({color: color(selected, this.hovering, this.audioLevel)}); - if (this.model) { - this.model.editOverlay({textures: textures(selected)}); - } - this.selected = selected; -}; -// Class methods: -var selectedIds = []; -ExtendedOverlay.isSelected = function (id) { - return -1 !== selectedIds.indexOf(id); -}; -ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier - return overlays[key]; -}; -ExtendedOverlay.some = function (iterator) { // Bails early as soon as iterator returns truthy. - var key; - for (key in overlays) { - if (iterator(ExtendedOverlay.get(key))) { - return; - } - } -}; -ExtendedOverlay.unHover = function () { // calls hover(false) on lastHoveringId (if any) - if (lastHoveringId) { - ExtendedOverlay.get(lastHoveringId).hover(false); - } -}; - -// hit(overlay) on the one overlay intersected by pickRay, if any. -// noHit() if no ExtendedOverlay was intersected (helps with hover) -ExtendedOverlay.applyPickRay = function (pickRay, hit, noHit) { - var pickedOverlay = Overlays.findRayIntersection(pickRay); // Depends on nearer coverOverlays to extend closer to us than farther ones. - if (!pickedOverlay.intersects) { - if (noHit) { - return noHit(); - } - return; - } - ExtendedOverlay.some(function (overlay) { // See if pickedOverlay is one of ours. - if ((overlay.activeOverlay) === pickedOverlay.overlayID) { - hit(overlay); - return true; - } - }); -}; - - -// -// Similar, for entities -// -function HighlightedEntity(id, entityProperties) { - this.id = id; - this.overlay = Overlays.addOverlay('cube', { - position: entityProperties.position, - rotation: entityProperties.rotation, - dimensions: entityProperties.dimensions, - solid: false, - color: { - red: 0xF3, - green: 0x91, - blue: 0x29 - }, - lineWidth: 1.0, - ignoreRayIntersection: true, - drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. - }); - HighlightedEntity.overlays.push(this); -} -HighlightedEntity.overlays = []; -HighlightedEntity.clearOverlays = function clearHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - Overlays.deleteOverlay(highlighted.overlay); - }); - HighlightedEntity.overlays = []; -}; -HighlightedEntity.updateOverlays = function updateHighlightedEntities() { - HighlightedEntity.overlays.forEach(function (highlighted) { - var properties = Entities.getEntityProperties(highlighted.id, ['position', 'rotation', 'dimensions']); - Overlays.editOverlay(highlighted.overlay, { - position: properties.position, - rotation: properties.rotation, - dimensions: properties.dimensions - }); - }); -}; - -// -// The qml window and communications. -// -var pal = new OverlayWindow({ - title: 'People Action List', - source: 'hifi/Pal.qml', - width: 580, - height: 640, - visible: false -}); -pal.fromQml.connect(function (message) { // messages are {method, params}, like json-rpc. See also sendToQml. - print('From PAL QML:', JSON.stringify(message)); - switch (message.method) { - case 'selected': - selectedIds = message.params; - ExtendedOverlay.some(function (overlay) { - var id = overlay.key; - var selected = ExtendedOverlay.isSelected(id); - overlay.select(selected); - }); - - HighlightedEntity.clearOverlays(); - if (selectedIds.length) { - Entities.findEntitiesInFrustum(Camera.frustum).forEach(function (id) { - // Because lastEditedBy is per session, the vast majority of entities won't match, - // so it would probably be worth reducing marshalling costs by asking for just we need. - // However, providing property name(s) is advisory and some additional properties are - // included anyway. As it turns out, asking for 'lastEditedBy' gives 'position', 'rotation', - // and 'dimensions', too, so we might as well make use of them instead of making a second - // getEntityProperties call. - // It would be nice if we could harden this against future changes by specifying all - // and only these four in an array, but see - // https://highfidelity.fogbugz.com/f/cases/2728/Entities-getEntityProperties-id-lastEditedBy-name-lastEditedBy-doesn-t-work - var properties = Entities.getEntityProperties(id, 'lastEditedBy'); - if (ExtendedOverlay.isSelected(properties.lastEditedBy)) { - new HighlightedEntity(id, properties); - } - }); - } - break; - case 'refresh': - removeOverlays(); - populateUserList(message.params); - UserActivityLogger.palAction("refresh", ""); - break; - case 'updateGain': - data = message.params; - if (data['isReleased']) { - // isReleased=true happens once at the end of a cycle of dragging - // the slider about, but with same gain as last isReleased=false so - // we don't set the gain in that case, and only here do we want to - // send an analytic event. - UserActivityLogger.palAction("avatar_gain_changed", data['sessionId']); - } else { - Users.setAvatarGain(data['sessionId'], data['gain']); - } - break; - case 'displayNameUpdate': - if (MyAvatar.displayName != message.params) { - MyAvatar.displayName = message.params; - UserActivityLogger.palAction("display_name_change", ""); - } - break; - default: - print('Unrecognized message from Pal.qml:', JSON.stringify(message)); - } -}); - -// -// Main operations. -// -function addAvatarNode(id) { - var selected = ExtendedOverlay.isSelected(id); - return new ExtendedOverlay(id, "sphere", { - drawInFront: true, - solid: true, - alpha: 0.8, - color: color(selected, false, 0.0), - ignoreRayIntersection: false}, selected, true); -} -function populateUserList(selectData) { - var data = []; - AvatarList.getAvatarIdentifiers().sort().forEach(function (id) { // sorting the identifiers is just an aid for debugging - var avatar = AvatarList.getAvatar(id); - var avatarPalDatum = { - displayName: avatar.sessionDisplayName, - userName: '', - sessionId: id || '', - audioLevel: 0.0, - admin: false - }; - // Request the username, fingerprint, and admin status from the given UUID - // Username and fingerprint returns default constructor output if the requesting user isn't an admin - Users.requestUsernameFromID(id); - // Request personal mute status and ignore status - // from NodeList (as long as we're not requesting it for our own ID) - if (id) { - avatarPalDatum['personalMute'] = Users.getPersonalMuteStatus(id); - avatarPalDatum['ignore'] = Users.getIgnoreStatus(id); - addAvatarNode(id); // No overlay for ourselves - } - data.push(avatarPalDatum); - print('PAL data:', JSON.stringify(avatarPalDatum)); - }); - pal.sendToQml({ method: 'users', params: data }); - if (selectData) { - selectData[2] = true; - pal.sendToQml({ method: 'select', params: selectData }); - } -} - -// The function that handles the reply from the server -function usernameFromIDReply(id, username, machineFingerprint, isAdmin) { - var data; - // If the ID we've received is our ID... - if (MyAvatar.sessionUUID === id) { - // Set the data to contain specific strings. - data = ['', username, isAdmin]; - } else if (Users.canKick) { - // Set the data to contain the ID and the username (if we have one) - // or fingerprint (if we don't have a username) string. - data = [id, username || machineFingerprint, isAdmin]; - } else { - // Set the data to contain specific strings. - data = [id, '', isAdmin]; - } - print('Username Data:', JSON.stringify(data)); - // Ship the data off to QML - pal.sendToQml({ method: 'updateUsername', params: data }); -} - -var pingPong = true; -function updateOverlays() { - var eye = Camera.position; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - if (!id) { - return; // don't update ourself - } - - var overlay = ExtendedOverlay.get(id); - if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. - print('Adding non-PAL avatar node', id); - overlay = addAvatarNode(id); - } - var avatar = AvatarList.getAvatar(id); - var target = avatar.position; - var distance = Vec3.distance(target, eye); - var offset = 0.2; - - // base offset on 1/2 distance from hips to head if we can - var headIndex = avatar.getJointIndex("Head"); - if (headIndex > 0) { - offset = avatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y / 2; - } - - // get diff between target and eye (a vector pointing to the eye from avatar position) - var diff = Vec3.subtract(target, eye); - - // move a bit in front, towards the camera - target = Vec3.subtract(target, Vec3.multiply(Vec3.normalize(diff), offset)); - - // now bump it up a bit - target.y = target.y + offset; - - overlay.ping = pingPong; - overlay.editOverlay({ - color: color(ExtendedOverlay.isSelected(id), overlay.hovering, overlay.audioLevel), - position: target, - dimensions: 0.032 * distance - }); - if (overlay.model) { - overlay.model.ping = pingPong; - overlay.model.editOverlay({ - position: target, - scale: 0.2 * distance, // constant apparent size - rotation: Camera.orientation - }); - } - }); - pingPong = !pingPong; - ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) - if (overlay.ping === pingPong) { - overlay.deleteOverlay(); - } - }); - // We could re-populateUserList if anything added or removed, but not for now. - HighlightedEntity.updateOverlays(); -} -function removeOverlays() { - selectedIds = []; - lastHoveringId = 0; - HighlightedEntity.clearOverlays(); - ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); -} - -// -// Clicks. -// -function handleClick(pickRay) { - ExtendedOverlay.applyPickRay(pickRay, function (overlay) { - // Don't select directly. Tell qml, who will give us back a list of ids. - var message = {method: 'select', params: [[overlay.key], !overlay.selected, false]}; - pal.sendToQml(message); - return true; - }); -} -function handleMouseEvent(mousePressEvent) { // handleClick if we get one. - if (!mousePressEvent.isLeftButton) { - return; - } - handleClick(Camera.computePickRay(mousePressEvent.x, mousePressEvent.y)); -} -function handleMouseMove(pickRay) { // given the pickRay, just do the hover logic - ExtendedOverlay.applyPickRay(pickRay, function (overlay) { - overlay.hover(true); - }, function () { - ExtendedOverlay.unHover(); - }); -} - -// handy global to keep track of which hand is the mouse (if any) -var currentHandPressed = 0; -const TRIGGER_CLICK_THRESHOLD = 0.85; -const TRIGGER_PRESS_THRESHOLD = 0.05; - -function handleMouseMoveEvent(event) { // find out which overlay (if any) is over the mouse position - if (HMD.active) { - if (currentHandPressed != 0) { - pickRay = controllerComputePickRay(currentHandPressed); - } else { - // nothing should hover, so - ExtendedOverlay.unHover(); - return; - } - } else { - pickRay = Camera.computePickRay(event.x, event.y); - } - handleMouseMove(pickRay); -} -function handleTriggerPressed(hand, value) { - // The idea is if you press one trigger, it is the one - // we will consider the mouse. Even if the other is pressed, - // we ignore it until this one is no longer pressed. - isPressed = value > TRIGGER_PRESS_THRESHOLD; - if (currentHandPressed == 0) { - currentHandPressed = isPressed ? hand : 0; - return; - } - if (currentHandPressed == hand) { - currentHandPressed = isPressed ? hand : 0; - return; - } - // otherwise, the other hand is still triggered - // so do nothing. -} - -// We get mouseMoveEvents from the handControllers, via handControllerPointer. -// But we don't get mousePressEvents. -var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); -var triggerPressMapping = Controller.newMapping(Script.resolvePath('') + '-press'); -function controllerComputePickRay(hand) { - var controllerPose = getControllerWorldLocation(hand, true); - if (controllerPose.valid) { - return { origin: controllerPose.position, direction: Quat.getUp(controllerPose.orientation) }; - } -} -function makeClickHandler(hand) { - return function (clicked) { - if (clicked > TRIGGER_CLICK_THRESHOLD) { - var pickRay = controllerComputePickRay(hand); - handleClick(pickRay); - } - }; -} -function makePressHandler(hand) { - return function (value) { - handleTriggerPressed(hand, value); - } -} -triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); -triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); -triggerPressMapping.from(Controller.Standard.RT).peek().to(makePressHandler(Controller.Standard.RightHand)); -triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Controller.Standard.LeftHand)); -// -// Message from other scripts, such as edit.js -// -var CHANNEL = 'com.highfidelity.pal'; -function receiveMessage(channel, messageString, senderID) { - if ((channel !== CHANNEL) || - (senderID !== MyAvatar.sessionUUID)) { - return; - } - var message = JSON.parse(messageString); - switch (message.method) { - case 'select': - if (!pal.visible) { - onClicked(); - } - pal.sendToQml(message); // Accepts objects, not just strings. - break; - default: - print('Unrecognized PAL message', messageString); - } -} -Messages.subscribe(CHANNEL); -Messages.messageReceived.connect(receiveMessage); - - -var AVERAGING_RATIO = 0.05; -var LOUDNESS_FLOOR = 11.0; -var LOUDNESS_SCALE = 2.8 / 5.0; -var LOG2 = Math.log(2.0); -var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too) -var myData = {}; // we're not includied in ExtendedOverlay.get. -var audioInterval; - -function getAudioLevel(id) { - // the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged - // But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency - // of updating (the latter for efficiency too). - var avatar = AvatarList.getAvatar(id); - var audioLevel = 0.0; - var data = id ? ExtendedOverlay.get(id) : myData; - if (!data) { - return audioLevel; - } - - // we will do exponential moving average by taking some the last loudness and averaging - data.accumulatedLevel = AVERAGING_RATIO * (data.accumulatedLevel || 0) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness); - - // add 1 to insure we don't go log() and hit -infinity. Math.log is - // natural log, so to get log base 2, just divide by ln(2). - var logLevel = Math.log(data.accumulatedLevel + 1) / LOG2; - - if (logLevel <= LOUDNESS_FLOOR) { - audioLevel = logLevel / LOUDNESS_FLOOR * LOUDNESS_SCALE; - } else { - audioLevel = (logLevel - (LOUDNESS_FLOOR - 1.0)) * LOUDNESS_SCALE; - } - if (audioLevel > 1.0) { - audioLevel = 1; - } - data.audioLevel = audioLevel; - return audioLevel; -} - -function createAudioInterval() { - // we will update the audioLevels periodically - // TODO: tune for efficiency - expecially with large numbers of avatars - return Script.setInterval(function () { - if (pal.visible) { - var param = {}; - AvatarList.getAvatarIdentifiers().forEach(function (id) { - var level = getAudioLevel(id); - // qml didn't like an object with null/empty string for a key, so... - var userId = id || 0; - param[userId] = level; - }); - pal.sendToQml({method: 'updateAudioLevel', params: param}); - } - }, AUDIO_LEVEL_UPDATE_INTERVAL_MS); -} - -// -// Manage the connection between the button and the window. -// -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); -var buttonName = "pal"; -var button = toolBar.addButton({ - objectName: buttonName, - imageURL: Script.resolvePath("assets/images/tools/people.svg"), - visible: true, - hoverState: 2, - defaultState: 1, - buttonState: 1, - alpha: 0.9 -}); - -var isWired = false; -var palOpenedAt; - -function off() { - if (isWired) { // It is not ok to disconnect these twice, hence guard. - Script.update.disconnect(updateOverlays); - Controller.mousePressEvent.disconnect(handleMouseEvent); - Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent); - isWired = false; - } - triggerMapping.disable(); // It's ok if we disable twice. - triggerPressMapping.disable(); // see above - removeOverlays(); - Users.requestsDomainListData = false; - if (palOpenedAt) { - var duration = new Date().getTime() - palOpenedAt; - UserActivityLogger.palOpened(duration / 1000.0); - palOpenedAt = 0; // just a falsy number is good enough. - } - if (audioInterval) { - Script.clearInterval(audioInterval); - } -} -function onClicked() { - if (!pal.visible) { - Users.requestsDomainListData = true; - populateUserList(); - pal.raise(); - isWired = true; - Script.update.connect(updateOverlays); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); - createAudioInterval(); - palOpenedAt = new Date().getTime(); - } else { - off(); - } - pal.setVisible(!pal.visible); -} -function avatarDisconnected(nodeID) { - // remove from the pal list - pal.sendToQml({method: 'avatarDisconnected', params: [nodeID]}); -} -// -// Button state. -// -function onVisibleChanged() { - button.writeProperty('buttonState', pal.visible ? 0 : 1); - button.writeProperty('defaultState', pal.visible ? 0 : 1); - button.writeProperty('hoverState', pal.visible ? 2 : 3); -} -button.clicked.connect(onClicked); -pal.visibleChanged.connect(onVisibleChanged); -pal.closed.connect(off); -Users.usernameFromIDReply.connect(usernameFromIDReply); -Users.avatarDisconnected.connect(avatarDisconnected); - -function clearLocalQMLDataAndClosePAL() { - pal.sendToQml({ method: 'clearLocalQMLData' }); - if (pal.visible) { - onClicked(); // Close the PAL - } -} -Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); -Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); - -// -// Cleanup. -// -Script.scriptEnding.connect(function () { - button.clicked.disconnect(onClicked); - toolBar.removeButton(buttonName); - pal.visibleChanged.disconnect(onVisibleChanged); - pal.closed.disconnect(off); - Users.usernameFromIDReply.disconnect(usernameFromIDReply); - Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); - Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); - Messages.unsubscribe(CHANNEL); - Messages.messageReceived.disconnect(receiveMessage); - Users.avatarDisconnected.disconnect(avatarDisconnected); - off(); -}); - - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 1909061cb1..6d2fb01d29 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -7,19 +7,39 @@ // Distributed under the Apache License, Version 2.0 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* globals Tablet, Toolbars, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar */ (function() { // BEGIN LOCAL_SCOPE var SNAPSHOT_DELAY = 500; // 500ms var FINISH_SOUND_DELAY = 350; -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var resetOverlays; var reticleVisible; var clearOverlayWhenMoving; -var button = tablet.addButton({ - icon: "icons/tablet-icons/snap-i.svg", - text: "SNAP" -}); + +var button; +var buttonName = "SNAP"; +var tablet = null; +var toolBar = null; + +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/snap.svg"), + visible: true, + buttonState: 1, + defaultState: 1, + hoverState: 2, + alpha: 0.9, + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/snap-i.svg", + text: buttonName + }); +} function shouldOpenFeedAfterShare() { var persisted = Settings.getValue('openFeedAfterShare', true); // might answer true, false, "true", or "false" @@ -51,10 +71,10 @@ function confirmShare(data) { Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); break; case 'setOpenFeedFalse': - Settings.setValue('openFeedAfterShare', false) + Settings.setValue('openFeedAfterShare', false); break; case 'setOpenFeedTrue': - Settings.setValue('openFeedAfterShare', true) + Settings.setValue('openFeedAfterShare', true); break; default: dialog.webEventReceived.disconnect(onMessage); @@ -200,7 +220,12 @@ Window.processingGif.connect(processingGif); Script.scriptEnding.connect(function () { button.clicked.disconnect(onClicked); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } Window.snapshotShared.disconnect(snapshotShared); Window.processingGif.disconnect(processingGif); }); diff --git a/scripts/system/snapshotHUD.js b/scripts/system/snapshotHUD.js deleted file mode 100644 index d79a6e46cb..0000000000 --- a/scripts/system/snapshotHUD.js +++ /dev/null @@ -1,226 +0,0 @@ -// -// snapshot.js -// -// Created by David Kelly on 1 August 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -var SNAPSHOT_DELAY = 500; // 500ms -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); -var resetOverlays; -var reticleVisible; -var clearOverlayWhenMoving; -var button = toolBar.addButton({ - objectName: "snapshot", - imageURL: Script.resolvePath("assets/images/tools/snap.svg"), - visible: true, - buttonState: 1, - defaultState: 1, - hoverState: 2, - alpha: 0.9, -}); - -function shouldOpenFeedAfterShare() { - var persisted = Settings.getValue('openFeedAfterShare', true); // might answer true, false, "true", or "false" - return persisted && (persisted !== 'false'); -} -function showFeedWindow() { - DialogsManager.showFeed(); -} - -var SNAPSHOT_REVIEW_URL = Script.resolvePath("html/SnapshotReview.html"); - -var outstanding; -function confirmShare(data) { - var dialog = new OverlayWebWindow('Snapshot Review', SNAPSHOT_REVIEW_URL, 800, 520); - function onMessage(message) { - // Receives message from the html dialog via the qwebchannel EventBridge. This is complicated by the following: - // 1. Although we can send POJOs, we cannot receive a toplevel object. (Arrays of POJOs are fine, though.) - // 2. Although we currently use a single image, we would like to take snapshot, a selfie, a 360 etc. all at the - // same time, show the user all of them, and have the user deselect any that they do not want to share. - // So we'll ultimately be receiving a set of objects, perhaps with different post processing for each. - var isLoggedIn; - var needsLogin = false; - switch (message) { - case 'ready': - dialog.emitScriptEvent(data); // Send it. - outstanding = 0; - break; - case 'openSettings': - Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); - break; - case 'setOpenFeedFalse': - Settings.setValue('openFeedAfterShare', false) - break; - case 'setOpenFeedTrue': - Settings.setValue('openFeedAfterShare', true) - break; - default: - dialog.webEventReceived.disconnect(onMessage); - dialog.close(); - isLoggedIn = Account.isLoggedIn(); - message.forEach(function (submessage) { - if (submessage.share && !isLoggedIn) { - needsLogin = true; - submessage.share = false; - } - if (submessage.share) { - print('sharing', submessage.localPath); - outstanding++; - Window.shareSnapshot(submessage.localPath, submessage.href); - } else { - print('not sharing', submessage.localPath); - } - }); - if (!outstanding && shouldOpenFeedAfterShare()) { - showFeedWindow(); - } - if (needsLogin) { // after the possible feed, so that the login is on top - Account.checkAndSignalForAccessToken(); - } - } - } - dialog.webEventReceived.connect(onMessage); - dialog.raise(); -} - -function snapshotShared(errorMessage) { - if (!errorMessage) { - print('snapshot uploaded and shared'); - } else { - print(errorMessage); - } - if ((--outstanding <= 0) && shouldOpenFeedAfterShare()) { - showFeedWindow(); - } -} -var href, domainId; -function onClicked() { - // Raising the desktop for the share dialog at end will interact badly with clearOverlayWhenMoving. - // Turn it off now, before we start futzing with things (and possibly moving). - clearOverlayWhenMoving = MyAvatar.getClearOverlayWhenMoving(); // Do not use Settings. MyAvatar keeps a separate copy. - MyAvatar.setClearOverlayWhenMoving(false); - - // We will record snapshots based on the starting location. That could change, e.g., when recording a .gif. - // Even the domainId could change (e.g., if the user falls into a teleporter while recording). - href = location.href; - domainId = location.domainId; - - // update button states - resetOverlays = Menu.isOptionChecked("Overlays"); // For completness. Certainly true if the button is visible to be clicke. - reticleVisible = Reticle.visible; - Reticle.visible = false; - Window.snapshotTaken.connect(resetButtons); - - button.writeProperty("buttonState", 0); - button.writeProperty("defaultState", 0); - button.writeProperty("hoverState", 2); - - // hide overlays if they are on - if (resetOverlays) { - Menu.setIsOptionChecked("Overlays", false); - } - - // hide hud - toolBar.writeProperty("visible", false); - - // take snapshot (with no notification) - Script.setTimeout(function () { - Window.takeSnapshot(false, true, 1.91); - }, SNAPSHOT_DELAY); -} - -function isDomainOpen(id) { - var request = new XMLHttpRequest(); - var options = [ - 'now=' + new Date().toISOString(), - 'include_actions=concurrency', - 'domain_id=' + id.slice(1, -1), - 'restriction=open,hifi' // If we're sharing, we're logged in - // If we're here, protocol matches, and it is online - ]; - var url = location.metaverseServerUrl + "/api/v1/user_stories?" + options.join('&'); - request.open("GET", url, false); - request.send(); - if (request.status != 200) { - return false; - } - var response = JSON.parse(request.response); // Not parsed for us. - return (response.status === 'success') && - response.total_entries; -} - -function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) { - // If we're not taking an animated snapshot, we have to show the HUD. - // If we ARE taking an animated snapshot, we've already re-enabled the HUD by this point. - if (pathAnimatedSnapshot === "") { - // show hud - toolBar.writeProperty("visible", true); - Reticle.visible = reticleVisible; - // show overlays if they were on - if (resetOverlays) { - Menu.setIsOptionChecked("Overlays", true); - } - } else { - // Allow the user to click the snapshot HUD button again - button.clicked.connect(onClicked); - } - // update button states - button.writeProperty("buttonState", 1); - button.writeProperty("defaultState", 1); - button.writeProperty("hoverState", 3); - Window.snapshotTaken.disconnect(resetButtons); - - // A Snapshot Review dialog might be left open indefinitely after taking the picture, - // during which time the user may have moved. So stash that info in the dialog so that - // it records the correct href. (We can also stash in .jpegs, but not .gifs.) - // last element in data array tells dialog whether we can share or not - var confirmShareContents = [ - { localPath: pathStillSnapshot, href: href }, - { - canShare: !!isDomainOpen(domainId), - openFeedAfterShare: shouldOpenFeedAfterShare() - }]; - if (pathAnimatedSnapshot !== "") { - confirmShareContents.unshift({ localPath: pathAnimatedSnapshot, href: href }); - } - confirmShare(confirmShareContents); - if (clearOverlayWhenMoving) { - MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog - } -} - -function processingGif() { - // show hud - toolBar.writeProperty("visible", true); - Reticle.visible = reticleVisible; - - // update button states - button.writeProperty("buttonState", 0); - button.writeProperty("defaultState", 0); - button.writeProperty("hoverState", 2); - // Don't allow the user to click the snapshot button yet - button.clicked.disconnect(onClicked); - // show overlays if they were on - if (resetOverlays) { - Menu.setIsOptionChecked("Overlays", true); - } -} - -button.clicked.connect(onClicked); -Window.snapshotShared.connect(snapshotShared); -Window.processingGif.connect(processingGif); - -Script.scriptEnding.connect(function () { - toolBar.removeButton("snapshot"); - button.clicked.disconnect(onClicked); - Window.snapshotShared.disconnect(snapshotShared); - Window.processingGif.disconnect(processingGif); -}); - -}()); // END LOCAL_SCOPE diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 017f9c0958..942534e3b6 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -108,6 +108,6 @@ Script.scriptEnding.connect(function () { Entities.deleteEntity(HMD.tabletID); HMD.tabletID = null; - HDM.homeButtonID = null; + HMD.homeButtonID = null; }); }()); // END LOCAL_SCOPE diff --git a/scripts/system/users.js b/scripts/system/users.js index 4c9663e203..b081768543 100644 --- a/scripts/system/users.js +++ b/scripts/system/users.js @@ -10,16 +10,37 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/*globals HMD, Toolbars, Script, Menu, Overlays, Tablet, Controller, Settings, OverlayWebWindow, Account, GlobalServices */ (function() { // BEGIN LOCAL_SCOPE +var button; +var buttonName = "USERS"; +var toolBar = null; +var tablet = null; + var MENU_ITEM = "Users Online"; -// create tablet button -var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); -var button = tablet.addButton({ - icon: "icons/tablet-icons/people-i.svg", - text: "Users", - isActive: Menu.isOptionChecked(MENU_ITEM) -}); + +if (HMD.hudUIEnabled) { + toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/people.svg"), + visible: true, + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 + }); +} else { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + button = tablet.addButton({ + icon: "icons/tablet-icons/people-i.svg", + text: "Users", + isActive: Menu.isOptionChecked(MENU_ITEM) + }); +} + + function onClicked() { Menu.setIsOptionChecked(MENU_ITEM, !Menu.isOptionChecked(MENU_ITEM)); button.editProperties({isActive: Menu.isOptionChecked(MENU_ITEM)}); @@ -442,11 +463,11 @@ var usersWindow = (function () { } // Reserve space for title, friends button, and option controls - nonUsersHeight = WINDOW_MARGIN + windowLineHeight - + (shouldShowFriendsButton() ? FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT : 0) - + DISPLAY_SPACER - + windowLineHeight + VISIBILITY_SPACER - + windowLineHeight + WINDOW_BASE_MARGIN; + nonUsersHeight = WINDOW_MARGIN + windowLineHeight + + (shouldShowFriendsButton() ? FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT : 0) + + DISPLAY_SPACER + + windowLineHeight + VISIBILITY_SPACER + + windowLineHeight + WINDOW_BASE_MARGIN; // Limit window to height of viewport above window position minus VU meter and mirror if displayed windowHeight = linesOfUsers.length * windowLineHeight - windowLineSpacing + nonUsersHeight; @@ -504,8 +525,8 @@ var usersWindow = (function () { x: scrollbarBackgroundPosition.x, y: scrollbarBackgroundPosition.y }); - scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 - + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2); + scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 + + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2); Overlays.editOverlay(scrollbarBar, { x: scrollbarBackgroundPosition.x + 1, y: scrollbarBarPosition.y @@ -513,10 +534,10 @@ var usersWindow = (function () { x = windowLeft + WINDOW_MARGIN; - y = windowPosition.y - - DISPLAY_SPACER - - windowLineHeight - VISIBILITY_SPACER - - windowLineHeight - WINDOW_BASE_MARGIN; + y = windowPosition.y - + DISPLAY_SPACER - + windowLineHeight - VISIBILITY_SPACER - + windowLineHeight - WINDOW_BASE_MARGIN; if (shouldShowFriendsButton()) { y -= FRIENDS_BUTTON_HEIGHT; Overlays.editOverlay(friendsButton, { @@ -811,8 +832,8 @@ var usersWindow = (function () { userClicked = firstUserToDisplay + lineClicked; - if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX - && overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) { + if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX && + overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) { //print("Go to " + usersOnline[linesOfUsers[userClicked]].username); location.goToUser(usersOnline[linesOfUsers[userClicked]].username); } @@ -885,12 +906,12 @@ var usersWindow = (function () { } if (isMovingScrollbar) { - if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x - && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN - && scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y - && event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) { - scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) - / (scrollbarBackgroundHeight - scrollbarBarHeight - 2); + if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x && + event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN && + scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y && + event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) { + scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) / + (scrollbarBackgroundHeight - scrollbarBarHeight - 2); scrollbarValue = Math.min(Math.max(scrollbarValue, 0.0), 1.0); firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); updateOverlayPositions(); @@ -918,13 +939,13 @@ var usersWindow = (function () { isVisible = isBorderVisible; if (isVisible) { - isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x - && event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH - && windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y - && event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN; + isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x && + event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH && + windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y && + event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN; } else { - isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH - && windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y; + isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH && + windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y; } if (isVisible !== isBorderVisible) { isBorderVisible = isVisible; @@ -951,10 +972,10 @@ var usersWindow = (function () { if (isMovingWindow) { // Save offset of bottom of window to nearest edge of the window. - offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2) - ? windowPosition.x : windowPosition.x - viewport.x; - offset.y = (windowPosition.y < viewport.y / 2) - ? windowPosition.y : windowPosition.y - viewport.y; + offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2) ? + windowPosition.x : windowPosition.x - viewport.x; + offset.y = (windowPosition.y < viewport.y / 2) ? + windowPosition.y : windowPosition.y - viewport.y; Settings.setValue(SETTING_USERS_WINDOW_OFFSET, JSON.stringify(offset)); isMovingWindow = false; } @@ -975,8 +996,8 @@ var usersWindow = (function () { isMirrorDisplay = Menu.isOptionChecked(MIRROR_MENU_ITEM); isFullscreenMirror = Menu.isOptionChecked(FULLSCREEN_MIRROR_MENU_ITEM); - if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay - || isFullscreenMirror !== oldIsFullscreenMirror) { + if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay || + isFullscreenMirror !== oldIsFullscreenMirror) { calculateWindowHeight(); updateUsersDisplay(); } @@ -1250,7 +1271,12 @@ var usersWindow = (function () { function cleanup () { //remove tablet button button.clicked.disconnect(onClicked); - tablet.removeButton(button); + if (tablet) { + tablet.removeButton(button); + } + if (toolBar) { + toolBar.removeButton(buttonName); + } } Script.scriptEnding.connect(cleanup); diff --git a/scripts/system/usersHUD.js b/scripts/system/usersHUD.js deleted file mode 100644 index 8c52240aa9..0000000000 --- a/scripts/system/usersHUD.js +++ /dev/null @@ -1,1237 +0,0 @@ -"use strict"; - -// -// users.js -// examples -// -// Created by David Rowe on 9 Mar 2015. -// 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 -// - -(function() { // BEGIN LOCAL_SCOPE - -// resolve these paths immediately -var MIN_MAX_BUTTON_SVG = Script.resolvePath("assets/images/tools/min-max-toggle.svg"); -var BASE_URL = Script.resolvePath("assets/images/tools/"); - -var PopUpMenu = function (properties) { - var value = properties.value, - promptOverlay, - valueOverlay, - buttonOverlay, - optionOverlays = [], - isDisplayingOptions = false, - OPTION_MARGIN = 4, - - MIN_MAX_BUTTON_SVG_WIDTH = 17.1, - MIN_MAX_BUTTON_SVG_HEIGHT = 32.5, - MIN_MAX_BUTTON_WIDTH = 14, - MIN_MAX_BUTTON_HEIGHT = MIN_MAX_BUTTON_WIDTH; - - function positionDisplayOptions() { - var y, - i; - - y = properties.y - (properties.values.length - 1) * properties.lineHeight - OPTION_MARGIN; - - for (i = 0; i < properties.values.length; i += 1) { - Overlays.editOverlay(optionOverlays[i], { - y: y - }); - y += properties.lineHeight; - } - } - - function showDisplayOptions() { - var i, - yOffScreen = Controller.getViewportDimensions().y; - - for (i = 0; i < properties.values.length; i += 1) { - optionOverlays[i] = Overlays.addOverlay("text", { - x: properties.x + properties.promptWidth, - y: yOffScreen, - width: properties.width - properties.promptWidth, - height: properties.textHeight + OPTION_MARGIN, // Only need to add margin at top to balance descenders - topMargin: OPTION_MARGIN, - leftMargin: OPTION_MARGIN, - color: properties.optionColor, - alpha: properties.optionAlpha, - backgroundColor: properties.popupBackgroundColor, - backgroundAlpha: properties.popupBackgroundAlpha, - text: properties.displayValues[i], - font: properties.font, - visible: true - }); - } - - positionDisplayOptions(); - - isDisplayingOptions = true; - } - - function deleteDisplayOptions() { - var i; - - for (i = 0; i < optionOverlays.length; i += 1) { - Overlays.deleteOverlay(optionOverlays[i]); - } - - isDisplayingOptions = false; - } - - function handleClick(overlay) { - var clicked = false, - i; - - if (overlay === valueOverlay || overlay === buttonOverlay) { - showDisplayOptions(); - return true; - } - - if (isDisplayingOptions) { - for (i = 0; i < optionOverlays.length; i += 1) { - if (overlay === optionOverlays[i]) { - value = properties.values[i]; - Overlays.editOverlay(valueOverlay, { - text: properties.displayValues[i] - }); - clicked = true; - } - } - - deleteDisplayOptions(); - } - - return clicked; - } - - function updatePosition(x, y) { - properties.x = x; - properties.y = y; - Overlays.editOverlay(promptOverlay, { - x: x, - y: y - }); - Overlays.editOverlay(valueOverlay, { - x: x + properties.promptWidth, - y: y - OPTION_MARGIN - }); - Overlays.editOverlay(buttonOverlay, { - x: x + properties.width - MIN_MAX_BUTTON_WIDTH - 1, - y: y - OPTION_MARGIN + 1 - }); - if (isDisplayingOptions) { - positionDisplayOptions(); - } - } - - function setVisible(visible) { - Overlays.editOverlay(promptOverlay, { - visible: visible - }); - Overlays.editOverlay(valueOverlay, { - visible: visible - }); - Overlays.editOverlay(buttonOverlay, { - visible: visible - }); - } - - function tearDown() { - Overlays.deleteOverlay(promptOverlay); - Overlays.deleteOverlay(valueOverlay); - Overlays.deleteOverlay(buttonOverlay); - if (isDisplayingOptions) { - deleteDisplayOptions(); - } - } - - function getValue() { - return value; - } - - function setValue(newValue) { - var index; - - index = properties.values.indexOf(newValue); - if (index !== -1) { - value = newValue; - Overlays.editOverlay(valueOverlay, { - text: properties.displayValues[index] - }); - } - } - - promptOverlay = Overlays.addOverlay("text", { - x: properties.x, - y: properties.y, - width: properties.promptWidth, - height: properties.textHeight, - topMargin: 0, - leftMargin: 0, - color: properties.promptColor, - alpha: properties.promptAlpha, - backgroundColor: properties.promptBackgroundColor, - backgroundAlpha: properties.promptBackgroundAlpha, - text: properties.prompt, - font: properties.font, - visible: properties.visible - }); - - valueOverlay = Overlays.addOverlay("text", { - x: properties.x + properties.promptWidth, - y: properties.y, - width: properties.width - properties.promptWidth, - height: properties.textHeight + OPTION_MARGIN, // Only need to add margin at top to balance descenders - topMargin: OPTION_MARGIN, - leftMargin: OPTION_MARGIN, - color: properties.optionColor, - alpha: properties.optionAlpha, - backgroundColor: properties.optionBackgroundColor, - backgroundAlpha: properties.optionBackgroundAlpha, - text: properties.displayValues[properties.values.indexOf(value)], - font: properties.font, - visible: properties.visible - }); - - buttonOverlay = Overlays.addOverlay("image", { - x: properties.x + properties.width - MIN_MAX_BUTTON_WIDTH - 1, - y: properties.y, - width: MIN_MAX_BUTTON_WIDTH, - height: MIN_MAX_BUTTON_HEIGHT, - imageURL: MIN_MAX_BUTTON_SVG, - subImage: { - x: 0, - y: 0, - width: MIN_MAX_BUTTON_SVG_WIDTH, - height: MIN_MAX_BUTTON_SVG_HEIGHT / 2 - }, - //color: properties.buttonColor, - alpha: properties.buttonAlpha, - visible: properties.visible - }); - - return { - updatePosition: updatePosition, - setVisible: setVisible, - handleClick: handleClick, - tearDown: tearDown, - getValue: getValue, - setValue: setValue - }; -}; - -var usersWindow = (function () { - - var WINDOW_WIDTH = 260, - WINDOW_MARGIN = 12, - WINDOW_BASE_MARGIN = 24, // A little less is needed in order look correct - WINDOW_FONT = { - size: 12 - }, - WINDOW_FOREGROUND_COLOR = { - red: 240, - green: 240, - blue: 240 - }, - WINDOW_FOREGROUND_ALPHA = 0.95, - WINDOW_HEADING_COLOR = { - red: 180, - green: 180, - blue: 180 - }, - WINDOW_HEADING_ALPHA = 0.95, - WINDOW_BACKGROUND_COLOR = { - red: 80, - green: 80, - blue: 80 - }, - WINDOW_BACKGROUND_ALPHA = 0.8, - windowPane, - windowHeading, - - // Margin on the left and right side of the window to keep - // it from getting too close to the edge of the screen which - // is unclickable. - WINDOW_MARGIN_X = 20, - - // Window border is similar to that of edit.js. - WINDOW_MARGIN_HALF = WINDOW_MARGIN / 2, - WINDOW_BORDER_WIDTH = WINDOW_WIDTH + 2 * WINDOW_MARGIN_HALF, - WINDOW_BORDER_TOP_MARGIN = 2 * WINDOW_MARGIN_HALF, - WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_MARGIN_HALF, - WINDOW_BORDER_LEFT_MARGIN = WINDOW_MARGIN_HALF, - WINDOW_BORDER_RADIUS = 4, - WINDOW_BORDER_COLOR = { red: 255, green: 255, blue: 255 }, - WINDOW_BORDER_ALPHA = 0.5, - windowBorder, - - MIN_MAX_BUTTON_SVG = BASE_URL + "min-max-toggle.svg", - MIN_MAX_BUTTON_SVG_WIDTH = 17.1, - MIN_MAX_BUTTON_SVG_HEIGHT = 32.5, - MIN_MAX_BUTTON_WIDTH = 14, - MIN_MAX_BUTTON_HEIGHT = MIN_MAX_BUTTON_WIDTH, - MIN_MAX_BUTTON_COLOR = { - red: 255, - green: 255, - blue: 255 - }, - MIN_MAX_BUTTON_ALPHA = 0.9, - minimizeButton, - SCROLLBAR_BACKGROUND_WIDTH = 12, - SCROLLBAR_BACKGROUND_COLOR = { - red: 70, - green: 70, - blue: 70 - }, - SCROLLBAR_BACKGROUND_ALPHA = 0.8, - scrollbarBackground, - SCROLLBAR_BAR_MIN_HEIGHT = 5, - SCROLLBAR_BAR_COLOR = { - red: 170, - green: 170, - blue: 170 - }, - SCROLLBAR_BAR_ALPHA = 0.8, - SCROLLBAR_BAR_SELECTED_ALPHA = 0.95, - scrollbarBar, - scrollbarBackgroundHeight, - scrollbarBarHeight, - FRIENDS_BUTTON_SPACER = 6, // Space before add/remove friends button - FRIENDS_BUTTON_SVG = BASE_URL + "add-remove-friends.svg", - FRIENDS_BUTTON_SVG_WIDTH = 107, - FRIENDS_BUTTON_SVG_HEIGHT = 27, - FRIENDS_BUTTON_WIDTH = FRIENDS_BUTTON_SVG_WIDTH, - FRIENDS_BUTTON_HEIGHT = FRIENDS_BUTTON_SVG_HEIGHT, - FRIENDS_BUTTON_COLOR = { - red: 225, - green: 225, - blue: 225 - }, - FRIENDS_BUTTON_ALPHA = 0.95, - FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends", - FRIENDS_WINDOW_WIDTH = 290, - FRIENDS_WINDOW_HEIGHT = 500, - FRIENDS_WINDOW_TITLE = "Add/Remove Friends", - friendsButton, - friendsWindow, - - OPTION_BACKGROUND_COLOR = { - red: 60, - green: 60, - blue: 60 - }, - OPTION_BACKGROUND_ALPHA = 0.1, - - DISPLAY_SPACER = 12, // Space before display control - DISPLAY_PROMPT = "Show me:", - DISPLAY_PROMPT_WIDTH = 60, - DISPLAY_EVERYONE = "everyone", - DISPLAY_FRIENDS = "friends", - DISPLAY_VALUES = [DISPLAY_EVERYONE, DISPLAY_FRIENDS], - DISPLAY_DISPLAY_VALUES = DISPLAY_VALUES, - DISPLAY_OPTIONS_BACKGROUND_COLOR = { - red: 120, - green: 120, - blue: 120 - }, - DISPLAY_OPTIONS_BACKGROUND_ALPHA = 0.9, - displayControl, - - VISIBILITY_SPACER = 6, // Space before visibility control - VISIBILITY_PROMPT = "Visible to:", - VISIBILITY_PROMPT_WIDTH = 60, - VISIBILITY_ALL = "all", - VISIBILITY_FRIENDS = "friends", - VISIBILITY_NONE = "none", - VISIBILITY_VALUES = [VISIBILITY_ALL, VISIBILITY_FRIENDS, VISIBILITY_NONE], - VISIBILITY_DISPLAY_VALUES = ["everyone", "friends", "no one"], - visibilityControl, - - windowHeight, - windowBorderHeight, - windowTextHeight, - windowLineSpacing, - windowLineHeight, // = windowTextHeight + windowLineSpacing - windowMinimumHeight, - - usersOnline, // Raw users data - linesOfUsers = [], // Array of indexes pointing into usersOnline - numUsersToDisplay = 0, - firstUserToDisplay = 0, - - API_URL = "https://metaverse.highfidelity.com/api/v1/users?status=online", - API_FRIENDS_FILTER = "&filter=friends", - HTTP_GET_TIMEOUT = 60000, // ms = 1 minute - usersRequest, - processUsers, - pollUsersTimedOut, - usersTimer = null, - USERS_UPDATE_TIMEOUT = 5000, // ms = 5s - - showMe, - myVisibility, - - MENU_NAME = "View", - MENU_ITEM = "Users Online", - MENU_ITEM_OVERLAYS = "Overlays", - MENU_ITEM_AFTER = MENU_ITEM_OVERLAYS, - - SETTING_USERS_SHOW_ME = "UsersWindow.ShowMe", - SETTING_USERS_VISIBLE_TO = "UsersWindow.VisibleTo", - SETTING_USERS_WINDOW_MINIMIZED = "UsersWindow.Minimized", - SETTING_USERS_WINDOW_OFFSET = "UsersWindow.Offset", - // +ve x, y values are offset from left, top of screen; -ve from right, bottom. - - isLoggedIn = false, - isVisible = true, - isMinimized = false, - isBorderVisible = false, - - viewport, - isMirrorDisplay = false, - isFullscreenMirror = false, - - windowPosition = {}, // Bottom left corner of window pane. - isMovingWindow = false, - movingClickOffset = { x: 0, y: 0 }, - - isUsingScrollbars = false, - isMovingScrollbar = false, - scrollbarBackgroundPosition = {}, - scrollbarBarPosition = {}, - scrollbarBarClickedAt, // 0.0 .. 1.0 - scrollbarValue = 0.0; // 0.0 .. 1.0 - - function isWindowDisabled() { - return !Menu.isOptionChecked(MENU_ITEM) || !Menu.isOptionChecked(MENU_ITEM_OVERLAYS); - } - - function isValueTrue(value) { - // Work around Boolean Settings values being read as string when Interface starts up but as Booleans when re-read after - // Being written if refresh script. - return value === true || value === "true"; - } - - function calculateWindowHeight() { - var AUDIO_METER_HEIGHT = 52, - MIRROR_HEIGHT = 220, - nonUsersHeight, - maxWindowHeight; - - if (isMinimized) { - windowHeight = windowTextHeight + WINDOW_MARGIN + WINDOW_BASE_MARGIN; - windowBorderHeight = windowHeight + WINDOW_BORDER_TOP_MARGIN + WINDOW_BORDER_BOTTOM_MARGIN; - return; - } - - // Reserve space for title, friends button, and option controls - nonUsersHeight = WINDOW_MARGIN + windowLineHeight - + (shouldShowFriendsButton() ? FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT : 0) - + DISPLAY_SPACER - + windowLineHeight + VISIBILITY_SPACER - + windowLineHeight + WINDOW_BASE_MARGIN; - - // Limit window to height of viewport above window position minus VU meter and mirror if displayed - windowHeight = linesOfUsers.length * windowLineHeight - windowLineSpacing + nonUsersHeight; - maxWindowHeight = windowPosition.y - AUDIO_METER_HEIGHT; - if (isMirrorDisplay && !isFullscreenMirror) { - maxWindowHeight -= MIRROR_HEIGHT; - } - windowHeight = Math.max(Math.min(windowHeight, maxWindowHeight), nonUsersHeight); - windowBorderHeight = windowHeight + WINDOW_BORDER_TOP_MARGIN + WINDOW_BORDER_BOTTOM_MARGIN; - - // Corresponding number of users to actually display - numUsersToDisplay = Math.max(Math.round((windowHeight - nonUsersHeight) / windowLineHeight), 0); - isUsingScrollbars = 0 < numUsersToDisplay && numUsersToDisplay < linesOfUsers.length; - if (isUsingScrollbars) { - firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); - } else { - firstUserToDisplay = 0; - scrollbarValue = 0.0; - } - } - - function saturateWindowPosition() { - windowPosition.x = Math.max(WINDOW_MARGIN_X, Math.min(viewport.x - WINDOW_WIDTH - WINDOW_MARGIN_X, windowPosition.x)); - windowPosition.y = Math.max(windowMinimumHeight, Math.min(viewport.y, windowPosition.y)); - } - - function updateOverlayPositions() { - // Overlay positions are all relative to windowPosition; windowPosition is the position of the windowPane overlay. - var windowLeft = windowPosition.x, - windowTop = windowPosition.y - windowHeight, - x, - y; - - Overlays.editOverlay(windowBorder, { - x: windowPosition.x - WINDOW_BORDER_LEFT_MARGIN, - y: windowTop - WINDOW_BORDER_TOP_MARGIN - }); - Overlays.editOverlay(windowPane, { - x: windowLeft, - y: windowTop - }); - Overlays.editOverlay(windowHeading, { - x: windowLeft + WINDOW_MARGIN, - y: windowTop + WINDOW_MARGIN - }); - - Overlays.editOverlay(minimizeButton, { - x: windowLeft + WINDOW_WIDTH - WINDOW_MARGIN / 2 - MIN_MAX_BUTTON_WIDTH, - y: windowTop + WINDOW_MARGIN - }); - - scrollbarBackgroundPosition.x = windowLeft + WINDOW_WIDTH - 0.5 * WINDOW_MARGIN - SCROLLBAR_BACKGROUND_WIDTH; - scrollbarBackgroundPosition.y = windowTop + WINDOW_MARGIN + windowTextHeight; - Overlays.editOverlay(scrollbarBackground, { - x: scrollbarBackgroundPosition.x, - y: scrollbarBackgroundPosition.y - }); - scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 - + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2); - Overlays.editOverlay(scrollbarBar, { - x: scrollbarBackgroundPosition.x + 1, - y: scrollbarBarPosition.y - }); - - - x = windowLeft + WINDOW_MARGIN; - y = windowPosition.y - - DISPLAY_SPACER - - windowLineHeight - VISIBILITY_SPACER - - windowLineHeight - WINDOW_BASE_MARGIN; - if (shouldShowFriendsButton()) { - y -= FRIENDS_BUTTON_HEIGHT; - Overlays.editOverlay(friendsButton, { - x: x, - y: y - }); - y += FRIENDS_BUTTON_HEIGHT; - } - - y += DISPLAY_SPACER; - displayControl.updatePosition(x, y); - - y += windowLineHeight + VISIBILITY_SPACER; - visibilityControl.updatePosition(x, y); - } - - function updateUsersDisplay() { - var displayText = "", - user, - userText, - textWidth, - maxTextWidth, - ellipsisWidth, - reducedTextWidth, - i; - - if (!isMinimized) { - maxTextWidth = WINDOW_WIDTH - (isUsingScrollbars ? SCROLLBAR_BACKGROUND_WIDTH : 0) - 2 * WINDOW_MARGIN; - ellipsisWidth = Overlays.textSize(windowPane, "...").width; - reducedTextWidth = maxTextWidth - ellipsisWidth; - - for (i = 0; i < numUsersToDisplay; i += 1) { - user = usersOnline[linesOfUsers[firstUserToDisplay + i]]; - userText = user.text; - textWidth = user.textWidth; - - if (textWidth > maxTextWidth) { - // Trim and append "..." to fit window width - maxTextWidth = maxTextWidth - Overlays.textSize(windowPane, "...").width; - while (textWidth > reducedTextWidth) { - userText = userText.slice(0, -1); - textWidth = Overlays.textSize(windowPane, userText).width; - } - userText += "..."; - } - - displayText += "\n" + userText; - } - - displayText = displayText.slice(1); // Remove leading "\n". - - scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2; - Overlays.editOverlay(scrollbarBackground, { - height: scrollbarBackgroundHeight, - visible: isLoggedIn && isUsingScrollbars - }); - scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight, - SCROLLBAR_BAR_MIN_HEIGHT); - Overlays.editOverlay(scrollbarBar, { - height: scrollbarBarHeight, - visible: isLoggedIn && isUsingScrollbars - }); - } - - Overlays.editOverlay(windowBorder, { - height: windowBorderHeight - }); - - Overlays.editOverlay(windowPane, { - height: windowHeight, - text: displayText - }); - - Overlays.editOverlay(windowHeading, { - text: isLoggedIn ? (linesOfUsers.length > 0 ? "Users online" : "No users online") : "Users online - log in to view" - }); - } - - function shouldShowFriendsButton() { - return isVisible && isLoggedIn && !isMinimized; - } - - function updateOverlayVisibility() { - Overlays.editOverlay(windowBorder, { - visible: isVisible && isBorderVisible - }); - Overlays.editOverlay(windowPane, { - visible: isVisible - }); - Overlays.editOverlay(windowHeading, { - visible: isVisible - }); - Overlays.editOverlay(minimizeButton, { - visible: isVisible - }); - Overlays.editOverlay(scrollbarBackground, { - visible: isVisible && isUsingScrollbars && !isMinimized - }); - Overlays.editOverlay(scrollbarBar, { - visible: isVisible && isUsingScrollbars && !isMinimized - }); - Overlays.editOverlay(friendsButton, { - visible: shouldShowFriendsButton() - }); - displayControl.setVisible(isVisible && !isMinimized); - visibilityControl.setVisible(isVisible && !isMinimized); - } - - function checkLoggedIn() { - var wasLoggedIn = isLoggedIn; - - isLoggedIn = Account.isLoggedIn(); - if (isLoggedIn !== wasLoggedIn) { - if (wasLoggedIn) { - setMinimized(true); - calculateWindowHeight(); - updateOverlayPositions(); - updateUsersDisplay(); - } - - updateOverlayVisibility(); - } - } - - function pollUsers() { - var url = API_URL; - - if (showMe === DISPLAY_FRIENDS) { - url += API_FRIENDS_FILTER; - } - - usersRequest = new XMLHttpRequest(); - usersRequest.open("GET", url, true); - usersRequest.timeout = HTTP_GET_TIMEOUT; - usersRequest.ontimeout = pollUsersTimedOut; - usersRequest.onreadystatechange = processUsers; - usersRequest.send(); - } - - processUsers = function () { - var response, - myUsername, - user, - userText, - i; - - if (usersRequest.readyState === usersRequest.DONE) { - if (usersRequest.status === 200) { - response = JSON.parse(usersRequest.responseText); - if (response.status !== "success") { - print("Error: Request for users status returned status = " + response.status); - usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay. - return; - } - if (!response.hasOwnProperty("data") || !response.data.hasOwnProperty("users")) { - print("Error: Request for users status returned invalid data"); - usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay. - return; - } - - usersOnline = response.data.users; - myUsername = GlobalServices.username; - linesOfUsers = []; - for (i = 0; i < usersOnline.length; i += 1) { - user = usersOnline[i]; - if (user.username !== myUsername && user.online) { - userText = user.username; - if (user.location.root) { - userText += " @ " + user.location.root.name; - } - - usersOnline[i].text = userText; - usersOnline[i].textWidth = Overlays.textSize(windowPane, userText).width; - - linesOfUsers.push(i); - } - } - - checkLoggedIn(); - calculateWindowHeight(); - updateUsersDisplay(); - updateOverlayPositions(); - - } else { - print("Error: Request for users status returned " + usersRequest.status + " " + usersRequest.statusText); - usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay. - return; - } - - usersTimer = Script.setTimeout(pollUsers, USERS_UPDATE_TIMEOUT); // Update after finished processing. - } - }; - - pollUsersTimedOut = function () { - print("Error: Request for users status timed out"); - usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay. - }; - - function setVisible(visible) { - isVisible = visible; - - if (isVisible) { - if (usersTimer === null) { - pollUsers(); - } - } else { - Script.clearTimeout(usersTimer); - usersTimer = null; - } - - updateOverlayVisibility(); - } - - function setMinimized(minimized) { - isMinimized = minimized; - Overlays.editOverlay(minimizeButton, { - subImage: { - y: isMinimized ? MIN_MAX_BUTTON_SVG_HEIGHT / 2 : 0 - } - }); - updateOverlayVisibility(); - Settings.setValue(SETTING_USERS_WINDOW_MINIMIZED, isMinimized); - } - - function onMenuItemEvent(event) { - if (event === MENU_ITEM) { - setVisible(Menu.isOptionChecked(MENU_ITEM)); - } - } - - function onFindableByChanged(event) { - if (VISIBILITY_VALUES.indexOf(event) !== -1) { - myVisibility = event; - visibilityControl.setValue(event); - Settings.setValue(SETTING_USERS_VISIBLE_TO, myVisibility); - } else { - print("Error: Unrecognized onFindableByChanged value: " + event); - } - } - - function onMousePressEvent(event) { - var clickedOverlay, - numLinesBefore, - overlayX, - overlayY, - minY, - maxY, - lineClicked, - userClicked, - delta; - - if (!isVisible || isWindowDisabled()) { - return; - } - - clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - - if (displayControl.handleClick(clickedOverlay)) { - if (usersTimer !== null) { - Script.clearTimeout(usersTimer); - usersTimer = null; - } - pollUsers(); - showMe = displayControl.getValue(); - Settings.setValue(SETTING_USERS_SHOW_ME, showMe); - return; - } - - if (visibilityControl.handleClick(clickedOverlay)) { - myVisibility = visibilityControl.getValue(); - GlobalServices.findableBy = myVisibility; - Settings.setValue(SETTING_USERS_VISIBLE_TO, myVisibility); - return; - } - - if (clickedOverlay === windowPane) { - - overlayX = event.x - windowPosition.x - WINDOW_MARGIN; - overlayY = event.y - windowPosition.y + windowHeight - WINDOW_MARGIN - windowLineHeight; - - numLinesBefore = Math.round(overlayY / windowLineHeight); - minY = numLinesBefore * windowLineHeight; - maxY = minY + windowTextHeight; - - lineClicked = -1; - if (minY <= overlayY && overlayY <= maxY) { - lineClicked = numLinesBefore; - } - - userClicked = firstUserToDisplay + lineClicked; - - if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX - && overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) { - //print("Go to " + usersOnline[linesOfUsers[userClicked]].username); - location.goToUser(usersOnline[linesOfUsers[userClicked]].username); - } - - return; - } - - if (clickedOverlay === minimizeButton) { - setMinimized(!isMinimized); - calculateWindowHeight(); - updateOverlayPositions(); - updateUsersDisplay(); - return; - } - - if (clickedOverlay === scrollbarBar) { - scrollbarBarClickedAt = (event.y - scrollbarBarPosition.y) / scrollbarBarHeight; - Overlays.editOverlay(scrollbarBar, { - backgroundAlpha: SCROLLBAR_BAR_SELECTED_ALPHA - }); - isMovingScrollbar = true; - return; - } - - if (clickedOverlay === scrollbarBackground) { - delta = scrollbarBarHeight / (scrollbarBackgroundHeight - scrollbarBarHeight); - - if (event.y < scrollbarBarPosition.y) { - scrollbarValue = Math.max(scrollbarValue - delta, 0.0); - } else { - scrollbarValue = Math.min(scrollbarValue + delta, 1.0); - } - - firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); - updateOverlayPositions(); - updateUsersDisplay(); - return; - } - - if (clickedOverlay === friendsButton) { - if (!friendsWindow) { - friendsWindow = new OverlayWebWindow({ - title: FRIENDS_WINDOW_TITLE, - width: FRIENDS_WINDOW_WIDTH, - height: FRIENDS_WINDOW_HEIGHT, - visible: false - }); - } - friendsWindow.setURL(FRIENDS_WINDOW_URL); - friendsWindow.setVisible(true); - friendsWindow.raise(); - return; - } - - if (clickedOverlay === windowBorder) { - movingClickOffset = { - x: event.x - windowPosition.x, - y: event.y - windowPosition.y - }; - - isMovingWindow = true; - } - } - - function onMouseMoveEvent(event) { - var isVisible; - - if (!isLoggedIn || isWindowDisabled()) { - return; - } - - if (isMovingScrollbar) { - if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x - && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN - && scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y - && event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) { - scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) - / (scrollbarBackgroundHeight - scrollbarBarHeight - 2); - scrollbarValue = Math.min(Math.max(scrollbarValue, 0.0), 1.0); - firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); - updateOverlayPositions(); - updateUsersDisplay(); - } else { - Overlays.editOverlay(scrollbarBar, { - backgroundAlpha: SCROLLBAR_BAR_ALPHA - }); - isMovingScrollbar = false; - } - } - - if (isMovingWindow) { - windowPosition = { - x: event.x - movingClickOffset.x, - y: event.y - movingClickOffset.y - }; - - saturateWindowPosition(); - calculateWindowHeight(); - updateOverlayPositions(); - updateUsersDisplay(); - - } else { - - isVisible = isBorderVisible; - if (isVisible) { - isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x - && event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH - && windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y - && event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN; - } else { - isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH - && windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y; - } - if (isVisible !== isBorderVisible) { - isBorderVisible = isVisible; - Overlays.editOverlay(windowBorder, { - visible: isBorderVisible - }); - } - } - } - - function onMouseReleaseEvent() { - var offset = {}; - - if (isWindowDisabled()) { - return; - } - - if (isMovingScrollbar) { - Overlays.editOverlay(scrollbarBar, { - backgroundAlpha: SCROLLBAR_BAR_ALPHA - }); - isMovingScrollbar = false; - } - - if (isMovingWindow) { - // Save offset of bottom of window to nearest edge of the window. - offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2) - ? windowPosition.x : windowPosition.x - viewport.x; - offset.y = (windowPosition.y < viewport.y / 2) - ? windowPosition.y : windowPosition.y - viewport.y; - Settings.setValue(SETTING_USERS_WINDOW_OFFSET, JSON.stringify(offset)); - isMovingWindow = false; - } - } - - function onScriptUpdate() { - var oldViewport = viewport, - oldIsMirrorDisplay = isMirrorDisplay, - oldIsFullscreenMirror = isFullscreenMirror, - MIRROR_MENU_ITEM = "Mirror", - FULLSCREEN_MIRROR_MENU_ITEM = "Fullscreen Mirror"; - - if (isWindowDisabled()) { - return; - } - - viewport = Controller.getViewportDimensions(); - isMirrorDisplay = Menu.isOptionChecked(MIRROR_MENU_ITEM); - isFullscreenMirror = Menu.isOptionChecked(FULLSCREEN_MIRROR_MENU_ITEM); - - if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay - || isFullscreenMirror !== oldIsFullscreenMirror) { - calculateWindowHeight(); - updateUsersDisplay(); - } - - if (viewport.y !== oldViewport.y) { - if (windowPosition.y > oldViewport.y / 2) { - // Maintain position w.r.t. bottom of window. - windowPosition.y = viewport.y - (oldViewport.y - windowPosition.y); - } - } - - if (viewport.x !== oldViewport.x) { - if (windowPosition.x + (WINDOW_WIDTH / 2) > oldViewport.x / 2) { - // Maintain position w.r.t. right of window. - windowPosition.x = viewport.x - (oldViewport.x - windowPosition.x); - } - } - - updateOverlayPositions(); - } - - function setUp() { - var textSizeOverlay, - offsetSetting, - offset = {}, - hmdViewport; - - textSizeOverlay = Overlays.addOverlay("text", { - font: WINDOW_FONT, - visible: false - }); - windowTextHeight = Math.floor(Overlays.textSize(textSizeOverlay, "1").height); - windowLineSpacing = Math.floor(Overlays.textSize(textSizeOverlay, "1\n2").height - 2 * windowTextHeight); - windowLineHeight = windowTextHeight + windowLineSpacing; - windowMinimumHeight = windowTextHeight + WINDOW_MARGIN + WINDOW_BASE_MARGIN; - Overlays.deleteOverlay(textSizeOverlay); - - viewport = Controller.getViewportDimensions(); - - offsetSetting = Settings.getValue(SETTING_USERS_WINDOW_OFFSET); - if (offsetSetting !== "") { - offset = JSON.parse(Settings.getValue(SETTING_USERS_WINDOW_OFFSET)); - } - if (offset.hasOwnProperty("x") && offset.hasOwnProperty("y")) { - windowPosition.x = offset.x < 0 ? viewport.x + offset.x : offset.x; - windowPosition.y = offset.y <= 0 ? viewport.y + offset.y : offset.y; - } else { - hmdViewport = Controller.getRecommendedOverlayRect(); - windowPosition = { - x: (viewport.x - hmdViewport.width) / 2, // HMD viewport is narrower than screen. - y: hmdViewport.height // HMD viewport starts at top of screen but only extends down so far. - }; - } - - saturateWindowPosition(); - calculateWindowHeight(); - - windowBorder = Overlays.addOverlay("rectangle", { - x: 0, - y: viewport.y, // Start up off-screen - width: WINDOW_BORDER_WIDTH, - height: windowBorderHeight, - radius: WINDOW_BORDER_RADIUS, - color: WINDOW_BORDER_COLOR, - alpha: WINDOW_BORDER_ALPHA, - visible: false - }); - - windowPane = Overlays.addOverlay("text", { - x: 0, - y: viewport.y, - width: WINDOW_WIDTH, - height: windowHeight, - topMargin: WINDOW_MARGIN + windowLineHeight, - leftMargin: WINDOW_MARGIN, - color: WINDOW_FOREGROUND_COLOR, - alpha: WINDOW_FOREGROUND_ALPHA, - backgroundColor: WINDOW_BACKGROUND_COLOR, - backgroundAlpha: WINDOW_BACKGROUND_ALPHA, - text: "", - font: WINDOW_FONT, - visible: false - }); - - windowHeading = Overlays.addOverlay("text", { - x: 0, - y: viewport.y, - width: WINDOW_WIDTH - 2 * WINDOW_MARGIN, - height: windowTextHeight, - topMargin: 0, - leftMargin: 0, - color: WINDOW_HEADING_COLOR, - alpha: WINDOW_HEADING_ALPHA, - backgroundAlpha: 0.0, - text: "Users online", - font: WINDOW_FONT, - visible: false - }); - - minimizeButton = Overlays.addOverlay("image", { - x: 0, - y: viewport.y, - width: MIN_MAX_BUTTON_WIDTH, - height: MIN_MAX_BUTTON_HEIGHT, - imageURL: MIN_MAX_BUTTON_SVG, - subImage: { - x: 0, - y: 0, - width: MIN_MAX_BUTTON_SVG_WIDTH, - height: MIN_MAX_BUTTON_SVG_HEIGHT / 2 - }, - color: MIN_MAX_BUTTON_COLOR, - alpha: MIN_MAX_BUTTON_ALPHA, - visible: false - }); - - scrollbarBackgroundPosition = { - x: 0, - y: viewport.y - }; - scrollbarBackground = Overlays.addOverlay("text", { - x: 0, - y: scrollbarBackgroundPosition.y, - width: SCROLLBAR_BACKGROUND_WIDTH, - height: windowTextHeight, - backgroundColor: SCROLLBAR_BACKGROUND_COLOR, - backgroundAlpha: SCROLLBAR_BACKGROUND_ALPHA, - text: "", - visible: false - }); - - scrollbarBarPosition = { - x: 0, - y: viewport.y - }; - scrollbarBar = Overlays.addOverlay("text", { - x: 0, - y: scrollbarBarPosition.y, - width: SCROLLBAR_BACKGROUND_WIDTH - 2, - height: windowTextHeight, - backgroundColor: SCROLLBAR_BAR_COLOR, - backgroundAlpha: SCROLLBAR_BAR_ALPHA, - text: "", - visible: false - }); - - friendsButton = Overlays.addOverlay("image", { - x: 0, - y: viewport.y, - width: FRIENDS_BUTTON_WIDTH, - height: FRIENDS_BUTTON_HEIGHT, - imageURL: FRIENDS_BUTTON_SVG, - subImage: { - x: 0, - y: 0, - width: FRIENDS_BUTTON_SVG_WIDTH, - height: FRIENDS_BUTTON_SVG_HEIGHT - }, - color: FRIENDS_BUTTON_COLOR, - alpha: FRIENDS_BUTTON_ALPHA, - visible: false - }); - - showMe = Settings.getValue(SETTING_USERS_SHOW_ME, ""); - if (DISPLAY_VALUES.indexOf(showMe) === -1) { - showMe = DISPLAY_EVERYONE; - } - - displayControl = new PopUpMenu({ - prompt: DISPLAY_PROMPT, - value: showMe, - values: DISPLAY_VALUES, - displayValues: DISPLAY_DISPLAY_VALUES, - x: 0, - y: viewport.y, - width: WINDOW_WIDTH - 1.5 * WINDOW_MARGIN, - promptWidth: DISPLAY_PROMPT_WIDTH, - lineHeight: windowLineHeight, - textHeight: windowTextHeight, - font: WINDOW_FONT, - promptColor: WINDOW_HEADING_COLOR, - promptAlpha: WINDOW_HEADING_ALPHA, - promptBackgroundColor: WINDOW_BACKGROUND_COLOR, - promptBackgroundAlpha: 0.0, - optionColor: WINDOW_FOREGROUND_COLOR, - optionAlpha: WINDOW_FOREGROUND_ALPHA, - optionBackgroundColor: OPTION_BACKGROUND_COLOR, - optionBackgroundAlpha: OPTION_BACKGROUND_ALPHA, - popupBackgroundColor: DISPLAY_OPTIONS_BACKGROUND_COLOR, - popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA, - buttonColor: MIN_MAX_BUTTON_COLOR, - buttonAlpha: MIN_MAX_BUTTON_ALPHA, - visible: false - }); - - myVisibility = Settings.getValue(SETTING_USERS_VISIBLE_TO, ""); - if (VISIBILITY_VALUES.indexOf(myVisibility) === -1) { - myVisibility = VISIBILITY_FRIENDS; - } - GlobalServices.findableBy = myVisibility; - - visibilityControl = new PopUpMenu({ - prompt: VISIBILITY_PROMPT, - value: myVisibility, - values: VISIBILITY_VALUES, - displayValues: VISIBILITY_DISPLAY_VALUES, - x: 0, - y: viewport.y, - width: WINDOW_WIDTH - 1.5 * WINDOW_MARGIN, - promptWidth: VISIBILITY_PROMPT_WIDTH, - lineHeight: windowLineHeight, - textHeight: windowTextHeight, - font: WINDOW_FONT, - promptColor: WINDOW_HEADING_COLOR, - promptAlpha: WINDOW_HEADING_ALPHA, - promptBackgroundColor: WINDOW_BACKGROUND_COLOR, - promptBackgroundAlpha: 0.0, - optionColor: WINDOW_FOREGROUND_COLOR, - optionAlpha: WINDOW_FOREGROUND_ALPHA, - optionBackgroundColor: OPTION_BACKGROUND_COLOR, - optionBackgroundAlpha: OPTION_BACKGROUND_ALPHA, - popupBackgroundColor: DISPLAY_OPTIONS_BACKGROUND_COLOR, - popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA, - buttonColor: MIN_MAX_BUTTON_COLOR, - buttonAlpha: MIN_MAX_BUTTON_ALPHA, - visible: false - }); - - Controller.mousePressEvent.connect(onMousePressEvent); - Controller.mouseMoveEvent.connect(onMouseMoveEvent); - Controller.mouseReleaseEvent.connect(onMouseReleaseEvent); - - Menu.addMenuItem({ - menuName: MENU_NAME, - menuItemName: MENU_ITEM, - afterItem: MENU_ITEM_AFTER, - isCheckable: true, - isChecked: isVisible - }); - Menu.menuItemEvent.connect(onMenuItemEvent); - - GlobalServices.findableByChanged.connect(onFindableByChanged); - - Script.update.connect(onScriptUpdate); - - pollUsers(); - - // Set minimized at end - setup code does not handle `minimized == false` correctly - setMinimized(isValueTrue(Settings.getValue(SETTING_USERS_WINDOW_MINIMIZED, true))); - } - - function tearDown() { - Menu.removeMenuItem(MENU_NAME, MENU_ITEM); - - Script.clearTimeout(usersTimer); - Overlays.deleteOverlay(windowBorder); - Overlays.deleteOverlay(windowPane); - Overlays.deleteOverlay(windowHeading); - Overlays.deleteOverlay(minimizeButton); - Overlays.deleteOverlay(scrollbarBackground); - Overlays.deleteOverlay(scrollbarBar); - Overlays.deleteOverlay(friendsButton); - displayControl.tearDown(); - visibilityControl.tearDown(); - } - - setUp(); - Script.scriptEnding.connect(tearDown); -}()); - -}()); // END LOCAL_SCOPE