mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 23:14:34 +02:00
Merge pull request #9788 from ctrlaltdavid/21186
Distance grab with second hand rotates entity
This commit is contained in:
commit
ac16d86835
1 changed files with 108 additions and 31 deletions
|
@ -205,14 +205,15 @@ var HARDWARE_MOUSE_ID = 0; // Value reserved for hardware mouse.
|
||||||
var STATE_OFF = 0;
|
var STATE_OFF = 0;
|
||||||
var STATE_SEARCHING = 1;
|
var STATE_SEARCHING = 1;
|
||||||
var STATE_DISTANCE_HOLDING = 2;
|
var STATE_DISTANCE_HOLDING = 2;
|
||||||
var STATE_NEAR_GRABBING = 3;
|
var STATE_DISTANCE_ROTATING = 3;
|
||||||
var STATE_NEAR_TRIGGER = 4;
|
var STATE_NEAR_GRABBING = 4;
|
||||||
var STATE_FAR_TRIGGER = 5;
|
var STATE_NEAR_TRIGGER = 5;
|
||||||
var STATE_HOLD = 6;
|
var STATE_FAR_TRIGGER = 6;
|
||||||
var STATE_ENTITY_STYLUS_TOUCHING = 7;
|
var STATE_HOLD = 7;
|
||||||
var STATE_ENTITY_LASER_TOUCHING = 8;
|
var STATE_ENTITY_STYLUS_TOUCHING = 8;
|
||||||
var STATE_OVERLAY_STYLUS_TOUCHING = 9;
|
var STATE_ENTITY_LASER_TOUCHING = 9;
|
||||||
var STATE_OVERLAY_LASER_TOUCHING = 10;
|
var STATE_OVERLAY_STYLUS_TOUCHING = 10;
|
||||||
|
var STATE_OVERLAY_LASER_TOUCHING = 11;
|
||||||
|
|
||||||
var CONTROLLER_STATE_MACHINE = {};
|
var CONTROLLER_STATE_MACHINE = {};
|
||||||
|
|
||||||
|
@ -231,6 +232,11 @@ CONTROLLER_STATE_MACHINE[STATE_DISTANCE_HOLDING] = {
|
||||||
enterMethod: "distanceHoldingEnter",
|
enterMethod: "distanceHoldingEnter",
|
||||||
updateMethod: "distanceHolding"
|
updateMethod: "distanceHolding"
|
||||||
};
|
};
|
||||||
|
CONTROLLER_STATE_MACHINE[STATE_DISTANCE_ROTATING] = {
|
||||||
|
name: "distance_rotating",
|
||||||
|
enterMethod: "distanceRotatingEnter",
|
||||||
|
updateMethod: "distanceRotating"
|
||||||
|
};
|
||||||
CONTROLLER_STATE_MACHINE[STATE_NEAR_GRABBING] = {
|
CONTROLLER_STATE_MACHINE[STATE_NEAR_GRABBING] = {
|
||||||
name: "near_grabbing",
|
name: "near_grabbing",
|
||||||
enterMethod: "nearGrabbingEnter",
|
enterMethod: "nearGrabbingEnter",
|
||||||
|
@ -891,7 +897,8 @@ function MyController(hand) {
|
||||||
newState !== STATE_OVERLAY_LASER_TOUCHING)) {
|
newState !== STATE_OVERLAY_LASER_TOUCHING)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setGrabCommunications((newState === STATE_DISTANCE_HOLDING) || (newState === STATE_NEAR_GRABBING));
|
setGrabCommunications((newState === STATE_DISTANCE_HOLDING) || (newState === STATE_DISTANCE_ROTATING)
|
||||||
|
|| (newState === STATE_NEAR_GRABBING));
|
||||||
if (WANT_DEBUG || WANT_DEBUG_STATE) {
|
if (WANT_DEBUG || WANT_DEBUG_STATE) {
|
||||||
var oldStateName = stateToName(this.state);
|
var oldStateName = stateToName(this.state);
|
||||||
var newStateName = stateToName(newState);
|
var newStateName = stateToName(newState);
|
||||||
|
@ -1050,7 +1057,7 @@ function MyController(hand) {
|
||||||
if (farParentID && farParentID != NULL_UUID) {
|
if (farParentID && farParentID != NULL_UUID) {
|
||||||
Overlays.editOverlay(this.overlayLine, {
|
Overlays.editOverlay(this.overlayLine, {
|
||||||
color: color,
|
color: color,
|
||||||
endParentID: farParentID
|
endParentID: farParentID
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Overlays.editOverlay(this.overlayLine, {
|
Overlays.editOverlay(this.overlayLine, {
|
||||||
|
@ -1465,9 +1472,10 @@ function MyController(hand) {
|
||||||
var props = entityPropertiesCache.getProps(hotspot.entityID);
|
var props = entityPropertiesCache.getProps(hotspot.entityID);
|
||||||
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
||||||
|
|
||||||
var okToEquipFromOtherHand = ((this.getOtherHandController().state == STATE_NEAR_GRABBING ||
|
var otherHandControllerState = this.getOtherHandController().state;
|
||||||
this.getOtherHandController().state == STATE_DISTANCE_HOLDING) &&
|
var okToEquipFromOtherHand = ((otherHandControllerState === STATE_NEAR_GRABBING
|
||||||
this.getOtherHandController().grabbedThingID == hotspot.entityID);
|
|| otherHandControllerState === STATE_DISTANCE_HOLDING || otherHandControllerState === STATE_DISTANCE_ROTATING)
|
||||||
|
&& this.getOtherHandController().grabbedThingID === hotspot.entityID);
|
||||||
var hasParent = true;
|
var hasParent = true;
|
||||||
if (props.parentID === NULL_UUID) {
|
if (props.parentID === NULL_UUID) {
|
||||||
hasParent = false;
|
hasParent = false;
|
||||||
|
@ -1768,7 +1776,11 @@ function MyController(hand) {
|
||||||
this.grabbedThingID = entity;
|
this.grabbedThingID = entity;
|
||||||
this.grabbedIsOverlay = false;
|
this.grabbedIsOverlay = false;
|
||||||
this.grabbedDistance = rayPickInfo.distance;
|
this.grabbedDistance = rayPickInfo.distance;
|
||||||
|
if (this.getOtherHandController().state === STATE_DISTANCE_HOLDING) {
|
||||||
|
this.setState(STATE_DISTANCE_ROTATING, "distance rotate '" + name + "'");
|
||||||
|
} else {
|
||||||
this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'");
|
this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// potentialFarGrabEntity = entity;
|
// potentialFarGrabEntity = entity;
|
||||||
|
@ -2073,6 +2085,19 @@ function MyController(hand) {
|
||||||
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.ensureDynamic = function () {
|
||||||
|
// if we distance hold something and keep it very still before releasing it, it ends up
|
||||||
|
// non-dynamic in bullet. If it's too still, give it a little bounce so it will fall.
|
||||||
|
var props = Entities.getEntityProperties(this.grabbedThingID, ["velocity", "dynamic", "parentID"]);
|
||||||
|
if (props.dynamic && props.parentID == NULL_UUID) {
|
||||||
|
var velocity = props.velocity;
|
||||||
|
if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD
|
||||||
|
velocity = { x: 0.0, y: 0.2, z: 0.0 };
|
||||||
|
Entities.editEntity(this.grabbedThingID, { velocity: velocity });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.distanceHoldingEnter = function() {
|
this.distanceHoldingEnter = function() {
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
this.grabPointSphereOff();
|
this.grabPointSphereOff();
|
||||||
|
@ -2139,25 +2164,20 @@ function MyController(hand) {
|
||||||
this.previousRoomControllerPosition = roomControllerPosition;
|
this.previousRoomControllerPosition = roomControllerPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ensureDynamic = function() {
|
|
||||||
// if we distance hold something and keep it very still before releasing it, it ends up
|
|
||||||
// non-dynamic in bullet. If it's too still, give it a little bounce so it will fall.
|
|
||||||
var props = Entities.getEntityProperties(this.grabbedThingID, ["velocity", "dynamic", "parentID"]);
|
|
||||||
if (props.dynamic && props.parentID == NULL_UUID) {
|
|
||||||
var velocity = props.velocity;
|
|
||||||
if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD
|
|
||||||
velocity = { x: 0.0, y: 0.2, z:0.0 };
|
|
||||||
Entities.editEntity(this.grabbedThingID, { velocity: velocity });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.distanceHolding = function(deltaTime, timestamp) {
|
this.distanceHolding = function(deltaTime, timestamp) {
|
||||||
|
|
||||||
if (!this.triggerClicked) {
|
if (!this.triggerClicked) {
|
||||||
this.callEntityMethodOnGrabbed("releaseGrab");
|
this.callEntityMethodOnGrabbed("releaseGrab");
|
||||||
this.ensureDynamic();
|
this.ensureDynamic();
|
||||||
this.setState(STATE_OFF, "trigger released");
|
this.setState(STATE_OFF, "trigger released");
|
||||||
|
if (this.getOtherHandController().state === STATE_DISTANCE_ROTATING) {
|
||||||
|
this.getOtherHandController().setState(STATE_SEARCHING, "trigger released on holding controller");
|
||||||
|
// Can't set state of other controller to STATE_DISTANCE_HOLDING because then either:
|
||||||
|
// (a) The entity would jump to line up with the formerly rotating controller's orientation, or
|
||||||
|
// (b) The grab beam would need an orientation offset to the controller's true orientation.
|
||||||
|
// Neither of these options is good, so instead set STATE_SEARCHING and subsequently let the formerly distance
|
||||||
|
// rotating controller start distance holding the entity if it happens to be pointing at the entity.
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2246,10 +2266,9 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.maybeScale(grabbedProperties);
|
this.maybeScale(grabbedProperties);
|
||||||
|
|
||||||
// visualizations
|
// visualizations
|
||||||
|
|
||||||
var rayPickInfo = this.calcRayPickInfo(this.hand);
|
var rayPickInfo = this.calcRayPickInfo(this.hand);
|
||||||
|
|
||||||
this.overlayLineOn(rayPickInfo.searchRay.origin,
|
this.overlayLineOn(rayPickInfo.searchRay.origin,
|
||||||
Vec3.subtract(grabbedProperties.position, this.offsetPosition),
|
Vec3.subtract(grabbedProperties.position, this.offsetPosition),
|
||||||
COLORS_GRAB_DISTANCE_HOLD,
|
COLORS_GRAB_DISTANCE_HOLD,
|
||||||
|
@ -2272,6 +2291,64 @@ function MyController(hand) {
|
||||||
this.previousRoomControllerPosition = roomControllerPosition;
|
this.previousRoomControllerPosition = roomControllerPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.distanceRotatingEnter = function() {
|
||||||
|
this.clearEquipHaptics();
|
||||||
|
this.grabPointSphereOff();
|
||||||
|
|
||||||
|
var controllerLocation = getControllerWorldLocation(this.handToController(), true);
|
||||||
|
var worldControllerPosition = controllerLocation.position;
|
||||||
|
var worldControllerRotation = controllerLocation.orientation;
|
||||||
|
|
||||||
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES);
|
||||||
|
this.currentObjectPosition = grabbedProperties.position;
|
||||||
|
this.grabRadius = this.grabbedDistance;
|
||||||
|
|
||||||
|
// Offset between controller vector at the grab radius and the entity position.
|
||||||
|
var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation));
|
||||||
|
targetPosition = Vec3.sum(targetPosition, worldControllerPosition);
|
||||||
|
this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition);
|
||||||
|
|
||||||
|
// Initial controller rotation.
|
||||||
|
this.previousWorldControllerRotation = worldControllerRotation;
|
||||||
|
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
|
this.turnOffVisualizations();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.distanceRotating = function(deltaTime, timestamp) {
|
||||||
|
|
||||||
|
if (!this.triggerClicked) {
|
||||||
|
this.callEntityMethodOnGrabbed("releaseGrab");
|
||||||
|
this.ensureDynamic();
|
||||||
|
this.setState(STATE_OFF, "trigger released");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES);
|
||||||
|
|
||||||
|
// Delta rotation of grabbing controller since last update.
|
||||||
|
var worldControllerRotation = getControllerWorldLocation(this.handToController(), true).orientation;
|
||||||
|
var controllerRotationDelta = Quat.multiply(worldControllerRotation, Quat.inverse(this.previousWorldControllerRotation));
|
||||||
|
|
||||||
|
// Rotate entity by twice the delta rotation.
|
||||||
|
controllerRotationDelta = Quat.multiply(controllerRotationDelta, controllerRotationDelta);
|
||||||
|
|
||||||
|
// Perform the rotation in the translation controller's action update.
|
||||||
|
this.getOtherHandController().currentObjectRotation = Quat.multiply(controllerRotationDelta,
|
||||||
|
this.getOtherHandController().currentObjectRotation);
|
||||||
|
|
||||||
|
// Rotate about the translation controller's target position.
|
||||||
|
this.offsetPosition = Vec3.multiplyQbyV(controllerRotationDelta, this.offsetPosition);
|
||||||
|
this.getOtherHandController().offsetPosition = Vec3.multiplyQbyV(controllerRotationDelta,
|
||||||
|
this.getOtherHandController().offsetPosition);
|
||||||
|
|
||||||
|
var rayPickInfo = this.calcRayPickInfo(this.hand);
|
||||||
|
this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition),
|
||||||
|
COLORS_GRAB_DISTANCE_HOLD, this.grabbedThingID);
|
||||||
|
|
||||||
|
this.previousWorldControllerRotation = worldControllerRotation;
|
||||||
|
}
|
||||||
|
|
||||||
this.setupHoldAction = function() {
|
this.setupHoldAction = function() {
|
||||||
this.actionID = Entities.addAction("hold", this.grabbedThingID, {
|
this.actionID = Entities.addAction("hold", this.grabbedThingID, {
|
||||||
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
|
@ -2547,9 +2624,9 @@ function MyController(hand) {
|
||||||
var grabEquipCheck = function () {
|
var grabEquipCheck = function () {
|
||||||
if (_this.state == STATE_NEAR_GRABBING) {
|
if (_this.state == STATE_NEAR_GRABBING) {
|
||||||
_this.callEntityMethodOnGrabbed("startNearGrab");
|
_this.callEntityMethodOnGrabbed("startNearGrab");
|
||||||
} else { // this.state == STATE_HOLD
|
} else { // this.state == STATE_HOLD
|
||||||
_this.callEntityMethodOnGrabbed("startEquip");
|
_this.callEntityMethodOnGrabbed("startEquip");
|
||||||
}
|
}
|
||||||
|
|
||||||
_this.currentHandControllerTipPosition =
|
_this.currentHandControllerTipPosition =
|
||||||
(_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
(_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
||||||
|
|
Loading…
Reference in a new issue