Added grab far events for non physical objects

This commit is contained in:
ericrius1 2015-10-07 18:06:37 -07:00
parent 039d9a6a98
commit efc2dfb68f

View file

@ -77,7 +77,9 @@ var STATE_NEAR_GRABBING = 4;
var STATE_CONTINUE_NEAR_GRABBING = 5; var STATE_CONTINUE_NEAR_GRABBING = 5;
var STATE_NEAR_GRABBING_NON_COLLIDING = 6; var STATE_NEAR_GRABBING_NON_COLLIDING = 6;
var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 7; var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 7;
var STATE_RELEASE = 8; var STATE_FAR_GRABBING_NON_COLLIDING = 8;
var STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING = 9;
var STATE_RELEASE = 10;
var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js
var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
@ -120,7 +122,7 @@ function MyController(hand, triggerAction) {
var TIP_CONTROLLER_OFFSET = 1; var TIP_CONTROLLER_OFFSET = 1;
this.triggerAction = triggerAction; this.triggerAction = triggerAction;
this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand;
this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET;
this.actionID = null; // action this script created... this.actionID = null; // action this script created...
this.grabbedEntity = null; // on this entity. this.grabbedEntity = null; // on this entity.
@ -131,49 +133,55 @@ function MyController(hand, triggerAction) {
var _this = this; var _this = this;
this.update = function() { this.update = function () {
this.updateSmoothedTrigger(); this.updateSmoothedTrigger();
switch (this.state) { switch (this.state) {
case STATE_OFF: case STATE_OFF:
this.off(); this.off();
this.touchTest(); this.touchTest();
break; break;
case STATE_SEARCHING: case STATE_SEARCHING:
this.search(); this.search();
break; break;
case STATE_DISTANCE_HOLDING: case STATE_DISTANCE_HOLDING:
this.distanceHolding(); this.distanceHolding();
break; break;
case STATE_CONTINUE_DISTANCE_HOLDING: case STATE_CONTINUE_DISTANCE_HOLDING:
this.continueDistanceHolding(); this.continueDistanceHolding();
break; break;
case STATE_NEAR_GRABBING: case STATE_NEAR_GRABBING:
this.nearGrabbing(); this.nearGrabbing();
break; break;
case STATE_CONTINUE_NEAR_GRABBING: case STATE_CONTINUE_NEAR_GRABBING:
this.continueNearGrabbing(); this.continueNearGrabbing();
break; break;
case STATE_NEAR_GRABBING_NON_COLLIDING: case STATE_NEAR_GRABBING_NON_COLLIDING:
this.nearGrabbingNonColliding(); this.nearGrabbingNonColliding();
break; break;
case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING:
this.continueNearGrabbingNonColliding(); this.continueNearGrabbingNonColliding();
break; break;
case STATE_RELEASE: case STATE_FAR_GRABBING_NON_COLLIDING:
this.release(); this.farGrabbingNonColliding();
break; break;
case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING:
this.continueFarGrabbingNonColliding();
break;
case STATE_RELEASE:
this.release();
break;
} }
}; };
this.setState = function(newState) { this.setState = function (newState) {
// print("STATE: " + this.state + " --> " + newState); // print("STATE: " + this.state + " --> " + newState);
this.state = newState; this.state = newState;
} }
this.lineOn = function(closePoint, farPoint, color) { this.lineOn = function (closePoint, farPoint, color) {
// draw a line // draw a line
if (this.pointer === null) { if (this.pointer === null) {
this.pointer = Entities.addEntity({ this.pointer = Entities.addEntity({
@ -197,41 +205,41 @@ function MyController(hand, triggerAction) {
}; };
this.lineOff = function() { this.lineOff = function () {
if (this.pointer !== null) { if (this.pointer !== null) {
Entities.deleteEntity(this.pointer); Entities.deleteEntity(this.pointer);
} }
this.pointer = null; this.pointer = null;
}; };
this.updateSmoothedTrigger = function() { this.updateSmoothedTrigger = function () {
var triggerValue = Controller.getActionValue(this.triggerAction); var triggerValue = Controller.getActionValue(this.triggerAction);
// smooth out trigger value // smooth out trigger value
this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) +
(triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO));
} }
this.triggerSmoothedSqueezed = function() { this.triggerSmoothedSqueezed = function () {
return this.triggerValue > TRIGGER_ON_VALUE; return this.triggerValue > TRIGGER_ON_VALUE;
}; };
this.triggerSmoothedReleased = function() { this.triggerSmoothedReleased = function () {
return this.triggerValue < TRIGGER_OFF_VALUE; return this.triggerValue < TRIGGER_OFF_VALUE;
}; };
this.triggerSqueezed = function() { this.triggerSqueezed = function () {
var triggerValue = Controller.getActionValue(this.triggerAction); var triggerValue = Controller.getActionValue(this.triggerAction);
return triggerValue > TRIGGER_ON_VALUE; return triggerValue > TRIGGER_ON_VALUE;
}; };
this.off = function() { this.off = function () {
if (this.triggerSmoothedSqueezed()) { if (this.triggerSmoothedSqueezed()) {
this.setState(STATE_SEARCHING); this.setState(STATE_SEARCHING);
return; return;
} }
} }
this.search = function() { this.search = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
return; return;
@ -251,9 +259,7 @@ function MyController(hand, triggerAction) {
}; };
var intersection = Entities.findRayIntersection(pickRay, true); var intersection = Entities.findRayIntersection(pickRay, true);
if (intersection.intersects && if (intersection.intersects && intersection.properties.locked === 0) {
intersection.properties.collisionsWillMove === 1 &&
intersection.properties.locked === 0) {
// the ray is intersecting something we can move. // the ray is intersecting something we can move.
var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection); var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection);
@ -266,14 +272,22 @@ function MyController(hand, triggerAction) {
} }
if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) { if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) {
// the hand is very close to the intersected object. go into close-grabbing mode. // the hand is very close to the intersected object. go into close-grabbing mode.
this.setState(STATE_NEAR_GRABBING); if (intersection.properties.collisionsWillMove === 1) {
this.setState(STATE_NEAR_GRABBING);
} else {
this.setState(STATE_NEAR_GRABBING_NON_COLLIDING);
}
} else { } else {
// don't allow two people to distance grab the same object // don't allow two people to distance grab the same object
if (entityIsGrabbedByOther(intersection.entityID)) { if (entityIsGrabbedByOther(intersection.entityID)) {
this.grabbedEntity = null; this.grabbedEntity = null;
} else { } else {
// the hand is far from the intersected object. go into distance-holding mode // the hand is far from the intersected object. go into distance-holding mode
this.setState(STATE_DISTANCE_HOLDING); if (intersection.properties.collisionsWillMove === 1) {
this.setState(STATE_DISTANCE_HOLDING);
} else {
this.setState(STATE_FAR_GRABBING_NON_COLLIDING);
}
} }
} }
} else { } else {
@ -308,12 +322,13 @@ function MyController(hand, triggerAction) {
} }
}; };
this.distanceHolding = function() { this.distanceHolding = function () {
var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation",
"gravity", "ignoreForCollisions"]); "gravity", "ignoreForCollisions"
]);
// add the action and initialize some variables // add the action and initialize some variables
this.currentObjectPosition = grabbedProperties.position; this.currentObjectPosition = grabbedProperties.position;
@ -351,7 +366,7 @@ function MyController(hand, triggerAction) {
}; };
this.continueDistanceHolding = function() { this.continueDistanceHolding = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
return; return;
@ -369,19 +384,19 @@ function MyController(hand, triggerAction) {
// how far did avatar move this timestep? // how far did avatar move this timestep?
var currentPosition = MyAvatar.position; var currentPosition = MyAvatar.position;
var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition);
this.currentAvatarPosition = currentPosition; this.currentAvatarPosition = currentPosition;
// How far did the avatar turn this timestep? // How far did the avatar turn this timestep?
// Note: The following code is too long because we need a Quat.quatBetween() function // Note: The following code is too long because we need a Quat.quatBetween() function
// that returns the minimum quaternion between two quaternions. // that returns the minimum quaternion between two quaternions.
var currentOrientation = MyAvatar.orientation; var currentOrientation = MyAvatar.orientation;
if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) {
var negativeCurrentOrientation = { var negativeCurrentOrientation = {
x: -currentOrientation.x, x: -currentOrientation.x,
y: -currentOrientation.y, y: -currentOrientation.y,
z: -currentOrientation.z, z: -currentOrientation.z,
w: -currentOrientation.w w: -currentOrientation.w
}; };
var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation));
} else { } else {
@ -389,8 +404,8 @@ function MyController(hand, triggerAction) {
} }
var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition);
var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition);
var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar);
var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar);
this.currentAvatarOrientation = currentOrientation; this.currentAvatarOrientation = currentOrientation;
// how far did hand move this timestep? // how far did hand move this timestep?
@ -411,7 +426,7 @@ function MyController(hand, triggerAction) {
var now = Date.now(); var now = Date.now();
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
this.computeReleaseVelocity(deltaPosition, deltaTime, false); this.computeReleaseVelocity(deltaPosition, deltaTime, false);
this.currentObjectPosition = newObjectPosition; this.currentObjectPosition = newObjectPosition;
this.currentObjectTime = now; this.currentObjectTime = now;
@ -431,7 +446,7 @@ function MyController(hand, triggerAction) {
}); });
}; };
this.nearGrabbing = function() { this.nearGrabbing = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
@ -440,8 +455,7 @@ function MyController(hand, triggerAction) {
this.lineOff(); this.lineOff();
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]);
["position", "rotation", "gravity", "ignoreForCollisions"]);
this.activateEntity(this.grabbedEntity, grabbedProperties); this.activateEntity(this.grabbedEntity, grabbedProperties);
var handRotation = this.getHandRotation(); var handRotation = this.getHandRotation();
@ -480,7 +494,7 @@ function MyController(hand, triggerAction) {
this.currentObjectTime = Date.now(); this.currentObjectTime = Date.now();
}; };
this.continueNearGrabbing = function() { this.continueNearGrabbing = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
return; return;
@ -504,10 +518,12 @@ function MyController(hand, triggerAction) {
this.currentObjectTime = now; this.currentObjectTime = now;
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
Entities.updateAction(this.grabbedEntity, this.actionID, {lifetime: ACTION_LIFETIME}); Entities.updateAction(this.grabbedEntity, this.actionID, {
lifetime: ACTION_LIFETIME
});
}; };
this.nearGrabbingNonColliding = function() { this.nearGrabbingNonColliding = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
return; return;
@ -521,16 +537,48 @@ function MyController(hand, triggerAction) {
this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING); this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING);
}; };
this.continueNearGrabbingNonColliding = function() { this.farGrabbingNonColliding = function () {
if (this.triggerSmoothedReleased()) { if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE); this.setState(STATE_RELEASE);
return; return;
} }
if (this.hand === RIGHT_HAND) {
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
} else {
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
}
Entities.callEntityMethod(this.grabbedEntity, "startFarGrabNonColliding");
this.setState(STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING);
};
this.continueNearGrabbingNonColliding = function () {
if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
return;
}
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding");
}; };
this.continueFarGrabbingNonColliding = function () {
if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
return;
}
var handPosition = this.getHandPosition();
var pickRay = {
origin: handPosition,
direction: Quat.getUp(this.getHandRotation())
};
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
Entities.callEntityMethod(this.grabbedEntity, "continueFarGrabbingNonColliding");
};
_this.allTouchedIDs = {}; _this.allTouchedIDs = {};
this.touchTest = function() { this.touchTest = function () {
var maxDistance = 0.05; var maxDistance = 0.05;
var leftHandPosition = MyAvatar.getLeftPalmPosition(); var leftHandPosition = MyAvatar.getLeftPalmPosition();
var rightHandPosition = MyAvatar.getRightPalmPosition(); var rightHandPosition = MyAvatar.getRightPalmPosition();
@ -539,19 +587,19 @@ function MyController(hand, triggerAction) {
var ids = []; var ids = [];
if (leftEntities.length !== 0) { if (leftEntities.length !== 0) {
leftEntities.forEach(function(entity) { leftEntities.forEach(function (entity) {
ids.push(entity); ids.push(entity);
}); });
} }
if (rightEntities.length !== 0) { if (rightEntities.length !== 0) {
rightEntities.forEach(function(entity) { rightEntities.forEach(function (entity) {
ids.push(entity); ids.push(entity);
}); });
} }
ids.forEach(function(id) { ids.forEach(function (id) {
var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); var props = Entities.getEntityProperties(id, ["boundingBox", "name"]);
if (props.name === 'pointer') { if (props.name === 'pointer') {
@ -584,19 +632,19 @@ function MyController(hand, triggerAction) {
}; };
this.startTouch = function(entityID) { this.startTouch = function (entityID) {
Entities.callEntityMethod(entityID, "startTouch"); Entities.callEntityMethod(entityID, "startTouch");
}; };
this.continueTouch = function(entityID) { this.continueTouch = function (entityID) {
Entities.callEntityMethod(entityID, "continueTouch"); Entities.callEntityMethod(entityID, "continueTouch");
}; };
this.stopTouch = function(entityID) { this.stopTouch = function (entityID) {
Entities.callEntityMethod(entityID, "stopTouch"); Entities.callEntityMethod(entityID, "stopTouch");
}; };
this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { this.computeReleaseVelocity = function (deltaPosition, deltaTime, useMultiplier) {
if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) {
var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime);
// don't update grabbedVelocity if the trigger is off. the smoothing of the trigger // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger
@ -613,13 +661,13 @@ function MyController(hand, triggerAction) {
} }
}; };
this.release = function() { this.release = function () {
this.lineOff(); this.lineOff();
if (this.grabbedEntity !== null) { if (this.grabbedEntity !== null) {
if(this.actionID !== null) { if (this.actionID !== null) {
Entities.deleteAction(this.grabbedEntity, this.actionID); Entities.deleteAction(this.grabbedEntity, this.actionID);
} }
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
} }
@ -637,11 +685,11 @@ function MyController(hand, triggerAction) {
this.setState(STATE_OFF); this.setState(STATE_OFF);
}; };
this.cleanup = function() { this.cleanup = function () {
this.release(); this.release();
}; };
this.activateEntity = function(entityID, grabbedProperties) { this.activateEntity = function (entityID, grabbedProperties) {
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
data["activated"] = true; data["activated"] = true;
data["avatarId"] = MyAvatar.sessionUUID; data["avatarId"] = MyAvatar.sessionUUID;
@ -650,12 +698,19 @@ function MyController(hand, triggerAction) {
if (data["refCount"] == 1) { if (data["refCount"] == 1) {
data["gravity"] = grabbedProperties.gravity; data["gravity"] = grabbedProperties.gravity;
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
Entities.editEntity(entityID, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); Entities.editEntity(entityID, {
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreForCollisions: true
});
} }
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
}; };
this.deactivateEntity = function(entityID) { this.deactivateEntity = function (entityID) {
var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {});
if (data && data["refCount"]) { if (data && data["refCount"]) {
data["refCount"] = data["refCount"] - 1; data["refCount"] = data["refCount"] - 1;
@ -687,4 +742,4 @@ function cleanup() {
} }
Script.scriptEnding.connect(cleanup); Script.scriptEnding.connect(cleanup);
Script.update.connect(update); Script.update.connect(update);