mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 17:01:18 +02:00
port action-near-grab to dispatcher
This commit is contained in:
parent
5e3b573d19
commit
0d0f147056
6 changed files with 321 additions and 59 deletions
|
@ -20,11 +20,11 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
||||||
"system/bubble.js",
|
"system/bubble.js",
|
||||||
"system/snapshot.js",
|
"system/snapshot.js",
|
||||||
"system/help.js",
|
"system/help.js",
|
||||||
// "system/pal.js", // "system/mod.js", // older UX, if you prefer
|
"system/pal.js", // "system/mod.js", // older UX, if you prefer
|
||||||
"system/makeUserConnection.js",
|
"system/makeUserConnection.js",
|
||||||
"system/tablet-goto.js",
|
"system/tablet-goto.js",
|
||||||
"system/marketplaces/marketplaces.js",
|
"system/marketplaces/marketplaces.js",
|
||||||
// "system/edit.js",
|
"system/edit.js",
|
||||||
"system/notifications.js",
|
"system/notifications.js",
|
||||||
"system/dialTone.js",
|
"system/dialTone.js",
|
||||||
"system/firstPersonHMD.js",
|
"system/firstPersonHMD.js",
|
||||||
|
|
|
@ -68,9 +68,9 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
getControllerWorldLocation(Controller.Standard.RightHand, true)];
|
getControllerWorldLocation(Controller.Standard.RightHand, true)];
|
||||||
|
|
||||||
var nearbyEntityProperties = [[], []];
|
var nearbyEntityProperties = [[], []];
|
||||||
for (var i = LEFT_HAND; i <= RIGHT_HAND; i ++) {
|
for (var h = LEFT_HAND; h <= RIGHT_HAND; h ++) {
|
||||||
// todo: check controllerLocations[i].valid
|
// todo: check controllerLocations[h].valid
|
||||||
var controllerPosition = controllerLocations[i].position;
|
var controllerPosition = controllerLocations[h].position;
|
||||||
var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MIN_RADIUS);
|
var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MIN_RADIUS);
|
||||||
for (var j = 0; j < nearbyEntityIDs.length; j++) {
|
for (var j = 0; j < nearbyEntityIDs.length; j++) {
|
||||||
var entityID = nearbyEntityIDs[j];
|
var entityID = nearbyEntityIDs[j];
|
||||||
|
@ -78,9 +78,15 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
props.id = entityID;
|
props.id = entityID;
|
||||||
props.distanceFromController = Vec3.length(Vec3.subtract(controllerPosition, props.position));
|
props.distanceFromController = Vec3.length(Vec3.subtract(controllerPosition, props.position));
|
||||||
if (props.distanceFromController < NEAR_MAX_RADIUS) {
|
if (props.distanceFromController < NEAR_MAX_RADIUS) {
|
||||||
nearbyEntityProperties[i].push(props);
|
nearbyEntityProperties[h].push(props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// sort by distance from each hand
|
||||||
|
nearbyEntityProperties[h].sort(function (a, b) {
|
||||||
|
var aDistance = Vec3.distance(a.position, controllerLocations[h]);
|
||||||
|
var bDistance = Vec3.distance(b.position, controllerLocations[h]);
|
||||||
|
return aDistance - bDistance;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var controllerData = {
|
var controllerData = {
|
||||||
|
|
|
@ -6,8 +6,18 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
|
||||||
/* global Camera, HMD, MyAvatar, getControllerJointIndex,
|
/* global Camera, HMD, MyAvatar, controllerDispatcherPlugins,
|
||||||
LEFT_HAND, RIGHT_HAND, NULL_UUID, AVATAR_SELF_ID, getGrabbableData */
|
MSECS_PER_SEC, LEFT_HAND, RIGHT_HAND, NULL_UUID, AVATAR_SELF_ID, FORBIDDEN_GRAB_TYPES,
|
||||||
|
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||||
|
enableDispatcherModule,
|
||||||
|
disableDispatcherModule,
|
||||||
|
getGrabbableData,
|
||||||
|
entityIsGrabbable,
|
||||||
|
getControllerJointIndex,
|
||||||
|
propsArePhysical
|
||||||
|
*/
|
||||||
|
|
||||||
|
MSECS_PER_SEC = 1000.0;
|
||||||
|
|
||||||
LEFT_HAND = 0;
|
LEFT_HAND = 0;
|
||||||
RIGHT_HAND = 1;
|
RIGHT_HAND = 1;
|
||||||
|
@ -15,6 +25,23 @@ RIGHT_HAND = 1;
|
||||||
NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
|
NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
|
||||||
AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}";
|
AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}";
|
||||||
|
|
||||||
|
FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"];
|
||||||
|
|
||||||
|
HAPTIC_PULSE_STRENGTH = 1.0;
|
||||||
|
HAPTIC_PULSE_DURATION = 13.0;
|
||||||
|
|
||||||
|
|
||||||
|
enableDispatcherModule = function (moduleName, module, priority) {
|
||||||
|
if (!controllerDispatcherPlugins) {
|
||||||
|
controllerDispatcherPlugins = {};
|
||||||
|
}
|
||||||
|
controllerDispatcherPlugins[moduleName] = module;
|
||||||
|
};
|
||||||
|
|
||||||
|
disableDispatcherModule = function (moduleName) {
|
||||||
|
delete controllerDispatcherPlugins[moduleName];
|
||||||
|
};
|
||||||
|
|
||||||
getGrabbableData = function (props) {
|
getGrabbableData = function (props) {
|
||||||
// look in userData for a "grabbable" key, return the value or some defaults
|
// look in userData for a "grabbable" key, return the value or some defaults
|
||||||
var grabbableData = {};
|
var grabbableData = {};
|
||||||
|
@ -29,10 +56,25 @@ getGrabbableData = function (props) {
|
||||||
if (!grabbableData.hasOwnProperty("grabbable")) {
|
if (!grabbableData.hasOwnProperty("grabbable")) {
|
||||||
grabbableData.grabbable = true;
|
grabbableData.grabbable = true;
|
||||||
}
|
}
|
||||||
|
if (!grabbableData.hasOwnProperty("ignoreIK")) {
|
||||||
|
grabbableData.ignoreIK = true;
|
||||||
|
}
|
||||||
|
if (!grabbableData.hasOwnProperty("kinematicGrab")) {
|
||||||
|
grabbableData.kinematicGrab = false;
|
||||||
|
}
|
||||||
|
|
||||||
return grabbableData;
|
return grabbableData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
entityIsGrabbable = function (props) {
|
||||||
|
var grabbable = getGrabbableData(props).grabbable;
|
||||||
|
if (!grabbable ||
|
||||||
|
props.locked ||
|
||||||
|
FORBIDDEN_GRAB_TYPES.indexOf(props.type) >= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
getControllerJointIndex = function (hand) {
|
getControllerJointIndex = function (hand) {
|
||||||
if (HMD.isHandControllerAvailable()) {
|
if (HMD.isHandControllerAvailable()) {
|
||||||
|
@ -52,3 +94,11 @@ getControllerJointIndex = function (hand) {
|
||||||
|
|
||||||
return MyAvatar.getJointIndex("Head");
|
return MyAvatar.getJointIndex("Head");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
propsArePhysical = function (props) {
|
||||||
|
if (!props.dynamic) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var isPhysical = (props.shapeType && props.shapeType != 'none');
|
||||||
|
return isPhysical;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// nearActionGrabEntity.js
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
||||||
|
getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
|
||||||
|
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
||||||
|
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation
|
||||||
|
*/
|
||||||
|
|
||||||
|
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function NearActionGrabEntity(hand) {
|
||||||
|
this.hand = hand;
|
||||||
|
this.grabbedThingID = null;
|
||||||
|
this.actionID = null; // action this script created...
|
||||||
|
|
||||||
|
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||||
|
var ACTION_TTL = 15; // seconds
|
||||||
|
var ACTION_TTL_REFRESH = 5;
|
||||||
|
|
||||||
|
// XXX does handJointIndex change if the avatar changes?
|
||||||
|
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
|
this.controllerJointIndex = getControllerJointIndex(this.hand);
|
||||||
|
|
||||||
|
|
||||||
|
// handPosition is where the avatar's hand appears to be, in-world.
|
||||||
|
this.getHandPosition = function () {
|
||||||
|
if (this.hand === RIGHT_HAND) {
|
||||||
|
return MyAvatar.getRightPalmPosition();
|
||||||
|
} else {
|
||||||
|
return MyAvatar.getLeftPalmPosition();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getHandRotation = function () {
|
||||||
|
if (this.hand === RIGHT_HAND) {
|
||||||
|
return MyAvatar.getRightPalmRotation();
|
||||||
|
} else {
|
||||||
|
return MyAvatar.getLeftPalmRotation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.startNearGrabAction = function (controllerData, grabbedProperties) {
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
|
|
||||||
|
var grabbableData = getGrabbableData(grabbedProperties);
|
||||||
|
this.ignoreIK = grabbableData.ignoreIK;
|
||||||
|
this.kinematicGrab = grabbableData.kinematicGrab;
|
||||||
|
|
||||||
|
var handRotation;
|
||||||
|
var handPosition;
|
||||||
|
if (this.ignoreIK) {
|
||||||
|
var controllerID =
|
||||||
|
(this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||||
|
var controllerLocation = getControllerWorldLocation(controllerID, false);
|
||||||
|
handRotation = controllerLocation.orientation;
|
||||||
|
handPosition = controllerLocation.position;
|
||||||
|
} else {
|
||||||
|
handRotation = this.getHandRotation();
|
||||||
|
handPosition = this.getHandPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
var objectRotation = grabbedProperties.rotation;
|
||||||
|
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||||
|
|
||||||
|
var currentObjectPosition = grabbedProperties.position;
|
||||||
|
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
||||||
|
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||||
|
|
||||||
|
if (this.actionID) {
|
||||||
|
Entities.deleteAction(this.grabbedThingID, this.actionID);
|
||||||
|
}
|
||||||
|
this.actionID = Entities.addAction("hold", this.grabbedThingID, {
|
||||||
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
|
relativePosition: this.offsetPosition,
|
||||||
|
relativeRotation: this.offsetRotation,
|
||||||
|
ttl: ACTION_TTL,
|
||||||
|
kinematic: this.kinematicGrab,
|
||||||
|
kinematicSetVelocity: true,
|
||||||
|
ignoreIK: this.ignoreIK
|
||||||
|
});
|
||||||
|
if (this.actionID === NULL_UUID) {
|
||||||
|
this.actionID = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||||
|
action: 'grab',
|
||||||
|
grabbedEntity: this.grabbedThingID,
|
||||||
|
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
// this is for when the action creation failed, before
|
||||||
|
this.restartNearGrabAction = function (controllerData) {
|
||||||
|
var props = Entities.getEntityProperties(this.grabbedThingID, ["position", "rotation", "userData"]);
|
||||||
|
if (props && entityIsGrabbable(props)) {
|
||||||
|
this.startNearGrabAction(controllerData, props);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// this is for when the action is going to time-out
|
||||||
|
this.refreshNearGrabAction = function (controllerData) {
|
||||||
|
var now = Date.now();
|
||||||
|
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSECS_PER_SEC) {
|
||||||
|
// if less than a 5 seconds left, refresh the actions ttl
|
||||||
|
var success = Entities.updateAction(this.grabbedThingID, this.actionID, {
|
||||||
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
|
relativePosition: this.offsetPosition,
|
||||||
|
relativeRotation: this.offsetRotation,
|
||||||
|
ttl: ACTION_TTL,
|
||||||
|
kinematic: this.kinematicGrab,
|
||||||
|
kinematicSetVelocity: true,
|
||||||
|
ignoreIK: this.ignoreIK
|
||||||
|
});
|
||||||
|
if (success) {
|
||||||
|
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||||
|
} else {
|
||||||
|
print("continueNearGrabbing -- updateAction failed");
|
||||||
|
this.restartNearGrabAction(controllerData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.endNearGrabAction = function (controllerData) {
|
||||||
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
|
Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args);
|
||||||
|
|
||||||
|
Entities.deleteAction(this.grabbedThingID, this.actionID);
|
||||||
|
this.actionID = null;
|
||||||
|
|
||||||
|
this.grabbedThingID = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isReady = function (controllerData) {
|
||||||
|
if (controllerData.triggerClicks[this.hand] == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var grabbedProperties = null;
|
||||||
|
// nearbyEntityProperties is already sorted by length from controller
|
||||||
|
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||||
|
for (var i = 0; i < nearbyEntityProperties.length; i++) {
|
||||||
|
var props = nearbyEntityProperties[i];
|
||||||
|
if (entityIsGrabbable(props)) {
|
||||||
|
grabbedProperties = props;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grabbedProperties) {
|
||||||
|
if (!propsArePhysical(grabbedProperties)) {
|
||||||
|
return false; // let nearParentGrabEntity handle it
|
||||||
|
}
|
||||||
|
this.grabbedThingID = grabbedProperties.id;
|
||||||
|
this.startNearGrabAction(controllerData, grabbedProperties);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.run = function (controllerData) {
|
||||||
|
if (controllerData.triggerClicks[this.hand] == 0) {
|
||||||
|
this.endNearGrabAction(controllerData);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.actionID) {
|
||||||
|
this.restartNearGrabAction(controllerData);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refreshNearGrabAction(controllerData);
|
||||||
|
|
||||||
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
|
Entities.callEntityMethod(this.grabbedThingID, "continueNearGrab", args);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
enableDispatcherModule("LeftNearActionGrabEntity", new NearActionGrabEntity(LEFT_HAND), 500);
|
||||||
|
enableDispatcherModule("RightNearActionGrabEntity", new NearActionGrabEntity(RIGHT_HAND), 500);
|
||||||
|
|
||||||
|
this.cleanup = function () {
|
||||||
|
disableDispatcherModule("LeftNearActionGrabEntity");
|
||||||
|
disableDispatcherModule("RightNearActionGrabEntity");
|
||||||
|
};
|
||||||
|
Script.scriptEnding.connect(this.cleanup);
|
||||||
|
}());
|
|
@ -1,38 +1,24 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// nearGrab.js
|
// nearParentGrabEntity.js
|
||||||
//
|
//
|
||||||
// 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
|
||||||
|
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, Controller, controllerDispatcherPlugins,
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID,
|
||||||
RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, getGrabbableData, NULL_UUID */
|
getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
|
||||||
|
FORBIDDEN_GRAB_TYPES, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION
|
||||||
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
var HAPTIC_PULSE_STRENGTH = 1.0;
|
// XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true;
|
||||||
var HAPTIC_PULSE_DURATION = 13.0;
|
// XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC;
|
||||||
|
|
||||||
var FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"];
|
|
||||||
var FORBIDDEN_GRAB_NAMES = ["Grab Debug Entity", "grab pointer"];
|
|
||||||
|
|
||||||
function entityIsParentingGrabbable(props) {
|
|
||||||
var grabbable = getGrabbableData(props).grabbable;
|
|
||||||
if (!grabbable ||
|
|
||||||
props.locked ||
|
|
||||||
FORBIDDEN_GRAB_TYPES.indexOf(props.type) >= 0 ||
|
|
||||||
FORBIDDEN_GRAB_NAMES.indexOf(props.name) >= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NearGrabParenting(hand) {
|
|
||||||
this.priority = 5;
|
|
||||||
|
|
||||||
|
function NearParentingGrabEntity(hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
this.grabbedThingID = null;
|
this.grabbedThingID = null;
|
||||||
this.previousParentID = {};
|
this.previousParentID = {};
|
||||||
|
@ -40,8 +26,9 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
this.previouslyUnhooked = {};
|
this.previouslyUnhooked = {};
|
||||||
|
|
||||||
|
|
||||||
// todo: does this change if the avatar changes?
|
// XXX does handJointIndex change if the avatar changes?
|
||||||
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
|
this.controllerJointIndex = getControllerJointIndex(this.hand);
|
||||||
|
|
||||||
this.thisHandIsParent = function(props) {
|
this.thisHandIsParent = function(props) {
|
||||||
if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) {
|
if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) {
|
||||||
|
@ -68,12 +55,23 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.startNearGrabParenting = function (controllerData, grabbedProperties) {
|
this.startNearParentingGrabEntity = function (controllerData, grabbedProperties) {
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
|
|
||||||
|
var handJointIndex;
|
||||||
|
// if (this.ignoreIK) {
|
||||||
|
// handJointIndex = this.controllerJointIndex;
|
||||||
|
// } else {
|
||||||
|
// handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
|
// }
|
||||||
|
handJointIndex = this.controllerJointIndex;
|
||||||
|
|
||||||
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
|
Entities.callEntityMethod(this.grabbedThingID, "startNearGrab", args);
|
||||||
|
|
||||||
var reparentProps = {
|
var reparentProps = {
|
||||||
parentID: AVATAR_SELF_ID,
|
parentID: AVATAR_SELF_ID,
|
||||||
parentJointIndex: getControllerJointIndex(this.hand),
|
parentJointIndex: handJointIndex,
|
||||||
velocity: {x: 0, y: 0, z: 0},
|
velocity: {x: 0, y: 0, z: 0},
|
||||||
angularVelocity: {x: 0, y: 0, z: 0}
|
angularVelocity: {x: 0, y: 0, z: 0}
|
||||||
};
|
};
|
||||||
|
@ -87,9 +85,15 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex;
|
this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex;
|
||||||
}
|
}
|
||||||
Entities.editEntity(this.grabbedThingID, reparentProps);
|
Entities.editEntity(this.grabbedThingID, reparentProps);
|
||||||
|
|
||||||
|
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||||
|
action: 'grab',
|
||||||
|
grabbedEntity: this.grabbedThingID,
|
||||||
|
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.endNearGrabParenting = function (controllerData) {
|
this.endNearParentingGrabEntity = function (controllerData) {
|
||||||
if (this.previousParentID[this.grabbedThingID] === NULL_UUID) {
|
if (this.previousParentID[this.grabbedThingID] === NULL_UUID) {
|
||||||
Entities.editEntity(this.grabbedThingID, {
|
Entities.editEntity(this.grabbedThingID, {
|
||||||
parentID: this.previousParentID[this.grabbedThingID],
|
parentID: this.previousParentID[this.grabbedThingID],
|
||||||
|
@ -104,6 +108,10 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
angularVelocity: {x: 0, y: 0, z: 0}
|
angularVelocity: {x: 0, y: 0, z: 0}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
|
Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args);
|
||||||
|
|
||||||
this.grabbedThingID = null;
|
this.grabbedThingID = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,22 +121,22 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
var grabbedProperties = null;
|
var grabbedProperties = null;
|
||||||
var bestDistance = 1000;
|
// nearbyEntityProperties is already sorted by length from controller
|
||||||
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
|
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||||
|
for (var i = 0; i < nearbyEntityProperties.length; i++) {
|
||||||
for (var i = 0; i < nearbyEntityProperties.length; i ++) {
|
|
||||||
var props = nearbyEntityProperties[i];
|
var props = nearbyEntityProperties[i];
|
||||||
if (entityIsParentingGrabbable(props)) {
|
if (entityIsGrabbable(props)) {
|
||||||
if (props.distanceFromController < bestDistance) {
|
grabbedProperties = props;
|
||||||
bestDistance = props.distanceFromController;
|
break;
|
||||||
grabbedProperties = props;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grabbedProperties) {
|
if (grabbedProperties) {
|
||||||
|
if (propsArePhysical(grabbedProperties)) {
|
||||||
|
return false; // let nearActionGrabEntity handle it
|
||||||
|
}
|
||||||
this.grabbedThingID = grabbedProperties.id;
|
this.grabbedThingID = grabbedProperties.id;
|
||||||
this.startNearGrabParenting(controllerData, grabbedProperties);
|
this.startNearParentingGrabEntity(controllerData, grabbedProperties);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -137,29 +145,23 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
|
||||||
this.run = function (controllerData) {
|
this.run = function (controllerData) {
|
||||||
if (controllerData.triggerClicks[this.hand] == 0) {
|
if (controllerData.triggerClicks[this.hand] == 0) {
|
||||||
this.endNearGrabParenting(controllerData);
|
this.endNearParentingGrabEntity(controllerData);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
|
Entities.callEntityMethod(this.grabbedThingID, "continueNearGrab", args);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftNearGrabParenting = new NearGrabParenting(LEFT_HAND);
|
enableDispatcherModule("LeftNearParentingGrabEntity", new NearParentingGrabEntity(LEFT_HAND), 500);
|
||||||
leftNearGrabParenting.name = "leftNearGrabParenting";
|
enableDispatcherModule("RightNearParentingGrabEntity", new NearParentingGrabEntity(RIGHT_HAND), 500);
|
||||||
|
|
||||||
var rightNearGrabParenting = new NearGrabParenting(RIGHT_HAND);
|
|
||||||
rightNearGrabParenting.name = "rightNearGrabParenting";
|
|
||||||
|
|
||||||
if (!controllerDispatcherPlugins) {
|
|
||||||
controllerDispatcherPlugins = {};
|
|
||||||
}
|
|
||||||
controllerDispatcherPlugins.leftNearGrabParenting = leftNearGrabParenting;
|
|
||||||
controllerDispatcherPlugins.rightNearGrabParenting = rightNearGrabParenting;
|
|
||||||
|
|
||||||
|
|
||||||
this.cleanup = function () {
|
this.cleanup = function () {
|
||||||
delete controllerDispatcherPlugins.leftNearGrabParenting;
|
disableDispatcherModule("LeftNearParentingGrabEntity");
|
||||||
delete controllerDispatcherPlugins.rightNearGrabParenting;
|
disableDispatcherModule("RightNearParentingGrabEntity");
|
||||||
};
|
};
|
||||||
Script.scriptEnding.connect(this.cleanup);
|
Script.scriptEnding.connect(this.cleanup);
|
||||||
}());
|
}());
|
|
@ -19,7 +19,8 @@ var CONTOLLER_SCRIPTS = [
|
||||||
"toggleAdvancedMovementForHandControllers.js",
|
"toggleAdvancedMovementForHandControllers.js",
|
||||||
|
|
||||||
"ControllerDispatcher.js",
|
"ControllerDispatcher.js",
|
||||||
"nearGrab.js"
|
"controllerModules/nearParentGrabEntity.js",
|
||||||
|
"controllerModules/nearActionGrabEntity.js"
|
||||||
];
|
];
|
||||||
|
|
||||||
var DEBUG_MENU_ITEM = "Debug defaultScripts.js";
|
var DEBUG_MENU_ITEM = "Debug defaultScripts.js";
|
||||||
|
|
Loading…
Reference in a new issue