mirror of
https://github.com/overte-org/overte.git
synced 2025-04-09 10:45:24 +02:00
make use of tablet or HUD depend on a single variable. avoid some duplicated code
This commit is contained in:
parent
11d01a0c00
commit
f18094f565
25 changed files with 406 additions and 3188 deletions
|
@ -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<int> _showHandControllersCount { 0 };
|
||||
|
||||
bool _hudUIEnabled;
|
||||
};
|
||||
|
||||
#endif // hifi_HMDScriptingInterface_h
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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
|
|
@ -108,6 +108,6 @@
|
|||
Script.scriptEnding.connect(function () {
|
||||
Entities.deleteEntity(HMD.tabletID);
|
||||
HMD.tabletID = null;
|
||||
HDM.homeButtonID = null;
|
||||
HMD.homeButtonID = null;
|
||||
});
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue