mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 22:51:20 +02:00
Merge pull request #5702 from ericrius1/newGrab
update hydra grab to grab near and far objects, and removed grabbing…
This commit is contained in:
commit
e6f43d3dd7
2 changed files with 269 additions and 488 deletions
|
@ -1,307 +1,319 @@
|
||||||
//
|
|
||||||
// hydraGrab.js
|
// hydraGrab.js
|
||||||
// examples
|
// examples
|
||||||
//
|
//
|
||||||
// Created by Clément Brisset on 4/24/14.
|
// Created by Eric Levin on 9/2/15
|
||||||
// Updated by Eric Levin on 5/14/15.
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
//
|
||||||
// This script allows you to grab and move/rotate physical objects with the hydra
|
// Grab's physically moveable entities with the hydra- works for either near or far objects. User can also grab a far away object and drag it towards them by pressing the "4" button on either the left or ride controller.
|
||||||
//
|
|
||||||
// Using the hydras :
|
|
||||||
// grab physical entities with the right trigger
|
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
var entityProps, currentPosition, currentVelocity, currentRotation, distanceToTarget, velocityTowardTarget, desiredVelocity;
|
var RIGHT_HAND_CLICK = Controller.findAction("RIGHT_HAND_CLICK");
|
||||||
var addedVelocity, newVelocity, angularVelocity, dT, cameraEntityDistance;
|
var rightTriggerAction = RIGHT_HAND_CLICK;
|
||||||
var LEFT = 0;
|
|
||||||
var RIGHT = 1;
|
|
||||||
var LASER_WIDTH = 3;
|
|
||||||
var LASER_COLOR = {
|
|
||||||
red: 50,
|
|
||||||
green: 150,
|
|
||||||
blue: 200
|
|
||||||
};
|
|
||||||
var LASER_HOVER_COLOR = {
|
|
||||||
red: 200,
|
|
||||||
green: 50,
|
|
||||||
blue: 50
|
|
||||||
};
|
|
||||||
|
|
||||||
var DROP_DISTANCE = 5.0;
|
var LEFT_HAND_CLICK = Controller.findAction("LEFT_HAND_CLICK");
|
||||||
var DROP_COLOR = {
|
var leftTriggerAction = LEFT_HAND_CLICK;
|
||||||
red: 200,
|
|
||||||
green: 200,
|
|
||||||
blue: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
var FULL_STRENGTH = 0.05;
|
var ZERO_VEC = {
|
||||||
var LASER_LENGTH_FACTOR = 500;
|
|
||||||
var CLOSE_ENOUGH = 0.001;
|
|
||||||
var SPRING_RATE = 1.5;
|
|
||||||
var DAMPING_RATE = 0.8;
|
|
||||||
var SCREEN_TO_METERS = 0.001;
|
|
||||||
var DISTANCE_SCALE_FACTOR = 1000
|
|
||||||
|
|
||||||
var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
|
|
||||||
var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
|
|
||||||
|
|
||||||
function getRayIntersection(pickRay) {
|
|
||||||
var intersection = Entities.findRayIntersection(pickRay, true);
|
|
||||||
return intersection;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function controller(side) {
|
|
||||||
this.triggerHeld = false;
|
|
||||||
this.triggerThreshold = 0.9;
|
|
||||||
this.side = side;
|
|
||||||
this.palm = 2 * side;
|
|
||||||
this.tip = 2 * side + 1;
|
|
||||||
this.trigger = side;
|
|
||||||
this.originalGravity = {
|
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
};
|
}
|
||||||
|
var LINE_LENGTH = 500;
|
||||||
|
var THICK_LINE_WIDTH = 7;
|
||||||
|
var THIN_LINE_WIDTH = 2;
|
||||||
|
|
||||||
this.laser = Overlays.addOverlay("line3d", {
|
var NO_INTERSECT_COLOR = {
|
||||||
start: {
|
red: 10,
|
||||||
x: 0,
|
green: 10,
|
||||||
y: 0,
|
blue: 255
|
||||||
z: 0
|
};
|
||||||
},
|
var INTERSECT_COLOR = {
|
||||||
end: {
|
red: 250,
|
||||||
x: 0,
|
green: 10,
|
||||||
y: 0,
|
blue: 10
|
||||||
z: 0
|
};
|
||||||
},
|
|
||||||
color: LASER_COLOR,
|
|
||||||
alpha: 1,
|
|
||||||
lineWidth: LASER_WIDTH,
|
|
||||||
anchor: "MyAvatar"
|
|
||||||
});
|
|
||||||
|
|
||||||
this.dropLine = Overlays.addOverlay("line3d", {
|
var GRAB_RADIUS = 2;
|
||||||
color: DROP_COLOR,
|
|
||||||
alpha: 1,
|
|
||||||
visible: false,
|
|
||||||
lineWidth: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
|
var GRAB_COLOR = {
|
||||||
|
red: 250,
|
||||||
|
green: 10,
|
||||||
|
blue: 250
|
||||||
|
};
|
||||||
|
var SHOW_LINE_THRESHOLD = 0.2;
|
||||||
|
var DISTANCE_HOLD_THRESHOLD = 0.8;
|
||||||
|
|
||||||
this.update = function(deltaTime) {
|
var right4Action = 18;
|
||||||
this.updateControllerState();
|
var left4Action = 17;
|
||||||
this.moveLaser();
|
|
||||||
this.checkTrigger();
|
|
||||||
this.checkEntityIntersection();
|
|
||||||
if (this.grabbing) {
|
|
||||||
this.updateEntity(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.oldPalmPosition = this.palmPosition;
|
var TRACTOR_BEAM_VELOCITY_THRESHOLD = 0.5;
|
||||||
this.oldTipPosition = this.tipPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateEntity = function(deltaTime) {
|
var RIGHT = 1;
|
||||||
this.dControllerPosition = Vec3.subtract(this.palmPosition, this.oldPalmPosition);
|
var LEFT = 0;
|
||||||
this.cameraEntityDistance = Vec3.distance(Camera.getPosition(), this.currentPosition);
|
var rightController = new controller(RIGHT, rightTriggerAction, right4Action, "right")
|
||||||
this.targetPosition = Vec3.sum(this.targetPosition, Vec3.multiply(this.dControllerPosition, this.cameraEntityDistance * SCREEN_TO_METERS * DISTANCE_SCALE_FACTOR));
|
var leftController = new controller(LEFT, leftTriggerAction, left4Action, "left")
|
||||||
|
|
||||||
this.entityProps = Entities.getEntityProperties(this.grabbedEntity);
|
function controller(side, triggerAction, pullAction, hand) {
|
||||||
this.currentPosition = this.entityProps.position;
|
this.hand = hand;
|
||||||
this.currentVelocity = this.entityProps.velocity;
|
if (hand === "right") {
|
||||||
|
this.getHandPosition = MyAvatar.getRightPalmPosition;
|
||||||
var dPosition = Vec3.subtract(this.targetPosition, this.currentPosition);
|
this.getHandRotation = MyAvatar.getRightPalmRotation;
|
||||||
this.distanceToTarget = Vec3.length(dPosition);
|
|
||||||
if (this.distanceToTarget > CLOSE_ENOUGH) {
|
|
||||||
// compute current velocity in the direction we want to move
|
|
||||||
this.velocityTowardTarget = Vec3.dot(this.currentVelocity, Vec3.normalize(dPosition));
|
|
||||||
this.velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), this.velocityTowardTarget);
|
|
||||||
// compute the speed we would like to be going toward the target position
|
|
||||||
|
|
||||||
this.desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
|
|
||||||
// compute how much we want to add to the existing velocity
|
|
||||||
this.addedVelocity = Vec3.subtract(this.desiredVelocity, this.velocityTowardTarget);
|
|
||||||
//If target is to far, roll off force as inverse square of distance
|
|
||||||
if(this.distanceToTarget/ this.cameraEntityDistance > FULL_STRENGTH) {
|
|
||||||
this.addedVelocity = Vec3.multiply(this.addedVelocity, Math.pow(FULL_STRENGTH/ this.distanceToTarget, 2.0));
|
|
||||||
}
|
|
||||||
this.newVelocity = Vec3.sum(this.currentVelocity, this.addedVelocity);
|
|
||||||
this.newVelocity = Vec3.subtract(this.newVelocity, Vec3.multiply(this.newVelocity, DAMPING_RATE));
|
|
||||||
} else {
|
} else {
|
||||||
this.newVelocity = {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.transformedAngularVelocity = Controller.getSpatialControlRawAngularVelocity(this.tip);
|
|
||||||
this.transformedAngularVelocity = Vec3.multiplyQbyV(Camera.getOrientation(), this.transformedAngularVelocity);
|
|
||||||
|
|
||||||
Entities.editEntity(this.grabbedEntity, {
|
this.getHandPosition = MyAvatar.getLeftPalmPosition;
|
||||||
velocity: this.newVelocity,
|
this.getHandRotation = MyAvatar.getLeftPalmRotation;
|
||||||
angularVelocity: this.transformedAngularVelocity
|
}
|
||||||
|
this.triggerAction = triggerAction;
|
||||||
|
this.pullAction = pullAction;
|
||||||
|
this.actionID = null;
|
||||||
|
this.tractorBeamActive = false;
|
||||||
|
this.distanceHolding = false;
|
||||||
|
this.closeGrabbing = false;
|
||||||
|
this.triggerValue = 0;
|
||||||
|
this.prevTriggerValue = 0;
|
||||||
|
this.palm = 2 * side;
|
||||||
|
this.tip = 2 * side + 1;
|
||||||
|
this.pointer = Entities.addEntity({
|
||||||
|
type: "Line",
|
||||||
|
name: "pointer",
|
||||||
|
color: NO_INTERSECT_COLOR,
|
||||||
|
dimensions: {
|
||||||
|
x: 1000,
|
||||||
|
y: 1000,
|
||||||
|
z: 1000
|
||||||
|
},
|
||||||
|
visible: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
controller.prototype.updateLine = function() {
|
||||||
|
var handPosition = Controller.getSpatialControlPosition(this.palm);
|
||||||
|
var direction = Controller.getSpatialControlNormal(this.tip);
|
||||||
|
|
||||||
|
Entities.editEntity(this.pointer, {
|
||||||
|
position: handPosition,
|
||||||
|
linePoints: [
|
||||||
|
ZERO_VEC,
|
||||||
|
Vec3.multiply(direction, LINE_LENGTH)
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
this.updateDropLine(this.targetPosition);
|
//only check if we havent already grabbed an object
|
||||||
|
if (this.distanceHolding) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
|
||||||
this.updateControllerState = function() {
|
|
||||||
this.palmPosition = Controller.getSpatialControlPosition(this.palm);
|
|
||||||
this.tipPosition = Controller.getSpatialControlPosition(this.tip);
|
|
||||||
this.triggerValue = Controller.getTriggerValue(this.trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.checkTrigger = function() {
|
|
||||||
if (this.triggerValue > this.triggerThreshold && !this.triggerHeld) {
|
|
||||||
this.triggerHeld = true;
|
|
||||||
} else if (this.triggerValue < this.triggerThreshold && this.triggerHeld) {
|
|
||||||
this.triggerHeld = false;
|
|
||||||
if (this.grabbing) {
|
|
||||||
this.release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//move origin a bit away from hand so nothing gets in way
|
||||||
|
var origin = Vec3.sum(handPosition, direction);
|
||||||
|
if (this.checkForIntersections(origin, direction)) {
|
||||||
|
Entities.editEntity(this.pointer, {
|
||||||
|
color: INTERSECT_COLOR,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Entities.editEntity(this.pointer, {
|
||||||
|
color: NO_INTERSECT_COLOR,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.updateDropLine = function(position) {
|
|
||||||
|
|
||||||
Overlays.editOverlay(this.dropLine, {
|
|
||||||
visible: true,
|
|
||||||
start: {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y + DROP_DISTANCE,
|
|
||||||
z: position.z
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y - DROP_DISTANCE,
|
|
||||||
z: position.z
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.checkEntityIntersection = function() {
|
|
||||||
|
|
||||||
|
controller.prototype.checkForIntersections = function(origin, direction) {
|
||||||
var pickRay = {
|
var pickRay = {
|
||||||
origin: this.palmPosition,
|
origin: origin,
|
||||||
direction: Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition))
|
direction: direction
|
||||||
};
|
};
|
||||||
var intersection = getRayIntersection(pickRay, true);
|
|
||||||
if (intersection.intersects && intersection.properties.collisionsWillMove) {
|
var intersection = Entities.findRayIntersection(pickRay, true);
|
||||||
this.laserWasHovered = true;
|
if (intersection.intersects && intersection.properties.collisionsWillMove === 1) {
|
||||||
if (this.triggerHeld && !this.grabbing) {
|
this.distanceToEntity = Vec3.distance(origin, intersection.properties.position);
|
||||||
this.grab(intersection.entityID);
|
Entities.editEntity(this.pointer, {
|
||||||
}
|
linePoints: [
|
||||||
Overlays.editOverlay(this.laser, {
|
ZERO_VEC,
|
||||||
color: LASER_HOVER_COLOR
|
Vec3.multiply(direction, this.distanceToEntity)
|
||||||
});
|
]
|
||||||
} else if (this.laserWasHovered) {
|
});
|
||||||
this.laserWasHovered = false;
|
this.grabbedEntity = intersection.entityID;
|
||||||
Overlays.editOverlay(this.laser, {
|
return true;
|
||||||
color: LASER_COLOR
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.grab = function(entityId) {
|
controller.prototype.attemptMove = function() {
|
||||||
this.grabbing = true;
|
if (this.tractorBeamActive) {
|
||||||
this.grabbedEntity = entityId;
|
return;
|
||||||
this.entityProps = Entities.getEntityProperties(this.grabbedEntity);
|
}
|
||||||
this.targetPosition = this.entityProps.position;
|
if (this.grabbedEntity || this.distanceHolding) {
|
||||||
this.currentPosition = this.targetPosition;
|
var handPosition = Controller.getSpatialControlPosition(this.palm);
|
||||||
this.oldPalmPosition = this.palmPosition;
|
var direction = Controller.getSpatialControlNormal(this.tip);
|
||||||
this.originalGravity = this.entityProps.gravity;
|
|
||||||
Entities.editEntity(this.grabbedEntity, {
|
|
||||||
gravity: {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(this.laser, {
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
Audio.playSound(grabSound, {
|
|
||||||
position: this.entityProps.position,
|
|
||||||
volume: 0.25
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.release = function() {
|
var newPosition = Vec3.sum(handPosition, Vec3.multiply(direction, this.distanceToEntity))
|
||||||
this.grabbing = false;
|
this.distanceHolding = true;
|
||||||
|
//TO DO : USE SPRING ACTION UPDATE FOR MOVING
|
||||||
|
if (this.actionID === null) {
|
||||||
|
this.actionID = Entities.addAction("spring", this.grabbedEntity, {
|
||||||
|
targetPosition: newPosition,
|
||||||
|
linearTimeScale: .1
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||||
|
targetPosition: newPosition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.prototype.showPointer = function() {
|
||||||
|
Entities.editEntity(this.pointer, {
|
||||||
|
visible: true
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.prototype.hidePointer = function() {
|
||||||
|
Entities.editEntity(this.pointer, {
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
controller.prototype.letGo = function() {
|
||||||
|
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
Overlays.editOverlay(this.laser, {
|
this.actionID = null;
|
||||||
visible: true
|
this.distanceHolding = false;
|
||||||
});
|
this.tractorBeamActive = false;
|
||||||
Overlays.editOverlay(this.dropLine, {
|
this.checkForEntityArrival = false;
|
||||||
visible: false
|
this.closeGrabbing = false;
|
||||||
});
|
}
|
||||||
|
|
||||||
Audio.playSound(releaseSound, {
|
controller.prototype.update = function() {
|
||||||
position: this.entityProps.position,
|
if (this.tractorBeamActive && this.checkForEntityArrival) {
|
||||||
volume: 0.25
|
var entityVelocity = Entities.getEntityProperties(this.grabbedEntity).velocity
|
||||||
});
|
if (Vec3.length(entityVelocity) < TRACTOR_BEAM_VELOCITY_THRESHOLD) {
|
||||||
|
this.letGo();
|
||||||
// only restore the original gravity if it's not zero. This is to avoid...
|
}
|
||||||
// 1. interface A grabs an entity and locally saves off its gravity
|
return;
|
||||||
// 2. interface A sets the entity's gravity to zero
|
}
|
||||||
// 3. interface B grabs the entity and saves off its gravity (which is zero)
|
this.triggerValue = Controller.getActionValue(this.triggerAction);
|
||||||
// 4. interface A releases the entity and puts the original gravity back
|
if (this.triggerValue > SHOW_LINE_THRESHOLD && this.prevTriggerValue < SHOW_LINE_THRESHOLD) {
|
||||||
// 5. interface B releases the entity and puts the original gravity back (to zero)
|
//First check if an object is within close range and then run the close grabbing logic
|
||||||
if(vectorIsZero(this.originalGravity)) {
|
if (this.checkForInRangeObject()) {
|
||||||
Entities.editEntity(this.grabbedEntity, {
|
this.grabEntity();
|
||||||
gravity: this.originalGravity
|
} else {
|
||||||
});
|
this.showPointer();
|
||||||
|
this.shouldDisplayLine = true;
|
||||||
|
}
|
||||||
|
} else if (this.triggerValue < SHOW_LINE_THRESHOLD && this.prevTriggerValue > SHOW_LINE_THRESHOLD) {
|
||||||
|
this.hidePointer();
|
||||||
|
this.letGo();
|
||||||
|
this.shouldDisplayLine = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.moveLaser = function() {
|
if (this.shouldDisplayLine) {
|
||||||
var inverseRotation = Quat.inverse(MyAvatar.orientation);
|
this.updateLine();
|
||||||
var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position));
|
}
|
||||||
// startPosition = Vec3.multiply(startPosition, 1 / MyAvatar.scale);
|
if (this.triggerValue > DISTANCE_HOLD_THRESHOLD && !this.closeGrabbing) {
|
||||||
var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition));
|
this.attemptMove();
|
||||||
direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / (Vec3.length(direction) * MyAvatar.scale));
|
}
|
||||||
var endPosition = Vec3.sum(startPosition, direction);
|
|
||||||
|
|
||||||
Overlays.editOverlay(this.laser, {
|
|
||||||
start: startPosition,
|
this.prevTriggerValue = this.triggerValue;
|
||||||
end: endPosition
|
}
|
||||||
|
|
||||||
|
controller.prototype.grabEntity = function() {
|
||||||
|
var handRotation = this.getHandRotation();
|
||||||
|
var handPosition = this.getHandPosition();
|
||||||
|
|
||||||
|
var objectRotation = Entities.getEntityProperties(this.grabbedEntity).rotation;
|
||||||
|
var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||||
|
|
||||||
|
var objectPosition = Entities.getEntityProperties(this.grabbedEntity).position;
|
||||||
|
var offset = Vec3.subtract(objectPosition, handPosition);
|
||||||
|
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
||||||
|
this.closeGrabbing = true;
|
||||||
|
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
||||||
|
relativePosition: offsetPosition,
|
||||||
|
relativeRotation: offsetRotation,
|
||||||
|
hand: this.hand,
|
||||||
|
timeScale: 0.05
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cleanup = function() {
|
|
||||||
Overlays.deleteOverlay(this.laser);
|
|
||||||
Overlays.deleteOverlay(this.dropLine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(deltaTime) {
|
|
||||||
rightController.update(deltaTime);
|
controller.prototype.checkForInRangeObject = function() {
|
||||||
leftController.update(deltaTime);
|
var handPosition = Controller.getSpatialControlPosition(this.palm);
|
||||||
|
var entities = Entities.findEntities(handPosition, GRAB_RADIUS);
|
||||||
|
var minDistance = GRAB_RADIUS;
|
||||||
|
var grabbedEntity = null;
|
||||||
|
//Get nearby entities and assign nearest
|
||||||
|
for (var i = 0; i < entities.length; i++) {
|
||||||
|
var props = Entities.getEntityProperties(entities[i]);
|
||||||
|
var distance = Vec3.distance(props.position, handPosition);
|
||||||
|
if (distance < minDistance && props.name !== "pointer" && props.collisionsWillMove === 1) {
|
||||||
|
grabbedEntity = entities[i];
|
||||||
|
minDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grabbedEntity === null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.grabbedEntity = grabbedEntity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scriptEnding() {
|
|
||||||
rightController.cleanup();
|
controller.prototype.onActionEvent = function(action, state) {
|
||||||
leftController.cleanup();
|
if (this.pullAction === action && state === 1) {
|
||||||
|
if (this.actionID !== null) {
|
||||||
|
var self = this;
|
||||||
|
this.tractorBeamActive = true;
|
||||||
|
//We need to wait a bit before checking for entity arrival at target destination (meaning checking for velocity being close to some
|
||||||
|
//low threshold) because otherwise we'll think the entity has arrived before its even really gotten moving!
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
self.checkForEntityArrival = true;
|
||||||
|
}, 500);
|
||||||
|
var handPosition = Controller.getSpatialControlPosition(this.palm);
|
||||||
|
var direction = Controller.getSpatialControlNormal(this.tip);
|
||||||
|
//move final destination along line a bit, so it doesnt hit avatar hand
|
||||||
|
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||||
|
targetPosition: Vec3.sum(handPosition, Vec3.multiply(2, direction))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function vectorIsZero(v) {
|
controller.prototype.cleanup = function() {
|
||||||
return v.x === 0 && v.y === 0 && v.z === 0;
|
Entities.deleteEntity(this.pointer);
|
||||||
|
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rightController = new controller(RIGHT);
|
function update() {
|
||||||
var leftController = new controller(LEFT);
|
rightController.update();
|
||||||
|
leftController.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onActionEvent(action, state) {
|
||||||
|
rightController.onActionEvent(action, state);
|
||||||
|
leftController.onActionEvent(action, state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Script.update.connect(update);
|
function cleanup() {
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
rightController.cleanup();
|
||||||
|
leftController.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
Script.update.connect(update)
|
||||||
|
Controller.actionEvent.connect(onActionEvent);
|
|
@ -13,32 +13,7 @@ Script.include("http://s3.amazonaws.com/hifi-public/scripts/libraries/toolBars.j
|
||||||
|
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
|
||||||
var nullActionID = "00000000-0000-0000-0000-000000000000";
|
|
||||||
var controllerID;
|
|
||||||
var controllerActive;
|
|
||||||
var leftHandObjectID = null;
|
|
||||||
var rightHandObjectID = null;
|
|
||||||
var leftHandActionID = nullActionID;
|
|
||||||
var rightHandActionID = nullActionID;
|
|
||||||
|
|
||||||
var TRIGGER_THRESHOLD = 0.2;
|
|
||||||
var GRAB_RADIUS = 0.15;
|
|
||||||
|
|
||||||
var LEFT_HAND_CLICK = Controller.findAction("LEFT_HAND_CLICK");
|
|
||||||
var RIGHT_HAND_CLICK = Controller.findAction("RIGHT_HAND_CLICK");
|
|
||||||
var ACTION1 = Controller.findAction("ACTION1");
|
|
||||||
var ACTION2 = Controller.findAction("ACTION2");
|
|
||||||
|
|
||||||
var rightHandGrabAction = RIGHT_HAND_CLICK;
|
|
||||||
var leftHandGrabAction = LEFT_HAND_CLICK;
|
|
||||||
|
|
||||||
var rightHandGrabValue = 0;
|
|
||||||
var leftHandGrabValue = 0;
|
|
||||||
var prevRightHandGrabValue = 0
|
|
||||||
var prevLeftHandGrabValue = 0;
|
|
||||||
|
|
||||||
var grabColor = { red: 0, green: 255, blue: 0};
|
|
||||||
var releaseColor = { red: 0, green: 0, blue: 255};
|
|
||||||
|
|
||||||
var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.toybox.toolbar", function() {
|
var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.toybox.toolbar", function() {
|
||||||
return {
|
return {
|
||||||
|
@ -63,25 +38,6 @@ var cleanupButton = toolBar.addOverlay("image", {
|
||||||
alpha: 1
|
alpha: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
var overlays = false;
|
|
||||||
var leftHandOverlay;
|
|
||||||
var rightHandOverlay;
|
|
||||||
if (overlays) {
|
|
||||||
leftHandOverlay = Overlays.addOverlay("sphere", {
|
|
||||||
position: MyAvatar.getLeftPalmPosition(),
|
|
||||||
size: GRAB_RADIUS,
|
|
||||||
color: releaseColor,
|
|
||||||
alpha: 0.5,
|
|
||||||
solid: false
|
|
||||||
});
|
|
||||||
rightHandOverlay = Overlays.addOverlay("sphere", {
|
|
||||||
position: MyAvatar.getRightPalmPosition(),
|
|
||||||
size: GRAB_RADIUS,
|
|
||||||
color: releaseColor,
|
|
||||||
alpha: 0.5,
|
|
||||||
solid: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var OBJECT_HEIGHT_OFFSET = 0.5;
|
var OBJECT_HEIGHT_OFFSET = 0.5;
|
||||||
var MIN_OBJECT_SIZE = 0.05;
|
var MIN_OBJECT_SIZE = 0.05;
|
||||||
|
@ -98,8 +54,6 @@ var GRAVITY = {
|
||||||
z: 0.0
|
z: 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
var LEFT = 0;
|
|
||||||
var RIGHT = 1;
|
|
||||||
|
|
||||||
var tableCreated = false;
|
var tableCreated = false;
|
||||||
|
|
||||||
|
@ -108,7 +62,6 @@ var tableEntities = Array(NUM_OBJECTS + 1); // Also includes table
|
||||||
|
|
||||||
var VELOCITY_MAG = 0.3;
|
var VELOCITY_MAG = 0.3;
|
||||||
|
|
||||||
var entitiesToResize = [];
|
|
||||||
|
|
||||||
var MODELS = Array(
|
var MODELS = Array(
|
||||||
{ modelURL: "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx" },
|
{ modelURL: "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx" },
|
||||||
|
@ -136,196 +89,15 @@ var COLLISION_SOUNDS = Array(
|
||||||
var RESIZE_TIMER = 0.0;
|
var RESIZE_TIMER = 0.0;
|
||||||
var RESIZE_WAIT = 0.05; // 50 milliseconds
|
var RESIZE_WAIT = 0.05; // 50 milliseconds
|
||||||
|
|
||||||
var leftFist = Entities.addEntity( {
|
|
||||||
type: "Sphere",
|
|
||||||
shapeType: 'sphere',
|
|
||||||
position: MyAvatar.getLeftPalmPosition(),
|
|
||||||
dimensions: { x: GRAB_RADIUS, y: GRAB_RADIUS, z: GRAB_RADIUS },
|
|
||||||
rotation: MyAvatar.getLeftPalmRotation(),
|
|
||||||
visible: false,
|
|
||||||
collisionsWillMove: false,
|
|
||||||
ignoreForCollisions: true
|
|
||||||
});
|
|
||||||
var rightFist = Entities.addEntity( {
|
|
||||||
type: "Sphere",
|
|
||||||
shapeType: 'sphere',
|
|
||||||
position: MyAvatar.getRightPalmPosition(),
|
|
||||||
dimensions: { x: GRAB_RADIUS, y: GRAB_RADIUS, z: GRAB_RADIUS },
|
|
||||||
rotation: MyAvatar.getRightPalmRotation(),
|
|
||||||
visible: false,
|
|
||||||
collisionsWillMove: false,
|
|
||||||
ignoreForCollisions: true
|
|
||||||
});
|
|
||||||
|
|
||||||
function letGo(hand) {
|
|
||||||
var actionIDToRemove = (hand == LEFT) ? leftHandActionID : rightHandActionID;
|
|
||||||
var entityIDToEdit = (hand == LEFT) ? leftHandObjectID : rightHandObjectID;
|
|
||||||
var handVelocity = (hand == LEFT) ? MyAvatar.getLeftPalmVelocity() : MyAvatar.getRightPalmVelocity();
|
|
||||||
var handAngularVelocity = (hand == LEFT) ? MyAvatar.getLeftPalmAngularVelocity() :
|
|
||||||
MyAvatar.getRightPalmAngularVelocity();
|
|
||||||
if (actionIDToRemove != nullActionID && entityIDToEdit != null) {
|
|
||||||
Entities.deleteAction(entityIDToEdit, actionIDToRemove);
|
|
||||||
// TODO: upon successful letGo, restore collision groups
|
|
||||||
if (hand == LEFT) {
|
|
||||||
leftHandObjectID = null;
|
|
||||||
leftHandActionID = nullActionID;
|
|
||||||
} else {
|
|
||||||
rightHandObjectID = null;
|
|
||||||
rightHandActionID = nullActionID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setGrabbedObject(hand) {
|
|
||||||
var handPosition = (hand == LEFT) ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition();
|
|
||||||
var entities = Entities.findEntities(handPosition, GRAB_RADIUS);
|
|
||||||
var objectID = null;
|
|
||||||
var minDistance = GRAB_RADIUS;
|
|
||||||
for (var i = 0; i < entities.length; i++) {
|
|
||||||
// Don't grab the object in your other hands, your fists, or the table
|
|
||||||
if ((hand == LEFT && entities[i] == rightHandObjectID) ||
|
|
||||||
(hand == RIGHT && entities[i] == leftHandObjectID) ||
|
|
||||||
entities[i] == leftFist || entities[i] == rightFist ||
|
|
||||||
(tableCreated && entities[i] == tableEntities[0])) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
var distance = Vec3.distance(Entities.getEntityProperties(entities[i]).position, handPosition);
|
|
||||||
if (distance <= minDistance) {
|
|
||||||
objectID = entities[i];
|
|
||||||
minDistance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (objectID == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hand == LEFT) {
|
|
||||||
leftHandObjectID = objectID;
|
|
||||||
} else {
|
|
||||||
rightHandObjectID = objectID;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function grab(hand) {
|
|
||||||
if (!setGrabbedObject(hand)) {
|
|
||||||
// If you don't grab an object, make a fist
|
|
||||||
Entities.editEntity((hand == LEFT) ? leftFist : rightFist, { ignoreForCollisions: false } );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var objectID = (hand == LEFT) ? leftHandObjectID : rightHandObjectID;
|
|
||||||
var handRotation = (hand == LEFT) ? MyAvatar.getLeftPalmRotation() : MyAvatar.getRightPalmRotation();
|
|
||||||
var handPosition = (hand == LEFT) ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition();
|
|
||||||
|
|
||||||
var objectRotation = Entities.getEntityProperties(objectID).rotation;
|
|
||||||
var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
|
||||||
|
|
||||||
var objectPosition = Entities.getEntityProperties(objectID).position;
|
|
||||||
var offset = Vec3.subtract(objectPosition, handPosition);
|
|
||||||
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
|
||||||
// print(JSON.stringify(offsetPosition));
|
|
||||||
var actionID = Entities.addAction("hold", objectID, {
|
|
||||||
relativePosition: { x: 0, y: 0, z: 0 },
|
|
||||||
relativeRotation: offsetRotation,
|
|
||||||
hand: (hand == LEFT) ? "left" : "right",
|
|
||||||
timeScale: 0.05
|
|
||||||
});
|
|
||||||
if (actionID == nullActionID) {
|
|
||||||
if (hand == LEFT) {
|
|
||||||
leftHandObjectID = null;
|
|
||||||
} else {
|
|
||||||
rightHandObjectID = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO: upon successful grab, add to collision group so object doesn't collide with immovable entities
|
|
||||||
if (hand == LEFT) {
|
|
||||||
leftHandActionID = actionID;
|
|
||||||
} else {
|
|
||||||
rightHandActionID = actionID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resizeModels() {
|
|
||||||
var newEntitiesToResize = [];
|
|
||||||
for (var i = 0; i < entitiesToResize.length; i++) {
|
|
||||||
var naturalDimensions = Entities.getEntityProperties(entitiesToResize[i]).naturalDimensions;
|
|
||||||
if (naturalDimensions.x != 1.0 || naturalDimensions.y != 1.0 || naturalDimensions.z != 1.0) {
|
|
||||||
// bigger range of sizes for models
|
|
||||||
var dimensions = Vec3.multiply(randFloat(MIN_OBJECT_SIZE, 3.0*MAX_OBJECT_SIZE), Vec3.normalize(naturalDimensions));
|
|
||||||
Entities.editEntity(entitiesToResize[i], {
|
|
||||||
dimensions: dimensions,
|
|
||||||
shapeType: "box"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
newEntitiesToResize.push(entitiesToResize[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
entitiesToResize = newEntitiesToResize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(deltaTime) {
|
|
||||||
if (overlays) {
|
|
||||||
Overlays.editOverlay(leftHandOverlay, { position: MyAvatar.getLeftPalmPosition() });
|
|
||||||
Overlays.editOverlay(rightHandOverlay, { position: MyAvatar.getRightPalmPosition() });
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (tableCreated && RESIZE_TIMER < RESIZE_WAIT) {
|
|
||||||
// RESIZE_TIMER += deltaTime;
|
|
||||||
// } else if (tableCreated) {
|
|
||||||
// resizeModels();
|
|
||||||
// }
|
|
||||||
|
|
||||||
rightHandGrabValue = Controller.getActionValue(rightHandGrabAction);
|
|
||||||
leftHandGrabValue = Controller.getActionValue(leftHandGrabAction);
|
|
||||||
|
|
||||||
Entities.editEntity(leftFist, { position: MyAvatar.getLeftPalmPosition() });
|
|
||||||
Entities.editEntity(rightFist, { position: MyAvatar.getRightPalmPosition() });
|
|
||||||
|
|
||||||
if (rightHandGrabValue > TRIGGER_THRESHOLD &&
|
|
||||||
prevRightHandGrabValue < TRIGGER_THRESHOLD) {
|
|
||||||
if (overlays) {
|
|
||||||
Overlays.editOverlay(rightHandOverlay, { color: grabColor });
|
|
||||||
}
|
|
||||||
grab(RIGHT);
|
|
||||||
} else if (rightHandGrabValue < TRIGGER_THRESHOLD &&
|
|
||||||
prevRightHandGrabValue > TRIGGER_THRESHOLD) {
|
|
||||||
Entities.editEntity(rightFist, { ignoreForCollisions: true } );
|
|
||||||
if (overlays) {
|
|
||||||
Overlays.editOverlay(rightHandOverlay, { color: releaseColor });
|
|
||||||
}
|
|
||||||
letGo(RIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (leftHandGrabValue > TRIGGER_THRESHOLD &&
|
|
||||||
prevLeftHandGrabValue < TRIGGER_THRESHOLD) {
|
|
||||||
if (overlays) {
|
|
||||||
Overlays.editOverlay(leftHandOverlay, { color: grabColor });
|
|
||||||
}
|
|
||||||
grab(LEFT);
|
|
||||||
} else if (leftHandGrabValue < TRIGGER_THRESHOLD &&
|
|
||||||
prevLeftHandGrabValue > TRIGGER_THRESHOLD) {
|
|
||||||
Entities.editEntity(leftFist, { ignoreForCollisions: true } );
|
|
||||||
if (overlays) {
|
|
||||||
Overlays.editOverlay(leftHandOverlay, { color: releaseColor });
|
|
||||||
}
|
|
||||||
letGo(LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
prevRightHandGrabValue = rightHandGrabValue;
|
|
||||||
prevLeftHandGrabValue = leftHandGrabValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanUp() {
|
function cleanUp() {
|
||||||
letGo(RIGHT);
|
print("CLEANUP!!!")
|
||||||
letGo(LEFT);
|
|
||||||
if (overlays) {
|
if (overlays) {
|
||||||
Overlays.deleteOverlay(leftHandOverlay);
|
Overlays.deleteOverlay(leftHandOverlay);
|
||||||
Overlays.deleteOverlay(rightHandOverlay);
|
Overlays.deleteOverlay(rightHandOverlay);
|
||||||
}
|
}
|
||||||
Entities.deleteEntity(leftFist);
|
|
||||||
Entities.deleteEntity(rightFist);
|
|
||||||
removeTable();
|
removeTable();
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
}
|
}
|
||||||
|
@ -405,7 +177,6 @@ function createTable() {
|
||||||
density: 0.5,
|
density: 0.5,
|
||||||
collisionsWillMove: true,
|
collisionsWillMove: true,
|
||||||
color: { red: randInt(0, 255), green: randInt(0, 255), blue: randInt(0, 255) },
|
color: { red: randInt(0, 255), green: randInt(0, 255), blue: randInt(0, 255) },
|
||||||
// collisionSoundURL: COLLISION_SOUNDS[randInt(0, COLLISION_SOUNDS.length)]
|
|
||||||
});
|
});
|
||||||
if (type == "Model") {
|
if (type == "Model") {
|
||||||
var randModel = randInt(0, MODELS.length);
|
var randModel = randInt(0, MODELS.length);
|
||||||
|
@ -413,7 +184,6 @@ function createTable() {
|
||||||
shapeType: "box",
|
shapeType: "box",
|
||||||
modelURL: MODELS[randModel].modelURL
|
modelURL: MODELS[randModel].modelURL
|
||||||
});
|
});
|
||||||
entitiesToResize.push(tableEntities[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,5 +196,4 @@ function removeTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(cleanUp);
|
Script.scriptEnding.connect(cleanUp);
|
||||||
Script.update.connect(update);
|
|
||||||
Controller.mousePressEvent.connect(onClick);
|
Controller.mousePressEvent.connect(onClick);
|
Loading…
Reference in a new issue