mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 09:29:16 +02:00
use new-style far-grabbing code for mouse grabs
This commit is contained in:
parent
73a5f30350
commit
174c79d66d
2 changed files with 33 additions and 158 deletions
|
@ -3368,7 +3368,8 @@ void EntityItem::addGrab(GrabPointer grab) {
|
|||
EntityDynamicType dynamicType;
|
||||
QVariantMap arguments;
|
||||
int grabParentJointIndex =grab->getParentJointIndex();
|
||||
if (grabParentJointIndex == FARGRAB_RIGHTHAND_INDEX || grabParentJointIndex == FARGRAB_LEFTHAND_INDEX) {
|
||||
if (grabParentJointIndex == FARGRAB_RIGHTHAND_INDEX || grabParentJointIndex == FARGRAB_LEFTHAND_INDEX ||
|
||||
grabParentJointIndex == FARGRAB_MOUSE_INDEX) {
|
||||
// add a far-grab action
|
||||
dynamicType = DYNAMIC_TYPE_FAR_GRAB;
|
||||
arguments["otherID"] = grab->getOwnerID();
|
||||
|
|
|
@ -14,79 +14,25 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global MyAvatar, Entities, Script, HMD, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
|
||||
/* global MyAvatar, Entities, Script, HMD, Camera, Vec3, Reticle, Overlays, Messages, Quat, Controller,
|
||||
isInEditMode, entityIsGrabbable, Picks, PickType, Pointers, unhighlightTargetEntity, DISPATCHER_PROPERTIES,
|
||||
entityIsGrabbable, entityIsEquipped, getMainTabletIDs
|
||||
entityIsGrabbable, getMainTabletIDs
|
||||
*/
|
||||
/* jslint bitwise: true */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
Script.include("/~/system/libraries/utils.js");
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/utils.js");
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
var FAR_GRAB_JOINT = 65526; // FARGRAB_MOUSE_INDEX
|
||||
|
||||
var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed
|
||||
|
||||
var DELAY_FOR_30HZ = 33; // milliseconds
|
||||
|
||||
var ZERO_VEC3 = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
var IDENTITY_QUAT = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0,
|
||||
w: 0
|
||||
};
|
||||
|
||||
var DEFAULT_GRABBABLE_DATA = {
|
||||
grabbable: true,
|
||||
invertSolidWhileHeld: false
|
||||
};
|
||||
|
||||
|
||||
var ACTION_TTL = 10; // seconds
|
||||
|
||||
function getTag() {
|
||||
return "grab-" + MyAvatar.sessionUUID;
|
||||
}
|
||||
|
||||
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
||||
var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified
|
||||
var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified
|
||||
|
||||
function distanceGrabTimescale(mass, distance) {
|
||||
var timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME * mass /
|
||||
DISTANCE_HOLDING_UNITY_MASS * distance /
|
||||
DISTANCE_HOLDING_UNITY_DISTANCE;
|
||||
if (timeScale < DISTANCE_HOLDING_ACTION_TIMEFRAME) {
|
||||
timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME;
|
||||
}
|
||||
return timeScale;
|
||||
}
|
||||
function getMass(dimensions, density) {
|
||||
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
||||
}
|
||||
|
||||
function entityIsGrabbedByOther(entityID) {
|
||||
// by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*.
|
||||
var actionIDs = Entities.getActionIDs(entityID);
|
||||
for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) {
|
||||
var actionID = actionIDs[actionIndex];
|
||||
var actionArguments = Entities.getActionArguments(entityID, actionID);
|
||||
var tag = actionArguments.tag;
|
||||
if (tag == getTag()) {
|
||||
// we see a grab-*uuid* shaped tag, but it's our tag, so that's okay.
|
||||
continue;
|
||||
}
|
||||
if (tag.slice(0, 5) == "grab-") {
|
||||
// we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
||||
var IDENTITY_QUAT = { x: 0, y: 0, z: 0, w: 1 };
|
||||
|
||||
// helper function
|
||||
function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event, maxDistance) {
|
||||
|
@ -227,7 +173,6 @@ var beacon = {
|
|||
function Grabber() {
|
||||
this.isGrabbing = false;
|
||||
this.entityID = null;
|
||||
this.actionID = null;
|
||||
this.startPosition = ZERO_VEC3;
|
||||
this.lastRotation = IDENTITY_QUAT;
|
||||
this.currentPosition = ZERO_VEC3;
|
||||
|
@ -253,9 +198,6 @@ function Grabber() {
|
|||
z: 0
|
||||
};
|
||||
|
||||
this.targetPosition = null;
|
||||
this.targetRotation = null;
|
||||
|
||||
this.liftKey = false; // SHIFT
|
||||
this.rotateKey = false; // CONTROL
|
||||
|
||||
|
@ -305,7 +247,7 @@ Grabber.prototype.computeNewGrabPlane = function() {
|
|||
}
|
||||
}
|
||||
|
||||
this.pointOnPlane = Vec3.sum(this.currentPosition, this.offset);
|
||||
this.pointOnPlane = Vec3.subtract(this.currentPosition, this.offset);
|
||||
var xzOffset = Vec3.subtract(this.pointOnPlane, Camera.getPosition());
|
||||
xzOffset.y = 0;
|
||||
this.xzDistanceToGrab = Vec3.length(xzOffset);
|
||||
|
@ -341,16 +283,11 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
}
|
||||
|
||||
var props = Entities.getEntityProperties(pickResults.objectID, DISPATCHER_PROPERTIES);
|
||||
var isDynamic = props.dynamic;
|
||||
if (!entityIsGrabbable(props)) {
|
||||
// only grab grabbable objects
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.grab.grabbable) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pointers.setRenderState(this.mouseRayEntities, "grabbed");
|
||||
Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
|
||||
unhighlightTargetEntity(pickResults.objectID);
|
||||
|
@ -361,7 +298,6 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
var entityProperties = Entities.getEntityProperties(clickedEntity, DISPATCHER_PROPERTIES);
|
||||
this.startPosition = entityProperties.position;
|
||||
this.lastRotation = entityProperties.rotation;
|
||||
this.madeDynamic = false;
|
||||
var cameraPosition = Camera.getPosition();
|
||||
|
||||
var objectBoundingDiameter = Vec3.length(entityProperties.dimensions);
|
||||
|
@ -373,21 +309,10 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (entityIsGrabbable(props) && !isDynamic) {
|
||||
entityProperties.dynamic = true;
|
||||
Entities.editEntity(clickedEntity, entityProperties);
|
||||
this.madeDynamic = true;
|
||||
}
|
||||
// this.activateEntity(clickedEntity, entityProperties);
|
||||
this.isGrabbing = true;
|
||||
|
||||
this.entityID = clickedEntity;
|
||||
this.currentPosition = entityProperties.position;
|
||||
this.targetPosition = {
|
||||
x: this.startPosition.x,
|
||||
y: this.startPosition.y,
|
||||
z: this.startPosition.z
|
||||
};
|
||||
|
||||
// compute the grab point
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
|
@ -396,14 +321,13 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
nearestPoint = Vec3.multiply(distanceToGrab, pickRay.direction);
|
||||
this.pointOnPlane = Vec3.sum(cameraPosition, nearestPoint);
|
||||
|
||||
// compute the grab offset (points from object center to point of grab)
|
||||
this.offset = Vec3.subtract(this.pointOnPlane, this.startPosition);
|
||||
MyAvatar.setJointTranslation(FAR_GRAB_JOINT, MyAvatar.worldToJointPoint(this.startPosition));
|
||||
MyAvatar.setJointRotation(FAR_GRAB_JOINT, MyAvatar.worldToJointRotation(this.lastRotation));
|
||||
|
||||
this.offset = Vec3.subtract(this.startPosition, this.pointOnPlane); // offset in world-space
|
||||
|
||||
this.computeNewGrabPlane();
|
||||
|
||||
if (!entityIsGrabbedByOther(this.entityID)) {
|
||||
this.moveEvent(event);
|
||||
}
|
||||
this.moveEvent(event);
|
||||
|
||||
var args = "mouse";
|
||||
Entities.callEntityMethod(this.entityID, "startDistanceGrab", args);
|
||||
|
@ -413,6 +337,8 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
grabbedEntity: this.entityID
|
||||
}));
|
||||
|
||||
this.grabID = MyAvatar.grab(this.entityID, FAR_GRAB_JOINT, ZERO_VEC3, IDENTITY_QUAT);
|
||||
|
||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||
//Audio.playSound(grabSound, { position: entityProperties.position, volume: VOLUME });
|
||||
};
|
||||
|
@ -428,20 +354,7 @@ Grabber.prototype.releaseEvent = function(event) {
|
|||
}
|
||||
|
||||
if (this.isGrabbing) {
|
||||
// this.deactivateEntity(this.entityID);
|
||||
this.isGrabbing = false;
|
||||
if (this.actionID) {
|
||||
Entities.deleteAction(this.entityID, this.actionID);
|
||||
}
|
||||
|
||||
if (this.madeDynamic) {
|
||||
var entityProps = {};
|
||||
entityProps.dynamic = false;
|
||||
entityProps.localVelocity = {x: 0, y: 0, z: 0};
|
||||
Entities.editEntity(this.entityID, entityProps);
|
||||
}
|
||||
|
||||
this.actionID = null;
|
||||
|
||||
Pointers.setRenderState(this.mouseRayEntities, "");
|
||||
Pointers.setLockEndUUID(this.mouseRayEntities, null, false);
|
||||
|
@ -455,6 +368,13 @@ Grabber.prototype.releaseEvent = function(event) {
|
|||
joint: "mouse"
|
||||
}));
|
||||
|
||||
if (this.grabID) {
|
||||
MyAvatar.releaseGrab(this.grabID);
|
||||
this.grabID = null;
|
||||
}
|
||||
|
||||
MyAvatar.clearJointData(FAR_GRAB_JOINT);
|
||||
|
||||
// TODO: play sounds again when we aren't leaking AudioInjector threads
|
||||
//Audio.playSound(releaseSound, { position: entityProperties.position, volume: VOLUME });
|
||||
}
|
||||
|
@ -482,23 +402,12 @@ Grabber.prototype.moveEvent = function(event) {
|
|||
|
||||
Grabber.prototype.moveEventProcess = function() {
|
||||
this.moveEventTimer = null;
|
||||
// see if something added/restored gravity
|
||||
var entityProperties = Entities.getEntityProperties(this.entityID, DISPATCHER_PROPERTIES);
|
||||
if (!entityProperties || !entityProperties.gravity || HMD.active) {
|
||||
if (!entityProperties || HMD.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Vec3.length(entityProperties.gravity) !== 0.0) {
|
||||
this.originalGravity = entityProperties.gravity;
|
||||
}
|
||||
this.currentPosition = entityProperties.position;
|
||||
this.mass = getMass(entityProperties.dimensions, entityProperties.density);
|
||||
var cameraPosition = Camera.getPosition();
|
||||
|
||||
var actionArgs = {
|
||||
tag: getTag(),
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
|
||||
if (this.mode === "rotate") {
|
||||
var drag = mouse.getDrag();
|
||||
|
@ -510,19 +419,9 @@ Grabber.prototype.moveEventProcess = function() {
|
|||
var ROTATE_STRENGTH = 0.4; // magic number tuned by hand
|
||||
var angle = ROTATE_STRENGTH * Math.sqrt((drag.x * drag.x) + (drag.y * drag.y));
|
||||
var deltaQ = Quat.angleAxis(angle, axis);
|
||||
// var qZero = entityProperties.rotation;
|
||||
//var qZero = this.lastRotation;
|
||||
|
||||
this.lastRotation = Quat.multiply(deltaQ, this.lastRotation);
|
||||
|
||||
var distanceToCameraR = Vec3.length(Vec3.subtract(this.currentPosition, cameraPosition));
|
||||
var angularTimeScale = distanceGrabTimescale(this.mass, distanceToCameraR);
|
||||
|
||||
actionArgs = {
|
||||
targetRotation: this.lastRotation,
|
||||
angularTimeScale: angularTimeScale,
|
||||
tag: getTag(),
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
MyAvatar.setJointRotation(FAR_GRAB_JOINT, MyAvatar.worldToJointRotation(this.lastRotation));
|
||||
|
||||
} else {
|
||||
var newPointOnPlane;
|
||||
|
@ -534,17 +433,10 @@ Grabber.prototype.moveEventProcess = function() {
|
|||
planeNormal = Vec3.normalize(planeNormal);
|
||||
var pointOnCylinder = Vec3.multiply(planeNormal, this.xzDistanceToGrab);
|
||||
pointOnCylinder = Vec3.sum(Camera.getPosition(), pointOnCylinder);
|
||||
this.pointOnPlane = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, mouse.current, this.maxDistance);
|
||||
newPointOnPlane = {
|
||||
x: this.pointOnPlane.x,
|
||||
y: this.pointOnPlane.y,
|
||||
z: this.pointOnPlane.z
|
||||
};
|
||||
|
||||
newPointOnPlane = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, mouse.current, this.maxDistance);
|
||||
} else {
|
||||
|
||||
newPointOnPlane = mouseIntersectionWithPlane(
|
||||
this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance);
|
||||
var cameraPosition = Camera.getPosition();
|
||||
newPointOnPlane = mouseIntersectionWithPlane(this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance);
|
||||
var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition);
|
||||
var distance = Vec3.length(relativePosition);
|
||||
if (distance > this.maxDistance) {
|
||||
|
@ -553,26 +445,8 @@ Grabber.prototype.moveEventProcess = function() {
|
|||
newPointOnPlane = Vec3.sum(relativePosition, cameraPosition);
|
||||
}
|
||||
}
|
||||
this.targetPosition = Vec3.subtract(newPointOnPlane, this.offset);
|
||||
|
||||
var distanceToCameraL = Vec3.length(Vec3.subtract(this.targetPosition, cameraPosition));
|
||||
var linearTimeScale = distanceGrabTimescale(this.mass, distanceToCameraL);
|
||||
|
||||
actionArgs = {
|
||||
targetPosition: this.targetPosition,
|
||||
linearTimeScale: linearTimeScale,
|
||||
tag: getTag(),
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if (!this.actionID) {
|
||||
if (!entityIsGrabbedByOther(this.entityID) && !entityIsEquipped(this.entityID)) {
|
||||
this.actionID = Entities.addAction("far-grab", this.entityID, actionArgs);
|
||||
}
|
||||
} else {
|
||||
Entities.updateAction(this.entityID, this.actionID, actionArgs);
|
||||
MyAvatar.setJointTranslation(FAR_GRAB_JOINT, MyAvatar.worldToJointPoint(Vec3.sum(newPointOnPlane, this.offset)));
|
||||
}
|
||||
|
||||
this.scheduleMouseMoveProcessor();
|
||||
|
|
Loading…
Reference in a new issue