This commit is contained in:
Howard Stearns 2017-04-29 13:58:20 -07:00 committed by Chris Collins
parent b3e078eb74
commit 43f8467708

View file

@ -1,4 +1,6 @@
"use strict"; "use strict";
/*jslint vars:true, plusplus:true, forin:true*/
/*global Window, Script, Controller, MyAvatar, AvatarList, Entities, Messages, Audio, SoundCache, Account, UserActivityLogger, Vec3, Quat, XMLHttpRequest, location, print*/
// //
// makeUserConnection.js // makeUserConnection.js
// scripts/system // scripts/system
@ -93,7 +95,7 @@
"type": "ParticleEffect" "type": "ParticleEffect"
}; };
var currentHand = undefined; var currentHand;
var currentHandJointIndex = -1; var currentHandJointIndex = -1;
var state = STATES.INACTIVE; var state = STATES.INACTIVE;
var connectingInterval; var connectingInterval;
@ -183,7 +185,8 @@
function handToString(hand) { function handToString(hand) {
if (hand === Controller.Standard.RightHand) { if (hand === Controller.Standard.RightHand) {
return "RightHand"; return "RightHand";
} else if (hand === Controller.Standard.LeftHand) { }
if (hand === Controller.Standard.LeftHand) {
return "LeftHand"; return "LeftHand";
} }
debug("handToString called without valid hand! value: ", hand); debug("handToString called without valid hand! value: ", hand);
@ -193,7 +196,8 @@
function stringToHand(hand) { function stringToHand(hand) {
if (hand === "RightHand") { if (hand === "RightHand") {
return Controller.Standard.RightHand; return Controller.Standard.RightHand;
} else if (hand === "LeftHand") { }
if (hand === "LeftHand") {
return Controller.Standard.LeftHand; return Controller.Standard.LeftHand;
} }
debug("stringToHand called with bad hand string:", hand); debug("stringToHand called with bad hand string:", hand);
@ -203,7 +207,8 @@
function handToHaptic(hand) { function handToHaptic(hand) {
if (hand === Controller.Standard.RightHand) { if (hand === Controller.Standard.RightHand) {
return 1; return 1;
} else if (hand === Controller.Standard.LeftHand) { }
if (hand === Controller.Standard.LeftHand) {
return 0; return 0;
} }
debug("handToHaptic called without a valid hand!"); debug("handToHaptic called without a valid hand!");
@ -231,11 +236,11 @@
// This returns the ideal hand joint index for the avatar. // This returns the ideal hand joint index for the avatar.
// [hand]middle1 -> [hand]index1 -> [hand] // [hand]middle1 -> [hand]index1 -> [hand]
function getIdealHandJointIndex(avatar, hand) { function getIdealHandJointIndex(avatar, hand) {
debug("got hand " + hand + " for avatar " + avatar.sessionUUID); debug("get hand " + hand + " for avatar " + avatar.sessionUUID);
var handString = handToString(hand); var suffixIndex, jointName, jointIndex, handString = handToString(hand);
for (var i = 0; i < PREFERRER_HAND_JOINT_POSTFIX_ORDER.length; i++) { for (suffixIndex = 0; suffixIndex < PREFERRER_HAND_JOINT_POSTFIX_ORDER.length; suffixIndex++) {
var jointName = handString + PREFERRER_HAND_JOINT_POSTFIX_ORDER[i]; jointName = handString + PREFERRER_HAND_JOINT_POSTFIX_ORDER[suffixIndex];
var jointIndex = avatar.getJointIndex(jointName); jointIndex = avatar.getJointIndex(jointName);
if (jointIndex !== -1) { if (jointIndex !== -1) {
debug('found joint ' + jointName + ' (' + jointIndex + ')'); debug('found joint ' + jointName + ' (' + jointIndex + ')');
return jointIndex; return jointIndex;
@ -255,7 +260,7 @@
return avatar.getJointPosition(handJointIndex); return avatar.getJointPosition(handJointIndex);
} }
function shakeHandsAnimation(animationProperties) { function shakeHandsAnimation() {
// all we are doing here is moving the right hand to a spot // all we are doing here is moving the right hand to a spot
// that is in front of and a bit above the hips. Basing how // that is in front of and a bit above the hips. Basing how
// far in front as scaling with the avatar's height (say hips // far in front as scaling with the avatar's height (say hips
@ -412,8 +417,42 @@
}); });
return nearestAvatar; return nearestAvatar;
} }
function messageSend(message) {
Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message));
}
function lookForWaitingAvatar() {
// we started with nobody close enough, but maybe I've moved
// or they did. Note that 2 people doing this race, so stop
// as soon as you have a connectingId (which means you got their
// message before noticing they were in range in this loop)
// just in case we re-enter before stopping
stopWaiting();
debug("started looking for waiting avatars");
waitingInterval = Script.setInterval(function () {
if (state === STATES.WAITING && !connectingId) {
// find the closest in-range avatar, and send connection request
var nearestAvatar = findNearestWaitingAvatar();
if (nearestAvatar.avatar) {
connectingId = nearestAvatar.avatar;
connectingHandString = handToString(nearestAvatar.hand);
debug("sending connectionRequest to", connectingId);
messageSend({
key: "connectionRequest",
id: connectingId,
hand: handToString(currentHand)
});
}
} else {
// something happened, stop looking for avatars to connect
stopWaiting();
debug("stopped looking for waiting avatars");
}
}, WAITING_INTERVAL);
}
var pollCount = 0, requestUrl = location.metaverseServerUrl + '/api/v1/user/connection_request';
// As currently implemented, we select the closest waiting avatar (if close enough) and send // As currently implemented, we select the closest waiting avatar (if close enough) and send
// them a connectionRequest. If nobody is close enough we send a waiting message, and wait for a // them a connectionRequest. If nobody is close enough we send a waiting message, and wait for a
// connectionRequest. If the 2 people who want to connect are both somewhat out of range when they // connectionRequest. If the 2 people who want to connect are both somewhat out of range when they
@ -510,9 +549,8 @@
debug("updateTriggers called - gripping", handToString(hand)); debug("updateTriggers called - gripping", handToString(hand));
if (state !== STATES.INACTIVE) { if (state !== STATES.INACTIVE) {
return; return;
} else {
startHandshake(fromKeyboard);
} }
startHandshake(fromKeyboard);
} else { } else {
// TODO: should we end handshake even when inactive? Ponder // TODO: should we end handshake even when inactive? Ponder
debug("updateTriggers called -- no longer gripping", handToString(hand)); debug("updateTriggers called -- no longer gripping", handToString(hand));
@ -524,47 +562,12 @@
} }
} }
function messageSend(message) {
Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message));
}
function lookForWaitingAvatar() {
// we started with nobody close enough, but maybe I've moved
// or they did. Note that 2 people doing this race, so stop
// as soon as you have a connectingId (which means you got their
// message before noticing they were in range in this loop)
// just in case we re-enter before stopping
stopWaiting();
debug("started looking for waiting avatars");
waitingInterval = Script.setInterval(function () {
if (state === STATES.WAITING && !connectingId) {
// find the closest in-range avatar, and send connection request
var nearestAvatar = findNearestWaitingAvatar();
if (nearestAvatar.avatar) {
connectingId = nearestAvatar.avatar;
connectingHandString = handToString(nearestAvatar.hand);
debug("sending connectionRequest to", connectingId);
messageSend({
key: "connectionRequest",
id: connectingId,
hand: handToString(currentHand)
});
}
} else {
// something happened, stop looking for avatars to connect
stopWaiting();
debug("stopped looking for waiting avatars");
}
}, WAITING_INTERVAL);
}
/* There is a mini-state machine after entering STATES.makingConnection. /* There is a mini-state machine after entering STATES.makingConnection.
We make a request (which might immediately succeed, fail, or neither. We make a request (which might immediately succeed, fail, or neither.
If we immediately fail, we tell the user. If we immediately fail, we tell the user.
Otherwise, we wait MAKING_CONNECTION_TIMEOUT. At that time, we poll until success or fail. Otherwise, we wait MAKING_CONNECTION_TIMEOUT. At that time, we poll until success or fail.
*/ */
var result, requestBody, pollCount = 0, requestUrl = location.metaverseServerUrl + '/api/v1/user/connection_request'; var result, requestBody;
function connectionRequestCompleted() { // Final result is in. Do effects. function connectionRequestCompleted() { // Final result is in. Do effects.
if (result.status === 'success') { // set earlier if (result.status === 'success') { // set earlier
if (!successfulHandshakeInjector) { if (!successfulHandshakeInjector) {
@ -580,10 +583,15 @@
handToHaptic(currentHand)); handToHaptic(currentHand));
// don't change state (so animation continues while gripped) // don't change state (so animation continues while gripped)
// but do send a notification, by calling the slot that emits the signal for it // but do send a notification, by calling the slot that emits the signal for it
Window.makeConnection(true, result.connection.new_connection ? Window.makeConnection(true,
"You and " + result.connection.username + " are now connected!" : result.connection.username); result.connection.new_connection ?
UserActivityLogger.makeUserConnection(connectingId, true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" :
"new connection" : "already connected"); result.connection.username);
UserActivityLogger.makeUserConnection(connectingId,
true,
result.connection.new_connection ?
"new connection" :
"already connected");
return; return;
} // failed } // failed
endHandshake(); endHandshake();
@ -658,13 +666,16 @@
// This will immediately set response if successful (e.g., the other guy got his request in first), // This will immediately set response if successful (e.g., the other guy got his request in first),
// or immediate failure, and will otherwise poll (using the requestBody we just set). // or immediate failure, and will otherwise poll (using the requestBody we just set).
request({ // request({
uri: requestUrl, uri: requestUrl,
method: 'POST', method: 'POST',
json: true, json: true,
body: {'user_connection_request': requestBody} body: {'user_connection_request': requestBody}
}, handleConnectionResponseAndMaybeRepeat); }, handleConnectionResponseAndMaybeRepeat);
} }
function getConnectingHandJointIndex() {
return AvatarList.getAvatarIdentifiers().indexOf(connectingId) !== -1 ? getIdealHandJointIndex(AvatarList.getAvatar(connectingId), stringToHand(connectingHandString)) : -1;
}
// we change states, start the connectionInterval where we check // we change states, start the connectionInterval where we check
// to be sure the hand is still close enough. If not, we terminate // to be sure the hand is still close enough. If not, we terminate
@ -676,8 +687,7 @@
// do we need to do this? // do we need to do this?
connectingId = id; connectingId = id;
connectingHandString = hand; connectingHandString = hand;
connectingHandJointIndex = AvatarList.getAvatarIdentifiers().indexOf(connectingId) !== -1 ? connectingHandJointIndex = getConnectingHandJointIndex();
getIdealHandJointIndex(AvatarList.getAvatar(connectingId), stringToHand(connectingHandString)) : -1;
state = STATES.CONNECTING; state = STATES.CONNECTING;
// play sound // play sound
@ -760,14 +770,12 @@
break; break;
case "connectionRequest": case "connectionRequest":
delete waitingList[senderID]; delete waitingList[senderID];
if (state === STATES.WAITING && message.id === MyAvatar.sessionUUID && if (state === STATES.WAITING && message.id === MyAvatar.sessionUUID && (!connectingId || connectingId === senderID)) {
(!connectingId || connectingId === senderID)) {
// you were waiting for a connection request, so send the ack. Or, you and the other // you were waiting for a connection request, so send the ack. Or, you and the other
// guy raced and both send connectionRequests. Handle that too // guy raced and both send connectionRequests. Handle that too
connectingId = senderID; connectingId = senderID;
connectingHandString = message.hand; connectingHandString = message.hand;
connectingHandJointIndex = AvatarList.getAvatarIdentifiers().indexOf(connectingId) !== -1 ? connectingHandJointIndex = getConnectingHandJointIndex();
getIdealHandJointIndex(AvatarList.getAvatar(connectingId), stringToHand(connectingHandString)) : -1;
messageSend({ messageSend({
key: "connectionAck", key: "connectionAck",
id: senderID, id: senderID,
@ -786,8 +794,7 @@
// start connecting... // start connecting...
connectingId = senderID; connectingId = senderID;
connectingHandString = message.hand; connectingHandString = message.hand;
connectingHandJointIndex = AvatarList.getAvatarIdentifiers().indexOf(connectingId) !== -1 ? connectingHandJointIndex = getConnectingHandJointIndex();
getIdealHandJointIndex(AvatarList.getAvatar(connectingId), stringToHand(connectingHandString)) : -1;
stopWaiting(); stopWaiting();
startConnecting(senderID, connectingHandString); startConnecting(senderID, connectingHandString);
} else if (connectingId) { } else if (connectingId) {
@ -850,30 +857,25 @@
Messages.subscribe(MESSAGE_CHANNEL); Messages.subscribe(MESSAGE_CHANNEL);
Messages.messageReceived.connect(messageHandler); Messages.messageReceived.connect(messageHandler);
function makeGripHandler(hand, animate) { function makeGripHandler(hand, animate) {
// determine if we are gripping or un-gripping // determine if we are gripping or un-gripping
if (animate) { if (animate) {
return function (value) { return function (value) {
updateTriggers(value, true, hand); updateTriggers(value, true, hand);
}; };
}
} else {
return function (value) { return function (value) {
updateTriggers(value, false, hand); updateTriggers(value, false, hand);
}; };
} }
}
function keyPressEvent(event) { function keyPressEvent(event) {
if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) {
!event.isAlt) {
updateTriggers(1.0, true, Controller.Standard.RightHand); updateTriggers(1.0, true, Controller.Standard.RightHand);
} }
} }
function keyReleaseEvent(event) { function keyReleaseEvent(event) {
if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && if ((event.text === "x") && !event.isAutoRepeat && !event.isShifted && !event.isMeta && !event.isControl && !event.isAlt) {
!event.isAlt) {
updateTriggers(0.0, true, Controller.Standard.RightHand); updateTriggers(0.0, true, Controller.Standard.RightHand);
} }
} }