Refactor of pal.js to dynamically switch between toolbar and tablet.

This commit is contained in:
Anthony J. Thibault 2017-02-10 15:06:55 -08:00
parent d0dc642cd8
commit f8055a027e

View file

@ -1,6 +1,7 @@
"use strict";
/* jslint vars: true, plusplus: true, forin: true*/
/*globals Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print, getControllerWorldLocation */
/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print, getControllerWorldLocation */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
//
// pal.js
//
@ -15,19 +16,22 @@
// 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"),
var 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"),
var 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"),
var 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
var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
var conserveResources = true;
@ -94,12 +98,12 @@ ExtendedOverlay.prototype.hover = function (hovering) {
}
if (hovering) {
// un-hover the last hovering overlay
if (lastHoveringId && lastHoveringId != this.key) {
if (lastHoveringId && lastHoveringId !== this.key) {
ExtendedOverlay.get(lastHoveringId).hover(false);
}
lastHoveringId = this.key;
}
}
};
ExtendedOverlay.prototype.select = function (selected) {
if (this.selected === selected) {
return;
@ -204,6 +208,7 @@ var pal = new OverlayWindow({
visible: false
});
function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
var data;
switch (message.method) {
case 'selected':
selectedIds = message.params;
@ -250,7 +255,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
}
break;
case 'displayNameUpdate':
if (MyAvatar.displayName != message.params) {
if (MyAvatar.displayName !== message.params) {
MyAvatar.displayName = message.params;
UserActivityLogger.palAction("display_name_change", "");
}
@ -261,9 +266,9 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
}
function sendToQml(message) {
if (Settings.getValue("HUDUIEnabled")) {
if (currentUIMode === "toolbar") {
pal.sendToQml(message);
} else {
} else if (currentUIMode === "tablet") {
tablet.sendToQml(message);
}
}
@ -393,7 +398,9 @@ function removeOverlays() {
selectedIds = [];
lastHoveringId = 0;
HighlightedEntity.clearOverlays();
ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); });
ExtendedOverlay.some(function (overlay) {
overlay.deleteOverlay();
});
}
//
@ -423,12 +430,13 @@ function handleMouseMove(pickRay) { // given the pickRay, just do the hover logi
// 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;
var TRIGGER_CLICK_THRESHOLD = 0.85;
var TRIGGER_PRESS_THRESHOLD = 0.05;
function handleMouseMoveEvent(event) { // find out which overlay (if any) is over the mouse position
var pickRay;
if (HMD.active) {
if (currentHandPressed != 0) {
if (currentHandPressed !== 0) {
pickRay = controllerComputePickRay(currentHandPressed);
} else {
// nothing should hover, so
@ -444,12 +452,12 @@ 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) {
var isPressed = value > TRIGGER_PRESS_THRESHOLD;
if (currentHandPressed === 0) {
currentHandPressed = isPressed ? hand : 0;
return;
}
if (currentHandPressed == hand) {
if (currentHandPressed === hand) {
currentHandPressed = isPressed ? hand : 0;
return;
}
@ -478,7 +486,7 @@ function makeClickHandler(hand) {
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));
@ -491,7 +499,18 @@ var button;
var buttonName = "PEOPLE";
var tablet = null;
var toolBar = null;
if (Settings.getValue("HUDUIEnabled")) {
var currentUIMode;
function onTabletScreenChanged(type, url) {
if (type !== "QML" || url !== "../Pal.qml") {
off();
}
}
// @param mode {string} "tablet" or "toolbar"
function startup(mode) {
if (mode === "toolbar") {
toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
button = toolBar.addButton({
objectName: buttonName,
@ -500,7 +519,10 @@ if (Settings.getValue("HUDUIEnabled")) {
alpha: 0.9
});
pal.fromQml.connect(fromQml);
} else {
button.clicked.connect(onToolbarButtonClicked);
pal.visibleChanged.connect(onVisibleChanged);
pal.closed.connect(off);
} else if (mode === "tablet") {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
button = tablet.addButton({
text: buttonName,
@ -508,8 +530,25 @@ if (Settings.getValue("HUDUIEnabled")) {
sortOrder: 7
});
tablet.fromQml.connect(fromQml);
button.clicked.connect(onTabletButtonClicked);
tablet.screenChanged.connect(onTabletScreenChanged);
} else {
print("ERROR: pal.js: bad ui mode");
}
Users.usernameFromIDReply.connect(usernameFromIDReply);
Window.domainChanged.connect(clearLocalQMLDataAndClosePAL);
Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL);
Messages.subscribe(CHANNEL);
Messages.messageReceived.connect(receiveMessage);
Users.avatarDisconnected.connect(avatarDisconnected);
currentUIMode = mode;
}
// var mode = Settings.getValue("HUDUIEnabled");
startup(HMD.active ? "tablet" : "toolbar");
var isWired = false;
var audioTimer;
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
@ -521,14 +560,16 @@ function off() {
Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent);
isWired = false;
}
if (audioTimer) { Script.clearInterval(audioTimer); }
if (audioTimer) {
Script.clearInterval(audioTimer);
}
triggerMapping.disable(); // It's ok if we disable twice.
triggerPressMapping.disable(); // see above
removeOverlays();
Users.requestsDomainListData = false;
}
function onClicked() {
if (Settings.getValue("HUDUIEnabled")) {
function onToolbarButtonClicked() {
if (!pal.visible) {
Users.requestsDomainListData = true;
populateUserList();
@ -544,7 +585,9 @@ function onClicked() {
off();
}
pal.setVisible(!pal.visible);
} else {
}
function onTabletButtonClicked() {
tablet.loadQMLSource("../Pal.qml");
Users.requestsDomainListData = true;
populateUserList();
@ -556,7 +599,6 @@ function onClicked() {
triggerPressMapping.enable();
audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS);
}
}
//
// Message from other scripts, such as edit.js
@ -570,8 +612,8 @@ function receiveMessage(channel, messageString, senderID) {
var message = JSON.parse(messageString);
switch (message.method) {
case 'select':
if (!pal.visible) {
onClicked();
if (currentUIMode === "toolbar" && !pal.visible) {
onToolbarButtonClicked();
}
sendToQml(message); // Accepts objects, not just strings.
break;
@ -579,8 +621,6 @@ function receiveMessage(channel, messageString, senderID) {
print('Unrecognized PAL message', messageString);
}
}
Messages.subscribe(CHANNEL);
Messages.messageReceived.connect(receiveMessage);
var AVERAGING_RATIO = 0.05;
@ -638,57 +678,51 @@ function avatarDisconnected(nodeID) {
// remove from the pal list
sendToQml({method: 'avatarDisconnected', params: [nodeID]});
}
//
// Button state.
//
function onVisibleChanged() {
button.editProperties({isActive: pal.visible});
}
button.clicked.connect(onClicked);
pal.visibleChanged.connect(onVisibleChanged);
pal.closed.connect(off);
if (!Settings.getValue("HUDUIEnabled")) {
tablet.screenChanged.connect(function (type, url) {
if (type !== "QML" || url !== "../Pal.qml") {
off();
}
});
}
Users.usernameFromIDReply.connect(usernameFromIDReply);
Users.avatarDisconnected.connect(avatarDisconnected);
function clearLocalQMLDataAndClosePAL() {
sendToQml({ method: 'clearLocalQMLData' });
if (pal.visible) {
onClicked(); // Close the PAL
if (currentUIMode === "toolbar" && pal.visible) {
onToolbarButtonClicked(); // Close the PAL
}
}
Window.domainChanged.connect(clearLocalQMLDataAndClosePAL);
Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL);
function shutdown() {
if (currentUIMode === "toolbar") {
button.clicked.disconnect(onToolbarButtonClicked);
toolBar.removeButton(buttonName);
pal.visibleChanged.disconnect(onVisibleChanged);
pal.closed.disconnect(off);
} else if (currentUIMode === "tablet") {
button.clicked.disconnect(onTabletButtonClicked);
tablet.removeButton(button);
tablet.screenChanged.disconnect(onTabletScreenChanged);
}
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL);
Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL);
Messages.subscribe(CHANNEL);
Messages.messageReceived.disconnect(receiveMessage);
Users.avatarDisconnected.disconnect(avatarDisconnected);
off();
}
//
// Cleanup.
//
Script.scriptEnding.connect(function () {
button.clicked.disconnect(onClicked);
if (tablet) {
tablet.removeButton(button);
}
if (toolBar) {
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();
Script.scriptEnding.connect(shutdown);
HMD.displayModeChanged.connect(function () {
shutdown();
startup(HMD.active ? "tablet" : "toolbar");
});
}()); // END LOCAL_SCOPE