diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index a3d65a78a4..a9497386af 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -41,14 +41,41 @@ Rectangle { property int rowHeight: 50; property var userData: []; property var myData: ({displayName: "", userName: ""}); // valid dummy until set - function fromScript(data) { - var myIndex = 0; - while ((myIndex < data.length) && data[myIndex].sessionId) myIndex++; // no findIndex in .qml - myData = data[myIndex]; - data.splice(myIndex, 1); - userData = data; - console.log('FIXME', JSON.stringify(myData), myIndex, JSON.stringify(userData)); - sortModel(); + function findSessionIndex(sessionId) { // no findIndex in .qml + for (var i = 0; i < userData.length; i++) { + if (userData[i].sessionId === sessionId) { + return i; + } + } + return -1; + } + function fromScript(message) { + console.log('fixme got message from script', JSON.stringify(message)); + switch (message.method) { + case 'users': + var data = message.params; + var myIndex = findSessionIndex(''); + myData = data[myIndex]; + data.splice(myIndex, 1); + userData = data; + console.log('FIXME', JSON.stringify(myData), myIndex, JSON.stringify(userData)); + sortModel(); + break; + case 'select': + var sessionId = message.params[0]; + var selected = message.params[1]; + var userIndex = findSessionIndex(sessionId); + console.log('fixme select', sessionId, selected, userIndex); + if (selected) { + table.selection.clear(); // for now, no multi-select + table.selection.select(userIndex); + } else { + table.selection.deselect(userIndex); + } + break; + default: + console.log('Unrecognized message:', JSON.stringify(message)); + } } ListModel { id: userModel @@ -87,8 +114,7 @@ Rectangle { userIds.push(userData[userIndex].sessionId); }); console.log('fixme selected ' + JSON.stringify(userIds)); - pal.sendToScript(userIds); - //pal.parent.sendToScript(userIds); + pal.sendToScript({method: 'selected', params: userIds}); } Connections { target: table.selection diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 3fa86af72e..30a9aa5b29 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -1,6 +1,6 @@ "use strict"; /*jslint vars: true, plusplus: true, forin: true*/ -/*globals Script, AvatarList, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Controller, print */ +/*globals Script, AvatarList, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print */ // // pal.js // @@ -13,6 +13,8 @@ // FIXME when we make this a defaultScript: (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) { // A wrapper around overlays to store the key it is associated with. @@ -73,9 +75,16 @@ var pal = new OverlayWindow({ visible: false }); pal.fromQml.connect(function (message) { - ExtendedOverlay.some(function (overlay) { - overlay.select(-1 !== message.indexOf(overlay.key)); - }); + switch (message.method) { + case 'selected': + var sessionIds = message.params; + ExtendedOverlay.some(function (overlay) { + overlay.select(-1 !== sessionIds.indexOf(overlay.key)); + }); + break; + default: + print('Unrecognized message from Pal.qml:', JSON.stringify(message)); + } }); var AVATAR_OVERLAY = Script.resolvePath("assets/images/grabsprite-3.png"); @@ -87,7 +96,7 @@ function populateUserList() { data.push({ displayName: avatar.displayName || ('anonymous ' + counter++), userName: "fakeAcct" + (id || "Me"), - sessionId: id + sessionId: id || '' }); if (id) { // No overlay for us new ExtendedOverlay(id, "sphere", { // 3d so we don't go cross-eyed looking at it, but on top of everything @@ -99,7 +108,7 @@ function populateUserList() { }); } }); - pal.sendToQml(data); + pal.sendToQml({method: 'users', params: data}); } var pingPong = true; function updateOverlays() { @@ -108,15 +117,17 @@ function updateOverlays() { if (!id) { return; // don't update ourself } - var avatar = AvatarList.getAvatar(id); - var target = avatar.position; - var distance = Vec3.distance(target, eye); var overlay = ExtendedOverlay.get(id); - overlay.ping = pingPong; - overlay.editOverlay({ - position: target, - dimensions: 0.05 * distance // constant apparent size - }); + if (overlay) { + var avatar = AvatarList.getAvatar(id); + var target = avatar.position; + var distance = Vec3.distance(target, eye); + overlay.ping = pingPong; + overlay.editOverlay({ + position: target, + dimensions: 0.05 * distance // constant apparent size + }); + } }); pingPong = !pingPong; ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) @@ -129,6 +140,50 @@ function removeOverlays() { ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); } +// Clicks +function handleClick(pickRay) { + print('fixme handleClick', JSON.stringify(pickRay)); + ExtendedOverlay.applyPickRay(pickRay, function (overlay) { + var message = {method: 'select', params: [overlay.key, !overlay.selected]}; + print('fixme sending to qml:', JSON.stringify(message)); + pal.sendToQml(message); + return true; + }); +} +function handleMouseEvent(mousePressEvent) { // handleClick if we get one. + if (!mousePressEvent.isLeftButton) { + return; + } + handleClick(Camera.computePickRay(mousePressEvent.x, mousePressEvent.y)); +} +// We get mouseMoveEvents from the handControllers, via handControllerPointer. +// But we dont' get mousePressEvents. +var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); +function controllerComputePickRay(hand) { + print('fixme controllerComputePickRay', hand); + var controllerPose = getControllerWorldLocation(hand, true); + print('fixme pose', JSON.stringify(controllerPose), 'valid', controllerPose.valid); + if (controllerPose.valid) { + print('fixme controllerComputePickRay', hand); + var xxfixme = { origin: controllerPose.position, direction: Quat.getUp(controllerPose.orientation) }; + print('fixme result', JSON.stringify(xxfixme)); + return xxfixme; + } + print('fixme controllerComputePickRay failed', hand, JSON.stringify(controllerPose)); +} +function makeClickHandler(hand) { + return function(clicked) { + if (clicked > 0.85) { + print('fixme click handler on', clicked, hand); + var pickRay = controllerComputePickRay(hand); + print('fixme pickRay', JSON.stringify(pickRay)); + handleClick(pickRay); + } + }; +} +triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); +triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); + // Manage the connection between the button and the window. var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var buttonName = "pal"; @@ -141,17 +196,25 @@ var button = toolBar.addButton({ buttonState: 1, alpha: 0.9 }); +function off() { + Script.update.disconnect(updateOverlays); + Controller.mousePressEvent.disconnect(handleMouseEvent); + triggerMapping.disable(); + removeOverlays(); +} function onClicked() { if (!pal.visible) { populateUserList(); pal.raise(); Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + triggerMapping.enable(); } else { - Script.update.disconnect(updateOverlays); - removeOverlays(); + off(); } pal.setVisible(!pal.visible); } + function onVisibileChanged() { button.writeProperty('buttonState', pal.visible ? 0 : 1); button.writeProperty('defaultState', pal.visible ? 0 : 1); @@ -161,10 +224,10 @@ button.clicked.connect(onClicked); pal.visibleChanged.connect(onVisibileChanged); Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); toolBar.removeButton(buttonName); pal.visibleChanged.disconnect(onVisibileChanged); - button.clicked.disconnect(onClicked); - removeOverlays(); + off(); });